From c0c74533aac3ab7898673b1c572103e8ccf1b8ae Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Wed, 23 Feb 2005 11:46:02 +0000
Subject: [PATCH] From Sergei Linev

1. My TXMLEngine does not correctly treat quote symbol ("), which may appear
in comments to any data member.
   I fix this simple problem.

2. Somewhere between ROOT 4.01 and 4.03 algorithm how elements of STL
containers like vector<>,
   set<>, deque<> are stored in TBuffer was changed. Before each element was
stored individually, now they will
   be written simultaniousely by WriteFastArray operation. On binary level
it looks ok, but for xml
   format it brakes compatibility with previous versions. Hopefully, this
will not affect any users.

3. In connection with previous problem I modify TXMLPlayer class to have a
propper support of STL containers
   in external readers. I also add in class description link to example how
TXMLPlayer class can be used.
   This example inludes additional TXmlFile class (differ from ROOT
TXMLFile) which is now also integrates own
   xml parser and does not require libxml2 library.


git-svn-id: http://root.cern.ch/svn/root/trunk@11170 27541ba8-7e3a-0410-8455-c3a389f83636
---
 xml/src/TXMLBuffer.cxx |  4 +-
 xml/src/TXMLEngine.cxx | 32 ++++++++-------
 xml/src/TXMLPlayer.cxx | 90 ++++++++++++++++++++++++++++--------------
 3 files changed, 80 insertions(+), 46 deletions(-)

diff --git a/xml/src/TXMLBuffer.cxx b/xml/src/TXMLBuffer.cxx
index d934dfbef3e..55035c6ee24 100644
--- a/xml/src/TXMLBuffer.cxx
+++ b/xml/src/TXMLBuffer.cxx
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Name:  $:$Id: TXMLBuffer.cxx,v 1.10 2004/12/09 07:22:40 brun Exp $
+// @(#)root/xml:$Name:  $:$Id: TXMLBuffer.cxx,v 1.11 2004/12/09 09:40:05 brun Exp $
 // Author: Sergey Linev, Rene Brun  10.05.2004
 
 /*************************************************************************
@@ -1956,7 +1956,7 @@ void TXMLBuffer::WriteFastArray(const Char_t    *c, Int_t n)
    const Char_t* buf = c;
    if (!usedefault)
      for (int i=0;i<n;i++) {
-        if ((*buf<26)/* || (*buf=='<') || (*buf=='>') */ || (*buf=='\"'))
+        if ((*buf < 27) /* || (*buf=='<') || (*buf=='>')  || (*buf=='\"')*/)
          { usedefault = kTRUE; break; }
         buf++;
      }
diff --git a/xml/src/TXMLEngine.cxx b/xml/src/TXMLEngine.cxx
index f38672eebb6..6bbc5bbb601 100644
--- a/xml/src/TXMLEngine.cxx
+++ b/xml/src/TXMLEngine.cxx
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Name$:$Id$
+// @(#)root/xml:$Name:  $:$Id: TXMLEngine.cxx,v 1.11 2004/12/22 16:50:08 rdm Exp $
 // Author: Sergey Linev  10.05.2004
 
 /*************************************************************************
@@ -9,6 +9,14 @@
  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
  *************************************************************************/
 
+//________________________________________________________________________
+//
+//  This class is used to write and read xml files.
+//  It makes simplified parsing of xml files, but does not required 
+//  any external libraries like libxml2 or other
+//
+//________________________________________________________________________
+
 #include "TXMLEngine.h"
 
 #include "Riostream.h"
@@ -783,6 +791,9 @@ void TXMLEngine::UnpackSpecialCharacters(char* target, const char* source, int s
         } else
         if ((*(source+1)=='a') && (*(source+2)=='m') && (*(source+3)=='p') && (*(source+4)==';')) {
            *target++ = '&'; source+=5; srclen-=5;
+        } else
+        if ((*(source+1)=='q') && (*(source+2)=='u') && (*(source+3)=='o') && (*(source+4)=='t') && (*(source+5)==';')) {
+           *target++ = '\"'; source+=6; srclen-=6;
         } else
          { *target++ = *source++; srclen--; }
       } else { 
@@ -797,28 +808,19 @@ void TXMLEngine::UnpackSpecialCharacters(char* target, const char* source, int s
 void TXMLEngine::OutputValue(char* value, TXMLOutputStream* out)
 {
    if (value==0) return; 
-   char* find = value;
-   while (*find!=0) {
-   if ((*find=='<') || 
-       (*find=='>') || 
-       (*find=='&')) break;
-     find++;
-   }
-   if (*find==0) {
-     out->Write(value);  
-     return;
-   }
    
    char* last = value;
-   find = 0;
-   while ((find=strpbrk(last,"<&>")) !=0 ) {
+   char* find = 0;
+   while ((find=strpbrk(last,"<&>\"")) !=0 ) {
       char symb = *find;
       *find = 0;
       out->Write(last);
       *find = symb;
       last = find+1;
       if (symb=='<') out->Write("&lt;"); else
-      if (symb=='>') out->Write("&gt;"); else out->Write("&amp;");
+      if (symb=='>') out->Write("&gt;"); else 
+      if (symb=='&') out->Write("&amp;"); else 
+                     out->Write("&quot;");  
    }
    if (*last!=0)
      out->Write(last);
diff --git a/xml/src/TXMLPlayer.cxx b/xml/src/TXMLPlayer.cxx
index 478669fdf23..c31f7514675 100644
--- a/xml/src/TXMLPlayer.cxx
+++ b/xml/src/TXMLPlayer.cxx
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Name:  $:$Id: TXMLPlayer.cxx,v 1.5 2004/12/20 17:15:48 brun Exp $
+// @(#)root/xml:$Name:  $:$Id: TXMLPlayer.cxx,v 1.6 2005/01/19 18:30:58 brun Exp $
 // Author: Sergey Linev, Rene Brun  10.05.2004
 
 /*************************************************************************
@@ -40,7 +40,9 @@
 //    }
 // 
 //  3. Copy "streamers.h", "streamers.cxx", "TXmlFile.h", "TXmlFile.cxx" files
-//     to user project and compile them. 
+//     to user project and compile them. TXmlFile class implementation can be taken 
+//     from http://www-linux.gsi.de/~linev/xmlfile.tar.gz
+//
 // TXMLPlayer class generates one function per class, which called class streamer.
 // Name of such function for class TExample will be TExample_streamer.
 //
@@ -58,41 +60,44 @@
 //  - allowed arguments for stl containers are: simple data types, string, object, pointer on object
 //  Any other data member can not be (yet) read from xml file and write to xml file.
 //
-//  If data member of class is private or protected, it can not be accessed via 
-//  member name. Two alternative way is supported. First, if for class member fValue 
-//  exists function GetValue(), it will be used to get value from the class, and if 
-//  exists SetValue(), it will be used to set apropriate data member. Names of setter
-//  and getter methods can be specified in comments filed like:
+// If data member of class is private or protected, it can not be accessed via 
+// member name. Two alternative way is supported. First, if for class member fValue 
+// exists function GetValue(), it will be used to get value from the class, and if 
+// exists SetValue(), it will be used to set apropriate data member. Names of setter
+// and getter methods can be specified in comments filed like:
 //
-//     Int  fValue;   // *OPTION={GetMethod="GetV";SetMethod="SetV"}
+//     int  fValue;   // *OPTION={GetMethod="GetV";SetMethod="SetV"}
 // 
-//  If getter or setter methods does not available, address to data member will be 
-//  calculated as predefined offeset to object start address. In that case generated code 
-//  should be used only on the same platform (OS + compiler), where it was generated.
+// If getter or setter methods does not available, address to data member will be 
+// calculated as predefined offeset to object start address. In that case generated code 
+// should be used only on the same platform (OS + compiler), where it was generated.
 //
-//  Generated streamers resolve inheritance tree for given class. This allows to have
-//  array (or vector) of object pointers on some basic class, while objects of derived 
-//  class(es) are used.
+// Generated streamers resolve inheritance tree for given class. This allows to have
+// array (or vector) of object pointers on some basic class, while objects of derived 
+// class(es) are used.
 //
-//  To access data from xml files, user should use TXmlFile class, which is different from
-//  ROOT TXMLFile, but provides very similar functionality. For example, to read 
-//  object from xml file:
+// To access data from xml files, user should use TXmlFile class, which is different from
+// ROOT TXMLFile, but provides very similar functionality. For example, to read 
+// object from xml file:
 //
 //        TXmlFile file("test.xml");             // open xml file 
 //        file.ls();                             // show list of keys in file
 //        TExample* ex1 = (TExample*) file.Get("ex1", TExample_streamer); // get object 
 //        file.Close(); 
 //
-//  To write object to file: 
+// To write object to file: 
 // 
 //        TXmlFile outfile("test2.xml", "recreate");    // create xml file
 //        TExample* ex1 = new TExample;
 //        outfile.Write(ex1, "ex1", TExample_streamer);   // write object to file
 //        outfile.Close();
 //  
-//  Any bug reports and requests for additional functionality of generated code 
-//  or TXmlFile class are welcome. 
-//  Please contact Sergey Linev, S.Linev@gsi.de
+// Complete example for generating and using of external xml streamers can be taken from
+// http://www-linux.gsi.de/~linev/xmlreader.tar.gz
+//
+// Any bug reports and requests for additional functionality are welcome. 
+//  
+// Sergey Linev, S.Linev@gsi.de
 //
 //________________________________________________________________________
 
@@ -1006,6 +1011,8 @@ bool TXMLPlayer::ProduceSTLstreamer(ostream& fs, TClass* cl, TStreamerSTL* el, B
      
      if (stltyp<0) return false;
    }
+   
+   bool akaarrayaccess = (narg==1) && (argtype[0]<20);
 
    char tabs[30], tabs2[30];
    
@@ -1050,10 +1057,21 @@ bool TXMLPlayer::ProduceSTLstreamer(ostream& fs, TClass* cl, TStreamerSTL* el, B
                  
      if (isstr) {
         fs << tabs2 << "buf.WriteSTLstringData(" << accname << "c_str());" << endl;
-     } else {            
+     } else {   
+        if (akaarrayaccess) {
+           fs << tabs2 << argtname[0] << "* arr = new " << argtname[0] 
+                                      << "[" << accname << "size()];" << endl; 
+           fs << tabs2 << "int k = 0;" << endl;                           
+        }
+              
         fs << tabs2 << contcl->GetName() << "::const_iterator iter;" << endl;
         fs << tabs2 << "for (iter = " << accname << "begin(); iter != " 
                     << accname << "end(); iter++)";
+        if (akaarrayaccess) {
+           fs << endl << tabs2 << tab1 << "arr[k++] = *iter;" << endl;
+           fs << tabs2 << "buf.WriteArray(arr, " << accname << "size(), 0, false);" << endl;
+           fs << tabs2 << "delete[] arr;" << endl;
+        } else            
         if (narg==1) {
            fs << endl << tabs2 << tab1;
            WriteSTLarg(fs, "*iter", argtype[0], isargptr[0], argcl[0]);
@@ -1066,6 +1084,7 @@ bool TXMLPlayer::ProduceSTLstreamer(ostream& fs, TClass* cl, TStreamerSTL* el, B
            WriteSTLarg(fs, "iter->second", argtype[1], isargptr[1], argcl[1]);
            fs << tabs2 << "}" << endl;   
         }
+     
      } // if (isstr)
     
      if (isptr) fs << tabs << "}" << endl;
@@ -1125,23 +1144,36 @@ bool TXMLPlayer::ProduceSTLstreamer(ostream& fs, TClass* cl, TStreamerSTL* el, B
      if (isstr) {
         fs << tabs << "if (size>0) " << accname << "assign(buf.ReadSTLstringData(size));" << endl;  
      } else {
-        fs << tabs << "for(int k=0;k<size;k++) {" << endl;
+        if (akaarrayaccess) {
+           fs << tabs << argtname[0] << "* arr = new " << argtname[0] << "[size];" << endl;
+           fs << tabs << "buf.ReadArray(arr, size, 0, false);" << endl;
+        }
+     
+        fs << tabs << "for(int k=0;k<size;k++)";
+        
+        if (akaarrayaccess) {
+          fs << endl << tabs << tab1 << accname; 
+          if ((stltyp==TClassEdit::kSet) || (stltyp==TClassEdit::kMultiSet))
+            fs << "insert"; else fs << "push_back";  
+          fs << "(arr[k]);" << endl;
+          fs << tabs << "delete[] arr;" << endl;
+        } else
         if (narg==1) {
-          TString arg1("arg"), ifcond;  
-          fs << tabs << tab1;
+          TString arg1("arg"), ifcond;
+          fs << " {" << endl << tabs << tab1;
           ReadSTLarg(fs, arg1, argtype[0], isargptr[0], argcl[0], argtname[0], ifcond);  
           fs << tabs << tab1;
           if (ifcond.Length()>0) fs << "if (" << ifcond << ") ";
           fs << accname;
-          if ((stltyp==TClassEdit::kSet) ||
-              (stltyp==TClassEdit::kMultiSet))
+          if ((stltyp==TClassEdit::kSet) || (stltyp==TClassEdit::kMultiSet))
             fs << "insert"; else fs << "push_back";  
           fs << "(" << arg1 << ");" << endl;
+          fs << tabs << "}" << endl;
         }
         else 
         if (narg==2) {
            TString arg1("arg1"), arg2("arg2"), ifcond;  
-           fs << tabs << tab1;
+           fs << " {" << endl << tabs << tab1;
            ReadSTLarg(fs, arg1, argtype[0], isargptr[0], argcl[0], argtname[0], ifcond);  
            fs << tabs << tab1;
            ReadSTLarg(fs, arg2, argtype[1], isargptr[1], argcl[1], argtname[1], ifcond);
@@ -1149,8 +1181,8 @@ bool TXMLPlayer::ProduceSTLstreamer(ostream& fs, TClass* cl, TStreamerSTL* el, B
            if (ifcond.Length()>0) fs << "if (" << ifcond << ") ";
            fs << accname << "insert(make_pair(" 
               << arg1 << ", " << arg2 << "));" << endl;
+           fs << tabs << "}" << endl;   
         }
-        fs << tabs << "}" << endl;
      }
      
      if (isarr && el->GetArrayLength()) {
-- 
GitLab