OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/text_buffer.h" | 5 #include "platform/text_buffer.h" |
6 | 6 |
7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
8 #include "platform/globals.h" | 8 #include "platform/globals.h" |
9 #include "platform/utils.h" | 9 #include "platform/utils.h" |
10 #include "vm/os.h" | 10 #include "vm/os.h" |
11 #include "vm/unicode.h" | 11 #include "vm/unicode.h" |
12 | 12 |
13 namespace dart { | 13 namespace dart { |
14 | 14 |
15 TextBuffer::TextBuffer(intptr_t buf_size) { | 15 TextBuffer::TextBuffer(intptr_t buf_size) { |
16 ASSERT(buf_size > 0); | 16 ASSERT(buf_size > 0); |
17 buf_ = reinterpret_cast<char*>(malloc(buf_size)); | 17 buf_ = reinterpret_cast<char*>(malloc(buf_size)); |
18 if (buf_ == NULL) { | 18 if (buf_ == NULL) { |
19 OUT_OF_MEMORY(); | 19 OUT_OF_MEMORY(); |
20 } | 20 } |
21 buf_size_ = buf_size; | 21 buf_size_ = buf_size; |
22 Clear(); | 22 Clear(); |
23 } | 23 } |
24 | 24 |
25 | |
26 TextBuffer::~TextBuffer() { | 25 TextBuffer::~TextBuffer() { |
27 free(buf_); | 26 free(buf_); |
28 buf_ = NULL; | 27 buf_ = NULL; |
29 } | 28 } |
30 | 29 |
31 | |
32 void TextBuffer::Clear() { | 30 void TextBuffer::Clear() { |
33 msg_len_ = 0; | 31 msg_len_ = 0; |
34 buf_[0] = '\0'; | 32 buf_[0] = '\0'; |
35 } | 33 } |
36 | 34 |
37 | |
38 char* TextBuffer::Steal() { | 35 char* TextBuffer::Steal() { |
39 char* r = buf_; | 36 char* r = buf_; |
40 buf_ = NULL; | 37 buf_ = NULL; |
41 buf_size_ = 0; | 38 buf_size_ = 0; |
42 msg_len_ = 0; | 39 msg_len_ = 0; |
43 return r; | 40 return r; |
44 } | 41 } |
45 | 42 |
46 | |
47 void TextBuffer::AddChar(char ch) { | 43 void TextBuffer::AddChar(char ch) { |
48 EnsureCapacity(sizeof(ch)); | 44 EnsureCapacity(sizeof(ch)); |
49 buf_[msg_len_] = ch; | 45 buf_[msg_len_] = ch; |
50 msg_len_++; | 46 msg_len_++; |
51 buf_[msg_len_] = '\0'; | 47 buf_[msg_len_] = '\0'; |
52 } | 48 } |
53 | 49 |
54 | |
55 void TextBuffer::AddRaw(const uint8_t* buffer, intptr_t buffer_length) { | 50 void TextBuffer::AddRaw(const uint8_t* buffer, intptr_t buffer_length) { |
56 EnsureCapacity(buffer_length); | 51 EnsureCapacity(buffer_length); |
57 memmove(&buf_[msg_len_], buffer, buffer_length); | 52 memmove(&buf_[msg_len_], buffer, buffer_length); |
58 msg_len_ += buffer_length; | 53 msg_len_ += buffer_length; |
59 buf_[msg_len_] = '\0'; | 54 buf_[msg_len_] = '\0'; |
60 } | 55 } |
61 | 56 |
62 | |
63 intptr_t TextBuffer::Printf(const char* format, ...) { | 57 intptr_t TextBuffer::Printf(const char* format, ...) { |
64 va_list args; | 58 va_list args; |
65 va_start(args, format); | 59 va_start(args, format); |
66 intptr_t remaining = buf_size_ - msg_len_; | 60 intptr_t remaining = buf_size_ - msg_len_; |
67 ASSERT(remaining >= 0); | 61 ASSERT(remaining >= 0); |
68 intptr_t len = OS::VSNPrint(buf_ + msg_len_, remaining, format, args); | 62 intptr_t len = OS::VSNPrint(buf_ + msg_len_, remaining, format, args); |
69 va_end(args); | 63 va_end(args); |
70 if (len >= remaining) { | 64 if (len >= remaining) { |
71 EnsureCapacity(len); | 65 EnsureCapacity(len); |
72 remaining = buf_size_ - msg_len_; | 66 remaining = buf_size_ - msg_len_; |
73 ASSERT(remaining > len); | 67 ASSERT(remaining > len); |
74 va_list args2; | 68 va_list args2; |
75 va_start(args2, format); | 69 va_start(args2, format); |
76 intptr_t len2 = OS::VSNPrint(buf_ + msg_len_, remaining, format, args2); | 70 intptr_t len2 = OS::VSNPrint(buf_ + msg_len_, remaining, format, args2); |
77 va_end(args2); | 71 va_end(args2); |
78 ASSERT(len == len2); | 72 ASSERT(len == len2); |
79 } | 73 } |
80 msg_len_ += len; | 74 msg_len_ += len; |
81 buf_[msg_len_] = '\0'; | 75 buf_[msg_len_] = '\0'; |
82 return len; | 76 return len; |
83 } | 77 } |
84 | 78 |
85 | |
86 // Write a UTF-32 code unit so it can be read by a JSON parser in a string | 79 // Write a UTF-32 code unit so it can be read by a JSON parser in a string |
87 // literal. Use official encoding from JSON specification. http://json.org/ | 80 // literal. Use official encoding from JSON specification. http://json.org/ |
88 void TextBuffer::EscapeAndAddCodeUnit(uint32_t codeunit) { | 81 void TextBuffer::EscapeAndAddCodeUnit(uint32_t codeunit) { |
89 switch (codeunit) { | 82 switch (codeunit) { |
90 case '"': | 83 case '"': |
91 AddRaw(reinterpret_cast<uint8_t const*>("\\\""), 2); | 84 AddRaw(reinterpret_cast<uint8_t const*>("\\\""), 2); |
92 break; | 85 break; |
93 case '\\': | 86 case '\\': |
94 AddRaw(reinterpret_cast<uint8_t const*>("\\\\"), 2); | 87 AddRaw(reinterpret_cast<uint8_t const*>("\\\\"), 2); |
95 break; | 88 break; |
(...skipping 20 matching lines...) Expand all Loading... |
116 EscapeAndAddUTF16CodeUnit(codeunit); | 109 EscapeAndAddUTF16CodeUnit(codeunit); |
117 } else { | 110 } else { |
118 char encoded[6]; | 111 char encoded[6]; |
119 intptr_t length = Utf8::Length(codeunit); | 112 intptr_t length = Utf8::Length(codeunit); |
120 Utf8::Encode(codeunit, encoded); | 113 Utf8::Encode(codeunit, encoded); |
121 AddRaw(reinterpret_cast<uint8_t const*>(encoded), length); | 114 AddRaw(reinterpret_cast<uint8_t const*>(encoded), length); |
122 } | 115 } |
123 } | 116 } |
124 } | 117 } |
125 | 118 |
126 | |
127 // Write an incomplete UTF-16 code unit so it can be read by a JSON parser in a | 119 // Write an incomplete UTF-16 code unit so it can be read by a JSON parser in a |
128 // string literal. | 120 // string literal. |
129 void TextBuffer::EscapeAndAddUTF16CodeUnit(uint16_t codeunit) { | 121 void TextBuffer::EscapeAndAddUTF16CodeUnit(uint16_t codeunit) { |
130 Printf("\\u%04X", codeunit); | 122 Printf("\\u%04X", codeunit); |
131 } | 123 } |
132 | 124 |
133 | |
134 void TextBuffer::AddString(const char* s) { | 125 void TextBuffer::AddString(const char* s) { |
135 Printf("%s", s); | 126 Printf("%s", s); |
136 } | 127 } |
137 | 128 |
138 | |
139 void TextBuffer::AddEscapedString(const char* s) { | 129 void TextBuffer::AddEscapedString(const char* s) { |
140 intptr_t len = strlen(s); | 130 intptr_t len = strlen(s); |
141 for (int i = 0; i < len; i++) { | 131 for (int i = 0; i < len; i++) { |
142 EscapeAndAddCodeUnit(s[i]); | 132 EscapeAndAddCodeUnit(s[i]); |
143 } | 133 } |
144 } | 134 } |
145 | 135 |
146 | |
147 void TextBuffer::EnsureCapacity(intptr_t len) { | 136 void TextBuffer::EnsureCapacity(intptr_t len) { |
148 intptr_t remaining = buf_size_ - msg_len_; | 137 intptr_t remaining = buf_size_ - msg_len_; |
149 if (remaining <= len) { | 138 if (remaining <= len) { |
150 const int kBufferSpareCapacity = 64; // Somewhat arbitrary. | 139 const int kBufferSpareCapacity = 64; // Somewhat arbitrary. |
151 // TODO(turnidge): do we need to guard against overflow or other | 140 // TODO(turnidge): do we need to guard against overflow or other |
152 // security issues here? Text buffers are used by the debugger | 141 // security issues here? Text buffers are used by the debugger |
153 // to send user-controlled data (e.g. values of string variables) to | 142 // to send user-controlled data (e.g. values of string variables) to |
154 // the debugger front-end. | 143 // the debugger front-end. |
155 intptr_t new_size = buf_size_ + len + kBufferSpareCapacity; | 144 intptr_t new_size = buf_size_ + len + kBufferSpareCapacity; |
156 char* new_buf = reinterpret_cast<char*>(realloc(buf_, new_size)); | 145 char* new_buf = reinterpret_cast<char*>(realloc(buf_, new_size)); |
157 if (new_buf == NULL) { | 146 if (new_buf == NULL) { |
158 OUT_OF_MEMORY(); | 147 OUT_OF_MEMORY(); |
159 } | 148 } |
160 buf_ = new_buf; | 149 buf_ = new_buf; |
161 buf_size_ = new_size; | 150 buf_size_ = new_size; |
162 } | 151 } |
163 } | 152 } |
164 | 153 |
165 } // namespace dart | 154 } // namespace dart |
OLD | NEW |