preparation(#985): purge any remaining direct uses of boost::format

now we use boost::format through our own front-end util::_Fmt
solely, which both helps to reduce compilation time and code size,
and gives us a direct string conversion, which automatically
uses any custom operator string() available on arguments.

While desirable as such, I did this conversion now, since
it allows us to get rid of boost::str, which in turn helps
to drill down any remaning uses of our own util::str
This commit is contained in:
Fischlurch 2016-01-04 01:38:04 +01:00
parent 96ba1fc2d0
commit b96fd1299d
18 changed files with 144 additions and 140 deletions

View file

@ -33,7 +33,7 @@
** than the (small) performance gain of directly invoking boost::format (which is
** known to be 10 times slower than printf anyway).
**
** \par Implementation notes
** ## Implementation notes
** To perform the formatting, usually a \c _Fmt object is created as an anonymous
** temporary, but it may as well be stored into a variable. Copying is not permitted.
** Individual parameters are then fed for formatting through the \c '%' operator.
@ -53,20 +53,21 @@
** to be negligible, in comparison to using boost::format. When compiling a demo example
** on x86_64, the following executable sizes could be observed:
**
** debug stripped
** just string concatenation ............... 42k 8.8k
** including and using format-string.hpp ... 50k 9.4k
** including and using boost::format ....... 420k 140k
** |debug | stripped
** ----------------------------------------:|----: | ---:
** just string concatenation ... | 42k | 8.8k
** including and using format-string.hpp ...| 50k | 9.4k
** including and using boost::format ... | 420k | 140k
**
** In addition, we need to take the implementation translation unit (format-string.cpp)
** into account, which is required once per application and contains the specialisations
** for all primitive types. In the test showed above, the corresponding object file
** had a size of 1300k (with debug information) resp. 290k (stripped).
**
** \par Usage
** ## Usage
** The syntax of the format string is defined by boost::format and closely mimics
** the printf formatting directives. The notable difference is that boost::format
** uses the C++ stream output framework, and thus avoiding the perils of printf.
** uses the C++ stream output framework, and thus avoids the perils of printf.
** The individual formatting placeholders just set the corresponding flags on
** an embedded string stream, thus the actual parameter types cause the
** selection of a suitable format, not the definitions within the
@ -90,12 +91,13 @@
** \endcode
**
** @remarks See the unit-test for extensive usage examples and corner cases.
** The header format-util.hpp provides an alternative string conversion,
** The header format-conv.hpp provides an alternative string conversion,
** using a bit of boost type traits and lexical_cast, but no boost::format.
** @warning not suited for performance critical code. About 10 times slower than printf.
**
**
** @see FormatString_test
** @see format-util.hpp
** @see format-conv.hpp
**
*/
@ -165,6 +167,7 @@ namespace util {
mutable Implementation formatter_;
/** call into the opaque implementation */
template<typename VAL>
static void format (const VAL, Implementation&);

View file

@ -29,7 +29,7 @@
** Currently just implemented through the mangled RTTI type string
**
** @see FormatHelper_test
** @see format-string.hpp frontend for boost::format, printf-style
** @see [frontend for boost::format, printf-style](format-string.hpp)
**
*/
@ -240,7 +240,7 @@ namespace util {
this->emplace_back (move(s));
}
};
}
}//(end) stringify helper
/** convert a sequence of elements to string
@ -285,19 +285,26 @@ namespace util {
{ }
};
}
}//(end) join helper
/**
* enumerate a collection's contents, separated by delimiter.
* @param coll something that is standard-iterable
* @return all contents converted to string and joined into
* a single string, with separators interspersed.
* @remarks based on the \c boost::join library function,
* which in turn is based on
* additionally, we use our
* \link #str failsafe string conversion \endlink
* @remarks based `ostringstream`; additionally, we use our
* [failsafe string conversion](\ref util::str),
* which in turn invokes custom string conversion,
* or lexical_cast as appropriate.
* @remarks alternatively, the `boost::join` library function
* could be used, which works on _arbitrary sequences_,
* which incurs some additional weight (both in terms
* of header include and debug code size). And failures
* on template substitution tend to be hard to understand,
* since this _generic sequence_ concept is just so danm
* absolutely generic (In fact that was the reason why I
* gave up and just rolled our own `join` utility)
*/
template<class CON>
inline string

View file

@ -75,7 +75,7 @@ namespace meta {
* Naive implementation just trying the direct conversion.
* The embedded constant #value will be true in case this succeeds.
* Might fail in more tricky situations (references, const, volatile)
* @see string-util.hpp more elaborate solution including lexical_cast
* @see \ref format-conv.hpp more elaborate solution including lexical_cast
*/
template<typename T>
struct can_convertToString
@ -125,7 +125,7 @@ namespace meta {
* a typedef member \c is_defined. The embedded metafunction Test can be used
* as a predicate for filtering types which may yield a valid instantiation
* of the candidate template in question.
* \par
* @remarks
* A fully automated solution for this problem is impossible by theoretic reasons.
* Any non trivial use of such a \c is_defined trait would break the "One Definition Rule",
* as the state of any type can change from "partially defined" to "fully defined" over

View file

@ -36,6 +36,14 @@
** The first attempt to build such an entity is based on standard techniques,
** disregarding performance and memory footprint considerations.
**
** @todo 1/2016 this idea seems very reasonable, and we should just make it
** robust and usable, along the lines pointed out by that draft
** - remove the `<iostream>` and `format-util` dependency (!)
** - provide a hash implementation for real
** - extend to arbitrary number of sub-dimensions (variadic)
** - implement comparisons as you'd do for any algebraic type
** - provide a metaprogramming facility to get an id tuple
**
** @see SubID_test
** @see MultiFact
**

View file

@ -29,20 +29,20 @@
#include "proc/asset/unknown.hpp"
#include "backend/media-access-facade.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/format-string.hpp"
#include "lib/util.hpp"
#include "include/logging.h"
#include <boost/regex.hpp>
#include <boost/format.hpp>
using util::_Fmt;
using util::isnil;
using lib::time::FSecs;
using lib::time::Duration;
using backend_interface::MediaDesc;
using backend_interface::MediaAccessFacade;
using boost::format;
using boost::regex;
using boost::smatch;
using boost::regex_search;
@ -232,13 +232,12 @@ namespace asset {
MediaFactory::operator() (Media& mediaref)
{
if (mediaref.checkCompound())
throw error::Invalid (str(format("Attempt to create a asset::Clip from the media %s, "
"which is not toplevel but rather part or a compound "
"(multichannel) media. Found parent Media %s.")
% string(mediaref)
% string(*mediaref.checkCompound()))
,LUMIERA_ERROR_PART_OF_COMPOUND
);
throw error::Invalid (_Fmt("Attempt to create a asset::Clip from the media %s, "
"which is not toplevel but rather part of a compound "
"(multichannel) media. Found parent Media %s.")
% mediaref
% *mediaref.checkCompound()
,LUMIERA_ERROR_PART_OF_COMPOUND);
Clip* pC = new Clip (mediaref);
return AssetManager::instance().wrap (*pC);
}

View file

@ -30,13 +30,11 @@
#include "lib/util.hpp"
#include "lib/symbol.hpp"
#include "lib/query-util.hpp"
#include "lib/format-string.hpp"
#include "include/logging.h"
#include "common/query.hpp"
#include <boost/format.hpp>
using boost::format;
using util::_Fmt;
using lib::Symbol;
using lib::query::normaliseID;
using lumiera::query::QueryHandler;
@ -154,8 +152,8 @@ namespace asset {
{
normaliseID (pipeID);
normaliseID (streamID);
static format descriptor("pipe(%s), stream(%s).");
Pipe* pP = impl_->fabricate (Query<Pipe> (str(descriptor % pipeID % streamID)));
_Fmt descriptor("pipe(%s), stream(%s).");
Pipe* pP = impl_->fabricate (Query<Pipe> (descriptor % pipeID % streamID));
return AssetManager::instance().wrap (*pP);
}

View file

@ -22,10 +22,9 @@
#include "proc/asset/unknown.hpp"
#include <boost/format.hpp>
#include "lib/format-string.hpp"
using boost::format;
using util::_Fmt;
namespace proc {
namespace asset {
@ -54,12 +53,11 @@ namespace asset {
{
UNIMPLEMENTED ("how to get at the original media from a »Unknown« placeholder");
if (1==0)
throw lumiera::error::Invalid (str(format("Unable to locate original media "
"for ID=%s, filename=\"%s\".")
% string(this->ident)
% string(this->getFilename()))
,LUMIERA_ERROR_ORIG_NOT_FOUND
);
throw lumiera::error::Invalid (_Fmt("Unable to locate original media "
"for ID=%s, filename=\"%s\".")
% this->ident
% this->getFilename()
,LUMIERA_ERROR_ORIG_NOT_FOUND);
}

View file

@ -26,15 +26,15 @@
#include "lib/sync.hpp"
#include "lib/util-foreach.hpp"
#include "lib/format-string.hpp"
#include <functional>
#include <boost/format.hpp>
using std::static_pointer_cast;
using std::function;
using std::placeholders::_1;
using boost::format;
using util::for_each;
using util::_Fmt;
using lib::Depend;
using lib::Sync;
@ -42,16 +42,16 @@ using lib::Sync;
namespace proc {
namespace asset {
namespace error = lumiera::error;
/**
* AssetManager error responses, caused by querying
* invalid Asset IDs from the internal DB.
*/
class IDErr : public lumiera::error::Invalid
struct IDErr
: error::Invalid
{
public:
IDErr (const char* eID, format fmt)
: lumiera::error::Invalid(fmt.str(),eID) {}
using error::Invalid::Invalid;
};
@ -60,21 +60,23 @@ namespace asset {
LUMIERA_ERROR_DEFINE (UNKNOWN_ASSET_ID, "non-registered Asset ID");
LUMIERA_ERROR_DEFINE (WRONG_ASSET_KIND, "wrong Asset kind, unable to cast");
class UnknownID : public IDErr
struct UnknownID : IDErr
{
public:
UnknownID (ID<Asset> aID) : IDErr (LUMIERA_ERROR_UNKNOWN_ASSET_ID,
format("Query for Asset with ID=%d, which up to now "
"hasn't been created or encountered.") % aID) {}
UnknownID (ID<Asset> aID)
: IDErr(_Fmt("Query for Asset with ID=%d, which up to now "
"hasn't been created or encountered.") % aID
,LUMIERA_ERROR_UNKNOWN_ASSET_ID)
{ }
};
class WrongKind : public IDErr
struct WrongKind : IDErr
{
public:
WrongKind (Asset::Ident idi) : IDErr (LUMIERA_ERROR_WRONG_ASSET_KIND,
format("Request for Asset(%s), specifying an Asset kind, "
"that doesn't match the actual type (and can't be "
"casted either).") % string(idi)) {}
WrongKind (Asset::Ident idi)
: IDErr (_Fmt("Request for Asset(%s), specifying an Asset kind, "
"that doesn't match the actual type (and can't be "
"casted either).") % idi
,LUMIERA_ERROR_WRONG_ASSET_KIND)
{ }
};

View file

@ -42,7 +42,7 @@
#include "lib/util.hpp"
#include "lib/error.hpp"
#include "lib/symbol.hpp"
#include "include/logging.h"
#include "lib/format-string.hpp"
#include "proc/control/command.hpp"
#include "proc/control/command-def.hpp"
#include "proc/control/command-impl.hpp"
@ -50,15 +50,13 @@
#include "proc/control/command-impl-clone-builder.hpp"
#include "proc/control/handling-pattern.hpp"
#include <boost/format.hpp>
#include <sstream>
#include <string>
using std::ostringstream;
using std::string;
using boost::format;
using boost::str;
using util::cStr;
using util::_Fmt;
namespace proc {
@ -113,9 +111,9 @@ namespace control {
Command::get (Symbol cmdID)
{
Command cmd = CommandRegistry::instance().queryIndex (cmdID);
static format fmt("Command \"%s\" not found");
if (!cmd)
throw error::Invalid(str(fmt % cmdID), LUMIERA_ERROR_INVALID_COMMAND);
throw error::Invalid(_Fmt("Command \"%s\" not found") % cmdID
, LUMIERA_ERROR_INVALID_COMMAND);
ENSURE (cmdID == CommandRegistry::instance().findDefinition(cmd));
return cmd;
@ -152,7 +150,6 @@ namespace control {
Command::activate (shared_ptr<CommandImpl> const& implFrame, Symbol cmdID)
{
REQUIRE (implFrame);
static format fmt("Command \"%s\" already defined");
if (this->isValid())
duplicate_detected (cmdID);
@ -217,8 +214,11 @@ namespace control {
void
Command::duplicate_detected (Symbol newCmdID) const
{
static format fmt("Unable to store %s as new command. ID \"%s\" is already in use");
throw error::Logic (str (fmt % *this % newCmdID), LUMIERA_ERROR_DUPLICATE_COMMAND);
throw error::Logic (_Fmt("Unable to store %s as new command. "
"ID \"%s\" is already in use")
% *this
% newCmdID
, LUMIERA_ERROR_DUPLICATE_COMMAND);
}

View file

@ -22,19 +22,16 @@
#include "lib/error.hpp"
#include "proc/control/handling-pattern.hpp"
#include "proc/control/handling-patterns.hpp"
#include "include/logging.h"
#include "lib/format-string.hpp"
#include "lib/util.hpp"
#include <boost/format.hpp>
using boost::str;
using boost::format;
using util::isnil;
using util::cStr;
using util::_Fmt;
namespace proc {
@ -56,21 +53,21 @@ namespace control {
HandlingPattern::invoke (CommandImpl& command, Symbol name) const
{
TRACE (proc_dbg, "invoking %s...", name.c());
static format err_pre ("Error state detected, %s *NOT* invoked.");
static format err_post ("Error state after %s invocation.");
static format err_fatal ("Execution of %s raised unknown error.");
static _Fmt err_pre ("Error state detected, %s *NOT* invoked.");
static _Fmt err_post ("Error state after %s invocation.");
static _Fmt err_fatal ("Execution of %s raised unknown error.");
try
{
Symbol errID_pre = lumiera_error();
if (errID_pre)
return ExecResult (error::Logic (str (err_pre % command), errID_pre));
return ExecResult (error::Logic (err_pre % command, errID_pre));
// execute or undo it...
perform (command);
Symbol errID = lumiera_error();
if (errID)
return ExecResult (error::State (str (err_post % command),errID));
return ExecResult (error::State (err_post % command, errID));
else
return ExecResult();
}
@ -94,7 +91,7 @@ namespace control {
{
Symbol errID = lumiera_error();
ERROR (command, "Invocation of %s failed with unknown exception; error flag is: %s", name.c(), errID.c());
throw error::Fatal (str (err_fatal % command), errID);
throw error::Fatal (err_fatal % command, errID);
}
}

View file

@ -24,12 +24,11 @@
#include "proc/mobject/placement.hpp"
#include "proc/mobject/explicitplacement.hpp"
#include "proc/mobject/mobject.hpp"
#include "lib/format-string.hpp"
#include <boost/format.hpp>
#include <typeinfo>
using boost::format;
using boost::str;
using util::_Fmt;
namespace proc {
namespace mobject {
@ -51,22 +50,20 @@ namespace mobject {
Placement<MObject>::operator string () const
{
static format fmt("Placement<%s> %|50T.| use-cnt=%u ID(%x) adr=%p pointee=%p");
return str(fmt % typeid(*get()).name() % use_count()
% (size_t)getID()
% this
% get()
);
return _Fmt{"Placement<%s> %|50T.| use-cnt=%u ID(%x) adr=%p pointee=%p"}
% typeid(*get()).name() % use_count()
% (size_t)getID()
% this
% get()
;
}
string
format_PlacementID (Placement<MObject> const& pla)
{
static format fmt ("pID(%x)");
size_t hashVal = pla.getID();
return str(fmt % hashVal);
return _Fmt{"pID(%x)"} % hashVal;
}

View file

@ -22,12 +22,11 @@
#include "proc/mobject/session/abstractmo.hpp"
#include "lib/format-string.hpp"
#include "lib/util.hpp"
#include <boost/format.hpp>
using util::_Fmt;
using util::isnil;
using boost::format;
namespace proc {
namespace mobject {
@ -48,14 +47,13 @@ namespace session {
string
AbstractMO::buildShortID (lib::Literal typeID, string suffix) const
{
static uint i=0;
static format namePattern ("%s.%03d");
static size_t i=0;
REQUIRE (!isnil (typeID));
if (!isnil (suffix))
return typeID+"."+suffix;
else
return str(namePattern % typeID % (++i) );
return _Fmt{"%s.%03d"} % typeID % (++i);
}

View file

@ -23,12 +23,9 @@
#include "proc/mobject/session/query-focus.hpp"
#include "proc/mobject/mobject.hpp"
#include "lib/format-string.hpp"
#include <boost/format.hpp>
using boost::format;
using boost::str;
using util::_Fmt;
namespace proc {
namespace mobject {
@ -164,9 +161,9 @@ namespace session {
/** diagnostic self-display based on the ScopePath */
QueryFocus::operator string() const
{
static format display("Focus(%d)--->%s");
return str ( display % ScopeLocator::instance().stackSize()
% string (*focus_));
static _Fmt display("Focus(%d)--->%s");
return display % ScopeLocator::instance().stackSize()
% *focus_;
}

View file

@ -45,14 +45,14 @@
#include "proc/mobject/builder/buildertool.hpp"
#include "proc/mobject/session/abstractmo.hpp"
#include "proc/mobject/placement.hpp"
#include "lib/format-string.hpp"
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include <boost/format.hpp>
#include <iostream>
#include <cstdlib>
using boost::format;
using util::_Fmt;
using util::cStr;
using std::string;
using std::rand;
@ -91,8 +91,8 @@ namespace test {
string
display(Symbol name) const
{
static format fmt("%s(ID=%03d)");
return boost::str(fmt % name % this->id_);
static _Fmt fmt{"%s(ID=%03d)"};
return fmt % name % this->id_;
}
};

View file

@ -89,7 +89,7 @@ namespace test {
_Fmt fmt ("invoked( %2d )");
randVal_ = rand() % 100;
return str (fmt % randVal_);
return fmt % randVal_;
}
bool blowUp_;

View file

@ -25,12 +25,12 @@
#include "lib/test/test-helper.hpp"
#include "proc/mobject/output-mapping.hpp"
#include "proc/asset/pipe.hpp"
#include "lib/format-string.hpp"
#include "lib/util.hpp"
#include <boost/format.hpp>
#include <string>
using boost::format;
using util::_Fmt;
using util::isnil;
using std::string;
@ -76,8 +76,8 @@ namespace test {
buildQuery (PID sourcePipeID, uint seqNr =0)
{
PPipe srcP = Pipe::lookup (sourcePipeID);
format queryPattern ("id(master_%1%), stream(%1%), ord(%2%)");
return Query<Pipe> (str(queryPattern % srcP->getStreamID().getSym() % seqNr));
_Fmt queryPattern{"id(master_%1%), stream(%1%), ord(%2%)"};
return Query<Pipe> (queryPattern % srcP->getStreamID().getSym() % seqNr);
}
};

View file

@ -31,12 +31,11 @@
#include "proc/assetmanager.hpp"
#include "proc/mobject/session.hpp"
#include "proc/streamtype.hpp"
#include "lib/format-string.hpp"
#include "lib/query-util.hpp"
#include "common/query.hpp"
#include <boost/format.hpp>
using boost::format;
using util::_Fmt;
using util::isnil;
using std::string;
@ -60,23 +59,25 @@ namespace test {
using proc::ConfigResolver;
/** shortcut: query for given Pipe-ID */
bool
find (const string& pID)
{
return bool(Session::current->defaults.search (Query<Pipe> ("pipe("+pID+")")));
}
format pattern ("dummy_%s_%i");
/** create a random new ID */
string
newID (Symbol prefix)
{
return str (pattern % prefix % std::rand());
}
namespace { // test fixture...
/** shortcut: query for given Pipe-ID */
bool
find (const string& pID)
{
return bool(Session::current->defaults.search (Query<Pipe> ("pipe("+pID+")")));
}
_Fmt pattern ("dummy_%s_%i");
/** create a random new ID */
string
newID (Symbol prefix)
{
return pattern % prefix % std::rand();
}
}//(end)test fixture

View file

@ -24,6 +24,7 @@
#include "lib/test/run.hpp"
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include "lib/format-string.hpp"
#include "lib/query-util.hpp"
#include "common/query.hpp"
@ -34,9 +35,7 @@
#include "proc/mobject/session.hpp"
#include "proc/streamtype.hpp"
#include <boost/format.hpp>
using boost::format;
using util::_Fmt;
using util::isnil;
using std::string;
@ -145,10 +144,10 @@ namespace test {
{
PPipe pipe1 = Session::current->defaults(Query<Pipe> ("")); // "the default pipe"
string new_pID (str (format ("dummy_%s_%i")
string new_pID = _Fmt{"dummy_%s_%i"}
% pipe1->getPipeID()
% std::rand()
)); // make random new pipeID
; // make random new pipeID
Query<Pipe> query_for_new ("pipe("+new_pID+")");
CHECK (!find (query_for_new)); // check it doesn't exist