s11n-cvs Mailing List for s11n: easy object serialization in C++ (Page 3)
Brought to you by:
sgbeal
You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
(95) |
Apr
(43) |
May
(47) |
Jun
(81) |
Jul
(33) |
Aug
(241) |
Sep
(121) |
Oct
(65) |
Nov
(32) |
Dec
(77) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(2) |
Feb
(28) |
Mar
(95) |
Apr
(1) |
May
(38) |
Jun
(112) |
Jul
(89) |
Aug
(23) |
Sep
(28) |
Oct
(7) |
Nov
(66) |
Dec
(112) |
2006 |
Jan
(1) |
Feb
(2) |
Mar
(64) |
Apr
|
May
(9) |
Jun
(5) |
Jul
(2) |
Aug
(16) |
Sep
(20) |
Oct
|
Nov
|
Dec
(9) |
2007 |
Jan
(41) |
Feb
(227) |
Mar
(12) |
Apr
(3) |
May
(3) |
Jun
(63) |
Jul
(14) |
Aug
(1) |
Sep
(3) |
Oct
(9) |
Nov
|
Dec
|
2008 |
Jan
(8) |
Feb
|
Mar
|
Apr
(42) |
May
(65) |
Jun
(20) |
Jul
|
Aug
(16) |
Sep
(6) |
Oct
(8) |
Nov
(38) |
Dec
|
2009 |
Jan
|
Feb
(18) |
Mar
(1) |
Apr
(4) |
May
|
Jun
(7) |
Jul
(6) |
Aug
|
Sep
|
Oct
|
Nov
(10) |
Dec
(1) |
2010 |
Jan
|
Feb
|
Mar
(5) |
Apr
(8) |
May
(3) |
Jun
(5) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2012 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <sg...@us...> - 2009-04-13 18:56:55
|
Revision: 270 http://s11n.svn.sourceforge.net/s11n/?rev=270&view=rev Author: sgbeal Date: 2009-04-13 18:56:42 +0000 (Mon, 13 Apr 2009) Log Message: ----------- Added experimental s11n::node_query class. Modified Paths: -------------- trunk/src/client/sample/experimental.cpp trunk/src/s11n/Makefile Added Paths: ----------- trunk/src/s11n/s11n_node_query.hpp Modified: trunk/src/client/sample/experimental.cpp =================================================================== --- trunk/src/client/sample/experimental.cpp 2009-04-13 18:55:33 UTC (rev 269) +++ trunk/src/client/sample/experimental.cpp 2009-04-13 18:56:42 UTC (rev 270) @@ -27,12 +27,16 @@ #include <s11n.net/s11n/proxy/pod/string.hpp> #include <s11n.net/s11n/proxy/std/vector.hpp> +#if 0 #define S11N_MAP_TYPE_PROXY ::s11n::map::serialize_streamable_map_f #define S11N_MAP_TYPE_DESER_PROXY ::s11n::map::deserialize_streamable_map_f #include <s11n.net/s11n/proxy/std/map.hpp> // ^^^^ those #defines are consumed and undefined by the map reg supermacro +#else +#include <s11n.net/s11n/proxy/std/map.hpp> +#include <s11n.net/s11n/proxy/std/list.hpp> +#endif - //////////////////////////////////////////////////////////////////////// // misc util stuff #include <s11n.net/s11n/s11n_debuggering_macros.hpp> // CERR @@ -906,6 +910,91 @@ bindata_deser::deallocate( debin ); } +#include <s11n.net/s11n/s11n_node_query.hpp> +void do_query() +{ +#if 1 + using namespace s11nlite; + typedef s11nlite::node_type NT; + typedef s11nlite::node_traits NTR; + + NT n; + + typedef std::list<double> ListT; + typedef std::map<int,ListT> MapT; + + MapT map; + for( int i = 0; i < 3; ++i ) + { + ListT & l = map['a'+i]; + for( int x = 0; x < 3; ++x ) + { + l.push_back( x * i ); + } + } + s11nlite::serialize( n, map ); + s11nlite::save( n, std::cout ); + typedef s11n::node_query<NT> QT; + QT q(&n); + +#if 0 + q = q.copy() + .children() + .where( s11n::nq_name_is("pair") ) + .children() + .where( s11n::nq_name_is("first") ) + //.where( s11n::nq_has_prop("second") ) + ; +#else + q.children() + .where( s11n::nq_name_is("pair") ) + .children() + .where( s11n::nq_name_is("first") ) + //.where( s11n::nq_has_prop("second") ) + ; + +#endif + QT q2 = QT(&n) + .children() + .where( s11n::nq_name_is("pair") ) + .children() + //.where( s11n::nq_not( s11n::nq_name_is("first") ) ) + //.where( s11n::nq_name_is("second") ) + //.where( s11n::nq_class_name_is("list" ) ) + //.where( s11n::nq_class_name_is( (ListT const *)0 ) ) + //.where( s11n::nq_class_name_is::class_name<ListT>() ) + .where( s11n::nq_or( + //s11n::nq_class_name_is::class_name<ListT>(), + s11n::nq_name_is("second"), + s11n::nq_class_name_is::class_name<int>() + ) ) + //.copy() + //.children() + .append(q) + //.sort() + //.where( s11n::nq_has_prop("v") ) + ; + //q.intersect( q2 ); + q.onion( q2 ); + //q.append( q2 ) + //q = q2; + //q.sort(); + q.unique(); + QT::iterator it = q.results().begin(); + QT::iterator et = q.results().end(); + size_t count = 1; + COUT << "Matches:\n"; + for( ; et != it; ++it, ++count ) + { + NT const * N = *it; + COUT << "matching node #"<<count + << ": @"<< N + <<": " << NTR::name(*N) + << ':'<<NTR::class_name(*N)<< '\n'; + } +#endif +} + int main( int argc, char **argv ) { @@ -914,12 +1003,13 @@ s11nlite::serializer_class( "parens" ); try { - if(1) and_yet_MORE_TESTS(); + if(0) and_yet_MORE_TESTS(); if(0) do_some_tests(); if(0) do_some_more_tests(); if(0) do_even_more_tests(); if(0) do_version(); - if(1) do_bindata(); + if(0) do_bindata(); + if(1) do_query(); } catch( const std::exception & ex ) { Modified: trunk/src/s11n/Makefile =================================================================== --- trunk/src/s11n/Makefile 2009-04-13 18:55:33 UTC (rev 269) +++ trunk/src/s11n/Makefile 2009-04-13 18:56:42 UTC (rev 270) @@ -37,6 +37,7 @@ s11n_debuggering_macros.hpp \ s11n.hpp \ s11n_node.hpp \ + s11n_node_query.hpp \ serialize.hpp \ serialize.tpp \ tags.hpp \ Added: trunk/src/s11n/s11n_node_query.hpp =================================================================== --- trunk/src/s11n/s11n_node_query.hpp (rev 0) +++ trunk/src/s11n/s11n_node_query.hpp 2009-04-13 18:56:42 UTC (rev 270) @@ -0,0 +1,481 @@ +#ifndef s11n_S11N_NODE_QUERY_HPP_INCLUDED +#define s11n_S11N_NODE_QUERY_HPP_INCLUDED + +//////////////////////////////////////////////////////////////////////// +// s11n_node_query.hpp +// Experimental. Don't use. +// +// License: Public Domain +// Author: st...@s1... +//////////////////////////////////////////////////////////////////////// +#include <string> + +#include <vector> +#include <set> +#include <algorithm> +#include <iterator> +#include <s11n.net/s11n/export.hpp> +#include <s11n.net/s11n/exception.hpp> +#include <s11n.net/s11n/s11n_node.hpp> +#include <s11n.net/s11n/traits.hpp> + +namespace s11n { + + /** + EXPERIMENTAL - do not use! + + This class is for fetching s11n nodes matching certain + criteria. It is somewhat like using an SQL query builder, but + is much more limited in what it can do. + + Notable limitations: + + - Can only work on const nodes. It would seem to be impossible + to consolidate const- and non-const nodes in one API here, + partly because of the "inherited" constness of child nodes. + + - It does a lot of list copying, and it is conceivable that it + may use quite a lot of memory. We could use reference counting + of the internal result sets to reduce this, and may do so if + this class gets any appreciable use. + + + Added in versions 1.3.2/1.2.10. + */ + template <typename NodeType> + class node_query + { + public: + /** The templatized S11nNode type. */ + typedef NodeType node_t; + /** + s11n node traits type. + */ + typedef node_traits<NodeType> traits; + + /** + We cannot re-use traits::child_list_type here b/c we can + only work with const NodeType objects from here. + Additionally, some list operations require sorted lists and + the associated standard routines require random-access + iterators. + */ + typedef std::vector<NodeType const *> node_list; + + /** Internal convenience typedef. */ + typedef std::less<NodeType const *> compare_func; + + /** + Result set iterator type. + */ + typedef typename node_list::const_iterator iterator; + + /** + Creates a new query object which uses src for its + searching. If src is null then it acts like the no-arg + ctor. + */ + explicit node_query( node_t const * src ) + : m_li() + { + if( src ) m_li.push_back(src); + } + + /** + Creates an empty query object, useful only as the target + of assignment. + */ + node_query() + : m_li() + { + } + + /** + The current result list. + */ + node_list const & results() const { return m_li; } + + /** + The current result list. This non-const form + can be used by non-member algorithms to + manipulate a result set. + */ + node_list & results() { return m_li; } + + /** + Modifies this result set in place to contain all results() + items for which clause(item) returns true. + */ + template <typename Ftor> + node_query & where( Ftor clause ) + { + node_query res; + iterator it( m_li.begin() ); + typename node_list::const_iterator et( m_li.end() ); + for( ; et != it; ++it ) + { + if( clause( *it ) ) + { + res.results().push_back(*it); + } + } + m_li.swap( res.m_li ); + return *this; + } + + template <typename Ftor> + node_query where( Ftor clause ) const + { + node_query res; + iterator it( m_li.begin() ); + typename node_list::const_iterator et( m_li.end() ); + for( ; et != it; ++it ) + { + if( clause( *it ) ) + { + res.results().push_back(*it); + } + } + return res; + } + + /** + Modifies this result set in place to contain all child + nodes of all items in in the current result set. + */ + node_query & children() + { + node_query res; + iterator it( m_li.begin() ); + iterator et( m_li.end() ); + node_list & rli( res.results() ); + typedef typename traits::child_list_type NCL; + for( ; et != it; ++it ) + { + node_t const * n = *it; + NCL const & childs( traits::children( *n ) ); + typename NCL::const_iterator cit( childs.begin() ); + typename NCL::const_iterator cet( childs.end() ); + for( ; cit != cet; ++cit ) + { + rli.push_back(*cit); + } + } + m_li.swap( res.m_li ); + return *this; + } + + /** + Creates returns a copy of this object. This may be useful + in certain call-chaining contexts where we don't want to + edit a given query object in-place. + */ + node_query copy() const + { + return *this; + } + + /** + Assigns this object's results to be those from rhs. This + may be useful in certain complex call-chaining contexts. + */ + node_query & assign( node_query const & rhs ) + { + if( this != &rhs ) *this = rhs; + return *this; + } + + /** + Appends rhs.results() to the end of this result set. + */ + node_query & append( node_query const & rhs ) + { + std::copy( rhs.m_li.begin(), rhs.m_li.end(), + std::back_inserter( this->m_li ) + ); + return *this; + } + + /** + Sorts results() in-place using the given comparison + operator, which must follow the conventions required by + std::sort(). + */ + template <typename Compare> + node_query & sort( Compare cmp ) + { + std::sort( this->m_li.begin(), this->m_li.end(), cmp ); + return *this; + } + + /** + Sorts results() in-place using the default comparison + algorithm (which simply compares nodes by their pointer + values). + */ + node_query & sort() + { + return this->sort( compare_func() ); + } + + /** + Sorts this list in-place and removes any duplicate + entries. See sort() for the requirements of the Compare + functor. + */ + template <typename Compare> + node_query & unique( Compare cmp ) + { + this->sort( cmp ); + typedef typename node_list::iterator IT; + IT it = std::unique( this->m_li.begin(), this->m_li.end() ); + if( m_li.end() != it ) m_li.erase( it, m_li.end() ); + return *this; + } + + /** + Equivalent to unique(compre_func()). + */ + node_query & unique() + { + return this->unique( compare_func() ); + } + + + /** + Modifies this result set to include only items which are + both in this set and in rhs, using cmp to do the comparison + (which must conform to the requirements of std::sort() + comparison functions). This set gets sorted as a + side-effect. + */ + template <typename CompFunc> + node_query & intersect( node_query const & rhs, CompFunc cmp ) + { + if( &rhs == this ) return *this; + node_list l1( this->m_li ); + this->m_li.clear(); + std::sort( l1.begin(), l1.end(), cmp ); + node_list l2( rhs.m_li ); + std::sort( l2.begin(), l2.end(), cmp ); + std::set_intersection( l1.begin(), l1.end(), + l2.begin(), l2.end(), + std::back_inserter( this->m_li ), + cmp ); + return *this; + } + + /** + Equivalent to intersect( rhs, compare_func() ). + */ + node_query & intersect( node_query const & rhs ) + { + return this->intersect( rhs, compare_func() ); + } + + /** + Modifies this result set to include any items which are + either in this set or rhs (a union). It uses cmp to do the + comparison (which must conform to the requirements of + std::sort() comparison functions). This set gets sorted as + a side-effect. + + The result set may have duplicate entries. + + It is called onion() instead of union() because union() + is a reserved word in C++. + */ + template <typename CompFunc> + node_query & onion( node_query const & rhs, CompFunc cmp ) + { + if( &rhs == this ) return *this; + node_list l1( this->m_li ); + this->m_li.clear(); + std::sort( l1.begin(), l1.end(), cmp ); + node_list l2( rhs.m_li ); + std::sort( l2.begin(), l2.end(), cmp ); + std::set_union( l1.begin(), l1.end(), + l2.begin(), l2.end(), + std::back_inserter( this->m_li ), + cmp ); + return *this; + } + + /** + Equivalent to union(rhs,compare_func()). + */ + node_query & onion( node_query const & rhs ) + { + return this->onion( rhs, compare_func() ); + } + + private: + /** Result set. */ + node_list m_li; + }; + + /** + A Concept class which exists only to document the query + interface required by node_query. + */ + struct nq_concept + { + /** + Must determine whether n conforms to specific criteria + and return true on success, else false. + */ + template <typename NodeType> + bool operator()( NodeType const * n ) const; + }; + + /** + An nq_concept implementation for querying nodes + which have a specific node name. + */ + struct nq_name_is + { + std::string name; + explicit nq_name_is( std::string const & n ) :name(n) + {} + template <typename NodeType> + bool operator()( NodeType const * n ) const + { + typedef node_traits<NodeType> NTR; + return n + ? (this->name == NTR::name(*n)) + : false; + } + }; + + /** + An nq_concept implementation for querying nodes + which have a specific property. + */ + struct nq_has_prop + { + std::string key; + explicit nq_has_prop( std::string const & n ) : key(n) + {} + template <typename NodeType> + bool operator()( NodeType const * n ) const + { + typedef node_traits<NodeType> NTR; + return n + ? (NTR::is_set( *n, this->key )) + : false; + } + }; + + /** + An nq_concept implementation for querying nodes + which have a specific s11n class name. + */ + struct nq_class_name_is + { + std::string name; + explicit nq_class_name_is( std::string const & n ) :name(n) + {} +#if 0 // awkward to use + template <typename SerT> + nq_class_name_is( SerT const * ) : name(s11n_traits<SerT>::class_name(0)) + { + } +#endif + template <typename NodeType> + bool operator()( NodeType const * n ) const + { + typedef node_traits<NodeType> NTR; + return n + ? (this->name == NTR::class_name(*n)) + : false; + } + + /** + Convenience routine. It is + */ + template <typename SerT> + static nq_class_name_is class_name() + { + return nq_class_name_is( s11n_traits<SerT>::class_name(0) ); + } + }; + + + /** + Negates another node query functor. Ftor must conform to + */ + template <typename Ftor> + struct nq_negate_ftor + { + Ftor func; + nq_negate_ftor( Ftor f ) : func(f) + {} + template <typename NodeType> + bool operator()( NodeType const * n ) const + { + typedef node_traits<NodeType> NTR; + //if( ! n ) throw s11n_exception( S11N_SOURCEINFO, "ng_negate_ftor cannot sensibly react to null nodes!"); + return !func(n); + } + }; + + /** + Convenience routine to create an ng_negate_ftor object. + */ + template <typename Ftor> + nq_negate_ftor<Ftor> nq_not( Ftor f ) + { + typedef nq_negate_ftor<Ftor> x; + return x(f); + } + + /** + A node_query search functor which performs a logical + OR or AND of two nc_concept-compatible functors. + */ + template <typename Ftor1,typename Ftor2,bool IsAnd> + struct nq_andor_ftor + { + Ftor1 func1; + Ftor2 func2; + nq_andor_ftor( Ftor1 f, Ftor2 f2 ) : func1(f),func2(f2) + {} + /** + If IsAnd then returns (func1(n) && func2(n)) + else it returns (func1(n) || func2(n)). + */ + template <typename NodeType> + bool operator()( NodeType const * n ) const + { + return IsAnd + ? (func1(n) && func2(n)) + : (func1(n) || func2(n)); + } + }; + + /** + Convenience function to return a functor for performing + OR-style searches on node_query objects. + */ + template <typename Ftor1, typename Ftor2> + nq_andor_ftor<Ftor1,Ftor2,false> nq_or( Ftor1 f, Ftor2 f2 ) + { + typedef nq_andor_ftor<Ftor1,Ftor2,false> x; + return x(f,f2); + } + + + /** + Convenience function to return a functor for performing + AND-style searches on node_query objects. + */ + template <typename Ftor1, typename Ftor2> + nq_andor_ftor<Ftor1,Ftor2,true> nq_and( Ftor1 f, Ftor2 f2 ) + { + typedef nq_andor_ftor<Ftor1,Ftor2,true> x; + return x(f,f2); + } + +} // namespace s11n + +#endif // s11n_S11N_NODE_QUERY_HPP_INCLUDED This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sg...@us...> - 2009-04-13 18:55:47
|
Revision: 269 http://s11n.svn.sourceforge.net/s11n/?rev=269&view=rev Author: sgbeal Date: 2009-04-13 18:55:33 +0000 (Mon, 13 Apr 2009) Log Message: ----------- Apparently pulled in changes from another tree almost a year ago and never committed? Modified Paths: -------------- trunk/src/s11n/vappendf.cpp Modified: trunk/src/s11n/vappendf.cpp =================================================================== --- trunk/src/s11n/vappendf.cpp 2009-04-13 18:53:59 UTC (rev 268) +++ trunk/src/s11n/vappendf.cpp 2009-04-13 18:55:33 UTC (rev 269) @@ -33,46 +33,74 @@ typedef long double LONGDOUBLE_TYPE; /* -** If VAPPENDF_OMIT_FLOATING_POINT is defined to a true value, then -** floating point conversions are disabled. + If VAPPENDF_OMIT_FLOATING_POINT is defined to a true value, then + floating point conversions are disabled. */ #ifndef VAPPENDF_OMIT_FLOATING_POINT # define VAPPENDF_OMIT_FLOATING_POINT 0 #endif /* -** If VAPPENDF_OMIT_SIZE is defined to a true value, then -** the %n specifier is disabled. + If VAPPENDF_OMIT_SIZE is defined to a true value, then + the %n specifier is disabled. */ #ifndef VAPPENDF_OMIT_SIZE # define VAPPENDF_OMIT_SIZE 0 #endif /* -** If VAPPENDF_OMIT_SQL is defined to a true value, then -** the %q and %Q specifiers are disabled. + If VAPPENDF_OMIT_SQL is defined to a true value, then + the %q and %Q specifiers are disabled. */ -/** -Reminder: the SQL conversion code doesn't compile as-is on C++ -due to constness violations. -*/ #ifndef VAPPENDF_OMIT_SQL # define VAPPENDF_OMIT_SQL 0 #endif /* -** If VAPPENDIF_OMIT_HTML is defined to a true value then the %h (HTML -** escape), %t (URL escape), and %T (URL unescape) specifiers are -** disabled. + If VAPPENDIF_OMIT_HTML is defined to a true value then the %h (HTML + escape), %t (URL escape), and %T (URL unescape) specifiers are + disabled. */ #ifndef VAPPENDIF_OMIT_HTML # define VAPPENDIF_OMIT_HTML 0 #endif /* -** Conversion types fall into various categories as defined by the -** following enumeration. +Most C compilers handle variable-sized arrays, so we enable +that by default. Some (e.g. tcc) do not, so we provide a way +to disable it: set VAPPENDF_HAVE_VARARRAY to 0 + +One approach would be to look at: + + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + +but some compilers support variable-sized arrays even when not +explicitly running in c99 mode. */ +#if !defined(VAPPENDF_HAVE_VARARRAY) +# if defined(__TINYC__) +# define VAPPENDF_HAVE_VARARRAY 0 +# else +# define VAPPENDF_HAVE_VARARRAY 1 +# endif +#endif + +/** +VAPPENDF_CHARARRAY is a helper to allocate variable-sized arrays. +This exists mainly so this code can compile with the tcc compiler. +*/ +#if VAPPENDF_HAVE_VARARRAY +# define VAPPENDF_CHARARRAY(V,N) char V[N+1]; memset(V,0,N+1); +# define VAPPENDF_CHARARRAY_FREE(V) +#else +# define VAPPENDF_CHARARRAY(V,N) char * V = (char *)malloc(N+1); memset(V,0,N+1); +# define VAPPENDF_CHARARRAY_FREE(V) free(V) +#endif + +/* + Conversion types fall into various categories as defined by the + following enumeration. +*/ enum PrintfCategory {etRADIX = 1, /* Integer types. %d, %x, %o, and so forth */ etFLOAT = 2, /* Floating point. %f */ etEXP = 3, /* Exponentional notation. %e and %E */ @@ -101,13 +129,13 @@ }; /* -** An "etByte" is an 8-bit unsigned value. + An "etByte" is an 8-bit unsigned value. */ typedef unsigned char etByte; /* -** Each builtin conversion character (ex: the 'd' in "%d") is described -** by an instance of the following structure + Each builtin conversion character (ex: the 'd' in "%d") is described + by an instance of the following structure */ typedef struct et_info { /* Information about each format field */ char fmttype; /* The format field code letter */ @@ -119,7 +147,7 @@ } et_info; /* -** Allowed values for et_info.flags + Allowed values for et_info.flags */ enum et_info_flags { FLAG_SIGNED = 1, /* True if the value to convert is signed */ FLAG_EXTENDED = 2, /* True if for internal/extended use only. */ @@ -127,12 +155,26 @@ }; /* -** The following table is searched linearly, so it is good to put the -** most frequently used conversion types first. + Historically, the following table was searched linearly, so the most + common conversions were kept at the front. + + Change 2008 Oct 31 by Stephan Beal: we reserve an array or ordered + entries for all chars in the range [32..126]. Format character + checks can now be done in constant time by addressing that array + directly. This takes more static memory, but reduces the time and + per-call overhead costs of vappendf(). */ static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; static const char aPrefix[] = "-x0\000X0"; static const et_info fmtinfo[] = { +/** + If VAPPENDF_FMTINFO_FIXED is 1 then we use the original + implementation: a linear list of entries. Search time is linear. If + VAPPENDF_FMTINFO_FIXED is 0 then we use a fixed-size array which + we index directly using the format char as the key. +*/ +#define VAPPENDF_FMTINFO_FIXED 0 +#if VAPPENDF_FMTINFO_FIXED { 'd', 10, FLAG_SIGNED, etRADIX, 0, 0 }, { 's', 0, FLAG_STRING, etSTRING, 0, 0 }, { 'g', 0, FLAG_SIGNED, etGENERIC, 30, 0 }, @@ -165,22 +207,123 @@ #if !VAPPENDF_OMIT_SIZE { 'n', 0, 0, etSIZE, 0, 0 }, #endif +#else /* VAPPENDF_FMTINFO_FIXED */ + /* + These entries MUST stay in ASCII order, sorted + on their fmttype member! + */ + {' '/*32*/, 0, 0, 0, 0, 0 }, + {'!'/*33*/, 0, 0, 0, 0, 0 }, + {'"'/*34*/, 0, 0, 0, 0, 0 }, + {'#'/*35*/, 0, 0, 0, 0, 0 }, + {'$'/*36*/, 0, 0, 0, 0, 0 }, + {'%'/*37*/, 0, 0, etPERCENT, 0, 0 }, + {'&'/*38*/, 0, 0, 0, 0, 0 }, + {'\''/*39*/, 0, 0, 0, 0, 0 }, + {'('/*40*/, 0, 0, 0, 0, 0 }, + {')'/*41*/, 0, 0, 0, 0, 0 }, + {'*'/*42*/, 0, 0, 0, 0, 0 }, + {'+'/*43*/, 0, 0, 0, 0, 0 }, + {','/*44*/, 0, 0, 0, 0, 0 }, + {'-'/*45*/, 0, 0, 0, 0, 0 }, + {'.'/*46*/, 0, 0, 0, 0, 0 }, + {'/'/*47*/, 0, 0, 0, 0, 0 }, + {'0'/*48*/, 0, 0, 0, 0, 0 }, + {'1'/*49*/, 0, 0, 0, 0, 0 }, + {'2'/*50*/, 0, 0, 0, 0, 0 }, + {'3'/*51*/, 0, 0, 0, 0, 0 }, + {'4'/*52*/, 0, 0, 0, 0, 0 }, + {'5'/*53*/, 0, 0, 0, 0, 0 }, + {'6'/*54*/, 0, 0, 0, 0, 0 }, + {'7'/*55*/, 0, 0, 0, 0, 0 }, + {'8'/*56*/, 0, 0, 0, 0, 0 }, + {'9'/*57*/, 0, 0, 0, 0, 0 }, + {':'/*58*/, 0, 0, 0, 0, 0 }, + {';'/*59*/, 0, 0, 0, 0, 0 }, + {'<'/*60*/, 0, 0, 0, 0, 0 }, + {'='/*61*/, 0, 0, 0, 0, 0 }, + {'>'/*62*/, 0, 0, 0, 0, 0 }, + {'?'/*63*/, 0, 0, 0, 0, 0 }, + {'@'/*64*/, 0, 0, 0, 0, 0 }, + {'A'/*65*/, 0, 0, 0, 0, 0 }, + {'B'/*66*/, 0, 0, 0, 0, 0 }, + {'C'/*67*/, 0, 0, 0, 0, 0 }, + {'D'/*68*/, 0, 0, 0, 0, 0 }, + {'E'/*69*/, 0, FLAG_SIGNED, etEXP, 14, 0 }, + {'F'/*70*/, 0, 0, 0, 0, 0 }, + {'G'/*71*/, 0, FLAG_SIGNED, etGENERIC, 14, 0 }, + {'H'/*72*/, 0, 0, 0, 0, 0 }, + {'I'/*73*/, 0, 0, 0, 0, 0 }, + {'J'/*74*/, 0, 0, 0, 0, 0 }, + {'K'/*75*/, 0, 0, 0, 0, 0 }, + {'L'/*76*/, 0, 0, 0, 0, 0 }, + {'M'/*77*/, 0, 0, 0, 0, 0 }, + {'N'/*78*/, 0, 0, 0, 0, 0 }, + {'O'/*79*/, 0, 0, 0, 0, 0 }, + {'P'/*80*/, 0, 0, 0, 0, 0 }, + {'Q'/*81*/, 0, FLAG_STRING, etSQLESCAPE2, 0, 0 }, + {'R'/*82*/, 0, 0, 0, 0, 0 }, + {'S'/*83*/, 0, 0, 0, 0, 0 }, + {'T'/*84*/, 0, FLAG_STRING, etURLDECODE, 0, 0 }, + {'U'/*85*/, 0, 0, 0, 0, 0 }, + {'V'/*86*/, 0, 0, 0, 0, 0 }, + {'W'/*87*/, 0, 0, 0, 0, 0 }, + {'X'/*88*/, 16, 0, etRADIX, 0, 4 }, + {'Y'/*89*/, 0, 0, 0, 0, 0 }, + {'Z'/*90*/, 0, 0, 0, 0, 0 }, + {'['/*91*/, 0, 0, 0, 0, 0 }, + {'\\'/*92*/, 0, 0, 0, 0, 0 }, + {']'/*93*/, 0, 0, 0, 0, 0 }, + {'^'/*94*/, 0, 0, 0, 0, 0 }, + {'_'/*95*/, 0, 0, 0, 0, 0 }, + {'`'/*96*/, 0, 0, 0, 0, 0 }, + {'a'/*97*/, 0, 0, 0, 0, 0 }, + {'b'/*98*/, 0, 0, 0, 0, 0 }, + {'c'/*99*/, 0, 0, etCHARX, 0, 0 }, + {'d'/*100*/, 10, FLAG_SIGNED, etRADIX, 0, 0 }, + {'e'/*101*/, 0, FLAG_SIGNED, etEXP, 30, 0 }, + {'f'/*102*/, 0, FLAG_SIGNED, etFLOAT, 0, 0}, + {'g'/*103*/, 0, FLAG_SIGNED, etGENERIC, 30, 0 }, + {'h'/*104*/, 0, FLAG_STRING, etHTML, 0, 0 }, + {'i'/*105*/, 10, FLAG_SIGNED, etRADIX, 0, 0}, + {'j'/*106*/, 0, 0, 0, 0, 0 }, + {'k'/*107*/, 0, 0, 0, 0, 0 }, + {'l'/*108*/, 0, 0, 0, 0, 0 }, + {'m'/*109*/, 0, 0, 0, 0, 0 }, + {'n'/*110*/, 0, 0, etSIZE, 0, 0 }, + {'o'/*111*/, 8, 0, etRADIX, 0, 2 }, + {'p'/*112*/, 16, 0, etPOINTER, 0, 1 }, + {'q'/*113*/, 0, FLAG_STRING, etSQLESCAPE, 0, 0 }, + {'r'/*114*/, 10, (FLAG_EXTENDED|FLAG_SIGNED), etORDINAL, 0, 0}, + {'s'/*115*/, 0, FLAG_STRING, etSTRING, 0, 0 }, + {'t'/*116*/, 0, FLAG_STRING, etURLENCODE, 0, 0 }, + {'u'/*117*/, 10, 0, etRADIX, 0, 0 }, + {'v'/*118*/, 0, 0, 0, 0, 0 }, + {'w'/*119*/, 0, FLAG_STRING, etSQLESCAPE3, 0, 0 }, + {'x'/*120*/, 16, 0, etRADIX, 16, 1 }, + {'y'/*121*/, 0, 0, 0, 0, 0 }, + {'z'/*122*/, 0, FLAG_STRING, etDYNSTRING, 0, 0}, + {'{'/*123*/, 0, 0, 0, 0, 0 }, + {'|'/*124*/, 0, 0, 0, 0, 0 }, + {'}'/*125*/, 0, 0, 0, 0, 0 }, + {'~'/*126*/, 0, 0, 0, 0, 0 }, +#endif /* VAPPENDF_FMTINFO_FIXED */ }; -#define etNINFO ((int)(sizeof(fmtinfo)/sizeof(fmtinfo[0]))) +#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) #if ! VAPPENDF_OMIT_FLOATING_POINT /* -** "*val" is a double such that 0.1 <= *val < 10.0 -** Return the ascii code for the leading digit of *val, then -** multiply "*val" by 10.0 to renormalize. + "*val" is a double such that 0.1 <= *val < 10.0 + Return the ascii code for the leading digit of *val, then + multiply "*val" by 10.0 to renormalize. ** -** Example: -** input: *val = 3.14159 -** output: *val = 1.4159 function return = '3' + Example: + input: *val = 3.14159 + output: *val = 1.4159 function return = '3' ** -** The counter *cnt is incremented each time. After counter exceeds -** 16 (the number of significant digits in a 64-bit float) '0' is -** always returned. + The counter *cnt is incremented each time. After counter exceeds + 16 (the number of significant digits in a 64-bit float) '0' is + always returned. */ static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ int digit; @@ -195,12 +338,12 @@ #endif /* !VAPPENDF_OMIT_FLOATING_POINT */ /* -** On machines with a small stack size, you can redefine the -** VAPPENDF_BUF_SIZE to be less than 350. But beware - for -** smaller values some %f conversions may go into an infinite loop. + On machines with a small(?) stack size, you can redefine the + VAPPENDF_BUF_SIZE to be less than 350. But beware - for smaller + values some %f conversions may go into an infinite loop. */ #ifndef VAPPENDF_BUF_SIZE -# define VAPPENDF_BUF_SIZE 350 /* Size of the output buffer */ +# define VAPPENDF_BUF_SIZE 350 /* Size of the output buffer for numeric conversions */ #endif #ifdef VAPPENDF_INT64_TYPE @@ -215,7 +358,7 @@ #endif #if 0 -/** Not yet used. */ +/ Not yet used. */ enum PrintfArgTypes { TypeInt = 0, TypeIntP = 1, @@ -227,10 +370,10 @@ #if 0 -/** Not yet used. */ +/ Not yet used. */ typedef struct vappendf_spec_handler_def { - char letter; /** e.g. %s */ + char letter; / e.g. %s */ int xtype; /* reference to the etXXXX values, or fmtinfo[*].type. */ int ntype; /* reference to PrintfArgTypes enum. */ } spec_handler; @@ -278,7 +421,7 @@ /** - vappendf_spec_handler for etSTRING types. It assumes that varg is a + vappendf_spec_handler for etSTRING types. It assumes that varg is a null-terminated (char [const] *) */ static long spech_string( vappendf_appender pf, @@ -361,7 +504,7 @@ long ret = 0; char ch = *str; char const * hex = "0123456789ABCDEF"; - const int xbufsz = 10; +#define xbufsz 10 char xbuf[xbufsz]; memset( xbuf, 0, xbufsz ); int slen = 0; @@ -379,6 +522,7 @@ ret += pf( pfArg, xbuf, slen ); } } +#undef xbufsz return ret; } @@ -415,8 +559,7 @@ long ret = 0; char ch = 0; char ch2 = 0; - const int xbufsz = 4; - char xbuf[xbufsz]; + char xbuf[4]; int decoded; ch = *str; while( ch ) @@ -485,18 +628,16 @@ int i, j, n, ch, isnull; int needQuote; char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ - char *escarg = (char*) varg; + char const * escarg = (char const *) varg; char * bufpt = 0; - char * strNULL = (char *)"NULL"; - char * strNULL2 = (char *)"(NULL)"; isnull = escarg==0; - if( isnull ) escarg = (xtype==etSQLESCAPE2 ? strNULL : strNULL2); + if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); for(i=n=0; (ch=escarg[i])!=0; i++){ if( ch==q ) n++; } needQuote = !isnull && xtype==etSQLESCAPE2; n += i + 1 + needQuote*2; - bufpt = (char *) malloc( n ); + bufpt = (char *)malloc( n ); if( ! bufpt ) return -1; j = 0; if( needQuote ) bufpt[j++] = q; @@ -537,43 +678,45 @@ /* -** The root printf program. All variations call this core. It -** implements most of the common printf behaviours plus (optionally) -** some extended ones. -** -** INPUTS: -** -** pfAppend : The is a vappendf_appender function which is responsible -** for accumulating the output. If pfAppend returns a negative integer -** then processing stops immediately. -** -** pfAppendArg : is ignored by this function but passed as the first -** argument to pfAppend. pfAppend will presumably use it as a data -** store for accumulating its string. -** -** fmt : This is the format string, as in the usual printf(). -** -** ap : This is a pointer to a list of arguments. Same as in -** vprintf() and friends. -** -** OUTPUTS: -** The return value is the total number of characters sent to -** the function "func". Returns -1 on a error. -** -** Note that the order in which automatic variables are declared below -** seems to make a big difference in determining how fast this beast -** will run. -** -** Much of this code dates back to the early 1980's, supposedly. -** -** -** Known change history (most historic info has been lost): -** -** 10 Feb 2008 by Stephan Beal: refactored to remove the 'useExtended' -** flag (which is now always on). Added the vappendf_appender typedef to -** make this function generic enough to drop into other source trees -** without much work. -** + The root printf program. All variations call this core. It + implements most of the common printf behaviours plus (optionally) + some extended ones. + + INPUTS: + + pfAppend : The is a vappendf_appender function which is responsible + for accumulating the output. If pfAppend returns a negative integer + then processing stops immediately. + + pfAppendArg : is ignored by this function but passed as the first + argument to pfAppend. pfAppend will presumably use it as a data + store for accumulating its string. + + fmt : This is the format string, as in the usual printf(). + + ap : This is a pointer to a list of arguments. Same as in + vprintf() and friends. + + OUTPUTS: + + The return value is the total number of characters sent to the + function "func". Returns -1 on a error. + + Note that the order in which automatic variables are declared below + seems to make a big difference in determining how fast this beast + will run. + + Much of this code dates back to the early 1980's, supposedly. + + Known change history (most historic info has been lost): + + 10 Feb 2008 by Stephan Beal: refactored to remove the 'useExtended' + flag (which is now always on). Added the vappendf_appender typedef to + make this function generic enough to drop into other source trees + without much work. + + 31 Oct 2008 by Stephan Beal: refactored the et_info lookup to be + constant-time instead of linear. */ long vappendf( vappendf_appender pfAppend, /* Accumulate results here */ @@ -581,7 +724,17 @@ const char *fmt, /* Format string */ va_list ap /* arguments */ ){ + /** + HISTORIC NOTE (author and year unknown): + + Note that the order in which automatic variables are declared below + seems to make a big difference in determining how fast this beast + will run. + */ + +#if VAPPENDF_FMTINFO_FIXED const int useExtended = 1; /* Allow extended %-conversions */ +#endif long outCount = 0; /* accumulated output count */ int pfrc = 0; /* result from calling pfAppend */ int c; /* Next character in the format string */ @@ -614,28 +767,23 @@ etByte flag_rtz; /* True if trailing zeros should be removed */ etByte flag_exp; /* True to force display of the exponent */ int nsd; /* Number of significant digits returned */ - // Kludges necessary to avoid const violations when compiling this code as C++: - char * strNaN = (char *)"NaN"; - char * strInf = (char *)"Inf"; - char * strInfPos = (char *)"Inf+"; - char * strInfNeg = (char *)"Inf+"; #endif - /* VAPPENDF_RETURN, VAPPENDF_ACCUM, and VAPPENDF_SPACES + /* VAPPENDF_RETURN, VAPPENDF_CHECKERR, and VAPPENDF_SPACES are internal helpers. */ #define VAPPENDF_RETURN if( zExtra ) free(zExtra); return outCount; -#define VAPPENDF_ACCUM if( pfrc<0 ) { VAPPENDF_RETURN; } else outCount += pfrc; -#define VAPPENDF_SPACES(N) if(1){ \ - char zSpaces[N]; \ - memset( zSpaces,' ',N); \ - pfrc = pfAppend(pfAppendArg, zSpaces, N); \ - VAPPENDF_ACCUM; \ - } +#define VAPPENDF_CHECKERR(FREEME) if( pfrc<0 ) { VAPPENDF_CHARARRAY_FREE(FREEME); VAPPENDF_RETURN; } else outCount += pfrc; +#define VAPPENDF_SPACES(N) \ +if(1){ \ + VAPPENDF_CHARARRAY(zSpaces,N); \ + memset( zSpaces,' ',N); \ + pfrc = pfAppend(pfAppendArg, zSpaces, N); \ + VAPPENDF_CHECKERR(zSpaces); \ + VAPPENDF_CHARARRAY_FREE(zSpaces); \ +} -/* char const * zSpaces = " "; */ -/* const int zSpacesLen = strlen( zSpaces ); */ length = 0; bufpt = 0; for(; (c=(*fmt))!=0; ++fmt){ @@ -645,13 +793,13 @@ amt = 1; while( (c=(*++fmt))!='%' && c!=0 ) amt++; pfrc = pfAppend( pfAppendArg, bufpt, amt); - VAPPENDF_ACCUM; + VAPPENDF_CHECKERR(0); if( c==0 ) break; } if( (c=(*++fmt))==0 ){ errorflag = 1; pfrc = pfAppend( pfAppendArg, "%", 1); - VAPPENDF_ACCUM; + VAPPENDF_CHECKERR(0); break; } /* Find out what flags are present */ @@ -719,20 +867,32 @@ } /* Fetch the info entry for the field */ infop = 0; +#if VAPPENDF_FMTINFO_FIXED for(idx=0; idx<etNINFO; idx++){ if( c==fmtinfo[idx].fmttype ){ infop = &fmtinfo[idx]; if( useExtended || (infop->flags & FLAG_EXTENDED)==0 ){ xtype = infop->type; }else{ - VAPPENDF_RETURN; + VAPPENDF_RETURN; } break; } } +#else +#define FMTNDX(N) (N - fmtinfo[0].fmttype) +#define FMTINFO(N) (fmtinfo[ FMTNDX(N) ]) + infop = ((c>=(fmtinfo[0].fmttype)) && (c<fmtinfo[etNINFO-1].fmttype)) + ? &FMTINFO(c) + : 0; + //fprintf(stderr,"char '%c'/%d @ %d, type=%c/%d\n",c,c,FMTNDX(c),infop->fmttype,infop->type); + if( infop ) xtype = infop->type; +#undef FMTINFO +#undef FMTNDX +#endif /* VAPPENDF_FMTINFO_FIXED */ zExtra = 0; - if( infop==0 ){ - VAPPENDF_RETURN; + if( (!infop) || (!infop->type) ){ + VAPPENDF_RETURN; } @@ -742,25 +902,25 @@ } /* - ** At this point, variables are initialized as follows: + At this point, variables are initialized as follows: ** - ** flag_alternateform TRUE if a '#' is present. - ** flag_altform2 TRUE if a '!' is present. - ** flag_plussign TRUE if a '+' is present. - ** flag_leftjustify TRUE if a '-' is present or if the - ** field width was negative. - ** flag_zeropad TRUE if the width began with 0. - ** flag_long TRUE if the letter 'l' (ell) prefixed - ** the conversion character. - ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed - ** the conversion character. - ** flag_blanksign TRUE if a ' ' is present. - ** width The specified field width. This is - ** always non-negative. Zero is the default. - ** precision The specified precision. The default - ** is -1. - ** xtype The class of the conversion. - ** infop Pointer to the appropriate info struct. + flag_alternateform TRUE if a '#' is present. + flag_altform2 TRUE if a '!' is present. + flag_plussign TRUE if a '+' is present. + flag_leftjustify TRUE if a '-' is present or if the + field width was negative. + flag_zeropad TRUE if the width began with 0. + flag_long TRUE if the letter 'l' (ell) prefixed + the conversion character. + flag_longlong TRUE if the letter 'll' (ell ell) prefixed + the conversion character. + flag_blanksign TRUE if a ' ' is present. + width The specified field width. This is + always non-negative. Zero is the default. + precision The specified precision. The default + is -1. + xtype The class of the conversion. + infop Pointer to the appropriate info struct. */ switch( xtype ){ case etPOINTER: @@ -795,6 +955,7 @@ } bufpt = &buf[VAPPENDF_BUF_SIZE-1]; if( xtype==etORDINAL ){ + /** i sure would like to shake the hand of whoever figured this out: */ static const char zOrd[] = "thstndrd"; int x = longvalue % 10; if( x>=4 || (longvalue/10)%10==1 ){ @@ -857,8 +1018,12 @@ exp = 0; #if 1 if( (realvalue)!=(realvalue) ){ - /* from sqlite3: #define sqlite3_isnan(X) ((X)!=(X)) */ - bufpt = strNaN; + /* from sqlite3: #define sqlite3_isnan(X) ((X)!=(X)) */ + /* This weird array thing is to avoid constness violations + when assinging, e.g. "NaN" to bufpt. + */ + static char NaN[4] = {'N','a','N','\0'}; + bufpt = NaN; length = 3; break; } @@ -871,11 +1036,14 @@ while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; } if( exp>350 || exp<-350 ){ if( prefix=='-' ){ - bufpt = strInfNeg; + static char Inf[5] = {'-','I','n','f','\0'}; + bufpt = Inf; }else if( prefix=='+' ){ - bufpt = strInfPos; + static char Inf[5] = {'+','I','n','f','\0'}; + bufpt = Inf; }else{ - bufpt = strInf; + static char Inf[4] = {'I','n','f','\0'}; + bufpt = Inf; } length = strlen(bufpt); break; @@ -883,8 +1051,8 @@ } bufpt = buf; /* - ** If the field type is etGENERIC, then convert to either etEXP - ** or etFLOAT, as appropriate. + If the field type is etGENERIC, then convert to either etEXP + or etFLOAT, as appropriate. */ flag_exp = xtype==etEXP; if( xtype!=etFLOAT ){ @@ -926,7 +1094,7 @@ *(bufpt++) = '.'; } /* "0" digits after the decimal point but before the first - ** significant digit of the number */ + significant digit of the number */ for(e2++; e2<0 && precision>0; precision--, e2++){ *(bufpt++) = '0'; } @@ -964,13 +1132,13 @@ *bufpt = 0; /* The converted number is in buf[] and zero terminated. Output it. - ** Note that the number is in the usual order, not reversed as with - ** integer conversions. */ + Note that the number is in the usual order, not reversed as with + integer conversions. */ length = bufpt-buf; bufpt = buf; /* Special case: Add leading zeros if the flag_zeropad flag is - ** set and we are not left justified */ + set and we are not left justified */ if( flag_zeropad && !flag_leftjustify && length < width){ int i; int nPad = width - length; @@ -1011,7 +1179,7 @@ vappendf_spec_handler spf = (xtype==etSTRING) ? spech_string : spech_dynstring; pfrc = spf( pfAppend, pfAppendArg, bufpt ); - VAPPENDF_ACCUM; + VAPPENDF_CHECKERR(0); length = 0; if( precision>=0 && precision<length ) length = precision; } @@ -1020,19 +1188,19 @@ case etHTML: bufpt = va_arg(ap,char*); pfrc = spech_string_to_html( pfAppend, pfAppendArg, bufpt ); - VAPPENDF_ACCUM; + VAPPENDF_CHECKERR(0); length = 0; break; case etURLENCODE: bufpt = va_arg(ap,char*); pfrc = spech_urlencode( pfAppend, pfAppendArg, bufpt ); - VAPPENDF_ACCUM; + VAPPENDF_CHECKERR(0); length = 0; break; case etURLDECODE: bufpt = va_arg(ap,char *); pfrc = spech_urldecode( pfAppend, pfAppendArg, bufpt ); - VAPPENDF_ACCUM; + VAPPENDF_CHECKERR(0); length = 0; break; #endif /* VAPPENDIF_OMIT_HTML */ @@ -1049,16 +1217,16 @@ ); bufpt = va_arg(ap,char*); pfrc = spf( pfAppend, pfAppendArg, bufpt ); - VAPPENDF_ACCUM; + VAPPENDF_CHECKERR(0); length = 0; if( precision>=0 && precision<length ) length = precision; } #endif /* !VAPPENDF_OMIT_SQL */ }/* End switch over the format type */ /* - ** The text of the conversion is pointed to by "bufpt" and is - ** "length" characters long. The field width is "width". Do - ** the output. + The text of the conversion is pointed to by "bufpt" and is + "length" characters long. The field width is "width". Do + the output. */ if( !flag_leftjustify ){ int nspace; @@ -1069,7 +1237,7 @@ } if( length>0 ){ pfrc = pfAppend( pfAppendArg, bufpt, length); - VAPPENDF_ACCUM; + VAPPENDF_CHECKERR(0); } if( flag_leftjustify ){ int nspace; @@ -1088,7 +1256,7 @@ #undef VAPPENDF_SPACES -#undef VAPPENDF_ACCUM +#undef VAPPENDF_CHECKERR #undef VAPPENDF_RETURN #undef VAPPENDF_OMIT_FLOATING_POINT #undef VAPPENDF_OMIT_SIZE @@ -1097,9 +1265,9 @@ #undef VAPPENDIF_OMIT_HTML long appendf(vappendf_appender pfAppend, /* Accumulate results here */ - void * pfAppendArg, /* Passed as first arg to pfAppend. */ - const char *fmt, /* Format string */ - ... ) + void * pfAppendArg, /* Passed as first arg to pfAppend. */ + const char *fmt, /* Format string */ + ... ) { va_list vargs; va_start( vargs, fmt ); @@ -1108,6 +1276,125 @@ return ret; } + +long vappendf_FILE_appender( void * a, char const * s, long n ) +{ + FILE * fp = (FILE *)a; + if( ! fp ) return -1; + long ret = fwrite( s, sizeof(char), n, fp ); + return (ret >= 0) ? ret : -2; +} + + +long fappendf( FILE * fp, char const * fmt, ... ) +{ + va_list vargs; + va_start( vargs, fmt ); + int ret = vappendf( vappendf_FILE_appender, fp, fmt, vargs ); + va_end(vargs); + return ret; +} + + +#define VAPPENDF_OMIT_MAPPENDF 0 +#if !VAPPENDF_OMIT_MAPPENDF + +/** + Internal type for holding a string buffer for use + as a vappendf() target. + */ +struct cstring_appender_t +{ + int pos; + int len; + char * str; +}; +typedef struct cstring_appender_t cstring_appender_t; +/** + A vappendf_appender implementation which writes out all data to the + a pre-allocated string. + + It requires that dest be a pointer to an initialized + cstring_appender_t. If either s or n are 0 then 0 is returned. + + Returns: + + Success: n + + If (!ap), -1. + + If n bytes will not fit in the target string (according to dest->len), + then -2 is returned. +*/ +long vappendf_cstring_appender( void * dest, char const * s, long n ) +{ + if( !s || !n ) return 0; + cstring_appender_t * ap = (cstring_appender_t*)dest; + if( ! ap ) return -1; + if( (ap->pos + n) > ap->len ) return -2; + memcpy( ap->str + ap->pos, s, n ); + ap->pos += n; + return n; +} + + +char * vmnprintf( int len, char const *fmt, va_list vargs ) +{ + if( len < 1 ) return 0; + if( ! fmt ) return 0; + int reallen = len + 1; + char * ret = (char *) malloc(reallen); + cstring_appender_t cap; + cap.pos = 0; + cap.len = len; + cap.str = ret; + memset( ret, 0, reallen ); + long flen = 0; + flen = vappendf( vappendf_cstring_appender, &cap, fmt, vargs ); + /* reminder: flen cannot be >len now because vappendf_cstring_appender + rejects input at that point. + */ + if( flen < 0 ) + { + free( ret ); + return 0; + } + if( flen < reallen ) + { + ret = (char *)realloc( ret, flen + 1 ); + } + ret[flen] = 0; + return ret; +} + +char * mnprintf( int len, char const * fmt, ... ) +{ + va_list vargs; + va_start( vargs, fmt ); + char * ret = vmnprintf( len, fmt, vargs ); + va_end(vargs); + return ret; +} + +char * vmprintf( char const * fmt, va_list vargs ) +{ + return fmt + ? vmnprintf( 1024 * 4, fmt, vargs ) + : (char *)0; +} + +char * mprintf( char const * fmt, ... ) +{ + va_list vargs; + va_start( vargs, fmt ); + char * ret = vmprintf( fmt, vargs ); + va_end(vargs); + return ret; +} + +#endif // VAPPENDF_OMIT_MAPPENDF +#undef VAPPENDF_OMIT_MAPPENDF + static long vappendf_ostream_appender( void * osptr, char const * s, long n ) { std::ostream & os = *(static_cast<std::ostream *>(osptr)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sg...@us...> - 2009-04-13 18:54:03
|
Revision: 268 http://s11n.svn.sourceforge.net/s11n/?rev=268&view=rev Author: sgbeal Date: 2009-04-13 18:53:59 +0000 (Mon, 13 Apr 2009) Log Message: ----------- Fixed an old build bug. Modified Paths: -------------- trunk/src/client/s11nconvert/Makefile Modified: trunk/src/client/s11nconvert/Makefile =================================================================== --- trunk/src/client/s11nconvert/Makefile 2009-04-13 18:53:02 UTC (rev 267) +++ trunk/src/client/s11nconvert/Makefile 2009-04-13 18:53:59 UTC (rev 268) @@ -10,13 +10,13 @@ s11nconvert.BIN.OBJECTS = main.o argv_parser.o s11nconvert.BIN.LDADD = -rdynamic $(LIBS11N_CLIENT_INTREE_LDADD) $(call toc2.call.rules.c-bin,s11nconvert) - all: s11nconvert.BIN + all: $(s11nconvert.BIN) else c-bins.list := s11nconvert s11nconvert.BIN.OBJECTS = main.o argv_parser.o s11nconvert.BIN.LDADD = -rdynamic $(LIBS11N_CLIENT_INTREE_LDADD) include $(toc2.dirs.makefiles)/c-bins.make - all: s11nconvert.BIN + all: $(s11nconvert.BIN) endif package.install.bins = $(s11nconvert.BIN) package.install.man1 = s11nconvert.1 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sg...@us...> - 2009-04-13 18:53:08
|
Revision: 267 http://s11n.svn.sourceforge.net/s11n/?rev=267&view=rev Author: sgbeal Date: 2009-04-13 18:53:02 +0000 (Mon, 13 Apr 2009) Log Message: ----------- Tiny build updates. Modified Paths: -------------- trunk/toc2/make/c-bins.make trunk/toc2/make/doxygen.make Modified: trunk/toc2/make/c-bins.make =================================================================== --- trunk/toc2/make/c-bins.make 2009-02-22 10:46:31 UTC (rev 266) +++ trunk/toc2/make/c-bins.make 2009-04-13 18:53:02 UTC (rev 267) @@ -11,8 +11,8 @@ # c-bins.OBJECTS (optional - list of .o files to link to all c-bins.list) # # For each FOO in c-bins, define: -# FOO.bin.OBJECTS = list of .o files for FOO -# FOO.bin.LDADD = optional arguments to pass to linker, e.g. -lstdc++ +# FOO.BIN.OBJECTS = list of .o files for FOO +# FOO.BIN.LDADD = optional arguments to pass to linker, e.g. -lstdc++ # # Reminder: when linking binaries which will use dlopen() at some point, you # should add -rdynamic to the xxx.bin.LDADD flags. Without this, symbols won't be @@ -44,11 +44,11 @@ c-bins.RULES_GENERATOR = $(toc2.dirs.makefiles)/makerules.c-bins -c-bins.COMMON_DEPS += $(toc.2.files.makefile) $(c-bins.makefile) $(c-bins.objects) +c-bins.COMMON_DEPS += $(toc2.files.makefile) $(c-bins.makefile) $(c-bins.objects) ifeq (1,$(toc2.flags.making_clean)) $(c-bins.DEPSFILE): ; @true else -$(c-bins.DEPSFILE): $(toc.2.files.makefile) $(c-bins.RULES_GENERATOR) $(c-bins.makefile) +$(c-bins.DEPSFILE): $(toc2.files.makefile) $(c-bins.RULES_GENERATOR) $(c-bins.makefile) @echo "Generating c-bins rules: $(c-bins.list)"; \ $(call toc2.call.generate-rules,c-bins,$(c-bins.list)) > $@ endif Modified: trunk/toc2/make/doxygen.make =================================================================== --- trunk/toc2/make/doxygen.make 2009-02-22 10:46:31 UTC (rev 266) +++ trunk/toc2/make/doxygen.make 2009-04-13 18:53:02 UTC (rev 267) @@ -31,7 +31,7 @@ doxygen.index = Doxygen-index.txt package.dist_files += $(doxygen.doxyfile.at) $(doxygen.index) -doxygen.install-dir.basename ?= doxygen-$(PACKAGE_NAME)-$(PACKAGE_VERSION) +doxygen.install-dir.basename ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-doxygen docs: doxygen install: install-doxygen This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: stephan b. <sg...@us...> - 2009-03-21 14:29:57
|
Update of /cvsroot/s11n/ncutil In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv28990 Modified Files: createCursesPalette.sh Log Message: a fix for newer c++ compilers Index: createCursesPalette.sh =================================================================== RCS file: /cvsroot/s11n/ncutil/createCursesPalette.sh,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- createCursesPalette.sh 25 Sep 2008 14:53:05 -0000 1.3 +++ createCursesPalette.sh 21 Mar 2009 14:29:46 -0000 1.4 @@ -165,8 +165,8 @@ { std::string fore = f; std::string back = b; - std::transform( fore.begin(), fore.end(), fore.begin(), std::toupper ); - std::transform( back.begin(), back.end(), back.begin(), std::toupper ); + std::transform( fore.begin(), fore.end(), fore.begin(), (int(*)(int)) std::toupper ); + std::transform( back.begin(), back.end(), back.begin(), (int(*)(int)) std::toupper ); typedef std::pair<std::string,std::string> SP; typedef std::map< SP, short > MT; static MT bob; |
From: <sg...@us...> - 2009-02-22 10:46:37
|
Revision: 266 http://s11n.svn.sourceforge.net/s11n/?rev=266&view=rev Author: sgbeal Date: 2009-02-22 10:46:31 +0000 (Sun, 22 Feb 2009) Log Message: ----------- started refactoring core lib components into separate files, for maintainability. Modified Paths: -------------- c11n/src/c11n/c11n.c Added Paths: ----------- c11n/src/c11n/c11n_array.c c11n/src/c11n/c11n_core.c c11n/src/c11n/c11n_log.c c11n/src/c11n/c11n_pod.c Modified: c11n/src/c11n/c11n.c =================================================================== --- c11n/src/c11n/c11n.c 2009-02-21 14:59:11 UTC (rev 265) +++ c11n/src/c11n/c11n.c 2009-02-22 10:46:31 UTC (rev 266) @@ -6,41 +6,6 @@ - Try to work without requiring C99 when possible. Unfortunately, we currently require vsscanf() and that's only in C99, though. - - Notes about the dubious subclassing things we do: - - http://www.cellperformance.com/mike_acton/2006/05/demystifying_the_restrict_keyw.html - - says it's purely undefined - - http://discuss.joelonsoftware.com/default.asp?design.4.568512.13 - - says it's "safe to assume it'll work" if the subtypes have the same - prefix (initial members) as the other. - - Apparently the only truly legal option would be to literally include - all of the members in each subclass. But it also says: - - // Or this way, also portable - process((struct base *)&mything); - - which is *almost* what we're doing, but not quite. It also says: - - "It's also guaranteed that a pointer to a structure may be - converted to a pointer to its first member, and vice versa. So you - could do this: ..." - - Hmm. - - - And here's some lively discussion on the topic: - - - http://groups.google.com/group/comp.lang.c/browse_thread/thread/57a0e4839744d030/8199c2517d8bf8a3# - - Where some seem to say "yes, this approach is okay" and some say - essentially "it seems to be okay" or "it'll work with sane compilers." - */ #ifndef _ISOC99_SOURCE /* @@ -58,19 +23,12 @@ See 'man feature_test_macros': _FORTIFY_SOURCE - -we should add that to the memblob and whhash APIs. ??? - */ #include <stdlib.h> #include <string.h> /* strcmp(), memcpy() */ #include "s11n.net/c11n/c11n.h" -//#include "whgc.h" -//#include "whhash.h" -#include "s11n.net/c11n/detail/memblob.h" -#include "s11n.net/c11n/detail/vappendf.h" #ifdef __cplusplus #define ARG_UNUSED(X) @@ -87,1856 +45,17 @@ #define MARKER if(0) bogo_printf #endif -const c11n_node_api_t c11n_node_api = - { - c11n_node_prop_set, - c11n_node_prop_set_fv, - c11n_node_prop_set_fe, - c11n_node_prop_get, - c11n_node_prop_get_fv, - c11n_node_prop_get_fe, - c11n_node_set_name, - c11n_node_get_name, - c11n_node_set_class, - c11n_node_get_class - }; +#include "c11n_core.c" +#include "c11n_log.c" +#include "c11n_array.c" +#include "c11n_pod.c" -struct c11n_context -{ - c11n_node * root; - //whgc_context * gc; -}; -static const c11n_context c11n_context_init = { -0 /* root node */ -//0 /* gc */ -}; - - - -/** - To save a few bytes we limit c11n_node property lists to - (2^(sizeof(c11n_proptype_count_t))-1) entries. - - Note that this "limits" our number of properties per node (probably - to 64k). In practice (from libs11n usage), most nodes have under 10 - properties, though some (e.g. certain serialized lists/maps) have a - few hundred or a few thousand. -*/ -typedef unsigned short c11n_propcount_t; - -/** - @struct c11n_kvp - - c11n_kvp is a type for holding key/value pairs. -*/ -struct c11n_kvp -{ - c11n_string_t key; - c11n_string_t value; -}; -typedef struct c11n_kvp c11n_kvp; -static const c11n_kvp c11n_kvp_init = {0,0}; - -/** - @struct c11n_kvp_set - - c11n_kvp_set is a type for holding lists of key/value pairs. -*/ -struct c11n_kvp_set -{ - /** - List of c11n_kvp pointers. - */ - c11n_kvp ** list; - /** - When pre-allocating a list, this member should - be set to the full (allocated) size of the list. - */ - c11n_propcount_t reserved; - /** - The number of actual items in the list (must be - <= reserved). - */ - c11n_propcount_t count; -}; -typedef struct c11n_kvp_set c11n_kvp_set; -#define C11N_KVP_LIST_INIT { 0, 0, 0 } - -struct c11n_node -{ - /* cx is arguable. i don't like it, but i suspect it might - be useful for safe GC at deserialization. */ - //c11n_context * cx; - c11n_string_t name; - c11n_string_t classname; - //const c11n_node_funcs_t * funcs; - /** - Pointer to an arbitrary one of the node's child objects. - Normally this is the left-most child, but there's no guaranty. - */ - struct c11n_node * children; - /** - Pointer to the node's parent. This is ONLY here so that - destruction of a child can safely set parent->children - if parent->children is the object being destroyed. - */ - struct c11n_node * parent; - /** - Pointer to the left-hand sibling (if any). - */ - struct c11n_node * left; - /** - Pointer to the right-hand sibling (if any). - */ - struct c11n_node * right; - /** - List of key/value pairs. This object owns the - list and its contents. - */ - c11n_kvp_set kvp; -}; -static const c11n_node c11n_node_init = { -//0, /* cx */ -0, /* name */ -0, /* classname */ -0, /* children */ -0, /* parent */ -0, /* left */ -0, /* right */ -C11N_KVP_LIST_INIT /* kvp */ -}; - -bool c11n_compare_str( c11n_key_type key, c11n_key_type val ) -{ - if( (key && !val) || (val && !key) ) return false; /* protect strcmp() from nulls. */ - else return (key == val) || (0 == strcmp( key, val )); -} - -size_t c11n_strlen( c11n_const_string_t s ) -{ - return s ? strlen(s) : 0; -} - -c11n_string_t c11n_copy_strn( c11n_const_string_t s, long len ) -{ - if( !s || !*s || !len ) return 0; - else if( len < 0 ) - { - len = 0; - c11n_const_string_t x = s; - for( ; *x ; ++len, ++x) - /** - ^^^^^^^ Valgrind says: -==4835== Invalid read of size 1 -==4835== at 0x804A541: c11n_copy_strn (c11n.c:227) -==4835== by 0x804A5CA: c11n_copy_str (c11n.c:251) -==4835== by 0x804AA3F: c11n_node_prop_set_fv (c11n.c:386) -==4835== by 0x804AA87: c11n_node_prop_set_fe (c11n.c:396) -==4835== by 0x8048D77: test_node (test.c:108) - */ - { - //++len; - //MARKER("len [%s]=%ld\n",x,len); - //++x; - } - } - //MARKER("len [%s]=%ld\n",s,len); - if( len < 1 ) return 0; - c11n_string_t cp = (c11n_string_t)malloc(sizeof(char)* ((size_t)len+1)); - if( ! cp ) return 0; - c11n_string_t p = cp; - //long at = 0; - //for( ; (at<len); ++s, ++p, ++at ) *p = *s; - //for( ; (at++<len); ((*p++ = *s++)) ); - //for( ; (len-- > 0); ((*p++ = *s++)) ); - //for( ; ((*p++ = *s++)) && (at++<len); ); - while( (len-- > 0) ) *p++ = *s++; - *p = 0; - return cp; -} - -c11n_string_t c11n_copy_str( c11n_const_string_t s ) -{ - return c11n_copy_strn( s, -1 ); -} - - -bool c11n_node_prop_get( c11n_node const * n, - c11n_key_type key, - c11n_const_string_t * val ) -{ - if( !n || !n->kvp.list || !n->kvp.count) return false; - c11n_kvp * kvp = 0; - c11n_propcount_t i = 0; - for( kvp = n->kvp.list[0]; - kvp && kvp->key && (i < n->kvp.count); - kvp = n->kvp.list[++i] ) - { - if( c11n_compare_str( key, kvp->key ) ) - { - if( val ) *val = kvp->value; - return true; - } - } - return false; -} - -bool c11n_node_prop_get_f( c11n_node const * n, - c11n_key_type key, - c11n_const_string_t fmt, - void * tgt ) -{ - if( ! n || !key || !fmt ) return false; - c11n_const_string_t val = 0; - //MARKER; - if( ! c11n_node_prop_get( n, key, &val ) || !val ) return false; - int rc = sscanf( val, fmt, tgt ); - //MARKER("scanf=%d fmt=[%s] key[%s]=[%s]\n",rc,fmt,key,(char const *)val); - return EOF != rc; -} - -int c11n_node_prop_get_fv( c11n_node const * n, - c11n_key_type key, - c11n_const_string_t fmt, - va_list vargs ) -{ - if( ! n || !key || !fmt ) return false; - c11n_const_string_t val = 0; - if( ! c11n_node_prop_get( n, key, &val ) || !val ) return false; - int rc = vsscanf( val, fmt, vargs ); - //MARKER("scanf=%d fmt=[%s] key[%s]=[%s]\n",rc,fmt,key,val); - return rc; -} -int c11n_node_prop_get_fe( c11n_node const * n, - c11n_key_type key, - c11n_const_string_t fmt, ... ) -{ - va_list vargs; - va_start( vargs, fmt ); - int ret = c11n_node_prop_get_fv( n, key, fmt, vargs ); - va_end(vargs); - return ret; -} - -static c11n_kvp * c11n_node_search_kvp( c11n_node * n, c11n_key_type key ) -{ - if( ! n || !n->kvp.reserved ) return 0; - c11n_kvp * kvp = 0; - int i = 0; - for( kvp = n->kvp.list[0]; - kvp && kvp->key && (i < n->kvp.reserved); - kvp = n->kvp.list[++i] ) - { - if( c11n_compare_str( key, kvp->key ) ) - { - return kvp; - } - } - return 0; -} - -/** - Adds a new entry to li, expanding li->list as necessary. Returns - the new c11n_kvp object, or 0 if !li or alloc/realloc fails. -*/ -static c11n_kvp * c11n_kvp_set_add( c11n_kvp_set * li ) -{ - if( ! li ) return 0; - //MARKER("n=%p\n", n, n ); - if( (!li->count) || (li->count+1 == li->reserved) ) - { /* add space for more entries */ - c11n_kvp ** alo = 0; - if( 0 == li->reserved ) li->reserved += 5; - else li->reserved *= 2; - //MARKER("Reserving space for %d KVPs\n",li->reserved); -#if 0 - if( ! li->list ) - { - alo = (c11n_kvp**) calloc( li->reserved, sizeof(c11n_kvp*) ); - } - else - { - alo = (c11n_kvp**) realloc( li->list, sizeof(c11n_kvp*) * li->reserved ); - } -#else - alo = (c11n_kvp**) realloc( li->list, sizeof(c11n_kvp*) * li->reserved ); -#endif - if( ! alo ) return false; - li->list = alo; - } - c11n_kvp * x = (c11n_kvp*)malloc(sizeof(c11n_kvp)); - if( x ) - { - *x = c11n_kvp_init; - li->list[li->count++] = x; - li->list[li->count] = 0; - } - return x; -} - -bool c11n_node_prop_give_kvp( c11n_node *n, c11n_string_t key, c11n_string_t val ) -{ - if( !n || !key ) return false; - c11n_kvp * kvp = c11n_node_search_kvp(n,key); - if( kvp ) - { - //MARKER("node[@%p] replacing property [%s]=[%s]\n",n,key,v); - if( kvp->key != key ) free( key ); - if( kvp->value != val ) free( kvp->value ); - kvp->value = val; - return true; - } - kvp = c11n_kvp_set_add(&n->kvp); - if( ! kvp ) - { - return false; - } - //C11N_LOG(C11N_LOG_ALWAYS)("setting [%s] = [%s]", key, val ); - kvp->key = key; - kvp->value = val; - return true; -} - -bool c11n_node_prop_set( c11n_node * n, c11n_key_type key, c11n_const_string_t val ) -{ - if( !n || !key ) return false; - /* - Maybe todo: don't implement in terms of c11n_node_prop_give_kvp() because - doing so costs us one extra copy of key when re-setting an existing - property. - */ - return c11n_node_prop_give_kvp( n, c11n_copy_str(key), c11n_copy_str(val) ); -} - -bool c11n_node_prop_set_fv( c11n_node *n, c11n_key_type key, c11n_const_string_t fmt, va_list vargs ) -{ - if( !n || !key ) return false; - /* - Maybe todo: don't implement in terms of c11n_node_prop_give_kvp() because - doing so costs us one extra copy of key when re-setting an existing - property. - */ - return c11n_node_prop_give_kvp( n, c11n_copy_str(key), - fmt ? memblob_vmprintf( fmt, vargs ) : 0 ); -} - -bool c11n_node_prop_set_fe( c11n_node *n, c11n_key_type key, c11n_const_string_t fmt, ... ) -{ - va_list vargs; - va_start( vargs, fmt ); - bool ret = c11n_node_prop_set_fv(n,key,fmt,vargs); - va_end(vargs); - return ret; -} - - -bool c11n_node_prop_unset( c11n_node * n, c11n_key_type key ) -{ - if( ! n || !n->kvp.reserved ) return 0; - c11n_kvp_set * li = &n->kvp; - c11n_propcount_t i = 0; - c11n_kvp * e = li->list[i]; - //c11n_log(C11N_LOG_DEALLOC,C11N_SOURCE_INFO,"c11n_kvp_set @%p cleaning up.",li); - C11N_LOG(C11N_LOG_DEALLOC)("c11n_kvp_set @%p cleaning up.",li); - for( ; i < li->count; e = li->list[++i] ) - { - if( ! e ) - { - c11n_log( C11N_LOG_ERROR, C11N_SOURCE_INFO, "internal error: got a null property in the the list."); - continue; - } - if( ! c11n_compare_str( key, e->key ) ) continue; - C11N_LOG(C11N_LOG_DEALLOC)("node @%p unsetting kvp [%s]=[%s]",li,e->key,e->value); - free(e->key); - free(e->value); - e->key = e->value = 0; - free(e); - e = 0; - c11n_propcount_t pos = i; - while( pos < li->count ) - { - li->list[pos] = li->list[pos+1]; - ++pos; - } - --(li->count); - return true; - } - return false; -} - -char const ** c11n_node_prop_keys( c11n_node const * n ) -{ - if( ! n || ! n->kvp.count ) return 0; - char const ** ret = (char const **)calloc( n->kvp.count + 1, sizeof(char*) ); - if( ! ret ) return 0; - size_t i = 0; - c11n_kvp const * kvp = n->kvp.list[i]; - while( kvp && kvp->key && (i < n->kvp.count) ) - { - ret[i] = kvp->key; - kvp = n->kvp.list[++i]; - } - ret[i] = 0; - return ret; -} - -#if 0 -#define ITER_IMPL(SUFFIX,NODE_CONSTNESS,CHILDFETCHER) \ -c11n_node_iter ## SUFFIX c11n_node_children_iter ## SUFFIX ( c11n_node NODE_CONSTNESS * n ) \ -{\ - c11n_node_iter ## SUFFIX it;\ - it.node = CHILDFETCHER(n);\ - return it;\ -}\ -bool c11n_node_iter_isvaliditer ## SUFFIX ( c11n_node_iter ## SUFFIX const * iter ) \ -{\ - return iter && iter->node;\ -}\ -bool c11n_node_iter_has_nextiter ## SUFFIX ( c11n_node_iter ## SUFFIX const * it )\ -{\ - return (it && it->node && it->node->right );\ -}\ -bool c11n_node_iter_nextiter ## SUFFIX ( c11n_node_iter ## SUFFIX * it )\ -{\ - if( it )\ - {\ - it->node = it->node\ - ? it->node->right\ - : 0;\ - }\ - return 0 != it->node;\ -}\ -bool damned_bogus_semicolon_placeholder ## SUFFIX -ITER_IMPL(_c,const,c11n_node_children_c); -ITER_IMPL(,,c11n_node_children); - -#else -c11n_node_iter c11n_node_children_iter( c11n_node * n ) -{ - c11n_node_iter it; - it.node = c11n_node_children(n); - return it; -} -bool c11n_node_iter_isvalid( c11n_node_iter const * iter ) -{ - return iter && iter->node; -} -bool c11n_node_iter_has_next( c11n_node_iter const * it ) -{ - return (it && it->node && it->node->right ); -} -bool c11n_node_iter_next( c11n_node_iter * it ) -{ - if( it ) - { - it->node = it->node - ? it->node->right - : 0; - } - return 0 != it->node; -} - -c11n_node_iter_c c11n_node_children_iter_c( c11n_node const * n ) -{ - c11n_node_iter_c it; - it.node = c11n_node_children_c(n); - return it; -} -bool c11n_node_iter_isvalid_c( c11n_node_iter_c const * iter ) -{ - return iter && iter->node; -} -bool c11n_node_iter_has_next_c( c11n_node_iter_c const * it ) -{ - return (it && it->node && it->node->right ); -} -bool c11n_node_iter_next_c( c11n_node_iter_c * it ) -{ - if( it ) - { - it->node = it->node - ? it->node->right - : 0; - } - return 0 != it->node; -} -#endif - - -c11n_prop_iter c11n_node_prop_iter( c11n_node const * n ) -{ - c11n_prop_iter it; - it.kvp = ( n && n->kvp.count ) - ? &n->kvp - : 0; - it.pos = 0; - return it; -} -bool c11n_prop_iter_isvalid( c11n_prop_iter const * iter ) -{ - return iter && iter->kvp && (iter->pos < iter->kvp->count); -} - -c11n_const_string_t c11n_prop_iter_key( c11n_prop_iter const * it ) -{ - return (it && it->kvp && it->kvp->list ) - ? it->kvp->list[it->pos]->key - : 0; -} - -c11n_const_string_t c11n_prop_iter_val( c11n_prop_iter const * it ) -{ - return (it && it->kvp && it->kvp->list ) - ? it->kvp->list[it->pos]->value - : 0; -} - -bool c11n_prop_iter_has_next( c11n_prop_iter const * it ) -{ - return (it && it->kvp && it->kvp->list) - && ((it->pos+1) < it->kvp->count); -} - -bool c11n_prop_iter_next( c11n_prop_iter * it ) -{ - return (it && it->kvp && ( (++it->pos) < it->kvp->count)); -} - -bool c11n_marshaller_api_is_a( c11n_marshaller const * self, c11n_const_string_t classname ) -{ - return self - ? c11n_compare_str( self->api->classname, classname ) - : false; -} -bool c11n_marshaller_api_serialize( c11n_marshaller const * ARG_UNUSED(self), - c11n_node * ARG_UNUSED(dest), - void const * ARG_UNUSED(src) ) -{ - return false; -} - -bool c11n_marshaller_api_deserialize( c11n_marshaller const * ARG_UNUSED(self), - c11n_node const * ARG_UNUSED(src), - void * ARG_UNUSED(dest) ) -{ - return false; -} - -static void * c11n_marshaller_api_create( c11n_marshaller const * ARG_UNUSED(self)) -{ - return 0; -} -void c11n_marshaller_api_clear( c11n_marshaller const * ARG_UNUSED(self), - void * ARG_UNUSED(v) ) -{ -} - -void c11n_marshaller_api_destroy( c11n_marshaller const * self, - void * v ) -{ - if( self ) self->api->clear( self, v ); - free(v); -} - -#define C11N_MARSHALLER_API_DEFAULT(N) \ - C11N_MARSHALLER_API_INIT(N,\ - c11n_marshaller_api_serialize,\ - c11n_marshaller_api_deserialize,\ - c11n_marshaller_api_create,\ - c11n_marshaller_api_clear,\ - c11n_marshaller_api_destroy) - -const c11n_marshaller_api c11n_marshaller_api_init = - C11N_MARSHALLER_API_DEFAULT("unnamed"); - -#if 0 -/** - An object containing an "empty" marshaller type. It can be copied over - client-side objects to ensure a clean slate. The default - function implementations all do nothing and (if possible) - return an error code. The default classname is an unspecified - non-empty string. -*/ -extern const c11n_marshaller c11n_marshaller_init; -#define C11N_MARSHALLER_INIT {C11N_MARSHALLER_API_DEFAULT("unnamed")} -const c11n_marshaller c11n_marshaller_init = C11N_MARSHALLER_INIT; -#endif - - - -#if 0 -c11n_kvp * c11n_create_kvp( c11n_key_type k, - c11n_const_string_t v ) -{ - c11n_kvp * ret = k ? ((c11n_kvp*) sizeof(c11n_kvp)) : 0; - if( ret ) - { - *ret = c11n_kvp_init; - ret->key = c11n_copy_str(k); - ret->value = v ? c11n_copy_str(v) : 0; - } - return ret; -} -#endif - - -bool c11n_node_set_string( c11n_node * self, - c11n_key_type key, - c11n_const_string_t val ) -{ - return false; -} - - -c11n_context * c11n_context_create() -{ - c11n_context * cx = malloc(sizeof(c11n_context)); - if( ! cx ) return 0; - *cx = c11n_context_init; -#if 0 - cx->gc = whgc_create_context(cx); - if( ! cx->gc ) - { - free(cx); - cx = 0; - } -#endif - return cx; -} - -void c11n_context_destroy(c11n_context *cx) -{ - if( cx ) - { - if( cx->root ) - { - c11n_node_destroy( cx->root ); - } -#if 0 - whgc_destroy_context( cx->gc ); -#endif - free(cx); - } -} - - -bool c11n_serialize( c11n_marshaller const * traits, c11n_node * dest, void const * src ) -{ - if( !dest || !traits || !src ) return false; - c11n_node_set_class( dest, traits->api->classname ); - return traits->api->serialize( traits, dest, src ); -} - -bool c11n_serialize_subnode( c11n_marshaller const * marshaller, - c11n_node * parent, - c11n_key_type childName, - void const * src ) -{ - if( ! parent || !marshaller || !childName || !src ) return false; - c11n_node * ch = c11n_node_create( childName ); - if( ! ch ) return false; - - if( ! c11n_serialize( marshaller, ch, src ) ) - { - c11n_node_destroy(ch); - ch = 0; - } - else - { - c11n_node_add_child( parent, ch ); - } - return 0 != ch; -} - - -/** - A helper type for de/serializing object arrays. -*/ -typedef struct c11n_array_info -{ - /** - The marshaller which this type proxies - it is used - to de/serialize individual array elements. - */ - c11n_marshaller const * marshaller; - /** - The number of items in the array. - - Serialization: required to be set to the length of the array. - - Deserialization: will be set by the API to the number of items - in the deserialized list. - */ - size_t count; - /** - MUST be sizeof(ST), where ST is the marshaller's Serializable - Type. - */ - size_t sizeOf; - /** - Only for serialization - the source object to serialize. - */ - void const * src; - /** - Only for deserialization - the API will set it to the deserialized - array. - */ - void * dest; -} c11n_array_info; - -static const c11n_array_info c11n_array_info_init = {0,0,0,0,0}; - -/** - Initializes an c11n_array_info object. -*/ -static c11n_array_info c11n_array_get_info( c11n_marshaller const * m, - size_t count, - size_t sizeOf, - void const * src, - void * dest ) -{ - c11n_array_info inf; - inf.marshaller = m; - inf.count = count; - inf.sizeOf = sizeOf; - inf.src = src; - inf.dest = dest; - return inf; -} - -/** - Initializes a c11n_array_info object for serialization. -*/ -c11n_array_info c11n_array_info_s( c11n_marshaller const * m, - size_t count, - size_t sizeOf, - void const * src ) -{ - return c11n_array_get_info( m, count, sizeOf, src, 0 ); -} - -/** - Initializes a c11n_array_info object for deserialization. -*/ -c11n_array_info c11n_array_info_d( c11n_marshaller const * m, - size_t sizeOf, - void * dest ) -{ - return c11n_array_get_info( m, 0, sizeOf, 0, dest ); -} - - -#define METADECL(RV) c11n_array_info * meta = Info ? ((c11n_array_info *)Info) : 0; if(!meta) return RV -#define METADECLC(RV) c11n_array_info const * meta = src ? ((c11n_array_info const *)src) : 0; if(!meta) return RV -static bool c11n_array_api_serialize( struct c11n_marshaller const * self, c11n_node * dest, void const * src ) -{ - METADECLC(false); - if( ! dest || !meta->count || !meta->sizeOf || !src ) return false; - c11n_marshaller const * m = meta->marshaller; - c11n_node_set_class( dest, "array" ); - c11n_node_prop_set( dest, "type", m->api->classname ); - c11n_node_prop_set_fe( dest, "sizeof", "%u", meta->sizeOf ); - size_t at = 0; - for(; at < meta->count; ++at ) - { - if( ! c11n_serialize_subnode( m, dest, "entry", meta->src + ( at* meta->sizeOf ) ) ) - { - C11N_LOG(C11N_LOG_ERROR)("Serialize of array item #%u failed :(.", at); - return false; - } - } - /* - Reminder: we COULD store count as a property to save some work at deser-time, - but doing so would make hand-editing the output problematic, as the user would - have to ensure that the count prop matches the child count. - */ - return true; -} - -static bool c11n_array_api_deserialize( struct c11n_marshaller const * self, c11n_node const *src, void * Info ) -{ - METADECL(false); - c11n_marshaller const * m = meta->marshaller; - if( ! m ) return false; - c11n_const_string_t cn = c11n_node_get_class(src); - if( !c11n_compare_str( "array", cn ) ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " - "it was apparently not serialized using c11n_serialize_array() :(.", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src) ); - return 0; - } - c11n_const_string_t implClass = 0; - if( ! c11n_node_prop_get( src, "type", &implClass ) - || ! c11n_compare_str( m->api->classname, implClass ) - ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " - "its stored stored type name (%s) does not match the marshaller :(.", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src), - implClass ); - return 0; - } - size_t sizeCheck = 0; - if( (1 != c11n_node_prop_get_fe( src, "sizeof", "%u", &sizeCheck )) - || (!sizeCheck) ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " - "the sizeof property was not set :(.", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src) ); - return 0; // FIXME: log a message - } - if( sizeCheck != meta->sizeOf ) - { - C11N_LOG(C11N_LOG_WARNING)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]): " - "sizeof(%s) has changed since the data was serialized (old=%u, new=%u).", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src), - m->api->classname, sizeCheck, meta->sizeOf ); - /* keep going... */ - } - - c11n_node_iter_c iter = c11n_node_children_iter_c(src); - if( ! c11n_node_iter_isvalid_c( &iter ) ) return 0; - size_t count = 0; - do - { - ++count; - } while( c11n_node_iter_next_c( &iter ) ); - //MARKER("here, count=%u\n",count); - if( ! count ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " - "the c11n_node contains no children to deserialize :(.", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src) ); - return 0; - } - void * mal = calloc( count, meta->sizeOf ); - if( ! mal ) return 0; - void * prototype = m->api->create(m); - if( ! prototype ) - { - free( mal ); - return 0; - } - iter = c11n_node_children_iter_c(src); - bool isokay = true; - size_t decount = 0; - for( ; (decount < count) && c11n_node_iter_isvalid_c(&iter); ++decount ) - { - void * obj = (mal + (decount * meta->sizeOf)); - /** - The right thing to do here would be use m->api->create(m) - to instantiate a prototype object, copy it over obj, then - call free(m,prototype). However, i'm stil trying to think - of a use case where that pedenticness would matter. It'd cost us - count allocs, which is the only reason i haven't done it yet. - */ - memcpy( obj, prototype, meta->sizeOf ); - if( ! c11n_deserialize( m, iter.node, obj ) ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array)[#%u] from (c11n_node@%p[class=%s, name=%s]) failed :(.", - implClass, decount, iter.node, - c11n_node_get_class( iter.node ), c11n_node_get_name( iter.node ) - ); - isokay = false; - break; - } - c11n_node_iter_next_c(&iter); - } - m->api->destroy( m, prototype ); - if( ! isokay ) - { - size_t c = 0; - /** - c11n_deserialize() will clean up if it fails, but we need - to clean up all items leading up to (but not including) the - failed item. - */ - if(decount>0) for( ; c < (decount-1); ++c ) - { - m->api->clear(m, mal + ( c * meta->sizeOf )); - } - free( mal ); - count = 0; - } - else - { - meta->dest = mal; - meta->count = count; - } - return meta->count; -} - -static void * c11n_array_api_create( struct c11n_marshaller const * self ) -{ -#if 0 - /* - Arguable, because in the generic case (e.g. c11n_deserialize_new()) we cannot - initialize the object enough for deserialization to be able to - succeed. - */ - c11n_array_info * x = (c11n_array_info *)malloc(sizeof(c11n_array_info)); - if( x ) *x = c11n_array_info_init; - return x; -#else - return 0; -#endif -} - -static void c11n_array_api_clear( struct c11n_marshaller const * self, void * Info ) -{ - if( ! self || !Info ) return; - METADECL(); - if( meta->dest ) - { - size_t i = 0; - c11n_marshaller const * m = meta->marshaller; - for( ; i < meta->count; ++i ) - { - void * obj = meta->dest + (i * meta->sizeOf); - m->api->clear( m, obj ); - } - } - meta->count = meta->sizeOf = 0; - meta->src = 0; - meta->dest = 0; -} - -#undef METADECL -#undef METADECLC - -static void c11n_array_api_destroy( struct c11n_marshaller const * self, void * Info ) -{ - if( self ) - { - c11n_array_api_clear( self, Info ); - } - free(Info); -} - -c11n_marshaller_api c11n_array_info_marshaller_api = - C11N_MARSHALLER_API_INIT("array", - c11n_array_api_serialize, - c11n_array_api_deserialize, - c11n_array_api_create, - c11n_array_api_clear, - c11n_array_api_destroy); -static const c11n_marshaller c11n_array_info_marshaller = {&c11n_array_info_marshaller_api}; - -bool c11n_serialize_array( c11n_node * dest, - c11n_marshaller const * m, - size_t count, - size_t sizeOf, - void const * src ) -{ - if( ! dest || !m || !count || !sizeOf || !src ) return false; -#if 1 - c11n_array_info inf = c11n_array_info_s( m, count, sizeOf, src ); - return c11n_serialize( &c11n_array_info_marshaller, dest, &inf ); -#else - c11n_node_set_class( dest, "array" ); - c11n_node_prop_set( dest, "type", m->api->classname ); - c11n_node_prop_set_fe( dest, "sizeof", "%u", sizeOf ); - size_t at = 0; - for(; at < count; ++at ) - { - if( ! c11n_serialize_subnode( dest, m, "entry", src + (at*sizeOf) ) ) - { - C11N_LOG(C11N_LOG_ERROR)("Serialize of array item #%u failed :(.\n",at); - return false; - } - - } - /* - Reminder: we COULD store count as a property to save some work at deser-time, - but doing so would make hand-editing the output problematic, as the user would - have to ensure that the count prop matches the child count. - */ - return true; -#endif -} - -size_t c11n_deserialize_array( c11n_node const * src, - c11n_marshaller const * m, - size_t sizeOf, - void ** dest ) -{ - if( ! src || !m || !dest || !sizeOf ) return 0; - /* i think 85% of this code is error checking/reporting... */ - //MARKER("here: %p %p %u %p\n",src,m,sizeOf,dest); -#if 1 - c11n_array_info inf = c11n_array_info_d( m, sizeOf, dest ); - c11n_deserialize( &c11n_array_info_marshaller, src, &inf ); - if( inf.count ) - { - *dest = inf.dest; - } - return inf.count; -#else - c11n_const_string_t cn = c11n_node_get_class(src); - if( !c11n_compare_str( "array", cn ) ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " - "it was apparently not serialized using c11n_serialize_array() :(.", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src) ); - return 0; - } - c11n_const_string_t implClass = 0; - if( ! c11n_node_prop_get( src, "type", &implClass ) - || ! c11n_compare_str( m->api->classname, implClass ) - ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " - "its stored stored type name (%s) does not match the marshaller :(.", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src), - implClass ); - return 0; - } - size_t sizeCheck = 0; - if( (1 != c11n_node_prop_get_fe( src, "sizeof", "%u", &sizeCheck )) - || (!sizeCheck) ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " - "the sizeof property was not set :(.", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src) ); - return 0; // FIXME: log a message - } - if( sizeCheck != sizeOf ) - { - C11N_LOG(C11N_LOG_WARNING)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]): " - "sizeof(%s) has changed since the data was serialized (old=%u, new=%u).", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src), - m->api->classname, sizeCheck, sizeOf ); - /* keep going... */ - } - - c11n_node_iter_c iter = c11n_node_children_iter_c(src); - if( ! c11n_node_iter_isvalid_c( &iter ) ) return 0; - size_t count = 0; - do - { - ++count; - } while( c11n_node_iter_next_c( &iter ) ); - //MARKER("here, count=%u\n",count); - if( ! count ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " - "the c11n_node contains no children to deserialize :(.", - m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src) ); - return 0; - } - - void * mal = calloc( count, sizeOf ); - if( ! mal ) return 0; - void * prototype = m->api->create(m); - if( ! prototype ) - { - free( mal ); - return 0; - } - iter = c11n_node_children_iter_c(src); - bool isokay = true; - size_t decount = 0; - for( ; (decount < count) && c11n_node_iter_isvalid_c(&iter); ++decount ) - { - void * obj = (mal + (decount*sizeOf)); - /** - The right thing to do here would be use m->api->create(m) - to instantiate a prototype object, copy it over obj, then - call free(m,prototype). However, i'm stil trying to think - of a use case where that pedenticness would matter. It'd cost us - count allocs, which is the only reason i haven't done it yet. - */ - memcpy( obj, prototype, sizeOf ); - if( ! c11n_deserialize( iter.node, m, obj ) ) - { - C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array)[#%u] from (c11n_node@%p[class=%s, name=%s]) failed :(.", - implClass, decount, iter.node, - c11n_node_get_class( iter.node ), c11n_node_get_name( iter.node ) - ); - isokay = false; - break; - } - c11n_node_iter_next_c(&iter); - } - m->api->destroy( m, prototype ); - if( ! isokay ) - { - size_t c = 0; - /** - c11n_deserialize() will clean up if it fails, but we need - to clean up all items leading up to (but not including) the - failed item. - */ - if(decount>0) for( ; c < (decount-1); ++c ) - { - m->api->clear(m, mal + (c*sizeOf)); - } - free( mal ); - count = 0; - } - else - { - *dest = mal; - } - return count; -#endif -} - - - - - -bool c11n_node_predicate_name_is( c11n_node const * n1, void const * str ) -{ - return c11n_compare_str( c11n_node_get_name(n1), (c11n_const_string_t)str ); -} - -c11n_node * c11n_node_children_search( c11n_node * p, c11n_node_predicate_f f, void const * fArg ) -{ - if( ! p || !f ) return 0; - c11n_node_iter it = c11n_node_children_iter(p); - while( c11n_node_iter_isvalid(&it) ) - { - if( f( it.node, fArg ) ) return it.node; - else if( ! c11n_node_iter_next(&it) ) break; - } - return 0; -} -c11n_node const * c11n_node_children_search_c( c11n_node const * p, c11n_node_predicate_f f, void const * fArg ) -{ - if( ! p || !f ) return 0; - c11n_node_iter_c it = c11n_node_children_iter_c(p); - while( c11n_node_iter_isvalid_c(&it) ) - { - if( f( it.node, fArg ) ) return it.node; - else if( ! c11n_node_iter_next_c(&it) ) break; - } - return 0; -} - -bool c11n_deserialize( c11n_marshaller const * traits, c11n_node const * src, void * dest ) -{ - if ( !dest || !traits || !src ) return false; -#if 1 - // This is highly arguable: - if( ! traits->api->is_a( traits, c11n_node_get_class(src) ) ) - { - C11N_LOG(C11N_LOG_WARNING)("Type mismatch: node of type [%s] vs marshaller for type [%s]", - c11n_node_get_class(src), traits->api->classname ); - return false; - } -#endif - if( ! traits->api->deserialize( traits, src, dest ) ) - { - traits->api->clear( traits, dest ); - return false; - } - else - { - return true; - } -} - -void * c11n_deserialize_new( c11n_marshaller const * traits, c11n_node const * src ) -{ - if( ! src || ! traits ) return 0; - void * dest = traits->api->create( traits ); - if( dest && ! traits->api->deserialize( traits, src, dest ) ) - { - traits->api->destroy( traits, dest ); - dest = 0; - } - return dest; -} - -bool c11n_deserialize_subnode( c11n_marshaller const * marshaller, - c11n_node const * parent, - c11n_key_type childName, - void * dest ) -{ - if( ! parent || !marshaller || !childName || !dest ) return 0; - c11n_node const * ch = c11n_node_children_search_c( parent, c11n_node_predicate_name_is, childName ); - return ch - ? c11n_deserialize( marshaller, ch, dest ) - : false; -} - -void * c11n_clone( c11n_marshaller const * m, void * ct ) -{ - void * rt = (m && ct) - ? m->api->create(m) - : 0; - if( rt ) - { - c11n_node * n = c11n_node_create("c11n_clone"); - bool rc = c11n_serialize( m, n, ct ) - && c11n_deserialize( m, n, rt ); - if( ! rc ) - { - m->api->destroy(m,rt); - rt = 0; - } - c11n_node_destroy(n); - } - return rt; -} - -#if 0 -bool c11n_register_traits( c11n_context * cx, c11n_key_type key, c11n_marshaller const * traits ) -{ - /** - Registers the traits type, mainly for loading by classname at - deserialization. - */ - return false; -} - -c11n_marshaller const * c11n_get_traits_for_type( c11n_context * cx, c11n_key_type classname ) -{ - return 0; -} -void * c11n_classload( c11n_context * cx, c11n_key_type key ) -{ - return 0; -} -#endif - -#if 0 -/** - Allocates size bytes of memory using malloc(). If cx is not null - then the memory is added to cx's garbage pool, otherwise the memory - is owned by the caller. -*/ -void * c11n_malloc(c11n_context * cx, size_t size) -{ - void * c = malloc(size); - if( c && cx ) - { - whgc_add( cx->gc, c, free ); - // add c to cx's GC context - } - return c; -} -#endif - -c11n_const_string_t c11n_node_get_name( c11n_node const * n ) -{ - return n ? n->name : 0; -} -void c11n_node_set_name( c11n_node * n, c11n_key_type k ) -{ - if( n ) - { - free(n->name); - n->name = c11n_copy_str(k); - } -} - -c11n_const_string_t c11n_node_get_class( c11n_node const * n ) -{ - return n ? n->classname : 0; -} - -void c11n_node_set_class( c11n_node * n, c11n_key_type k ) -{ - if( n ) - { - free(n->classname); - n->classname = c11n_copy_str(k); - //MARKER("node@%p classname=[%s]\n",n,k); - } -} - -static void c11n_kvp_set_clear( c11n_kvp_set * li ) -{ - if( ! li || !li->list ) return; - c11n_propcount_t i = 0; - c11n_kvp * e = li->list[i]; - C11N_LOG(C11N_LOG_DEALLOC)("c11n_kvp_set @%p cleaning up.",li); - for( ; i < li->count; e = li->list[++i] ) - { - if( ! e ) - { - C11N_LOG(C11N_LOG_ERROR)( "internal error: got a null property in the the list."); - continue; - } - C11N_LOG(C11N_LOG_DEALLOC)("list @%p freeing kvp [%s]=[%s]",li,e->key,e->value); - free(e->key); - free(e->value); - e->key = e->value = 0; - free(e); - e = 0; - } - free(li->list); - li->count = li->reserved = 0; - li->list = 0; -} -void c11n_node_destroy( c11n_node * n ) -{ - C11N_LOGME_DEALLOCTP(c11n_node,n); - if( ! n ) return; - c11n_node * ch = n->children; /* must come before unlinking! */ - if( n->parent && (n->parent->children == n) ) - { - n->parent->children = n->left ? n->left : n->right; - } - if( n->right ) - { - n->right->left = n->left; - n->right = 0; - } - if( n->left ) - { - n->left->right = n->right; - n->left = 0; - } - while( ch && ch->left ) ch = ch->left; - while( ch ) - { - c11n_node * next = ch->right; - c11n_node_destroy( ch ); - ch = next; - } - c11n_kvp_set_clear( &n->kvp ); - free( n->name ); - free( n->classname ); - free( n ); -} - -c11n_node * c11n_node_create( c11n_key_type name ) -{ - c11n_node * n = (c11n_node *)malloc(sizeof(c11n_node)); - C11N_LOG(C11N_LOG_ALLOC)("created(?) c11n_node @%p",n); - if( n ) - { - *n = c11n_node_init; - c11n_node_set_name( n, name ); - } - return n; -} - -c11n_node * c11n_node_children( c11n_node * n ) -{ - c11n_node * ch = n ? n->children : n; - while( ch && ch->left ) ch = ch->left; - return ch; -} -c11n_node const * c11n_node_children_c( c11n_node const * n ) -{ - c11n_node const * ch = n ? n->children : n; - while( ch && ch->left ) ch = ch->left; - return ch; -} -c11n_node * c11n_node_parent( c11n_node * n ) -{ - return n ? n->parent : 0; -} -c11n_node const * c11n_node_parent_c( c11n_node const * n ) -{ - return n ? n->parent : 0; -} - -c11n_node * c11n_node_next_sibling( c11n_node * n ) -{ - return n ? n->right : 0; -} -c11n_node const * c11n_node_next_sibling_c( c11n_node const * n ) -{ - return n ? n->right : 0; -} - -bool c11n_node_add_child( c11n_node * p, c11n_node * ch ) -{ - if( ! p || !ch || (p == ch) ) return false; - if(p == ch->parent) return true; - /** Reconnect existing neighbors... */ - if( ch->left ) ch->left->right = ch->right; - if( ch->right ) ch->right->left = ch->left; - - if( ch->parent && (ch->parent->children == ch) ) - { - ch->parent->children = ch->left ? ch->left : ch->right; - } - /* ch->cx = p->cx; */ - ch->parent = p; - - c11n_node * sib = p->children; - if( ! sib ) - { - p->children = ch; - } - else - { - while( sib && sib->right ) - { - if( ch == sib ) - { - C11N_LOG(C11N_LOG_ERROR)( "internal error: duplicate child entry in node list???"); - break; - } - sib = sib->right; - } - if( ch != sib ) - { - sib->right = ch; - ch->left = sib; - } - } - return true; -} - -c11n_node * c11n_node_create_child( c11n_node * parent, c11n_key_type name ) -{ - c11n_node * ch = c11n_node_create( name ); - if( ch ) - { - if( parent && ! c11n_node_add_child( parent, ch ) ) - { - free(ch); - ch = 0; - } - } - return ch; -} - -bool c11n_serialize_binary( c11n_node * dest, void const * src, size_t sizeOf ) -{ - if( ! dest || !src || !sizeOf ) return false; - memblob * buf = memblob_new_n( sizeOf ); - if( ! buf ) return false; - memblob_append( buf, src, sizeOf ); - memblob_base64_enc( buf, buf ); - c11n_node_prop_set_fe( dest, "size", "%u", sizeOf ); - c11n_string_t key = c11n_copy_str( "base64" ); - char * val = memblob_take_buffer( buf ); - if( ! c11n_node_prop_give_kvp( dest, key, val ) ) - { - free(key); - free(val); - } - memblob_finalize( buf ); - return true; -} - -bool c11n_deserialize_binary( c11n_node const * src, c11n_binary_data * dest ) -{ - dest->data = 0; - dest->size = 0; - if( ! src || !dest ) return false; - size_t sz = 0; - if( 1 != c11n_node_prop_get_fe( src, "size", "%u", &sz ) ) return false; - dest->size = sz; - c11n_const_string_t val = 0; - if( ! c11n_node_prop_get( src, "base64", &val ) || !val ) return false; - dest->data = malloc(sz); - if( ! dest->data ) return false; - memset( dest->data, 0, sz ); - memblob * cb = memblob_new(); - memblob_append( cb, val, -1 ); - //MARKER("memblob_size(cb) ==%ld, strlen(val)=%d val=[%s]\n",memblob_size(cb),strlen(val),val); - bool rc = true; - if( ! cb ) - { - rc = false; - free( dest->data ); - dest->data = 0; - } - else - { - memblob_base64_dec( cb, cb ); - if( (size_t)memblob_size(cb) != sz ) - { - rc = false; - C11N_LOG(C11N_LOG_ERROR)("Declared size of data (%u) is not the same as the decoded size (%ld)", - sz, memblob_size(cb)); - } - else - { - memcpy( dest->data, memblob_bufferc(cb), sz ); - } - } - memblob_finalize( cb ); - return rc; -} - - - -void c11n_dump_node( c11n_node const * c, bool recurse ) -{ - if( ! c ) return; - if(1) printf("c11n_node[@%p]: name=[%s] classname=[%s] (\n", - (void*)c, /* the cast is for gcc -std=c99 -pedantic */ - c11n_node_get_name(c), - c11n_node_get_class(c) ); - if( c->kvp.count ) - { - puts("properties=("); - c11n_propcount_t i = 0; - c11n_kvp const * e = c->kvp.list[i]; - //MARKER("node[@%p] freeing kvp list\n",c,e); - for( ; i < c->kvp.count; e = c->kvp.list[++i] ) - { - if( ! e ) - { - MARKER("internal error: got a null property in the the list.\n"); - continue; - } - printf("\t[%s]=[%s]\n", e->key, e->value ); - } - puts(") end properties"); - } - c11n_node const * ch = c->children; - if( ch && recurse ) - { - puts("children=("); - while( ch && ch->left ) ch = ch->left; - while( ch ) - { - c11n_node const * next = ch->right; - c11n_dump_node(ch,true); - ch = next; - } - puts(") end children"); - } - if( 1 ) - { - //MARKER; - printf(") end c11n_node[@%p]: name=[%s] classname=[%s]\n", - (void*)c, /* the cast is for gcc -std=c99 -pedantic */ - c11n_node_get_name(c), - c11n_node_get_class(c) ); - } -} - - -static int c11n_log_flags = C11N_LOG_DEFAULT; -static FILE * c11n_log_stream = 0; - -void c11n_log_set_stream( FILE * f ) -{ - c11n_log_stream = f; -} - -unsigned int c11n_log_get_flags() -{ - return c11n_log_flags; -} -unsigned int c11n_log_set_flags(unsigned int newflags) -{ - unsigned int x = c11n_log_flags; - c11n_log_flags = newflags; - return x; -} - -/** - "Automatic" arguments for c11n_logv() and friends. Names of - elements must match those defined in C11N_SOURCE_INFO_PARAMS_DECL. -*/ -#define C11N_SOURCE_INFO_PARAMS_PASS _file,_line,_func - -struct c11n_log_PRIVATE_t -{ - char const * filename; - char const * funcname; - unsigned int lineno; - unsigned int condition; - char const * condString; -}; -struct c11n_log_PRIVATE_t c11n_log_PRIVATE_init = {0,0,0,0,0}; -struct c11n_log_PRIVATE_t c11n_log_PRIVATE = {0,0,0,0,0}; - - -void c11n_logv( unsigned int condition, - C11N_SOURCE_INFO_PARAMS_DECL, - c11n_const_string_t fmt, - va_list vargs ) -{ -#if C11N_CONFIG_LOG_ENABLE - if( c11n_log_stream - && ((c11n_log_flags & condition) || (C11N_LOG_ALWAYS == c11n_log_flags) || (C11N_LOG_ALWAYS == condition)) - && fmt ) - { - long rc = 0; -#define VAPARGS vappendf_FILE_appender, c11n_log_stream - if( c11n_log_PRIVATE.condString ) - { - rc = fappendf( c11n_log_stream,"c11n_log(%s):%s:%d:%s(): ",c11n_log_PRIVATE.condString,C11N_SOURCE_INFO_PARAMS_PASS); - c11n_log_PRIVATE.condString = 0; - } - else - { - rc = fappendf( c11n_log_stream,"c11n_log(0x%08x):%s:%d:%s(): ",condition,C11N_SOURCE_INFO_PARAMS_PASS); - } - if( rc >= 0 ) rc = vappendf( vappendf_FILE_appender, c11n_log_stream, fmt, vargs ); - //vfprintf(c11n_log_stream,fmt,vargs); - if( rc >= 0 ) - { - fputc('\n',c11n_log_stream); - fflush(c11n_log_stream); - } -#undef VAPARGS - } -#endif // C11N_CONFIG_LOG_ENABLE -} - -void c11n_log( unsigned int condition, - C11N_SOURCE_INFO_PARAMS_DECL, - c11n_const_string_t fmt, - ... ) -{ -#if C11N_CONFIG_LOG_ENABLE - if( c11n_log_stream - && ((C11N_LOG_ALWAYS == c11n_log_flags) || (c11n_log_flags & condition)) - && fmt ) - { - va_list vargs; - va_start( vargs, fmt ); - c11n_logv( condition, C11N_SOURCE_INFO_PARAMS_PASS, fmt, vargs ); - va_end(vargs); - } -#endif -} - -static void c11n_log_PRIVATE_phase2( c11n_const_string_t fmt, ... ) -{ -#if C11N_CONFIG_LOG_ENABLE - va_list vargs; - va_start( vargs, fmt ); - c11n_logv( c11n_log_PRIVATE.condition, - c11n_log_PRIVATE.filename, - c11n_log_PRIVATE.lineno, - c11n_log_PRIVATE.funcname, - fmt, vargs ); - va_end(vargs); - c11n_log_PRIVATE = c11n_log_PRIVATE_init; -#endif -} - -c11n_log_PRIVATE_f c11n_log_PRIVATE_phase1( unsigned int condition, - c11n_const_string_t condString, - c11n_const_string_t file, - unsigned int line, - c11n_const_string_t funcName ) -{ -#if C11N_CONFIG_LOG_ENABLE - c11n_log_PRIVATE.condition = condition; - c11n_log_PRIVATE.condString = condString; - c11n_log_PRIVATE.filename = file; - c11n_log_PRIVATE.lineno = line; - c11n_log_PRIVATE.funcname = funcName; -#endif - return c11n_log_PRIVATE_phase2; -} - - - - -#define C11N_POD_USE_STRING 0 -/** - An enum of types supported by c11n_marshaller_pod. - The MUST start at 0 and go sequentially from there, - as they will be used as array indexes. -*/ -enum PodTypes { -PodTypeInt = 0, -PodTypeUInt = 1, -PodTypeLong, -PodTypeULong, -PodTypeFloat, -PodTypeDouble -#if C11N_POD_USE_STRING -,PodTypeString -#endif -} PodTypes; - -/** - Internal info for the POD marshallers. -*/ -static struct PodMarshallerInfo -{ - /** - MUST be one of the values from the PodTypes enum. - */ - short type; - /** Non-null classname. */ - char const * name; - /** Non-null printf()/scanf() format specifier. */ - char const * format; -} PodInfo[] = { -/* Entries MUST be in the same order as in the PodTypes enum! */ -{PodTypeInt,"int","%d"}, -{PodTypeUInt,"uint","%u"}, -{PodTypeLong,"long","%ld"}, -{PodTypeULong,"ulong","%lu"}, -{PodTypeFloat,"float","%f"}, -{PodTypeDouble,"double","%lf"}, -{0,0,0} -}; -//static unsigned short PodInfoSize = sizeof(PodInfo) * sizeof(PodInfo[0]); -typedef struct PodMarshallerInfo PodMarshallerInfo; - -/** - Custom traits type for handling several different types - of PODs, using sscanf() and printf() for de/serialization. -*/ -struct c11n_marshaller_pod -{ - /** Required by c11n_marshaller interface. */ - c11n_marshaller_api const * api; - /** - printf/sscanf() format specifier. - */ - char const * format; - /** - One of the values from the PodTypes array. If that enum is - extended, the c11n_marshaller_pod_[de]serialize() routines need - to be extended as well. - */ - int type; -}; -typedef struct c11n_marshaller_pod c11n_marshaller_pod; - -/** - Helper to get info tied to a pod c11n_marshaller. - */ -#define POD_INFO ((PodMarshallerInfo const *)(self->api->implData)) -#define POD_CHECK(RT) if( ! POD_INFO ) return RT - -/** - Helper to check the logical type of a pod handler. -*/ -#define POD_ISA(T) (PodType ## T == POD_INFO->type) -static bool c11n_marshaller_pod_serialize( c11n_marshaller const * self, - c11n_node * dest, - void const * src ) -{ - if( ! src || !dest ) return false; - POD_CHECK(false); - c11n_node_set_class( dest, POD_INFO->name ); - -#define DOPOD(PT,T) if(POD_ISA(PT)){ \ - T * v = (T *)src;\ - return c11n_node_prop_set_fe( dest, "val", POD_INFO->format, *v );\ - } -#if C11N_POD_USE_STRING - if( POD_ISA(String) ) - { - return c11n_node_prop_set(dest,"val",(char const*)src); - } -#endif - DOPOD(Int,int); - DOPOD(UInt,unsigned int); - DOPOD(Long,long); - DOPOD(ULong,unsigned long); - DOPOD(Float,float); - DOPOD(Double,double); -#undef DOPOD - return false; -} - -static bool c11n_marshaller_pod_deserialize( c11n_marshaller const * self, - c11n_node const * src, - void * dest ) -{ - if( ! self || !src || !dest ) return false; - POD_CHECK(false); - if( ! self->api->is_a( self, c11n_node_get_class(src) ) ) - { - c11n_log(C11N_LOG_FLAGS(C11N_LOG_WARNING), - "Classname doesn't match: [%s] != [%s]", - c11n_node_get_class(src), self->api->classname ); - return false; - } - c11n_const_string_t dv = 0; - if( !c11n_node_prop_get( src, "val", &dv ) || !dv ) return false; - - if( ! self->api->is_a(self,c11n_node_get_class(src)) ) return false; - -#define DOPOD(PT,T) if(POD_ISA(PT)){ \ - T tmp = 0;\ - if( 1 != sscanf(dv, POD_INFO->format, &tmp ) ) return false; \ - T * d = (T*)dest;\ - *d = tmp; \ - return true; \ - } -#if C11N_POD_USE_STRING - if( POD_ISA(String) ) - { -#if 0 - c11n_string_t cp = c11n_copy_str(dv); - *((char const **)dest) = cp; -#else - *((char const **)dest) = dv; -#endif - return true; - } -#endif // POD_ISA(String) - DOPOD(Int,int); - DOPOD(UInt,unsigned int); - DOPOD(Long,long); - DOPOD(ULong,unsigned long); - DOPOD(Float,float); - DOPOD(Double,double); -#undef DOPOD - return false; -} - -static void * c11n_marshaller_pod_create(c11n_marshaller const * self) -{ - POD_CHECK(0); -#define DOPOD(PT,T) if( POD_ISA(PT) ) return malloc(sizeof(T)); - DOPOD(Int,int); - DOPOD(UInt,unsigned int); - DOPOD(Long,long); - DOPOD(ULong,unsigned long); - DOPOD(Float,float); - DOPOD(Double,double); - return 0; -#undef DOPOD -} - -#undef POD_ISA - -/** - Create an implementation for c11n_marshaller_pod_ ## CN - - CN: class name. It MUST be the same as is defined in the - PodInfo array. - - PT: member of PodTypes enum: (PodType ## PT) - - All generated data is const, and all is static-scope except for: - - const c11n_marshaller * c11n_marshaller_pod_ ## CN; - - which should be declared in the public API. -*/ -#define PODDEF(CN,PT) \ - static const c11n_marshaller_api c11n_marshaller_pod_api_ ## CN = \ - C11N_MARSHALLER_API_INIT_FULL(# CN, \ - c11n_marshaller_pod_serialize, \ - c11n_marshaller_pod_deserialize, \ - c11n_marshaller_pod_create, \ - c11n_marshaller_api_clear, \ - c11n_marshaller_api_destroy, \ - c11n_marshaller_api_is_a, \ - &PodInfo[PodType ## PT]); \ - static const c11n_marshaller c11n_marshaller_pod_ ## CN ## _bogo = {&c11n_marshaller_pod_api_ ## CN}; \ - const c11n_marshaller * c11n_marshaller_pod_ ## CN = &c11n_marshaller_pod_ ## CN ## _bogo -PODDEF(int,Int); -PODDEF(uint,UInt); -PODDEF(long,Long); -PODDEF(ulong,ULong); -PODDEF(float,Float); -PODDEF(double,Double); -#undef PODDEF - #undef ARG_UNUSED #undef MARKER #undef C11N_MARSHALLER_POD #undef C11N_MARSHALLER_INIT #undef C11N_MARSHALLER_API_DEFAULT + #ifdef __cplusplus } /* extern "C" */ #endif Added: c11n/src/c11n/c11n_array.c =================================================================== --- c11n/src/c11n/c11n_array.c (rev 0) +++ c11n/src/c11n/c11n_array.c 2009-02-22 10:46:31 UTC (rev 266) @@ -0,0 +1,443 @@ +#if !defined(C11N_MARSHALLER_API_INIT) +#error "Do not compile this file directly - include it from c11n.c" +#endif + +/** + A helper type for de/serializing object arrays. +*/ +typedef struct c11n_array_info +{ + /** + The marshaller which this type proxies - it is used + to de/serialize individual array elements. + */ + c11n_marshaller const * marshaller; + /** + The number of items in the array. + + Serialization: required to be set to the length of the array. + + Deserialization: will be set by the API to the number of items + in the deserialized list. + */ + size_t count; + /** + MUST be sizeof(ST), where ST is the marshaller's Serializable + Type. + */ + size_t sizeOf; + /** + Only for serialization - the source object to serialize. + */ + void const * src; + /** + Only for deserialization - the API will set it to the deserialized + array. + */ + void * dest; +} c11n_array_info; + +static const c11n_array_info c11n_array_info_init = {0,0,0,0,0}; + +/** + Initializes an c11n_array_info object. +*/ +static c11n_array_info c11n_array_get_info( c11n_marshaller const * m, + size_t count, + size_t sizeOf, + void const * src, + void * dest ) +{ + c11n_array_info inf; + inf.marshaller = m; + inf.count = count; + inf.sizeOf = sizeOf; + inf.src = src; + inf.dest = dest; + return inf; +} + +/** + Initializes a c11n_array_info object for serialization. +*/ +c11n_array_info c11n_array_info_s( c11n_marshaller const * m, + size_t count, + size_t sizeOf, + void const * src ) +{ + return c11n_array_get_info( m, count, sizeOf, src, 0 ); +} + +/** + Initializes a c11n_array_info object for deserialization. +*/ +c11n_array_info c11n_array_info_d( c11n_marshaller const * m, + size_t sizeOf, + void * dest ) +{ + return c11n_array_get_info( m, 0, sizeOf, 0, dest ); +} + + +/** Internal helper to get a c11n_array_info object. On error, it returns RV. */ +#define METADECL(RV) c11n_array_info * meta = Info ? ((c11n_array_info *)Info) : 0; if(!meta) return RV +/** Internal helper to get a c11n_array_info object. On error, it returns RV. */ +#define METADECLC(RV) c11n_array_info const * meta = src ? ((c11n_array_info const *)src) : 0; if(!meta) return RV +/** c11n_marshaller_api::serialize() implementation for arrays. */ +static bool c11n_array_api_serialize( struct c11n_marshaller const * self, c11n_node * dest, void const * src ) +{ + METADECLC(false); + if( ! dest || !meta->count || !meta->sizeOf || !src ) return false; + c11n_marshaller const * m = meta->marshaller; + c11n_node_set_class( dest, "array" ); + c11n_node_prop_set( dest, "type", m->api->classname ); + c11n_node_prop_set_fe( dest, "sizeof", "%u", meta->sizeOf ); + size_t at = 0; + for(; at < meta->count; ++at ) + { + if( ! c11n_serialize_subnode( m, dest, "entry", meta->src + ( at* meta->sizeOf ) ) ) + { + C11N_LOG(C11N_LOG_ERROR)("Serialize of array item #%u failed :(.", at); + return false; + } + } + /* + Reminder: we COULD store count as a property to save some work at deser-time, + but doing so would make hand-editing the output problematic, as the user would + have to ensure that the count prop matches the child count. + */ + return true; +} +/** c11n_marshaller_api::deserialize() implementation for arrays. */ +static bool c11n_array_api_deserialize( struct c11n_marshaller const * self, c11n_node const *src, void * Info ) +{ + METADECL(false); + c11n_marshaller const * m = meta->marshaller; + if( ! m ) return false; + c11n_const_string_t cn = c11n_node_get_class(src); + if( !c11n_compare_str( "array", cn ) ) + { + C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " + "it was apparently not serialized using c11n_serialize_array() :(.", + m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src) ); + return 0; + } + c11n_const_string_t implClass = 0; + if( ! c11n_node_prop_get( src, "type", &implClass ) + || ! c11n_compare_str( m->api->classname, implClass ) + ) + { + C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " + "its stored stored type name (%s) does not match the marshaller :(.", + m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src), + implClass ); + return 0; + } + size_t sizeCheck = 0; + if( (1 != c11n_node_prop_get_fe( src, "sizeof", "%u", &sizeCheck )) + || (!sizeCheck) ) + { + C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " + "the sizeof property was not set :(.", + m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src) ); + return 0; + } + if( sizeCheck != meta->sizeOf ) + { + C11N_LOG(C11N_LOG_WARNING)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]): " + "sizeof(%s) has changed since the data was serialized (old=%u, new=%u).", + m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src), + m->api->classname, sizeCheck, meta->sizeOf ); + /* keep going... */ + } + + c11n_node_iter_c iter = c11n_node_children_iter_c(src); + if( ! c11n_node_iter_isvalid_c( &iter ) ) return 0; + size_t count = 0; + do + { + ++count; + } while( c11n_node_iter_next_c( &iter ) ); + //MARKER("here, count=%u\n",count); + if( ! count ) + { + C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array) from (c11n_node@%p[class=%s, name=%s]) failed because " + "the c11n_node contains no children to deserialize :(.", + m->api->classname, src, c11n_node_get_class(src), c11n_node_get_name(src) ); + return 0; + } + void * mal = calloc( count, meta->sizeOf ); + if( ! mal ) return 0; + void * prototype = m->api->create(m); + if( ! prototype ) + { + free( mal ); + return 0; + } + iter = c11n_node_children_iter_c(src); + bool isokay = true; + size_t decount = 0; + for( ; (decount < count) && c11n_node_iter_isvalid_c(&iter); ++decount ) + { + void * obj = (mal + (decount * meta->sizeOf)); + /** + The right thing to do here would be use m->api->create(m) + to instantiate a prototype object, copy it over obj, then + call free(m,prototype). However, i'm stil trying to think + of a use case where that pedenticness would matter. It'd cost us + count allocs, which is the only reason i haven't done it yet. + */ + memcpy( obj, prototype, meta->sizeOf ); + if( ! c11n_deserialize( m, iter.node, obj ) ) + { + C11N_LOG(C11N_LOG_ERROR)("Deserialize of (%s array)[#%u] from (c11n_node@%p[class=%s, name=%s]) failed :(.", + implClass, decount, iter.node, + c11n_node_get_class( iter.node ), c11n_node_get_name( iter.node ) + ); + isokay = false; + break; + } + c11n_node_iter_next_c(&iter); + } + m->api->destroy( m, prototype ); + if( ! isokay ) + { + size_t c = 0; + /** + c11n_deserialize() will clean up if it fails, but we need + to clean up all items leading up to (but not including) the + failed item. + */ + if(decount>0) for( ; c < (decount-1); ++c ) + { + m->api->clear(m, mal + ( c * meta->sizeOf )); + } + free( mal ); + count = 0; + } + else + { + meta->dest = mal; + meta->count = count; + } + return meta->count; +} + +/** c11n_marshaller_api::create() implementation for arrays. */ +static void * c11n_array_api_create( struct c1... [truncated message content] |
From: <sg...@us...> - 2009-02-21 14:59:17
|
Revision: 265 http://s11n.svn.sourceforge.net/s11n/?rev=265&view=rev Author: sgbeal Date: 2009-02-21 14:59:11 +0000 (Sat, 21 Feb 2009) Log Message: ----------- minor windows compatibility addition. Modified Paths: -------------- c11n/src/io/c11n_stream_FILE.c Modified: c11n/src/io/c11n_stream_FILE.c =================================================================== --- c11n/src/io/c11n_stream_FILE.c 2009-02-21 14:16:48 UTC (rev 264) +++ c11n/src/io/c11n_stream_FILE.c 2009-02-21 14:59:11 UTC (rev 265) @@ -70,7 +70,7 @@ c11n_stream * c11n_stream_for_filename( c11n_const_string_t src, bool writeMode ) { - FILE * fp = fopen( src, writeMode ? "w" : "r" ); + FILE * fp = fopen( src, writeMode ? "wb" : "rb" ); if( ! fp ) return 0; c11n_stream * st = c11n_stream_for_FILE(fp); if( ! st ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sg...@us...> - 2009-02-21 14:16:58
|
Revision: 264 http://s11n.svn.sourceforge.net/s11n/?rev=264&view=rev Author: sgbeal Date: 2009-02-21 14:16:48 +0000 (Sat, 21 Feb 2009) Log Message: ----------- Minor updates and corrections. Modified Paths: -------------- c11n/doc/manual/libc11n-manual.odt Modified: c11n/doc/manual/libc11n-manual.odt =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:28
|
Update of /cvsroot/s11n/1.1/s11n/doc/manual In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/doc/manual Modified Files: libs11n.odt Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. Index: libs11n.odt =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/doc/manual/libs11n.odt,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 Binary files /tmp/cvskNpdaY and /tmp/cvsFtHBxU differ |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:28
|
Update of /cvsroot/s11n/1.1/s11n/src/io/compact In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/io/compact Modified Files: compact.flex.cpp Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:28
|
Update of /cvsroot/s11n/1.1/s11n/src/io/funxml In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/io/funxml Modified Files: funxml.flex.cpp Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:28
|
Update of /cvsroot/s11n/1.1/s11n/src/io/funtxt In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/io/funtxt Modified Files: funtxt.flex.cpp Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:27
|
Update of /cvsroot/s11n/1.1/s11n/src/io In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/io Modified Files: serializer_lex.make Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. Index: serializer_lex.make =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/io/serializer_lex.make,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- serializer_lex.make 25 Jan 2007 00:16:39 -0000 1.7 +++ serializer_lex.make 21 Feb 2009 13:41:22 -0000 1.8 @@ -94,6 +94,7 @@ -e 's|<FlexLexer\.h>|<$(FlexLexer_hpp)>|g;' \ -e 's|class (std\::)?istream;|#include <iostream>|;' \ -e 's/\biostream\.h\b/iostream/;' \ + -e 's|^\s*//(.*isatty.*)|$1|;' \ -e 'next if m/\biostream\b/;' \ -e 'next if m/::[io]stream/;' \ -e 's/(\bostream\b|\bistream\b)([^\.])/std::$$1$$2/g;' $@ || exit ; \ |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:27
|
Update of /cvsroot/s11n/1.1/s11n/src/io/parens In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/io/parens Modified Files: parens.flex.cpp Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. |
Update of /cvsroot/s11n/1.1/s11n/src/s11n In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/s11n Modified Files: algo.hpp algo.tpp exception.hpp export.hpp s11n_debuggering_macros.hpp s11n_node.hpp serialize.tpp traits.hpp Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. Index: exception.hpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/s11n/exception.hpp,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- exception.hpp 17 Feb 2007 17:12:53 -0000 1.13 +++ exception.hpp 21 Feb 2009 13:41:23 -0000 1.14 @@ -4,12 +4,17 @@ #include <string> #include <exception> #include <s11n.net/s11n/s11n_config.hpp> + +//Added by Damien to make Windows compile work +#include <s11n.net/s11n/export.hpp> // S11N_EXPORT_API + namespace s11n { /** The base-most exception type used by s11n. */ - struct s11n_exception : public std::exception + //Added by Damien to make Windows compile work + struct S11N_EXPORT_API s11n_exception : public std::exception { public: virtual ~s11n_exception() throw() {} @@ -60,7 +65,7 @@ cases because sometimes a classloader can try other alternatives on an error. */ - struct factory_exception : public s11n_exception + struct S11N_EXPORT_API factory_exception : public s11n_exception { public: virtual ~factory_exception() throw() {} Index: serialize.tpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/s11n/serialize.tpp,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- serialize.tpp 6 Nov 2008 16:16:42 -0000 1.5 +++ serialize.tpp 21 Feb 2009 13:41:23 -0000 1.6 @@ -199,11 +199,8 @@ typedef typename s11n::type_traits<DeserializableT>::type stype; typedef ::s11n::s11n_traits<stype> STR; typedef ::s11n::node_traits<DataNodeType> NTR; - typedef typename STR::factory_type FAC; - typedef s11n::cleanup_ptr<stype> CLEAN; - FAC fac; - CLEAN obj( fac( NTR::class_name(src) ) ); + s11n::cleanup_ptr<stype> obj( FAC()( NTR::class_name( src ) ) ); if( ! obj.get() ) { using namespace ::s11n::debug; Index: export.hpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/s11n/export.hpp,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- export.hpp 25 Jun 2005 14:41:39 -0000 1.1 +++ export.hpp 21 Feb 2009 13:41:23 -0000 1.2 @@ -16,16 +16,54 @@ **********************************************************************/ - #ifdef WIN32 // #warning "Exporting Windows-style!" -// # ifdef S11N_EXPORTS + # ifdef S11N_EXPORTS # define S11N_EXPORT_API __declspec(dllexport) -// # else -// # define S11N_EXPORT_API __declspec(dllimport) -// # endif + # else + # define S11N_EXPORT_API __declspec(dllimport) + # endif #else # define S11N_EXPORT_API #endif -#endif // s11n_net_S11N_EXPORT_HPP_INCLUDED +//#endif // s11n_net_S11N_EXPORT_HPP_INCLUDED + +/* +#ifdef S11NEXPORT +# undef S11NEXPORTAPI +# ifndef S11NEXPORTAPI +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define S11NEXPORTAPI +# else +# define S11NEXPORTAPI __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define S11NEXPORTAPI __attribute__ ((visibility("default"))) +# else +# define S11NEXPORTAPI +# endif +# endif +# endif +#else +# ifndef S11NEXPORTAPI +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define S11NEXPORTAPI +# else +# define S11NEXPORTAPI __declspec(dllimport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define S11NEXPORTAPI __attribute__ ((visibility("default"))) +# else +# define S11NEXPORTAPI +# endif +# endif +# endif +#endif +*/ +#endif + Index: s11n_node.hpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/s11n/s11n_node.hpp,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- s11n_node.hpp 27 Aug 2005 17:07:36 -0000 1.7 +++ s11n_node.hpp 21 Feb 2009 13:41:23 -0000 1.8 @@ -14,289 +14,292 @@ #include <s11n.net/s11n/variant.hpp> // for lexical casting #include <s11n.net/s11n/export.hpp> -namespace s11n { - /** - s11n_node is a slightly lighter-weight replacement for - the data_node type used in s11n 1.0.x. It will become - the standard node type for s11nlite in 1.1/1.2. - */ - class S11N_EXPORT_API s11n_node - { - public: +namespace s11n { + + + +/** +s11n_node is a slightly lighter-weight replacement for +the data_node type used in s11n 1.0.x. It will become +the standard node type for s11nlite in 1.1/1.2. +*/ +class S11N_EXPORT_API s11n_node +{ +public: + +/** +The map type this object uses to store properties. +*/ +typedef std::map < std::string, std::string > map_type; - /** - The map type this object uses to store properties. - */ - typedef std::map < std::string, std::string > map_type; +/** +A pair type used to store key/value properties +internally. +*/ +typedef map_type::value_type value_type; - /** - A pair type used to store key/value properties - internally. - */ - typedef map_type::value_type value_type; +/** The type used to store property keys. For +compatibility with std::map. +*/ +typedef map_type::key_type key_type; - /** The type used to store property keys. For - compatibility with std::map. - */ - typedef map_type::key_type key_type; +/** The type used to internally store property +values. For compatibility with std::map. +*/ +typedef map_type::mapped_type mapped_type; - /** The type used to internally store property - values. For compatibility with std::map. - */ - typedef map_type::mapped_type mapped_type; +/** +The container type used to store this object's children. +It contains (s11n_node *). - /** - The container type used to store this object's children. - It contains (s11n_node *). +While the exact type is not guaranteed, it is +guaranteed to obey the most-commonly-used +std::list/vector conventions: push_back(), erase(), +etc. +*/ +typedef std::vector<s11n_node *> child_list_type; - While the exact type is not guaranteed, it is - guaranteed to obey the most-commonly-used - std::list/vector conventions: push_back(), erase(), - etc. - */ - typedef std::vector<s11n_node *> child_list_type; +/** +Creates a new node with an empty name() and an +class_name() of "s11n::s11n_node". This +node is functionally useless until it's name is +set, as nodes with empty names are not supported by +any current i/o parsers. +*/ +s11n_node(); - /** - Creates a new node with an empty name() and an - class_name() of "s11n::s11n_node". This - node is functionally useless until it's name is - set, as nodes with empty names are not supported by - any current i/o parsers. - */ - s11n_node(); +/** +Creates a new node with the given name() and an +class_name() of "s11n::s11n_node". +*/ +explicit s11n_node( const std::string & name ); - /** - Creates a new node with the given name() and an - class_name() of "s11n::s11n_node". - */ - explicit s11n_node( const std::string & name ); +/** +Creates a new node with the given name() and and class_name(). - /** - Creates a new node with the given name() and and class_name(). +Does not throw. +*/ +s11n_node( const std::string & name, const std::string implclass ); - Does not throw. - */ - s11n_node( const std::string & name, const std::string implclass ); +/** +Destroys all child objects owned by this object, freeing up +their resources. - /** - Destroys all child objects owned by this object, freeing up - their resources. +Does not throw. +*/ +~s11n_node(); - Does not throw. - */ - ~s11n_node(); +/** +Swaps all publically-visible internal state with +rhs. This includes: - /** - Swaps all publically-visible internal state with - rhs. This includes: +- class_name() +- name() +- children() +- properties() - - class_name() - - name() - - children() - - properties() +Complexity is, in theory, constant time. For all +data we use their member swap() implementations, +which should be constant-time for the +containers. The C++ Standard apparently guarantees +O(1) swap() for strings, too. (Josuttis, The C++ +Standard Library, section 11.2.8, page 490.) - Complexity is, in theory, constant time. For all - data we use their member swap() implementations, - which should be constant-time for the - containers. The C++ Standard apparently guarantees - O(1) swap() for strings, too. (Josuttis, The C++ - Standard Library, section 11.2.8, page 490.) +Added in version 1.1.3. +*/ +void swap( s11n_node & rhs ); - Added in version 1.1.3. - */ - void swap( s11n_node & rhs ); +/** +Copies the properties, name, class name and +children of rhs. If rhs is this object then this +function does nothing. - /** - Copies the properties, name, class name and - children of rhs. If rhs is this object then this - function does nothing. +Does not throw. +*/ +s11n_node & operator=( const s11n_node & rhs ); - Does not throw. - */ - s11n_node & operator=( const s11n_node & rhs ); +/** +See copy(). - /** - See copy(). +Does not throw. +*/ +s11n_node( const s11n_node & rhs ); - Does not throw. - */ - s11n_node( const s11n_node & rhs ); +/** +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 manipulate this list directly. +*/ +child_list_type & children(); - /** - 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 manipulate this list directly. - */ - child_list_type & children(); +/** +The const form of children(). +*/ +const child_list_type & children() const; - /** - The const form of children(). - */ - const child_list_type & children() const; +/** +Removes all properties and deletes all children from +this object, freeing up their resources. - /** - Removes all properties and deletes all children from - this object, freeing up their resources. - - Any pointers to children of this object become - invalided by a call to this function (they get - deleted). - */ - void clear(); +Any pointers to children of this object become +invalided by a call to this function (they get +deleted). +*/ +void clear(); - /** - Defines the class name which should be used as the - implementation class when this node is - deserialize()d. +/** +Defines the class name which should be used as the +implementation class when this node is +deserialize()d. - Client Serializable types should call this one time - from their serialize() method, <em>after</em> calling - the parent class' serialize() method (if indeed that - is called at all), passing it the name of their class, - <em>using the name expected by the classloader</em>. By convention - the class name is the same as it's C++ name, thus Serializable - class foo::FooBar should call: +Client Serializable types should call this one time +from their serialize() method, <em>after</em> calling +the parent class' serialize() method (if indeed that +is called at all), passing it the name of their class, +<em>using the name expected by the classloader</em>. By convention +the class name is the same as it's C++ name, thus Serializable +class foo::FooBar should call: <pre> node.class_name( "foo::FooBar" ); </pre> - from it's serialize() function. - - - If classes to not set this then the serialized data - will not have a proper implementation class - name. That is likely to break deserialization. - - TODO: consider returning the old value, - to simplify swap() operations. - - Added in 1.1.3. - */ - void class_name( const std::string & n ); - +from it's serialize() function. - /** - Returns the implementation class name set via - class_name(). - */ - std::string class_name() 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 very well may.) - */ - void name( const std::string & n ); +If classes to not set this then the serialized data +will not have a proper implementation class +name. That is likely to break deserialization. - /** - Returns this node's name, as set via name(string). - */ - std::string name() const; +TODO: consider returning the old value, +to simplify swap() operations. - /** - Returns true if this object has no properties - and no children. The name() and class_name() - are *not* considered. - */ - bool empty() const; +Added in 1.1.3. +*/ +void class_name( const std::string & n ); - /** - Lexically casts val to a string and stores it as a - property. If this type conversion is not possible - it will fail at compile time. A value-conversion - failure, on the other hand, is not caught at - compile time. T must support complementary - ostream<< and istream>> operators. - */ - template < typename T > - void set( const std::string & key, const T & val ) - { - this->m_map[key] = ::s11n::Detail::variant(val).str(); - } +/** +Returns the implementation class name set via +class_name(). +*/ +std::string class_name() const; - /** - Tries to get a property named key and lexically - cast it to type T. If this type conversion is not - possible it will fail at compile time. A - value-conversion failure, on the other hand, is not - caught at compile time. If value conversion fails, - or if the requested property is not set, then - defaultval is returned. This can be interpretted as - an error value if the client so chooses, and it is - often helpful to pass a known-invalid value here - for that purpose. +/** +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 very well may.) +*/ +void name( const std::string & n ); - */ - template < typename T > - T get( const std::string & key, const T & defaultval ) const - { - map_type::const_iterator cit = this->m_map.find( key ); - return ( this->m_map.end() == cit ) ? defaultval : ::s11n::Detail::variant( (*cit).second ).cast_to(defaultval); - } +/** +Returns this node's name, as set via name(string). +*/ +std::string name() const; - /** - Returns true if this object contains the given - property, else false. - */ - bool is_set( const std::string & key ) const; +/** +Returns true if this object has no properties +and no children. The name() and class_name() +are *not* considered. +*/ +bool empty() const; - /** - Removes the given property from this object. - */ - void unset( const std::string & key ); - /** - Returns the map of properties contained by this - node. - */ - map_type & properties(); +/** +Lexically casts val to a string and stores it as a +property. If this type conversion is not possible +it will fail at compile time. A value-conversion +failure, on the other hand, is not caught at +compile time. T must support complementary +ostream<< and istream>> operators. +*/ +template < typename T > +void set( const std::string & key, const T & val ) +{ + this->m_map[key] = ::s11n::Detail::variant(val).str(); +} - /** Const overload. */ - const map_type & properties() const; +/** +Tries to get a property named key and lexically +cast it to type T. If this type conversion is not +possible it will fail at compile time. A +value-conversion failure, on the other hand, is not +caught at compile time. If value conversion fails, +or if the requested property is not set, then +defaultval is returned. This can be interpretted as +an error value if the client so chooses, and it is +often helpful to pass a known-invalid value here +for that purpose. - private: - std::string m_name; // name of this node - std::string m_iname; // class_name name of this node - map_type m_map; // stores key/value properties. - child_list_type m_children; // holds child pointers +*/ +template < typename T > +T get( const std::string & key, const T & defaultval ) const +{ + map_type::const_iterator cit = this->m_map.find( key ); + return ( this->m_map.end() == cit ) ? defaultval : ::s11n::Detail::variant( (*cit).second ).cast_to(defaultval); +} - /** - Copies all properties and child s11n_nodes from - rhs into this object, as well as any other details - which need to be copied. +/** +Returns true if this object contains the given +property, else false. +*/ +bool is_set( const std::string & key ) const; - This can be a very expensive operation, and is rarely - necessary. - */ - void copy( const s11n_node & rhs ); +/** +Removes the given property from this object. +*/ +void unset( const std::string & key ); - /** - Removes all property entries from this object. - */ - void clear_properties(); +/** +Returns the map of properties contained by this +node. +*/ +map_type & properties(); - /** - Removes all children from this object, deleting all - child pointers. - */ - void clear_children(); +/** Const overload. */ +const map_type & properties() const; - }; // class s11n_node +private: + std::string m_name; // name of this node + std::string m_iname; // class_name name of this node + map_type m_map; // stores key/value properties. + child_list_type m_children; // holds child pointers + + /** + Copies all properties and child s11n_nodes from + rhs into this object, as well as any other details + which need to be copied. + + This can be a very expensive operation, and is rarely + necessary. + */ + void copy( const s11n_node & rhs ); + + /** + Removes all property entries from this object. + */ + void clear_properties(); + + /** + Removes all children from this object, deleting all + child pointers. + */ + void clear_children(); + +}; // class s11n_node } // namespace s11n Index: algo.tpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/s11n/algo.tpp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- algo.tpp 3 Jun 2008 17:34:10 -0000 1.4 +++ algo.tpp 21 Feb 2009 13:41:23 -0000 1.5 @@ -102,7 +102,7 @@ template <typename NodeT> -void s11n::debug::dump_node_structure( const NodeT & n, int indentlv = 0 ) +void s11n::debug::dump_node_structure( const NodeT & n, int indentlv) { typedef s11n::node_traits<NodeT> TR; typedef typename TR::child_list_type CLT; Index: s11n_debuggering_macros.hpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/s11n/s11n_debuggering_macros.hpp,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- s11n_debuggering_macros.hpp 19 Sep 2008 15:51:10 -0000 1.5 +++ s11n_debuggering_macros.hpp 21 Feb 2009 13:41:23 -0000 1.6 @@ -13,6 +13,10 @@ #include <iostream> +//Added by Damien to make Windows compile work +#include <s11n.net/s11n/export.hpp> // S11N_EXPORT_API + + //////////////////////////////////////////////////////////////////////// // Debuggering/tracing macros for the s11n internals... // The xxx_PROFILE_xxx macros are NOT part of the API: @@ -93,13 +97,15 @@ /** Returns the current trace mask. */ - unsigned long trace_mask(); + //Added by Damien to make Windows compile work + S11N_EXPORT_API unsigned long trace_mask(); /** Returns the ostream used for tracing messages. Default is std::cerr. */ - std::ostream & trace_stream(); + //Added by Damien to make Windows compile work + S11N_EXPORT_API std::ostream & trace_stream(); /** Sets the ostream used for tracing messages. */ void trace_stream( std::ostream & ); Index: traits.hpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/s11n/traits.hpp,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- traits.hpp 19 Sep 2008 15:51:10 -0000 1.15 +++ traits.hpp 21 Feb 2009 13:41:23 -0000 1.16 @@ -10,6 +10,7 @@ #include <s11n.net/s11n/type_traits.hpp> #include <s11n.net/s11n/s11n_debuggering_macros.hpp> + namespace s11n { /** Index: algo.hpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/s11n/algo.hpp,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- algo.hpp 10 May 2008 12:17:33 -0000 1.16 +++ algo.hpp 21 Feb 2009 13:41:23 -0000 1.17 @@ -676,7 +676,6 @@ */ template <typename NodeT> void dump_node_structure( const NodeT & n, int indentlv = 0 ); - } // namespace |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:26
|
Update of /cvsroot/s11n/1.1/s11n/src/io/wesnoth In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/io/wesnoth Modified Files: wesnoth.flex.cpp Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:26
|
Update of /cvsroot/s11n/1.1/s11n/src/io/simplexml In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/io/simplexml Modified Files: simplexml.flex.cpp Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:26
|
Update of /cvsroot/s11n/1.1/s11n/src/plugin In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/plugin Modified Files: plugin.hpp Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. Index: plugin.hpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/plugin/plugin.hpp,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- plugin.hpp 3 Jul 2005 14:09:14 -0000 1.5 +++ plugin.hpp 21 Feb 2009 13:41:23 -0000 1.6 @@ -3,6 +3,10 @@ #include <s11n.net/s11n/plugin/path_finder.hpp> #include <s11n.net/s11n/plugin/plugin_config.hpp> + +//Added by Damien to make Windows compile work +#include <s11n.net/s11n/export.hpp> // S11N_EXPORT_API + namespace s11n { /** The plugin namespace encapsulates the braindeadly basic API @@ -48,7 +52,8 @@ /** Returns path().find( basename ). */ - std::string find( const std::string & basename ); + //Added by Damien to make Windows compile work + S11N_EXPORT_API std::string find( const std::string & basename ); /** Uses find(basename) to search for a file and, if @@ -71,7 +76,8 @@ then pass them to this function to do the platform-specific work of opening the DLL. */ - std::string open( const std::string & basename ); + //Added by Damien to make Windows compile work + S11N_EXPORT_API std::string open( const std::string & basename ); /** Called immediately after open() fails, it returns a @@ -91,7 +97,8 @@ under Win32. */ - std::string dll_error(); + //Added by Damien to make Windows compile work + S11N_EXPORT_API std::string dll_error(); } // namespace plugin } // namespace s11n |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:26
|
Update of /cvsroot/s11n/1.1/s11n/src/lite In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484/src/lite Modified Files: client_api.hpp s11nlite.hpp Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. Index: s11nlite.hpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/lite/s11nlite.hpp,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- s11nlite.hpp 19 Sep 2008 15:51:09 -0000 1.13 +++ s11nlite.hpp 21 Feb 2009 13:41:22 -0000 1.14 @@ -63,6 +63,9 @@ #include <s11n.net/s11n/io/data_node_io.hpp> // s11n::io::data_node_serializer class #include <s11n.net/s11n/client_api.hpp> // the "real" implementation for most of s11nlite. +//Added by Damien to make Windows compile work +#include <s11n.net/s11n/export.hpp> // S11N_EXPORT_API + namespace s11nlite { @@ -107,7 +110,8 @@ See instance(client_interface*) for more details. */ - client_interface & instance(); + //Added by Damien to make Windows compile work + S11N_EXPORT_API client_interface & instance(); /** Sets the client_interface object used by the s11nlite Index: client_api.hpp =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/src/lite/client_api.hpp,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- client_api.hpp 10 Dec 2005 12:16:38 -0000 1.10 +++ client_api.hpp 21 Feb 2009 13:41:22 -0000 1.11 @@ -226,9 +226,14 @@ virtual bool save( const node_type & src, std::ostream & dest ) { std::auto_ptr<serializer_interface> s(this->create_serializer()); - return s.get() - ? s->serialize( src, dest ) - : false; + if( s.get() ) + { + return s->serialize( src, dest ); + } + else + { + return false; + } } /** @@ -277,9 +282,14 @@ inline bool save( const SerializableType & src, std::ostream & dest ) { node_type n; - return this->serialize( n, src ) - ? this->save( n, dest ) - : false; + if( this->serialize( n, src ) ) + { + return this->save( n, dest ); + } + else + { + return false; + } } /** |
From: stephan b. <sg...@us...> - 2009-02-21 13:41:26
|
Update of /cvsroot/s11n/1.1/s11n In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv27484 Modified Files: ChangeLog configure configure.libs11n create_generated_tree.sh Log Message: Added patches from Damien Hocking to make s11n able to link as a DLL on Windows platforms. Index: create_generated_tree.sh =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/create_generated_tree.sh,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- create_generated_tree.sh 26 Apr 2008 16:33:34 -0000 1.5 +++ create_generated_tree.sh 21 Feb 2009 13:41:20 -0000 1.6 @@ -60,7 +60,7 @@ srctgt=${target_dir}/src test -d ${srctgt} || mkdir -p ${srctgt} for s in ${in_sources}; do - cp $s ${srctgt}/${s##*/} || exit + cp -p $s ${srctgt}/${s##*/} || exit done echo "Kludgy changes of some files..." @@ -74,9 +74,9 @@ perl -i -pe 's|(s11n_CONFIG_HAVE_ZFSTREAM) +.*|$1 0|;s|(s11n_CONFIG_HAVE_LIBEXPAT) +.*|$1 0|' $sconfig echo "Installing READMEs and rudimentary Makefile..." -cp README.WIN32 README.src INSTALL.nobuildfiles LICENSE.libs11n ${target_dir} +cp -p README.WIN32 README.src INSTALL.nobuildfiles LICENSE.libs11n ${target_dir} mf=${PWD}/src/Makefile.for.generated.src.tree -cp $mf ${srctgt}/Makefile +cp -p $mf ${srctgt}/Makefile echo "Finished. Output is in:" echo ${target_dir} Index: ChangeLog =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/ChangeLog,v retrieving revision 1.26 retrieving revision 1.27 diff -u -d -r1.26 -r1.27 --- ChangeLog 4 Jun 2008 19:36:48 -0000 1.26 +++ ChangeLog 21 Feb 2009 13:41:19 -0000 1.27 @@ -5,6 +5,32 @@ ======================================================================== +1.2.10: + +- Added patches from Damien Hocking to make s11n able to link as a +DLL on Windows platforms. + + +1.2.9: + +- Build tree now won't die when a clean tree is built using parallel +compilation (e.g. make -j2). + +- Corrected incorrect s11n_S11N_LIBRARY_VERSION_HEX macro value (was +set to version 1.2.7 instead of 1.2.8). + + +1.2.8: 8 Sept 2008 + +- A small fix for the multiple-registration fix from 1.2.7. The change +apparently does not make a difference, but it makes me feel better. + +- Fixed a couple warnings in the class factory code for certain compilers +(e.g. gcc 4.2.3). + +- Added s11nlite::load_node([stream|string], node_type &). + + 1.2.7: 5 June 2008 Achtung: not strictly code-compatible with 1.2.6 and earlier. This Index: configure =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/configure,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- configure 4 Jun 2008 19:36:48 -0000 1.13 +++ configure 21 Feb 2009 13:41:20 -0000 1.14 @@ -4,8 +4,8 @@ . ./find_toc.sh || exit export PACKAGE_NAME=libs11n -export PACKAGE_VERSION=1.2.7 -export PACKAGE_VERSION_HEX="0x010207" +export PACKAGE_VERSION=1.2.10 +export PACKAGE_VERSION_HEX="0x010210" # toconfigure will call configure.${PACKAGE_NAME}, so package-specific # processing should be done there. . ${TOC_HOME}/sbin/toconfigure "$@" Index: configure.libs11n =================================================================== RCS file: /cvsroot/s11n/1.1/s11n/configure.libs11n,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- configure.libs11n 26 Apr 2008 14:13:36 -0000 1.13 +++ configure.libs11n 21 Feb 2009 13:41:20 -0000 1.14 @@ -4,7 +4,7 @@ # This file will be sourced by the configure script, and is not # intended to be run directly. -toc_add_config PACKAGE_RELEASE_CODENAME="Arlo Guthrie" +toc_add_config PACKAGE_RELEASE_CODENAME="The Software Still Known As S11n" toc_export PACKAGE_VERSION_HEX="$PACKAGE_VERSION_HEX" toc_test check_dist_md5s |
From: <sg...@us...> - 2009-02-21 11:15:54
|
Revision: 263 http://s11n.svn.sourceforge.net/s11n/?rev=263&view=rev Author: sgbeal Date: 2009-02-21 11:15:45 +0000 (Sat, 21 Feb 2009) Log Message: ----------- egg Added Paths: ----------- s11n-qt/src/S11nQt/makeProxy.sh Added: s11n-qt/src/S11nQt/makeProxy.sh =================================================================== --- s11n-qt/src/S11nQt/makeProxy.sh (rev 0) +++ s11n-qt/src/S11nQt/makeProxy.sh 2009-02-21 11:15:45 UTC (rev 263) @@ -0,0 +1,75 @@ +#!/bin/bash +# Quick hack to create stub code for S11nQt proxies. +# Usage: $1 QtClassName +# Creates QtClassName.h and QtClassName.cpp +if [[ "$1x" = "x" ]]; then + echo "Usage: $0 CLASSNAME" + exit 1 +fi + +cl=$1 + +hpp=$cl.h +cpp=$cl.cpp +for i in $hpp $cpp; do + if [[ -e $i ]]; then + echo "Error: file already exists: $i" + exit 2 + fi +done + +guard="S11NQT_${cl}_H_INCLUDED" +lic=license.txt +test -f $lic || { + cat <<EOF > $lic +/* + * This file is (or was, at some point) part of the QBoard project + * (http://code.google.com/p/qboard) + * + * Copyright (c) 2008 Stephan Beal (http://wanderinghorse.net/home/stephan/) + * + * This file may be used under the terms of the GNU General Public + * License versions 2.0 or 3.0 as published by the Free Software + * Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 + * included in the packaging of this file. + * + */ +EOF + +} + +ftor="${cl}_s11n" +cat <<EOF > $hpp +#ifndef ${guard} +#define ${guard} 1 +#include <${cl}> +namespace s11n { namespace qt { +/* s11n proxy for ${cl}.*/ +struct ${ftor} +{ + /** Serializes src to dest. */ + bool operator()( S11nNode & dest, ${cl} const & src ) const; + /** Deserializes dest from src. */ + bool operator()( S11nNode const & src, ${cl} & dest ) const; +}; +}} // namespace +/** register s11n proxy for ${cl}. */ +#define S11N_TYPE ${cl} +#define S11N_TYPE_NAME "${cl}" +#define S11N_SERIALIZE_FUNCTOR s11n::qt::${ftor} +#include <s11n.net/s11n/reg_s11n_traits.hpp> +#endif // ${guard} +EOF + +cat <<EOF > $cpp +$(cat ${lic}) +#include "S11nQt.h" +#include "${cl}.h" +EOF + + +sed -ne "/^bool ${ftor}/,/^}/p" < ../S11nQt.cpp >> $cpp + +rm -f $lic 2>/dev/null +echo "#include \"S11nQt/${hpp}\"" +echo "Output is in ${cpp} and ${hpp}" Property changes on: s11n-qt/src/S11nQt/makeProxy.sh ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sg...@us...> - 2009-02-21 11:14:45
|
Revision: 262 http://s11n.svn.sourceforge.net/s11n/?rev=262&view=rev Author: sgbeal Date: 2009-02-21 11:14:36 +0000 (Sat, 21 Feb 2009) Log Message: ----------- Fixed de/ser of QRegExp::minimal, added QBitArray. Modified Paths: -------------- s11n-qt/src/S11nQt/QByteArray.h s11n-qt/src/S11nQt.cpp Modified: s11n-qt/src/S11nQt/QByteArray.h =================================================================== --- s11n-qt/src/S11nQt/QByteArray.h 2009-02-21 11:12:03 UTC (rev 261) +++ s11n-qt/src/S11nQt/QByteArray.h 2009-02-21 11:14:36 UTC (rev 262) @@ -37,7 +37,7 @@ If set to 0 then compression is disabled. The default value is quite small - technically undefined, but "probably" around 100. */ - static unsigned short compressionThreshold; + static unsigned long compressionThreshold; }; }} // namespaces /** s11n proxy for QByteArray. */ Modified: s11n-qt/src/S11nQt.cpp =================================================================== --- s11n-qt/src/S11nQt.cpp 2009-02-21 11:12:03 UTC (rev 261) +++ s11n-qt/src/S11nQt.cpp 2009-02-21 11:14:36 UTC (rev 262) @@ -19,6 +19,7 @@ #include "S11nQt.h" #include <s11n.net/s11n/functional.hpp> +#include "S11nQt/QBitArray.h" #include "S11nQt/QBrush.h" #include "S11nQt/QByteArray.h" #include "S11nQt/QColor.h" @@ -33,7 +34,6 @@ #include "S11nQt/QPair.h" #include "S11nQt/QPen.h" #include "S11nQt/QPixmap.h" -#include "S11nQt/QPixmap.h" #include "S11nQt/QPoint.h" #include "S11nQt/QPointF.h" #include "S11nQt/QRect.h" @@ -157,6 +157,61 @@ return bob.value( i, QString("NoBrush") ); } +bool QBitArray_s11n::operator()(S11nNode & dest, QBitArray const & src ) const +{ + typedef s11nlite::node_traits NT; + int count = src.count(); + NT::set( dest, "count", count ); + int pos = 0; + std::ostringstream buf; + while( pos < count ) + { + unsigned long byt = 0; + for( int i = 31; (i >= 0) && (pos<count); --i, ++pos ) + { + int b = src.testBit(pos) ? 1 : 0; + byt |= (b << i); + } + buf << std::hex << byt; + if( pos < count ) buf << ' '; + } + NT::set( dest, "bits", buf.str() ); + return true; +} + +bool QBitArray_s11n::operator()( S11nNode const & src, QBitArray & dest ) const +{ + typedef s11nlite::node_traits NT; + int count = NT::get( src, "count", int(0) ); + QBitArray tmp(count); + if( ! count ) + { + dest = tmp; + return true; + } + std::string sbits( NT::get(src,"bits",std::string()) ); + if( sbits.empty() ) return false; + int pos = 0; + std::istringstream is( sbits ); + while( pos < count ) + { + unsigned long byt = 0; + if( ! is.good() ) + { + qDebug() << "QBitArray_s11n::deserialize: error reading next byte group."; + return false; + } + is >> std::hex >> byt; + for( int i = 31; (i >= 0) && (pos<count); --i, ++pos ) + { + int b = (byt >> i) & 0x1; + tmp.setBit( pos, b ? true : false ); + } + } + dest = tmp; + return true; +} + bool QBrush_s11n::operator()(S11nNode & dest, QBrush const & src ) const { typedef s11nlite::node_traits NT; @@ -225,13 +280,13 @@ return hash; } -unsigned short QByteArray_s11n::compressionThreshold = 100; +unsigned long QByteArray_s11n::compressionThreshold = 100; bool QByteArray_s11n::operator()( S11nNode & dest, QByteArray const & src ) const { if( src.isEmpty() ) return true; typedef s11nlite::node_traits NT; bool zIt = QByteArray_s11n::compressionThreshold - ? ((src.size() > QByteArray_s11n::compressionThreshold) ? true : false) + ? ((((unsigned long)src.size()) > QByteArray_s11n::compressionThreshold) ? true : false) : false; QByteArray b64( QByteArray( zIt ? qCompress(src) @@ -262,6 +317,10 @@ } tmp = QByteArray::fromBase64( tmp ); dest = qUncompress( tmp ); + if( dest.isEmpty() ) + { // try harder to see if these warnings are valid: "qUncompress: Z_DATA_ERROR: Input data is corrupted" + dest = tmp; + } return true; } @@ -488,6 +547,12 @@ NT::set(dest,"miterLimit", int(src.miterLimit()) ); NT::set(dest,"width", src.width() ); // TODO: dashOffset() + dashPattern() + QVector<qreal> dp( src.dashPattern() ); + if( ! dp.empty() ) + { + NT::set(dest,"dashOffset", src.dashOffset() ); + s11n::list::serialize_streamable_list( dest, "dashPattern", dp ); + } return s11n::serialize_subnode( dest, "brush", src.brush() ) && s11n::serialize_subnode( dest, "color", src.color() ) ; @@ -511,6 +576,14 @@ tmp.setJoinStyle( Qt::PenJoinStyle(NT::get(src,"joinStyle", int(tmp.joinStyle())))); tmp.setMiterLimit( NT::get(src,"miterLimit", int(tmp.miterLimit())) ); tmp.setWidth( NT::get(src,"width", tmp.width() ) ); + const S11nNode * ch = s11n::find_child_by_name(src,"dashPattern"); + if( ch ) + { // Reminder: this must come after calling tmp.setStyle() + QVector<qreal> dp; + if( ! s11n::list::deserialize_streamable_list( *ch, dp ) ) return false; + tmp.setDashOffset( NT::get(src,"dashOffset", dest.dashOffset() ) ); + tmp.setDashPattern(dp); + } dest = tmp; return true; } @@ -633,7 +706,7 @@ if( ! s11n::serialize_subnode( dest, "pattern", src.pattern() ) ) return false; NT::set( dest, "syntax", int(src.patternSyntax()) ); NT::set( dest, "case", int(src.caseSensitivity()) ); - NT::set( dest, "min", int(src.caseSensitivity()) ); + NT::set( dest, "min", bool(src.isMinimal()) ); return true; } bool QRegExp_s11n::operator()( S11nNode const & src, QRegExp & dest ) const @@ -950,7 +1023,8 @@ bool QVariant_s11n::canHandle( int t ) { return - (t == QVariant::ByteArray) + (t == QVariant::BitArray) + || (t == QVariant::ByteArray) || (t == QVariant::Brush) || (t == QVariant::Color) || (t == QVariant::Date) @@ -1150,6 +1224,7 @@ switch( vt ) { + CASE_OBJ(BitArray, src.value<QBitArray>() ); CASE_OBJ(Brush, src.value<QBrush>() ); CASE_OBJ(ByteArray, src.toByteArray() ); CASE_PROP(Int,toInt()); @@ -1220,6 +1295,7 @@ switch( vt ) { + CASE_OBJ(BitArray,QBitArray); CASE_OBJ(Brush,QBrush); CASE_OBJ(ByteArray,QByteArray); CASE_OBJ(Color,QColor); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sg...@us...> - 2009-02-21 11:12:08
|
Revision: 261 http://s11n.svn.sourceforge.net/s11n/?rev=261&view=rev Author: sgbeal Date: 2009-02-21 11:12:03 +0000 (Sat, 21 Feb 2009) Log Message: ----------- egg Added Paths: ----------- s11n-qt/src/S11nQt/QBitArray.h Added: s11n-qt/src/S11nQt/QBitArray.h =================================================================== --- s11n-qt/src/S11nQt/QBitArray.h (rev 0) +++ s11n-qt/src/S11nQt/QBitArray.h 2009-02-21 11:12:03 UTC (rev 261) @@ -0,0 +1,30 @@ +#ifndef S11NQT_QBitArray_H_INCLUDED +#define S11NQT_QBitArray_H_INCLUDED 1 +#include <QBitArray> +namespace s11n { namespace qt { + /* + s11n proxy for QBitArray. + + Stores QBitArrays using a relatively space-efficient algorithm + (efficient when compared to most other s11n proxies, anyway). + */ + struct QBitArray_s11n + { + /** Serializes src to dest. */ + bool operator()( S11nNode & dest, QBitArray const & src ) const; + /** + Deserializes dest from src. + + Dest is only modified if this routine succeeds. + */ + bool operator()( S11nNode const & src, QBitArray & dest ) const; + }; + +}} // namespace + +/** register s11n proxy for QBitArray. */ +#define S11N_TYPE QBitArray +#define S11N_TYPE_NAME "QBitArray" +#define S11N_SERIALIZE_FUNCTOR s11n::qt::QBitArray_s11n +#include <s11n.net/s11n/reg_s11n_traits.hpp> +#endif // S11NQT_QBitArray_H_INCLUDED This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sg...@us...> - 2008-11-25 13:41:01
|
Revision: 260 http://s11n.svn.sourceforge.net/s11n/?rev=260&view=rev Author: sgbeal Date: 2008-11-25 13:40:59 +0000 (Tue, 25 Nov 2008) Log Message: ----------- ??? Modified Paths: -------------- c11n/doc/manual/libc11n-manual.odt Modified: c11n/doc/manual/libc11n-manual.odt =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sg...@us...> - 2008-11-25 13:40:32
|
Revision: 259 http://s11n.svn.sourceforge.net/s11n/?rev=259&view=rev Author: sgbeal Date: 2008-11-25 13:40:27 +0000 (Tue, 25 Nov 2008) Log Message: ----------- Minor doc touchups. Modified Paths: -------------- c11n/include/s11n.net/c11n/io/c11n_io.h Modified: c11n/include/s11n.net/c11n/io/c11n_io.h =================================================================== --- c11n/include/s11n.net/c11n/io/c11n_io.h 2008-11-25 13:39:13 UTC (rev 258) +++ c11n/include/s11n.net/c11n/io/c11n_io.h 2008-11-25 13:40:27 UTC (rev 259) @@ -419,7 +419,7 @@ off of the stack and revert back to the previous node. Using only 3 functions, plus a couple routines from the c11n_node API, we can build up trees of nodes in a manner which fits well with many file - parsers (which always parse DOM trees depth-first). + parsers (which always(?) parse DOM trees depth-first). This approach, adopted from libs11n, has proven especially useful in the generation of input parsers which need a generic way to @@ -547,7 +547,6 @@ 0, /*root_node*/ \ 0 /*current_node*/ \ } -extern const c11n_io_tree_builder c11n_io_tree_builder_init; struct c11n_io_handler; @@ -575,11 +574,13 @@ cookie as well as those which do not. */ char const * cookie_string; + /** Saves src to dest using self's output grammar. Returns true on success, false on error. */ bool (*save_node)( struct c11n_io_handler * self, c11n_node const * src, c11n_stream * dest ); + /** Tries to parse src using self's grammar. On success it creates a new tree of c11n_nodes and returns the root node. On error (lots of different @@ -658,9 +659,9 @@ cookie argument. Some formats might support different cookies to turn on/off different options or version modes. It is common for client code to register user-friendly aliases for cookies (e.g. the - cookie "51191011" has the alias "binarish"), so if a factory gets a - cookie it does not recognize it should return some default - implementation. + cookie "51191011" has the alias "compact"), so if a factory gets a + cookie it does not recognize it should assume it is an alias and return + some default implementation. Implementations should return 0 to signal an error (e.g. malloc failure). This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |