1// This file is generated by Values_cpp.template. 2 3// Copyright 2016 The Chromium Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style license that can be 5// found in the LICENSE file. 6 7//#include "Values.h" 8 9{% if config.encoding_lib.header %} 10#include "{{config.encoding_lib.header}}" 11{% endif %} 12 13{% for namespace in config.protocol.namespace %} 14namespace {{namespace}} { 15{% endfor %} 16 17namespace { 18 19const char* const nullValueString = "null"; 20const char* const trueValueString = "true"; 21const char* const falseValueString = "false"; 22 23inline bool escapeChar(uint16_t c, StringBuilder* dst) 24{ 25 switch (c) { 26 case '\b': StringUtil::builderAppend(*dst, "\\b"); break; 27 case '\f': StringUtil::builderAppend(*dst, "\\f"); break; 28 case '\n': StringUtil::builderAppend(*dst, "\\n"); break; 29 case '\r': StringUtil::builderAppend(*dst, "\\r"); break; 30 case '\t': StringUtil::builderAppend(*dst, "\\t"); break; 31 case '\\': StringUtil::builderAppend(*dst, "\\\\"); break; 32 case '"': StringUtil::builderAppend(*dst, "\\\""); break; 33 default: 34 return false; 35 } 36 return true; 37} 38 39const char hexDigits[17] = "0123456789ABCDEF"; 40 41void appendUnsignedAsHex(uint16_t number, StringBuilder* dst) 42{ 43 StringUtil::builderAppend(*dst, "\\u"); 44 for (size_t i = 0; i < 4; ++i) { 45 uint16_t c = hexDigits[(number & 0xF000) >> 12]; 46 StringUtil::builderAppend(*dst, c); 47 number <<= 4; 48 } 49} 50 51template <typename Char> 52void escapeStringForJSONInternal(const Char* str, unsigned len, 53 StringBuilder* dst) 54{ 55 for (unsigned i = 0; i < len; ++i) { 56 Char c = str[i]; 57 if (escapeChar(c, dst)) 58 continue; 59 if (c < 32 || c > 126) { 60 appendUnsignedAsHex(c, dst); 61 } else { 62 StringUtil::builderAppend(*dst, c); 63 } 64 } 65} 66 67// When parsing CBOR, we limit recursion depth for objects and arrays 68// to this constant. 69static constexpr int kStackLimitValues = 1000; 70 71{% if config.encoding_lib.namespace %} 72using {{"::".join(config.encoding_lib.namespace)}}::Error; 73using {{"::".join(config.encoding_lib.namespace)}}::Status; 74using {{"::".join(config.encoding_lib.namespace)}}::span; 75namespace cbor { 76using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::CBORTokenTag; 77using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::CBORTokenizer; 78using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeBinary; 79using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeDouble; 80using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeFalse; 81using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeFromLatin1; 82using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeFromUTF16; 83using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeIndefiniteLengthArrayStart; 84using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeIndefiniteLengthMapStart; 85using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeInt32; 86using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeNull; 87using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeStop; 88using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeString8; 89using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeTrue; 90using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EnvelopeEncoder; 91using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::InitialByteForEnvelope; 92} // namespace cbor 93{% endif %} 94 95// Below are three parsing routines for CBOR, which cover enough 96// to roundtrip JSON messages. 97std::unique_ptr<DictionaryValue> parseMap(int32_t stack_depth, cbor::CBORTokenizer* tokenizer); 98std::unique_ptr<ListValue> parseArray(int32_t stack_depth, cbor::CBORTokenizer* tokenizer); 99std::unique_ptr<Value> parseValue(int32_t stack_depth, cbor::CBORTokenizer* tokenizer); 100 101// |bytes| must start with the indefinite length array byte, so basically, 102// ParseArray may only be called after an indefinite length array has been 103// detected. 104std::unique_ptr<ListValue> parseArray(int32_t stack_depth, cbor::CBORTokenizer* tokenizer) { 105 DCHECK(tokenizer->TokenTag() == cbor::CBORTokenTag::ARRAY_START); 106 tokenizer->Next(); 107 auto list = ListValue::create(); 108 while (tokenizer->TokenTag() != cbor::CBORTokenTag::STOP) { 109 // Error::CBOR_UNEXPECTED_EOF_IN_ARRAY 110 if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE) return nullptr; 111 if (tokenizer->TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr; 112 // Parse value. 113 auto value = parseValue(stack_depth, tokenizer); 114 if (!value) return nullptr; 115 list->pushValue(std::move(value)); 116 } 117 tokenizer->Next(); 118 return list; 119} 120 121std::unique_ptr<Value> parseValue( 122 int32_t stack_depth, cbor::CBORTokenizer* tokenizer) { 123 // Error::CBOR_STACK_LIMIT_EXCEEDED 124 if (stack_depth > kStackLimitValues) return nullptr; 125 // Skip past the envelope to get to what's inside. 126 if (tokenizer->TokenTag() == cbor::CBORTokenTag::ENVELOPE) 127 tokenizer->EnterEnvelope(); 128 switch (tokenizer->TokenTag()) { 129 case cbor::CBORTokenTag::ERROR_VALUE: 130 return nullptr; 131 case cbor::CBORTokenTag::DONE: 132 // Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE 133 return nullptr; 134 case cbor::CBORTokenTag::TRUE_VALUE: { 135 std::unique_ptr<Value> value = FundamentalValue::create(true); 136 tokenizer->Next(); 137 return value; 138 } 139 case cbor::CBORTokenTag::FALSE_VALUE: { 140 std::unique_ptr<Value> value = FundamentalValue::create(false); 141 tokenizer->Next(); 142 return value; 143 } 144 case cbor::CBORTokenTag::NULL_VALUE: { 145 std::unique_ptr<Value> value = FundamentalValue::null(); 146 tokenizer->Next(); 147 return value; 148 } 149 case cbor::CBORTokenTag::INT32: { 150 std::unique_ptr<Value> value = FundamentalValue::create(tokenizer->GetInt32()); 151 tokenizer->Next(); 152 return value; 153 } 154 case cbor::CBORTokenTag::DOUBLE: { 155 std::unique_ptr<Value> value = FundamentalValue::create(tokenizer->GetDouble()); 156 tokenizer->Next(); 157 return value; 158 } 159 case cbor::CBORTokenTag::STRING8: { 160 span<uint8_t> str = tokenizer->GetString8(); 161 std::unique_ptr<Value> value = 162 StringValue::create(StringUtil::fromUTF8(str.data(), str.size())); 163 tokenizer->Next(); 164 return value; 165 } 166 case cbor::CBORTokenTag::STRING16: { 167 span<uint8_t> wire = tokenizer->GetString16WireRep(); 168 DCHECK_EQ(wire.size() & 1, 0u); 169 std::unique_ptr<Value> value = StringValue::create(StringUtil::fromUTF16( 170 reinterpret_cast<const uint16_t*>(wire.data()), wire.size() / 2)); 171 tokenizer->Next(); 172 return value; 173 } 174 case cbor::CBORTokenTag::BINARY: { 175 span<uint8_t> payload = tokenizer->GetBinary(); 176 tokenizer->Next(); 177 return BinaryValue::create(Binary::fromSpan(payload.data(), payload.size())); 178 } 179 case cbor::CBORTokenTag::MAP_START: 180 return parseMap(stack_depth + 1, tokenizer); 181 case cbor::CBORTokenTag::ARRAY_START: 182 return parseArray(stack_depth + 1, tokenizer); 183 default: 184 // Error::CBOR_UNSUPPORTED_VALUE 185 return nullptr; 186 } 187} 188 189// |bytes| must start with the indefinite length array byte, so basically, 190// ParseArray may only be called after an indefinite length array has been 191// detected. 192std::unique_ptr<DictionaryValue> parseMap( 193 int32_t stack_depth, cbor::CBORTokenizer* tokenizer) { 194 auto dict = DictionaryValue::create(); 195 tokenizer->Next(); 196 while (tokenizer->TokenTag() != cbor::CBORTokenTag::STOP) { 197 if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE) { 198 // Error::CBOR_UNEXPECTED_EOF_IN_MAP 199 return nullptr; 200 } 201 if (tokenizer->TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr; 202 // Parse key. 203 String key; 204 if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) { 205 span<uint8_t> key_span = tokenizer->GetString8(); 206 key = StringUtil::fromUTF8(key_span.data(), key_span.size()); 207 tokenizer->Next(); 208 } else if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING16) { 209 span<uint8_t> key_span = tokenizer->GetString16WireRep(); 210 if (key_span.size() & 1) return nullptr; // UTF16 is 2 byte multiple. 211 key = StringUtil::fromUTF16( 212 reinterpret_cast<const uint16_t*>(key_span.data()), 213 key_span.size() / 2); 214 tokenizer->Next(); 215 } else { 216 // Error::CBOR_INVALID_MAP_KEY 217 return nullptr; 218 } 219 // Parse value. 220 auto value = parseValue(stack_depth, tokenizer); 221 if (!value) return nullptr; 222 dict->setValue(key, std::move(value)); 223 } 224 tokenizer->Next(); 225 return dict; 226} 227 228} // anonymous namespace 229 230// static 231std::unique_ptr<Value> Value::parseBinary(const uint8_t* data, size_t size) { 232 span<uint8_t> bytes(data, size); 233 234 // Error::CBOR_NO_INPUT 235 if (bytes.empty()) return nullptr; 236 237 // Error::CBOR_INVALID_START_BYTE 238 if (bytes[0] != cbor::InitialByteForEnvelope()) return nullptr; 239 240 cbor::CBORTokenizer tokenizer(bytes); 241 if (tokenizer.TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr; 242 243 // We checked for the envelope start byte above, so the tokenizer 244 // must agree here, since it's not an error. 245 DCHECK(tokenizer.TokenTag() == cbor::CBORTokenTag::ENVELOPE); 246 tokenizer.EnterEnvelope(); 247 // Error::MAP_START_EXPECTED 248 if (tokenizer.TokenTag() != cbor::CBORTokenTag::MAP_START) return nullptr; 249 std::unique_ptr<Value> result = parseMap(/*stack_depth=*/1, &tokenizer); 250 if (!result) return nullptr; 251 if (tokenizer.TokenTag() == cbor::CBORTokenTag::DONE) return result; 252 if (tokenizer.TokenTag() == cbor::CBORTokenTag::ERROR_VALUE) return nullptr; 253 // Error::CBOR_TRAILING_JUNK 254 return nullptr; 255} 256 257bool Value::asBoolean(bool*) const 258{ 259 return false; 260} 261 262bool Value::asDouble(double*) const 263{ 264 return false; 265} 266 267bool Value::asInteger(int*) const 268{ 269 return false; 270} 271 272bool Value::asString(String*) const 273{ 274 return false; 275} 276 277bool Value::asBinary(Binary*) const 278{ 279 return false; 280} 281 282void Value::writeJSON(StringBuilder* output) const 283{ 284 DCHECK(m_type == TypeNull); 285 StringUtil::builderAppend(*output, nullValueString, 4); 286} 287 288void Value::writeBinary(std::vector<uint8_t>* bytes) const { 289 DCHECK(m_type == TypeNull); 290 bytes->push_back(cbor::EncodeNull()); 291} 292 293std::unique_ptr<Value> Value::clone() const 294{ 295 return Value::null(); 296} 297 298String Value::toJSONString() const 299{ 300 StringBuilder result; 301 StringUtil::builderReserve(result, 512); 302 writeJSON(&result); 303 return StringUtil::builderToString(result); 304} 305 306String Value::serializeToJSON() { 307 return toJSONString(); 308} 309 310std::vector<uint8_t> Value::serializeToBinary() { 311 std::vector<uint8_t> bytes; 312 writeBinary(&bytes); 313 return bytes; 314} 315 316bool FundamentalValue::asBoolean(bool* output) const 317{ 318 if (type() != TypeBoolean) 319 return false; 320 *output = m_boolValue; 321 return true; 322} 323 324bool FundamentalValue::asDouble(double* output) const 325{ 326 if (type() == TypeDouble) { 327 *output = m_doubleValue; 328 return true; 329 } 330 if (type() == TypeInteger) { 331 *output = m_integerValue; 332 return true; 333 } 334 return false; 335} 336 337bool FundamentalValue::asInteger(int* output) const 338{ 339 if (type() != TypeInteger) 340 return false; 341 *output = m_integerValue; 342 return true; 343} 344 345void FundamentalValue::writeJSON(StringBuilder* output) const 346{ 347 DCHECK(type() == TypeBoolean || type() == TypeInteger || type() == TypeDouble); 348 if (type() == TypeBoolean) { 349 if (m_boolValue) 350 StringUtil::builderAppend(*output, trueValueString, 4); 351 else 352 StringUtil::builderAppend(*output, falseValueString, 5); 353 } else if (type() == TypeDouble) { 354 if (!std::isfinite(m_doubleValue)) { 355 StringUtil::builderAppend(*output, nullValueString, 4); 356 return; 357 } 358 StringUtil::builderAppend(*output, StringUtil::fromDouble(m_doubleValue)); 359 } else if (type() == TypeInteger) { 360 StringUtil::builderAppend(*output, StringUtil::fromInteger(m_integerValue)); 361 } 362} 363 364void FundamentalValue::writeBinary(std::vector<uint8_t>* bytes) const { 365 switch (type()) { 366 case TypeDouble: 367 cbor::EncodeDouble(m_doubleValue, bytes); 368 return; 369 case TypeInteger: 370 cbor::EncodeInt32(m_integerValue, bytes); 371 return; 372 case TypeBoolean: 373 bytes->push_back(m_boolValue ? cbor::EncodeTrue() : cbor::EncodeFalse()); 374 return; 375 default: 376 DCHECK(false); 377 } 378} 379 380std::unique_ptr<Value> FundamentalValue::clone() const 381{ 382 switch (type()) { 383 case TypeDouble: return FundamentalValue::create(m_doubleValue); 384 case TypeInteger: return FundamentalValue::create(m_integerValue); 385 case TypeBoolean: return FundamentalValue::create(m_boolValue); 386 default: 387 DCHECK(false); 388 } 389 return nullptr; 390} 391 392bool StringValue::asString(String* output) const 393{ 394 *output = m_stringValue; 395 return true; 396} 397 398void StringValue::writeJSON(StringBuilder* output) const 399{ 400 DCHECK(type() == TypeString); 401 StringUtil::builderAppendQuotedString(*output, m_stringValue); 402} 403 404namespace { 405// This routine distinguishes between the current encoding for a given 406// string |s|, and calls encoding routines that will 407// - Ensure that all ASCII strings end up being encoded as UTF8 in 408// the wire format - e.g., EncodeFromUTF16 will detect ASCII and 409// do the (trivial) transcode to STRING8 on the wire, but if it's 410// not ASCII it'll do STRING16. 411// - Select a format that's cheap to convert to. E.g., we don't 412// have LATIN1 on the wire, so we call EncodeFromLatin1 which 413// transcodes to UTF8 if needed. 414void EncodeString(const String& s, std::vector<uint8_t>* out) { 415 if (StringUtil::CharacterCount(s) == 0) { 416 cbor::EncodeString8(span<uint8_t>(nullptr, 0), out); // Empty string. 417 } else if (StringUtil::CharactersLatin1(s)) { 418 cbor::EncodeFromLatin1(span<uint8_t>(StringUtil::CharactersLatin1(s), 419 StringUtil::CharacterCount(s)), 420 out); 421 } else if (StringUtil::CharactersUTF16(s)) { 422 cbor::EncodeFromUTF16(span<uint16_t>(StringUtil::CharactersUTF16(s), 423 StringUtil::CharacterCount(s)), 424 out); 425 } else if (StringUtil::CharactersUTF8(s)) { 426 cbor::EncodeString8(span<uint8_t>(StringUtil::CharactersUTF8(s), 427 StringUtil::CharacterCount(s)), 428 out); 429 } 430} 431} // namespace 432 433void StringValue::writeBinary(std::vector<uint8_t>* bytes) const { 434 EncodeString(m_stringValue, bytes); 435} 436 437std::unique_ptr<Value> StringValue::clone() const 438{ 439 return StringValue::create(m_stringValue); 440} 441 442bool BinaryValue::asBinary(Binary* output) const 443{ 444 *output = m_binaryValue; 445 return true; 446} 447 448void BinaryValue::writeJSON(StringBuilder* output) const 449{ 450 DCHECK(type() == TypeBinary); 451 StringUtil::builderAppendQuotedString(*output, m_binaryValue.toBase64()); 452} 453 454void BinaryValue::writeBinary(std::vector<uint8_t>* bytes) const { 455 cbor::EncodeBinary(span<uint8_t>(m_binaryValue.data(), 456 m_binaryValue.size()), bytes); 457} 458 459std::unique_ptr<Value> BinaryValue::clone() const 460{ 461 return BinaryValue::create(m_binaryValue); 462} 463 464void SerializedValue::writeJSON(StringBuilder* output) const 465{ 466 DCHECK(type() == TypeSerialized); 467 StringUtil::builderAppend(*output, m_serializedJSON); 468} 469 470void SerializedValue::writeBinary(std::vector<uint8_t>* output) const 471{ 472 DCHECK(type() == TypeSerialized); 473 output->insert(output->end(), m_serializedBinary.begin(), m_serializedBinary.end()); 474} 475 476std::unique_ptr<Value> SerializedValue::clone() const 477{ 478 return std::unique_ptr<SerializedValue>(new SerializedValue(m_serializedJSON, m_serializedBinary)); 479} 480 481DictionaryValue::~DictionaryValue() 482{ 483} 484 485void DictionaryValue::setBoolean(const String& name, bool value) 486{ 487 setValue(name, FundamentalValue::create(value)); 488} 489 490void DictionaryValue::setInteger(const String& name, int value) 491{ 492 setValue(name, FundamentalValue::create(value)); 493} 494 495void DictionaryValue::setDouble(const String& name, double value) 496{ 497 setValue(name, FundamentalValue::create(value)); 498} 499 500void DictionaryValue::setString(const String& name, const String& value) 501{ 502 setValue(name, StringValue::create(value)); 503} 504 505void DictionaryValue::setValue(const String& name, std::unique_ptr<Value> value) 506{ 507 set(name, value); 508} 509 510void DictionaryValue::setObject(const String& name, std::unique_ptr<DictionaryValue> value) 511{ 512 set(name, value); 513} 514 515void DictionaryValue::setArray(const String& name, std::unique_ptr<ListValue> value) 516{ 517 set(name, value); 518} 519 520bool DictionaryValue::getBoolean(const String& name, bool* output) const 521{ 522 protocol::Value* value = get(name); 523 if (!value) 524 return false; 525 return value->asBoolean(output); 526} 527 528bool DictionaryValue::getInteger(const String& name, int* output) const 529{ 530 Value* value = get(name); 531 if (!value) 532 return false; 533 return value->asInteger(output); 534} 535 536bool DictionaryValue::getDouble(const String& name, double* output) const 537{ 538 Value* value = get(name); 539 if (!value) 540 return false; 541 return value->asDouble(output); 542} 543 544bool DictionaryValue::getString(const String& name, String* output) const 545{ 546 protocol::Value* value = get(name); 547 if (!value) 548 return false; 549 return value->asString(output); 550} 551 552DictionaryValue* DictionaryValue::getObject(const String& name) const 553{ 554 return DictionaryValue::cast(get(name)); 555} 556 557protocol::ListValue* DictionaryValue::getArray(const String& name) const 558{ 559 return ListValue::cast(get(name)); 560} 561 562protocol::Value* DictionaryValue::get(const String& name) const 563{ 564 Dictionary::const_iterator it = m_data.find(name); 565 if (it == m_data.end()) 566 return nullptr; 567 return it->second.get(); 568} 569 570DictionaryValue::Entry DictionaryValue::at(size_t index) const 571{ 572 const String key = m_order[index]; 573 return std::make_pair(key, m_data.find(key)->second.get()); 574} 575 576bool DictionaryValue::booleanProperty(const String& name, bool defaultValue) const 577{ 578 bool result = defaultValue; 579 getBoolean(name, &result); 580 return result; 581} 582 583int DictionaryValue::integerProperty(const String& name, int defaultValue) const 584{ 585 int result = defaultValue; 586 getInteger(name, &result); 587 return result; 588} 589 590double DictionaryValue::doubleProperty(const String& name, double defaultValue) const 591{ 592 double result = defaultValue; 593 getDouble(name, &result); 594 return result; 595} 596 597void DictionaryValue::remove(const String& name) 598{ 599 m_data.erase(name); 600 m_order.erase(std::remove(m_order.begin(), m_order.end(), name), m_order.end()); 601} 602 603void DictionaryValue::writeJSON(StringBuilder* output) const 604{ 605 StringUtil::builderAppend(*output, '{'); 606 for (size_t i = 0; i < m_order.size(); ++i) { 607 Dictionary::const_iterator it = m_data.find(m_order[i]); 608 CHECK(it != m_data.end()); 609 if (i) 610 StringUtil::builderAppend(*output, ','); 611 StringUtil::builderAppendQuotedString(*output, it->first); 612 StringUtil::builderAppend(*output, ':'); 613 it->second->writeJSON(output); 614 } 615 StringUtil::builderAppend(*output, '}'); 616} 617 618void DictionaryValue::writeBinary(std::vector<uint8_t>* bytes) const { 619 cbor::EnvelopeEncoder encoder; 620 encoder.EncodeStart(bytes); 621 bytes->push_back(cbor::EncodeIndefiniteLengthMapStart()); 622 for (size_t i = 0; i < m_order.size(); ++i) { 623 const String& key = m_order[i]; 624 Dictionary::const_iterator value = m_data.find(key); 625 DCHECK(value != m_data.cend() && value->second); 626 EncodeString(key, bytes); 627 value->second->writeBinary(bytes); 628 } 629 bytes->push_back(cbor::EncodeStop()); 630 encoder.EncodeStop(bytes); 631} 632 633std::unique_ptr<Value> DictionaryValue::clone() const 634{ 635 std::unique_ptr<DictionaryValue> result = DictionaryValue::create(); 636 for (size_t i = 0; i < m_order.size(); ++i) { 637 String key = m_order[i]; 638 Dictionary::const_iterator value = m_data.find(key); 639 DCHECK(value != m_data.cend() && value->second); 640 result->setValue(key, value->second->clone()); 641 } 642 return result; 643} 644 645DictionaryValue::DictionaryValue() 646 : Value(TypeObject) 647{ 648} 649 650ListValue::~ListValue() 651{ 652} 653 654void ListValue::writeJSON(StringBuilder* output) const 655{ 656 StringUtil::builderAppend(*output, '['); 657 bool first = true; 658 for (const std::unique_ptr<protocol::Value>& value : m_data) { 659 if (!first) 660 StringUtil::builderAppend(*output, ','); 661 value->writeJSON(output); 662 first = false; 663 } 664 StringUtil::builderAppend(*output, ']'); 665} 666 667void ListValue::writeBinary(std::vector<uint8_t>* bytes) const { 668 cbor::EnvelopeEncoder encoder; 669 encoder.EncodeStart(bytes); 670 bytes->push_back(cbor::EncodeIndefiniteLengthArrayStart()); 671 for (size_t i = 0; i < m_data.size(); ++i) { 672 m_data[i]->writeBinary(bytes); 673 } 674 bytes->push_back(cbor::EncodeStop()); 675 encoder.EncodeStop(bytes); 676} 677 678std::unique_ptr<Value> ListValue::clone() const 679{ 680 std::unique_ptr<ListValue> result = ListValue::create(); 681 for (const std::unique_ptr<protocol::Value>& value : m_data) 682 result->pushValue(value->clone()); 683 return result; 684} 685 686ListValue::ListValue() 687 : Value(TypeArray) 688{ 689} 690 691void ListValue::pushValue(std::unique_ptr<protocol::Value> value) 692{ 693 DCHECK(value); 694 m_data.push_back(std::move(value)); 695} 696 697protocol::Value* ListValue::at(size_t index) 698{ 699 DCHECK_LT(index, m_data.size()); 700 return m_data[index].get(); 701} 702 703void escapeLatinStringForJSON(const uint8_t* str, unsigned len, StringBuilder* dst) 704{ 705 escapeStringForJSONInternal<uint8_t>(str, len, dst); 706} 707 708void escapeWideStringForJSON(const uint16_t* str, unsigned len, StringBuilder* dst) 709{ 710 escapeStringForJSONInternal<uint16_t>(str, len, dst); 711} 712 713{% for namespace in config.protocol.namespace %} 714} // namespace {{namespace}} 715{% endfor %} 716