Vault  4.1
vbento.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved.
00003 This file is part of the Code Vault version 4.1
00004 http://www.bombaydigital.com/
00005 License: MIT. See LICENSE.md in the Vault top level directory.
00006 */
00007 
00010 #include "vbento.h"
00011 #include "vtypes_internal.h"
00012 
00013 #include "vexception.h"
00014 #include "vbufferedfilestream.h"
00015 
00016 // VBentoTextParser ----------------------------------------------------------
00017 
00022 class VBentoTextNodeParser {
00023     public:
00024 
00025         VBentoTextNodeParser();
00026         ~VBentoTextNodeParser() {}
00027 
00028         void parse(VTextIOStream& stream, VBentoNode& buildNode);
00029         void parse(const VString& s, VBentoNode& buildNode);
00030 
00031     private:
00032 
00033         typedef enum {
00034             START,
00035             IN_NODE,
00036             IN_NODE_NAME,
00037             IN_ATTRIBUTE,
00038             IN_ATTRIBUTE_NAME,
00039             IN_ATTRIBUTE_TYPE,
00040             IN_ATTRIBUTE_PRE_VALUE,
00041             IN_ATTRIBUTE_PRE_VALUE_QUALIFIER,
00042             IN_ATTRIBUTE_VALUE_DOUBLE_QUOTED,
00043             IN_ATTRIBUTE_VALUE_SINGLE_QUOTED,
00044             IN_ATTRIBUTE_VALUE_UNQUOTED
00045 
00046         } TokenState;
00047 
00048         void _parseCharacter(const VCodePoint& c);
00049 
00050         TokenState mTokenState;
00051         VString mPendingToken;
00052         bool mTokenEscapePending;
00053         VBentoNode* mRootNode;
00054         VBentoNode* mPendingNode;
00055         VBentoNodePtrVector mParseNodeStack;
00056         VString mPendingAttributeName;
00057         VString mPendingAttributeType;
00058         VString mPendingAttributeQualifier;
00059         VString mPendingAttributeValue;
00060 
00061         VBentoTextNodeParser(const VBentoTextNodeParser&); // not copyable
00062         VBentoTextNodeParser& operator=(const VBentoTextNodeParser&); // not assignable
00063 };
00064 
00065 VBentoTextNodeParser::VBentoTextNodeParser()
00066     : mTokenState(START)
00067     , mPendingToken()
00068     , mTokenEscapePending(false)
00069     , mRootNode(NULL)
00070     , mPendingNode(NULL)
00071     , mParseNodeStack()
00072     , mPendingAttributeName()
00073     , mPendingAttributeType()
00074     , mPendingAttributeValue()
00075     {
00076 }
00077 
00078 void VBentoTextNodeParser::parse(VTextIOStream& stream, VBentoNode& node) {
00079     mRootNode = &node;
00080 
00081     try {
00082         for (;;) {
00083             VCodePoint c = stream.readUTF8CodePoint();
00084             this->_parseCharacter(c);
00085         }
00086     } catch (const VEOFException& /*ex*/) { // normal EOF on input stream simply ends parsing
00087     } catch (const VException& ex) {
00088         throw VException(VSTRING_FORMAT("The Bento text stream was incorrectly formatted: %s", ex.what()));
00089     }
00090 }
00091 
00092 void VBentoTextNodeParser::parse(const VString& s, VBentoNode& node) {
00093     mRootNode = &node;
00094 
00095     try {
00096         for (VString::const_iterator i = s.begin(); i != s.end(); ++i) {
00097             this->_parseCharacter(*i);
00098         }
00099     } catch (const VEOFException& /*ex*/) { // normal EOF on input stream simply ends parsing
00100     } catch (const VException& ex) {
00101         throw VException(VSTRING_FORMAT("The Bento text stream was incorrectly formatted: %s", ex.what()));
00102     }
00103 }
00104 
00105 static bool _isSkippable(const VCodePoint& c) {
00106     return (c.intValue() <= 0x20) || (c.intValue() == 0x7F);
00107 }
00108 
00109 void VBentoTextNodeParser::_parseCharacter(const VCodePoint& c) {
00110     switch (mTokenState) {
00111         case START:
00112             if (_isSkippable(c)) {
00113                 // nothing
00114             } else if (c == '{') {
00115                 mTokenState = IN_NODE;
00116                 mPendingNode = mRootNode;
00117                 mParseNodeStack.push_back(mPendingNode);
00118             } else {
00119                 throw VException(VSTRING_FORMAT("Parser expected whitespace or { but got '%s'.", c.toString().chars()));
00120             }
00121             break;
00122         case IN_NODE:
00123             if (_isSkippable(c)) {
00124                 // nothing
00125             } else if (c == '\"') {
00126                 mTokenState = IN_NODE_NAME;
00127             } else if (c == '[') {
00128                 mTokenState = IN_ATTRIBUTE;
00129                 mPendingAttributeName = VString::EMPTY();
00130                 mPendingAttributeType = VString::EMPTY();
00131                 mPendingAttributeQualifier = VString::EMPTY();
00132                 mPendingAttributeValue = VString::EMPTY();
00133             } else if (c == '{') {
00134                 mTokenState = IN_NODE;
00135                 VBentoNode* child = new VBentoNode();
00136                 mPendingNode->addChildNode(child);
00137                 mPendingNode = child;
00138                 mParseNodeStack.push_back(child);
00139             } else if (c == '}') {
00140                 mTokenState = IN_NODE;
00141                 mParseNodeStack.pop_back(); // pop the last node
00142                 if (mParseNodeStack.size() == 0)
00143                     mPendingNode = NULL; // we're back at top level outside all nodes
00144                 else
00145                     mPendingNode = mParseNodeStack.back(); // the new last node is now pending
00146             } else {
00147                 throw VException(VSTRING_FORMAT("Parser expected whitespace, node name, [, {, or } but got '%s'.", c.toString().chars()));
00148             }
00149             break;
00150         case IN_NODE_NAME:
00151             if (c == '\\') { // backslash (escape) char
00152                 if (mTokenEscapePending) {
00153                     mPendingToken += c;
00154                     mTokenEscapePending = false;
00155                 } else {
00156                     mTokenEscapePending = true;
00157                 }
00158             } else if (c == '\"') { // double-quote char
00159                 if (mTokenEscapePending) {
00160                     mPendingToken += c;
00161                     mTokenEscapePending = false;
00162                 } else {
00163                     mPendingNode->setName(mPendingToken);
00164                     mPendingToken = VString::EMPTY();
00165                     mTokenState = IN_NODE;
00166                 }
00167             } else {
00168                 mPendingToken += c;
00169                 mTokenEscapePending = false;
00170             }
00171             break;
00172         case IN_ATTRIBUTE:
00173             if (_isSkippable(c)) {
00174                 // nothing
00175             } else if (c == '\"') {
00176                 mTokenState = IN_ATTRIBUTE_NAME;
00177             } else if (c == '(') {
00178                 mTokenState = IN_ATTRIBUTE_TYPE;
00179             } else if (c == '=') {
00180                 mTokenState = IN_ATTRIBUTE_PRE_VALUE;
00181             } else if (c == ']') {
00182                 mTokenState = IN_NODE;
00183 
00184                 mPendingNode->_addAttribute(VBentoAttribute::newObjectFromBentoTextValues(mPendingAttributeName, mPendingAttributeType, mPendingAttributeValue, mPendingAttributeQualifier));
00185 
00186                 mPendingAttributeName = VString::EMPTY();
00187                 mPendingAttributeType = VString::EMPTY();
00188                 mPendingAttributeQualifier = VString::EMPTY();
00189                 mPendingAttributeValue = VString::EMPTY();
00190             } else {
00191                 throw VException(VSTRING_FORMAT("Parser expected whitespace, attr name/type/value, or ] but got '%s'.", c.toString().chars()));
00192             }
00193             break;
00194         case IN_ATTRIBUTE_NAME:
00195             if (c == '\\') { // backslash (escape) char
00196                 if (mTokenEscapePending) {
00197                     mPendingToken += c;
00198                     mTokenEscapePending = false;
00199                 } else {
00200                     mTokenEscapePending = true;
00201                 }
00202             } else if (c == '\"') { // double-quote char
00203                 if (mTokenEscapePending) {
00204                     mPendingToken += c;
00205                     mTokenEscapePending = false;
00206                 } else {
00207                     mPendingAttributeName = mPendingToken;
00208                     mPendingToken = VString::EMPTY();
00209                     mTokenState = IN_ATTRIBUTE;
00210                 }
00211             } else {
00212                 mPendingToken += c;
00213                 mTokenEscapePending = false;
00214             }
00215             break;
00216         case IN_ATTRIBUTE_TYPE:
00217             if (c == ')') {
00218                 mPendingAttributeType = mPendingToken;
00219                 mPendingToken = VString::EMPTY();
00220                 mTokenState = IN_ATTRIBUTE;
00221             } else {
00222                 mPendingToken += c;
00223             }
00224             break;
00225         case IN_ATTRIBUTE_PRE_VALUE:
00226             if (c == '(') {
00227                 mTokenState = IN_ATTRIBUTE_PRE_VALUE_QUALIFIER;
00228             } else if (c == '\\') { // backslash (escape) char
00229                 mTokenEscapePending = true;
00230                 mTokenState = IN_ATTRIBUTE_VALUE_UNQUOTED;
00231             } else if (c == '\"') { // double-quote char
00232                 if (mTokenEscapePending) {
00233                     mPendingToken += c;
00234                     mTokenEscapePending = false;
00235                 } else {
00236                     mPendingToken += c;
00237                     mTokenState = IN_ATTRIBUTE_VALUE_DOUBLE_QUOTED;
00238                 }
00239             } else if (c == '\'') { // single-quote char
00240                 if (mTokenEscapePending) {
00241                     mPendingToken += c;
00242                     mTokenEscapePending = false;
00243                 } else {
00244                     mPendingToken += c;
00245                     mTokenState = IN_ATTRIBUTE_VALUE_SINGLE_QUOTED;
00246                 }
00247             } else {
00248                 mPendingToken += c;
00249                 mTokenState = IN_ATTRIBUTE_VALUE_UNQUOTED;
00250                 mTokenEscapePending = false;
00251             }
00252             break;
00253         case IN_ATTRIBUTE_PRE_VALUE_QUALIFIER:
00254             if (c == ')') {
00255                 mPendingAttributeQualifier = mPendingToken;
00256                 mPendingToken = VString::EMPTY();
00257                 mTokenState = IN_ATTRIBUTE_PRE_VALUE;
00258             } else {
00259                 mPendingToken += c;
00260             }
00261             break;
00262         case IN_ATTRIBUTE_VALUE_DOUBLE_QUOTED:
00263         case IN_ATTRIBUTE_VALUE_SINGLE_QUOTED:
00264             if (c == '\\') { // backslash (escape) char
00265                 if (mTokenEscapePending) {
00266                     mPendingToken += c;
00267                     mTokenEscapePending = false;
00268                 } else {
00269                     mTokenEscapePending = true;
00270                 }
00271             } else if (((c == '\"') && (mTokenState == IN_ATTRIBUTE_VALUE_DOUBLE_QUOTED)) || // matched double-quote char
00272                        ((c == '\'') && (mTokenState == IN_ATTRIBUTE_VALUE_SINGLE_QUOTED))) {   // matched single-quote char
00273                 if (mTokenEscapePending) {
00274                     mPendingToken += c;
00275                     mTokenEscapePending = false;
00276                 } else {
00277                     mPendingToken += c;
00278                     mPendingAttributeValue = mPendingToken;
00279                     mPendingToken = VString::EMPTY();
00280                     mTokenState = IN_ATTRIBUTE;
00281                 }
00282             } else {
00283                 mPendingToken += c;
00284                 mTokenEscapePending = false;
00285             }
00286             break;
00287         case IN_ATTRIBUTE_VALUE_UNQUOTED:
00288             if (c == '\\') { // backslash (escape) char
00289                 if (mTokenEscapePending) {
00290                     mPendingToken += c;
00291                     mTokenEscapePending = false;
00292                 } else {
00293                     mTokenEscapePending = true;
00294                 }
00295             } else if (_isSkippable(c)) { // whitespace of some kind (a space or any lower unprintable character like CR, LF, tab, ...)
00296                 if (mTokenEscapePending) {
00297                     mPendingToken += c;
00298                     mTokenEscapePending = false;
00299                 } else {
00300                     mPendingAttributeValue = mPendingToken;
00301                     mPendingToken = VString::EMPTY();
00302                     mTokenState = IN_ATTRIBUTE;
00303                 }
00304             } else if (c == ']') { // end of attribute (unless an escape is pending)
00305                 if (mTokenEscapePending) {
00306                     mPendingToken += c;
00307                     mTokenEscapePending = false;
00308                 } else {
00309                     mPendingAttributeValue = mPendingToken;
00310                     mPendingToken = VString::EMPTY();
00311                     mTokenState = IN_NODE;
00312 
00313                     mPendingNode->_addAttribute(VBentoAttribute::newObjectFromBentoTextValues(mPendingAttributeName, mPendingAttributeType, mPendingAttributeValue, mPendingAttributeQualifier));
00314 
00315                     mPendingAttributeName = VString::EMPTY();
00316                     mPendingAttributeType = VString::EMPTY();
00317                     mPendingAttributeQualifier = VString::EMPTY();
00318                     mPendingAttributeValue = VString::EMPTY();
00319                 }
00320             } else {
00321                 mPendingToken += c;
00322                 mTokenEscapePending = false;
00323             }
00324             break;
00325         default:
00326             break;
00327     }
00328 }
00329 
00330 // VBentoAttribute -----------------------------------------------------------
00331 
00332 VBentoAttribute::VBentoAttribute()
00333     : mName("uninitialized")
00334     , mDataType(VString::EMPTY())
00335     {
00336 }
00337 
00338 VBentoAttribute::VBentoAttribute(VBinaryIOStream& stream, const VString& dataType)
00339     : mName(VString::EMPTY())
00340     , mDataType(dataType)
00341     {
00342     stream.readString(mName);
00343 }
00344 
00345 VBentoAttribute::VBentoAttribute(const VString& name, const VString& dataType)
00346     : mName(name)
00347     , mDataType(dataType)
00348     {
00349 }
00350 
00351 VBentoAttribute::~VBentoAttribute() {
00352 }
00353 
00354 const VString& VBentoAttribute::getName() const {
00355     return mName;
00356 }
00357 
00358 const VString& VBentoAttribute::getDataType() const {
00359     return mDataType;
00360 }
00361 
00362 Vs64 VBentoAttribute::calculateContentSize() const {
00363     Vs64 lengthOfType = 4;
00364     Vs64 lengthOfName = VBentoNode::_getBinaryStringLength(mName);
00365     Vs64 lengthOfData = this->getDataLength();
00366 
00367     return lengthOfType + lengthOfName + lengthOfData;
00368 }
00369 
00370 Vs64 VBentoAttribute::calculateTotalSize() const {
00371     Vs64 contentSize = this->calculateContentSize();
00372     Vs64 lengthOfLength = VBentoNode::_getLengthOfLength(contentSize);
00373 
00374     return lengthOfLength + contentSize;
00375 }
00376 
00377 void VBentoAttribute::writeToStream(VBinaryIOStream& stream) const {
00378     Vs64 contentSize = this->calculateContentSize();
00379 
00380     VBentoNode::_writeLengthToStream(stream, contentSize);
00381     VBentoNode::_writeFourCharCodeToStream(stream, mDataType);
00382     stream.writeString(mName);
00383 
00384     this->writeDataToBinaryStream(stream);
00385 }
00386 
00387 static void _escapeString(VString& s) {
00388     // Insert a backslash in front of any special character.
00389     for (int i = 0; i < s.length(); ++i) {
00390         char c = s[i];
00391         if ((c == '\\') ||
00392             (c == '{') ||
00393             (c == '}') ||
00394             (c == '"') ||
00395             (c == '\'')) {
00396             s.insert('\\', i);
00397             ++i;
00398         }
00399     }
00400 }
00401 
00402 static void _unescapeString(VString& s) {
00403     // Remove any backslash that precedes a special character.
00404     s.replace("\\'", "\'");
00405     s.replace("\\\"", "\"");
00406     s.replace("\\}", "}");
00407     s.replace("\\{", "{");
00408     s.replace("\\\\", "\\");
00409 }
00410 
00411 void VBentoAttribute::writeToBentoTextStream(VTextIOStream& stream) const {
00412     VString name(mName);
00413     _escapeString(name);
00414     VString valueString;
00415     this->getValueAsBentoTextString(valueString);
00416 
00417     // The less-used types must self-describe their type in text form.
00418     // But String, bool, and vs32 are most common and we can infer them
00419     // from how we format them, so we can have a cleaner format for them.
00420     // - string are "quoted"
00421     // - char are 'quoted'
00422     // - vs32 (int) are unquoted and are numeric (a leading minus sign is OK)
00423     // - bool are unquoted true or false
00424     // - every other type has a (type) before the equal sign and is quoted.
00425     // Examples:
00426     // - A string:           "address"="123 Main St."
00427     // - An encoded string:  "address"=(US-ASCII)"123 Main St."
00428     // - A char:             "initial"='X'
00429     // - An integer:         "speed"=70
00430     // - A boolean:          "active"=true
00431     // - A 16-bit unsigned:  "message_id"(vu16)="7"
00432     // - A 64-bit signed:    "file_size(vs64)"="2723674238"
00433     // - A VISize:           "dim(sizi)"="25,30"
00434     // - A VPoint:           "location(pt_d)"="25.387,30.702"
00435     // - A VPoint3D:         "location(pt3d)"="25.387,30.702,37.252"
00436     // - A VLine:            "track(line)"="32.775,26.539:42.383,29.373"
00437     // - A VRect:            "bounds(recd)"="32.775,26.539:100.0*100.0"
00438     // - A VIPolygon:        "outline(poli)"="(24,30)(40,42)(56,30)"
00439     // - A VColor:           "shading(rgba)"="127,64,200,255"
00440     // - Binary data:        "thing(bina)"="0x165231FCE64546DE45AD" (0x is optional)
00441     if (mDataType == VBentoString::DATA_TYPE_ID()) {
00442         _escapeString(valueString);
00443         const VBentoString* thisString = static_cast<const VBentoString*>(this); // already type-checked above, no need to dynamic cast
00444         const VString& encoding = thisString->getEncoding();
00445         if (encoding.isEmpty()) {
00446             stream.writeString(VSTRING_FORMAT("[\"%s\"=\"%s\"]", name.chars(), valueString.chars()));
00447         } else {
00448             stream.writeString(VSTRING_FORMAT("[\"%s\"=(%s)\"%s\"]", name.chars(), encoding.chars(), valueString.chars()));
00449         }
00450     } else if (mDataType == VBentoChar::DATA_TYPE_ID()) {
00451         _escapeString(valueString);
00452         stream.writeString(VSTRING_FORMAT("[\"%s\"='%s']", name.chars(), valueString.chars()));
00453     } else if ((mDataType == VBentoS32::DATA_TYPE_ID()) || (mDataType == VBentoBool::DATA_TYPE_ID())) {
00454         stream.writeString(VSTRING_FORMAT("[\"%s\"=%s]", name.chars(), valueString.chars()));
00455     } else if (mDataType == VBentoStringArray::DATA_TYPE_ID()) {
00456         VString dataType(mDataType);
00457         _escapeString(dataType);
00458         // Single-quote but do not escape the value string. It contains double-quoted, escaped elements.
00459         stream.writeString(VSTRING_FORMAT("[\"%s\"(%s)='%s']", name.chars(), dataType.chars(), valueString.chars()));
00460     } else {
00461         VString dataType(mDataType);
00462         _escapeString(dataType);
00463         _escapeString(valueString);
00464         stream.writeString(VSTRING_FORMAT("[\"%s\"(%s)=\"%s\"]", name.chars(), dataType.chars(), valueString.chars()));
00465     }
00466 }
00467 
00468 static const VString XML_NAME_VALUE_SEPARATOR("=\"");
00469 static const VString XML_VALUE_TERMINATOR("\"");
00470 
00471 void VBentoAttribute::writeToXMLTextStream(VTextIOStream& stream, bool /*lineWrap*/, int /*indentDepth*/) const {
00472     if (! this->xmlAppearsAsArray()) {
00473         // Simple attributes do not use line wrap nor indent. They appear inline in the node's tag.
00474         stream.writeString(mName);
00475         stream.writeString(XML_NAME_VALUE_SEPARATOR);
00476         VString xmlText;
00477         this->getValueAsXMLText(xmlText);
00478         stream.writeString(xmlText);
00479         stream.writeString(XML_VALUE_TERMINATOR);
00480     }
00481 }
00482 
00483 void VBentoAttribute::printHexDump(VHex& hexDump) const {
00484     VMemoryStream buffer;
00485     VBinaryIOStream stream(buffer);
00486 
00487     this->writeToStream(stream);
00488 
00489     hexDump.printHex(buffer.getBuffer(), buffer.getEOFOffset());
00490 }
00491 
00492 VBentoAttribute* VBentoAttribute::newObjectFromStream(VBinaryIOStream& stream) {
00493     Vs64    theDataLength = VBentoNode::_readLengthFromStream(stream);
00494     VString    theDataType;
00495 
00496     VBentoNode::_readFourCharCodeFromStream(stream, theDataType);
00497 
00498     // Put the most used and preferred types first for efficiency.
00499     if (theDataType == VBentoS32::DATA_TYPE_ID())
00500         return new VBentoS32(stream);
00501     else if (theDataType == VBentoString::DATA_TYPE_ID())
00502         return new VBentoString(stream);
00503     else if (theDataType == VBentoBool::DATA_TYPE_ID())
00504         return new VBentoBool(stream);
00505     else if (theDataType == VBentoChar::DATA_TYPE_ID())
00506         return new VBentoChar(stream);
00507     else if (theDataType == VBentoChar::LEGACY_DATA_TYPE_ID())
00508         return VBentoChar::newFromLegacyCharStream(stream);
00509     else if (theDataType == VBentoS64::DATA_TYPE_ID())
00510         return new VBentoS64(stream);
00511     else if (theDataType == VBentoDouble::DATA_TYPE_ID())
00512         return new VBentoDouble(stream);
00513     else if (theDataType == VBentoDuration::DATA_TYPE_ID())
00514         return new VBentoDuration(stream);
00515     else if (theDataType == VBentoInstant::DATA_TYPE_ID())
00516         return new VBentoInstant(stream);
00517     // Now the less used or less preferred types in order of definition.
00518     else if (theDataType == VBentoS8::DATA_TYPE_ID())
00519         return new VBentoS8(stream);
00520     else if (theDataType == VBentoU8::DATA_TYPE_ID())
00521         return new VBentoU8(stream);
00522     else if (theDataType == VBentoS16::DATA_TYPE_ID())
00523         return new VBentoS16(stream);
00524     else if (theDataType == VBentoU16::DATA_TYPE_ID())
00525         return new VBentoU16(stream);
00526     else if (theDataType == VBentoU32::DATA_TYPE_ID())
00527         return new VBentoU32(stream);
00528     else if (theDataType == VBentoU64::DATA_TYPE_ID())
00529         return new VBentoU64(stream);
00530     else if (theDataType == VBentoFloat::DATA_TYPE_ID())
00531         return new VBentoFloat(stream);
00532     else if (theDataType == VBentoSize::DATA_TYPE_ID())
00533         return new VBentoSize(stream);
00534     else if (theDataType == VBentoISize::DATA_TYPE_ID())
00535         return new VBentoISize(stream);
00536     else if (theDataType == VBentoPoint::DATA_TYPE_ID())
00537         return new VBentoPoint(stream);
00538     else if (theDataType == VBentoIPoint::DATA_TYPE_ID())
00539         return new VBentoIPoint(stream);
00540     else if (theDataType == VBentoPoint3D::DATA_TYPE_ID())
00541         return new VBentoPoint3D(stream);
00542     else if (theDataType == VBentoIPoint3D::DATA_TYPE_ID())
00543         return new VBentoIPoint3D(stream);
00544     else if (theDataType == VBentoLine::DATA_TYPE_ID())
00545         return new VBentoLine(stream);
00546     else if (theDataType == VBentoILine::DATA_TYPE_ID())
00547         return new VBentoILine(stream);
00548     else if (theDataType == VBentoRect::DATA_TYPE_ID())
00549         return new VBentoRect(stream);
00550     else if (theDataType == VBentoIRect::DATA_TYPE_ID())
00551         return new VBentoIRect(stream);
00552     else if (theDataType == VBentoPolygon::DATA_TYPE_ID())
00553         return new VBentoPolygon(stream);
00554     else if (theDataType == VBentoIPolygon::DATA_TYPE_ID())
00555         return new VBentoIPolygon(stream);
00556     else if (theDataType == VBentoColor::DATA_TYPE_ID())
00557         return new VBentoColor(stream);
00558     else if (theDataType == VBentoBinary::DATA_TYPE_ID())
00559         return new VBentoBinary(stream);
00560     else if (theDataType == VBentoS8Array::DATA_TYPE_ID())
00561         return new VBentoS8Array(stream);
00562     else if (theDataType == VBentoS16Array::DATA_TYPE_ID())
00563         return new VBentoS16Array(stream);
00564     else if (theDataType == VBentoS32Array::DATA_TYPE_ID())
00565         return new VBentoS32Array(stream);
00566     else if (theDataType == VBentoS64Array::DATA_TYPE_ID())
00567         return new VBentoS64Array(stream);
00568     else if (theDataType == VBentoStringArray::DATA_TYPE_ID())
00569         return new VBentoStringArray(stream);
00570     else if (theDataType == VBentoBoolArray::DATA_TYPE_ID())
00571         return new VBentoBoolArray(stream);
00572     else if (theDataType == VBentoDoubleArray::DATA_TYPE_ID())
00573         return new VBentoDoubleArray(stream);
00574     else if (theDataType == VBentoDurationArray::DATA_TYPE_ID())
00575         return new VBentoDurationArray(stream);
00576     else if (theDataType == VBentoInstantArray::DATA_TYPE_ID())
00577         return new VBentoInstantArray(stream);
00578     else
00579         return new VBentoUnknownValue(stream, theDataLength, theDataType);
00580 }
00581 
00582 VBentoAttribute* VBentoAttribute::newObjectFromStream(VTextIOStream& /*stream*/) {
00583     // Reading unknown data types from a text stream is not (yet) supported.
00584     return new VBentoUnknownValue();
00585 }
00586 
00587 VBentoAttribute* VBentoAttribute::newObjectFromBentoTextValues(const VString& attributeName, const VString& attributeType, const VString& attributeValue, const VString& attributeQualifier) {
00588     // First we have to determine the data type. If it is supplied,
00589     // it is wrapped in parentheses, so we just strip them. If it
00590     // is not supplied we must infer the type from the format of
00591     // the value. We support:
00592     //   numeric value strings imply int (leading minus sign is allowed)
00593     //   "quoted" value strings imply string
00594     //     - optional encoding name in parens before quoted string, for example: (US-ASCII)"foo"
00595     //   'quoted' value strings imply UTF-8 code point; legacy values may contain any byte value (we check and upgrade bad char to Unicode if needed)
00596     //   true or false value strings imply bool
00597     //   NOW, PAST, FUTURE, NEVER value strings imply instant
00598     VBentoAttribute* result = NULL;
00599     VString actualValue = attributeValue;
00600 
00601     if (! attributeType.isEmpty()) {
00602         if (actualValue.startsWith('\"') || actualValue.startsWith('\'')) {
00603             actualValue.substringInPlace(1, actualValue.length() - 1);
00604 
00605             if (attributeType != VBentoStringArray::DATA_TYPE_ID()) { // A string array's elements are themselves escaped, and will be parsed individually.
00606                 _unescapeString(actualValue);
00607             }
00608         }
00609 
00610         if (attributeType == VBentoS8::DATA_TYPE_ID())
00611             result = new VBentoS8(attributeName, static_cast<Vs8>(actualValue.parseS64()));
00612         else if (attributeType == VBentoU8::DATA_TYPE_ID())
00613             result = new VBentoU8(attributeName, static_cast<Vu8>(actualValue.parseU64()));
00614         else if (attributeType == VBentoS16::DATA_TYPE_ID())
00615             result = new VBentoS16(attributeName, static_cast<Vs16>(actualValue.parseS64()));
00616         else if (attributeType == VBentoU16::DATA_TYPE_ID())
00617             result = new VBentoU16(attributeName, static_cast<Vu16>(actualValue.parseU64()));
00618         else if (attributeType == VBentoS32::DATA_TYPE_ID())
00619             result = new VBentoS32(attributeName, static_cast<Vs32>(actualValue.parseS64()));
00620         else if (attributeType == VBentoU32::DATA_TYPE_ID())
00621             result = new VBentoU32(attributeName, static_cast<Vu32>(actualValue.parseU64()));
00622         else if (attributeType == VBentoS64::DATA_TYPE_ID())
00623             result = new VBentoS64(attributeName, actualValue.parseS64());
00624         else if (attributeType == VBentoU64::DATA_TYPE_ID())
00625             result = new VBentoU64(attributeName, actualValue.parseU64());
00626         else if (attributeType == VBentoBool::DATA_TYPE_ID())
00627             result = new VBentoBool(attributeName, actualValue == "true");
00628         else if (attributeType == VBentoString::DATA_TYPE_ID())
00629             result = new VBentoString(attributeName, actualValue, attributeQualifier/*the encoding*/);
00630         else if (attributeType == VBentoChar::DATA_TYPE_ID())
00631             result = new VBentoChar(attributeName, actualValue.length() == 0 ? VCodePoint(0) : VCodePoint(*actualValue.begin()));
00632         else if (attributeType == VBentoChar::LEGACY_DATA_TYPE_ID())
00633             result = new VBentoChar(attributeName, actualValue.length() == 0 ? VCodePoint(0) : VCodePoint((int) actualValue[0]));
00634         else if (attributeType == VBentoFloat::DATA_TYPE_ID()) {
00635             VDouble d;
00636             (void) ::sscanf(actualValue, VSTRING_FORMATTER_DOUBLE, &d);
00637             result = new VBentoFloat(attributeName, static_cast<VFloat>(d));
00638         } else if (attributeType == VBentoDouble::DATA_TYPE_ID()) {
00639             VDouble d;
00640             (void) ::sscanf(actualValue, VSTRING_FORMATTER_DOUBLE, &d);
00641             result = new VBentoDouble(attributeName, d);
00642         } else if (attributeType == VBentoDuration::DATA_TYPE_ID()) {
00643             // Although we always generate with a "ms" suffix, allow any valid
00644             // VDuration magnitude suffix, by letting VDuration parse it.
00645             VDuration d;
00646             d.setDurationString(actualValue);
00647             result = new VBentoDuration(attributeName, d);
00648         } else if (attributeType == VBentoInstant::DATA_TYPE_ID()) {
00649             VInstant i;
00650             i.setUTCString(actualValue);
00651             result = new VBentoInstant(attributeName, i);
00652         } else if (attributeType == VBentoSize::DATA_TYPE_ID()) {
00653             VDouble width;
00654             VDouble height;
00655             (void) ::sscanf(actualValue, "%lf,%lf", &width, &height);
00656             result = new VBentoSize(attributeName, VSize(width, height));
00657         } else if (attributeType == VBentoISize::DATA_TYPE_ID()) {
00658             int width;
00659             int height;
00660             (void) ::sscanf(actualValue, "%d,%d", &width, &height);
00661             result = new VBentoISize(attributeName, VISize(width, height));
00662         } else if (attributeType == VBentoPoint::DATA_TYPE_ID()) {
00663             VDouble x;
00664             VDouble y;
00665             (void) ::sscanf(actualValue, "%lf,%lf", &x, &y);
00666             result = new VBentoPoint(attributeName, VPoint(x, y));
00667         } else if (attributeType == VBentoIPoint::DATA_TYPE_ID()) {
00668             int x;
00669             int y;
00670             (void) ::sscanf(actualValue, "%d,%d", &x, &y);
00671             result = new VBentoIPoint(attributeName, VIPoint(x, y));
00672         } else if (attributeType == VBentoPoint3D::DATA_TYPE_ID()) {
00673             VDouble x;
00674             VDouble y;
00675             VDouble z;
00676             (void) ::sscanf(actualValue, "%lf,%lf,%lf", &x, &y, &z);
00677             result = new VBentoPoint3D(attributeName, VPoint3D(x, y, z));
00678         } else if (attributeType == VBentoIPoint3D::DATA_TYPE_ID()) {
00679             int x;
00680             int y;
00681             int z;
00682             (void) ::sscanf(actualValue, "%d,%d,%d", &x, &y, &z);
00683             result = new VBentoIPoint3D(attributeName, VIPoint3D(x, y, z));
00684         } else if (attributeType == VBentoLine::DATA_TYPE_ID()) {
00685             VDouble x1;
00686             VDouble y1;
00687             VDouble x2;
00688             VDouble y2;
00689             (void) ::sscanf(actualValue, "%lf,%lf:%lf,%lf", &x1, &y1, &x2, &y2);
00690             result = new VBentoLine(attributeName, VLine(VPoint(x1, y1), VPoint(x2, y2)));
00691         } else if (attributeType == VBentoILine::DATA_TYPE_ID()) {
00692             int x1;
00693             int y1;
00694             int x2;
00695             int y2;
00696             (void) ::sscanf(actualValue, "%d,%d:%d,%d", &x1, &y1, &x2, &y2);
00697             result = new VBentoILine(attributeName, VILine(VIPoint(x1, y1), VIPoint(x2, y2)));
00698         } else if (attributeType == VBentoRect::DATA_TYPE_ID()) {
00699             VDouble x;
00700             VDouble y;
00701             VDouble width;
00702             VDouble height;
00703             (void) ::sscanf(actualValue, "%lf,%lf:%lf*%lf", &x, &y, &width, &height);
00704             result = new VBentoRect(attributeName, VRect(VPoint(x, y), VSize(width, height)));
00705         } else if (attributeType == VBentoIRect::DATA_TYPE_ID()) {
00706             int x;
00707             int y;
00708             int width;
00709             int height;
00710             (void) ::sscanf(actualValue, "%d,%d:%d*%d", &x, &y, &width, &height);
00711             result = new VBentoIRect(attributeName, VIRect(VIPoint(x, y), VISize(width, height)));
00712         } else if (attributeType == VBentoPolygon::DATA_TYPE_ID()) {
00713             VPolygon p;
00714             VBentoPolygon::readPolygonFromBentoTextString(actualValue, p);
00715             result = new VBentoPolygon(attributeName, p);
00716         } else if (attributeType == VBentoIPolygon::DATA_TYPE_ID()) {
00717             VIPolygon p;
00718             VBentoIPolygon::readPolygonFromBentoTextString(actualValue, p);
00719             result = new VBentoIPolygon(attributeName, p);
00720         } else if (attributeType == VBentoColor::DATA_TYPE_ID()) {
00721             int r;
00722             int g;
00723             int b;
00724             int alpha;
00725             (void) ::sscanf(actualValue, "%d,%d,%d,%d", &r, &g, &b, &alpha);
00726             result = new VBentoColor(attributeName, VColor(r, g, b, alpha));
00727         } else if (attributeType == VBentoBinary::DATA_TYPE_ID()) {
00728             result = VBentoBinary::newFromBentoTextString(attributeName, actualValue);
00729         } else if (attributeType == VBentoS8Array::DATA_TYPE_ID()) {
00730             result = VBentoS8Array::newFromBentoTextString(attributeName, actualValue);
00731         } else if (attributeType == VBentoS16Array::DATA_TYPE_ID()) {
00732             result = VBentoS16Array::newFromBentoTextString(attributeName, actualValue);
00733         } else if (attributeType == VBentoS32Array::DATA_TYPE_ID()) {
00734             result = VBentoS32Array::newFromBentoTextString(attributeName, actualValue);
00735         } else if (attributeType == VBentoS64Array::DATA_TYPE_ID()) {
00736             result = VBentoS64Array::newFromBentoTextString(attributeName, actualValue);
00737         } else if (attributeType == VBentoStringArray::DATA_TYPE_ID()) {
00738             result = VBentoStringArray::newFromBentoTextString(attributeName, actualValue);
00739         } else if (attributeType == VBentoBoolArray::DATA_TYPE_ID()) {
00740             result = VBentoBoolArray::newFromBentoTextString(attributeName, actualValue);
00741         } else if (attributeType == VBentoDoubleArray::DATA_TYPE_ID()) {
00742             result = VBentoDoubleArray::newFromBentoTextString(attributeName, actualValue);
00743         } else if (attributeType == VBentoDurationArray::DATA_TYPE_ID()) {
00744             result = VBentoDurationArray::newFromBentoTextString(attributeName, actualValue);
00745         } else if (attributeType == VBentoInstantArray::DATA_TYPE_ID()) {
00746             result = VBentoInstantArray::newFromBentoTextString(attributeName, actualValue);
00747         } else {
00748             throw VException(VSTRING_FORMAT("Parser encountered unknown data type '%s'", attributeType.chars()));
00749         }
00750     } else {
00751         // Infer the type from the format of the value.
00752         if ((attributeValue == "true") || (attributeValue == "false")) {
00753             result = new VBentoBool(attributeName, attributeValue == "true");
00754         } else if ((attributeValue == "NOW") || (attributeValue == "NEVER") || (attributeValue == "PAST") || (attributeValue == "FUTURE")) {
00755             VInstant when;
00756             when.setLocalString(attributeValue);
00757             result = new VBentoInstant(attributeName, when);
00758         } else if (attributeValue.startsWith('\"') || attributeValue.startsWith('(')) {
00759             actualValue.substringInPlace(1, actualValue.length() - 1);
00760             _unescapeString(actualValue);
00761             result = new VBentoString(attributeName, actualValue, attributeQualifier/*the encoding*/);
00762         } else if (attributeValue.startsWith('\'')) {
00763             attributeValue.getSubstring(actualValue, 1, attributeValue.length() - 1);
00764             _unescapeString(actualValue);
00765             result = new VBentoChar(attributeName, actualValue.isEmpty() ? VCodePoint(0) : *(actualValue.begin()));
00766         } else {
00767             result = new VBentoS32(attributeName, static_cast<Vs32>(actualValue.parseS64()));
00768         }
00769     }
00770 
00771     return result;
00772 }
00773 
00783 static int _replaceCharWithString(VString& target, int atIndex, const VString& replacement) {
00784     // Assumption: replacement is not empty.
00785     target[atIndex] = replacement[0];
00786     target.insert(replacement.chars() + 1, atIndex + 1);
00787     return replacement.length() - 1;
00788 }
00789 
00790 static VString XML_AMPERSAND_ESCAPE("&amp;");
00791 static VString XML_APOSTROPHE_ESCAPE("&apos;");
00792 static VString XML_DOUBLEQUOTE_ESCAPE("&quot;");
00793 static VString XML_LESSTHAN_ESCAPE("&lt;");
00794 static VString XML_GREATERTHAN_ESCAPE("&gt;");
00795 
00796 // static
00797 void VBentoAttribute::_escapeXMLValue(VString& text) {
00798     // Post-Vault 3.3:
00799     // Replaced naive series of calls to text.replace("f", "&foo;") with optimized one-pass
00800     // in-place insertion replacement. Approximately 80x performance improvement for plain text,
00801     // and 30x improvement for heavily escaped text.
00802 
00803     // Strategy:
00804     // When we find a char requiring escape, replace it where it is:
00805     // 1. Overwrite the char with the first char of the escape sequence.
00806     // 2. Insert the rest of the escape sequence in front of the next char.
00807     // 3. Advance our string/loop index past the newly inserted escape sequence.
00808     for (int i = 0; i < text.length(); ++i) {
00809         char c = text[i];
00810         if (c == '&') {
00811             i += _replaceCharWithString(text, i, XML_AMPERSAND_ESCAPE);     // & -> &amp;
00812         } else if (c == '\'') {
00813             i += _replaceCharWithString(text, i, XML_APOSTROPHE_ESCAPE);    // ' -> &apos;
00814         } else if (c == '\"') {
00815             i += _replaceCharWithString(text, i, XML_DOUBLEQUOTE_ESCAPE);   // " -> &quot;
00816         } else if (c == '<') {
00817             i += _replaceCharWithString(text, i, XML_LESSTHAN_ESCAPE);      // < -> &lt;
00818         } else if (c == '>') {
00819             i += _replaceCharWithString(text, i, XML_GREATERTHAN_ESCAPE);   // > -> &gt;
00820         } else if (((int) c < 0x20) || ((int) c == 0x7F)) {
00821             i += _replaceCharWithString(text, i, VSTRING_FORMAT("&#x%02X;", (Vu8) c)); // unprintable -> &#xNN; where NN is exactly 2 hex digits char code
00822         }
00823     }
00824 }
00825 
00826 static VString _indent(int depth) {
00827     VString spaces;
00828     spaces.preflight(depth);
00829 
00830     for (int i = 0; i < depth; ++i) {
00831         spaces += ' ';
00832     }
00833 
00834     return spaces;
00835 }
00836 
00837 static void _indentIfRequested(VTextIOStream& stream, bool lineWrap, int depth) {
00838     if (lineWrap && (depth > 0)) {
00839         stream.writeString(_indent(depth));
00840     }
00841 }
00842 
00843 static void _lineEndIfRequested(VTextIOStream& stream, bool lineWrap) {
00844     if (lineWrap) {
00845         stream.writeLineEnd();
00846     }
00847 }
00848 
00852 static void _writeLineItemToStream(VTextIOStream& stream, bool lineWrap, int depth, const VString& lineText) {
00853     _indentIfRequested(stream, lineWrap, depth);
00854     stream.writeString(lineText);
00855     _lineEndIfRequested(stream, lineWrap);
00856 }
00857 
00858 // VBentoChar ----------------------------------------------------------------
00859 
00860 // static
00861 VBentoChar* VBentoChar::newFromLegacyCharStream(VBinaryIOStream& stream) {
00862     VString name = stream.readString();
00863 
00864     // Read the byte that was the legacy C char value. Then form the code point
00865     // using the char-oriented constructor, which will deal with both ASCII and
00866     // non-ASCII char byte values.
00867     VChar c((char) stream.readU8());
00868     return new VBentoChar(name, VCodePoint(c));
00869 }
00870 
00871 // VBentoSize ----------------------------------------------------------------
00872 
00873 void VBentoSize::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00874     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s width=\"%lf\" height=\"%lf\"/>", this->getName().chars(), mValue.getWidth(), mValue.getHeight()));
00875 }
00876 
00877 // VBentoISize ---------------------------------------------------------------
00878 
00879 void VBentoISize::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00880     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s width=\"%d\" height=\"%d\"/>", this->getName().chars(), mValue.getWidth(), mValue.getHeight()));
00881 }
00882 
00883 // VBentoPoint ---------------------------------------------------------------
00884 
00885 void VBentoPoint::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00886     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s x=\"%lf\" y=\"%lf\"/>", this->getName().chars(), mValue.getX(), mValue.getY()));
00887 }
00888 
00889 // VBentoIPoint --------------------------------------------------------------
00890 
00891 void VBentoIPoint::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00892     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s x=\"%d\" y=\"%d\"/>", this->getName().chars(), mValue.getX(), mValue.getY()));
00893 }
00894 
00895 // VBentoPoint3D -------------------------------------------------------------
00896 
00897 void VBentoPoint3D::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00898     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s x=\"%lf\" y=\"%lf\" z=\"%lf\"/>", this->getName().chars(), mValue.getX(), mValue.getY(), mValue.getZ()));
00899 }
00900 
00901 // VBentoIPoint3D ------------------------------------------------------------
00902 
00903 void VBentoIPoint3D::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00904     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s x=\"%d\" y=\"%d\" z=\"%d\"/>", this->getName().chars(), mValue.getX(), mValue.getY(), mValue.getZ()));
00905 }
00906 
00907 // VBentoLine ----------------------------------------------------------------
00908 
00909 void VBentoLine::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00910     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s x1=\"%lf\" y1=\"%lf\" x2=\"%lf\" y2=\"%lf\"/>", this->getName().chars(), mValue.getP1().getX(), mValue.getP1().getY(), mValue.getP2().getX(), mValue.getP2().getY()));
00911 }
00912 
00913 // VBentoILine ---------------------------------------------------------------
00914 
00915 void VBentoILine::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00916     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\"/>", this->getName().chars(), mValue.getP1().getX(), mValue.getP1().getY(), mValue.getP2().getX(), mValue.getP2().getY()));
00917 }
00918 
00919 // VBentoRect ----------------------------------------------------------------
00920 
00921 void VBentoRect::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00922     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s left=\"%lf\" top=\"%lf\" width=\"%lf\" height=\"%lf\"/>", this->getName().chars(), mValue.getLeft(), mValue.getTop(), mValue.getWidth(), mValue.getHeight()));
00923 }
00924 
00925 // VBentoIRect ---------------------------------------------------------------
00926 
00927 void VBentoIRect::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00928     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s left=\"%d\" top=\"%d\" width=\"%d\" height=\"%d\"/>", this->getName().chars(), mValue.getLeft(), mValue.getTop(), mValue.getWidth(), mValue.getHeight()));
00929 }
00930 
00931 // VBentoPolygon -------------------------------------------------------------
00932 
00933 // static
00934 void VBentoPolygon::_formatPolygonAsBentoTextString(const VPolygon& p, VString& s) {
00935     // example: "(1.0,2.0)(3.0,4.0)(5.0,6.0)"
00936     int numPoints = p.getNumPoints();
00937     for (int i = 0; i < numPoints; ++i) {
00938         VPoint point = p.getPoint(i);
00939         s += VSTRING_FORMAT("(%lf,%lf)", point.getX(), point.getY());
00940     }
00941 }
00942 
00943 // static
00944 void VBentoPolygon::readPolygonFromBentoTextString(const VString& s, VPolygon& p) {
00945     // example: "(1.0,2.0)(3.0,4.0)(5.0,6.0)"
00946     p.eraseAll();
00947     VString nextPointText;
00948     int openParenIndex = s.indexOf('(');
00949     int closeParenIndex = s.indexOf(')', openParenIndex);
00950     while (openParenIndex != -1 && closeParenIndex != -1) {
00951         s.getSubstring(nextPointText, openParenIndex + 1, closeParenIndex);
00952         VDouble x;
00953         VDouble y;
00954         (void) ::sscanf(nextPointText, "%lf,%lf", &x, &y);
00955         p.add(VPoint(x, y));
00956 
00957         openParenIndex = s.indexOf('(', closeParenIndex);
00958         closeParenIndex = s.indexOf(')', openParenIndex);
00959     }
00960 }
00961 
00962 void VBentoPolygon::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
00963     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
00964 
00965     const VPointVector& pts = mValue.getPoints();
00966     for (VPointVector::const_iterator i = pts.begin(); i != pts.end(); ++i) {
00967         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<point x=\"%lf\" y=\"%lf\"/>", (*i).getX(), (*i).getY()));
00968     }
00969 
00970     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
00971 }
00972 
00973 // VBentoIPolygon -------------------------------------------------------------
00974 
00975 // static
00976 void VBentoIPolygon::_formatPolygonAsBentoTextString(const VIPolygon& p, VString& s) {
00977     // example: "(1,2)(3,4)(5,6)"
00978     int numPoints = p.getNumPoints();
00979     for (int i = 0; i < numPoints; ++i) {
00980         VIPoint point = p.getPoint(i);
00981         s += VSTRING_FORMAT("(%d,%d)", point.getX(), point.getY());
00982     }
00983 }
00984 
00985 // static
00986 void VBentoIPolygon::readPolygonFromBentoTextString(const VString& s, VIPolygon& p) {
00987     // example: "(1,2)(3,4)(5,6)"
00988     p.eraseAll();
00989     VString nextPointText;
00990     int openParenIndex = s.indexOf('(');
00991     int closeParenIndex = s.indexOf(')', openParenIndex);
00992     while (openParenIndex != -1 && closeParenIndex != -1) {
00993         s.getSubstring(nextPointText, openParenIndex + 1, closeParenIndex);
00994         int x;
00995         int y;
00996         (void) ::sscanf(nextPointText, "%d,%d", &x, &y);
00997         p.add(VIPoint(x, y));
00998 
00999         openParenIndex = s.indexOf('(', closeParenIndex);
01000         closeParenIndex = s.indexOf(')', openParenIndex);
01001     }
01002 }
01003 
01004 void VBentoIPolygon::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01005     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01006 
01007     const VIPointVector& pts = mValue.getPoints();
01008     for (VIPointVector::const_iterator i = pts.begin(); i != pts.end(); ++i) {
01009         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<point x=\"%d\" y=\"%d\"/>", (*i).getX(), (*i).getY()));
01010     }
01011 
01012     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01013 }
01014 
01015 // VBentoBinary --------------------------------------------------------------
01016 
01017 // static
01018 VBentoBinary* VBentoBinary::newFromBentoTextString(const VString& name, const VString& bentoText) {
01019     int bufferLength = (bentoText.length() + 1) / 2;
01020 
01021     bool hasLeading0x = bentoText.startsWith("0x") || bentoText.startsWith("0X");
01022     if (hasLeading0x) {
01023         --bufferLength;
01024     }
01025 
01026     Vu8* buffer = new Vu8[bufferLength];
01027     VHex::hexStringToBuffer(bentoText, buffer, hasLeading0x);
01028 
01029     VBentoBinary* result = new VBentoBinary(name, buffer, VMemoryStream::kAllocatedByOperatorNew, true /*adoptBuffer*/, bufferLength, bufferLength);
01030     return result;
01031 }
01032 
01033 void VBentoBinary::writeDataToBinaryStream(VBinaryIOStream& stream) const {
01034     Vs64 length = mValue.getEOFOffset();
01035     VReadOnlyMemoryStream reader(mValue.getBuffer(), length);
01036 
01037     VBentoNode::_writeLengthToStream(stream, length);
01038     (void) VStream::streamCopy(reader, stream, length);
01039 }
01040 
01041 void VBentoBinary::_getValueAsHexString(VString& s) const {
01042     VHex::bufferToHexString(mValue.getBuffer(), mValue.getEOFOffset(), s, true/*want leading 0x*/);
01043 }
01044 
01045 // VBentoS8Array --------------------------------------------------------------
01046 
01047 // static
01048 VBentoS8Array* VBentoS8Array::newFromBentoTextString(const VString& name, const VString& s) {
01049     VBentoS8Array* result = new VBentoS8Array(name);
01050 
01051     // example: "0,1,2"
01052     VString nextElementText;
01053     int previousSeparatorIndex = -1;
01054     int nextSeparatorIndex = s.indexOf(',');
01055     do {
01056         s.getSubstring(nextElementText, previousSeparatorIndex + 1, nextSeparatorIndex);
01057         int value;
01058         (void) ::sscanf(nextElementText, VSTRING_FORMATTER_INT, &value); // Note: %hhd for Vs8 not universally supported; using plain old int conversion instead.
01059         result->appendValue(static_cast<Vs8>(value));
01060 
01061         previousSeparatorIndex = nextSeparatorIndex;
01062         nextSeparatorIndex = s.indexOf(',', previousSeparatorIndex + 1);
01063     } while (previousSeparatorIndex != -1);
01064 
01065     return result;
01066 }
01067 
01068 void VBentoS8Array::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01069     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01070 
01071     for (Vs8Array::const_iterator i = mValue.begin(); i != mValue.end(); ++i) {
01072         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<item value=\"%d\"/>", (int)(*i)));
01073     }
01074 
01075     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01076 }
01077 
01078 // VBentoS16Array --------------------------------------------------------------
01079 
01080 // static
01081 VBentoS16Array* VBentoS16Array::newFromBentoTextString(const VString& name, const VString& s) {
01082     VBentoS16Array* result = new VBentoS16Array(name);
01083 
01084     // example: "0,1,2"
01085     VString nextElementText;
01086     int previousSeparatorIndex = -1;
01087     int nextSeparatorIndex = s.indexOf(',');
01088     do {
01089         s.getSubstring(nextElementText, previousSeparatorIndex + 1, nextSeparatorIndex);
01090         Vs16 value;
01091         (void) ::sscanf(nextElementText, VSTRING_FORMATTER_S16, &value);
01092         result->appendValue(value);
01093 
01094         previousSeparatorIndex = nextSeparatorIndex;
01095         nextSeparatorIndex = s.indexOf(',', previousSeparatorIndex + 1);
01096     } while (previousSeparatorIndex != -1);
01097 
01098     return result;
01099 }
01100 
01101 void VBentoS16Array::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01102     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01103 
01104     for (Vs16Array::const_iterator i = mValue.begin(); i != mValue.end(); ++i) {
01105         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<item value=\"" VSTRING_FORMATTER_S16 "\"/>", (*i)));
01106     }
01107 
01108     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01109 }
01110 
01111 // VBentoS32Array --------------------------------------------------------------
01112 
01113 // static
01114 VBentoS32Array* VBentoS32Array::newFromBentoTextString(const VString& name, const VString& s) {
01115     VBentoS32Array* result = new VBentoS32Array(name);
01116 
01117     // example: "0,1,2"
01118     VString nextElementText;
01119     int previousSeparatorIndex = -1;
01120     int nextSeparatorIndex = s.indexOf(',');
01121     do {
01122         s.getSubstring(nextElementText, previousSeparatorIndex + 1, nextSeparatorIndex);
01123         Vs32 value;
01124         (void) ::sscanf(nextElementText, VSTRING_FORMATTER_S32, &value);
01125         result->appendValue(value);
01126 
01127         previousSeparatorIndex = nextSeparatorIndex;
01128         nextSeparatorIndex = s.indexOf(',', previousSeparatorIndex + 1);
01129     } while (previousSeparatorIndex != -1);
01130 
01131     return result;
01132 }
01133 
01134 void VBentoS32Array::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01135     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01136 
01137     for (Vs32Array::const_iterator i = mValue.begin(); i != mValue.end(); ++i) {
01138         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<item value=\"" VSTRING_FORMATTER_S32 "\"/>", (*i)));
01139     }
01140 
01141     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01142 }
01143 
01144 // VBentoS64Array --------------------------------------------------------------
01145 
01146 // static
01147 VBentoS64Array* VBentoS64Array::newFromBentoTextString(const VString& name, const VString& s) {
01148     VBentoS64Array* result = new VBentoS64Array(name);
01149 
01150     // example: "0,1,2"
01151     VString nextElementText;
01152     int previousSeparatorIndex = -1;
01153     int nextSeparatorIndex = s.indexOf(',');
01154     do {
01155         s.getSubstring(nextElementText, previousSeparatorIndex + 1, nextSeparatorIndex);
01156         Vs64 value;
01157         (void) ::sscanf(nextElementText, VSTRING_FORMATTER_S64, &value);
01158         result->appendValue(value);
01159 
01160         previousSeparatorIndex = nextSeparatorIndex;
01161         nextSeparatorIndex = s.indexOf(',', previousSeparatorIndex + 1);
01162     } while (previousSeparatorIndex != -1);
01163 
01164     return result;
01165 }
01166 
01167 void VBentoS64Array::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01168     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01169 
01170     for (Vs64Array::const_iterator i = mValue.begin(); i != mValue.end(); ++i) {
01171         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<item value=\"" VSTRING_FORMATTER_S64 "\"/>", (*i)));
01172     }
01173 
01174     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01175 }
01176 
01177 // VBentoBoolArray --------------------------------------------------------------
01178 
01179 // static
01180 VBentoBoolArray* VBentoBoolArray::newFromBentoTextString(const VString& name, const VString& s) {
01181     VBentoBoolArray* result = new VBentoBoolArray(name);
01182 
01183     // example: "true,false,true"
01184     VString nextElementText;
01185     int previousSeparatorIndex = -1;
01186     int nextSeparatorIndex = s.indexOf(',');
01187     do {
01188         s.getSubstring(nextElementText, previousSeparatorIndex + 1, nextSeparatorIndex);
01189         result->appendValue(nextElementText.equalsIgnoreCase("true"));
01190 
01191         previousSeparatorIndex = nextSeparatorIndex;
01192         nextSeparatorIndex = s.indexOf(',', previousSeparatorIndex + 1);
01193     } while (previousSeparatorIndex != -1);
01194 
01195     return result;
01196 }
01197 
01198 void VBentoBoolArray::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01199     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01200 
01201     for (VBoolArray::const_iterator i = mValue.begin(); i != mValue.end(); ++i) {
01202         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<item value=\"%s\"/>", (*i) ? "true" : "false"));
01203     }
01204 
01205     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01206 }
01207 
01208 // VBentoStringArray --------------------------------------------------------------
01209 
01211 typedef enum {
01212     kStringArrayParseState_Init,            
01213     kStringArrayParseState_InArray,         
01214     kStringArrayParseState_InElement,       
01215     kStringArrayParseState_ElementEnded,    
01216     kStringArrayParseState_EscapePending,   
01217     kStringArrayParseState_Done             
01218 } StringArrayParseState;
01219 
01220 // static
01221 VBentoStringArray* VBentoStringArray::newFromBentoTextString(const VString& name, const VString& s) {
01222     VBentoStringArray* result = new VBentoStringArray(name);
01223 
01224     // example: "one","two\"quote\"two","three,comma,three"
01225     // The complete string we receive contains zero or more elements.
01226     // Each individual element string is double-quoted.
01227     // Any double-quote inside an element string is escaped with a backslash.
01228 
01229     VString pendingString;
01230     StringArrayParseState state = kStringArrayParseState_InArray;
01231     int index = 0;
01232     for (VString::const_iterator i = s.begin(); i != s.end(); ++i, ++index) {
01233         VCodePoint c = *i;
01234 
01235         switch (state) {
01236             case kStringArrayParseState_Init:
01237                 if (c == '"')
01238                     state = kStringArrayParseState_InArray;
01239                 else
01240                     throw VException(VSTRING_FORMAT("VBentoStringArray::newFromBentoTextString: At character %d in Init state, required \" but got %s.", index, c.toString().chars()));
01241                 break;
01242 
01243             case kStringArrayParseState_InArray:
01244                 if (c == '"')
01245                     state = kStringArrayParseState_InElement;
01246                 else
01247                     throw VException(VSTRING_FORMAT("VBentoStringArray::newFromBentoTextString: At character %d in InArray state, required \" but got %s.", index, c.toString().chars()));
01248                 break;
01249 
01250             case kStringArrayParseState_InElement:
01251                 if (c == '"') {
01252                     result->appendValue(pendingString);
01253                     pendingString = VString::EMPTY();
01254                     state = kStringArrayParseState_ElementEnded;
01255                 } else if (c == '\\') {
01256                     state = kStringArrayParseState_EscapePending;
01257                 } else {
01258                     pendingString += c;
01259                 }
01260                 break;
01261 
01262             case kStringArrayParseState_ElementEnded:
01263                 if (c == ',')
01264                     state = kStringArrayParseState_InArray;
01265                 else if (c == '"')
01266                     state = kStringArrayParseState_Done;
01267                 else if (c.isWhitespace())
01268                     ; // skip any whitespace between elements
01269                 else
01270                     throw VException(VSTRING_FORMAT("VBentoStringArray::newFromBentoTextString: At character %d in ElementEnded state, required comma, \" or whitespace but got %s.", index, c.toString().chars()));
01271                 break;
01272 
01273             case kStringArrayParseState_EscapePending:
01274                 pendingString += c;
01275                 state = kStringArrayParseState_InElement;
01276                 break;
01277 
01278             case kStringArrayParseState_Done:
01279                 if (! c.isWhitespace())
01280                     throw VException(VSTRING_FORMAT("VBentoStringArray::newFromBentoTextString: At character %d in Done state, required whitespace but got %s.", index, c.toString().chars()));
01281                 break;
01282 
01283         }
01284     }
01285 
01286     return result;
01287 }
01288 
01289 void VBentoStringArray::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01290     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01291 
01292     for (VStringVector::const_iterator i = mValue.begin(); i != mValue.end(); ++i) {
01293         VString value = (*i);
01294         VBentoAttribute::_escapeXMLValue(value);
01295         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<item value=\"%s\"/>", value.chars()));
01296     }
01297 
01298     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01299 }
01300 
01301 // VBentoDoubleArray --------------------------------------------------------------
01302 
01303 // static
01304 VBentoDoubleArray* VBentoDoubleArray::newFromBentoTextString(const VString& name, const VString& s) {
01305     VBentoDoubleArray* result = new VBentoDoubleArray(name);
01306 
01307     // example: "0.0,1.11,2.222"
01308     VString nextElementText;
01309     int previousSeparatorIndex = -1;
01310     int nextSeparatorIndex = s.indexOf(',');
01311     do {
01312         s.getSubstring(nextElementText, previousSeparatorIndex + 1, nextSeparatorIndex);
01313         VDouble value;
01314         (void) ::sscanf(nextElementText, VSTRING_FORMATTER_DOUBLE, &value);
01315         result->appendValue(value);
01316 
01317         previousSeparatorIndex = nextSeparatorIndex;
01318         nextSeparatorIndex = s.indexOf(',', previousSeparatorIndex + 1);
01319     } while (previousSeparatorIndex != -1);
01320 
01321     return result;
01322 }
01323 
01324 void VBentoDoubleArray::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01325     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01326 
01327     for (VDoubleArray::const_iterator i = mValue.begin(); i != mValue.end(); ++i) {
01328         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<item value=\"%lf\"/>", (*i)));
01329     }
01330 
01331     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01332 }
01333 
01334 // VBentoDurationArray --------------------------------------------------------------
01335 
01336 // static
01337 VBentoDurationArray* VBentoDurationArray::newFromBentoTextString(const VString& name, const VString& s) {
01338     VBentoDurationArray* result = new VBentoDurationArray(name);
01339 
01340     // example: "0ms,1111ms,2723847ms"
01341     VString nextElementText;
01342     int previousSeparatorIndex = -1;
01343     int nextSeparatorIndex = s.indexOf(',');
01344     do {
01345         s.getSubstring(nextElementText, previousSeparatorIndex + 1, nextSeparatorIndex);
01346         Vs64 value;
01347         (void) ::sscanf(nextElementText, VSTRING_FORMATTER_S64 "ms", &value);
01348         result->appendValue(VDuration::MILLISECOND() * value);
01349 
01350         previousSeparatorIndex = nextSeparatorIndex;
01351         nextSeparatorIndex = s.indexOf(',', previousSeparatorIndex + 1);
01352     } while (previousSeparatorIndex != -1);
01353 
01354     return result;
01355 }
01356 
01357 void VBentoDurationArray::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01358     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01359 
01360     for (VDurationVector::const_iterator i = mValue.begin(); i != mValue.end(); ++i) {
01361         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<item value=\"%s\"/>", (*i).getDurationString().chars()));
01362     }
01363 
01364     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01365 }
01366 
01367 // VBentoInstantArray --------------------------------------------------------------
01368 
01369 // static
01370 VBentoInstantArray* VBentoInstantArray::newFromBentoTextString(const VString& name, const VString& s) {
01371     VBentoInstantArray* result = new VBentoInstantArray(name);
01372 
01373     // example: ""2007-11-23 09:08:07.234 UTC","2007-12-17 13:14:15.678 UTC","2008-01-06 05:06:07.890""
01374     VString nextElementText;
01375     int previousSeparatorIndex = -1;
01376     int nextSeparatorIndex = s.indexOf(',');
01377     do {
01378         s.getSubstring(nextElementText, previousSeparatorIndex + 1, nextSeparatorIndex);
01379         if (nextElementText.startsWith('"'))
01380             nextElementText.substringInPlace(1);
01381         if (nextElementText.endsWith('"'))
01382             nextElementText.substringInPlace(0, nextElementText.length() - 1);
01383 
01384         VInstant value = VInstant::NEVER_OCCURRED(); // avoid unnecessary clock read
01385         value.setUTCString(nextElementText);
01386         result->appendValue(value);
01387 
01388         previousSeparatorIndex = nextSeparatorIndex;
01389         nextSeparatorIndex = s.indexOf(',', previousSeparatorIndex + 1);
01390     } while (previousSeparatorIndex != -1);
01391 
01392     return result;
01393 }
01394 
01395 void VBentoInstantArray::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01396     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("<%s>", this->getName().chars()));
01397 
01398     for (VInstantVector::const_iterator i = mValue.begin(); i != mValue.end(); ++i) {
01399         _writeLineItemToStream(stream, lineWrap, indentDepth + 1, VSTRING_FORMAT("<item value=\"%s\"/>", (*i).getUTCString().chars()));
01400     }
01401 
01402     _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", this->getName().chars()));
01403 }
01404 
01405 // VBentoNode ----------------------------------------------------------------
01406 
01407 VBentoNode::VBentoNode()
01408     : mName("uninitialized")
01409     , mAttributes()
01410     , mParentNode(NULL)
01411     , mChildNodes()
01412     {
01413 }
01414 
01415 VBentoNode::VBentoNode(const VString& name)
01416     : mName(name)
01417     , mAttributes()
01418     , mParentNode(NULL)
01419     , mChildNodes()
01420     {
01421 }
01422 
01423 VBentoNode::VBentoNode(VBinaryIOStream& stream)
01424     : mName()
01425     , mAttributes()
01426     , mParentNode(NULL)
01427     , mChildNodes()
01428     {
01429     this->readFromStream(stream);
01430 }
01431 
01432 VBentoNode::VBentoNode(VTextIOStream& bentoTextStream)
01433     : mName()
01434     , mAttributes()
01435     , mParentNode(NULL)
01436     , mChildNodes()
01437     {
01438     this->readFromBentoTextStream(bentoTextStream);
01439 }
01440 
01441 VBentoNode::~VBentoNode() {
01442     try {
01443         VSizeType    numAttributes = mAttributes.size();
01444         for (VSizeType i = 0; i < numAttributes; ++i) {
01445             delete mAttributes[i];
01446         }
01447 
01448         VSizeType    numChildNodes = mChildNodes.size();
01449         for (VSizeType i = 0; i < numChildNodes; ++i) {
01450             delete mChildNodes[i];
01451         }
01452     } catch (...) { // block exceptions from propagating
01453     }
01454 
01455     mParentNode = NULL; //we do not own parent, it owns us
01456 }
01457 
01458 VBentoNode::VBentoNode(const VBentoNode& original) :
01459     mName(original.getName()),
01460     mAttributes(),
01461     mParentNode(NULL),
01462     mChildNodes() {
01463     const VBentoAttributePtrVector& originalAttributes = original.getAttributes();
01464     for (VBentoAttributePtrVector::const_iterator i = originalAttributes.begin(); i != originalAttributes.end(); ++i) {
01465         mAttributes.push_back((*i)->clone());
01466     }
01467 
01468     const VBentoNodePtrVector& originalNodes = original.getNodes();
01469     for (VBentoNodePtrVector::const_iterator i = originalNodes.begin(); i != originalNodes.end(); ++i) {
01470         VBentoNode* child = new VBentoNode(**i);
01471         mChildNodes.push_back(child);
01472         child->mParentNode = this;
01473     }
01474 }
01475 
01476 void VBentoNode::clear() {
01477     VSizeType    numAttributes = mAttributes.size();
01478     for (VSizeType i = 0; i < numAttributes; ++i)
01479         delete mAttributes[i];
01480 
01481     VSizeType    numChildNodes = mChildNodes.size();
01482     for (VSizeType i = 0; i < numChildNodes; ++i)
01483         delete mChildNodes[i];
01484 
01485     mAttributes.clear();
01486     mChildNodes.clear();
01487 }
01488 
01489 void VBentoNode::orphanAttributes() {
01490     mAttributes.clear(); // does not actually delete the objects
01491 }
01492 
01493 void VBentoNode::orphanNodes() {
01494     size_t numChildNodes = mChildNodes.size();
01495     for (VSizeType i = 0; i < numChildNodes; ++i) {
01496         mChildNodes[i]->mParentNode = NULL;
01497     }
01498     mChildNodes.clear(); // does not actually delete the objects
01499 }
01500 
01501 void VBentoNode::orphanNode(const VBentoNode* node) {
01502     VBentoNodePtrVector::iterator position = std::find(mChildNodes.begin(), mChildNodes.end(), node);
01503     if (position != mChildNodes.end()) {
01504         (**position).mParentNode = NULL;
01505         mChildNodes.erase(position);
01506     }
01507 }
01508 
01509 void VBentoNode::adoptFrom(VBentoNode* node) {
01510     // Destroy any existing attributes and children of this node.
01511     this->clear();
01512 
01513     // Copy that node's name, then adopt its attributes and child nodes using shallow vector copy.
01514     mName = node->getName();
01515     mAttributes = node->mAttributes;
01516     mChildNodes = node->mChildNodes;
01517 
01518     // We now own that node's attribute and child objects. Tell it to let go of them.
01519     node->orphanAttributes();
01520     node->orphanNodes();
01521 
01522     size_t numChildNodes = mChildNodes.size();
01523     for (VSizeType i = 0; i < numChildNodes; ++i) {
01524         mChildNodes[i]->mParentNode = this;
01525     }
01526 }
01527 
01528 void VBentoNode::updateFrom(const VBentoNode& source) {
01529     // Copy the name if not empty.
01530     if (source.getName().isNotEmpty()) {
01531         mName = source.getName();
01532     }
01533 
01534     // Copy (adding as necessary) the attributes.
01535     const VBentoAttributePtrVector& sourceAttributes = source.getAttributes();
01536     for (VBentoAttributePtrVector::const_iterator i = sourceAttributes.begin(); i != sourceAttributes.end(); ++i) {
01537         VBentoAttribute* targetAttribute = this->_findMutableAttribute((*i)->getName(), (*i)->getDataType());
01538         if (targetAttribute == NULL) {
01539             // Clone the source attribute and add it.
01540             VBentoAttribute* clonedAttribute = (*i)->clone();
01541             this->_addAttribute(clonedAttribute);
01542         } else {
01543             // Copy source attribute to target using VBentoAttribute assignment operator.
01544             VBentoAttribute* sourceAttribute = *i;
01545             *targetAttribute = *sourceAttribute;
01546         }
01547     }
01548 
01549     const VBentoNodePtrVector& sourceChildren = source.getNodes();
01550     for (VBentoNodePtrVector::const_iterator i = sourceChildren.begin(); i != sourceChildren.end(); ++i) {
01551         const VBentoNode* targetChild = this->findNode((*i)->getName());
01552         if (targetChild == NULL) {
01553             // Clone the source node and add it.
01554             VBentoNode* clonedChild = new VBentoNode(**i);
01555             this->addChildNode(clonedChild);
01556         } else {
01557             // Recursively update the target child node.
01558             const_cast<VBentoNode*>(targetChild)->updateFrom(**i); // const_cast: WORKAROUND. Alternative is to define a findMutableNode() API.
01559         }
01560     }
01561 }
01562 
01563 void VBentoNode::addChildNode(VBentoNode* node) {
01564     node->mParentNode = this;
01565     mChildNodes.push_back(node);
01566 }
01567 
01568 VBentoNode* VBentoNode::addNewChildNode(const VString& name) {
01569     VBentoNode* child = new VBentoNode(name);
01570     child->mParentNode = this;
01571     mChildNodes.push_back(child);
01572     return child;
01573 }
01574 
01575 void VBentoNode::addInt(const VString& name, int value) { this->addS32(name, static_cast<Vs32>(value)); }
01576 void VBentoNode::addBool(const VString& name, bool value) { this->_addAttribute(new VBentoBool(name, value)); }
01577 void VBentoNode::addString(const VString& name, const VString& value, const VString& encoding) { this->_addAttribute(new VBentoString(name, value, encoding)); }
01578 void VBentoNode::addStringIfNotEmpty(const VString& name, const VString& value, const VString& encoding) { if (!value.isEmpty()) this->_addAttribute(new VBentoString(name, value, encoding)); }
01579 void VBentoNode::addChar(const VString& name, const VCodePoint& value) { this->_addAttribute(new VBentoChar(name, value)); }
01580 void VBentoNode::addDouble(const VString& name, VDouble value) { this->_addAttribute(new VBentoDouble(name, value)); }
01581 void VBentoNode::addDuration(const VString& name, const VDuration& value) { this->_addAttribute(new VBentoDuration(name, value)); }
01582 void VBentoNode::addInstant(const VString& name, const VInstant& value) { this->_addAttribute(new VBentoInstant(name, value)); }
01583 void VBentoNode::addSize(const VString& name, const VSize& value) { this->_addAttribute(new VBentoSize(name, value)); }
01584 void VBentoNode::addISize(const VString& name, const VISize& value) { this->_addAttribute(new VBentoISize(name, value)); }
01585 void VBentoNode::addPoint(const VString& name, const VPoint& value) { this->_addAttribute(new VBentoPoint(name, value)); }
01586 void VBentoNode::addIPoint(const VString& name, const VIPoint& value) { this->_addAttribute(new VBentoIPoint(name, value)); }
01587 void VBentoNode::addPoint3D(const VString& name, const VPoint3D& value) { this->_addAttribute(new VBentoPoint3D(name, value)); }
01588 void VBentoNode::addIPoint3D(const VString& name, const VIPoint3D& value) { this->_addAttribute(new VBentoIPoint3D(name, value)); }
01589 void VBentoNode::addLine(const VString& name, const VLine& value) { this->_addAttribute(new VBentoLine(name, value)); }
01590 void VBentoNode::addILine(const VString& name, const VILine& value) { this->_addAttribute(new VBentoILine(name, value)); }
01591 void VBentoNode::addRect(const VString& name, const VRect& value) { this->_addAttribute(new VBentoRect(name, value)); }
01592 void VBentoNode::addIRect(const VString& name, const VIRect& value) { this->_addAttribute(new VBentoIRect(name, value)); }
01593 void VBentoNode::addPolygon(const VString& name, const VPolygon& value) { this->_addAttribute(new VBentoPolygon(name, value)); }
01594 void VBentoNode::addIPolygon(const VString& name, const VIPolygon& value) { this->_addAttribute(new VBentoIPolygon(name, value)); }
01595 void VBentoNode::addColor(const VString& name, const VColor& value) { this->_addAttribute(new VBentoColor(name, value)); }
01596 void VBentoNode::addS8(const VString& name, Vs8 value) { this->_addAttribute(new VBentoS8(name, value)); }
01597 void VBentoNode::addU8(const VString& name, Vu8 value) { this->_addAttribute(new VBentoU8(name, value)); }
01598 void VBentoNode::addS16(const VString& name, Vs16 value) { this->_addAttribute(new VBentoS16(name, value)); }
01599 void VBentoNode::addU16(const VString& name, Vu16 value) { this->_addAttribute(new VBentoU16(name, value)); }
01600 void VBentoNode::addS32(const VString& name, Vs32 value) { this->_addAttribute(new VBentoS32(name, value)); }
01601 void VBentoNode::addU32(const VString& name, Vu32 value) { this->_addAttribute(new VBentoU32(name, value)); }
01602 void VBentoNode::addS64(const VString& name, Vs64 value) { this->_addAttribute(new VBentoS64(name, value)); }
01603 void VBentoNode::addU64(const VString& name, Vu64 value) { this->_addAttribute(new VBentoU64(name, value)); }
01604 void VBentoNode::addFloat(const VString& name, VFloat value) { this->_addAttribute(new VBentoFloat(name, value)); }
01605 void VBentoNode::addBinary(const VString& name, const Vu8* data, Vs64 length) { this->_addAttribute(new VBentoBinary(name, data, length)); }
01606 void VBentoNode::addBinary(const VString& name, Vu8* data, VMemoryStream::BufferAllocationType allocationType, bool adoptBuffer, Vs64 suppliedBufferSize, Vs64 suppliedEOFOffset) { this->_addAttribute(new VBentoBinary(name, data, allocationType, adoptBuffer, suppliedBufferSize, suppliedEOFOffset)); }
01607 VBentoS8Array* VBentoNode::addS8Array(const VString& name) { VBentoS8Array* attr = new VBentoS8Array(name); this->_addAttribute(attr); return attr;}
01608 VBentoS8Array* VBentoNode::addS8Array(const VString& name, const Vs8Array& value) { VBentoS8Array* attr = new VBentoS8Array(name, value); this->_addAttribute(attr); return attr;}
01609 VBentoS16Array* VBentoNode::addS16Array(const VString& name) { VBentoS16Array* attr = new VBentoS16Array(name); this->_addAttribute(attr); return attr;}
01610 VBentoS16Array* VBentoNode::addS16Array(const VString& name, const Vs16Array& value) { VBentoS16Array* attr = new VBentoS16Array(name, value); this->_addAttribute(attr); return attr;}
01611 VBentoS32Array* VBentoNode::addS32Array(const VString& name) { VBentoS32Array* attr = new VBentoS32Array(name); this->_addAttribute(attr); return attr;}
01612 VBentoS32Array* VBentoNode::addS32Array(const VString& name, const Vs32Array& value) { VBentoS32Array* attr = new VBentoS32Array(name, value); this->_addAttribute(attr); return attr;}
01613 VBentoS64Array* VBentoNode::addS64Array(const VString& name) { VBentoS64Array* attr = new VBentoS64Array(name); this->_addAttribute(attr); return attr;}
01614 VBentoS64Array* VBentoNode::addS64Array(const VString& name, const Vs64Array& value) { VBentoS64Array* attr = new VBentoS64Array(name, value); this->_addAttribute(attr); return attr;}
01615 VBentoStringArray* VBentoNode::addStringArray(const VString& name) { VBentoStringArray* attr = new VBentoStringArray(name); this->_addAttribute(attr); return attr;}
01616 VBentoStringArray* VBentoNode::addStringArray(const VString& name, const VStringVector& value) { VBentoStringArray* attr = new VBentoStringArray(name, value); this->_addAttribute(attr); return attr;}
01617 VBentoBoolArray* VBentoNode::addBoolArray(const VString& name) { VBentoBoolArray* attr = new VBentoBoolArray(name); this->_addAttribute(attr); return attr;}
01618 VBentoBoolArray* VBentoNode::addBoolArray(const VString& name, const VBoolArray& value) { VBentoBoolArray* attr = new VBentoBoolArray(name, value); this->_addAttribute(attr); return attr;}
01619 VBentoDoubleArray* VBentoNode::addDoubleArray(const VString& name) { VBentoDoubleArray* attr = new VBentoDoubleArray(name); this->_addAttribute(attr); return attr;}
01620 VBentoDoubleArray* VBentoNode::addDoubleArray(const VString& name, const VDoubleArray& value) { VBentoDoubleArray* attr = new VBentoDoubleArray(name, value); this->_addAttribute(attr); return attr;}
01621 VBentoDurationArray* VBentoNode::addDurationArray(const VString& name) { VBentoDurationArray* attr = new VBentoDurationArray(name); this->_addAttribute(attr); return attr;}
01622 VBentoDurationArray* VBentoNode::addDurationArray(const VString& name, const VDurationVector& value) { VBentoDurationArray* attr = new VBentoDurationArray(name, value); this->_addAttribute(attr); return attr;}
01623 VBentoInstantArray* VBentoNode::addInstantArray(const VString& name) { VBentoInstantArray* attr = new VBentoInstantArray(name); this->_addAttribute(attr); return attr;}
01624 VBentoInstantArray* VBentoNode::addInstantArray(const VString& name, const VInstantVector& value) { VBentoInstantArray* attr = new VBentoInstantArray(name, value); this->_addAttribute(attr); return attr;}
01625 
01626 void VBentoNode::writeToStream(VBinaryIOStream& stream) const {
01627     Vs64 contentSize = this->_calculateContentSize();
01628     VBentoNode::_writeLengthToStream(stream, contentSize);
01629 
01630     VSizeType numAttributes = mAttributes.size();
01631     stream.writeSize32(numAttributes);
01632 
01633     VSizeType numChildNodes = mChildNodes.size();
01634     stream.writeSize32(numChildNodes);
01635 
01636     stream.writeString(mName);
01637 
01638     for (VSizeType i = 0; i < numAttributes; ++i) {
01639         mAttributes[i]->writeToStream(stream);
01640     }
01641 
01642     for (VSizeType i = 0; i < numChildNodes; ++i) {
01643         mChildNodes[i]->writeToStream(stream);
01644     }
01645 }
01646 
01647 void VBentoNode::writeToBentoTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
01648     _lineEndIfRequested(stream, lineWrap);
01649     _indentIfRequested(stream, lineWrap, indentDepth);
01650 
01651     VString name(mName);
01652     _escapeString(name);
01653     stream.writeString(VSTRING_FORMAT("{ \"%s\" ", name.chars()));
01654 
01655     VSizeType numAttributes = mAttributes.size();
01656     for (VSizeType i = 0; i < numAttributes; ++i) {
01657         mAttributes[i]->writeToBentoTextStream(stream);
01658         stream.writeString(" ");
01659     }
01660 
01661     VSizeType numChildNodes = mChildNodes.size();
01662     for (VSizeType i = 0; i < numChildNodes; ++i) {
01663         mChildNodes[i]->writeToBentoTextStream(stream, lineWrap, indentDepth + 1);
01664         stream.writeString(" ");
01665     }
01666 
01667     if (numChildNodes != 0) {
01668         _lineEndIfRequested(stream, lineWrap);
01669         _indentIfRequested(stream, lineWrap, indentDepth);
01670     }
01671 
01672     stream.writeString("}");
01673 }
01674 
01675 void VBentoNode::writeToBentoTextString(VString& s, bool lineWrap) const {
01676     VMemoryStream buffer;
01677     VTextIOStream stream(buffer);
01678     this->writeToBentoTextStream(stream, lineWrap);
01679     stream.writeLineEnd();
01680     stream.seek0();
01681 
01682     s = VString::EMPTY();
01683     stream.readAll(s, lineWrap);
01684 }
01685 
01686 void VBentoNode::readFromStream(VBinaryIOStream& stream) {
01687     /* unused Vs64 contentSize = */ (void) VBentoNode::_readLengthFromStream(stream);
01688     Vs32 numAttributes = stream.readS32();
01689     Vs32 numChildNodes = stream.readS32();
01690 
01691     stream.readString(mName);
01692 
01693     for (int i = 0; i < numAttributes; ++i) {
01694         this->_addAttribute(VBentoAttribute::newObjectFromStream(stream));
01695     }
01696 
01697     for (int i = 0; i < numChildNodes; ++i) {
01698         this->addChildNode(new VBentoNode(stream));
01699     }
01700 }
01701 
01702 void VBentoNode::readFromBentoTextStream(VTextIOStream& bentoTextStream) {
01703     VBentoTextNodeParser parser;
01704     parser.parse(bentoTextStream, *this);
01705 }
01706 
01707 void VBentoNode::readFromBentoTextString(const VString& bentoTextString) {
01708     VBentoTextNodeParser parser;
01709     parser.parse(bentoTextString, *this);
01710 }
01711 
01712 VBentoNode* VBentoNode::getParentNode() const {
01713     return mParentNode;
01714 }
01715 
01716 const VBentoNodePtrVector& VBentoNode::getNodes() const {
01717     return mChildNodes;
01718 }
01719 
01720 const VBentoNode* VBentoNode::findNode(const VString& nodeName) const {
01721     for (VBentoNodePtrVector::const_iterator i = mChildNodes.begin(); i != mChildNodes.end(); ++i) {
01722         if (nodeName.equalsIgnoreCase((*i)->getName())) {
01723             return (*i);
01724         }
01725     }
01726 
01727     return NULL;
01728 }
01729 
01730 const VBentoNode* VBentoNode::findNode(const VString& nodeName, const VString& attributeName, const VString& dataType) const {
01731     for (VBentoNodePtrVector::const_iterator i = mChildNodes.begin(); i != mChildNodes.end(); ++i) {
01732         if (nodeName.equalsIgnoreCase((*i)->getName())) {
01733             if ((*i)->_findAttribute(attributeName, dataType) != NULL) {
01734                 return (*i);
01735             }
01736         }
01737     }
01738 
01739     return NULL;
01740 }
01741 
01742 int VBentoNode::getInt(const VString& name, int defaultValue) const {
01743     return static_cast<int>(this->getS32(name, static_cast<Vs32>(defaultValue)));
01744 }
01745 
01746 int VBentoNode::getInt(const VString& name) const {
01747     return static_cast<int>(this->getS32(name));
01748 }
01749 
01750 bool VBentoNode::getBool(const VString& name, bool defaultValue) const {
01751     const VBentoBool* attribute = dynamic_cast<const VBentoBool*>(this->_findAttribute(name, VBentoBool::DATA_TYPE_ID()));
01752     return (attribute == NULL) ? defaultValue : attribute->getValue();
01753 }
01754 
01755 bool VBentoNode::getBool(const VString& name) const {
01756     const VBentoBool* attribute = dynamic_cast<const VBentoBool*>(this->_findAttribute(name, VBentoBool::DATA_TYPE_ID()));
01757 
01758     if (attribute == NULL)
01759         throw VBentoNotFoundException(VBentoBool::DATA_TYPE_ID(), name);
01760 
01761     return attribute->getValue();
01762 }
01763 
01764 const VString& VBentoNode::getString(const VString& name, const VString& defaultValue) const {
01765     const VBentoString* attribute = dynamic_cast<const VBentoString*>(this->_findAttribute(name, VBentoString::DATA_TYPE_ID()));
01766     return (attribute == NULL) ? defaultValue : attribute->getValue();
01767 }
01768 
01769 const VString& VBentoNode::getString(const VString& name) const {
01770     const VBentoString* attribute = dynamic_cast<const VBentoString*>(this->_findAttribute(name, VBentoString::DATA_TYPE_ID()));
01771 
01772     if (attribute == NULL)
01773         throw VBentoNotFoundException(VBentoString::DATA_TYPE_ID(), name);
01774 
01775     return attribute->getValue();
01776 }
01777 
01778 const VCodePoint& VBentoNode::getChar(const VString& name, const VCodePoint& defaultValue) const {
01779     const VBentoChar* attribute = dynamic_cast<const VBentoChar*>(this->_findAttribute(name, VBentoChar::DATA_TYPE_ID()));
01780     return (attribute == NULL) ? defaultValue : attribute->getValue();
01781 }
01782 
01783 const VCodePoint& VBentoNode::getChar(const VString& name) const {
01784     const VBentoChar* attribute = dynamic_cast<const VBentoChar*>(this->_findAttribute(name, VBentoChar::DATA_TYPE_ID()));
01785 
01786     if (attribute == NULL)
01787         throw VBentoNotFoundException(VBentoChar::DATA_TYPE_ID(), name);
01788 
01789     return attribute->getValue();
01790 }
01791 
01792 VDouble VBentoNode::getDouble(const VString& name, VDouble defaultValue) const {
01793     const VBentoDouble* attribute = dynamic_cast<const VBentoDouble*>(this->_findAttribute(name, VBentoDouble::DATA_TYPE_ID()));
01794     return (attribute == NULL) ? defaultValue : attribute->getValue();
01795 }
01796 
01797 VDouble VBentoNode::getDouble(const VString& name) const {
01798     const VBentoDouble* attribute = dynamic_cast<const VBentoDouble*>(this->_findAttribute(name, VBentoDouble::DATA_TYPE_ID()));
01799 
01800     if (attribute == NULL)
01801         throw VBentoNotFoundException(VBentoDouble::DATA_TYPE_ID(), name);
01802 
01803     return attribute->getValue();
01804 }
01805 
01806 const VDuration& VBentoNode::getDuration(const VString& name, const VDuration& defaultValue) const {
01807     const VBentoDuration* attribute = dynamic_cast<const VBentoDuration*>(this->_findAttribute(name, VBentoDuration::DATA_TYPE_ID()));
01808     return (attribute == NULL) ? defaultValue : attribute->getValue();
01809 }
01810 
01811 const VDuration& VBentoNode::getDuration(const VString& name) const {
01812     const VBentoDuration* attribute = dynamic_cast<const VBentoDuration*>(this->_findAttribute(name, VBentoDuration::DATA_TYPE_ID()));
01813 
01814     if (attribute == NULL)
01815         throw VBentoNotFoundException(VBentoDuration::DATA_TYPE_ID(), name);
01816 
01817     return attribute->getValue();
01818 }
01819 
01820 const VInstant& VBentoNode::getInstant(const VString& name, const VInstant& defaultValue) const {
01821     const VBentoInstant* attribute = dynamic_cast<const VBentoInstant*>(this->_findAttribute(name, VBentoInstant::DATA_TYPE_ID()));
01822     return (attribute == NULL) ? defaultValue : attribute->getValue();
01823 }
01824 
01825 const VInstant& VBentoNode::getInstant(const VString& name) const {
01826     const VBentoInstant* attribute = dynamic_cast<const VBentoInstant*>(this->_findAttribute(name, VBentoInstant::DATA_TYPE_ID()));
01827 
01828     if (attribute == NULL)
01829         throw VBentoNotFoundException(VBentoInstant::DATA_TYPE_ID(), name);
01830 
01831     return attribute->getValue();
01832 }
01833 
01834 const VSize& VBentoNode::getSize(const VString& name, const VSize& defaultValue) const {
01835     const VBentoSize* attribute = dynamic_cast<const VBentoSize*>(this->_findAttribute(name, VBentoSize::DATA_TYPE_ID()));
01836     return (attribute == NULL) ? defaultValue : attribute->getValue();
01837 }
01838 
01839 const VSize& VBentoNode::getSize(const VString& name) const {
01840     const VBentoSize* attribute = dynamic_cast<const VBentoSize*>(this->_findAttribute(name, VBentoSize::DATA_TYPE_ID()));
01841 
01842     if (attribute == NULL)
01843         throw VBentoNotFoundException(VBentoSize::DATA_TYPE_ID(), name);
01844 
01845     return attribute->getValue();
01846 }
01847 
01848 const VISize& VBentoNode::getISize(const VString& name, const VISize& defaultValue) const {
01849     const VBentoISize* attribute = dynamic_cast<const VBentoISize*>(this->_findAttribute(name, VBentoISize::DATA_TYPE_ID()));
01850     return (attribute == NULL) ? defaultValue : attribute->getValue();
01851 }
01852 
01853 const VISize& VBentoNode::getISize(const VString& name) const {
01854     const VBentoISize* attribute = dynamic_cast<const VBentoISize*>(this->_findAttribute(name, VBentoISize::DATA_TYPE_ID()));
01855 
01856     if (attribute == NULL)
01857         throw VBentoNotFoundException(VBentoISize::DATA_TYPE_ID(), name);
01858 
01859     return attribute->getValue();
01860 }
01861 
01862 const VPoint& VBentoNode::getPoint(const VString& name, const VPoint& defaultValue) const {
01863     const VBentoPoint* attribute = dynamic_cast<const VBentoPoint*>(this->_findAttribute(name, VBentoPoint::DATA_TYPE_ID()));
01864     return (attribute == NULL) ? defaultValue : attribute->getValue();
01865 }
01866 
01867 const VPoint& VBentoNode::getPoint(const VString& name) const {
01868     const VBentoPoint* attribute = dynamic_cast<const VBentoPoint*>(this->_findAttribute(name, VBentoPoint::DATA_TYPE_ID()));
01869 
01870     if (attribute == NULL)
01871         throw VBentoNotFoundException(VBentoPoint::DATA_TYPE_ID(), name);
01872 
01873     return attribute->getValue();
01874 }
01875 
01876 const VIPoint& VBentoNode::getIPoint(const VString& name, const VIPoint& defaultValue) const {
01877     const VBentoIPoint* attribute = dynamic_cast<const VBentoIPoint*>(this->_findAttribute(name, VBentoIPoint::DATA_TYPE_ID()));
01878     return (attribute == NULL) ? defaultValue : attribute->getValue();
01879 }
01880 
01881 const VIPoint& VBentoNode::getIPoint(const VString& name) const {
01882     const VBentoIPoint* attribute = dynamic_cast<const VBentoIPoint*>(this->_findAttribute(name, VBentoIPoint::DATA_TYPE_ID()));
01883 
01884     if (attribute == NULL)
01885         throw VBentoNotFoundException(VBentoIPoint::DATA_TYPE_ID(), name);
01886 
01887     return attribute->getValue();
01888 }
01889 
01890 const VPoint3D& VBentoNode::getPoint3D(const VString& name, const VPoint3D& defaultValue) const {
01891     const VBentoPoint3D* attribute = dynamic_cast<const VBentoPoint3D*>(this->_findAttribute(name, VBentoPoint3D::DATA_TYPE_ID()));
01892     return (attribute == NULL) ? defaultValue : attribute->getValue();
01893 }
01894 
01895 const VPoint3D& VBentoNode::getPoint3D(const VString& name) const {
01896     const VBentoPoint3D* attribute = dynamic_cast<const VBentoPoint3D*>(this->_findAttribute(name, VBentoPoint3D::DATA_TYPE_ID()));
01897 
01898     if (attribute == NULL)
01899         throw VBentoNotFoundException(VBentoPoint3D::DATA_TYPE_ID(), name);
01900 
01901     return attribute->getValue();
01902 }
01903 
01904 const VIPoint3D& VBentoNode::getIPoint3D(const VString& name, const VIPoint3D& defaultValue) const {
01905     const VBentoIPoint3D* attribute = dynamic_cast<const VBentoIPoint3D*>(this->_findAttribute(name, VBentoIPoint3D::DATA_TYPE_ID()));
01906     return (attribute == NULL) ? defaultValue : attribute->getValue();
01907 }
01908 
01909 const VIPoint3D& VBentoNode::getIPoint3D(const VString& name) const {
01910     const VBentoIPoint3D* attribute = dynamic_cast<const VBentoIPoint3D*>(this->_findAttribute(name, VBentoIPoint3D::DATA_TYPE_ID()));
01911 
01912     if (attribute == NULL)
01913         throw VBentoNotFoundException(VBentoIPoint3D::DATA_TYPE_ID(), name);
01914 
01915     return attribute->getValue();
01916 }
01917 
01918 const VLine& VBentoNode::getLine(const VString& name, const VLine& defaultValue) const {
01919     const VBentoLine* attribute = dynamic_cast<const VBentoLine*>(this->_findAttribute(name, VBentoLine::DATA_TYPE_ID()));
01920     return (attribute == NULL) ? defaultValue : attribute->getValue();
01921 }
01922 
01923 const VLine& VBentoNode::getLine(const VString& name) const {
01924     const VBentoLine* attribute = dynamic_cast<const VBentoLine*>(this->_findAttribute(name, VBentoLine::DATA_TYPE_ID()));
01925 
01926     if (attribute == NULL)
01927         throw VBentoNotFoundException(VBentoLine::DATA_TYPE_ID(), name);
01928 
01929     return attribute->getValue();
01930 }
01931 
01932 const VILine& VBentoNode::getILine(const VString& name, const VILine& defaultValue) const {
01933     const VBentoILine* attribute = dynamic_cast<const VBentoILine*>(this->_findAttribute(name, VBentoILine::DATA_TYPE_ID()));
01934     return (attribute == NULL) ? defaultValue : attribute->getValue();
01935 }
01936 
01937 const VILine& VBentoNode::getILine(const VString& name) const {
01938     const VBentoILine* attribute = dynamic_cast<const VBentoILine*>(this->_findAttribute(name, VBentoILine::DATA_TYPE_ID()));
01939 
01940     if (attribute == NULL)
01941         throw VBentoNotFoundException(VBentoILine::DATA_TYPE_ID(), name);
01942 
01943     return attribute->getValue();
01944 }
01945 
01946 const VRect& VBentoNode::getRect(const VString& name, const VRect& defaultValue) const {
01947     const VBentoRect* attribute = dynamic_cast<const VBentoRect*>(this->_findAttribute(name, VBentoRect::DATA_TYPE_ID()));
01948     return (attribute == NULL) ? defaultValue : attribute->getValue();
01949 }
01950 
01951 const VRect& VBentoNode::getRect(const VString& name) const {
01952     const VBentoRect* attribute = dynamic_cast<const VBentoRect*>(this->_findAttribute(name, VBentoRect::DATA_TYPE_ID()));
01953 
01954     if (attribute == NULL)
01955         throw VBentoNotFoundException(VBentoRect::DATA_TYPE_ID(), name);
01956 
01957     return attribute->getValue();
01958 }
01959 
01960 const VIRect& VBentoNode::getIRect(const VString& name, const VIRect& defaultValue) const {
01961     const VBentoIRect* attribute = dynamic_cast<const VBentoIRect*>(this->_findAttribute(name, VBentoIRect::DATA_TYPE_ID()));
01962     return (attribute == NULL) ? defaultValue : attribute->getValue();
01963 }
01964 
01965 const VIRect& VBentoNode::getIRect(const VString& name) const {
01966     const VBentoIRect* attribute = dynamic_cast<const VBentoIRect*>(this->_findAttribute(name, VBentoIRect::DATA_TYPE_ID()));
01967 
01968     if (attribute == NULL)
01969         throw VBentoNotFoundException(VBentoIRect::DATA_TYPE_ID(), name);
01970 
01971     return attribute->getValue();
01972 }
01973 
01974 const VPolygon& VBentoNode::getPolygon(const VString& name, const VPolygon& defaultValue) const {
01975     const VBentoPolygon* attribute = dynamic_cast<const VBentoPolygon*>(this->_findAttribute(name, VBentoPolygon::DATA_TYPE_ID()));
01976     return (attribute == NULL) ? defaultValue : attribute->getValue();
01977 }
01978 
01979 const VPolygon& VBentoNode::getPolygon(const VString& name) const {
01980     const VBentoPolygon* attribute = dynamic_cast<const VBentoPolygon*>(this->_findAttribute(name, VBentoPolygon::DATA_TYPE_ID()));
01981 
01982     if (attribute == NULL)
01983         throw VBentoNotFoundException(VBentoPolygon::DATA_TYPE_ID(), name);
01984 
01985     return attribute->getValue();
01986 }
01987 
01988 const VIPolygon& VBentoNode::getIPolygon(const VString& name, const VIPolygon& defaultValue) const {
01989     const VBentoIPolygon* attribute = dynamic_cast<const VBentoIPolygon*>(this->_findAttribute(name, VBentoIPolygon::DATA_TYPE_ID()));
01990     return (attribute == NULL) ? defaultValue : attribute->getValue();
01991 }
01992 
01993 const VIPolygon& VBentoNode::getIPolygon(const VString& name) const {
01994     const VBentoIPolygon* attribute = dynamic_cast<const VBentoIPolygon*>(this->_findAttribute(name, VBentoIPolygon::DATA_TYPE_ID()));
01995 
01996     if (attribute == NULL)
01997         throw VBentoNotFoundException(VBentoIPolygon::DATA_TYPE_ID(), name);
01998 
01999     return attribute->getValue();
02000 }
02001 
02002 const VColor& VBentoNode::getColor(const VString& name, const VColor& defaultValue) const {
02003     const VBentoColor* attribute = dynamic_cast<const VBentoColor*>(this->_findAttribute(name, VBentoColor::DATA_TYPE_ID()));
02004     return (attribute == NULL) ? defaultValue : attribute->getValue();
02005 }
02006 
02007 const VColor& VBentoNode::getColor(const VString& name) const {
02008     const VBentoColor* attribute = dynamic_cast<const VBentoColor*>(this->_findAttribute(name, VBentoColor::DATA_TYPE_ID()));
02009 
02010     if (attribute == NULL)
02011         throw VBentoNotFoundException(VBentoColor::DATA_TYPE_ID(), name);
02012 
02013     return attribute->getValue();
02014 }
02015 
02016 Vs8 VBentoNode::getS8(const VString& name, Vs8 defaultValue) const {
02017     const VBentoS8* attribute = dynamic_cast<const VBentoS8*>(this->_findAttribute(name, VBentoS8::DATA_TYPE_ID()));
02018     return (attribute == NULL) ? defaultValue : attribute->getValue();
02019 }
02020 
02021 Vs8 VBentoNode::getS8(const VString& name) const {
02022     const VBentoS8* attribute = dynamic_cast<const VBentoS8*>(this->_findAttribute(name, VBentoS8::DATA_TYPE_ID()));
02023 
02024     if (attribute == NULL)
02025         throw VBentoNotFoundException(VBentoS8::DATA_TYPE_ID(), name);
02026 
02027     return attribute->getValue();
02028 }
02029 
02030 Vu8 VBentoNode::getU8(const VString& name, Vu8 defaultValue) const {
02031     const VBentoU8* attribute = dynamic_cast<const VBentoU8*>(this->_findAttribute(name, VBentoU8::DATA_TYPE_ID()));
02032     return (attribute == NULL) ? defaultValue : attribute->getValue();
02033 }
02034 
02035 Vu8 VBentoNode::getU8(const VString& name) const {
02036     const VBentoU8* attribute = dynamic_cast<const VBentoU8*>(this->_findAttribute(name, VBentoU8::DATA_TYPE_ID()));
02037 
02038     if (attribute == NULL)
02039         throw VBentoNotFoundException(VBentoU8::DATA_TYPE_ID(), name);
02040 
02041     return attribute->getValue();
02042 }
02043 
02044 Vs16 VBentoNode::getS16(const VString& name, Vs16 defaultValue) const {
02045     const VBentoS16* attribute = dynamic_cast<const VBentoS16*>(this->_findAttribute(name, VBentoS16::DATA_TYPE_ID()));
02046     return (attribute == NULL) ? defaultValue : attribute->getValue();
02047 }
02048 
02049 Vs16 VBentoNode::getS16(const VString& name) const {
02050     const VBentoS16* attribute = dynamic_cast<const VBentoS16*>(this->_findAttribute(name, VBentoS16::DATA_TYPE_ID()));
02051 
02052     if (attribute == NULL)
02053         throw VBentoNotFoundException(VBentoS16::DATA_TYPE_ID(), name);
02054 
02055     return attribute->getValue();
02056 }
02057 
02058 Vu16 VBentoNode::getU16(const VString& name, Vu16 defaultValue) const {
02059     const VBentoU16* attribute = dynamic_cast<const VBentoU16*>(this->_findAttribute(name, VBentoU16::DATA_TYPE_ID()));
02060     return (attribute == NULL) ? defaultValue : attribute->getValue();
02061 }
02062 
02063 Vu16 VBentoNode::getU16(const VString& name) const {
02064     const VBentoU16* attribute = dynamic_cast<const VBentoU16*>(this->_findAttribute(name, VBentoU16::DATA_TYPE_ID()));
02065 
02066     if (attribute == NULL)
02067         throw VBentoNotFoundException(VBentoU16::DATA_TYPE_ID(), name);
02068 
02069     return attribute->getValue();
02070 }
02071 
02072 Vs32 VBentoNode::getS32(const VString& name, Vs32 defaultValue) const {
02073     const VBentoS32* attribute = dynamic_cast<const VBentoS32*>(this->_findAttribute(name, VBentoS32::DATA_TYPE_ID()));
02074     return (attribute == NULL) ? defaultValue : attribute->getValue();
02075 }
02076 
02077 Vs32 VBentoNode::getS32(const VString& name) const {
02078     const VBentoS32* attribute = dynamic_cast<const VBentoS32*>(this->_findAttribute(name, VBentoS32::DATA_TYPE_ID()));
02079 
02080     if (attribute == NULL)
02081         throw VBentoNotFoundException(VBentoS32::DATA_TYPE_ID(), name);
02082 
02083     return attribute->getValue();
02084 }
02085 
02086 Vu32 VBentoNode::getU32(const VString& name, Vu32 defaultValue) const {
02087     const VBentoU32* attribute = dynamic_cast<const VBentoU32*>(this->_findAttribute(name, VBentoU32::DATA_TYPE_ID()));
02088     return (attribute == NULL) ? defaultValue : attribute->getValue();
02089 }
02090 
02091 Vu32 VBentoNode::getU32(const VString& name) const {
02092     const VBentoU32* attribute = dynamic_cast<const VBentoU32*>(this->_findAttribute(name, VBentoU32::DATA_TYPE_ID()));
02093 
02094     if (attribute == NULL)
02095         throw VBentoNotFoundException(VBentoU32::DATA_TYPE_ID(), name);
02096 
02097     return attribute->getValue();
02098 }
02099 
02100 Vs64 VBentoNode::getS64(const VString& name, Vs64 defaultValue) const {
02101     const VBentoS64* attribute = dynamic_cast<const VBentoS64*>(this->_findAttribute(name, VBentoS64::DATA_TYPE_ID()));
02102     return (attribute == NULL) ? defaultValue : attribute->getValue();
02103 }
02104 
02105 Vs64 VBentoNode::getS64(const VString& name) const {
02106     const VBentoS64* attribute = dynamic_cast<const VBentoS64*>(this->_findAttribute(name, VBentoS64::DATA_TYPE_ID()));
02107 
02108     if (attribute == NULL)
02109         throw VBentoNotFoundException(VBentoS64::DATA_TYPE_ID(), name);
02110 
02111     return attribute->getValue();
02112 }
02113 
02114 Vu64 VBentoNode::getU64(const VString& name, Vu64 defaultValue) const {
02115     const VBentoU64* attribute = dynamic_cast<const VBentoU64*>(this->_findAttribute(name, VBentoU64::DATA_TYPE_ID()));
02116     return (attribute == NULL) ? defaultValue : attribute->getValue();
02117 }
02118 
02119 Vu64 VBentoNode::getU64(const VString& name) const {
02120     const VBentoU64* attribute = dynamic_cast<const VBentoU64*>(this->_findAttribute(name, VBentoU64::DATA_TYPE_ID()));
02121 
02122     if (attribute == NULL)
02123         throw VBentoNotFoundException(VBentoU64::DATA_TYPE_ID(), name);
02124 
02125     return attribute->getValue();
02126 }
02127 
02128 VFloat VBentoNode::getFloat(const VString& name, VFloat defaultValue) const {
02129     const VBentoFloat* attribute = dynamic_cast<const VBentoFloat*>(this->_findAttribute(name, VBentoFloat::DATA_TYPE_ID()));
02130     return (attribute == NULL) ? defaultValue : attribute->getValue();
02131 }
02132 
02133 VFloat VBentoNode::getFloat(const VString& name) const {
02134     const VBentoFloat* attribute = dynamic_cast<const VBentoFloat*>(this->_findAttribute(name, VBentoFloat::DATA_TYPE_ID()));
02135 
02136     if (attribute == NULL)
02137         throw VBentoNotFoundException(VBentoFloat::DATA_TYPE_ID(), name);
02138 
02139     return attribute->getValue();
02140 }
02141 
02142 bool VBentoNode::getBinary(const VString& name, VReadOnlyMemoryStream& returnedReader) const {
02143     const VBentoBinary* attribute = dynamic_cast<const VBentoBinary*>(this->_findAttribute(name, VBentoBinary::DATA_TYPE_ID()));
02144 
02145     if (attribute == NULL)
02146         return false;
02147 
02148     returnedReader = attribute->getReader();
02149     return true;
02150 }
02151 
02152 VReadOnlyMemoryStream VBentoNode::getBinary(const VString& name) const {
02153     const VBentoBinary* attribute = dynamic_cast<const VBentoBinary*>(this->_findAttribute(name, VBentoBinary::DATA_TYPE_ID()));
02154 
02155     if (attribute == NULL)
02156         throw VBentoNotFoundException(VBentoBinary::DATA_TYPE_ID(), name);
02157 
02158     return attribute->getReader();
02159 }
02160 
02161 const Vs8Array& VBentoNode::getS8Array(const VString& name, const Vs8Array& defaultValue) const {
02162     const VBentoS8Array* attribute = dynamic_cast<const VBentoS8Array*>(this->_findAttribute(name, VBentoS8Array::DATA_TYPE_ID()));
02163     return (attribute == NULL) ? defaultValue : attribute->getValue();
02164 }
02165 
02166 const Vs8Array& VBentoNode::getS8Array(const VString& name) const {
02167     const VBentoS8Array* attribute = dynamic_cast<const VBentoS8Array*>(this->_findAttribute(name, VBentoS8Array::DATA_TYPE_ID()));
02168 
02169     if (attribute == NULL)
02170         throw VBentoNotFoundException(VBentoS8Array::DATA_TYPE_ID(), name);
02171 
02172     return attribute->getValue();
02173 }
02174 
02175 const Vs16Array& VBentoNode::getS16Array(const VString& name, const Vs16Array& defaultValue) const {
02176     const VBentoS16Array* attribute = dynamic_cast<const VBentoS16Array*>(this->_findAttribute(name, VBentoS16Array::DATA_TYPE_ID()));
02177     return (attribute == NULL) ? defaultValue : attribute->getValue();
02178 }
02179 
02180 const Vs16Array& VBentoNode::getS16Array(const VString& name) const {
02181     const VBentoS16Array* attribute = dynamic_cast<const VBentoS16Array*>(this->_findAttribute(name, VBentoS16Array::DATA_TYPE_ID()));
02182 
02183     if (attribute == NULL)
02184         throw VBentoNotFoundException(VBentoS16Array::DATA_TYPE_ID(), name);
02185 
02186     return attribute->getValue();
02187 }
02188 
02189 const Vs32Array& VBentoNode::getS32Array(const VString& name, const Vs32Array& defaultValue) const {
02190     const VBentoS32Array* attribute = dynamic_cast<const VBentoS32Array*>(this->_findAttribute(name, VBentoS32Array::DATA_TYPE_ID()));
02191     return (attribute == NULL) ? defaultValue : attribute->getValue();
02192 }
02193 
02194 const Vs32Array& VBentoNode::getS32Array(const VString& name) const {
02195     const VBentoS32Array* attribute = dynamic_cast<const VBentoS32Array*>(this->_findAttribute(name, VBentoS32Array::DATA_TYPE_ID()));
02196 
02197     if (attribute == NULL)
02198         throw VBentoNotFoundException(VBentoS32Array::DATA_TYPE_ID(), name);
02199 
02200     return attribute->getValue();
02201 }
02202 
02203 const Vs64Array& VBentoNode::getS64Array(const VString& name, const Vs64Array& defaultValue) const {
02204     const VBentoS64Array* attribute = dynamic_cast<const VBentoS64Array*>(this->_findAttribute(name, VBentoS64Array::DATA_TYPE_ID()));
02205     return (attribute == NULL) ? defaultValue : attribute->getValue();
02206 }
02207 
02208 const Vs64Array& VBentoNode::getS64Array(const VString& name) const {
02209     const VBentoS64Array* attribute = dynamic_cast<const VBentoS64Array*>(this->_findAttribute(name, VBentoS64Array::DATA_TYPE_ID()));
02210 
02211     if (attribute == NULL)
02212         throw VBentoNotFoundException(VBentoS64Array::DATA_TYPE_ID(), name);
02213 
02214     return attribute->getValue();
02215 }
02216 
02217 const VStringVector& VBentoNode::getStringArray(const VString& name, const VStringVector& defaultValue) const {
02218     const VBentoStringArray* attribute = dynamic_cast<const VBentoStringArray*>(this->_findAttribute(name, VBentoStringArray::DATA_TYPE_ID()));
02219 
02220     if (attribute == NULL)
02221         return defaultValue;
02222 
02223     return attribute->getValue();
02224 }
02225 
02226 const VStringVector& VBentoNode::getStringArray(const VString& name) const {
02227     const VBentoStringArray* attribute = dynamic_cast<const VBentoStringArray*>(this->_findAttribute(name, VBentoStringArray::DATA_TYPE_ID()));
02228 
02229     if (attribute == NULL)
02230         throw VBentoNotFoundException(VBentoStringArray::DATA_TYPE_ID(), name);
02231 
02232     return attribute->getValue();
02233 }
02234 
02235 const VBoolArray& VBentoNode::getBoolArray(const VString& name, const VBoolArray& defaultValue) const {
02236     const VBentoBoolArray* attribute = dynamic_cast<const VBentoBoolArray*>(this->_findAttribute(name, VBentoBoolArray::DATA_TYPE_ID()));
02237     return (attribute == NULL) ? defaultValue : attribute->getValue();
02238 }
02239 
02240 const VBoolArray& VBentoNode::getBoolArray(const VString& name) const {
02241     const VBentoBoolArray* attribute = dynamic_cast<const VBentoBoolArray*>(this->_findAttribute(name, VBentoBoolArray::DATA_TYPE_ID()));
02242 
02243     if (attribute == NULL)
02244         throw VBentoNotFoundException(VBentoBoolArray::DATA_TYPE_ID(), name);
02245 
02246     return attribute->getValue();
02247 }
02248 
02249 const VDoubleArray& VBentoNode::getDoubleArray(const VString& name, const VDoubleArray& defaultValue) const {
02250     const VBentoDoubleArray* attribute = dynamic_cast<const VBentoDoubleArray*>(this->_findAttribute(name, VBentoDoubleArray::DATA_TYPE_ID()));
02251     return (attribute == NULL) ? defaultValue : attribute->getValue();
02252 }
02253 
02254 const VDoubleArray& VBentoNode::getDoubleArray(const VString& name) const {
02255     const VBentoDoubleArray* attribute = dynamic_cast<const VBentoDoubleArray*>(this->_findAttribute(name, VBentoDoubleArray::DATA_TYPE_ID()));
02256 
02257     if (attribute == NULL)
02258         throw VBentoNotFoundException(VBentoDoubleArray::DATA_TYPE_ID(), name);
02259 
02260     return attribute->getValue();
02261 }
02262 
02263 const VDurationVector& VBentoNode::getDurationArray(const VString& name, const VDurationVector& defaultValue) const {
02264     const VBentoDurationArray* attribute = dynamic_cast<const VBentoDurationArray*>(this->_findAttribute(name, VBentoDurationArray::DATA_TYPE_ID()));
02265     return (attribute == NULL) ? defaultValue : attribute->getValue();
02266 }
02267 
02268 const VDurationVector& VBentoNode::getDurationArray(const VString& name) const {
02269     const VBentoDurationArray* attribute = dynamic_cast<const VBentoDurationArray*>(this->_findAttribute(name, VBentoDurationArray::DATA_TYPE_ID()));
02270 
02271     if (attribute == NULL)
02272         throw VBentoNotFoundException(VBentoDurationArray::DATA_TYPE_ID(), name);
02273 
02274     return attribute->getValue();
02275 }
02276 
02277 const VInstantVector& VBentoNode::getInstantArray(const VString& name, const VInstantVector& defaultValue) const {
02278     const VBentoInstantArray* attribute = dynamic_cast<const VBentoInstantArray*>(this->_findAttribute(name, VBentoInstantArray::DATA_TYPE_ID()));
02279     return (attribute == NULL) ? defaultValue : attribute->getValue();
02280 }
02281 
02282 const VInstantVector& VBentoNode::getInstantArray(const VString& name) const {
02283     const VBentoInstantArray* attribute = dynamic_cast<const VBentoInstantArray*>(this->_findAttribute(name, VBentoInstantArray::DATA_TYPE_ID()));
02284 
02285     if (attribute == NULL)
02286         throw VBentoNotFoundException(VBentoInstantArray::DATA_TYPE_ID(), name);
02287 
02288     return attribute->getValue();
02289 }
02290 
02291 void VBentoNode::setInt(const VString& name, int value) {
02292     VBentoS32* attribute = dynamic_cast<VBentoS32*>(this->_findMutableAttribute(name, VBentoS32::DATA_TYPE_ID()));
02293     if (attribute == NULL)
02294         this->addInt(name, value);
02295     else
02296         attribute->setValue(value);
02297 }
02298 
02299 void VBentoNode::setBool(const VString& name, bool value) {
02300     VBentoBool* attribute = dynamic_cast<VBentoBool*>(this->_findMutableAttribute(name, VBentoBool::DATA_TYPE_ID()));
02301     if (attribute == NULL)
02302         this->addBool(name, value);
02303     else
02304         attribute->setValue(value);
02305 }
02306 
02307 void VBentoNode::setString(const VString& name, const VString& value, const VString& encoding) {
02308     VBentoString* attribute = dynamic_cast<VBentoString*>(this->_findMutableAttribute(name, VBentoString::DATA_TYPE_ID()));
02309     if (attribute == NULL) {
02310         this->addString(name, value, encoding);
02311     } else {
02312         attribute->setValue(value);
02313         attribute->setEncoding(encoding);
02314     }
02315 }
02316 
02317 void VBentoNode::setChar(const VString& name, const VCodePoint& value) {
02318     VBentoChar* attribute = dynamic_cast<VBentoChar*>(this->_findMutableAttribute(name, VBentoChar::DATA_TYPE_ID()));
02319     if (attribute == NULL)
02320         this->addChar(name, value);
02321     else
02322         attribute->setValue(value);
02323 }
02324 
02325 void VBentoNode::setDouble(const VString& name, VDouble value) {
02326     VBentoDouble* attribute = dynamic_cast<VBentoDouble*>(this->_findMutableAttribute(name, VBentoDouble::DATA_TYPE_ID()));
02327     if (attribute == NULL)
02328         this->addDouble(name, value);
02329     else
02330         attribute->setValue(value);
02331 }
02332 
02333 void VBentoNode::setDuration(const VString& name, const VDuration& value) {
02334     VBentoDuration* attribute = dynamic_cast<VBentoDuration*>(this->_findMutableAttribute(name, VBentoDuration::DATA_TYPE_ID()));
02335     if (attribute == NULL)
02336         this->addDuration(name, value);
02337     else
02338         attribute->setValue(value);
02339 }
02340 
02341 void VBentoNode::setInstant(const VString& name, const VInstant& value) {
02342     VBentoInstant* attribute = dynamic_cast<VBentoInstant*>(this->_findMutableAttribute(name, VBentoInstant::DATA_TYPE_ID()));
02343     if (attribute == NULL)
02344         this->addInstant(name, value);
02345     else
02346         attribute->setValue(value);
02347 }
02348 
02349 void VBentoNode::setSize(const VString& name, const VSize& value) {
02350     VBentoSize* attribute = dynamic_cast<VBentoSize*>(this->_findMutableAttribute(name, VBentoSize::DATA_TYPE_ID()));
02351     if (attribute == NULL)
02352         this->addSize(name, value);
02353     else
02354         attribute->setValue(value);
02355 }
02356 
02357 void VBentoNode::setISize(const VString& name, const VISize& value) {
02358     VBentoISize* attribute = dynamic_cast<VBentoISize*>(this->_findMutableAttribute(name, VBentoISize::DATA_TYPE_ID()));
02359     if (attribute == NULL)
02360         this->addISize(name, value);
02361     else
02362         attribute->setValue(value);
02363 }
02364 
02365 void VBentoNode::setPoint(const VString& name, const VPoint& value) {
02366     VBentoPoint* attribute = dynamic_cast<VBentoPoint*>(this->_findMutableAttribute(name, VBentoPoint::DATA_TYPE_ID()));
02367     if (attribute == NULL)
02368         this->addPoint(name, value);
02369     else
02370         attribute->setValue(value);
02371 }
02372 
02373 void VBentoNode::setIPoint(const VString& name, const VIPoint& value) {
02374     VBentoIPoint* attribute = dynamic_cast<VBentoIPoint*>(this->_findMutableAttribute(name, VBentoIPoint::DATA_TYPE_ID()));
02375     if (attribute == NULL)
02376         this->addIPoint(name, value);
02377     else
02378         attribute->setValue(value);
02379 }
02380 
02381 void VBentoNode::setPoint3D(const VString& name, const VPoint3D& value) {
02382     VBentoPoint3D* attribute = dynamic_cast<VBentoPoint3D*>(this->_findMutableAttribute(name, VBentoPoint3D::DATA_TYPE_ID()));
02383     if (attribute == NULL)
02384         this->addPoint3D(name, value);
02385     else
02386         attribute->setValue(value);
02387 }
02388 
02389 void VBentoNode::setIPoint3D(const VString& name, const VIPoint3D& value) {
02390     VBentoIPoint3D* attribute = dynamic_cast<VBentoIPoint3D*>(this->_findMutableAttribute(name, VBentoIPoint3D::DATA_TYPE_ID()));
02391     if (attribute == NULL)
02392         this->addIPoint3D(name, value);
02393     else
02394         attribute->setValue(value);
02395 }
02396 
02397 void VBentoNode::setLine(const VString& name, const VLine& value) {
02398     VBentoLine* attribute = dynamic_cast<VBentoLine*>(this->_findMutableAttribute(name, VBentoLine::DATA_TYPE_ID()));
02399     if (attribute == NULL)
02400         this->addLine(name, value);
02401     else
02402         attribute->setValue(value);
02403 }
02404 
02405 void VBentoNode::setILine(const VString& name, const VILine& value) {
02406     VBentoILine* attribute = dynamic_cast<VBentoILine*>(this->_findMutableAttribute(name, VBentoILine::DATA_TYPE_ID()));
02407     if (attribute == NULL)
02408         this->addILine(name, value);
02409     else
02410         attribute->setValue(value);
02411 }
02412 
02413 void VBentoNode::setRect(const VString& name, const VRect& value) {
02414     VBentoRect* attribute = dynamic_cast<VBentoRect*>(this->_findMutableAttribute(name, VBentoRect::DATA_TYPE_ID()));
02415     if (attribute == NULL)
02416         this->addRect(name, value);
02417     else
02418         attribute->setValue(value);
02419 }
02420 
02421 void VBentoNode::setIRect(const VString& name, const VIRect& value) {
02422     VBentoIRect* attribute = dynamic_cast<VBentoIRect*>(this->_findMutableAttribute(name, VBentoIRect::DATA_TYPE_ID()));
02423     if (attribute == NULL)
02424         this->addIRect(name, value);
02425     else
02426         attribute->setValue(value);
02427 }
02428 
02429 void VBentoNode::setPolygon(const VString& name, const VPolygon& value) {
02430     VBentoPolygon* attribute = dynamic_cast<VBentoPolygon*>(this->_findMutableAttribute(name, VBentoPolygon::DATA_TYPE_ID()));
02431     if (attribute == NULL)
02432         this->addPolygon(name, value);
02433     else
02434         attribute->setValue(value);
02435 }
02436 
02437 void VBentoNode::setIPolygon(const VString& name, const VIPolygon& value) {
02438     VBentoIPolygon* attribute = dynamic_cast<VBentoIPolygon*>(this->_findMutableAttribute(name, VBentoIPolygon::DATA_TYPE_ID()));
02439     if (attribute == NULL)
02440         this->addIPolygon(name, value);
02441     else
02442         attribute->setValue(value);
02443 }
02444 
02445 void VBentoNode::setColor(const VString& name, const VColor& value) {
02446     VBentoColor* attribute = dynamic_cast<VBentoColor*>(this->_findMutableAttribute(name, VBentoColor::DATA_TYPE_ID()));
02447     if (attribute == NULL)
02448         this->addColor(name, value);
02449     else
02450         attribute->setValue(value);
02451 }
02452 
02453 void VBentoNode::setS64(const VString& name, Vs64 value) {
02454     VBentoS64* attribute = dynamic_cast<VBentoS64*>(this->_findMutableAttribute(name, VBentoS64::DATA_TYPE_ID()));
02455     if (attribute == NULL)
02456         this->addS64(name, value);
02457     else
02458         attribute->setValue(value);
02459 }
02460 
02461 const VBentoAttributePtrVector& VBentoNode::getAttributes() const {
02462     return mAttributes;
02463 }
02464 
02465 const VString& VBentoNode::getName() const {
02466     return mName;
02467 }
02468 
02469 void VBentoNode::setName(const VString& name) {
02470     mName = name;
02471 }
02472 
02473 void VBentoNode::writeToXMLTextStream(VTextIOStream& stream, bool lineWrap, int indentDepth) const {
02474     _indentIfRequested(stream, lineWrap, indentDepth);
02475     stream.writeString("<");
02476     stream.writeString(mName);
02477 
02478     bool hasArrayAttributes = false;
02479     for (VBentoAttributePtrVector::const_iterator i = mAttributes.begin(); i != mAttributes.end(); ++i) {
02480         if ((*i)->xmlAppearsAsArray()) {
02481             hasArrayAttributes = true;
02482         } else {
02483             stream.writeString(" ");
02484             (*i)->writeToXMLTextStream(stream, lineWrap, indentDepth + 1);
02485         }
02486     }
02487 
02488     if (hasArrayAttributes || (mChildNodes.size() != 0)) {
02489         stream.writeString(">"); // leave tag open for array/child elements
02490     } else {
02491         stream.writeString("/>"); // close tag, we're all done
02492     }
02493 
02494     _lineEndIfRequested(stream, lineWrap);
02495 
02496     // Write any array attributes as child xml nodes.
02497     for (VBentoAttributePtrVector::const_iterator i = mAttributes.begin(); i != mAttributes.end(); ++i) {
02498         if ((*i)->xmlAppearsAsArray()) {
02499             (*i)->writeToXMLTextStream(stream, lineWrap, indentDepth + 1);
02500         }
02501     }
02502 
02503     // Write child nodes as child xml nodes.
02504     for (VBentoNodePtrVector::const_iterator i = mChildNodes.begin(); i != mChildNodes.end(); ++i) {
02505         (*i)->writeToXMLTextStream(stream, lineWrap, indentDepth + 1);
02506     }
02507 
02508     // Close the tag if we left it open for child xml nodes.
02509     if (hasArrayAttributes || (mChildNodes.size() != 0)) {
02510         _writeLineItemToStream(stream, lineWrap, indentDepth, VSTRING_FORMAT("</%s>", mName.chars()));
02511     }
02512 }
02513 
02514 void VBentoNode::printXML() const {
02515     try {
02516         VBufferedFileStream    stdoutStream(stdout, false/*don't close on destruct*/);
02517         VTextIOStream        printStream(stdoutStream, VTextIOStream::kUseUnixLineEndings);
02518 
02519         this->writeToXMLTextStream(printStream);
02520 
02521         stdoutStream.flush();
02522     } catch (const VException& ex) {
02523         std::cout << "VBentoNode::printXML unable to print: '" << ex.what() << "'" << std::endl;
02524     }
02525 }
02526 
02527 void VBentoNode::printHexDump(VHex& hexDump) const {
02528     VMemoryStream   buffer;
02529     VBinaryIOStream stream(buffer);
02530 
02531     VSizeType   numAttributes = mAttributes.size();
02532     VSizeType   numChildNodes = mChildNodes.size();
02533     Vs64        totalSize = this->_calculateContentSize();
02534 
02535     VBentoNode::_writeLengthToStream(stream, totalSize);
02536     stream.writeSize32(numAttributes);
02537     stream.writeSize32(numChildNodes);
02538     stream.writeString(mName);
02539 
02540     hexDump.printHex(buffer.getBuffer(), buffer.getEOFOffset());
02541 
02542     for (VSizeType i = 0; i < numAttributes; ++i)
02543         mAttributes[i]->printHexDump(hexDump);
02544 
02545     for (VSizeType i = 0; i < numChildNodes; ++i)
02546         mChildNodes[i]->printHexDump(hexDump);
02547 }
02548 
02549 Vs64 VBentoNode::_calculateContentSize() const {
02550     Vs64 lengthOfCounters = 8; // 4 bytes each for #attributes and #children
02551     Vs64 lengthOfName = VBentoNode::_getBinaryStringLength(mName);
02552 
02553     Vs64 lengthOfAttributes = 0;
02554     for (VBentoAttributePtrVector::const_iterator i = mAttributes.begin(); i != mAttributes.end(); ++i)
02555         lengthOfAttributes += (*i)->calculateTotalSize();
02556 
02557     Vs64 lengthOfChildren = 0;
02558     for (VBentoNodePtrVector::const_iterator i = mChildNodes.begin(); i != mChildNodes.end(); ++i)
02559         lengthOfChildren += (*i)->_calculateTotalSize();
02560 
02561     Vs64 contentSize = lengthOfCounters + lengthOfName + lengthOfAttributes + lengthOfChildren;
02562 
02563     return contentSize;
02564 }
02565 
02566 Vs64 VBentoNode::_calculateTotalSize() const {
02567     Vs64 contentSize = this->_calculateContentSize();
02568     Vs64 lengthOfLength = VBentoNode::_getLengthOfLength(contentSize);
02569 
02570     return lengthOfLength + contentSize;
02571 }
02572 
02573 void VBentoNode::_addAttribute(VBentoAttribute* attribute) {
02574     mAttributes.push_back(attribute);
02575 }
02576 
02577 const VBentoAttribute* VBentoNode::_findAttribute(const VString& name, const VString& dataType) const {
02578     // Just return from the mutable find, with appropriate cast.
02579     return const_cast<VBentoNode*>(this)->_findMutableAttribute(name, dataType); // const_cast: NON-CONST WRAPPER
02580 }
02581 
02582 VBentoAttribute* VBentoNode::_findMutableAttribute(const VString& name, const VString& dataType) {
02583     for (VBentoAttributePtrVector::const_iterator i = mAttributes.begin(); i != mAttributes.end(); ++i) {
02584         if (name.equalsIgnoreCase((*i)->getName()) &&
02585                 ((*i)->getDataType() == dataType)) {
02586             return (*i);
02587         }
02588     }
02589 
02590     return NULL;
02591 }
02592 
02593 // static
02594 Vs64 VBentoNode::_readLengthFromStream(VBinaryIOStream& stream) {
02595     return stream.readDynamicCount();
02596 }
02597 
02598 // static
02599 void VBentoNode::_writeLengthToStream(VBinaryIOStream& stream, Vs64 length) {
02600     stream.writeDynamicCount(length);
02601 }
02602 
02603 // static
02604 Vs64 VBentoNode::_getLengthOfLength(Vs64 length) {
02605     return VBinaryIOStream::getDynamicCountLength(length);
02606 }
02607 
02608 // static
02609 void VBentoNode::_readFourCharCodeFromStream(VBinaryIOStream& stream, VString& code) {
02610     code.preflight(4);
02611     (void) stream.read(code.getDataBuffer(), CONST_S64(4));
02612     code.postflight(4);
02613 }
02614 
02615 // static
02616 void VBentoNode::_writeFourCharCodeToStream(VBinaryIOStream& stream, const VString& code) {
02617     int codeLength = code.length();
02618 
02619     (void) stream.write(code.getDataBufferConst(), V_MIN(4, codeLength));
02620 
02621     // In case code is less than 4 chars, pad with spaces. Please don't use such codes,
02622     // it's not efficient!
02623     for (int i = codeLength; i < 4; ++i)
02624         stream.writeS8(' ');
02625 }
02626 
02627 // static
02628 Vs64 VBentoNode::_getBinaryStringLength(const VString& s) {
02629     int textLength = s.length();
02630     Vs64 lengthOfLength = VBentoNode::_getLengthOfLength(textLength);
02631 
02632     return lengthOfLength + textLength;
02633 }
02634 
02635 // VBentoUnknownValue --------------------------------------------------------
02636 
02637 VBentoUnknownValue::VBentoUnknownValue(VBinaryIOStream& stream, Vs64 dataLength, const VString& dataType)
02638     : VBentoAttribute(stream, dataType)
02639     , mValue(dataLength)
02640     {
02641     VBinaryIOStream memoryIOStream(mValue);
02642     (void) VStream::streamCopy(stream, memoryIOStream, dataLength);
02643 }
02644 
02645 void VBentoUnknownValue::writeDataToBinaryStream(VBinaryIOStream& stream) const {
02646     // To ensure that there are no side-effects and we are indeed const in behavior,
02647     // we save and restore mValue stream's offset, while doing a const-cast so
02648     // that we are allowed to use manipulate the stream.
02649     Vs64 savedOffset = mValue.getIOOffset();
02650     VBinaryIOStream memoryIOStream(const_cast<VBentoUnknownValue*>(this)->mValue); // const_cast: WORKAROUND. Save/restore state.
02651 
02652     memoryIOStream.seek0();
02653     (void) VStream::streamCopy(memoryIOStream, stream, mValue.getEOFOffset());
02654     memoryIOStream.seek(savedOffset, SEEK_SET);
02655 }
02656 
02657 // VBentoCallbackParser ------------------------------------------------------
02658 
02659 VBentoCallbackParser::VBentoCallbackParser(VBinaryIOStream& stream) {
02660     VBentoCallbackParser::processNode(0, stream);
02661 }
02662 
02663 void VBentoCallbackParser::processNode(int depth, VBinaryIOStream& stream) {
02664     Vs64    theDataLength = VBentoNode::_readLengthFromStream(stream);
02665     Vs32    numAttributes = stream.readS32();
02666     Vs32    numChildNodes = stream.readS32();
02667     VString theName;
02668 
02669     stream.readString(theName);
02670 
02671     this->nodeHeaderComplete(depth, theDataLength, numAttributes, numChildNodes, theName);
02672 
02673     for (int i = 0; i < numAttributes; ++i) {
02674         this->processAttribute(depth, stream);
02675     }
02676 
02677     this->nodeAttributesComplete(depth, theDataLength, numAttributes, numChildNodes, theName);
02678 
02679     for (int i = 0; i < numChildNodes; ++i) {
02680         this->processNode(depth + 1, stream);
02681     }
02682 
02683     this->nodeComplete(depth, theDataLength, numAttributes, numChildNodes, theName);
02684 }
02685 
02686 void VBentoCallbackParser::processAttribute(int depth, VBinaryIOStream& stream) {
02687     Vs64    theDataLength = VBentoNode::_readLengthFromStream(stream);
02688     VString    type;
02689     VString    theName;
02690 
02691     VBentoNode::_readFourCharCodeFromStream(stream, type);
02692     stream.readString(theName);
02693 
02694     this->attributeHeaderComplete(depth, theDataLength, type, theName);
02695 
02696     this->readAttributeData(depth, stream, static_cast<Vu64>(theDataLength));
02697 
02698     this->attributeComplete(depth, theDataLength, type, theName);
02699 }
02700 
02701 void VBentoCallbackParser::nodeHeaderComplete(int /*depth*/, Vs64 /*length*/, Vs32 /*numAttributes*/, Vs32 /*numChildren*/, const VString& /*name*/) {
02702 }
02703 
02704 void VBentoCallbackParser::nodeAttributesComplete(int /*depth*/, Vs64 /*length*/, Vs32 /*numAttributes*/, Vs32 /*numChildren*/, const VString& /*name*/) {
02705 }
02706 
02707 void VBentoCallbackParser::nodeComplete(int /*depth*/, Vs64 /*length*/, Vs32 /*numAttributes*/, Vs32 /*numChildren*/, const VString& /*name*/) {
02708 }
02709 
02710 void VBentoCallbackParser::attributeHeaderComplete(int /*depth*/, Vs64 /*length*/, const VString& /*type*/, const VString& /*name*/) {
02711 }
02712 
02713 void VBentoCallbackParser::attributeComplete(int /*depth*/, Vs64 /*length*/, const VString& /*type*/, const VString& /*name*/) {
02714 }
02715 
02716 void VBentoCallbackParser::readAttributeData(int /*depth*/, VBinaryIOStream& stream, Vu64 dataLength) {
02717     stream.skip(static_cast<Vu64>(dataLength));
02718 }
02719 
02720 // VBentoArray ----------------------------------------------------------------------
02721 
02722 void VBentoArray::_getValueAsBentoTextString(VString& s) const {
02723     int numElements = this->_getNumElements();
02724     if (numElements > 0) {
02725         this->_appendElementBentoText(0, s);
02726         for (int i = 1; i < numElements; ++i) {
02727             s += ',';
02728             this->_appendElementBentoText(i, s);
02729         }
02730     }
02731 }
02732 

Copyright ©1997-2014 Trygve Isaacson. All rights reserved. This documentation was generated with Doxygen.