ERAV: Entity Relation Attribute Value:
ERAV.h
Go to the documentation of this file.
00001 // ERAV.h           (C) 2010 adolfo@di-mare.com
00002 
00003 #ifndef   ERAV_h
00004 #define   ERAV_h   // Aboid multiple inclusion
00005 
00006 #include <map>     // these are all the #includes used in the implementation
00007 #include <list>
00008 #include <string>
00009 
00010 #include <cctype>  // isalpha() && isdigit() && tolower()
00011 #include <cstdlib> // atoi()
00012 #include <cstring> // memcmp() && size_t
00013 
00014 /// [E]ntity [R]elation [A]ttribute [V]alue
00015 namespace ERAV { class WORD; class WORD_tuple; class tuple; class parser; }
00016 
00017 #if 0
00018            "erav2xml( L ==> XML )"     "xml2erav( XML ==> L )"
00019 #endif
00020 
00021 // <?xml []...[] ?> <erav> XML </erav>
00022 void erav2xml_enclose( std::string& XML );
00023 
00024 // L<tuple> ==> XML ((append))
00025 #define        NOT_const      // L is NOT const: L gets reordered
00026 void erav2xml( NOT_const std::list<ERAV::tuple>& L, std::string& XML );
00027 
00028 // L<tuple> ==> XML ((append))
00029 void erav2xml( const std::list<ERAV::WORD_tuple>& L , std::string& XML );
00030 
00031 // L<word> ==> W<word> ((append)) || L<string> ==> S<string> ((append))
00032 void erav2xml( const std::list<ERAV::WORD_tuple>& L , ERAV::WORD& W );
00033 
00034 // W<word> ==> XML ((append))
00035 void erav2xml( const ERAV::WORD& W , std::string& XML , bool isWORD=true );
00036 
00037 // S<string> ==> XML ((append))
00038 inline
00039 void erav2xml( const ERAV::WORD& S , std::string& XML , const std::string& );
00040 
00041 // XML ==> [ L<tuple> && W<word> && S<string> ] ((append))
00042 inline void xml2erav(           // throws ERAV::exception on error
00043     const std::string& XML    ,
00044     std::list<ERAV::tuple>& L , // append to current value
00045     ERAV::WORD&             W , // append to current value
00046     ERAV::WORD&             S   // append to current value
00047 );
00048 
00049 // [ L<tuple> && W<word> && S<string> ] ==> XML ((append))
00050 inline void erav2xml(
00051           std::list<ERAV::tuple>& L , // reordered
00052     const ERAV::WORD&             W ,
00053     const ERAV::WORD&             S ,
00054           std::string& XML            // append to current value
00055 ) {
00056     erav2xml( L , XML );
00057     erav2xml( W , XML );
00058     erav2xml( S , XML, std::string() );
00059 //  erav2xml_enclose( XML );
00060 }
00061 
00062 inline void erav_clear(
00063     std::list<ERAV::tuple>& L ,
00064     ERAV::WORD&             W ,
00065     ERAV::WORD&             S
00066 );
00067 
00068 namespace ERAV {
00069     // Load L from FROM skippind duplicates.
00070     void merge_into( std::list<ERAV::tuple>& L, std::list<ERAV::tuple>& FROM );
00071 
00072 class tuple { // tuples in the ERAV data base
00073 public:
00074     int    ID_ENT;       // NOT NULL, -- <K+++> <E> Entity
00075     struct _rel_ {       //           --        <R> Relation
00076         short ID;        // NOT NULL, -- <+K++>
00077         short SUB;       // NOT NULL, -- <++K+>
00078         char  TYPE;      // NOT NULL,
00079     } REL;
00080     int     ATTRIB;      // NOT NULL, -- <+++K>  <A> Attribute
00081     struct _val_ {       // NOT NULL,            <V> Value
00082 #if 0
00083         union {
00084             int    INT;  // (int) or reference into "WORD"
00085             double FLOAT;
00086         //  long   TIME; // 2.1474.83.64.7 == 2^31-1
00087             long   DATE; //   1492-12-31
00088             long   HOUR; // 12:25:37.000
00089         };               // 21.47.48.3647  == 2^31-1
00090 #endif
00091         std::string BLOB;      // binary large object
00092     } VAL;
00093 //  CONSTRAINT [ERAV_KEY] UNIQUE ( ID_ENT,REL_ID,REL_SUB,ATTRIB )};
00094 };
00095 
00096 /// (l<r)==>(-1)   (l==r)==>((0))   (l>r)==>(+1).
00097 int  tplcmp( const ERAV::tuple& l, const ERAV::tuple& r );
00098 /// (l<r) ???.
00099 bool isLess( const ERAV::tuple& l, const ERAV::tuple& r );
00100 // { return ( tplcmp(l,r)<0 ); }
00101 #define USE_isLess
00102 #undef  USE_isLess
00103 
00104 /// (l<r) ???.
00105 inline bool operator<( const ERAV::tuple& l, const ERAV::tuple& r ) {
00106     #ifdef  USE_isLess
00107         return ( isLess(l,r) );
00108     #else
00109         return ( tplcmp(l,r)<0 );
00110     #endif
00111 }
00112 
00113 /// (l==r) ???.
00114 inline bool operator==( const ERAV::tuple& l, const ERAV::tuple& r ) {
00115     #ifdef  USE_isLess
00116         return ( !isLess(l,r) && !isLess(r,l) );
00117     #else
00118         return ( tplcmp(l,r)==0 );
00119     #endif
00120 }
00121 
00122 const int LANG_LEN=2; // "es" "en" etc...
00123 
00124 class WORD_tuple { // referenced by VAL_INT in ERAV_tuple
00125 public:
00126     int  ID_WORD;
00127     std::string DESCR;
00128     char LANG[LANG_LEN];
00129 };
00130 
00131 /// \c map<> ( WORD && STRING ).
00132 class WORD { // WORD[25] == [ ("es","Juan"),("en","John"),... ]
00133     friend void ::erav2xml( const ERAV::WORD& W , std::string& XML , bool );
00134 private:
00135     typedef std::list< std::pair< std::string , std::string > > DESCR;
00136     typedef std::map< int , DESCR > MAP;
00137 private:
00138     MAP m_WORD;
00139 public:
00140     std::string lookUp( int n , const std::string& lang ) const;
00141     bool update( int n , const std::string& lang , const std::string& descr );
00142     void erase( int n );
00143     void toList( std::list<ERAV::WORD_tuple>& L ) const;
00144     bool empty() const { return m_WORD.empty(); }
00145     void clear() { m_WORD.clear(); }
00146 private:
00147     static DESCR::iterator       lFind(       DESCR& L, const std::string& lang );
00148     static DESCR::const_iterator lFind( const DESCR& L, const std::string& lang )
00149     { return lFind( *const_cast<DESCR*>(&L), lang ); }
00150 };
00151 
00152 struct attrib { // valid XML attributes for ERAV records
00153     static const char eREL_TYPE = 'e'; //<entity> && <record>
00154     enum { ATTRIB=0, FIRST=ATTRIB,
00155            DESCR,
00156                ID_ENT, REL_ID,  REL_SUB,   REL_TYPE,
00157                VAL,    ID_WORD, ID_STRING, LANG,
00158            LAST=LANG, NONE
00159 };}; // namespace attrib { }
00160 
00161 struct tag { // valid XML tags for ERAV records
00162     enum { attrib=attrib::ATTRIB, first=attrib,
00163                descr=attrib::DESCR,
00164                head, erav, entity, record, word, string,
00165            last=string, none=attrib::NONE
00166 };}; // namespace tag { }
00167 
00168 class token {
00169 public: //         "<?"     "?>" "</" "/>"     '..'  ".."
00170     enum { ZERO=0, LTQ=512, QGT, LTS, SGT,  ID,  STRING }; // token numbers
00171 private:
00172     friend class parser;
00173     token() : m_token(0), m_line(), m_lexeme() { }
00174 public:
00175 //  token( char ch ) : m_token(ch), m_lexeme() { m_lexeme = ch; };
00176     token( int num ) : m_token(num), m_line(), m_lexeme() { };
00177     void set( int number, const char* yytext, int yyleng, int yyline ) {
00178         m_token = number; m_lexeme.assign(yytext, yyleng); m_line = yyline;
00179         setTagAttrib();
00180     }
00181     int getTag()    const { return m_tag_attrib; }
00182     int getAttrib() const { return m_tag_attrib; }
00183 //  operator int()  const { return m_token; } // avoid ambiguity problems
00184     int num()       const { return m_token; } // return token number
00185     const std::string & lexeme() const { return m_lexeme; }
00186     static const char* name(int tk); // token´s name
00187     bool operator==( int tk ) const { return this->m_token == tk; }
00188 private:
00189     void setTagAttrib();  // set m_tag_attrib
00190     int  m_token;         // ZERO, LTQ ... STRING
00191     int  m_line;
00192     int  m_tag_attrib;    // record tag && attrib code
00193     std::string m_lexeme;
00194 };
00195 
00196 class context {
00197     friend class parser;
00198 private:
00199     context() {}
00200     ~context() { if (prev!=0) { delete prev; } } // recursive delete all
00201 private:
00202     context * prev;
00203     int       REL_ID;
00204 };
00205 
00206 // scanner
00207 int yylex( char const** cursor, char const** yytext, int* yyleng, int* yyline );
00208 
00209 class parser {
00210 public:
00211     parser( const char* XML, std::list<ERAV::tuple> & L,
00212             ERAV::WORD & W, ERAV::WORD & S
00213     ) : token1(), token2(),
00214         deleteXML(false),
00215         m_context(0), m_context_old(0), m_nest_id(0),
00216         m_str_val()
00217     { real_set(XML,L,W,S, false); }
00218     parser( const std::string& XML, std::list<ERAV::tuple> & L,
00219             ERAV::WORD & W, ERAV::WORD & S
00220     ) : token1(), token2(),
00221         deleteXML(false),
00222         m_context(0), m_context_old(0), m_nest_id(0),
00223         m_str_val()
00224     { real_set(XML.c_str(),L,W,S,true); } // makeCopy=true
00225     void set( const char* XML, std::list<ERAV::tuple> & L,
00226               ERAV::WORD & W, ERAV::WORD & S )
00227        { real_set(XML,L,W,S, false); }
00228     void set( const std::string& XML, std::list<ERAV::tuple> & L,
00229               ERAV::WORD & W, ERAV::WORD & S )
00230        { real_set(XML.c_str(), L,W,S,true); }
00231     ~parser();
00232     void parse();
00233 private:
00234     void real_set( const char* XML, std::list<ERAV::tuple> & L,
00235               ERAV::WORD & W, ERAV::WORD & S, bool makeCopy );
00236     void match( int num );
00237     void error( const char* msg ) /* abort(); */;
00238     friend class exception;
00239     #define ID_val const std::string & lexeme
00240         void all();        // all  : head docs;
00241         void head();       // head : "<?" "xml" args "?>"   | /* empty */;
00242 
00243         void docs();       // docs : doc docs               | /* empty */;
00244         void doc();        // doc  : '<' ID args nest;
00245         void nest(ID_val); // nest : "/>" | '>' docs "</" ID '>'
00246 
00247         void args();       // args : arg args               | /* empty */;
00248         void arg();        // arg  : ID ('=' STRING)?
00249     #undef ID_val
00250 private:
00251     void pushContext();   void setAttrib();
00252     void popContext();    void setAttribVal();
00253     void emit();
00254 private:
00255     parser( const parser& ); // forbidden
00256     void operator= ( const parser& ); // forbidden
00257 private:
00258     token * m_lookahead;    // flip~flop between token1 && token2
00259     token   token1, token2; // last && current token
00260 
00261     const char* m_XML;    // yylex() big string input
00262     bool    deleteXML;    // true when m_XML is a copy
00263     const char* m_yytext; // scanner fields
00264     int         m_yyleng;
00265     int         m_yyline;
00266     const char* m_cursor;
00267 
00268     context * m_context;     // pushContext() && popContext()
00269     context * m_context_old; // reuse context structs
00270 
00271     int         m_id;         // current entity id
00272     int         m_nest_id;    // current rel_id for nested records
00273 
00274     int         m_tag;        // current XML tag being processed
00275     int         m_attrib;     // which attrib to set with m_str_val
00276     char        m_rel_type;   // type of m_attrib
00277     std::string m_str_val;    // attribute value
00278     int         m_attrib_ref; // reference in attrib argument
00279 
00280     int         m_id_word;   // current word && string id
00281     bool        m_inWord;    // true <==> <word><descr>
00282     char        m_lang[4];   // word && string language
00283 
00284     std::list<ERAV::tuple> * m_L; // list<> where ERAV records get appended
00285     ERAV::WORD * m_WORD;          // WORD  dictionary
00286     ERAV::WORD * m_STRING;        // STRING dictionary
00287 };
00288 
00289 class exception { // thrown from parser::error()
00290     const char * m_what; // string for last error
00291     friend void ERAV::parser::error( const char* );
00292 public:
00293     exception( const char* w ) throw() : m_what(w) { }
00294 //  exception( const exception & o ) : m_what(o.m_what) { }
00295     const char* what() const throw() { return m_what; }
00296 };
00297 
00298 } // namespace ERAV
00299 
00300 /// (l == r) ???
00301 inline bool operator==( const ERAV::token& l , int r ) {
00302     return l.num() == r;
00303 }
00304 
00305 #if 0
00306 /// (l == r) ???
00307 inline bool operator==( const ERAV::token& l , const ERAV::token& r ) {
00308     return ( l.num()== r.num());
00309 }
00310 #endif
00311 
00312 /// { L.clear(), W.clear(), S.clear(); }
00313 inline void erav_clear(
00314     std::list<ERAV::tuple>& L ,
00315     ERAV::WORD&             W ,
00316     ERAV::WORD&             S
00317 ) {
00318     L.clear(), W.clear(), S.clear();
00319 }
00320 
00321 // XML ==> [ L<tuple> && W<word> && S<string> ] ((append))
00322 inline void xml2erav(           // throws ERAV::exception on error
00323     const std::string& XML    ,
00324     std::list<ERAV::tuple>& L , // append to current value
00325     ERAV::WORD&             W , // append to current value
00326     ERAV::WORD&             S   // append to current value
00327 ) {
00328     #if 1
00329         ERAV::parser P( XML , L , W, S );
00330         P.parse();
00331     #else
00332         try {
00333             ERAV::parser P( XML , L , W, S );
00334             P.parse();
00335         }
00336         catch ( ERAV::exception e ) { /* e.what() describes the error */ }
00337         catch ( ... ) { /* catch all */ }
00338     #endif
00339 }
00340 
00341 inline
00342 void erav2xml( const ERAV::WORD& S , std::string& XML , const std::string& ) {
00343      erav2xml( S , XML , false );
00344 }
00345 
00346 #undef NOT_const
00347 #endif // ERAV_h
00348 
00349 // EOF: ERAV.h
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines