00001 // See ../license.txt for license information. 00002 // 00003 // dumpobj.cpp 00004 // 00005 // 21-Jul-2003 phamilton Created 00006 // 00007 00008 #define PERSIST_IN_LIBRARY_SOURCE 00009 00010 #include "dumpobj.hpp" 00011 00012 using namespace ph::persist; 00013 00014 bool dumpobj::start(const std::string &tagname) 00015 /* 00016 The input to start and end is "TAGNAME". The state table for the 00017 tree must start from TAGNAME and work out. 00018 */ 00019 { 00020 // Close off the previous tag (if there is one). 00021 if (!_tagname.empty()) 00022 { 00023 if (_data.empty()) 00024 { 00025 // object ::= 00026 // object-start 00027 // ... 00028 object_start(); 00029 _tabs++; 00030 } 00031 else 00032 data_object(); 00033 } 00034 00035 // and get started for the next tag. 00036 _attrs.clear(); 00037 _tagname = tagname; 00038 _data = ""; 00039 00040 return true; 00041 } 00042 00043 bool dumpobj::end(const std::string &tagname) 00044 { 00045 // close off the current tag (if there is one). 00046 if (_tagname.empty()) 00047 { 00048 /* 00049 object ::= 00050 ... 00051 object-end 00052 */ 00053 // there was no accumulated tagname, just unnest, 00054 _tabs--; 00055 object_end(); 00056 } 00057 else 00058 { 00059 if (_data.empty()) 00060 { 00061 /* 00062 object ::= 00063 object-start 00064 ... 00065 object-end 00066 */ 00067 // the last tag had no data, so the last one was an object. 00068 object_start(); 00069 object_end(); 00070 } 00071 else 00072 data_object(); 00073 } 00074 00075 _attrs.clear(); 00076 _tagname = ""; 00077 _data = ""; 00078 00079 return true; 00080 } 00081 00082 bool dumpobj::attr(const std::string &name, const std::string &value) 00083 { 00084 if (_tagname.empty()) 00085 { 00086 *_console << "bad state detected in attr(). _tagname should not be empty." << std::endl; 00087 return false; 00088 } 00089 if (!_data.empty()) 00090 { 00091 *_console << "bad state detected in attr(). _data should be empty." << std::endl; 00092 return false; 00093 } 00094 // and save this attribute. 00095 _attrs[name] = value; 00096 return true; 00097 } 00098 00099 bool dumpobj::data(const std::string &d) 00100 { 00101 if (!_data.empty()) 00102 { 00103 *_console << "bad state detected in data(). _data should be empty." << std::endl; 00104 return false; 00105 } 00106 // and save this data. 00107 _data = d; 00108 return true; 00109 } 00110 00111 void dumpobj::object_start() 00112 /* 00113 object-start ::= 00114 TAGNAME ["(" attr-list ")"] "{" 00115 00116 attr-list ::= 00117 [attr-pair ([", " attr-pair])*] 00118 00119 attr-pair ::= 00120 name "=" value 00121 */ 00122 { 00123 if (_tagname.empty()) 00124 { 00125 *_console << "bad state detected in object_decl(). _tagname should not be empty." << std::endl; 00126 return; 00127 } 00128 tabs(); 00129 *_stream << _tagname; 00130 if (!_attrs.empty()) 00131 { 00132 *_stream << "("; 00133 // should get to use a std::for_each here somehow. 00134 for (std::map<std::string, std::string>::iterator i=_attrs.begin(); i != _attrs.end(); i++) 00135 { 00136 if (i != _attrs.begin()) 00137 *_stream << ", "; 00138 *_stream << i->first << "=" << i->second; 00139 } 00140 *_stream << ")"; 00141 } 00142 *_stream << " {"; 00143 cr(); 00144 } 00145 00146 void dumpobj::object_end() 00147 /* 00148 object-end ::= 00149 "}" 00150 */ 00151 { 00152 tabs(); 00153 *_stream << "}"; 00154 cr(); 00155 } 00156 00157 void dumpobj::data_object() 00158 /* 00159 data-object ::= 00160 TAGNAME "=" data 00161 */ 00162 { 00163 tabs(); *_stream << _tagname << "=" << _data; cr(); 00164 } 00165 00166 void dumpobj::tabs() 00167 { 00168 for (int i=0; i<_tabs; i++) 00169 *_stream << " "; 00170 } 00171 00172 void dumpobj::cr() 00173 { 00174 *_stream << std::endl; 00175 } 00176