tools/profiler/JSStreamWriter.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "JSStreamWriter.h"
michael@0 7
michael@0 8 #include "mozilla/ArrayUtils.h" // for ArrayLength
michael@0 9 #include "nsDataHashtable.h"
michael@0 10 #include "nsString.h"
michael@0 11 #include "nsTArray.h"
michael@0 12 #include "nsUTF8Utils.h"
michael@0 13
michael@0 14 #if _MSC_VER
michael@0 15 #define snprintf _snprintf
michael@0 16 #endif
michael@0 17
michael@0 18 #define ARRAY (void*)1
michael@0 19 #define OBJECT (void*)2
michael@0 20
michael@0 21 // Escape a UTF8 string to a stream. When an illegal encoding
michael@0 22 // is found it will insert "INVALID" and the function will return.
michael@0 23 static void EscapeToStream(std::ostream& stream, const char* str) {
michael@0 24 stream << "\"";
michael@0 25
michael@0 26 size_t len = strlen(str);
michael@0 27 const char* end = &str[len];
michael@0 28 while (str < end) {
michael@0 29 bool err;
michael@0 30 const char* utf8CharStart = str;
michael@0 31 uint32_t ucs4Char = UTF8CharEnumerator::NextChar(&str, end, &err);
michael@0 32
michael@0 33 if (err) {
michael@0 34 // Encoding error
michael@0 35 stream << "INVALID\"";
michael@0 36 return;
michael@0 37 }
michael@0 38
michael@0 39 // See http://www.ietf.org/rfc/rfc4627.txt?number=4627
michael@0 40 // characters that must be escaped: quotation mark,
michael@0 41 // reverse solidus, and the control characters
michael@0 42 // (U+0000 through U+001F).
michael@0 43 if (ucs4Char == '\"') {
michael@0 44 stream << "\\\"";
michael@0 45 } else if (ucs4Char == '\\') {
michael@0 46 stream << "\\\\";
michael@0 47 } else if (ucs4Char > 0xFF) {
michael@0 48 char16_t chr[2];
michael@0 49 ConvertUTF8toUTF16 encoder(chr);
michael@0 50 encoder.write(utf8CharStart, uint32_t(str-utf8CharStart));
michael@0 51 char escChar[13];
michael@0 52 snprintf(escChar, mozilla::ArrayLength(escChar), "\\u%04X\\u%04X", chr[0], chr[1]);
michael@0 53 stream << escChar;
michael@0 54 } else if (ucs4Char < 0x1F || ucs4Char > 0xFF) {
michael@0 55 char escChar[7];
michael@0 56 snprintf(escChar, mozilla::ArrayLength(escChar), "\\u%04X", ucs4Char);
michael@0 57 stream << escChar;
michael@0 58 } else {
michael@0 59 stream << char(ucs4Char);
michael@0 60 }
michael@0 61 }
michael@0 62 stream << "\"";
michael@0 63 }
michael@0 64
michael@0 65 JSStreamWriter::JSStreamWriter(std::ostream& aStream)
michael@0 66 : mStream(aStream)
michael@0 67 , mNeedsComma(false)
michael@0 68 , mNeedsName(false)
michael@0 69 { }
michael@0 70
michael@0 71 JSStreamWriter::~JSStreamWriter()
michael@0 72 {
michael@0 73 MOZ_ASSERT(mStack.GetSize() == 0);
michael@0 74 }
michael@0 75
michael@0 76 void
michael@0 77 JSStreamWriter::BeginObject()
michael@0 78 {
michael@0 79 MOZ_ASSERT(!mNeedsName);
michael@0 80 if (mNeedsComma && mStack.Peek() == ARRAY) {
michael@0 81 mStream << ",";
michael@0 82 }
michael@0 83 mStream << "{";
michael@0 84 mNeedsComma = false;
michael@0 85 mNeedsName = true;
michael@0 86 mStack.Push(OBJECT);
michael@0 87 }
michael@0 88
michael@0 89 void
michael@0 90 JSStreamWriter::EndObject()
michael@0 91 {
michael@0 92 MOZ_ASSERT(mStack.Peek() == OBJECT);
michael@0 93 mStream << "}";
michael@0 94 mNeedsComma = true;
michael@0 95 mNeedsName = false;
michael@0 96 mStack.Pop();
michael@0 97 if (mStack.GetSize() > 0 && mStack.Peek() == OBJECT) {
michael@0 98 mNeedsName = true;
michael@0 99 }
michael@0 100 }
michael@0 101
michael@0 102 void
michael@0 103 JSStreamWriter::BeginArray()
michael@0 104 {
michael@0 105 MOZ_ASSERT(!mNeedsName);
michael@0 106 if (mNeedsComma && mStack.Peek() == ARRAY) {
michael@0 107 mStream << ",";
michael@0 108 }
michael@0 109 mStream << "[";
michael@0 110 mNeedsComma = false;
michael@0 111 mStack.Push(ARRAY);
michael@0 112 }
michael@0 113
michael@0 114 void
michael@0 115 JSStreamWriter::EndArray()
michael@0 116 {
michael@0 117 MOZ_ASSERT(!mNeedsName);
michael@0 118 MOZ_ASSERT(mStack.Peek() == ARRAY);
michael@0 119 mStream << "]";
michael@0 120 mNeedsComma = true;
michael@0 121 mStack.Pop();
michael@0 122 if (mStack.GetSize() > 0 && mStack.Peek() == OBJECT) {
michael@0 123 mNeedsName = true;
michael@0 124 }
michael@0 125 }
michael@0 126
michael@0 127 void
michael@0 128 JSStreamWriter::Name(const char *aName)
michael@0 129 {
michael@0 130 MOZ_ASSERT(mNeedsName);
michael@0 131 if (mNeedsComma && mStack.Peek() == OBJECT) {
michael@0 132 mStream << ",";
michael@0 133 }
michael@0 134 EscapeToStream(mStream, aName);
michael@0 135 mStream << ":";
michael@0 136 mNeedsName = false;
michael@0 137 }
michael@0 138
michael@0 139 void
michael@0 140 JSStreamWriter::Value(int aValue)
michael@0 141 {
michael@0 142 MOZ_ASSERT(!mNeedsName);
michael@0 143 if (mNeedsComma && mStack.Peek() == ARRAY) {
michael@0 144 mStream << ",";
michael@0 145 }
michael@0 146 mStream << aValue;
michael@0 147 mNeedsComma = true;
michael@0 148 if (mStack.Peek() == OBJECT) {
michael@0 149 mNeedsName = true;
michael@0 150 }
michael@0 151 }
michael@0 152
michael@0 153 void
michael@0 154 JSStreamWriter::Value(double aValue)
michael@0 155 {
michael@0 156 MOZ_ASSERT(!mNeedsName);
michael@0 157 if (mNeedsComma && mStack.Peek() == ARRAY) {
michael@0 158 mStream << ",";
michael@0 159 }
michael@0 160 mStream.precision(18);
michael@0 161 mStream << aValue;
michael@0 162 mNeedsComma = true;
michael@0 163 if (mStack.Peek() == OBJECT) {
michael@0 164 mNeedsName = true;
michael@0 165 }
michael@0 166 }
michael@0 167
michael@0 168 void
michael@0 169 JSStreamWriter::Value(const char *aValue)
michael@0 170 {
michael@0 171 MOZ_ASSERT(!mNeedsName);
michael@0 172 if (mNeedsComma && mStack.Peek() == ARRAY) {
michael@0 173 mStream << ",";
michael@0 174 }
michael@0 175 EscapeToStream(mStream, aValue);
michael@0 176 mNeedsComma = true;
michael@0 177 if (mStack.Peek() == OBJECT) {
michael@0 178 mNeedsName = true;
michael@0 179 }
michael@0 180 }

mercurial