• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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