|
From: Teiniker E. <tei...@us...> - 2007-01-22 10:09:03
|
Update of /cvsroot/ccmtools/cpp-environment/utils/code In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv14231/utils/code Added Files: DebugWriter.h indent.cc smartptr.h debug.h HashSet.h doxycode.h debug.cc StringMap.h atomic_count.h extern_c.h StringMap.cc align.h HashMap.h smartptr.cc Confix2.dir .cvsignore indent.h DebugWriterMgr.h linkassert.h CerrDebugWriter.h Log Message: Added utils/code and utils/error to the runtime lib --- NEW FILE: .cvsignore --- Makefile.am Makefile.in --- NEW FILE: StringMap.h --- // // $Id$ // #ifndef wx_utils_code_stringmap_h #define wx_utils_code_stringmap_h #include "HashMap.h" #include <string> namespace wamas { namespace platform { namespace utils { struct StringHash { std::size_t operator()(std::string const& s) const; }; /** @brief A hash-map with keys of type std::string. */ template< typename T > class StringMap : public HashMap<std::string, T, StringHash> { public: explicit StringMap(std::size_t n) : HashMap<std::string, T, StringHash>(n) {} StringMap() {} }; } // /namespace } // /namespace } // /namespace #endif --- NEW FILE: smartptr.h --- #ifndef wx_utils_code_smartptr_h #define wx_utils_code_smartptr_h #include "atomic_count.h" #include "linkassert.h" #include <iostream> #ifdef WX_REFCOUNTED_COLLECT_NEW #include <map> #endif namespace wamas { namespace platform { namespace utils { /** \brief Base class for all classes which are supposed to be pointed to by a smart pointer. Actually doesn't do anything, but rather provides the interface. \ingroup utils_code \author Joerg Faschingbauer \b COPYING \b A \b REFERENCE \b COUNTED \b THING Copying a refcounted thing is not straightforward yet it is simple. In an ideal world you would pass a class object either by copy or by using a smart pointer. The former method does not care about anything, it just copies, whereas the latter method maintains a reference count inside the object that is being passed. Everything is fine if you don't intermix both methods (which you shouldn't unless there is need to AND you know what you're doing). It gets more complicated if, for example, \b COPY \b CONSTRUCTOR we take a copy of a smartpointed object and pass that copy around using a smart pointer: we get a smart pointer xp that points to some object, say *x. \code SmartPtr<X> xp = get_object(); \endcode Now assume that *x, after execution of that statement, has a refcount of 2 (x->refcount()==2). In other words, another smart pointer (other than xp) points to it somewhere outside our scope. We now copy that object *x (not the smart pointer xp) into another object, *y. \code X* y = new X(*xp.ptr()); \endcode The question is: what reference count must *y now have? Obviously, since the reference count reflects the number of smart pointers pointing at it (well, ideally; one can always dirtily ref() and unref() by hand), the reference count of *y must be ZERO. Otherwise, if we would pass *y around using smart pointers (which would then be responsible for cleanup), we would leak memory. \code XPtr yp = XPtr(y); pass_around(yp); // leak \endcode \b ASSIGNMENT \b OPERATOR Now for the assignment operator. Suppose we get an object *x which is pointed to by, say, 2 smart pointers (x->refcount()==2), one of them being xp. \code SmartPtr<X> xp = get_object(); \endcode Now, eagerly crying for subtle bugs, we want to replace the content of *x with that of some other object newx of class X. \code X newx(...); *xp.ptr() = newx; \endcode The question is: what must be the reference count of *x? Obviously, since the number of smart pointers pointing at it does not change, the reference count must not change, it must still be 2 as before the assignment. */ class RefCounted { public: RefCounted() : refcount_(0) {} virtual ~RefCounted() {} /** @name see the big note above for copy semantics */ //@{ RefCounted(const RefCounted&) : refcount_(0) {} RefCounted& operator=(const RefCounted&) { return *this; } //@} /// increment reference count virtual void ref(); /// decrement reference count virtual void unref(); /// return the reference count long refcount() const { return refcount_; } /** @name simple wrappers to accommodate null pointers */ //@{ static void ref(RefCounted* r) { if (r) r->ref(); } static void unref(RefCounted* r) { if (r) r->unref(); } //@} #ifdef WX_REFCOUNTED_COLLECT_NEW void* operator new (std::size_t); void operator delete (void*); typedef std::map<std::size_t, long> NewStatistics; static NewStatistics new_statistics_; #endif private: atomic_count refcount_; public: LTA_MEMDECL(20061107); }; LTA_STATDEF(RefCounted, 20061107); /** \class SmartPtr \ingroup utils_code \brief Template class which manages pointers to RefCounted objects. \author Joerg Faschingbauer Smart pointers are supposed to be used in cases where you do not want to care about memory ownerships. For example, when you pass a pointer to an object to a function, you and the function have to agree upon who is responsible for deleting the object. You use a smart pointer to automatically accomplish that. You wrap a smart pointer around the raw pointer, and pass the smart pointer instead (of course, the function must be prepared to expect a smart pointer). If you are not interested in the object after the call, you simply let the smart pointer go out of scope. The smart pointer's destructor will then decrement the reference count of the pointed-to object, and, if the reference count has become zero, delete it. If you are interested in keeping the object, you store the smart pointer somewhere. This prevents the object's reference count from becoming zero. The function, on the other hand, may decide to store the smart pointer somewhere (and keep a reference on it), or to only temporarily use it and then forget about it (let it go out of scope). */ template <class T> class SmartPtr { public: /** Default constructor. Initially a smart pointer points to nothing (i.e., has the value 0). */ SmartPtr(): ptr_(0) {} /** "Eating" constructor. The object the argument points to is now managed by the smart pointer object. Hence it must not be deleted explicitly afterwards. */ explicit SmartPtr(T* p): ptr_(p) { RefCounted::ref(ptr_); } /** Copy constructor, template version (to be able to assign derived pointees). Increments the reference count on the object by one. */ template<class RHS> SmartPtr(const SmartPtr<RHS>& p): ptr_(0) { operator=(p); } /** Copy constructor, non-template version. Increments the reference count on the object by one. Implementor's note: one would think that the emplate version of the copy ctor should be used by the compiler to generate the default copy ctor. But that's not how C++ is defined - if we do not define an explicit non-template copy ctor, we would get a real default copy ctor which only copies the pointer and does no refcounting. */ SmartPtr(const SmartPtr& p): ptr_(0) { operator=(p); } /** Destructor. Decrements the reference count by one. Deletes the object (better to say, the object deletes itself) if the reference count becomes zero. */ ~SmartPtr() { RefCounted::unref(ptr_); } /** Assignment operator, template version. Same semantics as template copy constructor. */ template<class RHS> SmartPtr& operator=( const SmartPtr<RHS>& p) { if (this->ptr() != p.ptr()) { RefCounted::ref(p.ptr()); RefCounted::unref(this->ptr()); ptr_ = p.ptr(); } return *this; } /** Assignment operator, non-template version. Same semantics as copy constructor. Implementor's note: we have to define a non-template version for the same reason why we have to define a non-template copy ctor. */ SmartPtr& operator=( const SmartPtr& p) { if (this->ptr() != p.ptr()) { RefCounted::ref(p.ptr()); RefCounted::unref(this->ptr()); ptr_ = p.ptr(); } return *this; } /** Acquire responsibility for the object (and increment its reference count). An eventual existing responsibility for a different object is canceled, and that reference is decremented. */ template<class RHS> void eat(RHS* p) { if (p == ptr_) return; RefCounted::unref(ptr_); ptr_ = p; RefCounted::ref(p); } /** Become a NULL pointer. Unreference an object that we are pointing to. */ void forget() { if (ptr_) { RefCounted::unref(ptr_); ptr_ = NULL; } } /** \name Smart pointer comparison */ //@{ operator bool() const { // Doze bullshit yells "Performance warning" if I don't cast // explicitly return static_cast<bool>(ptr_); } bool operator !() const { return !ptr_; } bool operator< (const SmartPtr& that) const { return ptr_< that.ptr_; } bool operator==(const SmartPtr& that) const { return ptr_==that.ptr_; } bool operator> (const SmartPtr& that) const { return ptr_> that.ptr_; } bool operator<=(const SmartPtr& that) const { return ptr_<=that.ptr_; } bool operator>=(const SmartPtr& that) const { return ptr_>=that.ptr_; } //@} /** A pointer to the object, modifiable. */ T* ptr() const { return ptr_; } /** A pointer to the object, modifiable, trading off for readability. */ T* operator->() { return ptr_; } /** A pointer to the object, non-modifiable. */ const T* cptr() const { return ptr_; } /** A pointer to the object, non-modifiable, trading off for readability. */ const T* operator->() const { return ptr_; } private: T* ptr_; }; } // /namespace } // /namespace } // /namespace #endif --- NEW FILE: debug.h --- // -*- mode: C++; c-basic-offset: 3 -*- // // $Id$ // #ifndef wx_utils_code_debug_h #define wx_utils_code_debug_h #include <sstream> #include <string> #include "DebugWriterMgr.h" namespace wamas { namespace platform { namespace utils { /** \brief Enable/disable/select debugging. \ingroup utils_code */ class Debug { public: Debug(bool read_env=true); Debug(const std::string& levels, bool read_env=true); ~Debug(); /** Have all debugging messages printed out */ void set_global(bool b) { global_=b; } /** Check whether we output all debugging messages */ bool get_global() { return global_; } /** Have debugging messages with \c level printed out */ void add_level(const std::string& level); void parse_levels(const std::string& levelstr); /** Check whether we output debugging messages with \c level */ bool have_level(const std::string& level); int n_levels(); /** singleton */ static Debug& instance(); private: class DebugImpl* impl_; bool global_; }; /** \def LDEBUGNL(level,msg) \ingroup utils_code \brief Output a message \a msg plus newline if \a level is on. \a level is stringified by the C preprocessor, so you don't enclose it into double quotes. \a msg is anything an ostream can handle. For example, \code int n = some_number(); LDEBUGNL(MyLevel, "Here I have "<<n<<" pieces"); \endcode */ /** \def LDEBUG(level,msg) \brief Same as LDEBUGNL, but without newline \ingroup utils_code */ #ifdef WXDEBUG # define WRITE_MSG_TO_DEBUGWRITER(msg,facility,level)\ {\ std::ostringstream os;\ os << msg << std::ends;\ wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().write(__FILE__,__LINE__,facility,\ level,os.str());\ } // Trace level # define TRACE(msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(""))\ WRITE_MSG_TO_DEBUGWRITER(msg, "",wamas::platform::utils::DebugWriter::Trace)\ } # define TRACENL(msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(""))\ WRITE_MSG_TO_DEBUGWRITER(msg<<'\n',"",wamas::platform::utils::DebugWriter::Trace)\ } # define LTRACE(facility,msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(#facility))\ WRITE_MSG_TO_DEBUGWRITER(msg,#facility,wamas::platform::utils::DebugWriter::Trace)\ } # define LTRACENL(facility,msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(#facility))\ WRITE_MSG_TO_DEBUGWRITER(msg<<'\n',#facility,wamas::platform::utils::DebugWriter::Trace)\ } // Debug level # define DEBUG(msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(""))\ WRITE_MSG_TO_DEBUGWRITER(msg, "",wamas::platform::utils::DebugWriter::Debug)\ } # define DEBUGNL(msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(""))\ WRITE_MSG_TO_DEBUGWRITER(msg<<'\n',"",wamas::platform::utils::DebugWriter::Debug)\ } # define LDEBUG(facility,msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(#facility))\ WRITE_MSG_TO_DEBUGWRITER(msg,#facility,wamas::platform::utils::DebugWriter::Debug)\ } # define LDEBUGNL(facility,msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(#facility))\ WRITE_MSG_TO_DEBUGWRITER(msg<<'\n',#facility,wamas::platform::utils::DebugWriter::Debug)\ } // Notify level # define NOTIFY(msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(""))\ WRITE_MSG_TO_DEBUGWRITER(msg, "",wamas::platform::utils::DebugWriter::Notify)\ } # define NOTIFYNL(msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(""))\ WRITE_MSG_TO_DEBUGWRITER(msg<<'\n',"",wamas::platform::utils::DebugWriter::Notify)\ } # define LNOTIFY(facility,msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(#facility))\ WRITE_MSG_TO_DEBUGWRITER(msg,#facility,wamas::platform::utils::DebugWriter::Notify)\ } # define LNOTIFYNL(facility,msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(#facility))\ WRITE_MSG_TO_DEBUGWRITER(msg<<'\n',#facility,wamas::platform::utils::DebugWriter::Notify)\ } // Alert level # define ALERT(msg)\ {\ if (wamas::platform::utils::EmergWriterMgr::instance().getDebugWriter().check(""))\ WRITE_MSG_TO_DEBUGWRITER(msg, "",wamas::platform::utils::DebugWriter::Alert)\ } # define ALERTNL(msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(""))\ WRITE_MSG_TO_DEBUGWRITER(msg<<'\n',"",wamas::platform::utils::DebugWriter::Alert)\ } # define LALERT(facility,msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(#facility))\ WRITE_MSG_TO_DEBUGWRITER(msg,#facility,wamas::platform::utils::DebugWriter::Alert)\ } # define LALERTNL(facility,msg)\ {\ if (wamas::platform::utils::DebugWriterMgr::instance().getDebugWriter().check(#facility))\ WRITE_MSG_TO_DEBUGWRITER(msg<<'\n',#facility,wamas::platform::utils::DebugWriter::Alert)\ } #else # define TRACE(msg) # define TRACENL(msg) # define LTRACE(facility,msg) # define LTRACENL(facility,msg) # define DEBUG(msg) # define DEBUGNL(msg) # define LDEBUG(facility,msg) # define LDEBUGNL(facility,msg) # define NOTIFY(msg) # define NOTIFYNL(msg) # define LNOTIFY(facility,msg) # define LNOTIFYNL(facility,msg) # define ALERT(msg) # define ALERTNL(msg) # define LALERT(facility,msg) # define LALERTNL(facility,msg) #endif } // /namespace } // /namespace } // /namespace #endif --- NEW FILE: doxycode.h --- // -*- mode: C++; c-basic-offset: 3 -*- // // $Id$ // namespace wamas { namespace platform { namespace utils { /** \defgroup utils_code Little cuties \ingroup utils */ } // /namespace } // /namespace } // /namespace --- NEW FILE: align.h --- // -*- mode: C++; c-basic-offset: 3 -*- // // $Id$ // #ifndef wx_utils_code_align_h #define wx_utils_code_align_h namespace wamas { namespace platform { namespace utils { // FIXME: is this ALIGNMENT calculation correct? >>> struct _al { void* p ; char c ; } ; static const size_t ALIGNMENT = sizeof(_al) - sizeof(void*); } // /namespace } // /namespace } // /namespace #endif --- NEW FILE: DebugWriter.h --- // // $Id$ // #ifndef wx_utils_DebugWriter_h #define wx_utils_DebugWriter_h #include <string> namespace wamas { namespace platform { namespace utils { class DebugWriter { public: // Debug levels enum { Emerg, Alert, Error, Notify, Debug, Trace }; virtual int write(const char* file, int line, const std::string& facility, const int level, const std::string& msg)=0; virtual bool check(const std::string& facility)=0; virtual ~DebugWriter() {}; }; } // /namespace } // /namespace } // /namespace #endif // end of wx_utils_DebugWriter_h --- NEW FILE: atomic_count.h --- #ifndef wx__utils__atomic_count #define wx__utils__atomic_count #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_BOOST #ifndef BOOST_DISABLE_THREADS #include <boost/detail/atomic_count.hpp> #ifdef BOOST_HAS_THREADS #define WX_ATOMIC_COUNT_WITH_BOOST 1 #endif // BOOST_HAS_THREADS #endif // ! BOOST_DISABLE_THREADS #endif // HAVE_BOOST #ifdef WX_ATOMIC_COUNT_WITH_BOOST namespace wamas { namespace platform { namespace utils { typedef boost::detail::atomic_count atomic_count; } // /namespace } // /namespace } // /namespace #else // ! WX_ATOMIC_COUNT_WITH_BOOST #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) #include <windows.h> namespace wamas {namespace platform {namespace utils { // stolen from boost/detail/atomic_count_win32.hpp class atomic_count { public: explicit atomic_count( long v ) : value_( v ) {} long operator++() { return ::InterlockedIncrement( &value_ ); } long operator--() { return ::InterlockedDecrement( &value_ ); } operator long() const { return static_cast<long const volatile &>( value_ ); } private: atomic_count( atomic_count const & ); atomic_count & operator=( atomic_count const & ); long value_; }; }}} #else // !WIN32 namespace wamas {namespace platform {namespace utils { typedef long atomic_count; }}} #endif // WIN32 #endif // WX_ATOMIC_COUNT_WITH_BOOST #endif // wx__utils__atomic_count --- NEW FILE: HashSet.h --- // // $Id$ // #ifndef wx_utils_code_hashset_h #define wx_utils_code_hashset_h #ifdef HAVE_CONFIG_H # include <config.h> #endif #ifdef HAVE_HASH_MAP # include <ext/hash_set> #else # include <set> #endif namespace wamas { namespace platform { namespace utils { /** @brief Hash-set; a normal set for older C++ compilers. */ template< typename VALUE, typename HASHFUNC > class HashSet #ifdef HAVE_HASH_MAP : public HASH_MAP_NAMESPACE::hash_set<VALUE, HASHFUNC> { public: explicit HashSet(std::size_t n) : HASH_MAP_NAMESPACE::hash_set<VALUE, HASHFUNC>(n) {} HashSet() {} }; #else : public std::set<VALUE> { public: explicit HashSet(std::size_t) {} HashSet() {} }; #endif } // /namespace } // /namespace } // /namespace #endif --- NEW FILE: smartptr.cc --- #include "smartptr.h" namespace wamas { namespace platform { namespace utils { LTA_MEMDEF(RefCounted, 20061107, "$Id$"); void RefCounted::ref() { ++refcount_; } void RefCounted::unref() { if (!--refcount_) delete this; } #ifdef WX_REFCOUNTED_COLLECT_NEW RefCounted::NewStatistics RefCounted::new_statistics_; void* RefCounted::operator new (std::size_t s) { NewStatistics::iterator pos = new_statistics_.find(s); if(pos==new_statistics_.end()) new_statistics_[s] = 1; else ++(pos->second); return malloc(s); } void RefCounted::operator delete (void* p) { free(p); } #endif // WX_REFCOUNTED_COLLECT_NEW } // /namespace } // /namespace } // /namespace --- NEW FILE: CerrDebugWriter.h --- // // $Id$ // #ifndef wx_utils_CerrDebugWriter_h #define wx_utils_CerrDebugWriter_h #include "DebugWriter.h" namespace wamas { namespace platform { namespace utils { class CerrDebugWriter : public DebugWriter { public: int write(const char* file, int line, const std::string& facility, const int level, const std::string& msg); bool check(const std::string& facility); static CerrDebugWriter& instance(); // ensures singleton private: static CerrDebugWriter* inst_; // the instance of CerrDebugWriter private: CerrDebugWriter() {}; }; } // /namespace } // /namespace } // /namespace #endif // end of wx_utils_CerrDebugWriter_h --- NEW FILE: linkassert.h --- // -*- mode: C++; c-basic-offset: 3 -*- // // $Id$ // #ifndef wx_utils_code_linkassert_h #define wx_utils_code_linkassert_h namespace wamas { namespace platform { namespace utils { /** \page page_utils_code_linkassert Link Time Assertions \see LTA_MEMDECL \see LTA_MEMDEF \see LTA_STATDEF \section utils_code_linkassert What is that? Best to explain the problem in C first because it is more explicit there. Suppose you have a header file containing the following declaration, plus a "member" function: \code struct foo { long l1; long l2; }; extern void foo_print_l2(const struct foo*); \endcode In the implementation (the .c file), suppose you define <tt>foo_print_l2()</tt> as follows: \code void foo_print_l2(const struct foo* f) { printf ("%ld\n", f->l2) ; } \endcode Now, you change the declaration of <tt>struct foo</tt> to read \code struct foo { long l1; long l1_5; long l2; }; \endcode (note the move of \c l2 by 1 long in the memory layout) and you do \em not recompile your .c file to tell the function <tt>foo_print_l2()</tt> to use the new offset of \c l2 from the base pointer, the function will print <tt>foo->l1_5</tt> instead of <tt>foo->l2</tt>, if it is linked with a fresh executable. (This whole thing applies to classes as well (which are structs basically)). A general precaution to this is to reference a variable from the .h file that is defined in the .c file. In C, before the change, this would read in the header file \code struct foo { long l1; long l2; }; extern int foo_version1; // you have to explicitly reference the foo_version1 so that the // compiler does not ignore the declaration and thus does not // reference it static int foo_version = foo_version1; \endcode and in the .c file \code int foo_version1; \endcode If you change the memory layout of the struct, you somehow have to force a recompile of the .c file. Do this through a change of the name of the extern variable. In the .h file write \code struct foo { long l1; long l1_5; long l2; }; extern int foo_version2; static int foo_version = foo_version2; \endcode In the .c file write \code int foo_version2; \endcode Thus, if you make the .h file publicly available, and an executable compiled with this new <tt>struct foo</tt> memory layout references the <tt>foo_print_l2()</tt> function, it must also reference the <tt>foo_version2</tt> extern variable. If the executable is linked with the old .o file, the linker won't be able to resolve the reference because the old .o file still contains the old variable <tt>foo_version1</tt>. We call this (most sophisticatedly) a <em>link time assertion</em>. In C++, this could be written as follows using static members. No matter how you view it, in C or C++, the principle is the same. The .h file: \code class Foo { public: // something ... public: static const char* version1; } ; static const char* Foo_version = Foo::version1; \endcode The .cc file: \code // we use a char* for the variable (formatted like this) because // this enables us to grep a binary for a particular class // version/revision const char* Foo::version1 = "Foo"; \endcode \section utils_code_linkassert_when When to increment the version number To summarize, the rules of thumb as to when to change the <em>link time assertion symbol</em> (e.g. increment <tt>version1</tt> to <tt>version2</tt> in the example) are: <ul> <li>You added and/or removed a member variable</li> <li>You added and/or removed a virtual method (this changes the layout of the vtable (or so))</li> <li>You added and/or removed a base class (a base class can be thought of as an implicit member)</li> <li>You added and/or removed the <tt>virtual</tt> keyword to/from a base class</li> <li>You need not increment the version if you added/removed a non-virtual method.</li> </ul> */ /** \def LTA_MEMDECL(num) \ingroup utils_code \brief Declare class member with version number \a num. You write this macro in the class definition, about where you would declare the member (in fact, the macro declares the member for you). See \ref page_utils_code_linkassert for a description. */ #define LTA_MEMDECL(num) static const char* version##num /** \def LTA_MEMDEF(class, num, rhs) \ingroup utils_code \brief Implement member of \a class with version number \a and the value \a rhs. \a rhs is a string. You write this macro in the .cc file, just where you would implement the static member you declared with LTA_MEMDECL. See \ref page_utils_code_linkassert for a description. */ #define LTA_MEMDEF(class, num, rhs) const char* class::version##num = rhs /** \def LTA_STATDEF(class, num) \ingroup utils_code \brief Reference the static member. Referencing the static member is necessary. It persuades the compiler to generate a reference to the member, and to not optimize it away. See \ref page_utils_code_linkassert for a description. */ #ifdef __PXWC__ #define LTA_STATDEF(class, num) #else #define LTA_STATDEF(class, num) static const char* class##_##version##num = class::version##num #endif } // /namespace } // /namespace } // /namespace #endif --- NEW FILE: DebugWriterMgr.h --- // // $Id$ // #ifndef wx_utils_DebugWriterMgr_h #define wx_utils_DebugWriterMgr_h #include "CerrDebugWriter.h" namespace wamas { namespace platform { namespace utils { class DebugWriterMgr { public: DebugWriter& getDebugWriter(); void setDebugWriter(DebugWriter* debWriter); void activate(); void deactivate(); static DebugWriterMgr& instance(); private: static DebugWriterMgr* inst_; DebugWriter* defaultWriter_; DebugWriter* explicitWriter_; DebugWriter* debugWriter_; private: DebugWriterMgr(); }; } // /namespace } // /namespace } // /namespace #endif // end of wx_utils_DebugWriterMgr_h --- NEW FILE: debug.cc --- // -*- mode: C++; c-basic-offset: 3 -*- // // $Id$ // #include "debug.h" #include <set> #include <iostream> namespace wamas { namespace platform { namespace utils { using namespace std; class DebugImpl : public set<string> {}; Debug instance_; static const char* env_levels = "WX_DEBUG_LEVELS"; enum ParseState { PS_SPACE, PS_CHAR }; static inline bool is_levelchar( char c) { switch (c) { case '_': case ':': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return true; } return false; } Debug::Debug( bool read_env) { impl_ = new DebugImpl; if (read_env) { const char* envlevels = getenv(env_levels); if (envlevels) parse_levels(envlevels); } } Debug::Debug( const string& levels, bool read_env) { impl_ = new DebugImpl; parse_levels(levels); if (read_env) { const char* envlevels = getenv(env_levels); if (envlevels) parse_levels(envlevels); } } Debug::~Debug() { delete impl_; } void Debug::add_level( const string& l) { impl_->insert(l); } void Debug::parse_levels( const string& levelstr) { ParseState state = PS_SPACE; string::size_type beg; for (string::size_type i=0; i<levelstr.size(); i++) { char c = levelstr[i]; switch (state) { case PS_SPACE: { if (is_levelchar(c)) { beg = i; state = PS_CHAR; } break; } case PS_CHAR: { if (!is_levelchar(c)) { impl_->insert(levelstr.substr(beg, i-beg)); state = PS_SPACE; } break; } } } if (state == PS_CHAR) impl_->insert(levelstr.substr(beg, levelstr.size()-beg)); } bool Debug::have_level( const string& level) { DebugImpl::const_iterator pos = impl_->find(level); return pos != impl_->end(); } int Debug::n_levels() { return impl_->size(); } Debug& Debug::instance() { return instance_; } } // /namespace } // /namespace } // /namespace --- NEW FILE: Confix2.dir --- --- NEW FILE: StringMap.cc --- // // $Id$ // #include "StringMap.h" namespace wamas { namespace platform { namespace utils { std::size_t StringHash::operator()(std::string const& s) const { #ifdef HAVE_HASH_MAP HASH_MAP_NAMESPACE::hash<const char*> H; return H(s.c_str()); #else unsigned long h=0; for(std::string::const_iterator it=s.begin(); it!=s.end(); ++it) { h = 5*h + *it; } return std::size_t(h); #endif } } // /namespace } // /namespace } // /namespace --- NEW FILE: indent.h --- // -*- mode: C++; c-basic-offset: 3 -*- // // $Id$ // #ifndef wx_utils_code_indent_h #define wx_utils_code_indent_h #include <iostream> namespace wamas { namespace platform { namespace utils { std::ostream& indent(std::ostream&, int indent); } // /namespace } // /namespace } // /namespace #endif --- NEW FILE: HashMap.h --- // // $Id$ // #ifndef wx_utils_code_hashmap_h #define wx_utils_code_hashmap_h #ifdef HAVE_CONFIG_H # include <config.h> #endif #ifdef HAVE_HASH_MAP # include <ext/hash_map> #else # include <map> #endif namespace wamas { namespace platform { namespace utils { /** @brief Hash-map; a normal map for older C++ compilers. */ template< typename KEY, typename VALUE, typename HASHFUNC > class HashMap #ifdef HAVE_HASH_MAP : public HASH_MAP_NAMESPACE::hash_map<KEY, VALUE, HASHFUNC> { public: explicit HashMap(std::size_t n) : HASH_MAP_NAMESPACE::hash_map<KEY, VALUE, HASHFUNC>(n) {} HashMap() {} }; #else : public std::map<KEY, VALUE> { public: explicit HashMap(std::size_t) {} HashMap() {} }; #endif /** @brief Hash-multi-map; a normal multi-map for older C++ compilers. */ template< typename KEY, typename VALUE, typename HASHFUNC > class HashMultiMap #ifdef HAVE_HASH_MAP : public HASH_MAP_NAMESPACE::hash_multimap<KEY, VALUE, HASHFUNC> { public: explicit HashMultiMap(std::size_t n) : HASH_MAP_NAMESPACE::hash_multimap<KEY, VALUE, HASHFUNC>(n) {} HashMultiMap() {} }; #else : public std::multimap<KEY, VALUE> { public: explicit HashMultiMap(std::size_t) {} HashMultiMap() {} }; #endif } // /namespace } // /namespace } // /namespace #endif --- NEW FILE: indent.cc --- // -*- mode: C++; c-basic-offset: 3 -*- // // $Id$ // #include "indent.h" namespace wamas { namespace platform { namespace utils { std::ostream& indent(std::ostream& o, int indent) { while (indent--) o << ' '; return o; } } // /namespace } // /namespace } // /namespace --- NEW FILE: extern_c.h --- // -*- mode: C++; c-basic-offset: 3 -*- // // $Id$ // #ifndef wx_utils_code_extern_c_h #define wx_utils_code_extern_c_h #ifdef __cplusplus // we use confix's fancy namespace-to-includedir mapping. as there is // nothing in this file but macros, namespaces don't apply at all, so // there's no other reason to include namespaces here. namespace wamas { namespace platform { namespace utils { #endif #ifdef __cplusplus # define BEGIN_CPLUSPLUS extern "C" { # define END_CPLUSPLUS } #else # define BEGIN_CPLUSPLUS # define END_CPLUSPLUS #endif #ifdef __cplusplus } // /namespace } // /namespace }; // /namespace #endif #endif |