DSQSS  1.1
xml.h
説明を見る。
00001 
00002 // Known bugs:
00003 // (1) Tags must be separated from other words by one or more spaces or 
00004 //     line breaks. Otherwise they are not recognized.
00005 // (2) The comment identifiers <!-- and --> must be separated by spaces or
00006 //     line breaks, too. 
00007 
00008 #ifndef XML_H
00009 #define XML_H
00010 
00011 #include "io.h"
00012 #include "array.h"
00013 
00014 namespace XML {
00015 
00016 //#######################################################################
00017 
00018 class Block;
00019 
00020 //======================================================================
00021 
00022 inline bool isCommentOpening(const string& key) {
00023   string sopen = "<!--";
00024   int n = key.length();
00025   if ( n < 4 ) return false;
00026   if ( key.substr(0,4) == sopen ) return true;
00027   return false;
00028 }
00029 
00030 //======================================================================
00031 
00032 inline bool isOpening(const string& key) {
00033   int n = key.length();
00034   if ( key[0] != '<' ) return false;
00035   if ( key[1] == '/' ) return false;
00036   if ( key[n-1] != '>' ) return false;
00037   return true;
00038 }
00039 
00040 //======================================================================
00041 
00042 inline bool isClosing(const string& key) {
00043   int n = key.length();
00044   if ( key[0] != '<' ) return false;
00045   if ( key[1] != '/' ) return false;
00046   if ( key[n-1] != '>' ) return false;
00047   return true;
00048 }
00049 
00050 //======================================================================
00051 
00052 inline const string getOpeningName(const string& key) {
00053   if ( !isOpening(key) ) exit(0);
00054   int n = key.length();
00055   string ans = key.substr(1,n-2);
00056   return ans;
00057 }
00058 
00059 //======================================================================
00060 
00061 inline const string getClosingName(const string& key) {
00062   if ( ! isClosing(key) ) exit(0);
00063   int n = key.length();
00064   string ans = key.substr(2,n-3);
00065   return ans;
00066 }
00067 
00068 //#######################################################################
00069 
00070 class Block {
00071 
00072 private:
00073 
00074   string Name; // the name of the element
00075   string* Word; // the whole list of words to be processed
00076   string Open; // the key at which to start the process
00077   string Close; // the key at which to terminate the process
00078   int NB; // the number of subelements
00079   Array<Block> SubBlock;
00080   int NV; // the number of values
00081   Array<string> Value;
00082 
00083 public:
00084 
00085   void initialize( string* word , const string& name = "" );
00086   void initialize( const string& FNAME , const string& name = "" );
00087 
00088   Block () {
00089     NB = 0; 
00090     NV = 0; 
00091   };
00092 
00093   Block (const string& FNAME, const string& BNAME="") {
00094     NB = 0; 
00095     NV = 0; 
00096     initialize(FNAME, BNAME);
00097   };
00098 
00099   ~Block () {
00100     //    printf("*** Destroying XML::Block (%s)\n", Name.c_str());
00101   };
00102 
00103   const int& NumberOfBlocks() const { return NB; };
00104   const int& NumberOfValues() const { return NV; };
00105   string getJoinedString();
00106   const string& getName() const;
00107   bool syntax_error();
00108   void read();
00109   int getInteger(const int i=0);
00110   double getDouble(const int i=0);
00111   string& getString(const int i=0);
00112   Block& getElement(const int i);
00113   Block& getElement(const string& name);
00114   Block& getElement(
00115     const string& name, const string& idkey, const int id );
00116   Block& operator[] (const int& i) { return SubBlock[i]; };
00117   Block& operator[] (const string& name);
00118   void dump(const string& prompt="");
00119 
00120 };
00121 
00122 //======================================================================
00123 
00124 inline string Block::getJoinedString() {
00125   string s="";
00126   if ( NV == 0 ) return s;
00127   s = Value[0];
00128   for (int i=1; i<NV; i++) {
00129     s += " ";
00130     s += Value[i];
00131   }
00132   return s;
00133 }
00134 
00135 //======================================================================
00136 
00137 inline const string& Block::getName() const { return Name; }
00138 
00139 //======================================================================
00140 
00141 inline void Block::initialize( string* word , const string& name ) {
00142 //        printf("Block::initialize> Pass 1\n");
00143   Name = name;
00144   Word = word;
00145   if ( name == "" ) {
00146     Open = "";
00147     Close = "";
00148   } else {
00149     Open = "<"+name+">";
00150     Close = "</"+name+">";
00151   }
00152   read();
00153 }
00154 
00155 //======================================================================
00156 
00157 void Block::initialize( const string& FNAME , const string& name ) {
00158 //      printf("Block::initialize> Pass 2\n"); // koko
00159 
00160   FileReader F;
00161   F.open(FNAME.c_str());
00162   int NW;
00163   string* W;
00164   F.getWordList( NW , W ); //単語の数、最初の括弧<algorithm>
00165   initialize( W , name );
00166   delete [] W;
00167 }
00168 
00169 //======================================================================
00170 
00171 inline bool Block::syntax_error() {
00172   NB = 0;
00173   NV = 0;
00174   int depth = 0;
00175   bool open = false;
00176   string SkipTo = "";
00177   int i=0;
00178   while(Word[i] != EOL) {
00179     string& w = Word[i++];
00180     if ( Name == "" ) {
00181       if ( isOpening(w) ) {
00182         const string name = getOpeningName(w);
00183         Name = name;
00184         Open = "<"+name+">";
00185         Close = "</"+name+">";
00186       }
00187     }
00188     if ( w == Open ) {
00189       depth++;
00190       open = true;
00191       continue;
00192     }
00193     if ( ! open ) continue;
00194     if ( w == Close ) {
00195       depth--;
00196       break;
00197     }
00198     if ( SkipTo != "" && w != SkipTo ) continue;
00199     if ( SkipTo != "" && w == SkipTo ) {
00200       depth--;
00201       SkipTo = "";
00202       continue;
00203     }
00204     if ( isCommentOpening(w) ) {
00205 //cout << "  ... beginning of a comment" << endl;
00206       depth++;
00207       SkipTo = "-->";
00208       continue;
00209     }
00210     if ( isOpening(w) ) {
00211 //cout << "  ... beginning of a subelement [" << w << "]" << endl;
00212       depth++;
00213       const string name = getOpeningName(w);
00214 //cout << "opening name : " << name << endl;
00215       SkipTo = "</" + name + ">";
00216       NB++;
00217       continue;
00218     }
00219     if ( isClosing(w) ) {
00220       printf("Block::read> Error.\n");
00221       printf("  An unexpected closing tag %s\n", w.c_str());
00222       printf("  is detected in reading an element of name [%s].\n", 
00223         getName().c_str());
00224       return true;
00225     }
00226 //cout << "  ... a value" << endl;
00227     NV++;
00228   }
00229 
00230   if ( depth != 0 ) {
00231     printf("Block::read> Error.\n");
00232     string expected = SkipTo;
00233     if ( expected == "" ) {
00234       expected = Close;
00235     }
00236     printf("  A missing closing tag %s\n", expected.c_str());
00237     printf("  is detected in reading an element of name [%s].\n", 
00238       getName().c_str());
00239     return true;
00240   }
00241 
00242   return false;
00243 
00244 }
00245 
00246 //======================================================================
00247 
00248 void Block::read() {
00249 
00250 //  printf("Block::read> Pass 1\n");
00251   if ( syntax_error() ) exit(0);
00252 
00253   if ( NV > 0 ) Value.init("Value",1,NV);
00254   if ( NB > 0 ) SubBlock.init("SubBlock",1,NB);
00255 
00256   bool open = false;
00257   string SkipTo = "";
00258   int ib = 0;
00259   int iv = 0;
00260   int i=0;
00261   while(true) {
00262     string& w = Word[i++];
00263 //    cout << "### " << w << endl;
00264     if ( w == Open ) {
00265 //printf("Opened. %s\n", w.c_str());
00266       open = true;
00267       continue;
00268     }
00269     if ( ! open ) continue;
00270     if ( w == Close ) break;
00271     if ( SkipTo != "" && w != SkipTo ) continue;
00272     if ( SkipTo != "" && w == SkipTo ) {
00273       SkipTo = "";
00274       continue;
00275     }
00276     if ( isCommentOpening(w) ) {
00277       SkipTo = "-->";
00278       continue;
00279     }
00280     if ( isOpening(w) ) {
00281       const string name = getOpeningName(w);
00282       SubBlock[ib].initialize(&w,name);
00283       ib++;
00284       SkipTo = "</" + name + ">";
00285       continue;
00286     }
00287     Value[iv] = w;
00288     iv++;
00289   }
00290 }
00291 
00292 //======================================================================
00293 
00294 inline string& Block::getString(const int i) {
00295 #ifdef DEB
00296   if ( i < 0 || i >= NV ) {
00297     printf("Block::getString> Error.\n");
00298     printf("  The argument (= %d) is out of the bounds [0,%d).\n", i, NV);
00299     exit(0);
00300   }
00301 #endif
00302   return Value[i];
00303 }
00304 
00305 //======================================================================
00306 
00307 inline int Block::getInteger(const int i) {
00308 #ifdef DEB
00309   if ( i < 0 || i >= NV ) {
00310     printf("Block::getInteger> Error.\n");
00311     printf("  The argument (= %d) is out of the bounds [0,%d).\n", i, NV);
00312     exit(0);
00313   }
00314 #endif
00315   string& s = getString(i);
00316   return atoi(s.c_str());
00317 }
00318 
00319 //======================================================================
00320 
00321 inline double Block::getDouble(const int i) {
00322 #ifdef DEB
00323   if ( i < 0 || i >= NV ) {
00324     printf("Block::getDouble> Error.\n");
00325     printf("  The argument (= %d) is out of the bounds [0,%d).\n", i, NV);
00326     exit(0);
00327   }
00328 #endif
00329   string& s = getString(i);
00330   return (double)atof(s.c_str());
00331 }
00332 
00333 //======================================================================
00334 
00335 inline Block& Block::getElement(const int i) {
00336   return SubBlock[i];
00337 }
00338 
00339 //======================================================================
00340 
00341 inline Block& Block::getElement(const string& name) {
00342   int ib;
00343   for (ib=0; ib<NB; ib++) {
00344     if ( name == SubBlock[ib].getName() ) break;
00345   }
00346   if ( ib < NB ) { 
00347     return SubBlock[ib];
00348   } else {
00349     printf("Block::getElement> Error.\n");
00350     printf("  Tried to find a subblock '%s',\n",
00351       name.c_str());
00352     printf("  but no such block exists in a block '%s'.\n", 
00353       getName().c_str());
00354     exit(0);
00355   }
00356 }
00357 
00358 //======================================================================
00359 
00360 inline Block& Block::getElement(
00361   const string& name, const string& idkey, const int id ) {
00362   int ib;
00363   for (ib=0; ib<NB; ib++) {
00364     if ( name == SubBlock[ib].getName() ) {
00365       Block& E = SubBlock[ib];
00366 //    E.dump();
00367       int id0 = E[idkey].getInteger();
00368 //    printf("id0 = %d, id = %d\n", id0, id);
00369       if ( id0 == id ) break;
00370     }
00371   }
00372   if ( ib < NB ) { 
00373     return SubBlock[ib];
00374   } else {
00375     printf("Block::getElement> Error.\n");
00376     printf("  Tried to find a subblock '%s',\n",
00377       name.c_str());
00378     printf("  but no such block exists in a block '%s'.\n", 
00379       getName().c_str());
00380     exit(0);
00381   }
00382 }
00383 
00384 //======================================================================
00385 
00386 Block& Block::operator[] (const string& name) {
00387   Block& B = getElement(name);
00388   return B;
00389 }
00390 
00391 //======================================================================
00392 
00393 inline void Block::dump(const string& prompt) {
00394   if ( NV == 1 && NB == 0 ) {
00395     printf("%s"     , prompt.c_str());
00396     printf("<%s>"   , Name.c_str());
00397     printf(" %s"    , Value[0].c_str());
00398     printf(" </%s>" , Name.c_str());
00399     printf("\n");
00400   } else {
00401     printf("%s<%s>\n", prompt.c_str(), Name.c_str());
00402     for (int i=0; i<NV; i++) {
00403       printf("%s  (%2d) %s\n", prompt.c_str(), i, Value[i].c_str());
00404     }
00405     for (int i=0; i<NB; i++) {
00406 //    printf("%s  subelement %2d:\n", prompt.c_str(), i);
00407       SubBlock[i].dump(prompt+"  ");
00408     }
00409     printf("%s</%s>\n", prompt.c_str(), Name.c_str());
00410   }
00411 }
00412 
00413 //#######################################################################
00414 
00415 } // 先頭の namespace XML { と対になる } .
00416 
00417 #endif
 全て クラス ネームスペース ファイル 関数 変数 型定義 列挙型の値 フレンド マクロ定義