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";' */ |