~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebCore/inspector/InspectorValues.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Google Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions are
 
6
 * met:
 
7
 *
 
8
 *     * Redistributions of source code must retain the above copyright
 
9
 * notice, this list of conditions and the following disclaimer.
 
10
 *     * Redistributions in binary form must reproduce the above
 
11
 * copyright notice, this list of conditions and the following disclaimer
 
12
 * in the documentation and/or other materials provided with the
 
13
 * distribution.
 
14
 *     * Neither the name of Google Inc. nor the names of its
 
15
 * contributors may be used to endorse or promote products derived from
 
16
 * this software without specific prior written permission.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
19
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
20
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
21
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
22
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
23
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
24
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
28
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 */
 
30
 
 
31
#include "config.h"
 
32
#include "InspectorValues.h"
 
33
 
 
34
#include <wtf/DecimalNumber.h>
 
35
#include <wtf/dtoa.h>
 
36
#include <wtf/text/StringBuilder.h>
 
37
 
 
38
namespace WebCore {
 
39
 
 
40
namespace {
 
41
 
 
42
static const int stackLimit = 1000;
 
43
 
 
44
enum Token {
 
45
    OBJECT_BEGIN,
 
46
    OBJECT_END,
 
47
    ARRAY_BEGIN,
 
48
    ARRAY_END,
 
49
    STRING,
 
50
    NUMBER,
 
51
    BOOL_TRUE,
 
52
    BOOL_FALSE,
 
53
    NULL_TOKEN,
 
54
    LIST_SEPARATOR,
 
55
    OBJECT_PAIR_SEPARATOR,
 
56
    INVALID_TOKEN,
 
57
};
 
58
 
 
59
const char* const nullString = "null";
 
60
const char* const trueString = "true";
 
61
const char* const falseString = "false";
 
62
 
 
63
bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEnd, const char* token)
 
64
{
 
65
    while (start < end && *token != '\0' && *start++ == *token++) { }
 
66
    if (*token != '\0')
 
67
        return false;
 
68
    *tokenEnd = start;
 
69
    return true;
 
70
}
 
71
 
 
72
bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros)
 
73
{
 
74
    if (start == end)
 
75
        return false;
 
76
    bool haveLeadingZero = '0' == *start;
 
77
    int length = 0;
 
78
    while (start < end && '0' <= *start && *start <= '9') {
 
79
        ++start;
 
80
        ++length;
 
81
    }
 
82
    if (!length)
 
83
        return false;
 
84
    if (!canHaveLeadingZeros && length > 1 && haveLeadingZero)
 
85
        return false;
 
86
    *tokenEnd = start;
 
87
    return true;
 
88
}
 
89
 
 
90
bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
 
91
{
 
92
    // We just grab the number here.  We validate the size in DecodeNumber.
 
93
    // According   to RFC4627, a valid number is: [minus] int [frac] [exp]
 
94
    if (start == end)
 
95
        return false;
 
96
    UChar c = *start;
 
97
    if ('-' == c)
 
98
        ++start;
 
99
 
 
100
    if (!readInt(start, end, &start, false))
 
101
        return false;
 
102
    if (start == end) {
 
103
        *tokenEnd = start;
 
104
        return true;
 
105
    }
 
106
 
 
107
    // Optional fraction part
 
108
    c = *start;
 
109
    if ('.' == c) {
 
110
        ++start;
 
111
        if (!readInt(start, end, &start, true))
 
112
            return false;
 
113
        if (start == end) {
 
114
            *tokenEnd = start;
 
115
            return true;
 
116
        }
 
117
        c = *start;
 
118
    }
 
119
 
 
120
    // Optional exponent part
 
121
    if ('e' == c || 'E' == c) {
 
122
        ++start;
 
123
        if (start == end)
 
124
            return false;
 
125
        c = *start;
 
126
        if ('-' == c || '+' == c) {
 
127
            ++start;
 
128
            if (start == end)
 
129
                return false;
 
130
        }
 
131
        if (!readInt(start, end, &start, true))
 
132
            return false;
 
133
    }
 
134
 
 
135
    *tokenEnd = start;
 
136
    return true;
 
137
}
 
138
 
 
139
bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits)
 
140
{
 
141
    if (end - start < digits)
 
142
        return false;
 
143
    for (int i = 0; i < digits; ++i) {
 
144
        UChar c = *start++;
 
145
        if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')))
 
146
            return false;
 
147
    }
 
148
    *tokenEnd = start;
 
149
    return true;
 
150
}
 
151
 
 
152
bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
 
153
{
 
154
    while (start < end) {
 
155
        UChar c = *start++;
 
156
        if ('\\' == c) {
 
157
            c = *start++;
 
158
            // Make sure the escaped char is valid.
 
159
            switch (c) {
 
160
            case 'x':
 
161
                if (!readHexDigits(start, end, &start, 2))
 
162
                    return false;
 
163
                break;
 
164
            case 'u':
 
165
                if (!readHexDigits(start, end, &start, 4))
 
166
                    return false;
 
167
                break;
 
168
            case '\\':
 
169
            case '/':
 
170
            case 'b':
 
171
            case 'f':
 
172
            case 'n':
 
173
            case 'r':
 
174
            case 't':
 
175
            case 'v':
 
176
            case '"':
 
177
                break;
 
178
            default:
 
179
                return false;
 
180
            }
 
181
        } else if ('"' == c) {
 
182
            *tokenEnd = start;
 
183
            return true;
 
184
        }
 
185
    }
 
186
    return false;
 
187
}
 
188
 
 
189
Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, const UChar** tokenEnd)
 
190
{
 
191
    while (start < end && isSpaceOrNewline(*start))
 
192
        ++start;
 
193
 
 
194
    if (start == end)
 
195
        return INVALID_TOKEN;
 
196
 
 
197
    *tokenStart = start;
 
198
 
 
199
    switch (*start) {
 
200
    case 'n':
 
201
        if (parseConstToken(start, end, tokenEnd, nullString))
 
202
            return NULL_TOKEN;
 
203
        break;
 
204
    case 't':
 
205
        if (parseConstToken(start, end, tokenEnd, trueString))
 
206
            return BOOL_TRUE;
 
207
        break;
 
208
    case 'f':
 
209
        if (parseConstToken(start, end, tokenEnd, falseString))
 
210
            return BOOL_FALSE;
 
211
        break;
 
212
    case '[':
 
213
        *tokenEnd = start + 1;
 
214
        return ARRAY_BEGIN;
 
215
    case ']':
 
216
        *tokenEnd = start + 1;
 
217
        return ARRAY_END;
 
218
    case ',':
 
219
        *tokenEnd = start + 1;
 
220
        return LIST_SEPARATOR;
 
221
    case '{':
 
222
        *tokenEnd = start + 1;
 
223
        return OBJECT_BEGIN;
 
224
    case '}':
 
225
        *tokenEnd = start + 1;
 
226
        return OBJECT_END;
 
227
    case ':':
 
228
        *tokenEnd = start + 1;
 
229
        return OBJECT_PAIR_SEPARATOR;
 
230
    case '0':
 
231
    case '1':
 
232
    case '2':
 
233
    case '3':
 
234
    case '4':
 
235
    case '5':
 
236
    case '6':
 
237
    case '7':
 
238
    case '8':
 
239
    case '9':
 
240
    case '-':
 
241
        if (parseNumberToken(start, end, tokenEnd))
 
242
            return NUMBER;
 
243
        break;
 
244
    case '"':
 
245
        if (parseStringToken(start + 1, end, tokenEnd))
 
246
            return STRING;
 
247
        break;
 
248
    }
 
249
    return INVALID_TOKEN;
 
250
}
 
251
 
 
252
inline int hexToInt(UChar c)
 
253
{
 
254
    if ('0' <= c && c <= '9')
 
255
        return c - '0';
 
256
    if ('A' <= c && c <= 'F')
 
257
        return c - 'A' + 10;
 
258
    if ('a' <= c && c <= 'f')
 
259
        return c - 'a' + 10;
 
260
    ASSERT_NOT_REACHED();
 
261
    return 0;
 
262
}
 
263
 
 
264
bool decodeString(const UChar* start, const UChar* end, StringBuilder* output)
 
265
{
 
266
    while (start < end) {
 
267
        UChar c = *start++;
 
268
        if ('\\' != c) {
 
269
            output->append(c);
 
270
            continue;
 
271
        }
 
272
        c = *start++;
 
273
        switch (c) {
 
274
        case '"':
 
275
        case '/':
 
276
        case '\\':
 
277
            break;
 
278
        case 'b':
 
279
            c = '\b';
 
280
            break;
 
281
        case 'f':
 
282
            c = '\f';
 
283
            break;
 
284
        case 'n':
 
285
            c = '\n';
 
286
            break;
 
287
        case 'r':
 
288
            c = '\r';
 
289
            break;
 
290
        case 't':
 
291
            c = '\t';
 
292
            break;
 
293
        case 'v':
 
294
            c = '\v';
 
295
            break;
 
296
        case 'x':
 
297
            c = (hexToInt(*start) << 4) +
 
298
                hexToInt(*(start + 1));
 
299
            start += 2;
 
300
            break;
 
301
        case 'u':
 
302
            c = (hexToInt(*start) << 12) +
 
303
                (hexToInt(*(start + 1)) << 8) +
 
304
                (hexToInt(*(start + 2)) << 4) +
 
305
                hexToInt(*(start + 3));
 
306
            start += 4;
 
307
            break;
 
308
        default:
 
309
            return false;
 
310
        }
 
311
        output->append(c);
 
312
    }
 
313
    return true;
 
314
}
 
315
 
 
316
bool decodeString(const UChar* start, const UChar* end, String* output)
 
317
{
 
318
    if (start == end) {
 
319
        *output = "";
 
320
        return true;
 
321
    }
 
322
    if (start > end)
 
323
        return false;
 
324
    StringBuilder buffer;
 
325
    buffer.reserveCapacity(end - start);
 
326
    if (!decodeString(start, end, &buffer))
 
327
        return false;
 
328
    *output = buffer.toString();
 
329
    return true;
 
330
}
 
331
 
 
332
PassRefPtr<InspectorValue> buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth)
 
333
{
 
334
    if (depth > stackLimit)
 
335
        return 0;
 
336
 
 
337
    RefPtr<InspectorValue> result;
 
338
    const UChar* tokenStart;
 
339
    const UChar* tokenEnd;
 
340
    Token token = parseToken(start, end, &tokenStart, &tokenEnd);
 
341
    switch (token) {
 
342
    case INVALID_TOKEN:
 
343
        return 0;
 
344
    case NULL_TOKEN:
 
345
        result = InspectorValue::null();
 
346
        break;
 
347
    case BOOL_TRUE:
 
348
        result = InspectorBasicValue::create(true);
 
349
        break;
 
350
    case BOOL_FALSE:
 
351
        result = InspectorBasicValue::create(false);
 
352
        break;
 
353
    case NUMBER: {
 
354
        bool ok;
 
355
        double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok);
 
356
        if (!ok)
 
357
            return 0;
 
358
        result = InspectorBasicValue::create(value);
 
359
        break;
 
360
    }
 
361
    case STRING: {
 
362
        String value;
 
363
        bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value);
 
364
        if (!ok)
 
365
            return 0;
 
366
        result = InspectorString::create(value);
 
367
        break;
 
368
    }
 
369
    case ARRAY_BEGIN: {
 
370
        RefPtr<InspectorArray> array = InspectorArray::create();
 
371
        start = tokenEnd;
 
372
        token = parseToken(start, end, &tokenStart, &tokenEnd);
 
373
        while (token != ARRAY_END) {
 
374
            RefPtr<InspectorValue> arrayNode = buildValue(start, end, &tokenEnd, depth + 1);
 
375
            if (!arrayNode)
 
376
                return 0;
 
377
            array->pushValue(arrayNode);
 
378
 
 
379
            // After a list value, we expect a comma or the end of the list.
 
380
            start = tokenEnd;
 
381
            token = parseToken(start, end, &tokenStart, &tokenEnd);
 
382
            if (token == LIST_SEPARATOR) {
 
383
                start = tokenEnd;
 
384
                token = parseToken(start, end, &tokenStart, &tokenEnd);
 
385
                if (token == ARRAY_END)
 
386
                    return 0;
 
387
            } else if (token != ARRAY_END) {
 
388
                // Unexpected value after list value.  Bail out.
 
389
                return 0;
 
390
            }
 
391
        }
 
392
        if (token != ARRAY_END)
 
393
            return 0;
 
394
        result = array.release();
 
395
        break;
 
396
    }
 
397
    case OBJECT_BEGIN: {
 
398
        RefPtr<InspectorObject> object = InspectorObject::create();
 
399
        start = tokenEnd;
 
400
        token = parseToken(start, end, &tokenStart, &tokenEnd);
 
401
        while (token != OBJECT_END) {
 
402
            if (token != STRING)
 
403
                return 0;
 
404
            String key;
 
405
            if (!decodeString(tokenStart + 1, tokenEnd - 1, &key))
 
406
                return 0;
 
407
            start = tokenEnd;
 
408
 
 
409
            token = parseToken(start, end, &tokenStart, &tokenEnd);
 
410
            if (token != OBJECT_PAIR_SEPARATOR)
 
411
                return 0;
 
412
            start = tokenEnd;
 
413
 
 
414
            RefPtr<InspectorValue> value = buildValue(start, end, &tokenEnd, depth + 1);
 
415
            if (!value)
 
416
                return 0;
 
417
            object->setValue(key, value);
 
418
            start = tokenEnd;
 
419
 
 
420
            // After a key/value pair, we expect a comma or the end of the
 
421
            // object.
 
422
            token = parseToken(start, end, &tokenStart, &tokenEnd);
 
423
            if (token == LIST_SEPARATOR) {
 
424
                start = tokenEnd;
 
425
                token = parseToken(start, end, &tokenStart, &tokenEnd);
 
426
                 if (token == OBJECT_END)
 
427
                    return 0;
 
428
            } else if (token != OBJECT_END) {
 
429
                // Unexpected value after last object value.  Bail out.
 
430
                return 0;
 
431
            }
 
432
        }
 
433
        if (token != OBJECT_END)
 
434
            return 0;
 
435
        result = object.release();
 
436
        break;
 
437
    }
 
438
 
 
439
    default:
 
440
        // We got a token that's not a value.
 
441
        return 0;
 
442
    }
 
443
    *valueTokenEnd = tokenEnd;
 
444
    return result.release();
 
445
}
 
446
 
 
447
inline bool escapeChar(UChar c, StringBuilder* dst)
 
448
{
 
449
    switch (c) {
 
450
    case '\b': dst->append("\\b", 2); break;
 
451
    case '\f': dst->append("\\f", 2); break;
 
452
    case '\n': dst->append("\\n", 2); break;
 
453
    case '\r': dst->append("\\r", 2); break;
 
454
    case '\t': dst->append("\\t", 2); break;
 
455
    case '\\': dst->append("\\\\", 2); break;
 
456
    case '"': dst->append("\\\"", 2); break;
 
457
    default:
 
458
        return false;
 
459
    }
 
460
    return true;
 
461
}
 
462
 
 
463
inline void doubleQuoteString(const String& str, StringBuilder* dst)
 
464
{
 
465
    dst->append('"');
 
466
    for (unsigned i = 0; i < str.length(); ++i) {
 
467
        UChar c = str[i];
 
468
        if (!escapeChar(c, dst)) {
 
469
            if (c < 32 || c > 126 || c == '<' || c == '>') {
 
470
                // 1. Escaping <, > to prevent script execution.
 
471
                // 2. Technically, we could also pass through c > 126 as UTF8, but this
 
472
                //    is also optional.  It would also be a pain to implement here.
 
473
                unsigned int symbol = static_cast<unsigned int>(c);
 
474
                String symbolCode = String::format("\\u%04X", symbol);
 
475
                dst->append(symbolCode.characters(), symbolCode.length());
 
476
            } else
 
477
                dst->append(c);
 
478
        }
 
479
    }
 
480
    dst->append('"');
 
481
}
 
482
 
 
483
} // anonymous namespace
 
484
 
 
485
bool InspectorValue::asBoolean(bool*) const
 
486
{
 
487
    return false;
 
488
}
 
489
 
 
490
bool InspectorValue::asNumber(double*) const
 
491
{
 
492
    return false;
 
493
}
 
494
 
 
495
bool InspectorValue::asNumber(long*) const
 
496
{
 
497
    return false;
 
498
}
 
499
 
 
500
bool InspectorValue::asNumber(int*) const
 
501
{
 
502
    return false;
 
503
}
 
504
 
 
505
bool InspectorValue::asNumber(unsigned long*) const
 
506
{
 
507
    return false;
 
508
}
 
509
 
 
510
bool InspectorValue::asNumber(unsigned int*) const
 
511
{
 
512
    return false;
 
513
}
 
514
 
 
515
bool InspectorValue::asString(String*) const
 
516
{
 
517
    return false;
 
518
}
 
519
 
 
520
bool InspectorValue::asValue(RefPtr<InspectorValue>* output)
 
521
{
 
522
    *output = this;
 
523
    return true;
 
524
}
 
525
 
 
526
bool InspectorValue::asObject(RefPtr<InspectorObject>*)
 
527
{
 
528
    return false;
 
529
}
 
530
 
 
531
bool InspectorValue::asArray(RefPtr<InspectorArray>*)
 
532
{
 
533
    return false;
 
534
}
 
535
 
 
536
PassRefPtr<InspectorObject> InspectorValue::asObject()
 
537
{
 
538
    return 0;
 
539
}
 
540
 
 
541
PassRefPtr<InspectorArray> InspectorValue::asArray()
 
542
{
 
543
    return 0;
 
544
}
 
545
 
 
546
PassRefPtr<InspectorValue> InspectorValue::parseJSON(const String& json)
 
547
{
 
548
    const UChar* start = json.characters();
 
549
    const UChar* end = json.characters() + json.length();
 
550
    const UChar *tokenEnd;
 
551
    RefPtr<InspectorValue> value = buildValue(start, end, &tokenEnd, 0);
 
552
    if (!value || tokenEnd != end)
 
553
        return 0;
 
554
    return value.release();
 
555
}
 
556
 
 
557
String InspectorValue::toJSONString() const
 
558
{
 
559
    StringBuilder result;
 
560
    result.reserveCapacity(512);
 
561
    writeJSON(&result);
 
562
    return result.toString();
 
563
}
 
564
 
 
565
void InspectorValue::writeJSON(StringBuilder* output) const
 
566
{
 
567
    ASSERT(m_type == TypeNull);
 
568
    output->append(nullString, 4);
 
569
}
 
570
 
 
571
bool InspectorBasicValue::asBoolean(bool* output) const
 
572
{
 
573
    if (type() != TypeBoolean)
 
574
        return false;
 
575
    *output = m_boolValue;
 
576
    return true;
 
577
}
 
578
 
 
579
bool InspectorBasicValue::asNumber(double* output) const
 
580
{
 
581
    if (type() != TypeNumber)
 
582
        return false;
 
583
    *output = m_doubleValue;
 
584
    return true;
 
585
}
 
586
 
 
587
bool InspectorBasicValue::asNumber(long* output) const
 
588
{
 
589
    if (type() != TypeNumber)
 
590
        return false;
 
591
    *output = static_cast<long>(m_doubleValue);
 
592
    return true;
 
593
}
 
594
 
 
595
bool InspectorBasicValue::asNumber(int* output) const
 
596
{
 
597
    if (type() != TypeNumber)
 
598
        return false;
 
599
    *output = static_cast<int>(m_doubleValue);
 
600
    return true;
 
601
}
 
602
 
 
603
bool InspectorBasicValue::asNumber(unsigned long* output) const
 
604
{
 
605
    if (type() != TypeNumber)
 
606
        return false;
 
607
    *output = static_cast<unsigned long>(m_doubleValue);
 
608
    return true;
 
609
}
 
610
 
 
611
bool InspectorBasicValue::asNumber(unsigned int* output) const
 
612
{
 
613
    if (type() != TypeNumber)
 
614
        return false;
 
615
    *output = static_cast<unsigned int>(m_doubleValue);
 
616
    return true;
 
617
}
 
618
 
 
619
void InspectorBasicValue::writeJSON(StringBuilder* output) const
 
620
{
 
621
    ASSERT(type() == TypeBoolean || type() == TypeNumber);
 
622
    if (type() == TypeBoolean) {
 
623
        if (m_boolValue)
 
624
            output->append(trueString, 4);
 
625
        else
 
626
            output->append(falseString, 5);
 
627
    } else if (type() == TypeNumber) {
 
628
        NumberToLStringBuffer buffer;
 
629
        if (!isfinite(m_doubleValue)) {
 
630
            output->append(nullString, 4);
 
631
            return;
 
632
        }
 
633
        DecimalNumber decimal = m_doubleValue;
 
634
        unsigned length = 0;
 
635
        if (decimal.bufferLengthForStringDecimal() > WTF::NumberToStringBufferLength) {
 
636
            // Not enough room for decimal. Use exponential format.
 
637
            if (decimal.bufferLengthForStringExponential() > WTF::NumberToStringBufferLength) {
 
638
                // Fallback for an abnormal case if it's too little even for exponential.
 
639
                output->append("NaN", 3);
 
640
                return;
 
641
            }
 
642
            length = decimal.toStringExponential(buffer, WTF::NumberToStringBufferLength);
 
643
        } else
 
644
            length = decimal.toStringDecimal(buffer, WTF::NumberToStringBufferLength);
 
645
        output->append(buffer, length);
 
646
    }
 
647
}
 
648
 
 
649
bool InspectorString::asString(String* output) const
 
650
{
 
651
    *output = m_stringValue;
 
652
    return true;
 
653
}
 
654
 
 
655
void InspectorString::writeJSON(StringBuilder* output) const
 
656
{
 
657
    ASSERT(type() == TypeString);
 
658
    doubleQuoteString(m_stringValue, output);
 
659
}
 
660
 
 
661
InspectorObjectBase::~InspectorObjectBase()
 
662
{
 
663
}
 
664
 
 
665
bool InspectorObjectBase::asObject(RefPtr<InspectorObject>* output)
 
666
{
 
667
    COMPILE_ASSERT(sizeof(InspectorObject) == sizeof(InspectorObjectBase), cannot_cast);
 
668
    *output = static_cast<InspectorObject*>(this);
 
669
    return true;
 
670
}
 
671
 
 
672
PassRefPtr<InspectorObject> InspectorObjectBase::asObject()
 
673
{
 
674
    return openAccessors();
 
675
}
 
676
 
 
677
InspectorObject* InspectorObjectBase::openAccessors()
 
678
{
 
679
    COMPILE_ASSERT(sizeof(InspectorObject) == sizeof(InspectorObjectBase), cannot_cast);
 
680
    return static_cast<InspectorObject*>(this);
 
681
}
 
682
 
 
683
bool InspectorObjectBase::getBoolean(const String& name, bool* output) const
 
684
{
 
685
    RefPtr<InspectorValue> value = get(name);
 
686
    if (!value)
 
687
        return false;
 
688
    return value->asBoolean(output);
 
689
}
 
690
 
 
691
bool InspectorObjectBase::getString(const String& name, String* output) const
 
692
{
 
693
    RefPtr<InspectorValue> value = get(name);
 
694
    if (!value)
 
695
        return false;
 
696
    return value->asString(output);
 
697
}
 
698
 
 
699
PassRefPtr<InspectorObject> InspectorObjectBase::getObject(const String& name) const
 
700
{
 
701
    PassRefPtr<InspectorValue> value = get(name);
 
702
    if (!value)
 
703
        return 0;
 
704
    return value->asObject();
 
705
}
 
706
 
 
707
PassRefPtr<InspectorArray> InspectorObjectBase::getArray(const String& name) const
 
708
{
 
709
    PassRefPtr<InspectorValue> value = get(name);
 
710
    if (!value)
 
711
        return 0;
 
712
    return value->asArray();
 
713
}
 
714
 
 
715
PassRefPtr<InspectorValue> InspectorObjectBase::get(const String& name) const
 
716
{
 
717
    Dictionary::const_iterator it = m_data.find(name);
 
718
    if (it == m_data.end())
 
719
        return 0;
 
720
    return it->value;
 
721
}
 
722
 
 
723
void InspectorObjectBase::remove(const String& name)
 
724
{
 
725
    m_data.remove(name);
 
726
    for (size_t i = 0; i < m_order.size(); ++i) {
 
727
        if (m_order[i] == name) {
 
728
            m_order.remove(i);
 
729
            break;
 
730
        }
 
731
    }
 
732
}
 
733
 
 
734
void InspectorObjectBase::writeJSON(StringBuilder* output) const
 
735
{
 
736
    output->append('{');
 
737
    for (size_t i = 0; i < m_order.size(); ++i) {
 
738
        Dictionary::const_iterator it = m_data.find(m_order[i]);
 
739
        ASSERT(it != m_data.end());
 
740
        if (i)
 
741
            output->append(',');
 
742
        doubleQuoteString(it->key, output);
 
743
        output->append(':');
 
744
        it->value->writeJSON(output);
 
745
    }
 
746
    output->append('}');
 
747
}
 
748
 
 
749
InspectorObjectBase::InspectorObjectBase()
 
750
    : InspectorValue(TypeObject)
 
751
    , m_data()
 
752
    , m_order()
 
753
{
 
754
}
 
755
 
 
756
InspectorArrayBase::~InspectorArrayBase()
 
757
{
 
758
}
 
759
 
 
760
bool InspectorArrayBase::asArray(RefPtr<InspectorArray>* output)
 
761
{
 
762
    COMPILE_ASSERT(sizeof(InspectorArrayBase) == sizeof(InspectorArray), cannot_cast);
 
763
    *output = static_cast<InspectorArray*>(this);
 
764
    return true;
 
765
}
 
766
 
 
767
PassRefPtr<InspectorArray> InspectorArrayBase::asArray()
 
768
{
 
769
    COMPILE_ASSERT(sizeof(InspectorArrayBase) == sizeof(InspectorArray), cannot_cast);
 
770
    return static_cast<InspectorArray*>(this);
 
771
}
 
772
 
 
773
void InspectorArrayBase::writeJSON(StringBuilder* output) const
 
774
{
 
775
    output->append('[');
 
776
    for (Vector<RefPtr<InspectorValue> >::const_iterator it = m_data.begin(); it != m_data.end(); ++it) {
 
777
        if (it != m_data.begin())
 
778
            output->append(',');
 
779
        (*it)->writeJSON(output);
 
780
    }
 
781
    output->append(']');
 
782
}
 
783
 
 
784
InspectorArrayBase::InspectorArrayBase()
 
785
    : InspectorValue(TypeArray)
 
786
    , m_data()
 
787
{
 
788
}
 
789
 
 
790
PassRefPtr<InspectorValue> InspectorArrayBase::get(size_t index)
 
791
{
 
792
    ASSERT(index < m_data.size());
 
793
    return m_data[index];
 
794
}
 
795
 
 
796
} // namespace WebCore