00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _BASE_EXTERNALIZER_
00026 #define _BASE_EXTERNALIZER_
00027
00028 #include <base/base>
00029 #include <base/Externalizable>
00030 #include <base/Referenced>
00031 #include <base/PathName>
00032 #include <base/VFile>
00033 #include <base/Vector>
00034 #include <base/Vector3>
00035 #include <base/Matrix4>
00036 #include <base/Matrix>
00037
00038 #include <base/DOM>
00039
00040 #include <iostream>
00041 #include <list>
00042 #include <stack>
00043
00044
00045
00046
00047
00048
00049
00050 namespace base {
00051
00052
00053
00054
00055
00056 class XS
00057 {
00058 public:
00059 XS(String str)
00060 {
00061 const Int len = str.length();
00062 unicode = new XCh[len+8];
00063 dom::XMLString::transcode(str.c_str(), unicode, len+4);
00064 }
00065
00066 XS(const char *cstr)
00067 {
00068 const Int len = strlen(cstr);
00069 unicode = new XCh[len+8];
00070 dom::XMLString::transcode(cstr, unicode, len+4);
00071 }
00072
00073 XS(const XCh* xstr)
00074 {
00075 unicode = new XCh[dom::XMLString::stringLen(xstr)+4];
00076 dom::XMLString::copyString(unicode, xstr);
00077 }
00078
00079 ~XS() { delete[] unicode; }
00080
00081 operator XCh*() const { return unicode; }
00082
00083 operator String() const
00084 {
00085 char* cstr = dom::XMLString::transcode(unicode);
00086 String str(cstr);
00087 delete[] cstr;
00088 return str;
00089 }
00090
00091 private:
00092 XCh* unicode;
00093 };
00094
00095
00096
00097
00098 class Externalizer : public Object
00099 {
00100 public:
00101 Externalizer(Externalizable::ExternalizationType type, ref<VFile> archive);
00102 Externalizer(Externalizable::ExternalizationType type, std::ios& stream);
00103 virtual ~Externalizer();
00104
00105 virtual String className() const { return String("Externalizer"); }
00106
00107 bool isOutput() const { return isoutput; }
00108 bool isInput() const { return !isOutput(); }
00109 Externalizable::ExternalizationType ioType() { return isOutput()?Externalizable::Output:Externalizable::Input; }
00110
00111
00112
00113 PathName getArchivePath() const { return path; }
00114
00115 void flush();
00116
00117 bool moreInput()
00118 { Assert(isInput()); return bool(input()); }
00119 String readLine();
00120 String readString(SInt maxLength=-1);
00121 void writeLine(const String& line);
00122 void writeString(const String& str);
00123
00124 void writeComment(const String& comment);
00125
00126 static String readLineFromStream(std::istream& istream)
00127 {
00128 char linebuf[1024];
00129 istream.getline(linebuf,1024);
00130 linebuf[1023]=char(0);
00131 return String(linebuf);
00132 }
00133
00134
00135
00136
00137 dom::DOMDocument* doc() { if (!xmlMode) initXMLDoc(); return xmldoc; }
00138 dom::DOMNode* context() { if (!xmlMode) initXMLDoc(); return xmlcontext.top(); }
00139
00140
00141
00142
00143
00144
00145
00146 void setDocumentType(const String& name, const String& publicid, const String& sysid);
00147 dom::DOMElement* createElement(const String& tagname, bool indenting=true);
00148
00149 void pushContext(dom::DOMNode* context) { Assert(xmlMode); xmlcontext.push(context); }
00150 dom::DOMNode* popContext() { Assert(xmlMode); dom::DOMNode* top = xmlcontext.top(); xmlcontext.pop(); return top; }
00151
00152 void appendElement(dom::DOMElement* e) { Assert(xmlMode); if (e != xmlcontext.top()) { xmlcontext.top()->appendChild(e); lastAppendedElem=e;} }
00153 void appendBreak() { Assert(xmlMode); appendText(xmlcontext.top(), newline); }
00154 dom::DOMElement* lastAppendedElement() { Assert(xmlMode); return lastAppendedElem; }
00155 String elementTagName(dom::DOMNode* n) { Assert(xmlMode); return !isElement(n)?String():String(XS(dynamic_cast<dom::DOMElement*>(n)->getTagName())); }
00156
00157 void appendElement(dom::DOMNode* n, const String& tagname, bool indenting=true);
00158 void setElementAttribute(dom::DOMElement* e, const String& attrname, const String& value) { e->setAttribute(XS(attrname),XS(value)); }
00159 void appendProcessingInstruction(dom::DOMNode* n, const String& target, const String& data);
00160 dom::DOMText* createText(const String& text);
00161 void appendText(dom::DOMNode* n, const String& text);
00162 dom::DOMComment* createComment(const String& comment);
00163 void appendComment(dom::DOMNode* n, const String& comment);
00164 dom::DOMCDATASection* createCDATA(const String& text);
00165 void appendCDATA(dom::DOMNode* n, const String& text);
00166 void appendNode(dom::DOMNode* n, dom::DOMNode* n2) { Assert(xmlMode); n->appendChild(n2); }
00167 void appendBreak(dom::DOMNode* n) { Assert(xmlMode); appendText(n, newline); }
00168
00169
00170 dom::DOMElement* getFirstElement(dom::DOMNode* n, const String& tagname, bool required=true);
00171 dom::DOMElement* getFirstChildElement(dom::DOMNode* n, const String& tagname, bool required=true);
00172 dom::DOMElement* getNextSiblingElement(dom::DOMNode* n, const String& tagname, bool required=true);
00173 void removeElement(dom::DOMElement* e);
00174 String getContainedText(dom::DOMNode* n, bool removeIndentation=false);
00175 String getElementAttribute(dom::DOMElement* e, const String& attrname, bool required=true);
00176 String getDefaultedElementAttribute(dom::DOMElement* e, const String& attrname, const String& defaultValue);
00177
00178
00179 static array<String> splitIntoLines(const String& text, bool removeBlankLines=true);
00180 static array<String> splitAtDelimiter(const String& line, char delimiter=',');
00181 static base::Vector stringsToReals(const array<String>& strings, bool acceptUnits = true);
00182 static base::Matrix4 toMatrix4(const String& text);
00183 static String toString(const base::Matrix4& m);
00184 static base::Vector3 toVector3(const String& text, bool acceptUnits = true);
00185 static base::Vector toVector(const String& text, bool commasep=false, bool acceptUnits = true);
00186 static String toString(const base::Vector3& v);
00187 static String toString(const base::Vector& v, bool commasep=false);
00188 static String toString(const base::Matrix& m);
00189 static String toString(Real v, const String& units="m");
00190 static Real toReal(const String& text, bool acceptUnits = true);
00191 static base::Matrix toMatrix(const String& text);
00192 static String removeChar(const String& text, char toRemove);
00193 static bool isNumeric(const String& text);
00194
00195
00196
00197
00198 static const String newline;
00199 static const Int indentSpaces = 2;
00200
00201 protected:
00202 Externalizer(const Externalizer& e)
00203 : xmlMode(e.xmlMode), parser(e.parser),
00204 impl(e.impl), doctype(e.doctype),
00205 xmldoc(e.xmldoc), xmlcontext(e.xmlcontext),
00206 isoutput(e.isoutput), aborted(e.aborted)
00207 {}
00208
00209 std::istream& input() { Assert(isInput()); return *istream; }
00210 std::ostream& output() { Assert(isOutput()); return *ostream; }
00211
00212 bool xmlMode;
00213
00214
00215 static bool xmlInitialized;
00216 static void xmlInitialize();
00217
00218 void initXMLDoc(const String& rootElementName = "");
00219
00220 dom::DOMBuilder* parser;
00221 dom::DOMImplementation *impl;
00222 dom::DOMDocumentType* doctype;
00223 dom::DOMDocument* xmldoc;
00224 std::stack<dom::DOMNode*> xmlcontext;
00225 dom::DOMElement* lastAppendedElem;
00226
00227 dom::DOMDocument* xmlParseDocument();
00228 void xmlWriteDocument(dom::DOMDocument* doc);
00229 void xmlReleaseDocument();
00230 void xmlFormat(dom::DOMNode* n, Int indent);
00231
00232 bool isNewline(dom::DOMNode* n);
00233 bool equals(const XCh* str1, const String& str2);
00234 bool isElement(dom::DOMNode* n) { return n->getNodeType() == dom::DOMNode::ELEMENT_NODE; }
00235 bool isElement(dom::DOMNode* n, const String& tagname);
00236
00237
00238
00239 const static String inputToConstErrorString;
00240 const static String inputDuringOutputErrorString;
00241
00242
00243 void abort(const String& exceptionString);
00244
00245
00246 bool isoutput;
00247 bool aborted;
00248
00249 std::istream* istream;
00250 std::ostream* ostream;
00251 PathName path;
00252
00253 };
00254
00255
00256 }
00257
00258 #endif