Vault
4.1
|
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("&"); 00791 static VString XML_APOSTROPHE_ESCAPE("'"); 00792 static VString XML_DOUBLEQUOTE_ESCAPE("""); 00793 static VString XML_LESSTHAN_ESCAPE("<"); 00794 static VString XML_GREATERTHAN_ESCAPE(">"); 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); // & -> & 00812 } else if (c == '\'') { 00813 i += _replaceCharWithString(text, i, XML_APOSTROPHE_ESCAPE); // ' -> ' 00814 } else if (c == '\"') { 00815 i += _replaceCharWithString(text, i, XML_DOUBLEQUOTE_ESCAPE); // " -> " 00816 } else if (c == '<') { 00817 i += _replaceCharWithString(text, i, XML_LESSTHAN_ESCAPE); // < -> < 00818 } else if (c == '>') { 00819 i += _replaceCharWithString(text, i, XML_GREATERTHAN_ESCAPE); // > -> > 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