You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(58) |
Sep
(79) |
Oct
(41) |
Nov
(80) |
Dec
(23) |
---|
From: <sg...@us...> - 2003-11-17 21:05:28
|
Update of /cvsroot/libfunutil/libfunutil/toc/make In directory sc8-pr-cvs1:/tmp/cvs-serv5553 Modified Files: NAMESPACE.make Log Message: i'm a trottel sometimes - this one actually does something Index: NAMESPACE.make =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/toc/make/NAMESPACE.make,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- NAMESPACE.make 17 Nov 2003 21:00:14 -0000 1.3 +++ NAMESPACE.make 17 Nov 2003 21:05:03 -0000 1.4 @@ -28,8 +28,8 @@ cmp -s $(NAMESPACE_TMPFILE) $@ && rm $(NAMESPACE_TMPFILE); \ test -f $(NAMESPACE_TMPFILE) && { mv $(NAMESPACE_TMPFILE) $@; echo " updated"; } || echo " up to date"; -#NAMESPACE: $(NAMESPACE_FILTERED_FILES) -NAMESPACE: - @echo NAMESPACE_PREFIX=$(NAMESPACE_PREFIX) - @echo NAMESPACE_FILTERED_FILES=$(NAMESPACE_FILTERED_FILES) - @echo $(NAMESPACE_PREFIX)* +NAMESPACE: $(NAMESPACE_FILTERED_FILES) +#NAMESPACE: +# @echo NAMESPACE_PREFIX=$(NAMESPACE_PREFIX) +# @echo NAMESPACE_FILTERED_FILES=$(NAMESPACE_FILTERED_FILES) +# @echo $(NAMESPACE_PREFIX)* |
From: <sg...@us...> - 2003-11-17 21:00:39
|
Update of /cvsroot/libfunutil/libfunutil/toc/make In directory sc8-pr-cvs1:/tmp/cvs-serv4354a Modified Files: NAMESPACE.make Log Message: removed the need for the client to set NAMESPACE_FILTERED_FILES Index: NAMESPACE.make =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/toc/make/NAMESPACE.make,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- NAMESPACE.make 17 Nov 2003 19:08:11 -0000 1.2 +++ NAMESPACE.make 17 Nov 2003 21:00:14 -0000 1.3 @@ -5,19 +5,22 @@ # define: # NAMESPACE = mynamespace # NAMESPACE_TOKEN = token to replace when filtering. e.g. MY_NAMESPACE -# NAMESPACE_PREFIX = filename prefix for pre-filtered files. Defaults to ns. -# NAMESPACE_FILTERED_FILES = list containing XXX which should be filtered from -# $(NAMESPACE_PREFIX)XXX. -# then include this file. +# NAMESPACE_PREFIX = filename prefix for pre-filtered files. Defaults to "ns.". +# All files named $(NAMESPACE_PREFIX).XXX are filtered to XXX. +# +# Then include this file. NAMESPACE_PREFIX ?= ns. NAMESPACE_TOKEN ?= NAMESPACE ifeq (,$(NAMESPACE)) $(error You must set the variable NAMESPACE before including this file.) endif -$(top_srcdir)/toc.$(PACKAGE_NAME).make: + NAMESPACE_MAKE = $(toc_makesdir)/NAMESPACE.make NAMESPACE_TMPFILE = .toc.NAMESPACE.tmp + +NAMESPACE_FILTERED_FILES = $(patsubst $(NAMESPACE_PREFIX)%,%,$(wildcard $(NAMESPACE_PREFIX)*)) +CLEAN_FILES += $(NAMESPACE_FILTERED_FILES) $(NAMESPACE_FILTERED_FILES): %: $(NAMESPACE_PREFIX)% Makefile $(top_srcdir)/toc.$(PACKAGE_NAME).make $(NAMESPACE_MAKE) @nsf=$<; \ echo -n "namespace $(NAMESPACE): $$nsf --> $@ ... "; \ @@ -25,3 +28,8 @@ cmp -s $(NAMESPACE_TMPFILE) $@ && rm $(NAMESPACE_TMPFILE); \ test -f $(NAMESPACE_TMPFILE) && { mv $(NAMESPACE_TMPFILE) $@; echo " updated"; } || echo " up to date"; +#NAMESPACE: $(NAMESPACE_FILTERED_FILES) +NAMESPACE: + @echo NAMESPACE_PREFIX=$(NAMESPACE_PREFIX) + @echo NAMESPACE_FILTERED_FILES=$(NAMESPACE_FILTERED_FILES) + @echo $(NAMESPACE_PREFIX)* |
From: <sg...@us...> - 2003-11-17 20:54:17
|
Update of /cvsroot/libfunutil/libfunutil/client/s11nconvert In directory sc8-pr-cvs1:/tmp/cvs-serv3196/client/s11nconvert Modified Files: Makefile Log Message: namespace-related refactoring Index: Makefile =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/Makefile,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- Makefile 17 Nov 2003 20:41:14 -0000 1.3 +++ Makefile 17 Nov 2003 20:53:53 -0000 1.4 @@ -74,12 +74,10 @@ NAMESPACE = $(S11N_NAMESPACE) NAMESPACE_TOKEN = S11N_NAMESPACE NAMESPACE_PREFIX = ns. -NAMESPACE_FILTERED_FILES = $(SOURCES) $(HEADERS) -namespace: $(NAMESPACE_FILTERED_FILES) include $(toc_makesdir)/NAMESPACE.make -all: namespace BIN_PROGRAMS SHARED_LIBS tip link-bigso +all: NAMESPACE BIN_PROGRAMS SHARED_LIBS tip link-bigso alt: clean ALTS11N=1 ${MAKE} |
From: <sg...@us...> - 2003-11-17 20:54:07
|
Update of /cvsroot/libfunutil/libfunutil/client/s11nconvert In directory sc8-pr-cvs1:/tmp/cvs-serv3165/client/s11nconvert Added Files: ns.AltSerializable.cpp ns.AltSerializable.h ns.BarClass.cpp ns.BarClass.h ns.FooClass.cpp ns.FooClass.h ns.LoadableClass.h ns.LoadableSubclass.cpp ns.LoadableSubclass.h ns.main.cpp ns.maser.cpp Log Message: egg --- NEW FILE: ns.AltSerializable.cpp --- #include "AltSerializable.h" #include <s11n/debuggering_macros.h> // COUT/CERR #include <s11n/class_loader.h> // COUT/CERR #include <s11n/argv_parser.h> // COUT/CERR #define VERBOSE if (s11n::argv_parser::args().get_bool( "v", false ) ) CERR /** A test class for demonstrating the ability to use non-s11n::Serializable types with the s11n framework. */ namespace alts11n { AltSerializable::AltSerializable(){}; AltSerializable::~AltSerializable() { VERBOSE << "~AltSerializable()"<<std::endl; }; bool AltSerializable::save_state( AltSerializable::state & node ) const { // node.impl_class( this->get_class() ); VERBOSE << std::hex<<this<<" save_state("<<node.name()<<"/"<<node.impl_class()<<")"<<std::endl; return true; } bool AltSerializable::load_state( const AltSerializable::state & node ) { VERBOSE << std::hex<<this<<" load_state("<<node.name()<<"/"<<node.impl_class()<<") this="<<std::hex<<this<<""<<std::endl; const AltSerializable::state * subn = node.child( "sub" ); if( subn ) { AltSerializable * sub = 0; sub = subn->deserialize<AltSerializable>(); if( sub ){VERBOSE << "sub="<<std::hex<<sub<<": class?="<<subn->impl_class()<<std::endl;} else VERBOSE << "couldn't deserialize it!" << std::endl; delete( sub ); } return true; } void AltSerializable::bogo_method(std::string str) { VERBOSE << std::hex<<this<<" "<<"::bogo_method() msg=["<<str<<"]"<<std::endl; } AltSub::AltSub() {}; AltSub::~AltSub() { VERBOSE << "~AltSub()"<<std::endl; }; bool AltSub::load_state( const AltSerializable::state & node ) { VERBOSE << "AltSub::load_state("<<node.name()<<"/"<<node.impl_class()<<")"<<std::endl; // this->bogo_method("from AltSub"); bool b = this->AltSerializable::load_state( node ); const AltSerializable::state * subn = node.child( "subsub" ); if( subn ) { AltSerializable * sub = subn->deserialize<AltSubSub>(); //AltSub * sub = subn->deserialize<AltSub>(); // ^^^ no workie. to fix if( sub ) VERBOSE << "subsub="<<std::hex<<sub<<std::endl; else VERBOSE << "couldn't deserialize it!" << std::endl; delete( sub ); } return b; } AltSubSub::AltSubSub() {};// this->set_class("alts11n::AltSubSub"); } AltSubSub::~AltSubSub() { VERBOSE << "~AltSubSub()"<<std::endl; } bool AltSubSub::load_state( const AltSerializable::state & node ) { VERBOSE << "AltSubSub::load_state("<<node.name()<<"/"<<node.impl_class()<<")"<<std::endl; // this->bogo_method("from AltSubSub"); bool b = this->AltSub::load_state( node ); // AltSub hardcode; // const s11n_node * nsub = node.child( "sub" ); // if( nsub ) // { // VERBOSE << "hard-deserializing "<<nsub->name()<<" (class="<<nsub->impl_class()<<")"<<std::endl; // nsub->deserialize( hardcode ); // } return b; } }; // namespace alts11n:: --- NEW FILE: ns.AltSerializable.h --- #ifndef ALTS11N_ALTSERIALIZABLE_H_INCLUDED #define ALTS11N_ALTSERIALIZABLE_H_INCLUDED 1 #include <string> #include <s11n/s11n_node.h> /** A test class for demonstrating the ability to use non-s11n::Serializable types with the s11n framework. */ namespace alts11n { class AltSerializable { private: std::string m_name; public: AltSerializable(); virtual ~AltSerializable(); typedef s11n::s11n_node state; virtual bool save_state( state & node ) const; virtual bool load_state( const state & node ); void bogo_method(std::string str= ""); }; class AltSub : public AltSerializable { public: AltSub(); virtual ~AltSub(); virtual bool load_state( const AltSerializable::state & node ); }; class AltSubSub : public AltSub { public: AltSubSub(); virtual ~AltSubSub(); virtual bool load_state( const AltSerializable::state & node ); }; } // namespace alts11n:: #include <s11n/serializable_adapter.h> /** This creates the required serializable_adapter<AltSerializable> specializations to map the AltSerializable API to Serializable's. This is all it takes to make the framework able to use AltSerializable. You may provide your own implementation, instead of using this macro, and you must do so if your de/serialize() function signatures differ from the defaults. It also registers the types with the appropriate s11n::class_loader and sets up s11n::class_name<> specializations. */ #define EASY_WAY 0 #if EASY_WAY SERIALIZABLE_ADAPTER(alts11n::AltSerializable,save_state,load_state); #else CLASSLOADER_REGISTER(alts11n::AltSerializable,alts11n::AltSerializable); CLASS_NAME(alts11n::AltSerializable); namespace { typedef s11n::s11n_node node_type; template <> struct serializable_adapter<alts11n::AltSerializable,node_type> { typedef alts11n::AltSerializable serializable_type; typedef alts11n::AltSerializable impl_type; explicit serializable_adapter(){}; ~serializable_adapter(){}; static std::string class_name() { return "alts11n::AltSerializable"; } static bool serialize( const serializable_type & ser, node_type &node ) { static unsigned long count = 0; // you don't need this! ++count; node.impl_class( class_name() ); return ser.save_state( node ); } static bool deserialize( serializable_type & ser, const node_type & node ) { static unsigned long count = 0; // you don't need this! ++count; return ser.load_state( node ); } }; } #endif // EASY_WAY SERIALIZABLE_REGISTER(alts11n::AltSerializable,alts11n::AltSub); SERIALIZABLE_REGISTER(alts11n::AltSerializable,alts11n::AltSubSub); #endif // ALTS11N_ALTSERIALIZABLE_H_INCLUDED --- NEW FILE: ns.BarClass.cpp --- #include <s11n/s11n-macros.h> // COUT/CERR #include "BarClass.h" using namespace s11n; using namespace std; BarClass::BarClass( ) { name = "unnamed"; magic_number = 0; //LOUT << "BarClass()" << endl; }; BarClass::~BarClass( ) { //LIBE_VERBOSE_DTORS(BarClass); }; bool BarClass::s7e( s11n_node & ser ) const { if ( !this->Serializable::s7e( ser ) ) return false; ser.set( "name", this->name ); ser.set( "magic_number", magic_number ); return true; } bool BarClass::d9e( const s11n_node & node ) { CERR << "BarClass::deserialize()" << endl; this->name = node.get( "name", this->name ); this->magic_number = node.get( "magic_number", this->magic_number ); return true; } --- NEW FILE: ns.BarClass.h --- #include <s11n/s11n-macros.h> // COUT/CERR #include <s11n/s11n_node.h> using namespace s11n; using namespace std; // #include <s11n/serializable_adapter.h> #include <s11n/Serializable.h> struct BarClass: public s11n::Serializable { std::string name; int magic_number; BarClass( ); virtual ~ BarClass( ); virtual bool s7e( s11n::s11n_node & ser ) const; virtual bool d9e( const s11n::s11n_node & node ); }; SERIALIZABLE_REGISTER(s11n::Serializable,BarClass); --- NEW FILE: ns.FooClass.cpp --- #include <s11n/s11n-macros.h> // COUT/CERR #include <s11n/s11n_globals.h> // registration-related macros // #include <s11n/class_loader.h> // #include <s11n/instantiator.h> #include "FooClass.h" using namespace s11n; using namespace std; namespace foo { using namespace s11n; using namespace std; struct Baz : public foo::FooClass { ~Baz(){} }; struct BarClass : public foo::FooClass { ~BarClass(){} }; } // namespace foo SERIALIZABLE_REGISTER(s11n::Serializable,foo::BarClass); SERIALIZABLE_REGISTER(s11n::Serializable,foo::Baz); namespace { /** We use dll_loader_bootstrap() to run code, activated when static objects are initialized. i.e., before main() or when a DLL is dlopen()ed. */ int dll_loader_bootstrap() { CERR << "dll_loader_bootstrap()" << endl; typedef s11n::class_loader<s11n::Serializable> CL; CL::register_subtype<foo::FooClass>("foo::WonderBra"); return 0; } static const int nomeaning = dll_loader_bootstrap(); } namespace foo { using namespace s11n; using namespace std; FooClass::FooClass() { this->name = "unnamed FooClass object"; for( int i = 0; i < 5; i++ ) { this->m_vec.push_back( i ); } } FooClass::~FooClass() { } bool FooClass::s7e( s11n_node & node ) const { if ( !this->Serializable::s7e( node ) ) return false; node.set( "name", this->name ); node.serialize_list( "vector", this->m_vec ); return true; } bool FooClass::d9e( const s11n_node & node ) { this->m_vec.clear(); CERR <<"deserialize() impl_class="<<node.impl_class() << std::endl; if ( !this->Serializable::d9e( node ) ) return false; this->name = node.get( "name", "<unnamed>" ); node.deserialize_list( "vector", this->m_vec ); CERR << "m_vec size = " << m_vec.size() << std::endl; return true; } }; // namespace foo --- NEW FILE: ns.FooClass.h --- #ifndef FOO_H_INCLUDED #define FOO_H_INCLUDED 1 #include <s11n/s11n_node.h> #include <s11n/Serializable.h> #include <vector> namespace foo { struct FooClass : public s11n::Serializable { std::vector<int> m_vec; std::string name; FooClass( ); virtual ~ FooClass( ); virtual bool s7e( s11n::s11n_node & ser ) const; virtual bool d9e( const s11n::s11n_node & ser ); // private: // void bogosity(){} // int incompatibility; }; }; // namespace foo SERIALIZABLE_REGISTER(s11n::Serializable,foo::FooClass); #endif // FOO_H_INCLUDED --- NEW FILE: ns.LoadableClass.h --- #ifndef LOADABLECLASS_H_INCLUDED #define LOADABLECLASS_H_INCLUDED 1 #include <iostream> #include <s11n/s11n-macros.h> // COUT struct LoadableClass { LoadableClass(){}; virtual ~LoadableClass(){}; virtual void foo() { COUT << "LoadableClass::foo()" << std::endl; } }; #endif // LOADABLECLASS_H_INCLUDED --- NEW FILE: ns.LoadableSubclass.cpp --- #include "LoadableSubclass.h" void LoadableSubclass::foo() { COUT << "LoadableSubclass::foo()" << std::endl; } extern "C" { LoadableClass * new_LoadableSubclass() { return new LoadableSubclass(); } }; --- NEW FILE: ns.LoadableSubclass.h --- #ifndef LOADABLESUBCLASS_H_INCLUDED #define LOADABLESUBCLASS_H_INCLUDED 1 #include "LoadableClass.h" struct LoadableSubclass : public LoadableClass { LoadableSubclass(){}; virtual ~LoadableSubclass(){}; virtual void foo(); }; #endif // LOADABLESUBCLASS_H_INCLUDED --- NEW FILE: ns.main.cpp --- #include <cassert> #include <iostream> #include <fstream> #include <string> #include <stack> #include <list> #include <sstream> #include <algorithm> #include <stdlib.h> // random() #include <time.h> // time() #include <unistd.h> // isatty() #include <s11n/argv_parser.h> // #include <iterator> // for use with std::copy() #include <s11n/s11n-macros.h> // COUT/CERR #include <s11n/s11n_globals.h> // library_version() #include <s11n/s11n_node.h> #include <s11n/eprintf.h> // efstring() #include <s11n/pointer_list.h> #include <s11n/property_store.h> #include <s11n/class_loader.h> #include <s11n/class_name.h> #include <s11n/instantiator.h> #include <s11n/s11n_io.h> #include <s11n/serializer_loader.h> #include <s11n/node_loader.h> #include <s11n/Serializable.h> // #include <s11n/serializable_adapter.h> // SERIALIZABLE_ADAPTER(s11n::Serializable,s7e,d9e); // #include <s11n/include_from_main.h> #if HAVE_CONFIG_H # include "config.h" // S11N_LIBRARY_VERSION, PACKAGE_{VERSION,NAME} #endif #ifndef S11N_LIBRARY_VERSION # error S11N_LIBRARY_VERSION must be set! #endif #if HAVE_ZLIB # include <s11n/gzstream.h> #endif #if HAVE_BZLIB # include <s11n/bzstream.h> #endif #ifndef SERIALIZABLE_TYPE # define SERIALIZABLE_TYPE s11n::Serializable #endif #ifndef SERIALIZABLE_TYPE_STRING # define SERIALIZABLE_TYPE_STRING "s11n::Serializable" #endif #include "AltSerializable.h" using namespace s11n; using namespace s11n; using namespace std; #define APP_VERSION std::string("$Revision: 1.1 $") #define APP_NAME "s11nconvert" #define VERBOSE if( ARGV::args().get_bool( "v", ARGV::args().get_bool( "verbose", false ) ) ) CERR #define GIGOVERBOSE VERBOSE << "id["<<this->m_id<<"@"<<depth<<"] " typedef s11n::argv_parser ARGV; #define QUIETLY if( ! ARGV::args().get_bool( "q", ARGV::args().get_bool( "quiet", false ) ) ) CERR // ^^^^ output unless -q is set std::string random_ascii( unsigned int len ) { std::string out; for( unsigned int i = 0; i < len; i++ ) { //out += (unsigned char) ( random() % 78 ) + 46; out += (unsigned char) ( random() % 25 ) + 65; } return out; } // CLASS_NAME(std::map<int,double>); /** Garbage In, Garbage Out. For generating lots of junk serialized data quickly. */ class GIGO : public s11n::Serializable { public: typedef std::map<int,std::string> IntStrMap; typedef std::map<double,std::string> DblStrMap; static unsigned long inst_count; static unsigned long total_inst_count; IntStrMap istrmap; DblStrMap dstrmap; typedef s11n::pointer_list<GIGO> list_type; typedef std::list<std::string> SL; SL slist; list_type childs; s11n::property_store props; unsigned long m_id; GIGO() { m_id = ++total_inst_count; ++inst_count; childs.auto_delete( true ); // GIGOVERBOSE << "GIG0() #"<< inst_count << std::endl; } virtual ~GIGO() { --inst_count; // GIGOVERBOSE << "~GIG0() remaining: "<< inst_count << std::endl; } // populates this object with garbage data void garbage() { childs.delete_all(); istrmap.erase( istrmap.begin(), istrmap.end() ); dstrmap.erase( dstrmap.begin(), dstrmap.end() ); slist.erase( slist.begin(), slist.end() ); this->props.clear_properties(); static long depth = 0; ++depth; static const int max_childs = 5; for( int i = 0; i < random() % 5; i++ ) { slist.push_back( random_ascii(random()%30 ) ); } int i = 0; #define INSTR(S) istrmap[i++] = S; dstrmap[i++] = S; for( ; i < random() % 10; ) { INSTR(random_ascii(random()%30)); } int rnd = random() % 10; std::string pname; std::string pval; for( int i = 0; i < rnd; i++ ) { pname = s11n::efstring( "property",i ); pval = random_ascii( random() % 50 ); props.set( pname, pval ); } rnd = random() % max_childs - depth; GIGO * ch = 0; for( int i = 0; i < rnd; i++ ) { ch = new GIGO(); ch->garbage(); childs.push_back( ch ); } --depth; } virtual bool s7e( s11n_node & node ) const { if( ! this->Serializable::s7e( node ) ) return false; static long depth = 0; ++depth; GIGOVERBOSE << "GIG0::serialize()" << std::endl; node.set( "id", m_id ); node.serialize_list( "string_list", slist ); node.serialize_map( "int_to_str_map", istrmap ); node.serialize_map( "dbl_to_str_map", dstrmap ); node.serialize_properties( this->props ); node.serialize_children( "gigo_child", childs ); --depth; return true; } virtual bool d9e( const s11n_node & node ) { if( ! this->Serializable::d9e( node ) ) return false; static long depth = 0; ++depth; istrmap.erase( istrmap.begin(), istrmap.end() ); dstrmap.erase( dstrmap.begin(), dstrmap.end() ); childs.delete_all(); this->props.clear_properties(); slist.erase( slist.begin(), slist.end() ); this->m_id = node.get<int>( "id", m_id ); unsigned long count = 0; count = node.deserialize_list( "string_list", slist ); GIGOVERBOSE << "string_list entries: " << count << std::endl; // GIGO * g = node.deserialize<GIGO>( "gigo_child" ); // GIGOVERBOSE << "node.deserialize<GIGO>(...) = " <<std::hex<<g<<std::endl; // delete( g ); count = node.deserialize_properties( this->props ); GIGOVERBOSE << "property count: " << this->props.size() << std::endl; count = node.deserialize_map( "int_to_str_map", istrmap ); GIGOVERBOSE << "int_to_str_map entries: " << count << std::endl; count = node.deserialize_map( "dbl_to_str_map", dstrmap ); GIGOVERBOSE << " dbl_to_str_map entries: " << count << std::endl; count = node.deserialize_children( "gigo_child", childs ); GIGOVERBOSE << "gigo_child count: " << count << ", and childs.size() says: " << childs.size() << std::endl; --depth; return true; } }; unsigned long GIGO::inst_count = 0; unsigned long GIGO::total_inst_count = 0; /** Register with the framework: */ SERIALIZABLE_REGISTER(s11n::Serializable,GIGO); /** A test namespace. */ namespace fake { /** A test class. */ struct FakeRoot : public s11n::Serializable { std::string m_foo; std::string m_bar; typedef std::map<double,std::string> IntStrMap; typedef std::map<double,std::string> DblStrMap; typedef pointer_list < s11n::Serializable > FakeVec; //typedef std::vector<BarClass *> FakeVec; FakeVec m_vec; FakeRoot() { m_vec.auto_delete( true ); }; virtual ~ FakeRoot() { }; virtual bool s7e( s11n_node & node ) const { VERBOSE << "FakeRoot::serialize()" << std::endl; if ( !this->Serializable::s7e( node ) ) return false; node.set( "foo", m_foo ); node.set( "bar", m_bar ); node.serialize_children( "childs", m_vec ); return true; } virtual bool d9e( const s11n_node & node ) { VERBOSE << "FakeRoot::deserialize()" << std::endl; typedef alts11n::AltSerializable ALT; ALT * theother = 0; // node.classloader<ALT>().load( "alts11n::AltSerializable" ); theother = node.deserialize<ALT>("othertype"); VERBOSE << "theother=="<<std::hex<<theother<<std::endl; delete( theother ); m_vec.delete_all(); // node.deserialize_children<s11n::Serializable>( "foo_child", m_vec ); unsigned long count = 0; count = node.deserialize_children( "foo_child", m_vec ); VERBOSE << "deser: foo_child count: "<<count<<", and m_vec.size() says: " << m_vec.size() << std::endl; // VERBOSE << "deser: m_foo=["<<m_foo<<"]"<<std::endl; // VERBOSE << "deser: m_bar=["<<m_bar<<"]"<<std::endl; IntStrMap istrmap; unsigned long mcount = node.deserialize_map( "int_to_str_map", istrmap ); if( mcount ) { VERBOSE << "int-to-string map entry count: " << mcount << std::endl; IntStrMap::iterator it = istrmap.begin(), et = istrmap.end(); for( ; it != et; ++it ) VERBOSE << (*it).first << "=["<<(*it).second<<"]"<<std::endl; } DblStrMap dstrmap; mcount = node.deserialize_map( "dbl_to_str_map", dstrmap ); if( mcount ) { VERBOSE << "double-to-string map entry count: " << mcount << std::endl; DblStrMap::iterator it = dstrmap.begin(), et = dstrmap.end(); for( ; it != et; ++it ) VERBOSE << (*it).first << "=["<<(*it).second<<"]"<<std::endl; } return true; } }; }; // namespace fake SERIALIZABLE_REGISTER(s11n::Serializable,fake::FakeRoot); s11n_node *gigo( unsigned int gcount ) { s11n::pointer_list<GIGO> gc; gc.auto_delete( true ); GIGO * g = new GIGO(); gc.push_back( g ); g->garbage(); // CERR << "gigo class name="<< serializable_adapter<GIGO>::class_name(g)<<std::endl; s11n_node * node = new s11n_node( "garbage_nodes" ); // , g.impl_class() ); node->serialize( *g ); for( unsigned int i = 0; i < gcount; i++ ) { g = new GIGO(); gc.push_back( g ); g->garbage(); node->serialize( "gigo_child", *g ); } return node; } void show_version( std::ostream & out ) { out << APP_NAME << " " << APP_VERSION << std::endl; out << "s11n library version: " << std::endl; out << "\tCompiled for: " << S11N_LIBRARY_VERSION << std::endl; out << "\tRunning with: " << s11n::library_version() << std::endl; out << "Serializer interface: " << SERIALIZABLE_TYPE_STRING << std::endl; out << "License: " << PACKAGE_LICENSE << std::endl; #define VERSION_SHORTCUT 0 #if VERSION_SHORTCUT #define LOAD_SERIALIZABLE(ST,FN) root = load_serializable<ST>(FN); \ CERR << "load_serializable<"<<# ST<<">("<<FN<<") = " << std::hex<<root << std::endl; \ delete( root ); s11n::Serializable * root = 0; // fake::FakeRoot * root = 0; std::string infile = "in.s11n"; LOAD_SERIALIZABLE(fake::FakeRoot,infile); LOAD_SERIALIZABLE(s11n::Serializable,"in.s11n"); // fake::FakeRoot root; // s11n_node node; // node.serialize( "fake", root ); // node.serialize( "gigo", GIGO() ); // ParenSerializer serializer; // serializer.serialize( node, std::cerr ); // fake::FakeRoot * clone = s11n_clone( root ); // serializer.basic_serializer::serialize( "boo", *clone, std::cerr ); // WTF must i qualify that??? // delete( clone ); #endif } #define TEST_ANY 0 #if TEST_ANY #include <s11n/any.h> void any_test() { using s11n::any; any a = "12.12"; #define TESTANY(vaL,typE,defaulT) a = vaL; CERR << "any("<<a<<").get<"<<#typE<<">(err=["<<defaulT<<"]) = " << a.get<typE>(defaulT) << std::endl; TESTANY(17.17,double,-1.0); TESTANY(123.90,string,"error"); TESTANY(123.90,double,-1.0); TESTANY(123.90,int,-42); TESTANY("",int,-1); TESTANY("hi!",int,-1); TESTANY("17.12732",double,-1.0); TESTANY("this is a string",std::string,"error"); TESTANY("this is a string",int,-1); } #endif // TEST_ANY typedef std::map<int,std::string> TestType; // CLASS_NAME(fake::FakeRoot); CLASS_NAME(TestType); // CLASS_NAME(alts11n::AltSub); #define SHOW_CLASS_NAME(A) \ CERR << "class_name<"<<# A<<">() == "<<class_name<A>()<<std::endl; \ CERR << "class_name<"<<# A<<">::name() == "<<class_name<A>::name()<<std::endl; int main( int argc, char **argv ) { #if TEST_ANY any_test(); #endif srandom( ::time(NULL) ); // SHOW_CLASS_NAME(fake::FakeRoot); // SHOW_CLASS_NAME(alts11n::AltSub); // SHOW_CLASS_NAME(alts11n::AltSubSub); // SHOW_CLASS_NAME(alts11n::AltSerializable); if( S11N_LIBRARY_VERSION != s11n::library_version() ) { CERR << "Warning: your libs11n does not match the one this was compiled against. " << "This might not work at all!" << std::endl; show_version( std::cerr ); } enum Errors { NoError = 0, ErrorHelp = 0, ErrorVersion = 0, ErrorLoadFailed = 1, ErrorSaveFailed = 2, ErrorDeserializeFailed = 3, ErrorNoFileSpecified = 4, ErrorMultipleCompressors = 5, ErrorCloningFailed = 6 }; s11n::argv_parser & args = s11n::argv_parser::args( argc, argv ); args.set_help( "f filename", "input filename. Same as --file." ); args.set_help( "o filename", "output filename. Filename of - means stdout. Remember to also use -oFORMAT" ); args.set_help( "d", "try to deserialize the input file (useful for testing class loading)." ); args.set_help( "dc", "Requires -d. If -d succeeds, try to s11n_clone() the object." ); args.set_help( "dd", "Requires -d. If -d succeeds, dump the object using the selected -oX format. If -dc is used, the clone is dumped instead." ); args.set_help( "version", "print app and libs11n version info and quit." ); args.set_help( "ot", "output in fun::txt format" ); args.set_help( "ox", "output in fun::xml format" ); args.set_help( "osx", "output in s11n::simplexml format" ); args.set_help( "op", "output in s11n::parens format" ); args.set_help( "oh", "output in s11n::hex format" ); args.set_help( "oc", "output in s11n::compact format" ); args.set_help( "q, quiet", "disable some warnings." ); args.set_help( "v, verbose", "enable some extra output." ); args.set_help( "cldebug", "enable classloader debug output" ); args.set_help( "nodedebug", "enable s11n_node debug output" ); if( "s11n::Serializable" == SERIALIZABLE_TYPE_STRING ) { args.set_help( "sopath path", "Sets the classloader path. Use a :-delimited list." ); } args.set_help( "gigo N", "Number of garbage-in-garbage-out loops to run (for testing/debugging)." ); #if HAVE_ZLIB args.set_help( "z", "enable zlib compression on output." ); #endif #if HAVE_BZLIB args.set_help( "bz", "enable bz2 compression on output." ); #endif if( args.is_set( "version" ) ) { show_version( std::cout ); return ErrorVersion; } if ( args.is_help_set() ) { std::cout << args.dump_help() << std::endl; std::cout << "Only one -oFORMAT option may be used."<< std::endl; #if HAVE_ZLIB && HAVE_BZLIB std::cout << "Only one of -z or -bz can be used." <<std::endl; #endif #if HAVE_ZLIB || HAVE_BZLIB // yeah, i know this shows -bz even when it's not enabled. std::cout << "The -z and -bz options only apply when output is sent to a file (sorry about that)." << std::endl; #endif std::cout << "\nPossible exit codes:\n"; #define ERRUR(C,Desc) std::cout << "\t" << C << " = " << Desc << std::endl; ERRUR(ErrorLoadFailed,"Loading input file failed."); ERRUR(ErrorSaveFailed,"Saving output file failed."); ERRUR(ErrorDeserializeFailed,"Deserialization failed (only with -d flag)."); ERRUR(ErrorNoFileSpecified,"No input file was specified."); // ERRUR(ErrorNoOutputFormat,"No format was specified for the output file."); #if HAVE_ZLIB && HAVE_BZLIB ERRUR(ErrorMultipleCompressors,"Both -bz and -z were specified."); #endif ERRUR(ErrorCloningFailed,"the -dc command failed."); std::cout << "\n[Serializer interface=" << SERIALIZABLE_TYPE_STRING << "]"<<std::endl; std::cout << std::endl; return ErrorHelp; } #if HAVE_ZLIB && HAVE_BZLIB if( args.get_bool( "z", false ) && args.get_bool( "bz", false ) ) { CERR << "Only one of -z and -bz may be specified." << std::endl; return ErrorMultipleCompressors; } #endif // set library-wide compression policy: if( args.get_bool( "z", false ) ) s11n::compression_policy( s11n::GZipCompression ); else if( args.get_bool( "bz", false ) ) s11n::compression_policy( s11n::BZipCompression ); s11n_node::debug_level( args.get_bool( "nodedebug", false ) ? 1 : 0 ); s11n::class_loader_debug_level( args.get_bool( "cldebug", false ) ? 1 : 0 ); // CERR << "debug level: " << s11n_node::debug_level() << std::endl; string infilename = args.get_string( "file", args.get_string( "f", "" ) ); if ( infilename.empty() && ! args.is_set( "gigo" ) ) { // todo: add support for reading stdin. The problem is that // we can't normally load from streams unless we know the input // format in advance. CERR << "You must specify an input file with -f or --file." << endl; return ErrorNoFileSpecified; } std::ostream * os = 0; string ofilename = args.get_string( "o", "" ); /** Output formats enum. */ enum OutModes { NoFormat = 1, TextFormat, XMLFormat, SimpleXMLFormat, ParenFormat, HexFormat, CompactFormat }; int outmode = NoFormat; // get selected output mode: if( args.get_bool( "ox", false ) ) outmode = XMLFormat; else if( args.get_bool( "op", false ) ) outmode = ParenFormat; else if( args.get_bool( "osx", false ) ) outmode = SimpleXMLFormat; else if( args.get_bool( "ot", false ) ) outmode = TextFormat; else if( args.get_bool( "oh", false ) ) outmode = HexFormat; else if( args.get_bool( "oc", false ) ) outmode = CompactFormat; if( NoFormat == outmode ) QUIETLY << "Warning: no output format selected." << std::endl; if( args.is_set( "sopath" ) ) { VERBOSE << "setting DLL path=["<<args.get_string( "sopath" )<<"]"<<std::endl; class_loader<SERIALIZABLE_TYPE>().path(true).path( args.get_string( "sopath" ) ); } s11n_node * root = 0; int gigos = args.get( "gigo", -1 ); if( 0 < gigos ) { QUIETLY << "Running "<<gigos<<" Garbage In, Garbage Out loop"<<(gigos!=1?"s":"") << "..." << std::endl; root = gigo( gigos ); } else { node_loader sl; root = sl.load( infilename ); if( ! root ) { CERR << "node_loader couldn't load '"<<infilename<<"'."<< std::endl; return ErrorLoadFailed; } } if ( !root ) { CERR << "Couldn't load data from " << infilename<<"!" << endl; return ErrorLoadFailed; } bool warnonsavefail = false; // we don't want to warn if a // save to stdout fails, for // reasons i don't quite // remember. // write out the data in the selected format: bool workie = false; std::string failreason = "???"; // select output file: if( ofilename.empty() || "-" == ofilename) { os = &std::cout; } else { os = s11n::get_ostream( ofilename ); // possibly returns a compressor stream. warnonsavefail = true; } basic_serializer * serializer = 0; typedef class_loader<basic_serializer,int> S8rLoader; S8rLoader::register_subtype<FunXMLSerializer>( XMLFormat ); S8rLoader::register_subtype<SimpleXMLSerializer>( SimpleXMLFormat ); S8rLoader::register_subtype<FunTxtSerializer>( TextFormat ); S8rLoader::register_subtype<ParenSerializer>( ParenFormat ); // S8rLoader::register_subtype<HexSerializer>( HexFormat ); S8rLoader::register_subtype<CompactSerializer>( CompactFormat ); serializer = S8rLoader::load_class( outmode ); if( args.get_bool( "d", false ) || args.get_bool( "dd", false ) ) { // deserialize the data? // typedef class_loader<base_serializable_adapter> AdCL; // AdCL::value_type * whoa = AdCL::load_class( //"serializable_adapter<s11n::Serializable>" // std::string( "serializable_adapter<" ) + // std::string( SERIALIZABLE_TYPE_STRING ) + // std::string( ">" ) // ); // CERR << "whoa = " << std::hex<<whoa<<std::endl; // CERR << "impl_class()="<<whoa->impl_class() << std::endl; // CERR <<typeid(*whoa).name() << std::endl; // now what? we still can't get the exact TYPE we need at runtime, because // various Serializables necessarily decend from different bases :( //typedef alts11n::AltSerializable serializable_type; typedef SERIALIZABLE_TYPE serializable_type; // typedef class_loader<base_serializable_adapter> CLA; serializable_type * ser = 0; ser = root->deserialize<serializable_type>(); // ser = new serializable_type(); // bool gogo = root->deserialize( *ser ); // bool gogo = base_serializable_adapter::proxy_deserialize( *ser, *root ); if( ! ser ) { CERR << "deserialization failed. Can't tell you why, though. Try using, -v [--verbose], --cldebug or --nodedebug to get more information." << std::endl; return ErrorDeserializeFailed; } serializable_type * clone = 0; if( args.get_bool( "dc", false ) ) { clone = s11n::s11n_clone( *ser ); CERR << "s11n_clone()"<< (clone ? "worked" : "failed" ) << std::endl; if( ! clone ) return ErrorCloningFailed; } serializable_type * todump = (clone ? clone : ser); if( todump && serializer && args.get_bool( "dd", false ) ) { // dump deserialized object back out. Useful for debuggering. CERR << (clone ? "cloned" : "deser'd")<< " object:" << std::endl; serializer->serialize( "root", *todump, std::cout ); if( ! args.is_set( "o" ) ) outmode = NoFormat; // avoid duplicating the output to stdout } delete( clone ); delete( ser ); } #define DO_OUT(Mode,Cl) \ if( outmode & Mode ) { \ if( ! (workie = s11n_io<Cl>::save( *root, *os ) ) ) { \ failreason = std::string("format (") + std::string(# Mode) + std::string(") save failed.");\ break;\ }} if( outmode == NoFormat ) { workie = true; } else if( serializer ) { workie = serializer->serialize( *root, *os ); if( ! workie ) failreason = "Serializer's serialize() failed!"; } if ( ( os != &std::cout ) && ( os != &std::cerr ) ) { delete( os ); } if( ! workie && warnonsavefail ) { CERR << "saving " << ofilename << " failed! " << failreason << endl; delete( root ); return ErrorSaveFailed; } delete( root ); delete( serializer ); return NoError; }; /** notes: grep class names from SerialTree txt files: grep class= INFILE | cut -d'=' -f2 | sort -u | \ perl -ne \ 'chomp; print "CLASSLOADER\::register_factory( \"".$_."\", FACTORY_CLASS::new_instance );\n";' */ --- NEW FILE: ns.maser.cpp --- /** A demo/proof-of-concept/test application for s11n, demonstrating the use of s11n_node is a poor man's replacement for an XML --> XSLT transformation. */ #include <cassert> #include <iostream> #include <fstream> #include <string> #include <stack> #include <list> #include <sstream> #include <algorithm> #include <memory> // auto_ptr #include <sstream> #include <stdlib.h> // random() #include <time.h> // time() #include <unistd.h> // isatty() #include <s11n/argv_parser.h> #include <s11n/string_util.h> // translate_entities() // #include <iterator> // for use with std::copy() // #include <s11n/s11n_io.h> #include <s11n/s11n-macros.h> // COUT/CERR #include <s11n/s11n_globals.h> // library_version() #include <s11n/s11n_node.h> #include <s11n/node_loader.h> #include <s11n/Serializable.h> #include <s11n/Serializer.h> #if HAVE_CONFIG_H # include "config.h" // S11N_LIBRARY_VERSION, PACKAGE_{VERSION,NAME} #endif #ifndef SERIALIZABLE_TYPE # define SERIALIZABLE_TYPE s11n::Serializable #endif #ifndef SERIALIZABLE_TYPE_STRING # define SERIALIZABLE_TYPE_STRING "s11n::Serializable" #endif using namespace s11n; using namespace s11n; using namespace std; #define APP_VERSION std::string("$Revision: 1.1 $") #define APP_NAME "s11nconvert" #define VERBOSE if( ARGV::args().get_bool( "v", ARGV::args().get_bool( "verbose", false ) ) ) CERR typedef s11n::argv_parser ARGV; #define QUIETLY if( ! ARGV::args().get_bool( "q", ARGV::args().get_bool( "quiet", false ) ) ) CERR // ^^^^ output unless -q is set class MakeSerializer : public basic_serializer { public: MakeSerializer(){}; virtual ~MakeSerializer(){}; virtual s11n_node * deserialize( std::istream & ) { return NULL; } void serialize_command( const s11n_node & node, std::ostream & os ) const { std::string prefix; if( node.get_bool( "at", true ) ) prefix += '@'; if( node.get_bool( "plus", false ) ) prefix += '+'; if( node.get_bool( "minus", false ) ) prefix += '-'; os << "\t" << prefix << node.get( "code", "ERROR" ) << std::endl; } void serialize_rule( const s11n_node & node, std::ostream & os ) const { os << node.get( "name", "ERROR" )<<":"; const s11n_node::child_list_type & childs = node.children(); std::ostringstream depbuff; std::ostringstream cmdbuff; if( node.is_set( "deps" ) ) { depbuff << " " << node.get_string( "deps" ); } else if( 0 == childs.size() ) { os << std::endl; return; } typedef s11n_node::child_list_type::const_iterator IT; IT it = childs.begin(); IT et = childs.end(); const s11n_node * ch = 0; for( ; it != et; ++it ) { ch = (*it); if( "command" == ch->name() ) { serialize_command( *ch, cmdbuff ); continue; } } os << depbuff.str() << "\n"; os << cmdbuff.str(); os << std::endl; } void serialize_comment( const std::string & comment, std::ostream & os, const std::string & prefix ) const { if( comment.empty() ) return; std::string cmt = prefix + comment; static std::map<std::string,std::string> xmap; static bool donethat = false; if( (!donethat) && (donethat=true) ) { xmap["\n"] = std::string("\n") + prefix; } s11n::translate_entities( cmt, xmap ); os << cmt << std::endl; } virtual bool serialize( const s11n_node & node, std::ostream & os ) const { const s11n_node::child_list_type & childs = node.children(); static std::string make; static bool donethat = false; if( (!donethat) && (donethat=true) ) { path_finder bin; const char * p = getenv( "PATH" ); if( p ) bin.path( p ); make = argv_parser::args().get_string( "make" ); if( make.empty() ) make = bin.find( "make" ); if( make.empty() ) make = bin.find( "gmake" ); if( make.empty() ) make = "/path/to/make"; } os << "#!" << make << "\n"; os << "# generated by MakeSerializer\n"; // if( node.is_set( "usercode" ) ) // { // os << node.get_string( "usercode" ) << std::endl; // } typedef s11n_node::child_list_type::const_iterator IT; IT it = childs.begin(); IT et = childs.end(); const s11n_node * ch = 0; std::string name; std::string impl; std::string tmpstr; for( ; it != et; ++it ) { ch = (*it); name = ch->name(); impl = ch->impl_class(); if( "rule" == name ) { this->serialize_rule( *ch, os ); continue; } if( "assign" == name ) { if( ch->get_bool( "append", false ) ) tmpstr = " += "; else tmpstr = " = "; os << ch->get( "key", "ERROR" ) << tmpstr << ch->get( "value", "ERROR" ) << std::endl; continue; } if( "include" == name ) { if( ch->get_bool( "ignore_error", false ) ) os << '-'; os << "include " << ch->get( "path", "ERROR" ) << std::endl; continue; } if( "commenter" == name ) { serialize_comment( ch->get_string( "text" ) , os, ch->get( "prefix", "# " ) ); continue; } if( "formatter" == name ) { if( "as_is" == impl ) { os << ch->get_string( "text" ) << std::endl; continue; } CERR << "warning: unknown formatter: " << name << std::endl; continue; } if( ch->is_set("as_is") ) { os << ch->get( "as_is", "ERROR" ) << std::endl; continue; } CERR << "warning: unknown element: " << name << std::endl; } os << std::endl; return true; } }; void show_version( std::ostream & out ) { out << APP_NAME << " " << APP_VERSION << std::endl; out << "s11n library version: " << std::endl; out << "\tCompiled for: " << S11N_LIBRARY_VERSION << std::endl; out << "\tRunning with: " << s11n::library_version() << std::endl; out << "Serializer interface: " << SERIALIZABLE_TYPE_STRING << std::endl; out << "License: " << PACKAGE_LICENSE << std::endl; } int main( int argc, char **argv ) { srandom( ::time(NULL) ); if( S11N_LIBRARY_VERSION != s11n::library_version() ) { CERR << "Warning: your libs11n does not match the one this was compiled against. " << "This might not work at all!" << std::endl; show_version( std::cerr ); } enum Errors { NoError = 0, ErrorHelp = 0, ErrorVersion = 0, ErrorLoadFailed = 1, ErrorSaveFailed = 2, ErrorDeserializeFailed = 3, ErrorNoFileSpecified = 4 }; s11n::argv_parser & args = s11n::argv_parser::args( argc, argv ); args.set_help( "f filename", "input filename. Same as --file." ); args.set_help( "o filename", "output filename. Filename of - means stdout. Remember to also use -oFORMAT" ); args.set_help( "q, quiet", "disable some warnings." ); args.set_help( "v, verbose", "enable some extra output." ); if( "s11n::Serializable" == SERIALIZABLE_TYPE_STRING ) { args.set_help( "sopath path", "Sets the classloader path. Use a :-delimited list." ); } if( args.is_set( "version" ) ) { show_version( std::cout ); return ErrorVersion; } if ( args.is_help_set() ) { std::cout << args.dump_help() << std::endl; std::cout << "\nPossible exit codes:\n"; #define ERRUR(C,Desc) std::cout << "\t" << C << " = " << Desc << std::endl; ERRUR(ErrorLoadFailed,"Loading input file failed."); ERRUR(ErrorSaveFailed,"Saving output file failed."); ERRUR(ErrorDeserializeFailed,"Deserialization failed (only with -d flag)."); ERRUR(ErrorNoFileSpecified,"No input file was specified."); std::cout << std::endl; return ErrorHelp; } s11n_node::debug_level( args.get_bool( "nodedebug", false ) ? 1 : 0 ); class_loader_debug_level( args.get_bool( "cldebug", false ) ? 1 : 0 ); if( args.is_set( "sopath" ) ) { class_loader<MakeSerializer>().path(true).path( args.get_string( "sopath" ) ); } // CERR << "debug level: " << s11n_node::debug_level() << std::endl; string infilename; if( 2 == argc ) infilename = argv[1]; else infilename = args.get_string( "file", args.get_string( "f", "" ) ); if( infilename.empty() ) { CERR << "You must supply a file name using -f or --file." << std::endl; return ErrorNoFileSpecified; } typedef auto_ptr<s11n_node> NODE; NODE node = NODE( s11n::node_loader::load_node( infilename ) ); if( ! node.get() ) { CERR << "Error loading file '"<<infilename<<"'!"<<std::endl; return ErrorLoadFailed; } MakeSerializer outer; outer.serialize( *node, std::cout ); // std::ostream * os = 0; // string ofilename = args.get_string( "o", "" ); return NoError; }; /** notes: grep class names from SerialTree txt files: grep class= INFILE | cut -d'=' -f2 | sort -u | \ perl -ne \ 'chomp; print "CLASSLOADER\::register_factory( \"".$_."\", FACTORY_CLASS::new_instance );\n";' */ |
From: <sg...@us...> - 2003-11-17 20:53:48
|
Update of /cvsroot/libfunutil/libfunutil/client/s11nconvert In directory sc8-pr-cvs1:/tmp/cvs-serv3098/client/s11nconvert Removed Files: AltSerializable.cpp AltSerializable.h BarClass.cpp BarClass.h FooClass.cpp FooClass.h LoadableClass.h LoadableSubclass.cpp LoadableSubclass.h main.cpp maser.cpp Log Message: renaming for namespace-level refactoring. --- AltSerializable.cpp DELETED --- --- AltSerializable.h DELETED --- --- BarClass.cpp DELETED --- --- BarClass.h DELETED --- --- FooClass.cpp DELETED --- --- FooClass.h DELETED --- --- LoadableClass.h DELETED --- --- LoadableSubclass.cpp DELETED --- --- LoadableSubclass.h DELETED --- --- main.cpp DELETED --- --- maser.cpp DELETED --- |
From: <sg...@us...> - 2003-11-17 20:41:38
|
Update of /cvsroot/libfunutil/libfunutil/client/s11nconvert In directory sc8-pr-cvs1:/tmp/cvs-serv767 Modified Files: AltSerializable.cpp AltSerializable.h BarClass.cpp BarClass.h FooClass.cpp FooClass.h LoadableClass.h Makefile in.paren in.s11n main.cpp maser.cpp test_s11n.sh Log Message: about to reorg Index: AltSerializable.cpp =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/AltSerializable.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- AltSerializable.cpp 17 Oct 2003 09:07:35 -0000 1.2 +++ AltSerializable.cpp 17 Nov 2003 20:41:13 -0000 1.3 @@ -1,15 +1,14 @@ #include "AltSerializable.h" -#include <toolbox/debuggering_macros.h> // COUT/CERR -#include <toolbox/ClassLoader.h> // COUT/CERR -#include <toolbox/SimpleCLParser.h> // COUT/CERR -#include <s11n/serializable_adapter.h> +#include <S11N_NAMESPACEdebuggering_macros.h> // COUT/CERR +#include <S11N_NAMESPACEclass_loader.h> // COUT/CERR +#include <S11N_NAMESPACEargv_parser.h> // COUT/CERR -#define VERBOSE if (toolbox::SimpleCLParser::args().get_bool( "v", false ) ) CERR +#define VERBOSE if (S11N_NAMESPACEargv_parser::args().get_bool( "v", false ) ) CERR /** A test class for demonstrating the ability to use - non-s11n::Serializable types with the framework. + non-S11N_NAMESPACESerializable types with the s11n framework. */ namespace alts11n { AltSerializable::AltSerializable(){}; @@ -71,7 +70,7 @@ return b; } - AltSubSub::AltSubSub() {};// this->set_class("alts11n::AltSubSub"); } + AltSubSub::AltSubSub() {};// this->set_class("altS11N_NAMESPACEAltSubSub"); } AltSubSub::~AltSubSub() { VERBOSE << "~AltSubSub()"<<std::endl; @@ -91,4 +90,4 @@ return b; } }; - // namespace alts11n:: + // namespace altS11N_NAMESPACE Index: AltSerializable.h =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/AltSerializable.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- AltSerializable.h 17 Oct 2003 09:07:36 -0000 1.2 +++ AltSerializable.h 17 Nov 2003 20:41:14 -0000 1.3 @@ -1,8 +1,11 @@ +#ifndef ALTS11N_ALTSERIALIZABLE_H_INCLUDED +#define ALTS11N_ALTSERIALIZABLE_H_INCLUDED 1 + #include <string> -#include <s11n/s11n_node.h> +#include <S11N_NAMESPACEs11n_node.h> /** A test class for demonstrating the ability to use - non-s11n::Serializable types with the framework. + non-S11N_NAMESPACESerializable types with the s11n framework. */ namespace alts11n { class AltSerializable @@ -12,7 +15,7 @@ public: AltSerializable(); virtual ~AltSerializable(); - typedef s11n::s11n_node state; + typedef S11N_NAMESPACEs11n_node state; virtual bool save_state( state & node ) const; virtual bool load_state( const state & node ); void bogo_method(std::string str= ""); @@ -31,9 +34,10 @@ virtual ~AltSubSub(); virtual bool load_state( const AltSerializable::state & node ); }; -} // namespace alts11n:: +} // namespace altS11N_NAMESPACE +#include <S11N_NAMESPACEserializable_adapter.h> /** This creates the required serializable_adapter<AltSerializable> specializations to map the AltSerializable API to @@ -42,9 +46,45 @@ instead of using this macro, and you must do so if your de/serialize() function signatures differ from the defaults. - It also registers the types with the appropriate ClassLoader and - sets up class_name<> specializations. + It also registers the types with the appropriate + S11N_NAMESPACEclass_loader and sets up S11N_NAMESPACEclass_name<> + specializations. */ -SERIALIZABLE_ADAPTER(alts11n::AltSerializable,save_state,load_state); -SERIALIZABLE_REGISTER(alts11n::AltSerializable,alts11n::AltSub); -SERIALIZABLE_REGISTER(alts11n::AltSerializable,alts11n::AltSubSub); +#define EASY_WAY 0 +#if EASY_WAY +SERIALIZABLE_ADAPTER(altS11N_NAMESPACEAltSerializable,save_state,load_state); +#else +CLASSLOADER_REGISTER(altS11N_NAMESPACEAltSerializable,altS11N_NAMESPACEAltSerializable); +CLASS_NAME(altS11N_NAMESPACEAltSerializable); +namespace { + typedef S11N_NAMESPACEs11n_node node_type; + template <> struct serializable_adapter<altS11N_NAMESPACEAltSerializable,node_type> + { + typedef altS11N_NAMESPACEAltSerializable serializable_type; + typedef altS11N_NAMESPACEAltSerializable impl_type; + explicit serializable_adapter(){}; + ~serializable_adapter(){}; + static std::string class_name() + { + return "altS11N_NAMESPACEAltSerializable"; + } + static bool serialize( const serializable_type & ser, node_type &node ) + { + static unsigned long count = 0; // you don't need this! + ++count; + node.impl_class( class_name() ); + return ser.save_state( node ); + } + static bool deserialize( serializable_type & ser, const node_type & node ) + { + static unsigned long count = 0; // you don't need this! + ++count; + return ser.load_state( node ); + } + }; +} +#endif // EASY_WAY +SERIALIZABLE_REGISTER(altS11N_NAMESPACEAltSerializable,altS11N_NAMESPACEAltSub); +SERIALIZABLE_REGISTER(altS11N_NAMESPACEAltSerializable,altS11N_NAMESPACEAltSubSub); + +#endif // ALTS11N_ALTSERIALIZABLE_H_INCLUDED Index: BarClass.cpp =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/BarClass.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- BarClass.cpp 17 Oct 2003 09:07:36 -0000 1.2 +++ BarClass.cpp 17 Nov 2003 20:41:14 -0000 1.3 @@ -1,4 +1,4 @@ -#include <s11n/s11n-macros.h> // COUT/CERR +#include <S11N_NAMESPACEs11n-macros.h> // COUT/CERR #include "BarClass.h" Index: BarClass.h =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/BarClass.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- BarClass.h 17 Oct 2003 09:07:36 -0000 1.2 +++ BarClass.h 17 Nov 2003 20:41:14 -0000 1.3 @@ -1,19 +1,19 @@ -#include <s11n/s11n-macros.h> // COUT/CERR -#include <s11n/s11n_node.h> +#include <S11N_NAMESPACEs11n-macros.h> // COUT/CERR +#include <S11N_NAMESPACEs11n_node.h> using namespace s11n; using namespace std; -// #include <s11n/serializable_adapter.h> -#include <s11n/Serializable.h> +// #include <S11N_NAMESPACEserializable_adapter.h> +#include <S11N_NAMESPACESerializable.h> -struct BarClass: public s11n::Serializable +struct BarClass: public S11N_NAMESPACESerializable { std::string name; int magic_number; BarClass( ); virtual ~ BarClass( ); - virtual bool s7e( s11n::s11n_node & ser ) const; - virtual bool d9e( const s11n::s11n_node & node ); + virtual bool s7e( S11N_NAMESPACEs11n_node & ser ) const; + virtual bool d9e( const S11N_NAMESPACEs11n_node & node ); }; -SERIALIZABLE_REGISTER(s11n::Serializable,BarClass); +SERIALIZABLE_REGISTER(S11N_NAMESPACESerializable,BarClass); Index: FooClass.cpp =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/FooClass.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- FooClass.cpp 17 Oct 2003 09:07:36 -0000 1.2 +++ FooClass.cpp 17 Nov 2003 20:41:14 -0000 1.3 @@ -1,8 +1,8 @@ -#include <s11n/s11n-macros.h> // COUT/CERR -#include <s11n/s11n_globals.h> // registration-related macros -// #include <toolbox/ClassLoader.h> -// #include <toolbox/Instantiator.h> +#include <S11N_NAMESPACEs11n-macros.h> // COUT/CERR +#include <S11N_NAMESPACEs11n_globals.h> // registration-related macros +// #include <S11N_NAMESPACEclass_loader.h> +// #include <S11N_NAMESPACEinstantiator.h> #include "FooClass.h" @@ -24,50 +24,60 @@ } // namespace foo -SERIALIZABLE_REGISTER(s11n::Serializable,foo::BarClass); -SERIALIZABLE_REGISTER(s11n::Serializable,foo::Baz); +SERIALIZABLE_REGISTER(S11N_NAMESPACESerializable,foo::BarClass); +SERIALIZABLE_REGISTER(S11N_NAMESPACESerializable,foo::Baz); namespace { - int DLLLoader_bootstrap() + /** + We use dll_loader_bootstrap() to run code, activated when + static objects are initialized. i.e., before main() or when + a DLL is dlopen()ed. + */ + int dll_loader_bootstrap() { - CERR << "DLLLoader_bootstrap()" << endl; - typedef toolbox::ClassLoader<s11n::Serializable> CL; + CERR << "dll_loader_bootstrap()" << endl; + typedef S11N_NAMESPACEclass_loader<S11N_NAMESPACESerializable> CL; CL::register_subtype<foo::FooClass>("foo::WonderBra"); return 0; } - static const int nomeaning = DLLLoader_bootstrap(); + static const int nomeaning = dll_loader_bootstrap(); } namespace foo { using namespace s11n; using namespace std; - std::string name; FooClass::FooClass() { - this->name = "unnamed FooClass"; - //LOUT << "FooClass()" << endl; - }; + this->name = "unnamed FooClass object"; + for( int i = 0; i < 5; i++ ) + { + this->m_vec.push_back( i ); + } + } FooClass::~FooClass() { - //LIBE_VERBOSE_DTORS(FooClass); - }; + } bool FooClass::s7e( s11n_node & node ) const { if ( !this->Serializable::s7e( node ) ) return false; node.set( "name", this->name ); + node.serialize_list( "vector", this->m_vec ); return true; } bool FooClass::d9e( const s11n_node & node ) { - CERR << node.impl_class()<<"::deserialize()" << std::endl; + this->m_vec.clear(); + CERR <<"deserialize() impl_class="<<node.impl_class() << std::endl; if ( !this->Serializable::d9e( node ) ) return false; this->name = node.get( "name", "<unnamed>" ); + node.deserialize_list( "vector", this->m_vec ); + CERR << "m_vec size = " << m_vec.size() << std::endl; return true; } }; // namespace foo Index: FooClass.h =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/FooClass.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- FooClass.h 17 Oct 2003 09:07:36 -0000 1.2 +++ FooClass.h 17 Nov 2003 20:41:14 -0000 1.3 @@ -1,17 +1,19 @@ #ifndef FOO_H_INCLUDED #define FOO_H_INCLUDED 1 -#include <s11n/s11n_io.h> +#include <S11N_NAMESPACEs11n_node.h> +#include <S11N_NAMESPACESerializable.h> +#include <vector> -#include <s11n/Serializable.h> namespace foo { - struct FooClass : public s11n::Serializable + struct FooClass : public S11N_NAMESPACESerializable { + std::vector<int> m_vec; std::string name; FooClass( ); virtual ~ FooClass( ); - virtual bool s7e( s11n::s11n_node & ser ) const; - virtual bool d9e( const s11n::s11n_node & ser ); + virtual bool s7e( S11N_NAMESPACEs11n_node & ser ) const; + virtual bool d9e( const S11N_NAMESPACEs11n_node & ser ); // private: // void bogosity(){} @@ -19,6 +21,6 @@ }; }; // namespace foo -SERIALIZABLE_REGISTER(s11n::Serializable,foo::FooClass); +SERIALIZABLE_REGISTER(S11N_NAMESPACESerializable,foo::FooClass); #endif // FOO_H_INCLUDED Index: LoadableClass.h =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/LoadableClass.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- LoadableClass.h 14 Oct 2003 03:26:54 -0000 1.1 +++ LoadableClass.h 17 Nov 2003 20:41:14 -0000 1.2 @@ -2,7 +2,7 @@ #define LOADABLECLASS_H_INCLUDED 1 #include <iostream> -#include <s11n/s11n-macros.h> // COUT +#include <S11N_NAMESPACEs11n-macros.h> // COUT struct LoadableClass { Index: Makefile =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- Makefile 17 Oct 2003 09:07:36 -0000 1.2 +++ Makefile 17 Nov 2003 20:41:14 -0000 1.3 @@ -1,14 +1,22 @@ include toc.make +############################## expected from toc.make: +S11N_NAMESPACE ?= s11n +############################## # CPPFLAGS += -DCLASSLOADER_DEBUG=1 + DIST_FILES += $(wildcard in.* *.cpp *.h) + + BIN_PROGRAMS = s11nconvert +# maser # alts11nconvert s11nconvert_bin_OBJECTS = main.o AltSerializable.o +maser_bin_OBJECTS = maser.o alts11nconvert_bin_OBJECTS = main2.o AltSerializable.o main2.cpp: main.cpp @@ -30,10 +38,12 @@ endif main_cpp_CPPFLAGS = -DSERIALIZABLE_TYPE=$(SERIALIZABLE_TYPE) -DSERIALIZABLE_TYPE_STRING=\"$(SERIALIZABLE_TYPE)\" main2_cpp_CPPFLAGS = -DSERIALIZABLE_TYPE=alts11n::AltSerializable -DSERIALIZABLE_TYPE_STRING=\"alts11n::AltSerializable\" +maser_cpp_CPPFLAGS = $(main_cpp_CPPFLAGS) BIN_PROGRAMS_LDADD += $(S11N_CLIENT_LDADD) + include $(toc_makesdir)/BIN_PROGRAMS.make -INSTALL_BINS = $(BIN_PROGRAMS) +INSTALL_BINS = s11nconvert %.o: Makefile @@ -61,7 +71,15 @@ install-BINS: strip-bins -all: BIN_PROGRAMS SHARED_LIBS tip link-bigso +NAMESPACE = $(S11N_NAMESPACE) +NAMESPACE_TOKEN = S11N_NAMESPACE +NAMESPACE_PREFIX = ns. +NAMESPACE_FILTERED_FILES = $(SOURCES) $(HEADERS) +namespace: $(NAMESPACE_FILTERED_FILES) +include $(toc_makesdir)/NAMESPACE.make + + +all: namespace BIN_PROGRAMS SHARED_LIBS tip link-bigso alt: clean ALTS11N=1 ${MAKE} Index: in.paren =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/in.paren,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- in.paren 14 Oct 2003 03:26:54 -0000 1.1 +++ in.paren 17 Nov 2003 20:41:14 -0000 1.2 @@ -6,7 +6,7 @@ ; one-line comment # one-line comment somenode=(NoClass - (a \)\\b) (* <--- testing the backslashing *) (foo bar) (long this is a long property) + (a \(\)\\b) (* <--- testing the backslashing *) (foo bar) (long this is a long property) this_is_empty=() # comment comment fred=(FredClass (key value)) # comment wilma=(WilmaClass (the lovely wife)) Index: in.s11n =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/in.s11n,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- in.s11n 14 Oct 2003 03:26:54 -0000 1.1 +++ in.s11n 17 Nov 2003 20:41:14 -0000 1.2 @@ -1,125 +1,124 @@ #SerialTree 1 +; comment test +# comment test theroot class=fake::FakeRoot { - foo = one - bar = two + foo one + bar two - xml_test this & that is < than the other thing, or maybe > then it? -othertype class=alts11n::AltSerializable -{ - got_milk 1 - sub class=alts11n::AltSub + xmlish this & \\that is < than the other thing, or \\maybe >? + othertype class=alts11n::AltSerializable { - prop val - subsub class=alts11n::AltSubSub - { - prop val - sub class=alts11n::AltSub - { - } - } - } -} - - - int_to_str_map class=s11n::s11n_node { - 0 eeeek! - 1 awwwwk! - 2 gggaaaaaawwwwk! - 3 when you're this stoned, it's hard to be serious. - } - - dbl_to_str_map class=s11n::s11n_node { - 0.0 this is zero - 1.0 this is one - 2.0 this is two - 3.0 this is three - 4.5 this is four-point-five. - } - - foo_child class=foo::FooClass { - fee = fii - fo = fum + got_milk 1 + sub class=alts11n::AltSub + { + prop val + subsub class=alts11n::AltSubSub + { + prop val + sub class=alts11n::AltSub + { + } + } + } } - foo_child class=foo::Baz - { - fee = fii - fo = fum - } - foo_child class=foo::BarClass - { - fee = fii - fo = fum - } - foo_child class=BarClass - { - fee = fii - fo = fum - } + int_to_str_map class=s11n::s11n_node { + 0 eeeek! + 1 awwwwk! + 2 gggaaaaaawwwwk! + 3 whhheeeee! + } - foo_child class=foo::FooClass - { - fee = fii - fo = fum - } + dbl_to_str_map class=s11n::s11n_node { + 0.0 this is zero + 1.0 this is one + 2.0 this is two + 3.0 this is three + 4.5 this is four-point-five. + } - foo_child class=foo::WonderBra - { - fii = fee - fum = fo - } + foo_child class=foo::FooClass { + name Bob + fee fii + fo fum + vector class=s11n::s11n_node { + 1 4 + 2 7 + 3 849 + } + } - foo_child class=BarClass { - meeza_child = true - minibar class=woo::hoo::BarClass - { - myprop 17 - myotherprop "this string here, seen?" - } - not_loadable class=ThisClassIsNotRegistered - { - } + foo_child class=foo::Baz + { + fee fii + fo fum + } + foo_child class=foo::BarClass + { + fee fii + fo fum + } - } + foo_child class=BarClass + { + fee fii + fo fum + } - root class=FooClass - { - foo = one - bar = two - endvar true - } + foo_child class=foo::FooClass + { + fee fii + fo fum + } + foo_child class=foo::WonderBra + { + fii fee + fum fo + } - root_too class=BarClass - { - the_real_node 42.424242424242427848 - quoted_string="this is a quoted string" - unquoted_string this is an unquoted string - unquoted_string2 this is an "unquoted" string; - squoted_string 'this is a \ - single-quoted \ - string' + foo_child class=BarClass { + meeza_child true + minibar class=woo::hoo::BarClass + { + myprop 17 + myotherprop "this string here, seen?" + } + not_loadable class=ThisClassIsNotRegistered + { + } - mstring this is a \ - "multi-line" \ - string + } - key = semi-colon val; - another semi-colon val; + root class=FooClass + { + foo one + bar two + endvar true + } - yet = another \ - test eek \ - multi-line, ohne quote! - SOURCES = foo \ - elib_globals.cpp \ - CommandLiner.cpp + root_too class=BarClass + { + the_real_node 42.424242424242427848 + quoted_string "this is a quoted string" + unquoted_string this is an unquoted string + unquoted_string2 this is an "unquoted" string + squoted_string 'this is a \ + single-quoted \ + string' - HEADERS = Readline.h \ - ShellProcess.h \ - StringList.h + mstring this is a \ + "multi-line" \ + string + SOURCES foo \ +elib_globals.cpp \ + CommandLiner.cpp - } + HEADERS Readline.h \ + ShellProcess.h \ + StringList.h + } } Index: main.cpp =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/main.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- main.cpp 17 Oct 2003 09:07:36 -0000 1.2 +++ main.cpp 17 Nov 2003 20:41:14 -0000 1.3 @@ -11,31 +11,31 @@ #include <time.h> // time() #include <unistd.h> // isatty() -#include <toolbox/SimpleCLParser.h> +#include <S11N_NAMESPACEargv_parser.h> // #include <iterator> // for use with std::copy() -#include <s11n/s11n-macros.h> // COUT/CERR -#include <s11n/s11n_globals.h> // library_version() -#include <s11n/s11n_node.h> +#include <S11N_NAMESPACEs11n-macros.h> // COUT/CERR +#include <S11N_NAMESPACEs11n_globals.h> // library_version() +#include <S11N_NAMESPACEs11n_node.h> -#include <toolbox/eprintf.h> // efstring() -#include <toolbox/PointerList.h> -#include <toolbox/PropertyStore.h> -#include <toolbox/ClassLoader.h> -#include <toolbox/class_name.h> -#include <toolbox/Instantiator.h> +#include <S11N_NAMESPACEeprintf.h> // efstring() +#include <S11N_NAMESPACEpointer_list.h> +#include <S11N_NAMESPACEproperty_store.h> +#include <S11N_NAMESPACEclass_loader.h> +#include <S11N_NAMESPACEclass_name.h> +#include <S11N_NAMESPACEinstantiator.h> -#include <s11n/s11n_io.h> -#include <s11n/serializer_loader.h> -#include <s11n/node_loader.h> +#include <S11N_NAMESPACEs11n_io.h> +#include <S11N_NAMESPACEserializer_loader.h> +#include <S11N_NAMESPACEnode_loader.h> -#include <s11n/Serializable.h> -// #include <s11n/serializable_adapter.h> -// SERIALIZABLE_ADAPTER(s11n::Serializable,s7e,d9e); +#include <S11N_NAMESPACESerializable.h> +// #include <S11N_NAMESPACEserializable_adapter.h> +// SERIALIZABLE_ADAPTER(S11N_NAMESPACESerializable,s7e,d9e); -// #include <s11n/include_from_main.h> +// #include <S11N_NAMESPACEinclude_from_main.h> #if HAVE_CONFIG_H # include "config.h" // S11N_LIBRARY_VERSION, PACKAGE_{VERSION,NAME} @@ -45,24 +45,24 @@ #endif #if HAVE_ZLIB -# include <toolbox/gzstream.h> +# include <S11N_NAMESPACEgzstream.h> #endif #if HAVE_BZLIB -# include <toolbox/bzstream.h> +# include <S11N_NAMESPACEbzstream.h> #endif #ifndef SERIALIZABLE_TYPE -# define SERIALIZABLE_TYPE s11n::Serializable +# define SERIALIZABLE_TYPE S11N_NAMESPACESerializable #endif #ifndef SERIALIZABLE_TYPE_STRING -# define SERIALIZABLE_TYPE_STRING "s11n::Serializable" +# define SERIALIZABLE_TYPE_STRING "S11N_NAMESPACESerializable" #endif #include "AltSerializable.h" -using namespace toolbox; +using namespace s11n; using namespace s11n; using namespace std; @@ -70,9 +70,12 @@ #define APP_VERSION std::string("$Revision$") #define APP_NAME "s11nconvert" -int m_verbose = 0; +#define VERBOSE if( ARGV::args().get_bool( "v", ARGV::args().get_bool( "verbose", false ) ) ) CERR +#define GIGOVERBOSE VERBOSE << "id["<<this->m_id<<"@"<<depth<<"] " -#define VERBOSE if( 0 < m_verbose ) CERR +typedef S11N_NAMESPACEargv_parser ARGV; +#define QUIETLY if( ! ARGV::args().get_bool( "q", ARGV::args().get_bool( "quiet", false ) ) ) CERR +// ^^^^ output unless -q is set std::string random_ascii( unsigned int len ) { @@ -80,7 +83,8 @@ std::string out; for( unsigned int i = 0; i < len; i++ ) { - out += (unsigned char) ( random() % 94 ) + 32; + //out += (unsigned char) ( random() % 78 ) + 46; + out += (unsigned char) ( random() % 25 ) + 65; } return out; } @@ -93,84 +97,93 @@ Garbage In, Garbage Out. For generating lots of junk serialized data quickly. */ -class GIGO : public s11n::Serializable +class GIGO : public S11N_NAMESPACESerializable { public: typedef std::map<int,std::string> IntStrMap; typedef std::map<double,std::string> DblStrMap; - static long inst_count; + static unsigned long inst_count; + static unsigned long total_inst_count; + IntStrMap istrmap; + DblStrMap dstrmap; + typedef S11N_NAMESPACEpointer_list<GIGO> list_type; + typedef std::list<std::string> SL; + SL slist; + list_type childs; + S11N_NAMESPACEproperty_store props; + unsigned long m_id; GIGO() { - static bool donethat = false; - if( (!donethat) && (donethat=true) ) - { - inst_count = 0; - srandom( ::time(NULL) ); - } - VERBOSE << "GIG0() #"<< ++inst_count << std::endl; + m_id = ++total_inst_count; + ++inst_count; + childs.auto_delete( true ); +// GIGOVERBOSE << "GIG0() #"<< inst_count << std::endl; } virtual ~GIGO() { - VERBOSE << "~GIG0() remaining: "<< --inst_count << std::endl; + --inst_count; +// GIGOVERBOSE << "~GIG0() remaining: "<< inst_count << std::endl; } - virtual bool s7e( s11n_node & node ) const + // populates this object with garbage data + void garbage() { - VERBOSE << "GIG0::serialize()" << std::endl; - if( ! this->Serializable::s7e( node ) ) return false; - static int depth = 0; + childs.delete_all(); + istrmap.erase( istrmap.begin(), istrmap.end() ); + dstrmap.erase( dstrmap.begin(), dstrmap.end() ); + slist.erase( slist.begin(), slist.end() ); + this->props.clear_properties(); + static long depth = 0; + ++depth; static const int max_childs = 5; - typedef std::list<std::string> SL; - SL slist; for( int i = 0; i < random() % 5; i++ ) { - slist.push_back( toolbox::efstring( "string list item #", i ) ); + slist.push_back( random_ascii(random()%30 ) ); } - unsigned long count = node.serialize_list( "string_list", slist ); - //VERBOSE << "Serialized string_list: " << count << std::endl; - - IntStrMap istrmap; - DblStrMap dstrmap; int i = 0; + #define INSTR(S) istrmap[i++] = S; dstrmap[i++] = S; for( ; i < random() % 10; ) { INSTR(random_ascii(random()%30)); } - count = node.serialize_map( "int_to_str_map", istrmap ); - //VERBOSE << "Serialized int_to_str_map: " << count; - count = node.serialize_map( "dbl_to_str_map", dstrmap ); - //cerr << " dbl_to_str_map: " << count << std::endl; - int rnd = random() % 10; std::string pname; std::string pval; for( int i = 0; i < rnd; i++ ) { - pname = toolbox::efstring( "property",i ); + pname = S11N_NAMESPACEefstring( "property",i ); pval = random_ascii( random() % 50 ); - //toolbox::efstring( random() % 1000 * 1.17 ); - node.set( pname, pval ); + props.set( pname, pval ); } - GIGO * ch = 0; - toolbox::PointerList<GIGO> childs; // s11n::Serializable - childs.auto_delete( true ); rnd = random() % max_childs - depth; - ++depth; - node.set( "depth", depth ); + GIGO * ch = 0; for( int i = 0; i < rnd; i++ ) { ch = new GIGO(); + ch->garbage(); childs.push_back( ch ); -// ch = new GIGO(); -// node.serialize( "gigo_child", *ch ); -// delete( ch ); } + --depth; + } + + virtual bool s7e( s11n_node & node ) const + { + if( ! this->Serializable::s7e( node ) ) return false; + static long depth = 0; + ++depth; + GIGOVERBOSE << "GIG0::serialize()" << std::endl; + + node.set( "id", m_id ); + node.serialize_list( "string_list", slist ); + node.serialize_map( "int_to_str_map", istrmap ); + node.serialize_map( "dbl_to_str_map", dstrmap ); + node.serialize_properties( this->props ); node.serialize_children( "gigo_child", childs ); --depth; return true; @@ -178,37 +191,46 @@ virtual bool d9e( const s11n_node & node ) { if( ! this->Serializable::d9e( node ) ) return false; + static long depth = 0; + ++depth; - VERBOSE <<"d9e() depth="<<node.get_string("depth")<<std::endl; - typedef std::list<std::string> SL; - SL slist; - unsigned long count = node.deserialize_list( "string_list", slist ); - VERBOSE << "string_list entries: " << count << std::endl; + istrmap.erase( istrmap.begin(), istrmap.end() ); + dstrmap.erase( dstrmap.begin(), dstrmap.end() ); + childs.delete_all(); + this->props.clear_properties(); + slist.erase( slist.begin(), slist.end() ); - IntStrMap istrmap; - DblStrMap dstrmap; -// typedef alts11n::AltSerializable CHSType; // should fail to deserialize. - typedef GIGO CHSType; -// typedef s11n::Serializable CHSType; + this->m_id = node.get<int>( "id", m_id ); - toolbox::PointerList<CHSType> childs; - childs.auto_delete( true ); + unsigned long count = 0; + count = node.deserialize_list( "string_list", slist ); + GIGOVERBOSE << "string_list entries: " << count << std::endl; +// GIGO * g = node.deserialize<GIGO>( "gigo_child" ); +// GIGOVERBOSE << "node.deserialize<GIGO>(...) = " <<std::hex<<g<<std::endl; +// delete( g ); + count = node.deserialize_properties( this->props ); + GIGOVERBOSE << "property count: " << this->props.size() << std::endl; - VERBOSE << "int_to_str_map entries: " << node.deserialize_map( "int_to_str_map", istrmap ) - << " dbl_to_str_map entries: " << node.deserialize_map( "dbl_to_str_map", dstrmap ) - << " gigo_child count: " - << node.deserialize_children( "gigo_child", childs ) -// << node.deserialize_children<CHSType>( "gigo_child", childs ) - << std::endl; + count = node.deserialize_map( "int_to_str_map", istrmap ); + GIGOVERBOSE << "int_to_str_map entries: " << count << std::endl; + + count = node.deserialize_map( "dbl_to_str_map", dstrmap ); + GIGOVERBOSE << " dbl_to_str_map entries: " << count << std::endl; + + count = node.deserialize_children( "gigo_child", childs ); + GIGOVERBOSE << "gigo_child count: " << count + << ", and childs.size() says: " << childs.size() << std::endl; + --depth; return true; } }; -long GIGO::inst_count = 0; +unsigned long GIGO::inst_count = 0; +unsigned long GIGO::total_inst_count = 0; /** Register with the framework: */ -SERIALIZABLE_REGISTER(s11n::Serializable,GIGO); +SERIALIZABLE_REGISTER(S11N_NAMESPACESerializable,GIGO); /** A test namespace. @@ -218,14 +240,14 @@ /** A test class. */ - struct FakeRoot:public Serializable + struct FakeRoot : public S11N_NAMESPACESerializable { std::string m_foo; std::string m_bar; typedef std::map<double,std::string> IntStrMap; typedef std::map<double,std::string> DblStrMap; - typedef PointerList < s11n::Serializable > FakeVec; + typedef pointer_list < S11N_NAMESPACESerializable > FakeVec; //typedef std::vector<BarClass *> FakeVec; FakeVec m_vec; FakeRoot() @@ -246,36 +268,25 @@ return true; } - virtual bool d9e( const s11n_node & ser ) + virtual bool d9e( const s11n_node & node ) { VERBOSE << "FakeRoot::deserialize()" << std::endl; -#define TEST_ALT_IN_FAKE 1 -#if TEST_ALT_IN_FAKE - typedef alts11n::AltSerializable ALT; - ALT * theother = 0; // ser.classloader<ALT>().load( "alts11n::AltSerializable" ); - - theother = ser.deserialize<ALT>("othertype"); + typedef altS11N_NAMESPACEAltSerializable ALT; + ALT * theother = 0; // node.classloader<ALT>().load( "altS11N_NAMESPACEAltSerializable" ); + theother = node.deserialize<ALT>("othertype"); VERBOSE << "theother=="<<std::hex<<theother<<std::endl; - if( theother ) - { - theother->bogo_method(); - delete( theother ); - } -#endif - - //m_vec.deleteAll(); - m_foo = ser.get( "foo", "<not set>" ); - m_bar = ser.get( "bar", "<not set>" ); - m_vec.deleteAll(); - // ser.deserialize_children<s11n::Serializable>( "foo_child", m_vec ); - ser.deserialize_children( "foo_child", m_vec ); - VERBOSE << "deser: foo_child count: " << m_vec.size() << std::endl; + delete( theother ); + m_vec.delete_all(); + // node.deserialize_children<S11N_NAMESPACESerializable>( "foo_child", m_vec ); + unsigned long count = 0; + count = node.deserialize_children( "foo_child", m_vec ); + VERBOSE << "deser: foo_child count: "<<count<<", and m_vec.size() says: " << m_vec.size() << std::endl; // VERBOSE << "deser: m_foo=["<<m_foo<<"]"<<std::endl; // VERBOSE << "deser: m_bar=["<<m_bar<<"]"<<std::endl; IntStrMap istrmap; - unsigned long mcount = ser.deserialize_map( "int_to_str_map", istrmap ); + unsigned long mcount = node.deserialize_map( "int_to_str_map", istrmap ); if( mcount ) { VERBOSE << "int-to-string map entry count: " << mcount << std::endl; @@ -283,7 +294,7 @@ for( ; it != et; ++it ) VERBOSE << (*it).first << "=["<<(*it).second<<"]"<<std::endl; } DblStrMap dstrmap; - mcount = ser.deserialize_map( "dbl_to_str_map", dstrmap ); + mcount = node.deserialize_map( "dbl_to_str_map", dstrmap ); if( mcount ) { VERBOSE << "double-to-string map entry count: " << mcount << std::endl; @@ -298,20 +309,27 @@ }; }; // namespace fake -SERIALIZABLE_REGISTER(s11n::Serializable,fake::FakeRoot); +SERIALIZABLE_REGISTER(S11N_NAMESPACESerializable,fake::FakeRoot); s11n_node *gigo( unsigned int gcount ) { - GIGO g; + S11N_NAMESPACEpointer_list<GIGO> gc; + gc.auto_delete( true ); + GIGO * g = new GIGO(); + gc.push_back( g ); + g->garbage(); // CERR << "gigo class name="<< serializable_adapter<GIGO>::class_name(g)<<std::endl; s11n_node * node = new s11n_node( "garbage_nodes" ); // , g.impl_class() ); - node->serialize( g ); + node->serialize( *g ); for( unsigned int i = 0; i < gcount; i++ ) { - node->serialize( "gigo_child", g ); + g = new GIGO(); + gc.push_back( g ); + g->garbage(); + node->serialize( "gigo_child", *g ); } return node; } @@ -321,29 +339,62 @@ out << APP_NAME << " " << APP_VERSION << std::endl; out << "s11n library version: " << std::endl; out << "\tCompiled for: " << S11N_LIBRARY_VERSION << std::endl; - out << "\tRunning with: " << s11n::library_version() << std::endl; + out << "\tRunning with: " << S11N_NAMESPACElibrary_version() << std::endl; out << "Serializer interface: " << SERIALIZABLE_TYPE_STRING << std::endl; + out << "License: " << PACKAGE_LICENSE << std::endl; - -#define VERSION_SHORTCUT 1 +#define VERSION_SHORTCUT 0 #if VERSION_SHORTCUT - fake::FakeRoot root; - s11n_node node; - node.serialize( "fake", root ); - node.serialize( "gigo", GIGO() ); - ParenSerializer serializer; - serializer.serialize( node, std::cerr ); - fake::FakeRoot * clone = s11n_clone( root ); - serializer.basic_serializer::serialize( "boo", *clone, std::cerr ); // WTF must i qualify that??? - delete( clone ); +#define LOAD_SERIALIZABLE(ST,FN) root = load_serializable<ST>(FN); \ +CERR << "load_serializable<"<<# ST<<">("<<FN<<") = " << std::hex<<root << std::endl; \ +delete( root ); + + S11N_NAMESPACESerializable * root = 0; +// fake::FakeRoot * root = 0; + std::string infile = "in.s11n"; + LOAD_SERIALIZABLE(fake::FakeRoot,infile); + LOAD_SERIALIZABLE(S11N_NAMESPACESerializable,"in.s11n"); + +// fake::FakeRoot root; +// s11n_node node; +// node.serialize( "fake", root ); +// node.serialize( "gigo", GIGO() ); +// ParenSerializer serializer; +// serializer.serialize( node, std::cerr ); +// fake::FakeRoot * clone = s11n_clone( root ); +// serializer.basic_serializer::serialize( "boo", *clone, std::cerr ); // WTF must i qualify that??? +// delete( clone ); #endif } + + +#define TEST_ANY 0 +#if TEST_ANY +#include <S11N_NAMESPACEany.h> +void any_test() +{ + using S11N_NAMESPACEany; + any a = "12.12"; +#define TESTANY(vaL,typE,defaulT) a = vaL; CERR << "any("<<a<<").get<"<<#typE<<">(err=["<<defaulT<<"]) = " << a.get<typE>(defaulT) << std::endl; + TESTANY(17.17,double,-1.0); + TESTANY(123.90,string,"error"); + TESTANY(123.90,double,-1.0); + TESTANY(123.90,int,-42); + TESTANY("",int,-1); + TESTANY("hi!",int,-1); + TESTANY("17.12732",double,-1.0); + TESTANY("this is a string",std::string,"error"); + TESTANY("this is a string",int,-1); + +} +#endif // TEST_ANY + typedef std::map<int,std::string> TestType; // CLASS_NAME(fake::FakeRoot); CLASS_NAME(TestType); -// CLASS_NAME(alts11n::AltSub); +// CLASS_NAME(altS11N_NAMESPACEAltSub); #define SHOW_CLASS_NAME(A) \ CERR << "class_name<"<<# A<<">() == "<<class_name<A>()<<std::endl; \ CERR << "class_name<"<<# A<<">::name() == "<<class_name<A>::name()<<std::endl; @@ -351,12 +402,17 @@ int main( int argc, char **argv ) { +#if TEST_ANY + any_test(); +#endif + + srandom( ::time(NULL) ); // SHOW_CLASS_NAME(fake::FakeRoot); -// SHOW_CLASS_NAME(alts11n::AltSub); -// SHOW_CLASS_NAME(alts11n::AltSubSub); -// SHOW_CLASS_NAME(alts11n::AltSerializable); +// SHOW_CLASS_NAME(altS11N_NAMESPACEAltSub); +// SHOW_CLASS_NAME(altS11N_NAMESPACEAltSubSub); +// SHOW_CLASS_NAME(altS11N_NAMESPACEAltSerializable); - if( S11N_LIBRARY_VERSION != s11n::library_version() ) + if( S11N_LIBRARY_VERSION != S11N_NAMESPACElibrary_version() ) { CERR << "Warning: your libs11n does not match the one this was compiled against. " << "This might not work at all!" << std::endl; @@ -375,54 +431,56 @@ ErrorCloningFailed = 6 }; - toolbox::SimpleCLParser::args( argc, argv ); - toolbox::SimpleCLParser & args = toolbox::SimpleCLParser::args(); + S11N_NAMESPACEargv_parser & args = S11N_NAMESPACEargv_parser::args( argc, argv ); - args.setHelp( "f filename", "input filename. Same as --file." ); - args.setHelp( "o filename", "output filename. Filename of - means stdout." ); + args.set_help( "f filename", "input filename. Same as --file." ); + args.set_help( "o filename", "output filename. Filename of - means stdout. Remember to also use -oFORMAT" ); - args.setHelp( "d", "try to deserialize the input file (useful for testing class loading)." ); - args.setHelp( "dc", "Requires -d. If -d succeeds, try to s11n_clone() the object." ); - args.setHelp( "dd", "Requires -d. If -d succeeds, dump the object using the selected -oX format. If -dc is used, the clone is dumped." ); + args.set_help( "d", "try to deserialize the input file (useful for testing class loading)." ); + args.set_help( "dc", "Requires -d. If -d succeeds, try to s11n_clone() the object." ); + args.set_help( "dd", "Requires -d. If -d succeeds, dump the object using the selected -oX format. If -dc is used, the clone is dumped instead." ); - args.setHelp( "version", "print app and libs11n version info and quit." ); + args.set_help( "version", "print app and libs11n version info and quit." ); - args.setHelp( "ot", "output in fun::txt format" ); - args.setHelp( "ox", "output in fun::xml format" ); - args.setHelp( "osx", "output in s11n::simplexml format" ); - args.setHelp( "op", "output in s11n::parens format" ); - args.setHelp( "oh", "output in s11n::hex format" ); - args.setHelp( "oc", "output in s11n::compact format" ); + args.set_help( "ot", "output in fun::txt format" ); + args.set_help( "ox", "output in fun::xml format" ); + args.set_help( "osx", "output in S11N_NAMESPACEsimplexml format" ); + args.set_help( "op", "output in S11N_NAMESPACEparens format" ); + args.set_help( "oh", "output in S11N_NAMESPACEhex format" ); + args.set_help( "oc", "output in S11N_NAMESPACEcompact format" ); - args.setHelp( "v, verbose", "enable some extra output." ); + args.set_help( "q, quiet", "disable some warnings." ); - args.setHelp( "cldebug", "enable classloader debug output" ); - args.setHelp( "nodedebug", "enable s11n_node debug output" ); + args.set_help( "v, verbose", "enable some extra output." ); + + args.set_help( "cldebug", "enable classloader debug output" ); + args.set_help( "nodedebug", "enable s11n_node debug output" ); - if( "s11n::Serializable" == SERIALIZABLE_TYPE_STRING ) + if( "S11N_NAMESPACESerializable" == SERIALIZABLE_TYPE_STRING ) { - args.setHelp( "sopath path", "Sets the classloader path. Use a :-delimited list." ); + args.set_help( "sopath path", "Sets the classloader path. Use a :-delimited list." ); } - args.setHelp( "gigo N", "Number of garbage-in-garbage-out loops to run (for testing/debugging)." ); + args.set_help( "gigo N", "Number of garbage-in-garbage-out loops to run (for testing/debugging)." ); #if HAVE_ZLIB - args.setHelp( "z", "enable zlib compression on output." ); + args.set_help( "z", "enable zlib compression on output." ); #endif #if HAVE_BZLIB - args.setHelp( "bz", "enable bz2 compression on output." ); + args.set_help( "bz", "enable bz2 compression on output." ); #endif - if( args.isSet( "version" ) ) + if( args.is_set( "version" ) ) { show_version( std::cout ); return ErrorVersion; } - if ( args.isHelpSet() ) + if ( args.is_help_set() ) { - std::cout << "Only one -oX option may be used."<< std::endl; + std::cout << args.dump_help() << std::endl; + std::cout << "Only one -oFORMAT option may be used."<< std::endl; #if HAVE_ZLIB && HAVE_BZLIB std::cout << "Only one of -z or -bz can be used." <<std::endl; #endif @@ -455,22 +513,17 @@ } #endif - if( args.get_bool( "v", args.get_bool("verbose", false ) ) ) - { - m_verbose = 1; - } - // set library-wide compression policy: - if( args.get_bool( "z", false ) ) toolbox::compression_policy( toolbox::GZipCompression ); - else if( args.get_bool( "bz", false ) ) toolbox::compression_policy( toolbox::BZipCompression ); + if( args.get_bool( "z", false ) ) S11N_NAMESPACEcompression_policy( S11N_NAMESPACEGZipCompression ); + else if( args.get_bool( "bz", false ) ) S11N_NAMESPACEcompression_policy( S11N_NAMESPACEBZipCompression ); s11n_node::debug_level( args.get_bool( "nodedebug", false ) ? 1 : 0 ); - toolbox::classloader_debug_level( args.get_bool( "cldebug", false ) ? 1 : 0 ); + S11N_NAMESPACEclass_loader_debug_level( args.get_bool( "cldebug", false ) ? 1 : 0 ); // CERR << "debug level: " << s11n_node::debug_level() << std::endl; string infilename = args.get_string( "file", args.get_string( "f", "" ) ); - if ( infilename.empty() && ! args.isSet( "gigo" ) ) + if ( infilename.empty() && ! args.is_set( "gigo" ) ) { // todo: add support for reading stdin. The problem is that // we can't normally load from streams unless we know the input @@ -483,38 +536,33 @@ string ofilename = args.get_string( "o", "" ); /** - Output formats enum. The values are set up for bitmasking. + Output formats enum. */ - enum OutModes { NoFormat = 0x0000, - TextFormat = 0x0001, - XMLFormat = 0x0002, - SimpleXMLFormat = 0x0004, - ParenFormat = 0x0010, - HexFormat = 0x0020, - CompactFormat = 0x0040 + enum OutModes { NoFormat = 1, + TextFormat, + XMLFormat, + SimpleXMLFormat, + ParenFormat, + HexFormat, + CompactFormat }; - int outmode = NoFormat; // default mode + int outmode = NoFormat; // get selected output mode: - if( args.get_bool( "ox", false ) ) outmode += XMLFormat; - else if( args.get_bool( "op", false ) ) outmode += ParenFormat; - else if( args.get_bool( "osx", false ) ) outmode += SimpleXMLFormat; - else if( args.get_bool( "ot", false ) ) outmode += TextFormat; - else if( args.get_bool( "oh", false ) ) outmode += HexFormat; - else if( args.get_bool( "oc", false ) ) outmode += CompactFormat; - - if( outmode == NoFormat ) - { -// CERR << "No output format specified! Use one of the -oX options." << std::endl; -// return ErrorNoOutputFormat; - } + if( args.get_bool( "ox", false ) ) outmode = XMLFormat; + else if( args.get_bool( "op", false ) ) outmode = ParenFormat; + else if( args.get_bool( "osx", false ) ) outmode = SimpleXMLFormat; + else if( args.get_bool( "ot", false ) ) outmode = TextFormat; + else if( args.get_bool( "oh", false ) ) outmode = HexFormat; + else if( args.get_bool( "oc", false ) ) outmode = CompactFormat; + if( NoFormat == outmode ) QUIETLY << "Warning: no output format selected." << std::endl; - if( args.isSet( "sopath" ) ) + if( args.is_set( "sopath" ) ) { VERBOSE << "setting DLL path=["<<args.get_string( "sopath" )<<"]"<<std::endl; - s11n_node::classloader<s11n::Serializable>().path().path( args.get_string( "sopath" ) ); + class_loader<SERIALIZABLE_TYPE>().path(true).path( args.get_string( "sopath" ) ); } s11n_node * root = 0; @@ -522,7 +570,7 @@ int gigos = args.get( "gigo", -1 ); if( 0 < gigos ) { - CERR << "Running "<<gigos<<" Garbage In, Garbage Out loop"<<(gigos!=1?"s":"") << "..." << std::endl; + QUIETLY << "Running "<<gigos<<" Garbage In, Garbage Out loop"<<(gigos!=1?"s":"") << "..." << std::endl; root = gigo( gigos ); } else @@ -558,19 +606,19 @@ } else { - os = toolbox::get_ostream( ofilename ); // possibly returns a compressor stream. + os = S11N_NAMESPACEget_ostream( ofilename ); // possibly returns a compressor stream. warnonsavefail = true; } basic_serializer * serializer = 0; - typedef ClassLoader<basic_serializer,int> S8rLoader; + typedef class_loader<basic_serializer,int> S8rLoader; S8rLoader::register_subtype<FunXMLSerializer>( XMLFormat ); S8rLoader::register_subtype<SimpleXMLSerializer>( SimpleXMLFormat ); S8rLoader::register_subtype<FunTxtSerializer>( TextFormat ); S8rLoader::register_subtype<ParenSerializer>( ParenFormat ); - S8rLoader::register_subtype<HexSerializer>( HexFormat ); +// S8rLoader::register_subtype<HexSerializer>( HexFormat ); S8rLoader::register_subtype<CompactSerializer>( CompactFormat ); serializer = S8rLoader::load_class( outmode ); @@ -578,8 +626,8 @@ if( args.get_bool( "d", false ) || args.get_bool( "dd", false ) ) { // deserialize the data? -// typedef ClassLoader<base_serializable_adapter> AdCL; -// AdCL::value_type * whoa = AdCL::load_class( //"serializable_adapter<s11n::Serializable>" +// typedef class_loader<base_serializable_adapter> AdCL; +// AdCL::value_type * whoa = AdCL::load_class( //"serializable_adapter<S11N_NAMESPACESerializable>" // std::string( "serializable_adapter<" ) + // std::string( SERIALIZABLE_TYPE_STRING ) + // std::string( ">" ) @@ -590,9 +638,9 @@ // now what? we still can't get the exact TYPE we need at runtime, because // various Serializables necessarily decend from different bases :( - //typedef alts11n::AltSerializable serializable_type; + //typedef altS11N_NAMESPACEAltSerializable serializable_type; typedef SERIALIZABLE_TYPE serializable_type; -// typedef ClassLoader<base_serializable_adapter> CLA; +// typedef class_loader<base_serializable_adapter> CLA; serializable_type * ser = 0; ser = root->deserialize<serializable_type>(); @@ -608,7 +656,7 @@ serializable_type * clone = 0; if( args.get_bool( "dc", false ) ) { - clone = s11n::s11n_clone( *ser ); + clone = S11N_NAMESPACEs11n_clone( *ser ); CERR << "s11n_clone()"<< (clone ? "worked" : "failed" ) << std::endl; if( ! clone ) return ErrorCloningFailed; } @@ -616,8 +664,8 @@ if( todump && serializer && args.get_bool( "dd", false ) ) { // dump deserialized object back out. Useful for debuggering. CERR << (clone ? "cloned" : "deser'd")<< " object:" << std::endl; - serializer->serialize( "root", *todump, std::cerr ); - if( ! args.isSet( "o" ) ) outmode = NoFormat; // avoid duplicating the output to stdout + serializer->serialize( "root", *todump, std::cout ); + if( ! args.is_set( "o" ) ) outmode = NoFormat; // avoid duplicating the output to stdout } delete( clone ); delete( ser ); @@ -667,7 +715,7 @@ grep class= INFILE | cut -d'=' -f2 | sort -u | \ perl -ne \ - 'chomp; print "CLASSLOADER\::register_factory( \"".$_."\", FACTORY_CLASS::newInstance );\n";' + 'chomp; print "CLASSLOADER\::register_factory( \"".$_."\", FACTORY_CLASS::new_instance );\n";' */ Index: maser.cpp =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/maser.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- maser.cpp 17 Nov 2003 20:37:45 -0000 1.1 +++ maser.cpp 17 Nov 2003 20:41:14 -0000 1.2 @@ -17,30 +17,30 @@ #include <time.h> // time() #include <unistd.h> // isatty() -#include <s11n/argv_parser.h> -#include <s11n/string_util.h> // translate_entities() +#include <S11N_NAMESPACEargv_parser.h> +#include <S11N_NAMESPACEstring_util.h> // translate_entities() // #include <iterator> // for use with std::copy() -// #include <s11n/s11n_io.h> -#include <s11n/s11n-macros.h> // COUT/CERR -#include <s11n/s11n_globals.h> // library_version() -#include <s11n/s11n_node.h> +// #include <S11N_NAMESPACEs11n_io.h> +#include <S11N_NAMESPACEs11n-macros.h> // COUT/CERR +#include <S11N_NAMESPACEs11n_globals.h> // library_version() +#include <S11N_NAMESPACEs11n_node.h> -#include <s11n/node_loader.h> +#include <S11N_NAMESPACEnode_loader.h> -#include <s11n/Serializable.h> -#include <s11n/Serializer.h> +#include <S11N_NAMESPACESerializable.h> +#include <S11N_NAMESPACESerializer.h> #if HAVE_CONFIG_H # include "config.h" // S11N_LIBRARY_VERSION, PACKAGE_{VERSION,NAME} #endif #ifndef SERIALIZABLE_TYPE -# define SERIALIZABLE_TYPE s11n::Serializable +# define SERIALIZABLE_TYPE S11N_NAMESPACESerializable #endif #ifndef SERIALIZABLE_TYPE_STRING -# define SERIALIZABLE_TYPE_STRING "s11n::Serializable" +# define SERIALIZABLE_TYPE_STRING "S11N_NAMESPACESerializable" #endif @@ -54,7 +54,7 @@ #define VERBOSE if( ARGV::args().get_bool( "v", ARGV::args().get_bool( "verbose", false ) ) ) CERR -typedef s11n::argv_parser ARGV; +typedef S11N_NAMESPACEargv_parser ARGV; #define QUIETLY if( ! ARGV::args().get_bool( "q", ARGV::args().get_bool( "quiet", false ) ) ) CERR // ^^^^ output unless -q is set @@ -134,7 +134,7 @@ xmap["\n"] = std::string("\n") + prefix; } - s11n::translate_entities( cmt, xmap ); + S11N_NAMESPACEtranslate_entities( cmt, xmap ); os << cmt << std::endl; } @@ -232,7 +232,7 @@ out << APP_NAME << " " << APP_VERSION << std::endl; out << "s11n library version: " << std::endl; out << "\tCompiled for: " << S11N_LIBRARY_VERSION << std::endl; - out << "\tRunning with: " << s11n::library_version() << std::endl; + out << "\tRunning with: " << S11N_NAMESPACElibrary_version() << std::endl; out << "Serializer interface: " << SERIALIZABLE_TYPE_STRING << std::endl; out << "License: " << PACKAGE_LICENSE << std::endl; } @@ -244,7 +244,7 @@ srandom( ::time(NULL) ); - if( S11N_LIBRARY_VERSION != s11n::library_version() ) + if( S11N_LIBRARY_VERSION != S11N_NAMESPACElibrary_version() ) { CERR << "Warning: your libs11n does not match the one this was compiled against. " << "This might not work at all!" << std::endl; @@ -261,7 +261,7 @@ ErrorNoFileSpecified = 4 }; - s11n::argv_parser & args = s11n::argv_parser::args( argc, argv ); + S11N_NAMESPACEargv_parser & args = S11N_NAMESPACEargv_parser::args( argc, argv ); args.set_help( "f filename", "input filename. Same as --file." ); args.set_help( "o filename", "output filename. Filename of - means stdout. Remember to also use -oFORMAT" ); @@ -269,7 +269,7 @@ args.set_help( "q, quiet", "disable some warnings." ); args.set_help( "v, verbose", "enable some extra output." ); - if( "s11n::Serializable" == SERIALIZABLE_TYPE_STRING ) + if( "S11N_NAMESPACESerializable" == SERIALIZABLE_TYPE_STRING ) { args.set_help( "sopath path", "Sets the classloader path. Use a :-delimited list." ); } @@ -315,7 +315,7 @@ } typedef auto_ptr<s11n_node> NODE; - NODE node = NODE( s11n::node_loader::load_node( infilename ) ); + NODE node = NODE( S11N_NAMESPACEnode_loader::load_node( infilename ) ); if( ! node.get() ) { CERR << "Error loading file '"<<infilename<<"'!"<<std::endl; Index: test_s11n.sh =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/client/s11nconvert/test_s11n.sh,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- test_s11n.sh 14 Oct 2003 03:26:54 -0000 1.1 +++ test_s11n.sh 17 Nov 2003 20:41:14 -0000 1.2 @@ -1,7 +1,7 @@ #!/bin/bash infile=${1} converter=./s11nconvert -formats="x t p sx h c" +formats="x t p sx c" test x$infile = x && { echo "Usage: $0 input file" exit 1 |
From: <sg...@us...> - 2003-11-17 20:38:08
|
Update of /cvsroot/libfunutil/libfunutil/client/s11nconvert In directory sc8-pr-cvs1:/tmp/cvs-serv32552/client/s11nconvert Added Files: in.maser maser.cpp Log Message: egg --- NEW FILE: in.maser --- <!DOCTYPE SerialTree> <build_rules class="NONE"> <formatter class="as_is"> <text>### this is as-is data.</text> </formatter> <assign class="NONE"> <key>foo</key> <value>var</value> <append>y</append> </assign> <commenter class="NONE"> <prefix># </prefix> <text>this is a comment</text> </commenter> <rule class="NONE"> <deps>all</deps> <name>default</name> </rule> <rule class="NONE"> <name>all</name> <command class="NONE"> <minus>true</minus> <code>echo hello world</code> </command> <command class="NONE"> <plus>true</plus> <code>echo ${MAKE}</code> </command> <command class="NONE"> <at>false</at> <code>$(CXX) --help</code> </command> </rule> <include class="NONE"> <ignore_error>y</ignore_error> <path>/path/to/file</path> </include> <rule class="NONE"> <name>no-op</name> </rule> </build_rules> --- NEW FILE: maser.cpp --- /** A demo/proof-of-concept/test application for s11n, demonstrating the use of s11n_node is a poor man's replacement for an XML --> XSLT transformation. */ #include <cassert> #include <iostream> #include <fstream> #include <string> #include <stack> #include <list> #include <sstream> #include <algorithm> #include <memory> // auto_ptr #include <sstream> #include <stdlib.h> // random() #include <time.h> // time() #include <unistd.h> // isatty() #include <s11n/argv_parser.h> #include <s11n/string_util.h> // translate_entities() // #include <iterator> // for use with std::copy() // #include <s11n/s11n_io.h> #include <s11n/s11n-macros.h> // COUT/CERR #include <s11n/s11n_globals.h> // library_version() #include <s11n/s11n_node.h> #include <s11n/node_loader.h> #include <s11n/Serializable.h> #include <s11n/Serializer.h> #if HAVE_CONFIG_H # include "config.h" // S11N_LIBRARY_VERSION, PACKAGE_{VERSION,NAME} #endif #ifndef SERIALIZABLE_TYPE # define SERIALIZABLE_TYPE s11n::Serializable #endif #ifndef SERIALIZABLE_TYPE_STRING # define SERIALIZABLE_TYPE_STRING "s11n::Serializable" #endif using namespace s11n; using namespace s11n; using namespace std; #define APP_VERSION std::string("$Revision: 1.1 $") #define APP_NAME "s11nconvert" #define VERBOSE if( ARGV::args().get_bool( "v", ARGV::args().get_bool( "verbose", false ) ) ) CERR typedef s11n::argv_parser ARGV; #define QUIETLY if( ! ARGV::args().get_bool( "q", ARGV::args().get_bool( "quiet", false ) ) ) CERR // ^^^^ output unless -q is set class MakeSerializer : public basic_serializer { public: MakeSerializer(){}; virtual ~MakeSerializer(){}; virtual s11n_node * deserialize( std::istream & ) { return NULL; } void serialize_command( const s11n_node & node, std::ostream & os ) const { std::string prefix; if( node.get_bool( "at", true ) ) prefix += '@'; if( node.get_bool( "plus", false ) ) prefix += '+'; if( node.get_bool( "minus", false ) ) prefix += '-'; os << "\t" << prefix << node.get( "code", "ERROR" ) << std::endl; } void serialize_rule( const s11n_node & node, std::ostream & os ) const { os << node.get( "name", "ERROR" )<<":"; const s11n_node::child_list_type & childs = node.children(); std::ostringstream depbuff; std::ostringstream cmdbuff; if( node.is_set( "deps" ) ) { depbuff << " " << node.get_string( "deps" ); } else if( 0 == childs.size() ) { os << std::endl; return; } typedef s11n_node::child_list_type::const_iterator IT; IT it = childs.begin(); IT et = childs.end(); const s11n_node * ch = 0; for( ; it != et; ++it ) { ch = (*it); if( "command" == ch->name() ) { serialize_command( *ch, cmdbuff ); continue; } } os << depbuff.str() << "\n"; os << cmdbuff.str(); os << std::endl; } void serialize_comment( const std::string & comment, std::ostream & os, const std::string & prefix ) const { if( comment.empty() ) return; std::string cmt = prefix + comment; static std::map<std::string,std::string> xmap; static bool donethat = false; if( (!donethat) && (donethat=true) ) { xmap["\n"] = std::string("\n") + prefix; } s11n::translate_entities( cmt, xmap ); os << cmt << std::endl; } virtual bool serialize( const s11n_node & node, std::ostream & os ) const { const s11n_node::child_list_type & childs = node.children(); static std::string make; static bool donethat = false; if( (!donethat) && (donethat=true) ) { path_finder bin; const char * p = getenv( "PATH" ); if( p ) bin.path( p ); make = argv_parser::args().get_string( "make" ); if( make.empty() ) make = bin.find( "make" ); if( make.empty() ) make = bin.find( "gmake" ); if( make.empty() ) make = "/path/to/make"; } os << "#!" << make << "\n"; os << "# generated by MakeSerializer\n"; // if( node.is_set( "usercode" ) ) // { // os << node.get_string( "usercode" ) << std::endl; // } typedef s11n_node::child_list_type::const_iterator IT; IT it = childs.begin(); IT et = childs.end(); const s11n_node * ch = 0; std::string name; std::string impl; std::string tmpstr; for( ; it != et; ++it ) { ch = (*it); name = ch->name(); impl = ch->impl_class(); if( "rule" == name ) { this->serialize_rule( *ch, os ); continue; } if( "assign" == name ) { if( ch->get_bool( "append", false ) ) tmpstr = " += "; else tmpstr = " = "; os << ch->get( "key", "ERROR" ) << tmpstr << ch->get( "value", "ERROR" ) << std::endl; continue; } if( "include" == name ) { if( ch->get_bool( "ignore_error", false ) ) os << '-'; os << "include " << ch->get( "path", "ERROR" ) << std::endl; continue; } if( "commenter" == name ) { serialize_comment( ch->get_string( "text" ) , os, ch->get( "prefix", "# " ) ); continue; } if( "formatter" == name ) { if( "as_is" == impl ) { os << ch->get_string( "text" ) << std::endl; continue; } CERR << "warning: unknown formatter: " << name << std::endl; continue; } if( ch->is_set("as_is") ) { os << ch->get( "as_is", "ERROR" ) << std::endl; continue; } CERR << "warning: unknown element: " << name << std::endl; } os << std::endl; return true; } }; void show_version( std::ostream & out ) { out << APP_NAME << " " << APP_VERSION << std::endl; out << "s11n library version: " << std::endl; out << "\tCompiled for: " << S11N_LIBRARY_VERSION << std::endl; out << "\tRunning with: " << s11n::library_version() << std::endl; out << "Serializer interface: " << SERIALIZABLE_TYPE_STRING << std::endl; out << "License: " << PACKAGE_LICENSE << std::endl; } int main( int argc, char **argv ) { srandom( ::time(NULL) ); if( S11N_LIBRARY_VERSION != s11n::library_version() ) { CERR << "Warning: your libs11n does not match the one this was compiled against. " << "This might not work at all!" << std::endl; show_version( std::cerr ); } enum Errors { NoError = 0, ErrorHelp = 0, ErrorVersion = 0, ErrorLoadFailed = 1, ErrorSaveFailed = 2, ErrorDeserializeFailed = 3, ErrorNoFileSpecified = 4 }; s11n::argv_parser & args = s11n::argv_parser::args( argc, argv ); args.set_help( "f filename", "input filename. Same as --file." ); args.set_help( "o filename", "output filename. Filename of - means stdout. Remember to also use -oFORMAT" ); args.set_help( "q, quiet", "disable some warnings." ); args.set_help( "v, verbose", "enable some extra output." ); if( "s11n::Serializable" == SERIALIZABLE_TYPE_STRING ) { args.set_help( "sopath path", "Sets the classloader path. Use a :-delimited list." ); } if( args.is_set( "version" ) ) { show_version( std::cout ); return ErrorVersion; } if ( args.is_help_set() ) { std::cout << args.dump_help() << std::endl; std::cout << "\nPossible exit codes:\n"; #define ERRUR(C,Desc) std::cout << "\t" << C << " = " << Desc << std::endl; ERRUR(ErrorLoadFailed,"Loading input file failed."); ERRUR(ErrorSaveFailed,"Saving output file failed."); ERRUR(ErrorDeserializeFailed,"Deserialization failed (only with -d flag)."); ERRUR(ErrorNoFileSpecified,"No input file was specified."); std::cout << std::endl; return ErrorHelp; } s11n_node::debug_level( args.get_bool( "nodedebug", false ) ? 1 : 0 ); class_loader_debug_level( args.get_bool( "cldebug", false ) ? 1 : 0 ); if( args.is_set( "sopath" ) ) { class_loader<MakeSerializer>().path(true).path( args.get_string( "sopath" ) ); } // CERR << "debug level: " << s11n_node::debug_level() << std::endl; string infilename; if( 2 == argc ) infilename = argv[1]; else infilename = args.get_string( "file", args.get_string( "f", "" ) ); if( infilename.empty() ) { CERR << "You must supply a file name using -f or --file." << std::endl; return ErrorNoFileSpecified; } typedef auto_ptr<s11n_node> NODE; NODE node = NODE( s11n::node_loader::load_node( infilename ) ); if( ! node.get() ) { CERR << "Error loading file '"<<infilename<<"'!"<<std::endl; return ErrorLoadFailed; } MakeSerializer outer; outer.serialize( *node, std::cout ); // std::ostream * os = 0; // string ofilename = args.get_string( "o", "" ); return NoError; }; /** notes: grep class names from SerialTree txt files: grep class= INFILE | cut -d'=' -f2 | sort -u | \ perl -ne \ 'chomp; print "CLASSLOADER\::register_factory( \"".$_."\", FACTORY_CLASS::new_instance );\n";' */ |
From: <sg...@us...> - 2003-11-17 20:31:03
|
Update of /cvsroot/libfunutil/libfunutil/lib/s11n/parsers In directory sc8-pr-cvs1:/tmp/cvs-serv29633/lib/s11n/parsers Modified Files: Makefile Log Message: namespace-related refactoring Index: Makefile =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/lib/s11n/parsers/Makefile,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- Makefile 14 Oct 2003 03:38:14 -0000 1.3 +++ Makefile 17 Nov 2003 20:30:37 -0000 1.4 @@ -1,16 +1,37 @@ include toc.make -SOURCES = \ - flex_lexers.cpp +S11N_NAMESPACE ?= s11n + +NS_SOURCES = \ + ns.flex_lexers.cpp +NS_HEADERS = \ + ns.flex_lexers.h +# Be careful with SOURCES/HEADERS, lest they be cleaned up when you don't +# want them to be. Simplest is to put everything into NS_{HEADERS/SOURCES} and expect +# them to be filtered by sed. +SOURCES = \ + $(patsubst ns.%,%,$(NS_SOURCES)) HEADERS = \ - flex_lexers.h + $(patsubst ns.%,%,$(NS_HEADERS)) +CLEAN_FILES += $(SOURCES) $(HEADERS) -INSTALL_PACKAGE_HEADERS_DEST = $(prefix)/include/s11n + +INSTALL_PACKAGE_HEADERS_DEST = $(prefix)/include/$(S11N_NAMESPACE) INSTALL_PACKAGE_HEADERS = $(HEADERS) -FLEXES = compact hex paren funtxt funxml select_lexer simplexml +FLEXES = compact paren funtxt funxml select_lexer simplexml +CLEAN_FILES += $(addsuffix .flex.at,$(FLEXES)) +# hex SOURCES_FLEX = $(addsuffix .flex.cpp,$(FLEXES)) +NAMESPACE = $(S11N_NAMESPACE) +NAMESPACE_TOKEN = S11N_NAMESPACE +NAMESPACE_PREFIX = ns. +NAMESPACE_FILTERED_FILES = $(SOURCES) $(HEADERS) $(addsuffix .flex.at,$(FLEXES)) +namespace: $(NAMESPACE_FILTERED_FILES) +include $(toc_makesdir)/NAMESPACE.make + + FLEXES_ARGS = -p -+ funtxt_FLEXES_ARGS = -B -Psertxt funxml_FLEXES_ARGS = -B -Pserxml @@ -68,17 +89,18 @@ OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES) $(SOURCES_FLEX)) +INSTALL_PACKAGE_HEADERS_DEST = $(prefix)/include/$(S11N_NAMESPACE) INSTALL_PACKAGE_HEADERS = $(HEADERS) -DIST_FILES += $(SOURCES) $(HEADERS) $(COMMON_FLEX_DEFS) \ - $(addsuffix .flex.at,$(FLEXES)) +DIST_FILES += $(wildcard ns.*) \ + $(COMMON_FLEX_DEFS) SYMLINK_HEADERS = $(INSTALL_PACKAGE_HEADERS) -SYMLINK_HEADERS_DEST = $(top_srcdir)/include/s11n +SYMLINK_HEADERS_DEST = $(top_srcdir)/include/$(S11N_NAMESPACE) include $(toc_makesdir)/symlink_headers.make -all: flexes symlink-headers $(OBJECTS) +all: namespace flexes symlink-headers $(OBJECTS) COMMONS_DIR = $(ELIB_LIBDIR)/common @@ -117,5 +139,3 @@ CLEAN_FILES += $(bins) bins: $(bins) CLEAN_FILES += *.o - - |
From: <sg...@us...> - 2003-11-17 20:30:37
|
Update of /cvsroot/libfunutil/libfunutil/lib/s11n/parsers In directory sc8-pr-cvs1:/tmp/cvs-serv29568/lib/s11n/parsers Added Files: in.compact in.hex in.paren Log Message: egg --- NEW FILE: in.compact --- 51191001 f10008somenode0007NoClasse10001a0003)\be10003foo0003bare10004long0017this is a long propertyf10004fred0009FredClasse10003key0005valuef0 f10005wilma000aWilmaClasse10003the000blovely wifef0 f10005betty000aBettyClasse10005value0019the apple of Barney's eyef0 f10004deep0003Foof10006deeper0003Fooe10008how_deep000creally deep!f1000aand_deeper0004Ouchf0 f0 f0 f0 51191000 --- NEW FILE: in.hex --- 51190001 00110008736f6d656e6f646500074e6f436c61737300210001610003295c6200210003666f6f0003626172002100046c6f6e670017746869732069732061206c6f6e672070726f70657274790011000466726564000946726564436c617373002100036b6579000576616c75650010 0011000577696c6d61000a57696c6d61436c61737300210003746865000b6c6f76656c7920776966650010 001100056265747479000a4265747479436c6173730021000576616c75650019746865206170706c65206f66204261726e65792773206579650010 00110004646565700003466f6f001100066465657065720003466f6f00210008686f775f64656570000c7265616c6c792064656570210011000a616e645f64656570657200044f7563680010 0010 0010 0010 51190000 --- NEW FILE: in.paren --- #the lots-of-parens format somenode=(NoClass (a \)\\b) (foo bar) (long this is a long property) this_is_empty=() fred=(FredClass (key value)) # comment wilma=(WilmaClass (the lovely wife)) betty=(BettyClass (value the apple of Barney's eye)) deep=(Foo deeper=(Foo (how_deep really deep!) and_deeper=(Ouch)) ) |
From: <sg...@us...> - 2003-11-17 20:30:15
|
Update of /cvsroot/libfunutil/libfunutil/lib/s11n/parsers In directory sc8-pr-cvs1:/tmp/cvs-serv29404/lib/s11n/parsers Added Files: ns.compact.flex.at ns.flex_lexers.cpp ns.flex_lexers.h ns.funtxt.flex.at ns.funxml.flex.at ns.hex.flex.at ns.paren.flex.at ns.select_lexer.flex.at ns.simplexml.flex.at Log Message: egg --- NEW FILE: ns.compact.flex.at --- %option c++ %{ // // LICENSE: Public Domain // Author: stephan - st...@s1... // #define YY_SKIP_YYWRAP 1 int yywrap() { return 1; } // #include <stdio.h> #include <cassert> #include <iostream> #include <string> #include <deque> #include <S11N_NAMESPACE/s11n-macros.h> // COUT/CERR #define PCERR CERR << "compact.flex error:" // #include <S11N_NAMESPACE/string_util.h> // trim_string() // #include <S11N_NAMESPACE/property_store.h> // #include <S11N_NAMESPACE/class_loader.h> // #include <S11N_NAMESPACE/instantiator.h> // #include <S11N_NAMESPACE/key_value_parser.h> #include <S11N_NAMESPACE/node_builder.h> #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/string_util.h> // hex2int() using std::cin; using std::cerr; using std::cout; using std::endl; /** Basic grammar spec: {NODE_OPEN}{NAME_SIZE}{NODE_NAME}<class_name_size>{CLASSNAME} ({PROP_OPEN}<key_size><key><value_size><value>)* (sub-nodes)* {NODE_CLOSE} See the lex source for the meanings of the {TOKENS} named above. */ namespace { unsigned long node_depth = 0; unsigned int loops = 0; std::string word; std::string propname; std::string propval; std::string nodename; std::string nodeclass; bool in_prop; unsigned int decval = 0; unsigned int lcv = 0; S11N_NAMESPACE::node_builder * serbuilder = 0; } namespace S11N_NAMESPACE { FlexLexer * CompactTreeBuilder::lexer() { FlexLexer * fp = 0; fp = this->FlexTreeBuilder::lexer(); if( fp ) return fp; // else first-time setup: this->reset(); return this->FlexTreeBuilder::lexer(); } void CompactTreeBuilder::reset() { this->FlexTreeBuilder::reset(); FlexLexer * foo = new compactFlexLexer(); this->FlexTreeBuilder::lexer( foo ); serbuilder = this->builder(); node_depth = 0; } } // namespace S11N_NAMESPACE namespace { char inchar; } #define READWORD(SZ) word = ""; \ for( int i = 0; i < SZ; i++ )\ {\ inchar = yyinput(); \ if( 0 == inchar ) {word=""; PCERR << "Reached EOF during READWORD!" << endl; return 0;} \ word += inchar; \ };\ decval = S11N_NAMESPACE::hex2int(word) // if( 0 == decval ) { PCERR << "Error reading word of size " << SZ<<". Maybe reached end of input?" << endl; return 0; } %} HEX_DIGIT ([a-fA-F0-9]) WORD4 ({HEX_DIGIT}{4}) // maintenance note: these hex codes must be kept in sync with those from HexSerializer's enum NODE_OPEN f1 NODE_CLOSE f0 PROP_OPEN e1 COOKIE 51191001 DATA_END 51191000 %% {COOKIE} {;} {DATA_END} { return 0; } [ \t\n] {;} {NODE_OPEN} { //COUT << "Opening node." << std::endl; READWORD(2); // read node name size nodename = ""; loops = decval; for( lcv = 0; lcv < loops; lcv++ ) { //READWORD(2); //cout << "["<<word<<"/"<<decval<<"]"; nodename += yyinput(); // (unsigned char) decval; } //cout<< endl; READWORD(2); // get class name size nodeclass = ""; loops = decval; for( lcv = 0; lcv < loops; lcv++ ) { // read class name nodeclass += (unsigned char) yyinput(); // decval; } //COUT << "nodename=["<<nodename<<"]"<<"["<<nodeclass<<"]"<<endl; if( ! serbuilder->open_node( nodeclass, nodename ) ) { PCERR<< "open_node("<<nodeclass<<","<<nodename<<") failed." << endl; return 0; } nodename = nodeclass = ""; } {NODE_CLOSE} { //COUT << "Closing node." << std::endl; serbuilder->close_node(); if( 0 == serbuilder->node_depth() ) { // stop once we close the first top-level node. return 0; } continue; } {PROP_OPEN} { //COUTL( "Opening property" ); propname = ""; READWORD(2); // prop name size loops = decval; for( lcv = 0; lcv < loops; lcv++ ) { // read property name propname += (unsigned char) yyinput(); // decval; } READWORD(8); // get value size propval = ""; loops = decval; for( lcv = 0; lcv < loops; lcv++ ) { // read property's value propval += (unsigned char) yyinput(); // decval; } serbuilder->add_property( propname, propval ); propval = propname = ""; } [.] { PCERR << "unexpected token: " << YYText() <<std::endl; return 0; } %% #if COMPACT_DO_MAIN #include <S11N_NAMESPACE/s11n_io.h> // HexSerializer // #include <S11N_NAMESPACE/FlexShell.h> // #include <S11N_NAMESPACE/ELib.h> using namespace S11N_NAMESPACE; int main( int argc, char ** argv ) { S11N_NAMESPACE::CompactTreeBuilder bob; FlexLexer * lexer = bob.lexer(); // FlexLexer * lexer = new compactFlexLexer(); while( 0 != (lexer->yylex() ) ); if( bob.root_node() ) { S11N_NAMESPACE::ParenSerializer ser; ser.serialize( *(bob.root_node()), std::cout ); // S11N_NAMESPACE::CompactSerializer compact; // compact.serialize( *(bob.root_node()), std::cout ); } return 0; } #endif --- NEW FILE: ns.flex_lexers.cpp --- // Author: stephan beal <st...@s1...> // License: Public Domain #include "flex_lexers.h" #include <cassert> #include <S11N_NAMESPACE/s11n-macros.h> // COUT namespace S11N_NAMESPACE { FlexTreeBuilder::FlexTreeBuilder():m_lexer( 0 ), m_lexer_inited( false ), m_builder( 0 ) { } FlexTreeBuilder::~FlexTreeBuilder() { this->cleanup(); } FlexLexer *FlexTreeBuilder::lexer() { return this->m_lexer; } void FlexTreeBuilder::lexer( FlexLexer * newlexer ) { delete( this->m_lexer ); this->m_lexer = newlexer; } s11n_node * FlexTreeBuilder::root_node() { return this->m_builder ? this->m_builder->root_node() : NULL; } int FlexTreeBuilder::lexer_loop() { FlexLexer *l = this->lexer(); int ret; while ( 0 != ( ret = l->yylex() ) ) { } return ret; } void FlexTreeBuilder::reset() { delete( m_builder ); m_builder = new node_builder(); m_lexer_inited = true; } void FlexTreeBuilder::cleanup() { delete( m_builder ); m_builder = 0; m_lexer_inited = false; delete( this->m_lexer ); this->m_lexer = 0; } node_builder * FlexTreeBuilder::builder() { if ( !m_lexer_inited ) this->reset(); return m_builder; } bool FlexTreeBuilder::load( std::istream & in ) { if ( ! in.good() ) return false; FlexLexer *fl = this->lexer(); fl->switch_streams( &in ); int ret; ret = this->lexer_loop(); if ( 0 != ret ) { this->reset(); } return ( 0 == ret ); } } // namespace S11N_NAMESPACE --- NEW FILE: ns.flex_lexers.h --- #ifndef S11N_NAMESPACE_FLEX_LEXERS_H_INCLUDED #define S11N_NAMESPACE_FLEX_LEXERS_H_INCLUDED 1 // Author: stephan beal <st...@s1...> // License: Public Domain #include <string> #include <iostream> #ifndef FLEX_SCANNER #include <FlexLexer.h> #endif // #include <S11N_NAMESPACE/S11n.h> #include <S11N_NAMESPACE/node_builder.h> #define LEXER_LOUD 1 #if LEXER_LOUD # include <S11N_NAMESPACE/s11n-macros.h> // COUT/CERR #endif #define LOUT if(LEXER_LOUD) CERR #define lout if(LEXER_LOUD) cerr namespace S11N_NAMESPACE { /** FlexTreeBuilder declares an EXPERIMENTAL quasi-interface into the libfun/s11n-related flex parsers. It is meant to be included by the parsers and their clients. The ground rules are described in the FlexTreeBuilder struct, but the same notes apply to all the lexers which subclass it. Why all this hassle? Because getting multiple flex-based parsers into one library is more painful than it really ought to be, and the FlexLexer subclasses must be well-hidden from clients to avoid potential compilation problems. Additionally, loading data without knowing it's data type in advance is more trouble than it should be, largely due to the hassles involved with linking in multiple FlexLexer subclasses. Much of this code is implemented in flex_lexers.cpp, but some of it must be implemented by the specific lexers and lives elsewhere. Big Fat Warning: This interface is COMPLETELY not thread-safe! Much of the internal data used by the lexers is global-scope and multiple lexers, even of different types, should NOT be used in parallel! This can be considered a bug, and this limitation may be addressed (i.e., put off again) at some point. Usage notes: - You must never delete any lexer you fetch via lexer(): it is owned by the base class. - You should call FlexTreeBuilder::cleanup() when you're done so the tree builder can be deleted. Deleting a builder will clean it up, obviously. If you need to hold on to it's output you can call builder()->auto_delete(false) to keep it from deleting the parsed-in node. - Subclasses should assume that each input block contains exactly one root node, and stop parsing after processing one node. (This is purely a point of long-standing conventions.) Developer notes: - see the samples in fun{txt,xml}.flex.at, et al. todos: - investigate making this a subclass of node_builder. - the current subclasses duplicate way too much code. Find out how best to collapse that. */ class FlexTreeBuilder { // implementation lives in flex_lexers.cpp public: virtual ~ FlexTreeBuilder(); /** FlexLexer * lexer() Returns the FlexLexer parser set via lexer( FlexLexer * ), which subclasses should call to set the proper lexer. The default behaviour is to return NULL. This object is absolutely useless until the lexer() is set. The caller DOES NOT own the returned pointer. lexer implementors: you may want to do any one-time initialization of your lexer in the first call to lexer(). This is the only function which provides public access to your lexer, so doing any initialization here will ensure that it gets called before the lexer is actually used. Typically a call to reset() should be done here, as that creates a new internal tree builder (see builder(), below). By convention (the one set by FunXML and FunTxt, that is), a lexer should generally stop lexing after reading one DOM node. This assumes that, as in XML, there is one root node in any input. This model appears to work well for a wide variety of cases (the majority, i would say), so please don't let this minor limitation bother you (if it makes it any better, it's really up to the lexer what defines "a root node", and it could even artificially wrap it's output in an artificial root if it needed to). That said, the node_builder interface /should/ work with multiple root nodes, but it has not really been tested. After a lexer()->yylex() loop, if parsing got a root node it will be available via root_node(). */ virtual FlexLexer *lexer(); /** This function is simply a shortcut for builder()->root_node(). The default condition is that the caller does not own the returned pointer. The caller owns the given pointer if this->builder()->auto_delete() returns false, otherwise the pointer will be deleted when this object is cleaned up (via cleanup() or deletion). Typically clients should call this after a lexer().yylex() loop to fetch the object the parser collected. */ s11n_node * root_node(); /** Returns the current dom builder, which gets (or should get) populated by this object's lexer(). If it is null then no data has been parsed in. You can get much more info about the tree via this object, but it is rarely necessary to do so. The caller does not own the returned pointer. This function may return NULL. */ S11N_NAMESPACE::node_builder * builder(); /** Resets the parser to use a new builder. This deletes the object returned by builder(), so be careful not to hang on to that pointer too long. It is intended to be used by subclasses but may have uses in other contexts. */ virtual void reset(); /** Should be called after you are done lexing and retrieving the nodes so the lexer can free the builder (which also frees any loaded nodes). */ virtual void cleanup(); /** Convenience function: does a while(lexer()->yylex() != 0) loop and returns the last code returned by yylex(). If parsing gets a root node it will be available via root_node() or via the builder() object. */ int lexer_loop(); /** convenience function: parses the given input stream and stops parsing when this->lexer() is done with it. This normally means it stops after matching one input node. Note that the "one node rule" is conventional only: subclasses may choose to parse more than one node out of the input stream before returning. s11n convention, however, is to assume that any loaded data is contained in one root node. If the load fails then it is still possible that the builder() has some content, but it may be in an undefined state. */ bool load( std::istream & in ); /** Subclasses need to call this, passing their proper lexer type. It will delete any previously-assigned object. It may be useful for non-subclasses to call this, but it certainly only for unusual or particularly complex cases. */ void lexer( FlexLexer * lexer ); /** @deprecated This function is really no longer necessary: it has been obsoleted by S11N_NAMESPACE::node_loader's more flexible approach. It may still be useful in some specific contexts, but should be considered deprecated. load_builder() looks at the first line of the given file and tries to select an appropriate lexer for the token. It returns a pointer, perhaps NULL, which the caller takes responsibility for. If it finds a lexer but it finds no parseable tokens it will return NULL. If it finds a lexer it passes the file stream to the lexer, which will then populate the new builder object. If that fails then the builder is deleted and NULL is returned. Developer notes: This function WOULD take an istream, but i can't(?) reliably(?) read from it twice (once to get the magic cookie and once to feed the whole thing to the parser). Reading JUST the cookie, then passing the stream on to a different lexer for parsing screws up the stream (the bug is not yet localized). This function is implemented in select_lexer.flex.at. */ static FlexTreeBuilder *load_builder( const std::string & filename ); // /** // experimental way to generically support comment blocks in parsers. // */ // void comment_mode( bool b ) { this->m_comment_mode = b; }; // bool comment_mode() const { return this->m_comment_mode; }; protected: /** Only subclasses may instantiate objects of this class. */ FlexTreeBuilder(); private: FlexLexer * m_lexer; bool m_lexer_inited; // bool m_comment_mode; S11N_NAMESPACE::node_builder * m_builder; }; /** FunXML is for parsing what's known variably as "text", "serial-text" and "Rusty's" format. It's a simple-grammared text-based DOM which is easy for humans to read and hand-edit, as well as fairly easy to parse. This format is used by the QUB project (qub.sourceforge.net) and libFunUtil (libfunutil.sourceforge.net). */ class FunTxt:public FlexTreeBuilder { // implementation lives in funtxt.flex.at public: FunTxt(){} virtual ~FunTxt(){} /** Re-implemented for internal reasons. */ virtual FlexLexer *lexer(); /** Re-implemented for internal reasons. */ virtual void reset(); }; /** FunXML is for parsing what's sometimes affectionately known as "fun-xml format", which is a very limited dialect of XML used extensively by QUB (qub.sourceforge.net) and libFunUtil (libfunutil.sourceforge.net). Known "Potential Problems": - does only rudimentary entity translation: only enough to support the parser. */ class FunXML:public FlexTreeBuilder { // implementation lives in funxml.flex.at public: FunXML(){} virtual ~FunXML(){} /** Re-implemented for internal reasons. */ virtual FlexLexer *lexer(); /** Re-implemented for internal reasons. */ virtual void reset(); }; /** This flexer parses a simple XML dialect. This parser stores all XML attributes as properties, and objects with complex properties may very well result in unparseable data. Because s11n_node uses key=val properties to store all aribtrary data, and does not directly support the notion of CDATA, this class does some special handling of the "CDATA" property in deserialized nodes, and the SimpleXMLSerializer does the appropriate fiddling on the other end. i don't want to add a cdata-style type to the lower-level interface because it would only be there to accomodate XML, yet clients should not need to know they are working with XML. That said, however, XML-specific clients which use this class need to be aware that the CDATA is stored in the CDATA property of s11n_nodes which are deserialized by this class (e.g., available via node.get_string("CDATA")). This class does only rudimentaly XML entity translation, but it should suffice for simple cases where the data need not necessarily be 100% XML-compliant. */ class SimpleXMLFlexer:public FlexTreeBuilder { // implementation lives in simplexml.flex.at public: SimpleXMLFlexer(){} virtual ~ SimpleXMLFlexer(){} /** Re-implemented for internal reasons. */ virtual FlexLexer *lexer(); /** Re-implemented for internal reasons. */ virtual void reset(); }; /** A builder for "the parenthesis format" (see paren.flex.at). */ class ParenTreeBuilder:public FlexTreeBuilder { // implementation lives in paren.flex.at public: ParenTreeBuilder() {} virtual ~ ParenTreeBuilder(){} /** Re-implemented for internal reasons. */ virtual FlexLexer *lexer(); /** Re-implemented for internal reasons. */ virtual void reset(); }; /** HexTreeBuilder is used by the hexFlexLexer. */ class HexTreeBuilder:public FlexTreeBuilder { // implementation lives in hex.flex.at public: HexTreeBuilder(){} virtual ~ HexTreeBuilder() {} /** Re-implemented for internal reasons. */ virtual FlexLexer *lexer(); /** Re-implemented for internal reasons. */ virtual void reset(); }; /** CompactTreeBuilder is used by the compactFlexLexer. */ class CompactTreeBuilder:public FlexTreeBuilder { // implementation lives in compact.flex.at public: CompactTreeBuilder(){} virtual ~CompactTreeBuilder(){} /** Re-implemented for internal reasons. */ virtual FlexLexer *lexer(); /** Re-implemented for internal reasons. */ virtual void reset(); }; }; // namespace S11N_NAMESPACE #endif // S11N_NAMESPACE_FLEX_LEXERS_H_INCLUDED --- NEW FILE: ns.funtxt.flex.at --- %option c++ %{ namespace { // to get doxygen to ignore these comments :/ /** my first lex :) This code is for parsing Rusty Ballinger's "text mode serialization format" (as we call it). Here's a rough spec: nodename class=ClassName { property1_name property1_value property2_name "value with spaces" propertyN_name 'or single quotes' foo this \ line is split \ with backslashes. # comment lines nodename class=SomeClass { ... } } Extensions to the original format, probably not tolerated by older code and should probably be left out: - comment lines can start with ; or # or // - C++-style comment blocks are supported. Known problems: - If node_depth() is non-zero when this code starts parsing then it does not work properly at all. In practice this has never happened. - use proper lex STATES instead of assert_depth, if feasible. - add syntax extension: nodename class=SomeClass N where N is a number. That is, the node is replicated N times into the output. - add syntax extension: # nodename class=Foo will comment out the whole class block. */ }; // namespace #define YY_SKIP_YYWRAP 1 int yywrap() { return 1; } // #include <stdio.h> #include <cassert> #include <iostream> #include <string> #include <deque> #include <S11N_NAMESPACE/s11n-macros.h> // COUT/CERR #include <S11N_NAMESPACE/string_util.h> // trim_string() #include <S11N_NAMESPACE/property_store.h> #include <S11N_NAMESPACE/class_loader.h> #include <S11N_NAMESPACE/instantiator.h> #include <S11N_NAMESPACE/key_value_parser.h> #include <S11N_NAMESPACE/node_builder.h> #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/Serializer.h> using std::cin; using std::cerr; using std::cout; using std::endl; #define LEXCERR CERR namespace { unsigned long ignored; unsigned long bracedepth; S11N_NAMESPACE::node_builder * serbuilder; std::string nodename; std::string nodeclass; std::string property; bool escaped; static S11N_NAMESPACE::key_value_parser kvp; /** Runs key_value_parser::parse(str) and saves the result in the lexer's kvp object. If this function returns false then kvp is in an undefined state, otherwise kvp holds a key and value parsed from str. Accepted formats: key value value value ... key = value value value ... key todo: return a std::pair instead of using key_value_parser (it's usage is legacy stuff). */ bool parseKVP( const std::string & str ) { // todo: clean this shit up!!! // std::string val = str; std::string delim = " \t"; // check for an '='. These are a syntax extension, and // may cause incompatibilities when reading old-format // data which contains a '='. // if( std::string::npos != str.find( "=" ) ) delim = "="; std::string::size_type pos; pos = str.find_first_of( delim ); std::string key = str.substr( 0, pos ); S11N_NAMESPACE::trim_string( key ); kvp.key( key ); if( std::string::npos == pos ) { kvp.value( "" ); return true; } // pos = str.find_first_not_of( delim, pos ); // if( std::string::npos == pos ) // { // kvp.value( "" ); // return true; // } std::string val = str.substr( pos+1 ); // S11N_NAMESPACE::trim_string( ); static S11N_NAMESPACE::FunTxtSerializer ser; S11N_NAMESPACE::translate_entities( val, ser.translations(), true ); //CERR << "prop ["<<key<<"]=["<<val<<"]"<<std::endl; kvp.value( val ); return true; } }; #define assert_depth if( bracedepth != serbuilder->node_depth() ) { ++ignored; return 1; } namespace S11N_NAMESPACE { FlexLexer * FunTxt::lexer() { FlexLexer * fp = 0; fp = this->FlexTreeBuilder::lexer(); if( fp ) return fp; // else first-time setup: this->reset(); return this->FlexTreeBuilder::lexer(); } void FunTxt::reset() { this->FlexTreeBuilder::reset(); //this->lexer( new sertxtFlexLexer() ); // gcc 3.3 bitches about this.no matching function for call to `FunTxt::lexer(FlexLexer*&)' FlexLexer * foo = new sertxtFlexLexer(); this->FlexTreeBuilder::lexer( foo ); serbuilder = this->builder(); ignored = 0; bracedepth = 0; } } // namespace S11N_NAMESPACE %} @COMMON_DEFINITIONS@ // COMMON_DEFINITIONS: See common_flex_definitions.at %x READ_PROPERTY_VALUE %% "/*""*"* { // there is apparently an endless loop caused in some cases with this :/ // c++-style comments. Code mostly taken from the flex info pages. ++ignored; int c; while((c = yyinput()) != 0) { if(c == '*') { c = yyinput(); if( 0 == c || '/' == c ) break; } } return 1; } ({SPACE}*)([;#]|\/).* { ++ignored; return 1; /* single-line comment */ } ({SPACE}*){WORD}{SPACE}+{WORD}={CLASSNAME} { // nodename class=foo::Bar std::string foo = YYText(); S11N_NAMESPACE::trim_string( foo ); //LEXCERR << "class dec token=["<<foo<<"]"<<endl; nodename = foo.substr( 0, foo.find_first_of( " \t" ) ); nodeclass = foo.substr( foo.find( "=" ) + 1 ); int ret = serbuilder->open_node( nodeclass, nodename ) ? 1 : -1; if( (ret == -1) ) { LEXCERR << foo << endl; return 0; } //LEXCERR << bracedepth << " opening class node " << nodeclass << " : " << nodename << std::endl; return ret; } \{ { // node's opening brace ++bracedepth; // nothing. return 1; } \} { // node's closing brace if( bracedepth == serbuilder->node_depth() ) { // avoid closing node when open_node() fails //LEXCERR << bracedepth-1<<" closing node"<<std::endl; serbuilder->close_node(); } --bracedepth; if( 0 == serbuilder->node_depth() ) { // return once we close the first top-level node. //if( ignored ) LEXCERR << "lexer ignored " << ignored << " token"<<(ignored!=1?"s":"") << endl; return 0; } //LEXCERR << "node depth="<<serbuilder->node_depth()<<" brace_depth="<<bracedepth<<std::endl; } <READ_PROPERTY_VALUE>(\\\n)({SPACE})* { //property += " "; // YYText(); } <READ_PROPERTY_VALUE>. { property += YYText(); } <READ_PROPERTY_VALUE>^({SPACE})+ {;} // swallow it <READ_PROPERTY_VALUE>\n { // end of line //S11N_NAMESPACE::trim_string( property ); if( ! parseKVP( property ) ) { // wasn't a key/value pair, so we'll lazily assume it's a key with no value. kvp.key(property); kvp.value(""); //LEXCERR << "failed parsing key/value pair from property token ["<<property<<"]"<<endl; } std::string pval = kvp.value(); serbuilder->add_property( kvp.key(), pval ); //LEXCERR << "add_property(["<<kvp.key()<<"],["<<kvp.value()<<"])"<<std::endl; BEGIN INITIAL; } {PROPERTY_DECLS} { // property_name (=?) assert_depth; property = YYText(); BEGIN READ_PROPERTY_VALUE; } .|\n|{SPACE}+ {;} %% --- NEW FILE: ns.funxml.flex.at --- %option c++ %{ #define YY_SKIP_YYWRAP 1 int yywrap() { return 1; } #include <cassert> #include <iostream> #include <string> // #include <S11N_NAMESPACE/s11n-macros.h> // COUT/CERR #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/string_util.h> // translate_entities() #include <S11N_NAMESPACE/s11n_globals.h> // xml_entity_map() #include <S11N_NAMESPACE/Serializer.h> using std::cin; using std::cerr; using std::cout; using std::endl; // class FunXML_internal namespace { // public: unsigned long bracedepth; std::string nodename; std::string nodeclass; std::string yystr; std::string cdata; S11N_NAMESPACE::node_builder * the_builder; }; // struct FunXML_internal // FunXML_internal FunXMLi; namespace S11N_NAMESPACE { FlexLexer * FunXML::lexer() { FlexLexer * fp = 0; fp = this->FlexTreeBuilder::lexer(); if( fp ) return fp; // else first-time setup: this->reset(); return this->FlexTreeBuilder::lexer(); } void FunXML::reset() { this->FlexTreeBuilder::reset(); bracedepth = 0; this->FlexTreeBuilder::lexer(new serxmlFlexLexer()); the_builder = this->builder(); } } // namespace S11N_NAMESPACE %} @COMMON_DEFINITIONS@ // COMMON_DEFINITIONS: See common_flex_definitions.in KEY_TYPE ({WORD}|{NUMBER}) // NUMBER support is to help out s11n_node::deserialize_list/Map() %% \<{KEY_TYPE}{SPACE}+"class=\""{CLASSNAME}"\""{SPACE}*\> { // opening a node ++bracedepth; yystr = YYText(); //COUT << "class node? "<<yystr<<std::endl; std::string::size_type opos = yystr.find( "class=\"" ) + 7; std::string::size_type cpos = yystr.find( "\"", opos ); nodeclass = yystr.substr( opos, cpos - opos ); nodename = yystr.substr( 1, yystr.find_first_of( " \t\n" ) - 1 ); the_builder->open_node(nodeclass, nodename); continue; } \<{KEY_TYPE}\> { // opening a property cdata = ""; ++bracedepth; } \<\/{KEY_TYPE}\> { // closing something yystr = YYText(); if( bracedepth != the_builder->node_depth() ) { // closing a property. std::string prop = yystr.substr( 2, yystr.size() - 3 ); static S11N_NAMESPACE::FunXMLSerializer ser; S11N_NAMESPACE::translate_entities( cdata, ser.translations(), true ); the_builder->add_property( prop, cdata ); } else { // closing an object node. the_builder->close_node(); } --bracedepth; cdata = ""; if( 0 == the_builder->node_depth() ) { // return once we close the first top-level node. return 0; } } .|\n|({SPACE}) { cdata += YYText();} %% --- NEW FILE: ns.hex.flex.at --- %option c++ %{ // // LICENSE: Public Domain // Author: stephan - st...@s1... // #define YY_SKIP_YYWRAP 1 int yywrap() { return 1; } // #include <stdio.h> #include <cassert> #include <iostream> #include <string> #include <deque> #include <S11N_NAMESPACE/s11n-macros.h> // COUT/CERR #define PCERR CERR << "hex.flex error:" // #include <S11N_NAMESPACE/string_util.h> // trim_string() // #include <S11N_NAMESPACE/property_store.h> // #include <S11N_NAMESPACE/class_loader.h> // #include <S11N_NAMESPACE/instantiator.h> // #include <S11N_NAMESPACE/key_value_parser.h> #include <S11N_NAMESPACE/node_builder.h> #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/string_util.h> // hex2int() using std::cin; using std::cerr; using std::cout; using std::endl; /** Basic grammar spec for the "hexed" serialization format: {NODE_OPEN}{NAME_SIZE}{NODE_NAME}<class_name_size>{CLASSNAME} ({PROP_OPEN}<key_size><key><value_size><value>)* (sub-nodes)* {NODE_CLOSE} See the lex source for the meanings of the {TOKENS} named above. */ namespace { unsigned long node_depth = 0; unsigned int loops = 0; std::string word; std::string propname; std::string propval; std::string nodename; std::string nodeclass; bool in_prop; unsigned int decval = 0; unsigned int lcv = 0; S11N_NAMESPACE::node_builder * serbuilder = 0; } namespace S11N_NAMESPACE { FlexLexer * HexTreeBuilder::lexer() { FlexLexer * fp = 0; fp = this->FlexTreeBuilder::lexer(); if( fp ) return fp; // else first-time setup: this->reset(); return this->FlexTreeBuilder::lexer(); } void HexTreeBuilder::reset() { this->FlexTreeBuilder::reset(); FlexLexer * foo = new hexFlexLexer(); this->FlexTreeBuilder::lexer( foo ); serbuilder = this->builder(); node_depth = 0; } } // namespace S11N_NAMESPACE namespace { char inchar; } #define READWORD(SZ) word = ""; \ for( int i = 0; i < SZ; i++ )\ {\ inchar = yyinput(); \ if( 0 == inchar ) {word=""; return 0;} \ word += inchar; \ };\ decval = S11N_NAMESPACE::hex2int(word);\ if( 0 == decval ) { PCERR << "Error reading word (size="<<SZ<<"). Maybe reached end of input?" << endl; return 0; } %} HEX_DIGIT ([a-fA-F0-9]) WORD2 {HEX_DIGIT}{2} // maintenance note: these hex codes must be kept in sync with those from HexSerializer's enum NODE_OPEN 11 NODE_CLOSE 10 PROP_OPEN 21 COOKIE 51190001 DATA_END 51190000 %% \n {;} {COOKIE} {;} {DATA_END} { return 0; } {NODE_OPEN} { //COUT << "Opening node." << std::endl; READWORD(2); // read node name size nodename = ""; loops = decval; for( lcv = 0; lcv < loops; lcv++ ) { // read node name READWORD(2); // read next char of node name. nodename += (unsigned char) decval; } //cout<< endl; READWORD(2); // get class name size nodeclass = ""; loops = decval; for( lcv = 0; lcv < loops; lcv++ ) { // read class name READWORD(2); // get next char nodeclass += (unsigned char) decval; } if( ! serbuilder->open_node( nodeclass, nodename ) ) { PCERR<< "open_node("<<nodeclass<<","<<nodename<<") failed." << endl; return 0; } } {NODE_CLOSE} { //COUT << "Closing node." << std::endl; serbuilder->close_node(); if( 0 == serbuilder->node_depth() ) { // stop once we close the first top-level node. return 0; } } {PROP_OPEN} { //COUTL( "Opening property" ); READWORD(2); // prop name size //COUT << "name size=" <<word << " dec="<<decval<<std::endl; propname = ""; loops = decval; for( lcv = 0; lcv < loops; lcv++ ) { // read property naem READWORD(2); // next char propname += (unsigned char) decval; } READWORD(8); // get value size propval = ""; loops = decval; for( lcv = 0; lcv < loops; lcv++ ) { // read property's value READWORD(2); // next char propval += (unsigned char) decval; } serbuilder->add_property( propname, propval ); } {WORD2}|[.] { PCERR<< "unexpected token: " << YYText()<<std::endl; return 0; } %% #if HEX_DO_MAIN #include <S11N_NAMESPACE/s11n_io.h> // HexSerializer // #include <S11N_NAMESPACE/FlexShell.h> // #include <S11N_NAMESPACE/ELib.h> using namespace S11N_NAMESPACE; int main( int argc, char ** argv ) { S11N_NAMESPACE::HexTreeBuilder bob; FlexLexer * lexer = bob.lexer(); // FlexLexer * lexer = new hexFlexLexer(); while( 0 != (lexer->yylex() ) ); if( bob.root_node() ) { S11N_NAMESPACE::ParenSerializer ser; ser.serialize( *(bob.root_node()), std::cout ); } return 0; } #endif --- NEW FILE: ns.paren.flex.at --- %option c++ %{ /** LICENSE: Public Domain Author: stephan - st...@s1... This lexer reads in a lisp-like (but not lisp) grammar for the s11n framework. It's output partner is S11N_NAMESPACE::ParenSerializer. Sample: nodename=(ImplClassName (propery_name property value) (prop2 value of \) prop2) another_node=(ns::ClassName) ) nodename represents an s11n_node::name() ImplClassName represents the object's impl_class() value. Note that closing parens in your data must be backslash-escaped. This parser arguably strips all non-paired backslashes, so any actual backslashes must also be escaped (C-style). The ParensSerializer takes this into account and escapes it's serialized data. */ #define YY_SKIP_YYWRAP 1 int yywrap() { return 1; } // #include <stdio.h> #include <cassert> #include <iostream> #include <string> #include <deque> #include <S11N_NAMESPACE/s11n-macros.h> // COUT/CERR #define PCERR CERR << "paren.flex error:" #include <S11N_NAMESPACE/string_util.h> // trim_string() // #include <S11N_NAMESPACE/property_store.h> // #include <S11N_NAMESPACE/class_loader.h> // #include <S11N_NAMESPACE/instantiator.h> // #include <S11N_NAMESPACE/key_value_parser.h> #include <S11N_NAMESPACE/node_builder.h> #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/Serializer.h> // for ParenSerializer::translations() using std::cin; using std::cerr; using std::cout; using std::endl; namespace { unsigned long node_depth = 0; std::string tmpstr; std::string nodename; std::string nodeclass; bool in_prop; S11N_NAMESPACE::node_builder * serbuilder = 0; } namespace S11N_NAMESPACE { FlexLexer * ParenTreeBuilder::lexer() { FlexLexer * fp = 0; fp = this->FlexTreeBuilder::lexer(); if( fp ) return fp; // else first-time setup: this->reset(); return this->FlexTreeBuilder::lexer(); } void ParenTreeBuilder::reset() { this->FlexTreeBuilder::reset(); FlexLexer * foo = new parenFlexLexer(); this->FlexTreeBuilder::lexer( foo ); serbuilder = this->builder(); node_depth = 0; } } // namespace S11N_NAMESPACE /***** *****/ %} @COMMON_DEFINITIONS@ %x OPEN_CLASS %x IN_PROPERTY OPENER \( CLOSER \) NODENAME {VARNAME} PROPERTY {VARNAME} %% {SPACE}*[#;].*$ {;} // comment lines "(*" { // (* comment blocks *) // Code mostly taken from the flex info pages. int c; while((c = yyinput()) != 0) { if(c == '*') { c = yyinput(); if( 0 == c ) { PCERR << "hit EOF in a (*comment block*)." << std::endl; return 0; } if( ')' == c ) break; //??? else unput(c); } } return 1; } {OPENER}{SPACE}* { BEGIN IN_PROPERTY; } <IN_PROPERTY>({VARNAME}|{NUMBER})({SPACE})* { // key name of property std::string propname = YYText(); // strip leading/trailing spaces from the property name: static const std::string avoid = " \t\n"; std::string::size_type tail = propname.find_last_not_of( avoid ); propname = propname.substr( propname.find_first_not_of( avoid ), (std::string::npos == tail) ? tail : (tail + 1) ); //COUT << "property ["<<propname<<"] = "; // Now we consider all data until a non-escaped closing brace // to be the value of the property... std::string propval = ""; unsigned char c = yyinput(); bool escaped = false; while( 0 != c ) { if( (!escaped) && ('\\' == c) ) { // next char will be considered escaped escaped = true; propval += c; c = yyinput(); continue; } if ( (!escaped) && (')' == c) ) { // Look for a non-escaped paren to close us. break; } escaped = false; propval += c; c = yyinput(); //COUT << "["<<c<<"]"<<endl; } if( 0 == c ) { PCERR << "Reached EOF while reading value for property '"<<propname<<"'. This shouldn't happen." << std::endl; return 0; } // S11N_NAMESPACE::trim_string( propval, S11N_NAMESPACE::TrimLeading ); static S11N_NAMESPACE::ParenSerializer ser; S11N_NAMESPACE::translate_entities( propval, ser.translations(), true ); //std::cout << "["<<propval<<"]"<<std::endl; serbuilder->add_property( propname, propval ); BEGIN 0; } {NODENAME}={OPENER} { tmpstr = YYText(); nodename = tmpstr.substr( 0, tmpstr.find( "=" ) ); //COUT << "node name="<<nodename<<std::endl; BEGIN OPEN_CLASS; } <OPEN_CLASS>{SPACE}+ {;} <OPEN_CLASS>{CLOSER} { // special case: empty node: nodename=() --node_depth; //COUT << "ignoring empty node " << nodename << std::endl; BEGIN 0; } <OPEN_CLASS>[{SPACE}\n]+ {;} <OPEN_CLASS>{CLASSNAME} { nodeclass = std::string(YYText()); if( nodeclass.empty() ) { PCERR << "nodes may not have empty names!" <<std::endl; return 0; } //COUT << "opening '"<<nodename<<"', class=" << nodeclass << std::endl; ++node_depth; if( ! serbuilder->open_node( nodeclass, nodename ) ) { PCERR<< "open_node("<<nodeclass<<","<<nodename<<") failed." << endl; return 0; } BEGIN 0; } <OPEN_CLASS>[.\n] { PCERR << "did not find class name after '"<<nodename<<"=(" << std::endl; return 0; } {CLOSER} { //COUT << node_depth<< " Closing node" << std::endl; serbuilder->close_node(); --node_depth; if( 0 == serbuilder->node_depth() ) { // stop once we close the first top-level node. return 0; } } ^"(S11N_NAMESPACE::parens)" {;} // magic cookie ({SPACE})|\n {;} . {;} // [.]+ { PCERR << "Unexpected token: [" << YYText()<<"]"<<std::endl;} %% // ^{SPACE}*[#;].*$ {;} // comment lines // [#;][^{OPENER}]* {;} // comments trailing after node closures #if PAREN_DO_MAIN #include <S11N_NAMESPACE/s11n_io.h> // ParenSerializer int main( int argc, char ** argv ) { S11N_NAMESPACE::ParenTreeBuilder bob; FlexLexer * lexer = bob.lexer(); while( 0 != (lexer->yylex() ) ); if( bob.root_node() ) { S11N_NAMESPACE::ParenSerializer ser; ser.serialize( *(bob.root_node()), std::cout ); } return 0; } #endif --- NEW FILE: ns.select_lexer.flex.at --- %option c++ %{ /** LICENSE: Public Domain Searchs the first line of input (consuming it) for a "magic cookie" by which to identify a lexer. Maintenance: This code knows about the formats supplied with the s11n library, so it must be updated as those formats change. */ #define YY_SKIP_YYWRAP 1 int yywrap() { return 1; } #include <cassert> #include <iostream> #include <string> #include <sstream> #include <S11N_NAMESPACE/s11n-macros.h> // COUT/CERR // #include <S11N_NAMESPACE/node_builder.h> #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/file_util.h> // get_istream(), bytes_from_file() using std::cin; using std::cerr; using std::cout; using std::endl; namespace S11N_NAMESPACE { FlexTreeBuilder * m_selected_builder = 0; FlexTreeBuilder * FlexTreeBuilder::load_builder( const std::string & fname ) { m_selected_builder = 0; std::string token = S11N_NAMESPACE::bytes_from_file( fname, 50 ); if( token.empty() ) return NULL; //CERR << "cookie=["<<token<<"]"<<std::endl; std::istringstream cookiestream(token); select_lexerFlexLexer fl; fl.switch_streams( &cookiestream, 0 ); fl.yylex(); // only one iteration is needed unless the lexer code changes significantly. if( ! m_selected_builder ) { CERR << "FlexTreeBuilder::load_builder("<<fname<<") does not know how to handle this file." << std::endl; return NULL; } std::istream * is = S11N_NAMESPACE::get_istream( fname.c_str() ); if( ! is ) return NULL; // should never happen, since we were able to read the cookie. bool killit = false; FlexTreeBuilder * ret = m_selected_builder; if( ! ret->load( *is ) ) { killit = true; } delete( is ); if( ! m_selected_builder->root_node() ) { // no point, is there? killit = true; } if( killit ) { delete( m_selected_builder ); m_selected_builder = 0; ret = 0; } return ret; } }; %} @COMMON_DEFINITIONS@ // COMMON_DEFINITIONS: See common_flex_definitions.in %% ^"<!DOCTYPE SerialTree>" { // fun-xml S11N_NAMESPACE::m_selected_builder = new S11N_NAMESPACE::FunXML(); return 0; } ^"#SerialTree 1" { // fun-txt S11N_NAMESPACE::m_selected_builder = new S11N_NAMESPACE::FunTxt(); return 0; } ^"<!DOCTYPE S11N_NAMESPACE::simplexml>" { // s11n S11N_NAMESPACE::m_selected_builder = new S11N_NAMESPACE::SimpleXMLFlexer(); return 0; } ^"(S11N_NAMESPACE::parens)" { S11N_NAMESPACE::m_selected_builder = new S11N_NAMESPACE::ParenTreeBuilder(); return 0; } /** ^51190001 { S11N_NAMESPACE::m_selected_builder = new S11N_NAMESPACE::HexTreeBuilder(); return 0; } */ ^51191001 { S11N_NAMESPACE::m_selected_builder = new S11N_NAMESPACE::CompactTreeBuilder(); return 0; } ^"#!/S11N_NAMESPACE/TreeBuilder".* { // reminder: if i add a $ to the end is never matches! bug? CERR << "Future-compatibility file format:" << YYText() << std::endl; return 0; } (.|\n)+ { //CERR << "Eeek: " << YYText() << std::endl; S11N_NAMESPACE::m_selected_builder = NULL; return 0; } %% #if SELECT_LEXER_DO_MAIN int main() { FlexLexer * fl = new select_lexerFlexLexer(); while( fl->yylex() ); delete( fl ); } #endif --- NEW FILE: ns.simplexml.flex.at --- %option c++ %{ /** This flexer builds s11n_node trees out of a subset of XML. Most basic XML constructs are supported. XML CDATA, which is not directly supported by the s11n_node interface, is stored in the property named "CDATA", available via s11n_node::get_string("CDATA"). */ #define YY_SKIP_YYWRAP 1 int yywrap() { return 1; } #include <cassert> #include <iostream> #include <string> #include <stack> #include <S11N_NAMESPACE/string_util.h> // normalize_string(), xml_entity_map(), etc #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/Serializer.h> #include <S11N_NAMESPACE/key_value_parser.h> #include <S11N_NAMESPACE/context_singleton.h> using std::cin; using std::cerr; using std::cout; using std::endl; namespace { unsigned long bracedepth; std::string nodename; std::string nodeclass; std::string yystr; S11N_NAMESPACE::node_builder * the_builder; typedef std::stack<std::string> StringStack; StringStack cdata; void cleanup() { nodename = ""; nodeclass = ""; yystr = ""; for( StringStack::size_type i = 0; i < cdata.size(); ++i ) cdata.pop(); // the_builder will be freed elsewhere. } }; namespace S11N_NAMESPACE { FlexLexer * SimpleXMLFlexer::lexer() { FlexLexer * fp = 0; fp = this->FlexTreeBuilder::lexer(); if( fp ) return fp; // else first-time setup: this->reset(); return this->FlexTreeBuilder::lexer(); } void SimpleXMLFlexer::reset() { this->FlexTreeBuilder::reset(); bracedepth = 0; FlexLexer * fp = new simplexmlFlexLexer(); this->FlexTreeBuilder::lexer(fp); fp->set_debug( 1 ); the_builder = this->builder(); } } // namespace S11N_NAMESPACE static S11N_NAMESPACE::key_value_parser sxml_kvp; int sxml_close_node() { // closing something if( bracedepth == the_builder->node_depth() ) { const std::string & cd = cdata.top(); // S11N_NAMESPACE::trim_string( cd ); if( ! cd.empty() ) the_builder->add_property( "CDATA", cd ); the_builder->close_node(); } if( 0 == the_builder->node_depth() ) { // return once we close the first top-level node. cleanup(); return 0; } cdata.pop(); --bracedepth; return the_builder->node_depth(); } %} @COMMON_DEFINITIONS@ // COMMON_DEFINITIONS: See common_flex_definitions.in KEY_TYPE ({WORD}|{CLASSNAME}|{NUMBER}) // NUMBER is to help out s11n_node::deserialize_list/Map() %x IN_ELEM_DECL %x IN_COMMENT %x IN_CDATA %% // \<\!.+\n { // continue; // } "<?"[^>]+ {;} // todo: add a state to read through these! "<![CDATA[" { BEGIN IN_CDATA; } <IN_CDATA>"]]>" { BEGIN 0; } <INITIAL>^({SPACE}+) {continue;} <INITIAL>({SPACE}+)$ {continue;} <IN_CDATA>(.|\n) { if( ! cdata.empty() ) cdata.top() += YYText(); continue; } "<"{KEY_TYPE} { yystr = YYText(); //COUT << "opening element? "<<yystr<<std::endl; nodename = yystr.substr( 1 ); the_builder->open_node("NoClassYet", nodename); cdata.push(std::string()); ++bracedepth; BEGIN IN_ELEM_DECL; } <IN_ELEM_DECL>{KEY_TYPE}=({QUOTED_STRING}|{RGB_COLOR}|{KEY_TYPE}|([a-zA-Z_0-9]+)|(\"\")) { // foo if( ! sxml_kvp.parse( YYText() ) ) { CERR << "syntax error: could not parse key=value from ["<<YYText()<<"]"<<std::endl; cleanup(); return 0; } std::string attr = sxml_kvp.value(); if( attr.size() >= 2 ) { // strip quotes attr.erase(attr.begin()); attr.erase(attr.end()-1); } S11N_NAMESPACE::translate_entities( attr, S11N_NAMESPACE::context_singleton<S11N_NAMESPACE::SimpleXMLSerializer,void>::instance().translations(), true ); std::string k = sxml_kvp.key(); if( "s11n_class" == k ) { the_builder->current_node()->impl_class( attr ); } else { the_builder->add_property( k, attr ); } //CERR << "property val=["<<attr<<"] --> ["<<propval<<"]"<<std::endl; } <IN_ELEM_DECL>\/{SPACE}*> { if( 0 == sxml_close_node() ) return 0; BEGIN 0; } <IN_ELEM_DECL>">" { // closing element decl. //yystr = YYText(); BEGIN 0; } <IN_ELEM_DECL>"<" { CERR << "syntax error: we found a '<' character inside an element declaration." << std::endl; cleanup(); return 0; ; } <IN_ELEM_DECL>(.|\n) {;} \<\/({KEY_TYPE})({SPACE}*)\> { if( 0 == sxml_close_node() ) return 0; } "<!--" { //COUT << "entering comment..." << std::endl; BEGIN IN_COMMENT; } <IN_COMMENT>"<!--" { CERR << "syntax error: you may not have comments within comments." << std::endl; cleanup(); return 0; //BEGIN 0; } <IN_COMMENT>"-->" { //COUT << "... exiting comment" << std::endl; BEGIN 0; } <IN_COMMENT>[.\n] {;} .|\n {;} // swallow it %% #if SIMPLEXML_DO_MAIN #include <S11N_NAMESPACE/s11n_io.h> using namespace S11N_NAMESPACE; int main( int argc, char ** argv ) { SimpleXMLFlexer xmlflex; FlexLexer * lexer = xmlflex.lexer(); while( 0 != (lexer->yylex() ) ); std::cout << endl; if( s11n_node * node = xmlflex.root_node() ) { node->serialize_properties( *node ); COUT << "Re-serialized:\n"; s11n_io<SimpleXMLSerializer>::save( *node, std::cout ); s11n_io<FunTxtSerializer>::save( *node, std::cout ); s11n_io<FunXMLSerializer>::save( *node, std::cout ); } return 0; } #endif |
Update of /cvsroot/libfunutil/libfunutil/lib/s11n/parsers In directory sc8-pr-cvs1:/tmp/cvs-serv29289/lib/s11n/parsers Removed Files: compact.flex.at funtxt.flex.at funxml.flex.at paren.flex.at select_lexer.flex.at simplexml.flex.at Log Message: renamed to ns.* --- compact.flex.at DELETED --- --- funtxt.flex.at DELETED --- --- funxml.flex.at DELETED --- --- paren.flex.at DELETED --- --- select_lexer.flex.at DELETED --- --- simplexml.flex.at DELETED --- |
Update of /cvsroot/libfunutil/libfunutil/lib/s11n In directory sc8-pr-cvs1:/tmp/cvs-serv27725/lib/s11n Modified Files: Makefile Added Files: ns.CompactSerializer.cpp ns.FileLoader.cpp ns.FileLoader.h ns.HexSerializer.cpp ns.include_from_main.h ns.node_builder.cpp ns.node_builder.h ns.node_loader.cpp ns.node_loader.h ns.ParenSerializer.cpp ns.S11n.cpp ns.s11n_globals.cpp ns.s11n_globals.h ns.S11n.h ns.s11n_io.cpp ns.s11n_io.h ns.s11n-macros.h ns.s11n_node.cpp ns.s11n_node.h ns.serializable_adapter.h ns.Serializable.cpp ns.Serializable.h ns.Serializer.cpp ns.Serializer.h ns.serializer_loader.cpp ns.serializer_loader.h Log Message: egg --- NEW FILE: ns.CompactSerializer.cpp --- #include <iostream> #include <string> #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/string_util.h> #include <S11N_NAMESPACE/Serializer.h> // maintenance note: this class is about 98% identical to FunTxt. i // need a way to combine these better. namespace S11N_NAMESPACE { CompactSerializer::CompactSerializer() { }; CompactSerializer::~CompactSerializer() { }; s11n_node * CompactSerializer::deserialize( std::istream & is ) { S11N_NAMESPACE::CompactTreeBuilder parser; return basic_serializer::deserialize( parser, is ); } bool CompactSerializer::serialize( const s11n_node & node, std::ostream & os ) const { if ( !basic_serializer::serialize( node, os ) ) return false; static const int ctrlwidth = 2; static const int size2b = 2; static const int size8b = 8; static const int cookiewidth = 8; // static const int charwidth = 2; static unsigned int depth = 0; ++depth; std::string nname = node.name(); std::string impl = node.impl_class(); std::string::size_type sizE = 0; // WTF must all this stream manip be done on every fucking insert? #define OS_INT(C,W) os.width(W);os<<std::hex<<std::right<<(unsigned int)(C); #define INSERT(vaR,WIDTH) sizE = vaR.size(); OS_INT(sizE,WIDTH); \ for( std::string::size_type ins = 0; ins < sizE; ins++ ) {\ /*OS_INT(vaR[ins],charwidth);*/ \ os << (unsigned char) vaR[ins]; \ }; if ( 1 == depth ) { os.setf( std::ios_base::hex ); os.fill('0'); os.setf(std::ios_base::right, std::ios_base::adjustfield); OS_INT(Magic_Cookie,cookiewidth); os << '\n'; } OS_INT(Node_Open,ctrlwidth); INSERT(nname,size2b); INSERT(impl,size2b); S11N_NAMESPACE::property_store::const_iterator it = node.property_store::begin(); S11N_NAMESPACE::property_store::const_iterator et = node.property_store::end(); std::string propval; std::string propname; //bool gotprops = ( it != et ); for ( ; it != et; ++it ) { OS_INT(Prop_Open,ctrlwidth); propname = ( *it ).first; INSERT(propname,size2b); propval = ( *it ).second; INSERT(propval,size8b); //OS_INT(Prop_Close); } s11n_node::child_list_type::const_iterator cit = node.children().begin(); s11n_node::child_list_type::const_iterator cet = node.children().end(); bool ret = true; for ( ; cit != cet; ++cit ) { if ( !this->serialize( *( *cit ), os ) ) { ret = false; } //os << (out_type) '\n'; } OS_INT(Node_Close,ctrlwidth); os << '\n'; if( 1 == depth ) { OS_INT(Data_End,cookiewidth); os << std::endl; // //os << (out_type) '\n'; // os.flush(); // maintenance: os must be flush()ed or the client may be forced to do it. } --depth; return ret; } }; // namespace S11N_NAMESPACE --- NEW FILE: ns.FileLoader.cpp --- // // Author: stephan beal <st...@s1...> // License: Public Domain // #include <S11N_NAMESPACE/FileLoader.h> #include <S11N_NAMESPACE/flex_lexers.h> // FlexTreeBuilder #include <S11N_NAMESPACE/s11n-macros.h> // BROKEN() namespace S11N_NAMESPACE { s11n_node * FileLoader::loadNode( const std::string & key ) const { std::string path = this->path_finder::find( key ); if( path.empty() ) return NULL; FlexTreeBuilder * bob = FlexTreeBuilder::loadBuilder( path ); if( ! bob ) return NULL; s11n_node * node = 0; if( bob->builder() ) { node = bob->root_node(); bob->builder()->autoDelete( false ); // we take control of node. } delete( bob ); return node; } } // namespace S11N_NAMESPACE --- NEW FILE: ns.FileLoader.h --- // // Author: stephan beal <st...@s1...> // License: Public Domain // #ifndef S11N_NAMESPACE_S11NFILELOADER_H_INCLUDED #define S11N_NAMESPACE_S11NFILELOADER_H_INCLUDED 1 #include <string> #include <S11N_NAMESPACE/path_finder.h> #include <S11N_NAMESPACE/s11n_node.h> namespace S11N_NAMESPACE { /** A classloader for loading Serializable classes from files, plus a convenience class for loading files from arbitrary data types, without having to know the type nor if it is compressed or not. */ class FileLoader : public S11N_NAMESPACE::path_finder { public: typedef FileLoader ThisType; // typedef dll_loader ParentClass; // typedef ParentClass::value_type value_type; // typedef ParentClass::key_type key_type; FileLoader(){}; virtual ~ FileLoader(){}; /** First tries to load key via the ancestor's method(s), and returns that pointer if it works. Secondly it tries to find file key in this->path() and return a new value_type * if it can deserialize an object of that type from that file. The caller owns the returned pointer, which may be NULL. Note that the input file may be in any format internally supported by the library. */ template <typename SerializableType> SerializableType * load( const std::string & filename ) const { typedef SerializableType ST; s11n_node * node = FileLoader::loadNode( key ); if( node ) { ST * ch = 0; /** Grief!!!! gcc 3.3 refuses to compile this: ch = node->deserialize<ST>(); error is: parse error before `;' token but it allows the exact same code in some other contexts!!! A workaround is to qualify s11n_node's class, but that breaks polymorphism!!! deserialize() is a template func, so it can't be virtual, but that's beside the point! */ ch = node->s11n_node::deserialize<ST>(); delete( node ); } return ch; } /** Tries to load the root s11n_node from the input file. The caller owns the pointer. This is similar to load(), but the returned object is not deserialized (indeed, it is not Serializable). This function supports all current Serializer data formats, uncompressed or compressed (assuming the suitable decompressor is enabled in your library). */ s11n_node * loadNode( const std::string & ) const; }; // class FileLoader }; // namespace S11N_NAMESPACE #endif // S11N_NAMESPACE_S11NFILELOADER_H_INCLUDED --- NEW FILE: ns.HexSerializer.cpp --- #include <iostream> #include <string> #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/string_util.h> #include <S11N_NAMESPACE/Serializer.h> // maintenance note: this class is about 98% identical to FunTxt. i // need a way to combine these better. namespace S11N_NAMESPACE { HexSerializer::HexSerializer() { }; HexSerializer::~HexSerializer() { }; s11n_node * HexSerializer::deserialize( std::istream & is ) { S11N_NAMESPACE::HexTreeBuilder parser; return basic_serializer::deserialize( parser, is ); } bool HexSerializer::serialize( const s11n_node & node, std::ostream & os ) const { if ( !basic_serializer::serialize( node, os ) ) return false; typedef unsigned int out_type; static unsigned int depth = 0; // recursion depth. // token sizes: static const int width2b = 2; static const int cookie_width = 8; static const int width8b = 8; ++depth; std::string nname = node.name(); std::string impl = node.impl_class(); std::string::size_type sizE = 0; // WTF must all this stream manip be done on every insert? #define OS_INT(C,W) os.width(W);os<<std::hex<<std::right<<(out_type)(C); #define INSERT(vaR,WIDTH) sizE = vaR.size(); OS_INT(sizE,WIDTH); \ for( std::string::size_type ins = 0; ins < sizE; ins++ ) {\ OS_INT(vaR[ins],width2b); \ } if ( 1 == depth ) { os.setf( std::ios_base::hex ); os.fill('0'); os.setf(std::ios_base::right, std::ios_base::adjustfield); OS_INT(Magic_Cookie,cookie_width); os << '\n'; } OS_INT(Node_Open,width2b); INSERT(nname,width2b); INSERT(impl,width2b); S11N_NAMESPACE::property_store::const_iterator it = node.property_store::begin(); S11N_NAMESPACE::property_store::const_iterator et = node.property_store::end(); std::string propval; std::string propname; //bool gotprops = ( it != et ); for ( ; it != et; ++it ) { OS_INT(Prop_Open,width2b); propname = ( *it ).first; INSERT(propname,width2b); propval = ( *it ).second; INSERT(propval,width8b); //OS_INT(Prop_Close); } s11n_node::child_list_type::const_iterator cit = node.children().begin(); s11n_node::child_list_type::const_iterator cet = node.children().end(); bool ret = true; for ( ; cit != cet; ++cit ) { if ( !this->serialize( *( *cit ), os ) ) { ret = false; } //os << (out_type) '\n'; } OS_INT(Node_Close,width2b); os << '\n'; if( 1 == depth ) { OS_INT(Data_End,width8b); //os << (out_type) '\n'; os << std::endl; // maintenance: os must be flush()ed or the client may be forced to do it. } --depth; return ret; } }; // namespace S11N_NAMESPACE --- NEW FILE: ns.include_from_main.h --- #ifndef S11N_INCLUDE_FROM_MAIN_H #define S11N_INCLUDE_FROM_MAIN_H #include <S11N_NAMESPACE/serializable_adapter.h> #include <S11N_NAMESPACE/Serializable.h> // contains code which must, for linking reasons, // be defined only once, in the client's main app. // ======= fuck: clients must include this line in their main app. // SERIALIZABLE_ADAPTER(S11N_NAMESPACE::Serializable,s7e,d9e); // ======= if they don't then they don't get this specialization // and the lib won't link, because this code won't get linked // into libs11n. #endif // S11N_INCLUDE_FROM_MAIN_H --- NEW FILE: ns.node_builder.cpp --- // // Author: stephan beal <st...@s1...> // License: Public Domain // #include <deque> #include <cassert> #include <S11N_NAMESPACE/s11n-macros.h> // CERR macro #include <S11N_NAMESPACE/pointer_list.h> #include <S11N_NAMESPACE/class_loader.h> #include <S11N_NAMESPACE/node_builder.h> #include <S11N_NAMESPACE/serializable_adapter.h> #include <S11N_NAMESPACE/s11n_node.h> #include <S11N_NAMESPACE/Serializable.h> #define LEXER_LOUD 0 #define LOUT if(LEXER_LOUD) COUT #define lout if(LEXER_LOUD) cout namespace S11N_NAMESPACE { node_builder::node_builder( ):m_autodel( true ), m_node_count( 0 ), m_node( 0 ), m_root( 0 ) { } node_builder::~node_builder( ) { m_toplist.auto_delete( this->m_autodel ); } void node_builder::auto_delete( bool b ) { this->m_autodel = b; } bool node_builder::auto_delete( ) { return this->m_autodel; } unsigned long node_builder::node_count( ) const { return m_node_count; } unsigned long node_builder::node_depth( ) const { return m_nodestack.size( ); } bool node_builder::add_property( const std::string & key, const std::string & val ) { if ( !m_node ) return false; // if ( LEXER_LOUD ) // { // LOUT << node_depth( ) << " "; // for ( unsigned int i = 1; i < node_depth( ); i++ ) // lout << " "; // lout << "add_property(" << key << "," << val << ") [" << m_node->name( ) << "]" << endl; // } m_node->set( key, val ); return true; } bool node_builder::open_node( const std::string & classname, const std::string & name ) { typedef class_loader < S11N_NAMESPACE::Serializable > SerLoader; static SerLoader classLoader; ++m_node_count; m_node = ( m_nodestack.empty( )? NULL : m_nodestack.back( ) ); s11n_node * newnode = new s11n_node( ); if ( m_node ) { m_node->children( ).push_back( newnode ); } m_node = newnode; m_nodestack.push_back( m_node ); m_node->name( name ); m_node->impl_class( classname ); // if ( LEXER_LOUD ) // { // LOUT << node_depth( ) << " "; // for ( unsigned int i = 1; i < node_depth( ); i++ ) // lout << " "; // lout << "open_node(): new node [" << m_node->name( ) << "] [" << classname << "]" << endl; // } if ( 1 == node_depth( ) ) { m_root = m_node; m_toplist.push_back( m_node ); } return true; } bool node_builder::close_node( ) { if ( !m_node || m_nodestack.empty( ) ) { CERR << "close_node() error: called with an empty node stack!" << std::endl; assert( 0 /* close_node() error: called with an empty node stack! */ ); return false; } // if ( LEXER_LOUD ) // { // LOUT << node_depth( ) << " "; // for ( unsigned int i = 1; i < node_depth( ); i++ ) // lout << " "; // lout << "close_node() [" << m_node->impl_class( ) << "," << m_node->name( ) << "]" << endl; // } m_nodestack.pop_back( ); //LOUT << "last m_node=["<<*m_node<<"]" << endl; if ( m_nodestack.empty( ) ) { m_node = NULL; } else { m_node = m_nodestack.back( ); } return true; } node_builder::node_list_type & node_builder::root_nodes( ) { return m_toplist; } s11n_node *node_builder::root_node( ) { return m_root; } s11n_node * node_builder::current_node( ) { return m_node; } void node_builder::node_count( unsigned long c ) { this->m_node_count = c; } }; // namespace S11N_NAMESPACE --- NEW FILE: ns.node_builder.h --- #ifndef S11N_NAMESPACE_S11NNODEBUILDER_H_INCLUDED #define S11N_NAMESPACE_S11NNODEBUILDER_H_INCLUDED 1 // // Author: stephan beal <st...@s1...> // License: Public Domain // #include <deque> #include <cassert> #include <S11N_NAMESPACE/pointer_list.h> namespace S11N_NAMESPACE { class s11n_node; // forward decl /** node_builder is a helper class for building trees from deserialized data, designed particularly for use with lex/callback-based tree builders. It is experimental. Note that it owns all objects which build up it's tree. If you want them you must manually remove them from the container. You normally do not want them, however - they're mostly throwaway s11n_nodes on their way to becoming fully deserialized objects. This class only provides methods for building a tree, not for traversing it. Once you have built a tree, traverse it starting at the root_node(). */ class node_builder { public: typedef S11N_NAMESPACE::pointer_list < s11n_node > node_list_type; // note: i only use pointer_list because of it's memory // management. node_builder(); virtual ~ node_builder(); /** If auto_delete() is on (the default) then this object will delete it's children when it is destroyed. */ void auto_delete( bool b ); /** This is the getter for auto_delete( bool ). */ bool auto_delete(); /** Opens a new node, making that the current node. classname will be used for the node's impl_class() (see docs in s11n_node). name will be the object's name, which is important for de/serializing the node. It returns false on error, else true. The default implementation has no error conditions, and therefor always returns true. Node that classnames and node names need not be unique (nor make up unique combinations). Any number of nodes may have the same name or classname. */ virtual bool open_node( const std::string & classname, const std::string & nodename ); /** Closes the most-recently-opened node, effectively popping the previous node off of the node stack (it is not destroyed). It is an error, possibly fatal, to call this more often than calling open_node(). It returns false on error (e.g., called with no opened node). */ virtual bool close_node(); /** Adds an arbitrary property to the opened node. Note that you may not have more than one property of the same name - the one added last is the only one which exists. */ virtual bool add_property( const std::string & key, const std::string & val ); /** Returns the total number of nodes opened via open_node(). */ unsigned long node_count() const; /** Returns the current depth of opened nodes. */ unsigned long node_depth() const; /** Returns the list of all top-level nodes added via open_node(). Typically this is called after you are done using open_node() and close_node(), to collect any nodes added. More typically, this is called by a client to collect nodes which a lex-based parser added to this object. */ node_builder::node_list_type & root_nodes(); /** Returns the most recent root node parsed out of the input object. */ s11n_node *root_node(); /** Returns the current node. */ s11n_node * current_node(); // /** // experimental way to generically support comment blocks in parsers. // */ // void comment_mode( bool b ) { this->m_comment_mode = b; }; // bool comment_mode() const { return this->m_comment_mode; }; protected: /** Subclasses may use this to set the node count. */ void node_count( unsigned long c ); private: bool m_autodel; unsigned long m_node_count; // bool m_comment_mode; s11n_node * m_node; s11n_node * m_root; node_builder::node_list_type m_toplist; typedef std::deque < s11n_node * >node_stack; node_stack m_nodestack; }; }; // namespace S11N_NAMESPACE #endif // S11NNODEBUILDER_H_INCLUDE --- NEW FILE: ns.node_loader.cpp --- #include <S11N_NAMESPACE/serializer_loader.h> #include "node_loader.h" #include <iostream> #include <memory> // auto_ptr #include <S11N_NAMESPACE/Serializer.h> // #include <S11N_NAMESPACE/s11n_io.h> #include <S11N_NAMESPACE/debuggering_macros.h> // COUT/CERR #include <S11N_NAMESPACE/string_util.h> //trim_string() #include <S11N_NAMESPACE/file_util.h> //bytes_from_file() #include <S11N_NAMESPACE/serializer_loader.h> #include <S11N_NAMESPACE/s11n_node.h> #include <S11N_NAMESPACE/context_singleton.h> //#include <typeinfo> // debugging. namespace S11N_NAMESPACE { path_finder & node_loader::path() { return this->m_path; } const path_finder & node_loader::path() const { return this->m_path; } path_finder & node_loader::shared_path() { static path_finder bob; return bob; } s11n_node * node_loader::load_node( const std::string & key ) { return context_singleton<node_loader,node_loader>::instance().load( key ); } s11n_node * node_loader::load_node( std::istream & is ) { return context_singleton<node_loader,node_loader>::instance().load( is ); } s11n_node * node_loader::load( std::istream & is ) const { static serializer_loader bobTheLoader; char cookie[50]; is.getline( cookie, sizeof( cookie ) ); if( ! is.good() ) return NULL; std::auto_ptr<basic_serializer> ser = std::auto_ptr<basic_serializer>( bobTheLoader.load( cookie ) ); if( ! (ser.get()) ) { CERR << "Did not find Serializer for cookie ["<<cookie<<"]."<<std::endl; return NULL; } return ser->deserialize( is ); } s11n_node * node_loader::load( const std::string & key ) const { std::string path = this->path().find( key ); if( path.empty() ) path = shared_path().find( key ); if( path.empty() ) { CERR << "File '"<<key<<"' not found in path ["<<this->path()<<"]"<<std::endl; return NULL; } std::auto_ptr<std::istream> is = std::auto_ptr<std::istream>( S11N_NAMESPACE::get_istream( path ) ); if( !(is.get()) || (!is->good()) ) { CERR << "Error opening file ["<<path<<"]."<<std::endl; return NULL; } return load( *is ); } } // namespace --- NEW FILE: ns.node_loader.h --- #ifndef S11N_NAMESPACE_NODELOADER_H_INCLUDED #define S11N_NAMESPACE_NODELOADER_H_INCLUDED 1 // License: Public Domain // Author: st...@wa... #include <iostream> #include <S11N_NAMESPACE/class_loader.h> #include <S11N_NAMESPACE/path_finder.h> namespace S11N_NAMESPACE { class s11n_node; // forward decl /** node_loader is a convenience class for loading Serializables from files. It is similar to FlexTreeBuilder::loadBuilder(), but: - operates MUCH differently. - is extendable at runtime, so new parsers can be added/loaded dynamically. - it much simpler to use. sample usage: <pre> s11n_node * root = node_loader::load_node( infilename ); MySerializableType * foo = root->deserialize<MySerializableType>(); </pre> */ class node_loader { public: // typedef class_loader<s11n_node> ParentClass; node_loader(){}; ~node_loader(){}; /** Tries to load an s11n_node from the given filename, searching Both this->path() and node_loader::shared_path(). It auto-determines the file format. Returns null for a number of reasons, including: - file not found or inaccessible. - file found but no parser could be selected for it. - parser selected, but no root-level node was found. Ideally it will return a new s11n_node, which the caller takes ownership of. */ s11n_node * load( const std::string & key ) const; /** Looks at the first few bytes of the given stream and tries to find a Serializer for it. If it finds none it returns NULL. If it finds one it returns whatever that Serializer's deserialize() method returns. See S11N_NAMESPACE::basic_serializer and S11N_NAMESPACE::serializer_loader. */ s11n_node * load( std::istream & ) const; /** Convenience form of load(). */ static s11n_node * load_node( std::istream & ); /** Convenience form of load(). Uses shared_path() for file lookups. */ static s11n_node * load_node( const std::string & key ); /** A search path used by load(). */ const path_finder & path() const; /** A search path used by load(). */ path_finder & path(); /** A shared path used by all node_loader instances. It has a lower search priority than path() does. */ static path_finder & shared_path(); private: path_finder m_path; }; } // namespace #endif // S11N_NAMESPACE_NODELOADER_H_INCLUDED --- NEW FILE: ns.ParenSerializer.cpp --- #include <iostream> #include <string> #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/string_util.h> #include <S11N_NAMESPACE/Serializer.h> // maintenance note: this class is about 98% identical to FunTxt. i // need a way to combine these better. namespace S11N_NAMESPACE { ParenSerializer::ParenSerializer() { }; ParenSerializer::~ParenSerializer() { }; const basic_serializer::translation_map & ParenSerializer::translations() const { static ParenSerializer::translation_map bob; static bool donethat = false; if( (!donethat) && (donethat=true) ) { // The order of these escapes is signifant. // We only do double-backslashes to accomodate // the case that the final chars in a property // is a backslash (yes, this has happened, and // it hosed the data when sending it via a // format which uses \\\n to support multi-line // values). bob["\\"] = "\\\\"; bob[")"] = "\\)"; bob["("] = "\\("; // It is not strictly necessary to escape \(, // but we do so because Parens is intended to // be easy for hand-editing, and not escaping // them confuses emacs when we have escaped // closing parens. :) } return bob; } s11n_node * ParenSerializer::deserialize( std::istream & is ) { S11N_NAMESPACE::ParenTreeBuilder parser; return basic_serializer::deserialize( parser, is ); } bool ParenSerializer::serialize( const s11n_node & node, std::ostream & os ) const { if ( !basic_serializer::serialize( node, os ) ) return false; static const bool indention = true; static const std::string tab = (indention ? "\t" : ""); static unsigned int depth = 0; static const char Open = '('; static const char Close = ')'; ++depth; std::string nname = node.name(); std::string impl = node.impl_class(); std::string indent; for ( unsigned int i = 1; i < depth; i++ ) indent += tab; std::string indentChild = indent + tab; std::string indentProp = " "; // indent + tab; if ( 1 == depth ) { os << "(S11N_NAMESPACE::parens)\n"; } os << nname << "="<<Open<<impl; S11N_NAMESPACE::property_store::const_iterator it = node.property_store::begin(); S11N_NAMESPACE::property_store::const_iterator et = node.property_store::end(); std::string propval; //bool gotprops = ( it != et ); for ( ; it != et; ++it ) { propval = ( *it ).second; S11N_NAMESPACE::translate_entities( propval, this->translations(), false ); os << indentProp << Open <<( *it ).first << " " << propval << Close; } s11n_node::child_list_type::const_iterator cit = node.children().begin(); s11n_node::child_list_type::const_iterator cet = node.children().end(); bool ret = true; bool gotkids = (cit != cet); if( gotkids ) os << ( indention ? "\n" : " " ); for ( ; cit != cet; ++cit ) { os << indentChild; if ( !this->serialize( *( *cit ), os ) ) { ret = false; } } if( gotkids ) os << indent; os << ")"; os << (indention ? "\n" : " "); if( 1 == depth ) { if( ! indention ) os << std::endl; else os.flush(); } --depth; // maintenance: os must be flush()ed or the client may be forced to do it (endl does the same). return ret; } }; // namespace S11N_NAMESPACE --- NEW FILE: ns.S11n.cpp --- // // Author: stephan beal <st...@s1...> // License: Public Domain // #include "S11n.h" int classloader_registration_bogosity = 0; namespace S11N_NAMESPACE { }; // namespace S11N_NAMESPACE --- NEW FILE: ns.s11n_globals.cpp --- // // Author: stephan beal <st...@s1...> // License: Public Domain // #include <string> #if HAVE_CONFIG_H # include "config.h" // S11N_LIBRARY_VERSION #endif #ifndef S11N_LIBRARY_VERSION # error S11N_LIBRARY_VERSION must be set! #endif #include <S11N_NAMESPACE/s11n_globals.h> namespace S11N_NAMESPACE { std::string library_version() { return std::string(S11N_LIBRARY_VERSION); } } // namespace S11N_NAMESPACE --- NEW FILE: ns.s11n_globals.h --- // // Author: stephan beal <st...@s1...> // License: Public Domain // #ifndef S11N_NAMESPACE_S11N_GLOBALS_H_INCLUDED #define S11N_NAMESPACE_S11N_GLOBALS_H_INCLUDED 1 #include <string> #include <iostream> #include <memory> // auto_ptr // #include <S11N_NAMESPACE/class_loader.h> #include <S11N_NAMESPACE/instantiator.h> #include <S11N_NAMESPACE/s11n_node.h> #include <S11N_NAMESPACE/serializer_loader.h> #include <S11N_NAMESPACE/node_loader.h> // utility functions for client code. namespace S11N_NAMESPACE { /** Returns a string containing this library's version number. */ std::string library_version(); /** UNTESTED. Tries to deserialize a SerializableT from the input stream. Returns a new object on success and NULL on error. The caller owns the returned pointer. */ template <typename SerializableT> static SerializableT * load_serializable( std::istream & istr ) { static node_loader bob; std::auto_ptr<s11n_node> node = std::auto_ptr<s11n_node>( bob.load( istr ) ); if( ! (node.get()) ) { return NULL; } return node->s11n_node::deserialize<SerializableT>(); } /** UNTESTED. Tries to deserialize a SerializableT from the input stream. Returns a new object on success and NULL on error. The caller owns the returned pointer. */ template <typename SerializableT> static SerializableT * load_serializable( const std::string & file ) { std::auto_ptr<std::istream> istr = std::auto_ptr<std::istream>( get_istream( file ) ); if( ! (istr.get()) ) return NULL; return load_serializable<SerializableT>( *istr ); } } // namespace #endif // S11N_NAMESPACE_S11N_GLOBALS_H_INCLUDED --- NEW FILE: ns.S11n.h --- // Author: stephan beal <st...@s1...> // License: Public Domain #ifndef S11N_NAMESPACE_S11N_H_INCLUDED #define S11N_NAMESPACE_S11N_H_INCLUDED 1 // please don't use this header - it's being phased out. // #include <S11N_NAMESPACE/s11n_node.h> // #include <S11N_NAMESPACE/Serializable.h> // #include <S11N_NAMESPACE/serializable_adapter.h> /** The s11n serialization (s11n) framework is an object serialization framework modelled heavily off work by Rusty Ballinger (bo...@us... http://libfunutil.sourceforge.net). As far as i know Rusty was the one to coin the phrase "s11n" (short for "serialization", in the same way that i18n is short for internationalization). In addition to the class documentation, please see the library manual, available in the source tree, in the docs subdir. The most important classes for clients are: - s11n_node (and it's parent, S11N_NAMESPACE::property_store) - basic_serializer - node_loader */ namespace S11N_NAMESPACE { }; #endif // S11N_NAMESPACE_S11N_H_INCLUDED --- NEW FILE: ns.s11n_io.cpp --- // // Author: stephan beal <st...@s1...> // License: Public Domain // #include <iostream> #include <string> //#include <S11N_NAMESPACE/s11n-macros.h> // COUT/CERR macros #include <S11N_NAMESPACE/class_loader.h> #include <S11N_NAMESPACE/instantiator.h> // object_factory #include <S11N_NAMESPACE/flex_lexers.h> #include <S11N_NAMESPACE/string_util.h> // escape_string() #include <S11N_NAMESPACE/s11n_io.h> #include <S11N_NAMESPACE/s11n-macros.h> // COUT/CERR, for debugging only. // namespace S11N_NAMESPACE // { // };// namespace S11N_NAMESPACE --- NEW FILE: ns.s11n_io.h --- #ifndef S11N_NAMESPACE_S11NIO_H_INCLUDED #define S11N_NAMESPACE_S11NIO_H_INCLUDED 1 // // Author: stephan beal <st...@s1...> // License: Public Domain // This file defines interfaces for saving/loading s11n_node and // Serializable objects. // #include <sstream> #include <S11N_NAMESPACE/s11n_node.h> // #if HAVE_CONFIG_H // # include "config.h" // #endif #include <S11N_NAMESPACE/file_util.h> // get_ostream(), get_istream() #include <S11N_NAMESPACE/Serializer.h> namespace S11N_NAMESPACE { /** DefaultS11nType is a typedef for default saver/loader type used by s11n_io for de/serializing from/to iostreams. It must be an S11N_NAMESPACE::Serializer type. */ typedef S11N_NAMESPACE::FunXMLSerializer DefaultS11nType; /** s11n_io is a convenience (ha ha) class for saving/loading s11n_nodes and Serializables. The templatized parameter, SerializerT, must be a subtype of S11N_NAMESPACE::Serializer. A note about the static functions: whether they should be static or not is mainly a maintenance-related question. i feel that client code is more maintainable, via using typedefs and/or shared objects, than via having to create these objects each time they are needed. A prime consideration is the ease of switching an app's or framework's default serialization type: <pre> typedef SimpleXMLSerializer SerT; typedef s11n_io<SerT> SaveLoad; ... SaveLoad::save( ... ); </pre> Loading without knowing the input format beforehand is unfortunately significantly more painful. See S11N_NAMESPACE::node_loader for a utility class which can do that. It (indirectly) uses S11N_NAMESPACE::compression_policy() to determine whether to write non/compressed files, so set any preference via that function. */ template < typename SerializerT = DefaultS11nType > class s11n_io { /** Convenience typedef */ typedef s11n_io<SerializerT> ThisType; public: /** This type of Serializer this class uses. */ typedef SerializerT serializer_type; /** Saves node to the given output stream. Returns false on error, which almost invariably means that the output stream could not be written to. */ static bool save( const s11n_node & node, std::ostream & os ) { serializer_type bob; return bob.serialize( node, os ); } /** As save( node, ostream ), but saves to the given file. Returns false on error, which normally indicates a file/stream-level error. S11N_NAMESPACE::compression_policy() is honored. */ static bool save( const s11n_node & node, const std::string & filename ) { std::ostream * fs = 0; fs = S11N_NAMESPACE::get_ostream( filename ); bool b = save( node, *fs ); delete( fs ); return b; } /** Creates an s11n_node named nodename, serializes ser into it and saves that to the given filename. See save( s11n_node, string ) for info about gzip support. */ template <typename serializable_type> static bool save( const std::string & nodename, const serializable_type & ser, const std::string & filename ) { s11n_node node; node.name( nodename ); if( ! node.serialize( ser ) ) return false; return save( node, filename ); } /** Creates an s11n_node named nodename, serializes ser into it and saves that to the given ostream. */ template <typename serializable_type> static bool save( const std::string & nodename, const serializable_type & ser, std::ostream & os ) { s11n_node node; node.name( nodename ); if( ! node.serialize( ser ) ) return false; return save( node, os ); } /** Tries to load an s11n_node from the given input stream. It returns a pointer to the object, which may be null. The caller owns the returned pointer. */ static s11n_node *load( std::istream & is ) { serializer_type bob; s11n_node *node = NULL; node = bob.deserialize( is ); return node; } /** Tries to load an s11n_node from the given file. It returns a pointer to the object, which may be null (indicating either a file-level error, parse error, or just about anything else). The caller owns the returned pointer. */ static s11n_node *load( const std::string & filename ) { std::istream * fs = 0; fs = S11N_NAMESPACE::get_istream( filename ); if( ! fs->good() ) { delete( fs ); return NULL; } s11n_node * n = load( *fs ); delete( fs ); return n; } /** This is a genuine lossy shortcut: it grabs the first s11n_node from filename and abandons the rest. It ignores the node's name, which may or may not be significant for your code (it's not, generally speaking, since you apparently know the type of the file's data). If a SerT cannot be deserialized out of the given file then NULL is returned, otherwise a pointer is returned, which the caller takes ownership of. */ template < typename SerT > static SerT * load_deserialize( const std::string & filename ) { s11n_node *node = load( filename ); if ( !node ) return NULL; SerT * ch = node->s11n_node::deserialize<SerT>(); delete( node ); return ch; } }; } // namespace S11N_NAMESPACE #endif // S11N_NAMESPACE_S11NIO_H_INCLUDED --- NEW FILE: ns.s11n-macros.h --- // // Author: stephan beal <st...@s1...> // License: Public Domain // #ifndef S11N_MACROS_H #define S11N_MACROS_H #include <iostream> #ifndef CERR #define CERR std::cerr << __FILE__ << ":" << std::dec << __LINE__ << " : " #define CERRL(A) CERR << A << std::endl; #endif #ifndef COUT #define COUT std::cout << __FILE__ << ":" << std::dec << __LINE__ << " : " #define COUTL(A) COUT << A << std::endl; #endif #include <cassert> #define BROKEN(A) assert( 0 /* broken code: A */ ) #endif // S11N_MACROS_H --- NEW FILE: ns.s11n_node.cpp --- // #include <S11N_NAMESPACE/S11ndll_loader.h> // default classloader type #include "s11n_node.h" namespace S11N_NAMESPACE { #define NODE_IMPL_CLASS "S11N_NAMESPACE::s11n_node" s11n_node::s11n_node( const std::string & name ) : m_name(name),m_iname(NODE_IMPL_CLASS) { } s11n_node::s11n_node( const std::string & name, const std::string implclass ) : m_name( name ), m_iname( implclass ) { } s11n_node::s11n_node() : m_name("s11n_node"), m_iname(NODE_IMPL_CLASS) { } bool s11n_node::take_child( const s11n_node * ch ) { child_list_type::iterator it = this->children().begin(); child_list_type::iterator et = this->children().end(); bool got = false; for( ; it != et; ++it ) { if( (*it) != ch ) continue; this->children().erase( it ); got = true; break; } return got; } s11n_node::~s11n_node() { m_babysitter.delete_all(); // we use this in lieu of setting m_babysitter.auto_delete( true ) in the ctor } s11n_node::child_list_type & s11n_node::children() { return this->m_babysitter; } const s11n_node::child_list_type & s11n_node::children() const { return this->m_babysitter; } void s11n_node::reset() { this->m_babysitter.delete_all(); this->clear_properties(); } void s11n_node::impl_class( const std::string & n ) { this->m_iname = n; } std::string s11n_node::impl_class()const { return this->m_iname; } void s11n_node::name( const std::string & n ) { this->m_name = n; } std::string s11n_node::name() const { return this->m_name; } unsigned int s11n_node::serialize_properties( const property_store & props ) { return this->property_store::merge( props ); } unsigned int s11n_node::deserialize_properties( property_store & p ) const { return p.merge( *this ); } int m_s11n_node_debug_level = 0; void s11n_node::debug_level( int dlevel ) { m_s11n_node_debug_level = dlevel; } int s11n_node::debug_level() { return m_s11n_node_debug_level; } }; // namespace S11N_NAMESPACE --- NEW FILE: ns.s11n_node.h --- // s11n_node.h // License: Public Domain // Author: st...@wa... #ifndef S11N_NAMESPACE_NODE_H_INCLUDED #define S11N_NAMESPACE_NODE_H_INCLUDED #include <string> #include <S11N_NAMESPACE/property_store.h> #include <S11N_NAMESPACE/pointer_list.h> #include <S11N_NAMESPACE/dll_loader.h> #include <S11N_NAMESPACE/to_string.h> // to/from_string() #include <S11N_NAMESPACE/debuggering_macros.h> // COUT/CERR #include <S11N_NAMESPACE/serializable_adapter.h> namespace S11N_NAMESPACE { /** s11n_node makes up the core of the s11n framework. Please see the library manual for complete details. The inherited property_store interface makes up a large portion of this class' functionality, so please refer to that class after you have absorbed every last word of this one's documentation. */ class s11n_node : public S11N_NAMESPACE::property_store { public: /** A convenience typedef. */ typedef S11N_NAMESPACE::pointer_list<s11n_node> babysitter_type; /** The container type used to store this object's children. */ typedef babysitter_type child_list_type; /** Creates a new node with an empty name() and an impl_class() of "S11N_NAMESPACE::s11n_node". */ s11n_node(); /** Creates a new node with the given name() and an impl_class() of "S11N_NAMESPACE::s11n_node". */ explicit s11n_node( const std::string & name ); /** Creates a new node with the given name() and and impl_class(). */ s11n_node( const std::string & name, const std::string implclass ); /** This is primarily virtual because of the class' parentage, not because you should subclass this type. */ virtual ~s11n_node(); /** Returns a list of the s11n_node children of this object. The caller should not delete any pointers from this list unless he also removes the pointers from the list, or else they will get double-deleted later. In practice it is (almost) never necessary for client code to work with this list. */ child_list_type & children(); /** A const form of children(). */ const child_list_type & children() const; /** Completely Untested. Removes the given child from this object's list. The caller takes ownership of it. Returns true if this object contained the pointer, otherwise false. */ bool take_child( const s11n_node * ); /** Removes all properties and serialized children from this object. Any pointers to children of this object become invalided (they get deleted) by a call to this function. Since client code doesn't normally hold pointers to s11n_node<> pointers this should not be a practical problem. */ void reset(); /** Returns all children() with a name() matching the given string. The results go into the given container, which must support push_back( const s11n_node * ). The caller does NOT own the child pointers: they are still owned by this object. It returns the number of children added to the container. Complexity: basically linear, based on the number of children in this object and how many have the name nodename (more matches requires more insertions into the target container). */ template < typename ContainerType > unsigned long children( const std::string & nodename, ContainerType & ctr ) const { s11n_node *ch = 0; s11n_node::child_list_type::const_iterator cit = this->children().begin(); s11n_node::child_list_type::const_iterator cet = this->children().end(); unsigned long count = 0; for ( ; cit != cet; ++cit ) { ch = ( *cit ); if ( ch->name() == nodename ) { ++count; ctr.push_back( ch ); } } return count; } /** Returns the first child node with the given node name, or NULL. The caller does not own the pointer. */ const s11n_node * child( const std::string & nodename ) const { s11n_node *ch = 0; s11n_node::child_list_type::const_iterator cit = this->children().begin(); s11n_node::child_list_type::const_iterator cet = this->children().end(); for ( ; cit != cet; ++cit ) { if ( ( *cit )->name() == nodename ) { ch = ( *cit ); break; } } return ch; } /** Defines the class name which should be used as the implementation for the node when it is deserialize()d. You normally needn't set this directly: it is set internally during serialize() and fetched as needed by deserialize(). There are special cases where it must be set by client code. "You will know when the time comes." See the library manual for full details. */ void impl_class( const std::string & n ); /** Returns the implementation class name set via impl_class(). */ std::string impl_class() const; /** The name which should be used as the key for storing the node. This is normally translated to something like an XML element name (e.g., <name>), and should not contain spaces or other characters which may not be usable as key names. To be safe, stick to alphanumeric and underscores, starting with a letter or underscore. (This class does no enforce any naming conventions, but your data file parsers certainly will.) */ void name( const std::string & n ); /** Returns this node's name, as set via name(string). */ std::string name() const; /** Sets a debugging level. Currently only 1 and 0 are supported. */ static void debug_level( int dlevel ); /** Returns the current debugging level. */ static int debug_level(); #define NODEDEBUG if( debug_level() ) CERR /** Returns the current classloader for the given SerializableType. */ template <class SerializableType> static class_loader<SerializableType> & classloader() { return context_singleton< dll_loader<SerializableType>, s11n_node >::instance(); } /** Tries to create a new object of the type named in this->impl_class(). If that class cannot be loaded by class_loader<SerializableType> then NULL is returned. It next tries to deserialize() the new object, passing it (*this). If that fails, the new child is deleted and NULL is returned. If all else goes peachy, a (SerializableType *) is returned, which the caller takes ownership of. */ template <class SerializableType> SerializableType * deserialize() const { const std::string classname = this->impl_class(); SerializableType *tgt = 0; tgt = this->classloader<SerializableType>().load( classname ); NODEDEBUG << "deserialize() impl=["<<classname<<"] name=["<<this->name()<<"] classloaded=["<<std::hex<<tgt<<"]"<<std::endl; if ( !tgt ) { NODEDEBUG << "could not instantiate node '" << this->name() << "' from class '"<< classname << "'. It is probably not registered with the classloader." << std::endl; return tgt; } if ( ! serializable_adapter<SerializableType>::deserialize( *tgt, *this ) ) { NODEDEBUG << "tgt->deserialize() failed. Deleting tgt. impl_class="<< classname << ", nodename=" << this->name() << std::endl; delete( tgt ); tgt = NULL; } return tgt; } /** Serializes ser into a subnode of this node, named nodename and gives it to ser for serialization. If that fails, nothing happens and false is returned. If it succeeds, it adds the new child node to this object and returns true. */ template <class SerializableType> bool serialize( const std::string & nodename, const SerializableType & ser ) { s11n_node *node = new s11n_node(); node->name( nodename ); typedef serializable_adapter<SerializableType> Adapter; // std::string classname = Adapter::impl_class(); // node->impl_class( Adapter::impl_class() ); NODEDEBUG << "serialize(" << nodename << " , " <<std::hex << &ser << ") typeid=["<<typeid(ser).name()<<"] impl_class="<<node->impl_class() << std::endl; if ( !Adapter::serialize( ser, *node ) ) { NODEDEBUG << "serialize(" << nodename << " , " <<std::hex << &ser << ") failed!" << std::endl; delete( node ); return false; } this->children().push_back( node ); return true; } /** Effectively calls: <pre> ser.serialize( node ); </pre> But it uses the API mapping provided by serializable_adapter<SerializableType>::serialize(). */ template <class SerializableType> bool serialize( const SerializableType & ser ) { typedef serializable_adapter<SerializableType> Adapter; return Adapter::serialize( ser, *this ); } /** Convenience function. Copies prop's properties into this object. Returns the number of properties copied. */ unsigned int serialize_properties( const property_store & props ); /** Convenience function. Copies this object's properties to p. Returns the number of properties copied. */ unsigned int deserialize_properties( property_store & p ) const; /** Serializes the given STL map into a sub-node of this object. Returns the number of properties gleened from the map. No child node is created if this function returns zero (i.e., if map is empty). Assumptions: - map conforms to std::map conventions. - both the key and value types of the map support the istream>>/ostream<< operators. - neither key nor value types may be pointer types. - keys must be suitable for use as property keys in data files, otherwisethey may not be readable by all parsers. A prime example of a dubious choice is doubles, since 3.000 is not a valid key for some formats (e.g., XML). Note that the new sub-node is not actually deserialize()able - it is an s11n_node which simply contains properties. It can be retrieved with deserialize_map() or by manually iterating over it's properties. */ template <typename ContainerType> unsigned long serialize_map( const std::string & nodename, const ContainerType & map ) { if( 0 == map.size() ) return 0; unsigned long ret = 0; typedef typename ContainerType::const_iterator CIT; CIT it = map.begin(); CIT et = map.end(); if( it == et ) return ret; s11n_node * node = new s11n_node(); node->name(nodename); for( ; it != et; ++it ) { node->set( S11N_NAMESPACE::to_string( (*it).first ), (*it).second ); ++ret; } if( 0 == ret ) delete( node ); else this->children().push_back( node ); return ret; } /** Deserializes a map which has been serialized using serialize_map(). Returns the number of objects retrieved from the map. See serialize_map() for a description of the requirements for ContainerType. In addition: - map must have typedefs for value_type, key_type and mapped_type. Some STL docs refer to mapped_type as ... [truncated message content] |
From: <sg...@us...> - 2003-11-17 20:28:07
|
Update of /cvsroot/libfunutil/libfunutil/lib/cl In directory sc8-pr-cvs1:/tmp/cvs-serv27538/lib/cl Modified Files: Makefile Log Message: added *.o to CLEAN_FILES. Index: Makefile =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/lib/cl/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Makefile 17 Nov 2003 20:18:55 -0000 1.1 +++ Makefile 17 Nov 2003 20:27:43 -0000 1.2 @@ -39,7 +39,7 @@ HEADERS = \ $(patsubst ns.%,%,$(NS_HEADERS)) -CLEAN_FILES += $(SOURCES) $(HEADERS) +CLEAN_FILES += $(SOURCES) $(HEADERS) *.o NAMESPACE = $(CL_NAMESPACE) |
From: <sg...@us...> - 2003-11-17 20:27:37
|
Update of /cvsroot/libfunutil/libfunutil In directory sc8-pr-cvs1:/tmp/cvs-serv27488 Modified Files: configure.libfunutil configure.s11n toc.s11n.make.at toc_shared.make.at Log Message: adjusted to accomodate s11n-related refactoring. Index: configure.libfunutil =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/configure.libfunutil,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- configure.libfunutil 14 Oct 2003 03:43:25 -0000 1.21 +++ configure.libfunutil 17 Nov 2003 20:27:18 -0000 1.22 @@ -1,5 +1,10 @@ +#!/do/not/bash +# ^^^^ to help out emacs + # package-specific configure script for libfunutil +toc_run_failok check_dist_md5s + # toc_run_failok buildtool toc_add_config PACKAGE_COPYRIGHT="GNU General Public License, version 2. Copyright (c) 2000-2003 Rusty Ballinger (bo...@so...) and stephan beal (sg...@us...)." @@ -13,6 +18,7 @@ toc_run_fail gnu_cpp_tools toc_run_failok readline toc_run_failok zlib +toc_run_failok bzlib toc_add_config_h PACKAGE_EMAIL_ADDRESS=lib...@li... PACKAGE_URL=http://libfunutil.sourceforge.net/ @@ -26,6 +32,7 @@ toc_add_make configure_enable_cppdeps=1 toc_run_failok doxygen +toc_run_failok lyxport configure_with_qt=${configure_with_qt-1} @@ -51,7 +58,7 @@ toc_add_make FUN_API_QSTRING="$FUN_API_QSTRING" toc_add_make FUN_API_STD_STRING="$FUN_API_STD_STRING" -configure_developer_script=configure.$USER +configure_developer_script=configure.user.$USER test -f ${configure_developer_script} && { toc_boldecho "Running $USER's tests..." source ${configure_developer_script} || toc_die $? "${configure_developer_script} failed" @@ -67,6 +74,8 @@ echo ============================================================== echo "${PACKAGE_NAME} configuration checks completed." echo ============================================================== -# toc_run_fail toc_project_makefile + +toc_run_fail toc_project_makefile + return 0 Index: configure.s11n =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/configure.s11n,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- configure.s11n 14 Oct 2003 03:19:32 -0000 1.2 +++ configure.s11n 17 Nov 2003 20:27:18 -0000 1.3 @@ -1,11 +1,21 @@ - +#!/do/not/bash echo "==================== s11n-specific checks:" -toc_run_fail gcc_try_compile toc/tests/cpp/check_stl_newstyle.cpp -toc_run_fail gcc_try_compile toc/tests/cpp/gcc_2_95_typename_problem.cpp -toc_run_fail gcc_build_and_run toc/tests/c/check_for_dlopen_and_friends.c -export-dynamic -ldl -toc_run_fail flex toc_run_failok bzlib toc_run_failok lyxport -toc_atfilter_as_makefile toc.s11n.make.at toc.s11n.make + +toc_run_fail gcc_try_compile toc/tests/cpp/check_stl_newstyle.cpp +toc_run_fail gcc_try_compile toc/tests/cpp/gcc_2_95_typename_problem.cpp +toc_run_fail libltdl +toc_run_fail flex + + + +toc_add_config CL_NAMESPACE=fun +toc_add_config TOOLBOX_NAMESPACE=fun +toc_add_config S11N_NAMESPACE=fun +xtramakes="s11n" +for M in ${xtramakes}; do + toc_run_fail toc_project_makefile toc.$M.make +done Index: toc.s11n.make.at =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/toc.s11n.make.at,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- toc.s11n.make.at 14 Oct 2003 03:11:54 -0000 1.1 +++ toc.s11n.make.at 17 Nov 2003 20:27:18 -0000 1.2 @@ -1,14 +1,22 @@ #!/do/not/make -#^^^ only to help emacs out - -CLEAN_FILES += $(wildcard *.o *~) - +#^^^ only to help emacs out. -FLEX = @FLEX@ -configure_enable_zlib = @HAVE_ZLIB@ -configure_enable_bzlib = @HAVE_BZLIB@ +################# from libltdl test: +HAVE_LIBLTDL = @HAVE_LIBLTDL@ +HAVE_LIBDL = @HAVE_LIBDL@ +LDADD_LIBDL = @LDADD_LIBDL@ +LDADD_LIBLTDL = @LDADD_LIBLTDL@ +ifeq (1,$(HAVE_LIBLTDL)) + L_DL = -lltdl +else + L_DL = -ldl +endif +################ -S11N_LIBDIR = $(top_srcdir)/lib/s11n +################ s11n: +S11N_NAMESPACE = @S11N_NAMESPACE@ +TOOLBOX_NAMESPACE = @TOOLBOX_NAMESPACE@ +S11N_LIBDIR = $(top_srcdir)/lib S11N_LIB_A = $(S11N_LIBDIR)/libs11n.a $(S11N_LIB_A): ${MAKE} -C $(S11N_LIBDIR) @@ -16,7 +24,7 @@ $(S11N_LIB_SO): ${MAKE} -C $(S11N_LIBDIR) L_S11N = -L$(S11N_LIBDIR) -ls11n -S11N_CLIENT_LDADD = -export-dynamic $(L_S11N) -ldl +S11N_CLIENT_LDADD = $(L_S11N) $(LIBCL_CLIENT_LDADD) ifeq (1,$(configure_enable_zlib)) S11N_CLIENT_LDADD += -lz endif @@ -25,12 +33,15 @@ endif -configure_with_lyxport = @configure_with_lyxport@ -ifeq (1,$(configure_with_lyxport)) - # these flags are used by toc/make/lyxport.make - LYXPORT_L2HARGS = -nonavigation -show_section_numbers -split 0 -noimages - LYXPORT_ARGS = -c -tt - LYXPORT_ARGS += --html --opts_l2h '$(LYXPORT_L2HARGS)' - LYXPORT_ARGS += --ps --pdf - LYXPORT_BIN = @LYXPORT_BIN@ -endif +############################# libclass_loader: +CL_NAMESPACE = @CL_NAMESPACE@ +LIBCL_LIBNAME = $(CL_NAMESPACE)_class_loader +LIBCL_LIBDIR = $(top_srcdir)/lib/cl +LIBCL_LIB_A = $(LIBCL_LIBDIR)/lib$(LIBCL_LIBNAME).a +$(LIBCL_LIB_A): + ${MAKE} -C $(LIBCL_LIBDIR) +LIBCL_LIB_SO = $(LIBCL_LIBDIR)/lib$(LIBCL_LIBNAME).so +$(LIBCL_LIB_SO): + ${MAKE} -C $(LIBCL_LIBDIR) +L_CL = -L$(LIBCL_LIBDIR) -l$(LIBCL_LIBNAME) +LIBCL_CLIENT_LDADD = -export-dynamic $(L_DL) $(L_CL) Index: toc_shared.make.at =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/toc_shared.make.at,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- toc_shared.make.at 14 Oct 2003 03:11:17 -0000 1.24 +++ toc_shared.make.at 17 Nov 2003 20:27:18 -0000 1.25 @@ -118,16 +118,6 @@ DIST_FILES += Makefile -configure_enable_zlib = @HAVE_ZLIB@ -configure_enable_s11n = @configure_enable_s11n@ -configure_build_quietly = @configure_build_quietly@ - -configure_with_libreadline = @configure_with_libreadline@ -ifeq ($(configure_with_libreadline),1) - LIBREADLINE_LDADD = @LIBREADLINE_LDADD@ -endif - -include $(top_srcdir)/toc.s11n.make include $(toc_makesdir)/toc_mainincludes.make include $(toc_makesdir)/tests.make |
From: <sg...@us...> - 2003-11-17 20:26:35
|
Update of /cvsroot/libfunutil/libfunutil/lib In directory sc8-pr-cvs1:/tmp/cvs-serv27233/lib Modified Files: Makefile Log Message: added cl subdir if s11n enabled. Index: Makefile =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/lib/Makefile,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- Makefile 14 Oct 2003 20:41:56 -0000 1.7 +++ Makefile 17 Nov 2003 20:26:12 -0000 1.8 @@ -2,7 +2,7 @@ ifeq (1,$(configure_enable_s11n)) -SUBDIRS += toolbox s11n +SUBDIRS += cl toolbox s11n endif SUBDIRS += funUtil |
Update of /cvsroot/libfunutil/libfunutil/lib/cl In directory sc8-pr-cvs1:/tmp/cvs-serv25688/lib/cl Added Files: LoadableClass.cpp LoadableClass.h LoadableSubClass.cpp Makefile ns.class_loader.cpp ns.class_loader.h ns.classname_transformer.h ns.cl_demo.cpp ns.context_singleton.h ns.debuggering_macros.h ns.dll_loader.h ns.instantiator.h ns.path_finder.cpp ns.path_finder.h Log Message: egg --- NEW FILE: LoadableClass.cpp --- #include "LoadableClass.h" --- NEW FILE: LoadableClass.h --- #ifndef LOADABLECLASS_H_INCLUDED #define LOADABLECLASS_H_INCLUDED 1 // License: Public Domain // Author: st...@wa... #include "class_loader.h" #include "debuggering_macros.h" /** A base class for testing and demonstrating dll_loader. */ class LoadableClass { public: LoadableClass() { CERR << "LoadableClass()"<<std::endl; } virtual ~LoadableClass() { CERR << "~LoadableClass()"<<std::endl; } }; CLASSLOADER_REGISTER(LoadableClass,LoadableClass); #endif // LOADABLECLASS_H_INCLUDED --- NEW FILE: LoadableSubClass.cpp --- // License: Public Domain // Author: st...@wa... #include "class_loader.h" #include "debuggering_macros.h" #include "LoadableClass.h" /** A class for demonstrating dll_loader, intended to be compiled to a standalone DLL. */ class LoadableSubClass : public LoadableClass { public: LoadableSubClass() { CERR << "LoadableSubClass()"<<std::endl; } virtual ~LoadableSubClass() { CERR << "~LoadableSubClass()"<<std::endl; } }; CLASSLOADER_REGISTER(LoadableClass,LoadableSubClass); CLASSLOADER_REGISTER4(LoadableClass,LoadableSubClass,int,7); --- NEW FILE: Makefile --- include toc.make # maintenance notes: # expected via toc.make: # $(CL_NAMESPACE) # $(LIBCL_LIBNAME) # $(LIBCL_VERSION) # $(LIBCL_CLIENT_LDADD) CL_NAMESPACE ?= cl LIBCL_VERSION ?= $(PACKAGE_VERSION) LIBCL_LIBNAME ?= $(CL_NAMESPACE)_class_loader NS_SOURCES = ns.class_loader.cpp \ ns.path_finder.cpp \ ns.cl_demo.cpp # ns.classname_transformer.cpp NS_HEADERS = \ ns.class_loader.h \ ns.classname_transformer.h \ ns.context_singleton.h \ ns.dll_loader.h \ ns.instantiator.h \ ns.path_finder.h \ ns.debuggering_macros.h DIST_FILES += $(NS_SOURCES) $(NS_HEADERS) # Be careful with SOURCES/HEADERS, lest they be cleaned up when you don't # want them to be. Simplest is to put everything into NS_{HEADERS/SOURCES} and expect # them to be filtered by sed. SOURCES = \ $(patsubst ns.%,%,$(NS_SOURCES)) HEADERS = \ $(patsubst ns.%,%,$(NS_HEADERS)) CLEAN_FILES += $(SOURCES) $(HEADERS) NAMESPACE = $(CL_NAMESPACE) NAMESPACE_TOKEN = CL_NAMESPACE NAMESPACE_PREFIX = ns. NAMESPACE_FILTERED_FILES = $(SOURCES) $(HEADERS) include $(toc_makesdir)/NAMESPACE.make INSTALL_PACKAGE_HEADERS_DEST = $(prefix)/include/$(CL_NAMESPACE) INSTALL_PACKAGE_HEADERS = $(HEADERS) SYMLINK_HEADERS = $(INSTALL_PACKAGE_HEADERS) SYMLINK_HEADERS_DEST = $(top_srcdir)/include/$(CL_NAMESPACE) include $(toc_makesdir)/symlink_headers.make OBJECTS = $(addsuffix .o,class_loader path_finder) # DIST_FILES += LoadableClass.cpp LoadableClass.h LoadableSubClass.cpp SHARED_LIBS = lib$(LIBCL_LIBNAME) LoadableSubClass STATIC_LIBS = lib$(LIBCL_LIBNAME) lib$(LIBCL_LIBNAME)_so_OBJECTS = class_loader.o path_finder.o lib$(LIBCL_LIBNAME)_a_OBJECTS = $(lib$(LIBCL_LIBNAME)_so_OBJECTS) lib$(LIBCL_LIBNAME)_so_VERSION = $(LIBCL_VERSION) # LoadableClass_so_OBJECTS = LoadableClass.o # LoadableClass_so_LDADD = $(LIBCL_CLIENT_LDADD) LoadableSubClass_so_OBJECTS = LoadableSubClass.o LoadableSubClass_so_LDADD = $(LIBCL_CLIENT_LDADD) DIST_FILES += LoadableSubClass.cpp LoadableClass.h LoadableClass.cpp include $(toc_makesdir)/SHARED_LIBS.make include $(toc_makesdir)/STATIC_LIBS.make INSTALL_LIBEXECS = lib$(LIBCL_LIBNAME).so.$(lib$(LIBCL_LIBNAME)_so_VERSION) # ^^^ re-set the list to remove Loadable*.*, which are automatically added by SHARED_LIBS BIN_PROGRAMS = test_cl test_cl_bin_OBJECTS = cl_demo.o LoadableClass.o cl_demo_cpp_CPPFLAGS += -DCLASSLOADER_DEBUG=1 test_cl_bin_LDADD = $(LIBCL_CLIENT_LDADD) include $(toc_makesdir)/BIN_PROGRAMS.make INSTALL_BINS = # ^^^ we don't want cl_demo installed, and BIN_PROGRAMS does that by default all: $(SOURCES) $(HEADERS) symlink-headers deps $(OBJECTS) SHARED_LIBS STATIC_LIBS BIN_PROGRAMS @echo "When running the test_cl binary be sure to set your LD_LIBRARY_PATH to include ${PWD}!" @echo "Running the 'test' target does this for you." # $(ENM_NAMESFILE) RUNTEST = LD_LIBRARY_PATH=${PWD} ./test_cl # demonstrate a failed lookup for a DLL: faildll: mv LoadableSubClass.so tmp.foo -$(RUNTEST) mv tmp.foo LoadableSubClass.so # demo app: test-.: $(RUNTEST) test: test-. # for compatibility with toc's tests.make :/ --- NEW FILE: ns.class_loader.cpp --- #include <map> #include <typeinfo> #include <stdlib.h> // getenv() #if HAVE_CONFIG_H # include "config.h" // might have CLASS_LOADER_DEFAULT_PATH #endif #include "class_loader.h" #ifdef HAVE_LTDL // prefer libltdl, but if it's not available... # include <ltdl.h> #else // use libdl instead: # include <dlfcn.h> #endif // Clients may define CLASS_LOADER_DEFAULT_PATH when compiling. Be sure to escape the quotes: // -DCLASS_LOADER_DEFAULT_PATH=\"/some/path:/another/path\" #ifndef CLASS_LOADER_DEFAULT_PATH # define CLASS_LOADER_DEFAULT_PATH "." #endif #define CLASS_LOADER_PATH CLASS_LOADER_DEFAULT_PATH namespace CL_NAMESPACE { int m_CL_debug_level = CLASSLOADER_DEBUG; int class_loader_debug_level() { return m_CL_debug_level; } void class_loader_debug_level( int dlevel ) { m_CL_debug_level = dlevel; } std::string open_dll( const std::string & basename, const path_finder & finder ) { static bool donethat = false; if( !donethat ) { // About these dlopen(0) calls: // They are here for client-side convenience, to open the main() app. // In theory, that really isn't necessary any more, but that needs // to be tested. donethat = true; #if HAVE_LTDL lt_dlinit(); lt_dlopen( 0 ); #else dlopen( 0, RTLD_NOW | RTLD_GLOBAL ); #endif } std::string where = finder.find( basename ); if( where.empty() ) return where; void * soh = 0; #if HAVE_LTDL soh = lt_dlopen( where.c_str() ); #else soh = dlopen( where.c_str(), RTLD_NOW | RTLD_GLOBAL ); #endif return soh ? where : ""; // todo: add a helper class to dlclose(soh) post-main(). This has proven problematic // (crashes) in some cases, so we currently rely on the OS to clean everything up :/. } void class_loader_path_init() { static bool donethat = false; if( donethat ) return; donethat = true; path_finder & path = CL_NAMESPACE::context_singleton<path_finder,class_loader_sharing_context>::instance(); path.add_extension( ".so:.SO" ); path.add_path( CLASS_LOADER_PATH ); const char * p = getenv( "LD_LIBRARY_PATH" ); if( p ) { path.add_path( p ); } CL_DEBUG_STATIC << "Initialized shared class_loader path: ["<<path<<"] extensions=["<<path.extensions_string()<<"]"<<std::endl; return; } static const int class_loader_path_init_bogus = (class_loader_path_init(),0); } // namespace --- NEW FILE: ns.class_loader.h --- #ifndef CLASSLOADER_H_INCLUDED #define CLASSLOADER_H_INCLUDED 1 // Author: stephan beal <st...@s1...> // License: Public Domain #include <string> #include <iostream> #include <sstream> #include <fstream> #include <cassert> #include <map> #ifndef CLASSLOADER_DEBUG #define CLASSLOADER_DEBUG 0 #endif #if HAVE_CONFIG_H # include "config.h" // might have CL_NAMESPACE #endif #include "instantiator.h" #include "path_finder.h" #include "context_singleton.h" #include "debuggering_macros.h" // COUT/CERR #if CLASSLOADER_DEBUG #include <typeinfo> #endif #define CL_TYPENAME typeid(ThisType()).name() #define CL_DEBUG if( 0 != CL_NAMESPACE::class_loader_debug_level() ) CERR << CL_TYPENAME <<" " #define CL_DEBUG_STATIC if( 0 != CL_NAMESPACE::class_loader_debug_level() ) CERR << " " namespace CL_NAMESPACE { /** Internal helper class. */ struct class_loader_sharing_context {}; /** Utility function to help keep an instance count of T. Should ONLY be called from ctors and dtors. */ template <typename T> unsigned long & inst_count() { static unsigned long c = 0; return c; } /** Sets the framework-wide debug level. This is shared by all class_loaders, regardless of their templatized types. Currently only two values are supported: zero (no debugging output) and non-zero (all debugging output). Note that this uses a compile-time default, which means that if compiled without debugging, some debug messages will not show up because they happen pre-main(), before a client can set the debug level. */ void class_loader_debug_level( int dlevel ); /** Returns the framework-wide debug level. */ int class_loader_debug_level(); // /** // "Conceptually experimental" and currently unused. // */ // struct dll // { // void * handle; // handle returned by dlopen() // std::string path; // path where DLL was opened from // std::string key; // lookup key used to find DLL // dll(void *h,const std::string &p,const std::string &k) : handle(h),path(p),key(k) {}; // dll() : handle(0),path(""),key("") {}; // mainly to make this class useful for containers. // ~dll(){}; // }; /** UNTESTED Does exactly what it's name says: it searches for a DLL using the given basename and path_finder. If it finds a DLL it opens it, which triggers any class_loader registrations in the DLL. Returns the path to the DLL, if it was found/opened, else an empty string. This function is intended to be used by class_loader subclasses, and was written to reduce the need for DLL-capable loaders to rely on the dll_loader class. By convention basename is expected to be a class name, and a namespace part is acceptable. Namespaces are currently removed before doing the file search, but a different algorithm may be applied as some point, or an additional parameter to define a name-translation functor may be added. */ std::string find_and_open_dll( const std::string & basename, const path_finder & finder ); /** A basic templates-based classloader implementation, intended to work in conjunction with CL_NAMESPACE::instantiator for loading classes via registered object factories. Templatized on: BaseType - this is the type to which all loaded classes should be cast. This is analogous to libfun's fun::LoadableClass. KeyType - the key type to be used to search for classes. Historically this is a string, but any comparable type should work. It is important that KeyType support less-than ordering. UseSharedInstances - determines the ownership policy for pointers returned from load(). See load() and the library manual for full details. This parameter should be left as-is for most use-cases. To make any given class classloadable by this class, call this macro one time (preferably from the class' header file): <pre> CLASSLOADER_REGISTER(BaseType,SubType); CLASSLOADER_REGISTER(SubType,SubType); // optional, and sometimes useful </pre> BaseType need not be ClassLoadable, but SubType must derive from (or be) BaseType. The exact meanings of the parameters are discussed at length in the documentation for that macro, in the class_loader.h header file and in the libs11n manual. As a side-effect of it's template-ness, usage of this class is compile-time type-safe without the use of any casts. Please see cl_demo.cpp for a documented, runnable example of using this class. See s11n::dll_loader for a subclass which can load classes from DLLs. */ template < class BaseType, class KeyType = std::string, bool UseSharedInstances = false /* experimental */ > class class_loader { public: /** Highly experimental and largely untested. */ static const bool use_shared_instances = UseSharedInstances; /** value_type is the base-most class type to be used for casting. Contrary to usage in some std::-namespace CL_NAMESPACEasses, value_type is not a pointer type, even though this class deals only with pointers to value_type objects. This is intended to ease the use of value_type in many common contexts. */ typedef BaseType value_type; /** The key type used for class lookups. The default is std::string. */ typedef KeyType key_type; /** Convenience typedef. It's only public for documentation reasons. */ typedef class_loader < value_type, key_type, use_shared_instances > ThisType; /** factory_type is a function pointer which takes no arguments and returns a value_type pointer. todo: add proper functor support. */ typedef value_type *( *factory_type ) (); // todo: investigate utility of: BaseType *(*factory_type)( key_type ) class_loader() { ++inst_count<ThisType>(); //CL_DEBUG << "instance #" << inst_count<ThisType>()<<std::endl; } virtual ~class_loader() { if( use_shared_instances ) { // might be optimized away by the compiler :) if( 0 == --inst_count<ThisType>() ) { CL_DEBUG << "Cleaning up shared objects..." << std::endl; map_type & bob = context_singleton<map_type,ThisType>::instance(); typename map_type::iterator it = bob.begin(); typename map_type::iterator et = bob.end(); for( ; it != et; ++it ) { delete( (*it).second ); } } } } /** Returns a reference to a shared instance of this classloader type. */ static ThisType & shared() { return context_singleton<ThisType,ThisType>::instance(); } /** Tries to instantiate an object using a factory which has been mapped to the given key. Returns a non-NULL pointer on success and NULL on error. The caller takes ownership of the returned pointer... UNLESS: If ThisType::use_shared_instances is true then this function will always return the same object for any given key, and the client <b>DOES NOT</b> take ownership of the returned pointer! The objects will be deleted when the last class_loader of this type destructs, almost certainly post-main(). Subclasses should override this function to customize classloading behaviour. The default implementation loads classes which have been registered via: - ThisType::register_factory() - ThisType::register_subtype() (Remember, the CLASSLOADER_REGISTER macro normally calls those for you.) See CL_NAMESPACE::dll_loader for a DLL-capable implementation. */ virtual value_type * load( const key_type & key ) const { CL_DEBUG << ": load("<<key<<")"<<std::endl; if( ! ThisType::use_shared_instances ) { return ThisType::instantiator_type::instantiate( key ); } value_type * ch = NULL; map_type & bob = context_singleton<map_type,ThisType>::instance(); // we use this instance in other code, to delete the pointers. typename map_type::iterator it = bob.find( key ); // WTF does this require typename in this context? if( bob.end() == it ) { ch = instantiator_type::instantiate( key ); bob[key] = ch; } else { ch = (*it).second; } return ch; } /** Convenience static version of load( key ), which uses the class_loader returned by shared(). Avoid using this, as the following (quasi-incorrectly) have different behaviour: <pre> typedef CL_NAMESPACE::dll_loader<s11n::Serializable> CL; CL cl; s11n::Serializable * sable = NULL; sable = cl.load( "foo::FooClass" ); // works properly sable = CL::load_class( "foo::FooClass" ); // ends up calling class_loader<>::load() <pre> */ static value_type * load_class( const key_type & key ) { return shared().load( key ); } /** register_factory() associates key with a factory function. If fp == NULL then a default factory is used (normally this behaviour is just fine). register_factory() probably should not be static, but i'm not fully convinced that a non-static implementation is useful, and a static implementation eases use of this class. Since real classloaders must(?) use the same definitions for all like-types, anyway, it seems like a moot point. In any case, static appears to ease client usage, so static it is. */ static void register_factory( const key_type & key, factory_type fp = NULL ) { CL_DEBUG << "register_factory("<<key<<","<<std::hex<< fp<<")"<<std::endl; instantiator_type::register_factory( key, fp ); } /** Convenience function which registers a factory which creates SubT pointers but returns value_type pointers. */ template <typename SubT> static void register_subtype( const key_type & key ) { CL_DEBUG << " register_subtype("<<key<<")" <<std::endl; register_factory( key, CL_NAMESPACE::object_factory<value_type,SubT>::new_instance ); } /** path() returns a path_finder, which is useful for searching for files in a known set of directories and/or having a known set of file extensions. Note that path() has no use in the default class_loader implementation, but it is useful for subclasses which work with files. If use_global is false (the default) it returns a path shared by all class_loader<T> types sharing the same T. If use_global is true it returns a path() which is shared by ALL class_loaders. It is still up to the class_loader implementations to do something useful with the path(), however. */ path_finder & path( bool use_global = false ) const { return use_global ? CL_NAMESPACE::context_singleton<path_finder,class_loader_sharing_context>::instance() : CL_NAMESPACE::context_singleton<path_finder,ThisType>::instance(); } private: /** Factories registered with this instantiator_type are inherently loadable by this class. */ typedef CL_NAMESPACE::instantiator < BaseType, KeyType > instantiator_type; typedef std::map<key_type,value_type *> map_type; }; // class_loader } // namespace // ---------------------------------------------------------------------- namespace { // anonymous ns, important for linking reasons. // ---------------------------------------------------------------------- /** A helper object for registering classes when a DLL or application is opened (i.e., when static objects are initialized). Normally clients only need to run the CLASSLOADER_REGISTER macro somewhere in their impl code: <pre> CLASSLOADER_REGISTER(BaseType,ImplType); </pre> This class is a side-effect of the implementation of the CLASSLOADER_REGISTER macro (but, IMO, a pretty interesting side-effect ;). */ template <class BaseT,class SubT = BaseT, class KeyT = std::string, bool CLSharedInstances = false> struct classloader_registerer { typedef BaseT base_t; typedef SubT sub_t; typedef KeyT key_t; typedef classloader_registerer<base_t,sub_t> this_t; typedef CL_NAMESPACE::class_loader<base_t,key_t,CLSharedInstances> loader_t; typedef CL_NAMESPACE::object_factory<base_t,sub_t> factory_t; static const char * class_name() { assert( 0 && "this classloader_registerer<> is unspecialized!" ); return 0; } static void initialize() { assert( 0 && "this classloader_registerer<> is unspecialized!" ); return 0; } }; // ---------------------------------------------------------------------- } // anonymous namespace // ---------------------------------------------------------------------- /** Call this macro one time to make your classes loadable by all class_loader<BaseT> instances. Parameters: - BaseT, the base-most class type. i.e., that which will be used by clients when they call: <pre> BaseType * foo = class_loader<BaseType>( "mynamespace::SubtypeOfBaseT" ); </pre> The libs11n documentation goes into much more detail about this. - SubT, an implementation class derived from BaseT. Example: <pre> CLASSLOADER_REGISTER(mynamespace::MyDocumentBase,mynamespace::MyDocument); </pre> i'd like to call CLASS_NAME(SubT) from this macro, but doing so causes template specialization collisions when CLASSLOADER_REGISTER is called, e.g., like so: <pre> CLASSLOADER_REGISTER(BaseT,SubT); CLASSLOADER_REGISTER(SubT,SubT); </pre> This is valid usage, however, and necessary in some client cases, so i can't kill it's usage with an automatic CLASS_NAME() :(. See CLASSLOADER_REGISTER[1-5] if you want to customize the registration behaviour or register one class with multiple KeyT's. */ #define CLASSLOADER_REGISTER(BaseT,SubT) CLASSLOADER_REGISTER2(BaseT,SubT) // CLASSLOADER_REGISTER[1-5]: // Pneumonic for remembering which macro to call: the suffix is the number of args to pass. // 1-3 only known to work for (KeyT = std::string). // Example: // CLASSLOADER_REGISTER4(BaseType,SubType,double,42.42) // registers SubType via class_loader<BaseType>::register_factory( 42.42 ). #define CLASSLOADER_REGISTER1(BaseT) CLASSLOADER_REGISTER2(BaseT,BaseT) #define CLASSLOADER_REGISTER2(BaseT,SubT) CLASSLOADER_REGISTER3(BaseT,SubT,std::string) #define CLASSLOADER_REGISTER3(BaseT,SubT,KeyT) CLASSLOADER_REGISTER4(BaseT,SubT,KeyT,# SubT) #define CLASSLOADER_REGISTER4(BaseT,SubT,KeyT,ThekeY) CLASSLOADER_REGISTER5(BaseT,SubT,KeyT,ThekeY,false) #define CLASSLOADER_REGISTER5(BaseT,SubT,KeyT,ThekeY,UseshareD) \ namespace { template<> struct classloader_registerer<BaseT,SubT,KeyT,UseshareD> {\ typedef BaseT base_t; \ typedef SubT sub_t; \ typedef KeyT key_t; \ typedef classloader_registerer<base_t,sub_t> this_t;\ typedef CL_NAMESPACE::class_loader<base_t,key_t,UseshareD> loader_t; \ typedef CL_NAMESPACE::object_factory<base_t,sub_t> factory_t; \ static int placeholder; \ static KeyT key(){ return ThekeY; } \ static void initialize( const key_t & k = key() ) { \ loader_t::register_factory( k, factory_t::new_instance ); \ }\ }; \ int classloader_registerer<BaseT,SubT,KeyT,UseshareD>::placeholder = (classloader_registerer<BaseT,SubT,KeyT,UseshareD>::initialize(),0);\ } // many thanks to tom, from c.l.c++, for the (...,0) trick! // kill this some day: // if( CLASSLOADER_DEBUG ) CERR << typeid(this_t()).name()<<" initialize("<<k<<")"<<std::endl; // static factory_t factory(){ return CL_NAMESPACE::object_factory< base_t, sub_t >::new_instance; } // static bool donethat = false; if(donethat) return; donethat=true; // loader_t::register_factory( key(), CL_NAMESPACE::object_factory<base_t,sub_t>::new_instance ); #endif // CLASSLOADER_H_INCLUDED --- NEW FILE: ns.classname_transformer.h --- #ifndef CLASSNAME_TRANSFORMER_H #define CLASSNAME_TRANSFORMER_H // License: Do As You Damned Well Please // Author: st...@s1... #include <string> namespace CL_NAMESPACE { /** An interface for transforming class names into filesystem-friendly strings, for doing class-to-DLL lookups. It is intended for use by DLL-aware classloaders used in the libclass_loader framework. */ class classname_transformer { public: classname_transformer() {}; virtual ~classname_transformer() {}; /** Default implementation simply strips the namespace part from classname and returns the rest. e.g.: foo::Foo == Foo foo::bar::Foo == Foo Foo == Foo */ virtual std::string translate( const std::string & classname ); }; } // namespace CL_NAMESPACE #endif // CLASSNAME_TRANSFORMER_H --- NEW FILE: ns.cl_demo.cpp --- #define CLASSLOADER_DEBUG 1 #include "class_loader.h" /** It is important to understand that any given class_loader<T> instantiation works only for types which are exactly of type T, not for subtypes of T. As this essentially kills any chance of using polymorphic types, this is obviously a problem! That said, we can coerce the classloader into using sub-types of T by feeding it factories which creates (SubT*) and returns (T*). class_loader<T>::register_subtype<X>() provides a very simple way to register a default factory for type X, returning pointers to T (where X must be a subclass of T). The sample code below exemplifies the requirements placed on clients of class_loader: 1. Classes to be loaded from a given classoader type must derive from a common base type. 2. Clients calling load() must use a class_loader<T> instance, where T is the base type defined in (1). 3. Proper lookup keys must be registered with the appopriate classloader. **/ #include "debuggering_macros.h" struct A { A(){ CERR << "A()"<<std::endl; } virtual ~A(){ CERR << "~A()"<<std::endl; } }; struct B : public A { B(){ CERR << "B()"<<std::endl; } virtual ~B(){ CERR << "~B()"<<std::endl; } }; struct C : public B { C(){ CERR << "C()"<<std::endl; } virtual ~C(){ CERR << "~C()"<<std::endl; } }; // Define USE_REGISTER to 0 to disable the use of CLASSLOADER_REGISTER // and use manual factory registration instead. This is for testing // both approaches, and they should function identically. #define USE_REGISTER 1 #if USE_REGISTER // Corresponds to the ACL classloader in the example below: CLASSLOADER_REGISTER(A,A); CLASSLOADER_REGISTER(A,B); CLASSLOADER_REGISTER(A,C); // ^^^ normally clients would only use these 3, but the ones coming up // next are useful in some cases: // Corresponds to the BCL classloader in the example below: CLASSLOADER_REGISTER(B,B); CLASSLOADER_REGISTER(B,C); // Corresponds to the CCL classloader in the example below: CLASSLOADER_REGISTER(C,C); #endif // USE_REGISTER #include "LoadableClass.h" // sample BaseType #include "dll_loader.h" // a DLL-aware class_loader implementation int main() { using namespace CL_NAMESPACE; // Define some shortcuts: typedef class_loader<A,std::string,true> ACL; // demonstation of shared objects. CERR << "Note: class_loader<A> uses shared objects." << std::endl; typedef class_loader<B> BCL; typedef class_loader<C> CCL; #if ! USE_REGISTER /****************************** If we do not use CLASSLOADER_REGISTER the following code is necessary to register A, B and C. If you'll look closely you'll notice that these calls correspond one-to-one to the above macro calls. ****************************/ // Set up a loader for class A: ACL::register_factory( "A" ); // factory creating/returning A* ACL::register_subtype<B>( "B" ); // factory creating B*, returning A* ACL::register_subtype<C>( "C" ); // factory creating C*, returning A* // Set up a loader for class B: BCL::register_factory( "B" ); // factory creating B*, returning B* BCL::register_subtype<C>( "C" ); // factory creating C*, returning B* // BCL::register_subtype<A>( "A" ); // ERROR: there is no conversion for A* to B* // Set up a loader for class C: CCL::register_factory( "C" ); // factory creating C*, returning C* // CCL::register_subtype<A>( "A" ); // ERROR: there is no conversion from A* to C* // CCL::register_subtype<B>( "B" ); // ERROR: there is no conversion from B* to C* #endif // let's register an alias for class C: CCL::register_factory( "bogo::C" ); // it may be useful to define configurable classes types: ACL::register_subtype<C>( "default_document_class" ); #define TESTLOAD(OBJ,CL,NAME,SHOULDPASS) \ CERR << # OBJ << " = "<<#CL<<".load("<<NAME<<");"<<std::endl; \ OBJ = CL.load( NAME ); \ std::cerr << " = " << std::hex<<OBJ<<std::endl; \ if( SHOULDPASS && (!OBJ) ) { CERR << "TEST FAILED! :(" << std::endl; exit(1); } \ else CERR << "TEST PASSED :)" << std::endl; \ if( OBJ && ! CL.use_shared_instances ) delete( OBJ ); ACL acl; A * a = 0; TESTLOAD(a,acl,"A",true); // creates A* TESTLOAD(a,acl,"B",true); // creates B*, disguised as A* TESTLOAD(a,acl,"B",true); // test the shared object support. Should be the same as previous call. TESTLOAD(a,acl,"C",true); // creates C*, disguised as A* TESTLOAD(a,acl,"C",true); // test shared again... TESTLOAD(a,acl,"X",false); // NULL: key "X" was never registered with ACL TESTLOAD(a,acl,"default_document_class",true); // creates C* BCL bcl; B * b = 0; TESTLOAD(b,bcl,"B",true); // creates B* TESTLOAD(b,bcl,"A",false); // NULL: key "A" was never registered with BCL TESTLOAD(b,bcl,"C",true); // creates a C*, disguised as a B* CCL ccl; C * c = 0; TESTLOAD(c,ccl,"C",true); // creates a C* TESTLOAD(c,ccl,"bogo::C",true); // creates a C* TESTLOAD(c,ccl,"default_document_class",false); // NULL typedef dll_loader<LoadableClass> LCL; LCL lcl; LoadableClass * lc = 0; TESTLOAD(lc,lcl,"LoadableClass",true); TESTLOAD(lc,lcl,"LoadableSubClass",true); // a DLL, we hope typedef class_loader<LoadableClass,int> INTCL; INTCL intcl; TESTLOAD(lc,intcl,7,true); // see LoadableSubClass.cpp for why this works TESTLOAD(lc,intcl,1,false); // and why this doesn't. CERR << "Exiting main(). Any loaders using shared object instances should clean up now..." << std::endl; return 0; } --- NEW FILE: ns.context_singleton.h --- #ifndef CONTEXT_SINGLETON_H_INCLUDED #define CONTEXT_SINGLETON_H_INCLUDED 1 // Author: stephan beal <st...@s1...> // License: Public Domain namespace CL_NAMESPACE { /** A helper class to help avoid the usage of static data members in template classes, as they are often awkward to initialize. Templatized on: - SharedType: the type of object to share. - SharingType: a "context" in which this object is shared. example: <pre> struct sharing_context {}; context_singleton<std::string,sharing_context>::instance() = "foo"; std::string bar = context_singleton<std::string,sharing_context>::instance(); // "foo" </pre> */ template <class SharedType, class ContextType> class context_singleton { public: /** Returns an instance which is unique for the combination of SharedType and ContextType. Always returns the same instance. */ static SharedType & instance() { static SharedType meyers; return meyers; }; }; } // namespace #endif // CONTEXT_SINGLETON_H_INCLUDED --- NEW FILE: ns.debuggering_macros.h --- #ifndef DEBUGGERING_MACROS_H #define DEBUGGERING_MACROS_H 1 // CERR is a drop-in replacement for std::cerr, but slightly more // decorative. #ifndef CERR #define CERR std::cerr << __FILE__ << ":" << std::dec << __LINE__ << " : " #define CERRL(A) CERR << A << std::endl; #endif #ifndef COUT #define COUT std::cout << __FILE__ << ":" << std::dec << __LINE__ << " : " #define COUTL(A) COUT << A << std::endl; #endif #endif // DEBUGGERING_MACROS_H --- NEW FILE: ns.dll_loader.h --- #ifndef DLLLOADER_H_INCLUDED #define DLLLOADER_H_INCLUDED 1 // Author: stephan beal <st...@s1...> // License: Public Domain #include <stdlib.h> // abort() #include <typeinfo> #include <map> #include <string> #include <cassert> #ifdef NDEBUG #undef NDEBUG // i want to force an assert in a couple of cases. #endif #include "class_loader.h" // parent class, plus CL_DEBUG macro #include "debuggering_macros.h" // CERR/COUT #ifdef HAVE_LTDL // prefer libltdl, but if it's not available... # include <ltdl.h> #else // use libdl instead: # include <dlfcn.h> #endif namespace CL_NAMESPACE { /** A classloader for loading BaseType classes from DLLs. This class represents my very first usage of dlopen(), and there may be bugs related to how i use the dlXXX() functions. Conventions: Classes to be dynamically loaded must be registered with a classloader. How do we make the classloader aware of a class which doesn't exist yet? It's actually straightforward: We need to initialize the DLL when it is opened, and the simplest way to do this is for the client to simply assign a no-meaning value to a static const variable. Here's one way to register your class: <pre> static const int bogus_var = CL_NAMESPACE::class_loader<SerializableType>::register_subtype<myns::MyClass>( "myns::MyClass" ); </pre> a simpler approach is to use call the CLASSLOADER_REGISTER macro one time from your <i>header</i> files (for complex linking reasons): <pre> CLASSLOADER_REGISTER(BaseType,my_ns::MyClass); </pre> Please read the docs for that macro (class_loader.h)! However you do it, having code which is run when the DLL is opened allows you to feed your class to the classloader, instead of it trying to eat your class (so to speak). This is not a conventional approach to loading classes, but it's <b>compile-time type safe</b> and allows us to <b>avoid all types of casts</b> in the implementation. Classes must be saved in a file called ClassName.so and installed in one of these paths: - LD_LIBRARY_PATH (the run-time, not compile-time, value) - current directory - a path selected by client code, assuming that the client also modifies this class_loader's path to match. This class can also load objects which have been statically registered via dll_loader<BaseType>::registerXXX(). That means that any factories registered with class_loader<BaseType> are inherently loadable by this class as well. Factories registered from within DLLs are available to all like-typed class_loader<T> instances. When this document mentions dlopen(), dlclose() or dlerror() it is really refering to either dlXXX() or ltdlXXX(), depending on which one this library was built with. Their conventions are the same for our purposes, so this should not make a difference to client code, but is useful to know when low-level DLL opening problems arise. */ template <typename BaseType> class dll_loader : public CL_NAMESPACE::class_loader < BaseType, std::string, false > { public: /** value_type is for conformance with our parent class' interface. */ typedef BaseType value_type; /** A convenience typedef. */ typedef dll_loader<BaseType> ThisType; /** Convenience typedef. */ typedef CL_NAMESPACE::class_loader < value_type, std::string > ParentClass; /** Constructs a default dll_loader. */ dll_loader() { ++inst_count<ThisType>(); } /** */ virtual ~dll_loader() { } /** load() first tries to load key via the ancestor's load(), and returns that pointer if it is non-NULL. Secondly, it searches for a DLL named 'key.so', using this object's path(). If it is not found in this object's path then the global path() is searched. To make a very long story very short, if it succeeds it returns a pointer to a new object, otherwise it returns NULL. The internals are covered in more detail in the libclass_loader library manual. This function caches lookups it's finds and will refuse to try a second time to look up a failed key. This no-two-tries policy is very arguable, and may be made toggleable at some point. It cannot be done via adding a new argument to this function because that violates the class_loader interface, making this a special case, and i hate special cases. */ virtual ThisType::value_type * load( const std::string & key ) const { // todo: go through and clean all this up: value_type * ch = NULL; ch = this->ParentClass::load( key ); // if the parent can handle it, great. if ( ch ) { CL_DEBUG << "Parent class handled '"<<key<<"'"<<std::endl; return ch; } // Only first-time and EVIL (see below) entries will run past this point, // since all successful lookups are cached via the parent class. void * soh = 0; // shared object handle std::string path; // potentially a path to a DLL std::string xlated = key; // key, translated to remove namespace part (because :: is not filesystem-friendly). // strip namespace part from the file std::string::size_type colon = xlated.rfind( ":" ); if( std::string::npos != colon ) { xlated = xlated.substr( colon + 1 ); } path = this->path().find( xlated ); // search for DLL if( path.empty() ) { // try harder! path = this->path( true ).find( xlated ); } if ( path.empty() ) { // Backup plan: try the main application space: CL_DEBUG << "No DLL found for key '"<<key<<"' in paths ["<<this->path(false)<<"] ["<<this->path(true)<<"]"<<std::endl; soh = NULL; } else { // Freu! :) CL_DEBUG << "Found DLL for '"<<key<<"': " << path << std::endl; soh = this->open_dll( path.c_str() ); if( ! soh ) { // Trauer! :`( CERR << "open_dll("<<path<<") failed. DLERROR says: " << this->dll_error()<<std::endl; return NULL; } } if( ! soh ) { // no findie... CL_DEBUG << ":( Class '"<<key<<"' not found (maybe not registered with *this exact* class_loader type?)." << std::endl; return NULL; } // reminder: just because we got this far // DOES NOT inherently mean that that // the DLL contains a class for this // specific class_loader type! return this->ParentClass::load( key ); // ^^^^^ in theory it's registered with our // parent class by now, because that's how the // CLASSLOADER_REGISTER process works. This // assumes that we opened the correct DLL, // which might not actually be the case. :/ } // load() protected: /** Maps strings to dlopen() handles. */ typedef std::map<std::string,void *> soh_map_type; /** The internal map of keys (class names) and dlopen() handles. */ static ThisType::soh_map_type & ThisType::soh_map() { static ThisType::soh_map_type bob; return bob; } /** Tried to open the given DLL, following the semantics provided by the underlying dlopen() implementation. Returns a handle for the DLL, as per dlopen() conventions. If path.empty() then the main application is opened (i.e., the same as if NULL is passed to dlopen()). This method does not do any path() searching. The result of the lookup (perhaps NULL) is stored in soh_map(). */ void * open_dll( const std::string & path ) const { void * soh = 0; #if HAVE_LTDL soh = lt_dlopen( path.empty() ? 0 : path.c_str() ); #else soh = dlopen( path.empty() ? 0 : path.c_str(), RTLD_NOW | RTLD_GLOBAL ); #endif soh_map()[path] = soh; // that's okay if it's NULL return soh; } /** Close the given shared object handle, following the semantics provided by the underlying dlclose() implementation. */ void close_dll( void * soh ) { #if HAVE_LTDL lt_dlclose( soh ); #else dlclose( soh ); #endif // todo: remove entry from soh_map(). // The future of soh_map() is in limbo, // so that will wait. } /** Returns the same thing as the underlying dlerror() implementation. */ const char * dll_error() const { #if HAVE_LTDL return lt_dlerror(); #else return dlerror(); #endif } }; }; // namespace CL_NAMESPACE #endif // DLLLOADER_H_INCLUDED --- NEW FILE: ns.instantiator.h --- #ifndef INSTANTIATOR_H_INCLUDED #define INSTANTIATOR_H_INCLUDED 1 // Author: stephan beal <st...@s1...> // License: Public Domain #include <string> #include <map> namespace CL_NAMESPACE { /** object_factory is a helper object factory for the classes instantiator and class_loader . Classloaders, at least in my experience, need to be able to load all classes which derive from some given type. Without a common base class, one can't safely attempt to cast from an arbitrary pointer to the type we want to load. That's where the BaseType parameter comes in. All objects instantiated via this loader must inherit from BaseType. KeyType is a type which specifies the type of key used to look up classes, defaulting to std::string. Both BaseType and KeyType must be Default Constructable on the heap (e.g., via new BaseType()). This class holds no state: it only provides typedefs and one method. Sample usage: <pre> typedef instantiator<MyClass> CL; CL::register_factory( "my_key" ); // ^^^ uses a default factory creating MyClass objects: you can // pass your own as the second arg. MyClass *foo = CL::load( "some_key" ); // == NULL foo = CL::instantiate( "my_key" ); // == a new object </pre> */ template < class T, class SubT = T > struct object_factory { /** A typedef for the first template parameter for this type. */ typedef T result_type; /** A typedef for the second template parameter for this type. */ typedef SubT actual_type; /** This creates a new SubT, which is assumed to be a subclass of T. It can be used as a factory for instantiator & class_loader. */ static result_type *new_instance() { return new actual_type; } // result_type * operator()() const { return new_instance(); } // untested! }; /** instantiator is essentially a static classloader, capable of loading classes by using registered factories for a given set of keys (class names). */ template < class BaseType, class KeyType = std::string > class instantiator { public: /** Convenience typedef. */ typedef instantiator< BaseType, KeyType > ThisType; // i can't believe this works. /** A typedef for the BaseType used by this class. */ typedef BaseType value_type; /** A typedef for the KeyType used by this class. */ typedef KeyType key_type; /** The type of factories used by this class: a function taking void and returning (value_type *). todo: implement proper functor support. */ typedef value_type *( *factory_type ) (); /** Tries to instantiate an instance of value_type using the given key. Returns NULL if no class could be loaded for the given key. The caller takes responsibility for the returned pointer. */ static ThisType::value_type * instantiate( const ThisType::key_type & key ) { typename object_factory_map::const_iterator it = factory_map().find( key ); if ( it != factory_map().end() ) // found a factory? { return ( it->second ) (); // run our factory. } return NULL; } /** Registers a factory using the given key. If fp is NULL then ThisType::new_instance is used as the factory. Note that fp may not return a type other than ThisType::value_type *, but the actual object it creates may be a polymorphic subclass of value_type. See the object_factory class for a factory which does this subtype-to-base conversion. */ static void register_factory( const ThisType::key_type & key, ThisType::factory_type fp = NULL ) { ThisType::factory_type fac = (NULL==fp) ? object_factory<ThisType::value_type>::new_instance : fp; factory_map().insert( object_factory_map::value_type( key, fac ) ); } /** Convenience wrapper around register_factory( key, factory_for_SubOfBaseType ). Registers a factory for ThisType::value_type, using the given key and a default factory for producing SubOfBaseType objects. SubOfBaseType must be a subtype of ThisType::value_type. */ template <typename SubOfBaseType> static void register_subtype( const ThisType::key_type & key ) { register_factory( key, object_factory<ThisType::value_type,SubOfBaseType>::new_instance ); } // /** // Convenience factory which returns a default-constructed // instance of ThisType::value_type. The caller takes // responsibility for the returned pointer. // */ // static ThisType::value_type * new_instance() // { // return new ThisType::value_type(); // } /** Internal container type used for mapping keys to factories. */ typedef std::map < key_type, factory_type > object_factory_map; /** Returns the internal key-to-factory map. It is safe for clients to modify this except in multi-threaded environments, and then all guarantees go out the window. That said, it should never be necessary for clients to use this. */ static object_factory_map & factory_map() { static object_factory_map fac; return fac; } private: // intentionally unimplemented: instantiator(); ~instantiator(); instantiator( const ThisType & ); instantiator & operator=( const ThisType & ); }; // class instantiator } // namespace #endif // INSTANTIATOR_H_INCLUDED --- NEW FILE: ns.path_finder.cpp --- // Author: stephan beal <st...@s1...> // License: Public Domain #include <iostream> #include <unistd.h> #include <stdlib.h> // getenv() #if HAVE_CONFIG_H # include "config.h" // CONFIG_HAVE_CYGWIN #endif #include "path_finder.h" #include "debuggering_macros.h" using std::string; using std::ostream; namespace CL_NAMESPACE { using std::ostream; std::ostream & operator<<( ostream & os, const CL_NAMESPACE::path_finder & obj ) { os << obj.path_string(); return os; } string & operator<<( string & os, const CL_NAMESPACE::path_finder & obj ) { os += obj.path_string(); return os; } path_finder::~path_finder() { } CL_NAMESPACE::path_finder & operator +=( CL_NAMESPACE::path_finder & obj, const string & os ) { obj.add_path( os ); return obj; } path_finder::path_finder( const string & p, const string & e, const string & pathsep ) { this->path_separator( pathsep ); this->path( p ); this->extensions( e ); } const string & path_finder::path_separator() const { return ( ( path_finder * ) this )->pathseparator; } void path_finder::path_separator( const string & sep ) { this->pathseparator = sep; } std::string path_finder::join_list( const string_list & list, const std::string & separator ) const { std::string ret; unsigned long count = list.size(); unsigned long at = 0; string_list::const_iterator it = list.begin(); string_list::const_iterator et = list.end(); for(; it != et; ++it ) { ret += (*it); if( ++at != count ) ret += separator; } return ret; } string path_finder::path_string() const { return this->join_list( this->paths, this->pathseparator ); } const path_finder::string_list & path_finder::path() const { return this->paths; } string path_finder::extensions_string() const { return this->join_list( this->exts, this->pathseparator ); } const path_finder::string_list & path_finder::extensions() const { return this->exts; } unsigned int tokenize_to_list( const std::string & str, std::list<std::string> & li, const std::string & sep ) { // internal helper function if( str.empty() ) return 0; unsigned int c = 0; std::string token; std::string::size_type sz = str.size(); for( std::string::size_type i = 0; i < sz; i++ ) { if( sz-1 == i ) token += str[i]; if( str.find( sep, i ) == i || (sz-1 == i) ) { //CERR << "token="<<token<<std::endl; li.push_back( token ); token = ""; i += sep.size() - 1; continue; } token += str[i]; } return c; } unsigned int path_finder::path( const string & p ) { this->paths.erase( this->paths.begin(), this->paths.end() ); return tokenize_to_list( p, this->paths, this->pathseparator ); } unsigned int path_finder::path( const path_finder::string_list & p ) { this->paths = p; return this->paths.size(); } void path_finder::add_path( const string & p ) { tokenize_to_list( p, this->paths, this->pathseparator ); } unsigned int path_finder::extensions( const string & p ) { this->exts.erase( this->exts.begin(), this->exts.end() ); return tokenize_to_list( p, this->exts, this->pathseparator ); } unsigned int path_finder::extensions( const path_finder::string_list & e ) { this->exts = e; return this->exts.size(); } void path_finder::add_extension( const string & p ) { tokenize_to_list( p, this->exts, this->pathseparator ); } // static bool path_finder::is_accessible( const string & path ) { int err = access( path.c_str(), F_OK ); if ( err != 0 ) { // LIBE_VERBOSE << "exists("<<path<<"): access() returned error: "<<err<<endl; } return err == 0; } string path_finder::basename( const std::string & name ) { string::size_type slashat = name.find_last_of( path_finder::dir_separator() ); if ( slashat == string::npos ) return name; return name.substr( slashat + 1 ); } string path_finder::find( const string & resource, bool check_cache ) const { static const std::string NOT_FOUND = "path_finder::find() : no findie"; if ( resource.empty() ) return string(); string checkat; #define CHECKPATH(CHECKAT) checkat = CHECKAT; \ if( ! checkat.empty() && path_finder::is_accessible( checkat ) ) \ { this->hitcache[resource] = checkat; return checkat; } //CERR << "find( " << resource << " )" << std::endl; if( check_cache ) { checkat = this->hitcache[resource]; if ( checkat == NOT_FOUND ) return string(); if ( !checkat.empty() ) return checkat; } CHECKPATH( resource ); string_list::const_iterator piter = this->paths.begin(); string_list::const_iterator eiter = this->exts.begin(); string path; string ext; if ( path_finder::is_accessible( resource ) ) return resource; piter = this->paths.begin(); string checkhere; while ( piter != this->paths.end() ) { path = ( *piter ); if ( !path.empty() ) { path += path_finder::dir_separator(); } ++piter; checkhere = path + resource; //CERR << "find( " << resource << " ) checking " << checkhere << std::endl; CHECKPATH( checkhere ); eiter = this->exts.begin(); while ( eiter != this->exts.end() ) { ext = ( *eiter ); ++eiter; checkhere = path + resource + ext; //CERR << "find( " << resource << " ) checking " << checkhere << std::endl; CHECKPATH( checkhere ); } } //CERR << "find( "<<resource<<" ): not found :(" << std::endl; this->hitcache[resource] = NOT_FOUND; return string(); } // bin_path_finder::bin_path_finder() : path_finder( ::getenv( "PATH" ) ) // { // this->extensions( ".sh" ); // #if CONFIG_HAVE_CYGWIN // this->extensions(".exe:.bat"); // #endif // } // bin_path_finder::~bin_path_finder() // { // } }... [truncated message content] |
From: <sg...@us...> - 2003-11-17 20:18:33
|
Update of /cvsroot/libfunutil/libfunutil/lib/cl In directory sc8-pr-cvs1:/tmp/cvs-serv25566/lib/cl Log Message: Directory /cvsroot/libfunutil/libfunutil/lib/cl added to the repository |
From: <sg...@us...> - 2003-11-17 19:23:40
|
Update of /cvsroot/libfunutil/libfunutil/lib/toolbox In directory sc8-pr-cvs1:/tmp/cvs-serv12365/lib/toolbox Modified Files: Makefile Log Message: major refactoring to support a mutable namespace. Index: Makefile =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/lib/toolbox/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Makefile 14 Oct 2003 03:10:24 -0000 1.1 +++ Makefile 17 Nov 2003 19:22:36 -0000 1.2 @@ -1,52 +1,64 @@ include toc.make -SOURCES = \ - ClassLoader.cpp \ - DLLLoader.cpp \ - KeyValueParser.cpp \ - PathFinder.cpp \ - PropertyStore.cpp \ - SimpleCLParser.cpp \ - StdStringTokenizer.cpp \ - StringTokenizer.cpp \ - file_util.cpp \ - string_util.cpp \ - to_string.cpp +# maintenance notes: +# imported via toc: +# $(TOOLBOX_NAMESPACE) -HEADERS = ChildrenHolder.h \ - ClassLoader.h \ - DLLLoader.h \ - Instantiator.h \ - KeyValueParser.h \ - PathFinder.h \ - PointerList.h \ - PropertyStore.h \ - SimpleCLParser.h \ - StdStringTokenizer.h \ - StringTokenizer.h \ - class_name.h \ - debuggering_macros.h \ - eprintf.h \ - file_util.h \ - string_util.h \ - to_string.h \ - toolbox.h +TOOLBOX_NAMESPACE ?= toolbox + +NS_SOURCES = \ + ns.argv_parser.cpp \ + ns.file_util.cpp \ + ns.key_value_parser.cpp \ + ns.property_store.cpp \ + ns.stdstring_tokenizer.cpp \ + ns.string_tokenizer.cpp \ + ns.string_util.cpp \ + ns.to_string.cpp + + +NS_HEADERS = \ + ns.any.h \ + ns.argv_parser.h \ + ns.children_holder.h \ + ns.class_name.h \ + ns.debuggering_macros.h \ + ns.eprintf.h \ + ns.file_util.h \ + ns.key_value_parser.h \ + ns.pointer_list.h \ + ns.property_store.h \ + ns.stdstring_tokenizer.h \ + ns.string_tokenizer.h \ + ns.string_util.h \ + ns.to_string.h \ + ns.type_traits.h -NAMESPACE = toolbox ifeq (1,$(configure_enable_zlib)) -SOURCES += gzstream.cpp -HEADERS += gzstream.h +NS_SOURCES += ns.gzstream.cpp +NS_HEADERS += ns.gzstream.h endif ifeq (1,$(configure_enable_bzlib)) -SOURCES += bzstream.cpp -HEADERS += bzstream.h +NS_SOURCES += ns.bzstream.cpp +NS_HEADERS += ns.bzstream.h endif +SOURCES = $(patsubst ns.%,%,$(NS_SOURCES)) +HEADERS = $(patsubst ns.%,%,$(NS_HEADERS)) +CLEAN_FILES += $(SOURCES) $(HEADERS) + + +NAMESPACE = $(TOOLBOX_NAMESPACE) +NAMESPACE_TOKEN = TOOLBOX_NAMESPACE +NAMESPACE_PREFIX = ns. +NAMESPACE_FILTERED_FILES = $(SOURCES) $(HEADERS) +include $(toc_makesdir)/NAMESPACE.make + top_srcdir_absolute = $(shell cd $(top_srcdir) && pwd) -# DLLLoader_cpp_CPPFLAGS = -DDLLLOADER_DEFAULT_PATH=\".:$(top_srcdir_absolute)/lib/s11n:$(prefix)/lib\" +# dll_loader_cpp_CPPFLAGS = -DCLASS_LOADER_DEFAULT_PATH=\".:$(top_srcdir_absolute)/lib/s11n:$(prefix)/lib\" EPRINTF = eprintf_impl.h @@ -61,28 +73,25 @@ @echo "Creating printf implementations..." $(PERL_BIN) ./makePrintf $(EPRINTF_COUNT) >> $@ -#PACKAGE_NS_H = package_namespace.h -#$(PACKAGE_NS_H): $(PACKAGE_NS_H).at Makefile -# @$(call toc_atparse_file,$<,$@,PACKAGE_NAMESPACE="$(NAMESPACE)") \ -# || exit; touch $@ - -INSTALL_PACKAGE_HEADERS_DEST = $(prefix)/include/$(NAMESPACE) +INSTALL_PACKAGE_HEADERS_DEST = $(prefix)/include/$(TOOLBOX_NAMESPACE) INSTALL_PACKAGE_HEADERS = $(HEADERS) $(EPRINTF) -SYMLINK_HEADERS = $(INSTALL_PACKAGE_HEADERS) -SYMLINK_HEADERS_DEST = $(top_srcdir)/include/$(NAMESPACE) +SYMLINK_HEADERS = $(INSTALL_PACKAGE_HEADERS) +SYMLINK_HEADERS_DEST = $(top_srcdir)/include/$(TOOLBOX_NAMESPACE) include $(toc_makesdir)/symlink_headers.make OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES)) -DIST_FILES += $(SOURCES) $(HEADERS) makePrintf +DIST_FILES += $(NS_SOURCES) $(NS_HEADERS) makePrintf class_names +# DIST_FILES += LoadableClass.cpp LoadableClass.h LoadableSubClass.cpp -all: $(EPRINTF) symlink-headers $(OBJECTS) +all: $(SOURCES) $(HEADERS) $(EPRINTF) symlink-headers $(OBJECTS) +# SHARED_LIBS # $(ENM_NAMESFILE) |
Update of /cvsroot/libfunutil/libfunutil/lib/toolbox In directory sc8-pr-cvs1:/tmp/cvs-serv12245/lib/toolbox Added Files: class_names makePrintf ns.any.h ns.argv_parser.cpp ns.argv_parser.h ns.bzstream.cpp ns.bzstream.h ns.children_holder.h ns.class_name.h ns.debuggering_macros.h ns.eprintf.h ns.file_util.cpp ns.file_util.h ns.gzstream.cpp ns.gzstream.h ns.key_value_parser.cpp ns.key_value_parser.h ns.pointer_list.h ns.property_store.cpp ns.property_store.h ns.stdstring_tokenizer.cpp ns.stdstring_tokenizer.h ns.string_tokenizer.cpp ns.string_tokenizer.h ns.string_util.cpp ns.string_util.h ns.to_string.cpp ns.to_string.h ns.type_traits.h Log Message: egg --- NEW FILE: class_names --- #!/bin/bash # sample usage: # ./class_names "std::map<std::string,std::string>" "std::pair<int,std::string>" test $1x = x && { echo "Usage: $0 class_name1 [class_name2...]" exit 1 } while test $1x != x; do cl=$1 cat <<EOF namespace { template <> struct class_name< $cl > { static const char * name() {return "$cl"; } operator const char * () const { return name(); } }; } EOF shift done --- NEW FILE: ns.any.h --- #ifndef TOOLBOX_ANY_H_INCLUDED #define TOOLBOX_ANY_H_INCLUDED 1 // License: Public Domain // Author: st...@wa... #include <string> #include <iostream> #include "to_string.h" // to/from_string namespace TOOLBOX_NAMESPACE { /** * Completely untested. * A generic 'any' type inspired by, but not based on, * boost::any. It is used to store arbitrary values which can * be "cast" (so to speak, though no casting is used) to * arbitrary types. It supports any types which are * i/ostreamable. * See the namespace-scope <code>make_any()</code> function for a conventient way * to create populated any's. * Sample usage: * <pre> * #include <any.h> * using TOOLBOX_NAMESPACE; * void any_test() * { * any a = "12.12"; * #define TESTANY(vaL,typE,defaulT) a = make_any( vaL ); std::cout << "any("<<a<<").get<"<<#typE<<">(err=["<<defaulT<<"]) = " << a.get<typE>(defaulT) << std::endl; * TESTANY(17.17,double,-1.0); * TESTANY(123.90,string,"error"); * TESTANY(123.90,double,-1.0); * TESTANY(123.90,int,-42); * TESTANY("",int,-1); * TESTANY("hi!",int,-1); * TESTANY("17.12732",double,-1.0); * TESTANY("this is a string",std::string,"error"); * TESTANY("this is a string",int,-1); * } * </pre> * will output: * <pre> * any(17.170000).get<double>(err=[-1]) = 17.17 * any(123.900000).get<string>(err=[error]) = 123.900000 * any(123.900000).get<double>(err=[-1]) = 123.9 * any(123.900000).get<int>(err=[-42]) = 123 * any().get<int>(err=[-1]) = -1 * any(hi!).get<int>(err=[-1]) = -1 * any(17.12732).get<double>(err=[-1]) = 17.1273 * any(this is a string).get<std::string>(err=[error]) = this is a string * any(this is a string).get<int>(err=[-1]) = -1 * </pre> */ class any { public: /** Creates an empty any. */ any(){} ~any() {} /** Creates any with a copy of a's value. */ any( const any & a ) : m_val(a.m_val) {} /** Copies value from rhs into this object. */ any & operator = ( const any & rhs ) { this->m_val = rhs.m_val; return *this; } // todo: template < typename ValueType > any(const ValueType & val ) : m_val(TOOLBOX_NAMESPACE::to_string( val )) {} template<typename ValueType> any & operator=(const ValueType & val ) { this->m_val = TOOLBOX_NAMESPACE::to_string( val ); return *this; } /** Returns this object's value, converted to type T, returning default_or_error_val if the value cannot be converted. T must be i/ostreamable. If a valid default_or_error_val is not immediately available, e.g., if any given integer is valid for a call to get<int>(), clients can still check for an error by checking twice against different error values: <pre> any a = make_any( 0 ); if( ( 0 == a.get<int>(0) ) && (-1 == a.get<int>(-1) ) ) error... </pre> This works because if the any can validly be converted to the first default_or_error_val then it <i>cannot</i> also be validly converted to the second default_or_error_val. Thus, if the default_or_error_val is returned on both calls the client knows that the any was not convertable to the templatized type. This property is the main reason that this class uses no exceptions. ***/ template <typename T> T get( const T & default_or_error_val = T() ) const { return TOOLBOX_NAMESPACE::from_string( this->m_val, default_or_error_val ); } /** Sets this object's value to an internal representation of val. T must be i/ostreamable. */ template <typename T> void set( const T & val ) { this->m_val = TOOLBOX_NAMESPACE::to_string( val ); } /** Sends the internal representation of A's value to the given ostream. */ friend std::ostream & operator<<( std::ostream & os, const any & A ); private: std::string m_val; }; /** Sends the internal representation of A to the given ostream. */ std::ostream & operator<<( std::ostream & os, const any & a ) { // declared in TOOLBOX_NAMESPACE::any return os << a.m_val; } /** A non-member convenience function to create an <code>any</code> representing the given value. Similar in usage to <code>std::make_pair()</code>. T must be i/ostreamble. This function should not really be a friend, but it is for documentation reasons. i.e., it's much easier to find this function if it is in the class' documentation. */ template <typename T> static any make_any( const T & value ) { return any( TOOLBOX_NAMESPACE::to_string( value ) ); } } // namespace #endif // TOOLBOX_ANY_H_INCLUDED --- NEW FILE: ns.argv_parser.cpp --- // Copyright (C) 2002, 2003 st...@wa... // Released under the See LICENSE file in this directory. #include <iostream> #include <stdio.h> // sprintf() #include "stdstring_tokenizer.h" #include "key_value_parser.h" #include "argv_parser.h" #define ARG_PREFIX "-" namespace TOOLBOX_NAMESPACE { argv_parser::argv_parser() { } argv_parser::argv_parser( int argc, char *argv[], int startAt ) { args( argc, argv, startAt ); } argv_parser::~argv_parser() { } void argv_parser::set_help( const std::string &key, const std::string &text ) { this->helpmap.set_string( key, text ); } const std::string argv_parser::getHelp( const std::string &key ) const { std::string help = helpmap.get_string( key ); return help; } std::string argv_parser::get_string( const std::string &key, const std::string & defaultVal ) const { // DO NOT call LIBE_{DEBUG,VERBOSE} from here, or you'll cause an endless loop. std::string check = property_store::get_string( key, defaultVal ); if( check != defaultVal ) return check; if( key.find( "-" ) != 0 ) // non-dashed argument { // now try -key, --key check = key; std::string foo; for( int i = 0; i < 2; i++ ) { check.insert( check.begin(), '-' ); foo = property_store::get_string( check, defaultVal ); //std::cerr << "dash test: " << check << " = " << foo << endl; if( foo != defaultVal ) return foo; } } return defaultVal; } int argv_parser::args( int argc, char *argv[], int startAt, const char *argpre ) { using namespace std; if( startAt >= argc ) return -1; if( ! argv[startAt] ) return -1; std::string argprefix = argpre ? argpre : "-"; int acount = 0; std::string v; std::string a; key_value_parser kvp; std::string nextarg; static const string numbers = "0123456789"; bool skipnext = false; char * dollarstring = (char *) malloc( 10 ); for( int i = startAt; i < argc; i++ ) { ::snprintf( dollarstring,10,"$%d", i ); this->set_string( dollarstring, argv[i] ); if( skipnext ) { skipnext = false; continue; } a = std::string( (const char *)argv[i] ); //CERR << "arg="<<a<<endl; if( a.find(argprefix)!=0 ) continue; v = std::string(); ++acount; if( kvp.parse( a ) ) // check for: --foo=bar { a = kvp.key(); v = kvp.value(); } else // else it's space-separated or a boolean flag { if( i < argc-1 ) { nextarg = std::string(argv[i+1]); if( nextarg == "-" ) { // workaround for things like: myapp --infile - v = "-"; skipnext = true; } else if( nextarg.find(argprefix) == 0 ) { if( nextarg.find_first_of( numbers ) == 1 ) { // let's assume it's a negative number, not a flag // todo: actual atol() or atod() check // Note that this logic means that numbers as flags is not supported. :/ skipnext = true; v = nextarg; } else { // nextarg is argprefix'd, so treat this as a boolean flag v = "true"; } } else { // it was space-separated: --foo bar v = nextarg; skipnext = true; } } else { v = "true"; // the final item is an argument, toggling it to true. } } this->set( a, v ); //CERR << "["<<a<<"] = ["<<v<<"]"<<endl; } free( dollarstring ); return acount; } int argv_parser::args( std::string args, std::string separators ) { // if( args.empty() || args.find( "#" ) == 0 ) return 0; // arguable if( args.empty() ) return 0; stdstring_tokenizer toker; static const int maxargs = 256; char *cargs[maxargs]; // max number of arguments. This size is completely arbitrarily chosen. int count = 0; toker.tokenize( args, separators ); int argbufsize = 1024; while( toker.has_tokens() && count < maxargs - 1) { cargs[count] = (char *)malloc( argbufsize ); // if this isn't enough... there's a problem. strncpy( cargs[count], toker.next_token().c_str(), argbufsize ); // CERR << "parse(): token= [" << cargs[count] << "]" << endl; ++count; } cargs[count] = 0; int ret = count ? this->args( count, cargs, 0, 0 ) : 0; for( int i = 0; i < count; i++ ) free( cargs[i] ); return ret; } const std::string argv_parser::dump_help( bool scv /* show current values? */ ) const { property_store::const_iterator iter = this->helpmap.begin(); std::string outs; std::string key, val, realkey; // outs += "argument_name:"; // if( scv ) outs += " [current value]"; // outs += "\n\thelp text for argument.\n\n"; while( iter != this->helpmap.end() ) { key = (*iter).first; outs += key; outs += ':'; if( scv ) { val = this->get_string( key ); // this handles dashes for us, (*iter).second does not. if( ! val.empty() ) { outs += " ["; outs += val; outs += "]"; } } outs += "\n\t"; outs += this->getHelp( key ); outs += '\n'; ++iter; } outs += "\nAll arguments must start with either - or --, like -help or --help.\n"; outs += "Arguments and their values may optionally be separated by '=', and a '=' is required if the value starts with a '-'.\n"; return outs; } argv_parser & // static argv_parser::args( int argc, char *argv[] ) { argv_parser::args().args( argc, argv, 0 ); return argv_parser::args(); } argv_parser & // static argv_parser::args() { static argv_parser sharedargs; return sharedargs; } bool argv_parser::is_help_set() { return this->is_set( "help" ) || this->is_set( "-?" ) ; } bool argv_parser::is_set( const std::string &key ) const { //std::cout << "is_set( "<<key<<")???"<<endl; if( property_store::is_set( key ) ) return true; if( key.find( "-" ) != 0 ) // non-dashed argument { if( property_store::is_set( string("--")+key ) ) return true; if( property_store::is_set( string("-")+key ) ) return true; } return false; } } // namespace TOOLBOX_NAMESPACE --- NEW FILE: ns.argv_parser.h --- #ifndef ARGV_PARSER_H #define ARGV_PARSER_H 1 // Author: st...@wa... // License: Public Domain #include "property_store.h" namespace TOOLBOX_NAMESPACE { /** argv_parser is an object for parsing command line options. It exists in the s11n source tree only to ease development of test apps, and should not be considered to be part of the core library. Use it like this: <pre> #include <iostream> #include "argv_parser.h" #define VERBOSE if( opts.get( "verbose", false ) ) cerr int main( int argc, char **argv ) { argv_parser & opts = argv_parser::args( argc, argv ); opts.set( "dosomething", ! opts.get_bool( "donothing", false ) ); if( ! opts.get( "dosomething", true ) ) { exit( 0 )); } int myint = opts.get( "width", 20 ); double myangle = opts.get( "angle", 0.0 ); VERBOSE << "This is a verbose message." << endl; return opts.get( "errorcode", 0 ); } </pre> (that code's just off the top of my head - it may not compile as-is.) Note that client code outside of main can then get access to the args via the static function args(): <pre> argv_parser & opts = argv_parser::args(); </pre> See the property_store object's API for a full list of accessor functions. Supported command-line formats: <pre> -foo bar [that is, -foo == "bar"] is the same as: [--foo bar] [-foo=bar] [--foo=bar] -foo -bar false [-foo == true, -bar == false] -foo -bar=false [same] --double-dashed "some string value" --double-dashed="some string value" [same as previous line] </pre> Whether you use single or double dashes is irrelevant, but you must call get() with the same key as was actually passed on the command-line, like so: int width = opts.getInt( "-width", opts.getInt( "--width", 42 ) ); will check for -width first, then --width, defaulting to 42. Alternately, if you use this form: opts.get_string( "foo" ); // WITHOUT a dash the following options are searched: <ol> <li>foo <li>-foo <li>--foo </ol> so the above call may actually result in getting the value from -foo or --foo. This is a potential logic problem if your application uses two semantically-different, like-named arguments like -force and --force. In this case a call to get( "force" ) would find -force and not --force. Use get( "-force" ) or get("--force") to avoid this ambiguity. The dashed versions of an argument are only sought after if get() is called without a dash before the key. These sample dash-searching rules apply to is_set(). A note to Qt users: call args() on this object before calling QApplication a(argc, argv ), or QApplication will steal any argument called -name (and possibly others), removing it from argv. i.e., if you do not call args() on this object first, QApplication may steal arguments so you'll never see them. Been there, done that. Known Bugs and/or gotchyas: Negative numbers: <pre> --boolflag -123=something </pre> will be parsed as: <pre> [--boolflag == true] [-123=something] </pre> Search the .cpp file for 'negative' and you'll find where this bug lives. Since numeric arguments are so rare this is not such a big deal, i think. i can think of only a few real-world examples which use args like -1: ssh, [GNU] xargs, head, tail, lpr, ... okay, maybe they aren't so uncommon :/ Along those same lines: <pre> --bool -234 --foobar </pre> will be parsed as: <pre> [--bool == -234] [--foobar == true] </pre> Which i consider to be correct for most cases. If you want to set --bool to a negative number use: --bool=-123 If you want to force a boolean value in this case: <pre> --bool=true -234 546 </pre> parses as: <pre> --bool=true -234=456 </pre> i hate the inconsistency this adds, though. :/ */ class argv_parser : public property_store { public: /** Creates a new parser using the given arguments array and arg count. */ argv_parser( int argc, char *argv[], int startAt=0 ); argv_parser(); virtual ~argv_parser(); /** args( int, char * ) should be called once from your main() if you want clients to be able to use args() to get at them. */ static argv_parser & args( int argc, char *argv[] ); /** Returns the object containing the arguments supplied to args(int,char**). */ static argv_parser & args(); /** get/set_help() text for a given key. */ virtual void set_help( const std::string &key, const std::string &text ); /** Returns the help text associated with key. */ virtual const std::string getHelp( const std::string &key ) const; /** Re-implemented to check keys -FOO and --FOO if key FOO is not found. */ virtual bool is_set( const std::string &key ) const; /** get_string() is overridden to add a special case to all get() calls made via the property_store API: if a get() function is called with a key which does not start with a dash (-) character and they key cannot be found in our list then -key and --key will be tried. This means that, assuming the above sample code is in place, the following would work: <pre> ~/ > myapp --foo=17.34 ... double d = opts.getDouble( "foo", 0.0 ); // d == 17.34 </pre> As will this: <pre> opts.set( "--mykey", "myvalue" ); ... cerr << "mykey="<< opts.get_string( "mykey" ) << endl; </pre> Note, however, that command-line arguments passed without a leading dash are not treated as arguments, and will not be inside this object if the command-line arguments are passed in via args(). Additionally, it is important to note that if key is passed in with a leading "-" then the additional "dash checking" is NOT done. That is, if you call: <pre> opts.get_string( "-d", 0.0 ); </pre> then ONLY the entry -d will match, and not --d. */ virtual std::string get_string( const std::string &key, const std::string & defaultVal = std::string() ) const; /** * Makes a half-hearted attempt to parse out any args (begining with "-"). * Any args without values passed after them are assigned the value true. * Sample valid command lines: * <pre> * foo --a --b foo --c bar --f * (--a and --f == true, --b == "foo" and --c == "bar") * foo --a eat --b this --c "you lazy bum" * (--a==eat, --b==this, --c=="you lazy bum") * foo --a=b --c d * (--a == b, --c == d) </pre> * * These are identical for purposes of get( "c" ): <pre> * [... -c=-1.0 ...] [... -c -1.0 ...] [... --c 1.0 ...] [... --c=1.0 ...] </pre> * * * To get the values, call the property_store API functions like: <pre> * int foo = parser.getInt( "--i" ); // getInt("i") now works for -i or --i :) * bool bar = parser.get_bool( "--b" ); // or get_bool( "b") for -b or --b </pre> * 'startat' says which element in argv[] to start with. * * If argpre = 0 then it uses the default argument prefix (defaults to "-"). * If it is >0 then that is used as a char * prefix * for all arguments. * * This function also stores all processed values in a way familiar to bash and perl users: * $0 = the first argument, * $1 = the second arg * etc. * Thus given: <pre> * ./foo --arg1 val1 --arg2=foo </pre> * We have: <pre> * myargs["$1"] == "--arg1" * myargs["$3"] == "--arg2=foo" (it is arguably useful to split these, but then usage would be * inconsistent with bash/perl. However, as it is now it is inconsistent * with the results of "--arg2 foo" :/) </pre> * Note that the values are added to this object (or overwrite existing entries), and the list * is not cleared by this function. */ virtual int args( int argc, char *argv[], int startAt, const char *argpre = "-" ); /** * Similar to parse( int... ) except that this one reads a whole line of options, parses that into * an array, then passes it to parse(...). Note that this _may_ (but should not, ideally) behave slightly * differently from arguments passed to the other form, which typically come in as command-line args * (parsed by your shell). This functions uses a stdstring_tokenizer to do it's parsing, so * any differences in behaviour should be resolved there. i am not aware of any differences. */ virtual int args( std::string args, std::string separators = " " ); /** Creates a "usage"-like string for this object containing all keys for which set_help() has been called. If showcurrentvals is true then the current values are also added to th string, otherwise they are left out. Note that the order of the dumped help text/keys is alphabetic (because that's how the container object stores them). TODO: maintain the order of args, using the order from set_help(). Sample: <pre> in main() do: argv_parser & args = argv_parser::args( argc, argv ); if( args.is_hel_set() ) { // triggers on --help, -help, -? or --? cerr << args.dump_help(); exit( 0 ); // some apps exit with a non-zero for help, some don't. } </pre> */ virtual const std::string dump_help( bool showcurrentvals = true ) const; /** Returns true if -help --help, -? or --? is set. */ virtual bool is_help_set(); private: property_store helpmap; }; }; // namespace TOOLBOX_NAMESPACE #endif // ARGV_PARSER_H --- NEW FILE: ns.bzstream.cpp --- // ============================================================================ // bzstream, C++ iostream classes wrapping the zlib compression library. // Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner // Copyright (C) 2003 stephan beal <st...@s1...> // This code is basically a copy/paste of gzstream, adapted for libbz2 // by stephan (2 Oct 2003) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // ============================================================================ // // File : bzstream.cpp // Revision : $Revision: 1.1 $ // Revision_date : $Date: 2003/11/17 19:22:02 $ // Author(s) : Deepak Bandyopadhyay, Lutz Kettner // // Standard streambuf implementation following Nicolai Josuttis, "The // Standard C++ Library". // ============================================================================ #include "bzstream.h" #include <iostream> #include <string.h> // for memcpy #ifdef ZSTREAM_NAMESPACE namespace ZSTREAM_NAMESPACE { #endif // ---------------------------------------------------------------------------- // Internal classes to implement bzstream. See header file for user classes. // ---------------------------------------------------------------------------- // -------------------------------------- // class bzstreambuf: // -------------------------------------- bzstreambuf *bzstreambuf::open( const char *name, int open_mode ) { if ( is_open( ) ) return ( bzstreambuf * ) 0; mode = open_mode; // no append nor read/write mode if ( ( mode & std::ios::ate ) || ( mode & std::ios::app ) || ( ( mode & std::ios::in ) && ( mode & std::ios::out ) ) ) return ( bzstreambuf * ) 0; char fmode[10]; for( unsigned int i = 0; i < sizeof(fmode); i++ ) fmode[i] = '\0'; char *fmodeptr = fmode; if ( mode & std::ios::in ) *fmodeptr++ = 'r'; else if ( mode & std::ios::out ) { *fmodeptr++ = 'w'; if( this->zlevel() >= 0 && this->zlevel() <= 9 ) { *fmodeptr++ = (char)48 + this->zlevel(); // '0' - '9' } } *fmodeptr++ = 'b'; *fmodeptr = '\0'; file = BZ2_bzopen( name, fmode ); if ( file == 0 ) return ( bzstreambuf * ) 0; opened = 1; return this; } bzstreambuf *bzstreambuf::close( ) { if ( is_open( ) ) { sync( ); opened = 0; BZ2_bzclose( file ); int errnum; BZ2_bzerror( file, &errnum ); if( BZ_OK == errnum ) return this; } return ( bzstreambuf * ) 0; } int bzstreambuf::underflow( ) { // used for input buffer only if ( gptr( ) && ( gptr( ) < egptr( ) ) ) return *reinterpret_cast < unsigned char *>( gptr( ) ); if ( !( mode & std::ios::in ) || !opened ) return EOF; // Josuttis' implementation of inbuf int n_putback = gptr( ) - eback( ); if ( n_putback > 4 ) n_putback = 4; memcpy( buffer + ( 4 - n_putback ), gptr( ) - n_putback, n_putback ); int num = BZ2_bzread( file, buffer + 4, bufferSize - 4 ); if ( num <= 0 ) // ERROR or EOF return EOF; // reset buffer pointers setg( buffer + ( 4 - n_putback ), // beginning of putback area buffer + 4, // read position buffer + 4 + num ); // end of buffer // return next character return *reinterpret_cast < unsigned char *>( gptr( ) ); } int bzstreambuf::flush_buffer( ) { // Separate the writing of the buffer from overflow() and // sync() operation. int w = pptr( ) - pbase( ); if ( BZ2_bzwrite( file, pbase( ), w ) != w ) return EOF; pbump( -w ); return w; } int bzstreambuf::overflow( int c ) { // used for output buffer only if ( !( mode & std::ios::out ) || !opened ) return EOF; if ( c != EOF ) { *pptr( ) = c; pbump( 1 ); } if ( flush_buffer( ) == EOF ) return EOF; return c; } int bzstreambuf::sync( ) { // Changed to use flush_buffer() instead of overflow( EOF) // which caused improper behavior with std::endl and flush(), // bug reported by Vincent Ricard. if ( pptr( ) && pptr( ) > pbase( ) ) { if ( flush_buffer( ) == EOF ) return -1; } return 0; } // -------------------------------------- // class bzstreambase: // -------------------------------------- bzstreambase::bzstreambase( const char *name, int mode ) { init( &buf ); open( name, mode ); } bzstreambase::~bzstreambase( ) { buf.close( ); } void bzstreambase::open( const char *name, int open_mode ) { if ( !buf.open( name, open_mode ) ) clear( rdstate( ) | std::ios::badbit ); } void bzstreambase::close( ) { if ( buf.is_open( ) ) if ( !buf.close( ) ) clear( rdstate( ) | std::ios::badbit ); } #ifdef ZSTREAM_NAMESPACE } // namespace ZSTREAM_NAMESPACE #endif // ============================================================================ // EOF // --- NEW FILE: ns.bzstream.h --- // ============================================================================ // bzstream, C++ iostream classes wrapping the bz2lib compression library. // Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner // Copyright (C) 2003 stephan beal <st...@s1...> // // This code is basically a copy/paste of gzstream, adapted for libbz2 // by st...@s1... (2 Oct 2003) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // ============================================================================ // // File : bzstream.h // Revision : $Revision: 1.1 $ // Revision_date : $Date: 2003/11/17 19:22:02 $ // Author(s) : Deepak Bandyopadhyay, Lutz Kettner // // Standard streambuf implementation following Nicolai Josuttis, "The // Standard C++ Library". // ============================================================================ // Changes by st...@s1...: // October, 2003: // - added zlevel() to gzstreambase and gzstreambuf. Only works for ostreams. // - replaced gzip code with bzip code. #ifndef BZSTREAM_H_INCLUDED #define BZSTREAM_H_INCLUDED 1 // standard C++ with new header file names and std:: namespace #include <iostream> #include <fstream> #include <bzlib.h> // libbz2 header #ifndef ZSTREAM_NAMESPACE #define ZSTREAM_NAMESPACE TOOLBOX_NAMESPACE #endif #ifdef ZSTREAM_NAMESPACE namespace ZSTREAM_NAMESPACE { #endif // ---------------------------------------------------------------------------- // Internal classes to implement bzstream. See below for user classes. // ---------------------------------------------------------------------------- class bzstreambuf:public std::streambuf { private: static const int bufferSize = 47 + 256; // size of data buff // totals 512 bytes under g++ for ibzstream at the end. BZFILE * file; // file handle for compressed file char buffer[bufferSize]; // data buffer char opened; // open/close state of stream int mode; // I/O mode int flush_buffer( ); public: bzstreambuf( ):opened( 0 ), m_zlevel(-1) { setp( buffer, buffer + ( bufferSize - 1 ) ); setg( buffer + 4, // beginning of putback area buffer + 4, // read position buffer + 4 ); // end position // ASSERT: both input & output capabilities will not be used together } int is_open( ) { return opened; } bzstreambuf *open( const char *name, int open_mode ); bzstreambuf *close( ); ~bzstreambuf( ) { close( ); } virtual int overflow( int c = EOF ); virtual int underflow( ); virtual int sync( ); /** Defines the compression level, 0 - 9. A value of -1 means use the system-wide zlib default (normally 3). */ void zlevel( int z ) { this->m_zlevel = ( z<0 ? -1 : (z>9?9:z) ) ; } /** Returns the compression level for this stream. */ int zlevel() const { return this->m_zlevel; } private: int m_zlevel; }; /** Base stream class inherited by obzstream/igzstream. Any given instance may not be used for both input and output. Uses gzlib compression, and is compatible with files compressed using bzip2, or any number of other tools which support bz2lib. */ class bzstreambase:virtual public std::ios { private: int m_zlevel; protected: bzstreambuf buf; public: bzstreambase( ) { init( &buf ); } bzstreambase( const char *name, int open_mode ); ~bzstreambase( ); void open( const char *name, int open_mode ); void close( ); void zlevel( int z ) { buf.zlevel(z); } int zlevel() const { return buf.zlevel(); } bzstreambuf *rdbuf( ) { return &buf; } }; /** An input stream which decompresses it's input. Used identically to a std::ifstream. <pre> igzstream ifs( "myfile.bz2" ); </pre> */ class ibzstream:public bzstreambase, public std::istream { public: ibzstream( ):std::istream( &buf ) { } ibzstream( const char *name, int open_mode = std::ios::in ):bzstreambase( name, open_mode ), std::istream( &buf ) { } bzstreambuf *rdbuf( ) { return bzstreambase::rdbuf( ); } void open( const char *name, int open_mode = std::ios::in ) { bzstreambase::open( name, open_mode ); } }; /** An output stream which compresses it's output. Used identically to a std::ofstream: <pre> ogzstream of( "myfile.bz2" ); of << "hello, world!" << std::endl; </pre> */ class obzstream:public bzstreambase, public std::ostream { public: obzstream( ):std::ostream( &buf ) { } obzstream( const char *name, int mode = std::ios::out ):bzstreambase( name, mode ), std::ostream( &buf ) { } bzstreambuf *rdbuf( ) { return bzstreambase::rdbuf( ); } void open( const char *name, int open_mode = std::ios::out ) { bzstreambase::open( name, open_mode ); } }; #ifdef ZSTREAM_NAMESPACE } // namespace ZSTREAM_NAMESPACE #endif #endif // BZSTREAM_H_INCLUDED // ============================================================================ // EOF // --- NEW FILE: ns.children_holder.h --- // Author: stephan beal <st...@s1...> // License: Public Domain #ifndef CHILDRENHOLDER_H_INCLUDED #define CHILDRENHOLDER_H_INCLUDED 1 #include <string> #include <list> #include <map> #include <vector> //#include <deque> // causes crashes in some cases where vector does not :/ #ifndef TYPENAME #define TYPENAME typename // gcc 3.x handles typenames "properly" and gcc 2.95.3 does not, so we must do -DTYPENAME= // for gcc 2.95.3. #endif namespace TOOLBOX_NAMESPACE { /** EXPERIMENTAL! children_holder is an experimental object for creating pointer containers for arbitrary child types. The idea is that many objects i create have a heirarchical structure, and i'm looking for a generic way to code this pattern. The interface should allow any given class, including non-modifiable 3rd-party classes, to have any number of child types. This code does no automatic clean-up of children. Client code may free all child pointers by calling cleanup_parent(), and subclasses or proxies of this object should call that in their dtor. */ template < class PType, class CType > class children_holder { public: /** The type of this object's parents in parent-child relationships. */ typedef PType parent_type; /** The type of this object's children in parent-child relationships. */ typedef CType child_type; /** The container type used to store the lists of children. */ typedef std::vector < child_type * >list_type; /** A shortcut typedef to help ease the implementation code for this class. */ typedef children_holder < parent_type, child_type > ThisType; /** iterator which can be dereferenced to a (child_type *). */ typedef typename list_type::iterator iterator; /** iterator which can be dereferenced to a (const child_type *). */ typedef typename list_type::const_iterator const_iterator; /** Returns the child list for the given parent object. If creationPolicy is non-zero then this function will create the child list if it does not yet exist (in that case, this function will never return NULL except on an out-of-memory error). The caller takes ownership of the returned pointer. All children in the list can be deleted at once by calling cleanup_parent( parent ). Different calls to this function will always return the same list (or the same NULL, depending on creationPolicy ;) until either unmap_parent() or cleanup_parent() are called, in which case further calls to this function may return a different pointer the next time it is called. */ static ThisType::list_type * child_list( const ThisType::parent_type * parent, int creationPolicy = 0 ) { if ( !parent ) return NULL; static ThisType::map_type & cmap = parentChildMap(); typename map_type::const_iterator it = cmap.find( parent ); if ( cmap.end() != it ) return ( *it ).second; if ( 0 == creationPolicy ) return NULL; list_type *cl = new list_type(); cmap[parent] = cl; return cl; } /** Removes parent from this object's internal map. This only removes the pointer to the parent's child list and the mapping which binds the parent to the children, but does not delete() anything. Returns true if it unmaps the parent, else false. It will only fail if it doesn't have an entry for parent. This is more of a maintenance detail than anything else. */ static bool unmap_parent( const ThisType::parent_type * parent ) { if ( !parent ) return false; static ThisType::map_type & cmap = parentChildMap(); TYPENAME ThisType::map_type::iterator it = cmap.find( parent ); if ( it == cmap.end() ) return false; cmap.erase( parent ); return true; } /** Simlar as unmap_parent(), but also deletes the children in the list and then deletes the list. Subclasses or proxies of this class should call this function from their dtor, in order to avoid leaving any dangling pointers in this class' internal data. */ static bool cleanup_parent( const ThisType::parent_type * parent ) { if ( !parent ) return false; static ThisType::map_type & cmap = parentChildMap(); TYPENAME ThisType::map_type::iterator it = cmap.find( parent ); if ( it == cmap.end() ) { // we were probably just never registed because children() was never called. return false; } TYPENAME ThisType::list_type * li = ( *it ).second; if ( !unmap_parent( parent ) ) { return false; } TYPENAME ThisType::list_type::iterator vit; TYPENAME ThisType::child_type * child = 0; for ( vit = li->begin(); li->begin() != li->end() ) { child = ( *vit ); li->erase( vit ); delete( child ); child = 0; } delete( li ); return true; } private: typedef std::map < const ThisType::parent_type *, ThisType::list_type * > map_type; /** i hate working with static objects in template classes (for syntax reasons), and parentChildMap() is a helper to avoid that. */ static map_type & parentChildMap() { static map_type meyers; return meyers; } }; }; // namespace TOOLBOX_NAMESPACE #endif // CHILDRENHOLDER_H_INCLUDED --- NEW FILE: ns.class_name.h --- #ifndef CLASS_NAME_H_INCLUDED #define CLASS_NAME_H_INCLUDED 1 #include <cassert> namespace { // ns is not strictly necessary: works in global-scope as well. /** A utility class to provide human-usable class names, available at runtime. It MUST be specialized to work. Call one of these macros: <pre> CLASS_NAME(Type) CLASS_NAME_ALIAS(Type,AliasForType) </pre> from a class' header file (not an impl file, for complex linking reasons). It may only be called one time per Type per compilation unit, or you will get specialization collisions at compile time. Caveats: - template types with commas in the names will break the macro and... - typedef'd names will get their typedef'd name registered, not their real name. Maybe a feature, maybe not. To get proper names for such cases you must hand-specialize this class. See the macros for a sample implementation, or the class_names shell script which should have come with this class. */ template <class T> struct class_name { /** returns the class name for class T. */ static const char * name() { assert( 0 /* this class_name<> is unspecialized! */ ); return "error::class_name<unspecialized>"; } /** returns the class name for class T. */ operator const char * () const { return name(); } }; } // namespace /** Creates a class_name<> specialization for Type, using the class name Alias. */ #define CLASS_NAME_ALIAS(Type,Alias) \ namespace { \ template <> struct class_name< Type > {\ static const char * name() {return # Alias; }\ operator const char * () const { return name(); }\ };} #define CLASS_NAME(Type) CLASS_NAME_ALIAS(Type,Type) #endif // CLASS_NAME_H_INCLUDED --- NEW FILE: ns.debuggering_macros.h --- #ifndef DEBUGGERING_MACROS_H #define DEBUGGERING_MACROS_H 1 // CERR is a drop-in replacement for std::cerr, but slightly more // decorative. #ifndef CERR #define CERR std::cerr << __FILE__ << ":" << std::dec << __LINE__ << " : " #define CERRL(A) CERR << A << std::endl; #endif #ifndef COUT #define COUT std::cout << __FILE__ << ":" << std::dec << __LINE__ << " : " #define COUTL(A) COUT << A << std::endl; #endif #endif // DEBUGGERING_MACROS_H --- NEW FILE: ns.eprintf.h --- #ifndef EPRINTF_H_INCLUDED #define EPRINTF_H_INCLUDED 1 // License: Public Domain // Author: st...@wa... #include <iostream> #include <sstream> namespace TOOLBOX_NAMESPACE { /** The eprintf()-related functions: (Note: these functions have an "e" prefix ONLY because gcc 2.95.x warns about incorrect number of printf args, even when TOOLBOX_NAMESPACE::printf() is specified :/. Since i needed a prefix, and 'elib' was the library this code originated from, 'e' was the choice.) These functions are auto-generated, and they all follow the pattern set here: template <typename T0> static void esprintf( std::ostream & stream, T0 v0 ); template <typename T0> static void eprintf( T0 v0 ); template <typename T0> static std::string efstring( T0 v0 ); The same functions, taking up to 20 template parameters, are included via eprintf_impl.h (which is generated by makeEPrintf). (The exact number of parameters may be different: it's set in the Makefile.) Sample usage: <pre> cout << TOOLBOX_NAMESPACE::efstring("The int is ",42,". The double is ",42.42,".") << endl; TOOLBOX_NAMESPACE::esprintf(std::cout, "The int is ",42,". The double is ",42.42,".\n"); TOOLBOX_NAMESPACE::eprintf("Simply goes to cout.\n"); </pre> (Note the addition of a \n (or endl) to the string when using the stream-accepting variants.) Design note: the auto-generated sprintf() is more code-repetative than necessary, rather than recursive, to keep down the number of template instantiations. Consider: sprintf(cout,1,2,3,4,5,6,7,8,9,10); If that was implemented recursively, we would have 10 template instantiations (one for each number of arguments, not including the stream). The current impl will only generate 1 tmpl instantiation for that call. For maintenance reasons, printf() and fstring() are implemented in terms of sprintf(), so each unique-parm-count call to printf() or fstring() will incur 2 template instantiations: one for the function and one for the sprintf() it uses. They /could/ be implemented exactly like sprintf(), sparing a function call and a template instantiation, and this may change at some point (if i need a performance scapegoat). i tend to make lots of various printf() calls, but don't call them terribly many times, so i'm not too worried about it at this point. Note that these functions provide no additional functionality whatsoever over using standard streams, except /perhaps/ a nicer-looking calling convention. But, to be frank, i was too stoned to realize that until after the code was complete. ;) (Well, i /do/ get some use out of efstring(), anyway.) */ template <typename T0> static void esprintf( std::ostream & stream, const T0 & v0 ) { stream << v0; }; template <typename T0> static void eprintf( const T0 & v0 ) { TOOLBOX_NAMESPACE::esprintf( std::cout, v0 ); }; template <typename T0> static std::string efstring( const T0 & v0 ) { std::ostringstream stream; TOOLBOX_NAMESPACE::esprintf( stream, v0 ); return stream.str(); }; #include "eprintf_impl.h" }; // namespace TOOLBOX_NAMESPACE #endif // EPRINTF_H_INCLUDED --- NEW FILE: ns.file_util.cpp --- #include <iostream> #include <fstream> #include <map> #include <stdio.h> //fopen()/fread() #include "file_util.h" #include "debuggering_macros.h" // COUT macro #if HAVE_CONFIG_H # include "config.h" #endif #include <fstream> #if HAVE_ZLIB # include "gzstream.h" #endif #if HAVE_BZLIB # include "bzstream.h" #endif namespace TOOLBOX_NAMESPACE { static int m_comp_policy = TOOLBOX_NAMESPACE::NoCompression; void compression_policy( CompressionPolicy c ) { //CERR << "compression_policy = " << c << std::endl; m_comp_policy = c; } int compression_policy() { return m_comp_policy; } std::istream * get_istream( const std::string & filename ) { // if( "-" == filename ) return &std::cin; // i'd like // that, but clients will then delete it :/. One option // might be via tie(), but i have no experience with it. //CERR << "get_istream("<<filename<<")"<<std::endl; enum FTypes { Unknown, GZip, BZip }; std::ifstream check( filename.c_str() ); if( ! check.good() ) return NULL; FILE * inf = fopen( filename.c_str(), "rb" ); if( ! inf ) { CERR << "fopen("<<filename<<") failed!" << std::endl; return NULL; } unsigned char buff[4]; fread( buff, sizeof(buff), 1, inf ); fclose( inf ); #if HAVE_BZLIB // bzip=5a42 3968 (dec: 90 66 57 104) ascii: ZB9h if( 'B' == buff[0] && 'Z' == buff[1] ) { //COUT << "bzip!"<<std::endl; return new TOOLBOX_NAMESPACE::ibzstream( filename.c_str() ); } #endif #if HAVE_ZLIB // gzip=8b1f 0808 (dec: 139 31 8 8) if( 0x1f == buff[0] && 0x8b == buff[1] ) // maybe a bug here? // this ordering is probably big/little endian dependent(?) { //COUT << "gzip!"<<std::endl; return new TOOLBOX_NAMESPACE::igzstream( filename.c_str() ); } #endif return new std::ifstream( filename.c_str() ); } std::ostream * get_ostream( const std::string & fname ) { switch( TOOLBOX_NAMESPACE::compression_policy() ) { #if HAVE_ZLIB case GZipCompression: return new TOOLBOX_NAMESPACE::ogzstream( fname.c_str() ); #endif #if HAVE_BZLIB case BZipCompression: return new TOOLBOX_NAMESPACE::obzstream( fname.c_str() ); #endif default: return new std::ofstream( fname.c_str() ); } } std::string bytes_from_file( const std::string &fn, unsigned int count, bool read_past_nl ) { typedef std::map<std::string,std::string> Map; static Map cache; Map::iterator it = cache.find( fn ); if( it != cache.end() ) return (*it).second; std::istream * is = 0; is = TOOLBOX_NAMESPACE::get_istream( fn ); if( ! is ) return std::string(); if( !is->good() ) { delete( is ); return std::string(); } is->unsetf(std::ios_base::skipws); std::string line; char c; for( unsigned int i = 0; i < count; i++ ) { *is >> c; if( (!read_past_nl) && '\n' == c ) break; if( ! is->good() ) break; line += c; } delete( is ); cache[fn] = line; return line; } } // namespace TOOLBOX_NAMESPACE --- NEW FILE: ns.file_util.h --- #ifndef TOOLKIT_FILE_UTIL_H_INCLUDED #define TOOLKIT_FILE_UTIL_H_INCLUDED 1 #include <string> namespace TOOLBOX_NAMESPACE { /** CompressionPolicy describes the framework-wide policy regarding compression when writing to files. (Sorry, pure stream-based compression isn't yet supported.) Setting to GZip/BZipCompression only enables compression if HAVE_ZLIB or HAVE_BZLIB ars set during library compilation, otherwise non-compressed streams are used in all cases. bzip compresses much better than gzip, but is notably slower. The speed should not make much of a difference unless you are working with very large data sets, and then you will notice that gzip is faster. Tip: you can use get_istream() on an arbitrary filename to get an appropriate input stream. Likewise, use get_ostream() to open writable a file with the policy-mandated stream type (if possible, defaulting to std::ofstream). */ enum CompressionPolicy { /** NoCompression implies just what it says - do not use compressed output streams. */ NoCompression = 1, /** GZipCompression means to use the TOOLBOX_NAMESPACE::ogzstream class for output streams. */ GZipCompression = 2, /** BZipCompression means to use the TOOLBOX_NAMESPACE::obzstream class for output streams. */ BZipCompression = 3 }; /** Sets the framework-wide CompressionPolicy preference. See the TOOLBOX_NAMESPACE::CompressionPolicy enum. */ void compression_policy( CompressionPolicy c ); /*... [truncated message content] |
Update of /cvsroot/libfunutil/libfunutil/lib/toolbox In directory sc8-pr-cvs1:/tmp/cvs-serv10539/lib/toolbox Removed Files: bzstream.cpp bzstream.h ChildrenHolder.h ClassLoader.cpp ClassLoader.h class_name.h debuggering_macros.h DLLLoader.cpp DLLLoader.h eprintf.h file_util.cpp file_util.h gzstream.cpp gzstream.h Instantiator.h KeyValueParser.cpp KeyValueParser.h makePrintf PathFinder.cpp PathFinder.h PointerList.h PropertyStore.cpp PropertyStore.h SimpleCLParser.cpp SimpleCLParser.h StdStringTokenizer.cpp StdStringTokenizer.h StringTokenizer.cpp StringTokenizer.h string_util.cpp string_util.h to_string.cpp to_string.h Log Message: preparing for a massive re-import from a refactored tree. --- bzstream.cpp DELETED --- --- bzstream.h DELETED --- --- ChildrenHolder.h DELETED --- --- ClassLoader.cpp DELETED --- --- ClassLoader.h DELETED --- --- class_name.h DELETED --- --- debuggering_macros.h DELETED --- --- DLLLoader.cpp DELETED --- --- DLLLoader.h DELETED --- --- eprintf.h DELETED --- --- file_util.cpp DELETED --- --- file_util.h DELETED --- --- gzstream.cpp DELETED --- --- gzstream.h DELETED --- --- Instantiator.h DELETED --- --- KeyValueParser.cpp DELETED --- --- KeyValueParser.h DELETED --- --- makePrintf DELETED --- --- PathFinder.cpp DELETED --- --- PathFinder.h DELETED --- --- PointerList.h DELETED --- --- PropertyStore.cpp DELETED --- --- PropertyStore.h DELETED --- --- SimpleCLParser.cpp DELETED --- --- SimpleCLParser.h DELETED --- --- StdStringTokenizer.cpp DELETED --- --- StdStringTokenizer.h DELETED --- --- StringTokenizer.cpp DELETED --- --- StringTokenizer.h DELETED --- --- string_util.cpp DELETED --- --- string_util.h DELETED --- --- to_string.cpp DELETED --- --- to_string.h DELETED --- |
From: <sg...@us...> - 2003-11-17 19:12:17
|
Update of /cvsroot/libfunutil/libfunutil/lib/s11n/parsers In directory sc8-pr-cvs1:/tmp/cvs-serv10332/lib/s11n/parsers Removed Files: flex_lexers.cpp flex_lexers.h Log Message: preparing for a massive re-import from a drastically refactored tree. --- flex_lexers.cpp DELETED --- --- flex_lexers.h DELETED --- |
Update of /cvsroot/libfunutil/libfunutil/lib/s11n In directory sc8-pr-cvs1:/tmp/cvs-serv10332/lib/s11n Removed Files: CompactSerializer.cpp FileLoader.cpp FileLoader.h HexSerializer.cpp .indent.pro node_builder.cpp node_builder.h node_loader.cpp node_loader.h ParenSerializer.cpp S11n.cpp s11n_globals.cpp s11n_globals.h S11n.h s11n_io.cpp s11n_io.h s11n-macros.h s11n_node.cpp s11n_node.h serializable_adapter.h Serializable.cpp Serializable.h Serializer.cpp Serializer.h serializer_loader.cpp serializer_loader.h to_string.h Log Message: preparing for a massive re-import from a drastically refactored tree. --- CompactSerializer.cpp DELETED --- --- FileLoader.cpp DELETED --- --- FileLoader.h DELETED --- --- HexSerializer.cpp DELETED --- --- .indent.pro DELETED --- --- node_builder.cpp DELETED --- --- node_builder.h DELETED --- --- node_loader.cpp DELETED --- --- node_loader.h DELETED --- --- ParenSerializer.cpp DELETED --- --- S11n.cpp DELETED --- --- s11n_globals.cpp DELETED --- --- s11n_globals.h DELETED --- --- S11n.h DELETED --- --- s11n_io.cpp DELETED --- --- s11n_io.h DELETED --- --- s11n-macros.h DELETED --- --- s11n_node.cpp DELETED --- --- s11n_node.h DELETED --- --- serializable_adapter.h DELETED --- --- Serializable.cpp DELETED --- --- Serializable.h DELETED --- --- Serializer.cpp DELETED --- --- Serializer.h DELETED --- --- serializer_loader.cpp DELETED --- --- serializer_loader.h DELETED --- --- to_string.h DELETED --- |
From: <sg...@us...> - 2003-11-17 19:09:15
|
Update of /cvsroot/libfunutil/libfunutil/toc/make In directory sc8-pr-cvs1:/tmp/cvs-serv9726/toc/make Modified Files: NAMESPACE.make Log Message: Added a no-op dummy rule to accomodate some plausible cases. Index: NAMESPACE.make =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/toc/make/NAMESPACE.make,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- NAMESPACE.make 17 Nov 2003 18:23:07 -0000 1.1 +++ NAMESPACE.make 17 Nov 2003 19:08:11 -0000 1.2 @@ -15,6 +15,7 @@ ifeq (,$(NAMESPACE)) $(error You must set the variable NAMESPACE before including this file.) endif +$(top_srcdir)/toc.$(PACKAGE_NAME).make: NAMESPACE_MAKE = $(toc_makesdir)/NAMESPACE.make NAMESPACE_TMPFILE = .toc.NAMESPACE.tmp $(NAMESPACE_FILTERED_FILES): %: $(NAMESPACE_PREFIX)% Makefile $(top_srcdir)/toc.$(PACKAGE_NAME).make $(NAMESPACE_MAKE) |
From: <sg...@us...> - 2003-11-17 19:08:17
|
Update of /cvsroot/libfunutil/libfunutil/toc/sbin In directory sc8-pr-cvs1:/tmp/cvs-serv9545/toc/sbin Modified Files: toc_core.sh Log Message: Fixed sed expr to not bail after the first line, so the toc_run_description can be elsewhere in the file. Index: toc_core.sh =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/toc/sbin/toc_core.sh,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- toc_core.sh 14 Oct 2003 03:43:52 -0000 1.28 +++ toc_core.sh 17 Nov 2003 19:07:17 -0000 1.29 @@ -460,7 +460,7 @@ local desc= toc_find_test $testname && { path=${TOC_FIND_RESULT} - desc=$(sed -ne 's|\#.*toc_run_description.*= *\(.*\)|\1|p;q' ${TOC_FIND_RESULT}); + desc=$(sed -ne 's|\#.*toc_run_description.*= *\(.*\)|\1|p' ${TOC_FIND_RESULT}); } || { toc_die 127 toc_run cannot find script for test $testname. } |
From: <sg...@us...> - 2003-11-17 19:07:58
|
Update of /cvsroot/libfunutil/libfunutil/toc/tests In directory sc8-pr-cvs1:/tmp/cvs-serv9388/toc/tests Modified Files: toc_project_makefile.sh Log Message: removed the run description, since it was marginally inaccurate. Added optional $1, the name of the output file. As an input source, $1.at is expected. This is backwards-compatible. Index: toc_project_makefile.sh =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/toc/tests/toc_project_makefile.sh,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- toc_project_makefile.sh 27 Sep 2003 22:34:03 -0000 1.5 +++ toc_project_makefile.sh 17 Nov 2003 19:06:20 -0000 1.6 @@ -1,8 +1,7 @@ -# toc_run_description = looking for toc.${PACKAGE_NAME}.make.at # Creates toc.${PACKAGE_NAME}.make from toc.${PACKAGE_NAME}.make.at # This file is sought by toc.make (but is always optional) -mf=toc.${PACKAGE_NAME}.make +mf=${1-toc.${PACKAGE_NAME}.make} tmpl=$mf.at test -f $tmpl || { toc_add_make toc_include_project_makefile=0 |