OLD | NEW |
| (Empty) |
1 #include "my_struct_to_json.h" | |
2 #include "debugger/base/debug_blob.h" | |
3 | |
4 namespace { | |
5 const int kTabSpaces = 2; | |
6 } // namespace | |
7 | |
8 namespace json { | |
9 StructTextCreator::StructTextCreator() | |
10 : generate_comments_(true), | |
11 struct_defs_(0) { | |
12 } | |
13 | |
14 StructTextCreator::~StructTextCreator() { | |
15 } | |
16 | |
17 void StructTextCreator::SetGenerateComments(bool on, StructDefinitions* struct_d
efs) { | |
18 generate_comments_ = on; | |
19 struct_defs_ = struct_defs; | |
20 } | |
21 | |
22 void StructTextCreator::CreateText(const Value& value_in, std::string* text_out)
{ | |
23 Value& value = const_cast<Value&>(value_in); | |
24 std::ostringstream buffer; | |
25 offset_ = 0; | |
26 buff_out_ = &buffer; | |
27 value.Accept(this); | |
28 *text_out = buffer.str(); | |
29 } | |
30 | |
31 void StructTextCreator::OutputValue(int offset, Value& value_in, std::ostringst
ream* buff_out) { | |
32 offset_ = offset; | |
33 buff_out_ = buff_out; | |
34 value_in.Accept(this); | |
35 } | |
36 | |
37 void StructTextCreator::OutputOffset(int offset, std::ostringstream* buff_out)
{ | |
38 for (int i = 0; i < offset; i++) | |
39 *buff_out << " "; | |
40 } | |
41 | |
42 void StructTextCreator::Visit(Null& element) { | |
43 *buff_out_ << "null"; | |
44 } | |
45 | |
46 void StructTextCreator::Visit(Number& element) { | |
47 *buff_out_ << element.AsDecString(); | |
48 } | |
49 | |
50 void StructTextCreator::Visit(Boolean& element) { | |
51 *buff_out_ << (element.value() ? "true" : "false"); | |
52 } | |
53 | |
54 void StructTextCreator::Visit(String& element) { | |
55 *buff_out_ << "\"" << element.value() << "\""; | |
56 } | |
57 | |
58 void StructTextCreator::Visit(Blob& element) { | |
59 std::string str = element.value().ToHexString(); | |
60 // if ((0 != str.size()) && ('0' == str[0])) | |
61 // str. | |
62 | |
63 *buff_out_ << "\"" << str << "\""; | |
64 } | |
65 | |
66 void StructTextCreator::Visit(Array& element) { | |
67 //TODO:implement | |
68 } | |
69 | |
70 void StructTextCreator::Visit(Object& element) { | |
71 OutputOffset(offset_, buff_out_); | |
72 *buff_out_ << "{" << std::endl; | |
73 offset_ += kTabSpaces; | |
74 | |
75 std::deque<std::string> property_names; | |
76 element.GetPropertyNames(&property_names); | |
77 | |
78 std::string struct_type; | |
79 String* struct_type_obj = static_cast<String*>(element.GetProperty("_type")); | |
80 if (NULL != struct_type_obj) | |
81 struct_type = struct_type_obj->value(); | |
82 | |
83 size_t num = property_names.size(); | |
84 for (size_t i = 0; i < num; i++) { | |
85 std::string& prop_name = property_names[i]; | |
86 Value* prop = element.GetProperty(prop_name); | |
87 OutputOffset(offset_, buff_out_); | |
88 *buff_out_ << "\"" << prop_name << "\": "; | |
89 OutputValue(offset_, *prop, buff_out_); | |
90 if ((i + 1) != num) | |
91 *buff_out_ << ","; | |
92 | |
93 //aaa | |
94 if (NULL != struct_defs_) { | |
95 //struct_type + prop_name | |
96 StructDefinition* st_def = struct_defs_->FindStructDefinition(struct_type)
; | |
97 if (NULL != st_def) { | |
98 StructFieldDefinition* fd_def = st_def->GetFieldDefinition(prop_name); | |
99 if (NULL != fd_def) { | |
100 comment_ = CreateCommentFor(prop, fd_def); | |
101 } | |
102 } | |
103 } | |
104 if (comment_.size()) { | |
105 *buff_out_ << " // " << comment_; | |
106 comment_.clear(); | |
107 } | |
108 *buff_out_ << std::endl; | |
109 } | |
110 | |
111 offset_ -= kTabSpaces; | |
112 OutputOffset(offset_, buff_out_); | |
113 *buff_out_ << "}" << std::endl; | |
114 } | |
115 | |
116 std::string StructTextCreator::CreateCommentFor(Value* prop, StructFieldDefiniti
on* fd_def) { | |
117 std::string comment; | |
118 if ((fd_def->type_ == StructFieldDefinition::FT_INT) || | |
119 (fd_def->type_ == StructFieldDefinition::FT_ENUM)) { | |
120 Number* i_prop = static_cast<Number*>(prop); | |
121 comment = i_prop->AsHexString(); | |
122 if (comment != "null") | |
123 comment = std::string("0x") + comment; | |
124 } | |
125 if (fd_def->type_ == StructFieldDefinition::FT_HANDLE) { | |
126 Number* i_prop = static_cast<Number*>(prop); | |
127 comment = i_prop->AsHexString(); | |
128 } | |
129 if (fd_def->type_ == StructFieldDefinition::FT_ENUM) { | |
130 Number* i_prop = static_cast<Number*>(prop); | |
131 std::string enum_name = fd_def->GetEnumName(i_prop->value()); | |
132 comment.append(" "); | |
133 comment.append(enum_name); | |
134 } | |
135 | |
136 //TODO: implement | |
137 return comment; | |
138 } | |
139 | |
140 void Split(const std::string& str, std::deque<std::string>* tokens, const char*
delimiters) { | |
141 std::string token; | |
142 std::string::const_iterator it = str.begin(); | |
143 while (str.end() != it) { | |
144 char c = *it++; | |
145 if (strchr(delimiters, c) != 0) { | |
146 tokens->push_back(token); | |
147 token.clear(); | |
148 } else { | |
149 token.push_back(c); | |
150 } | |
151 } | |
152 if (0 != token.size()) | |
153 tokens->push_back(token); | |
154 } | |
155 | |
156 // example: "3:CREATE_PROCESS_DEBUG_EVENT,2:CREATE_THREAD_DEBUG_EVENT" | |
157 void StructFieldDefinition::ParseEnumValues(const std::string& key_value_pairs)
{ | |
158 enum_values_.clear(); | |
159 std::deque<std::string> statements; | |
160 Split(key_value_pairs, &statements, ","); | |
161 for (size_t i = 0; i < statements.size(); i++) { | |
162 std::string statement = statements[i]; | |
163 std::deque<std::string> parts; | |
164 Split(statement, &parts, ":"); | |
165 if (parts.size() >= 2) { | |
166 int id = atoi(parts[0].c_str()); | |
167 enum_values_[id] = parts[1]; | |
168 } | |
169 } | |
170 } | |
171 | |
172 std::string StructFieldDefinition::GetEnumName(long long id) { | |
173 if (enum_values_.find(id) != enum_values_.end()) | |
174 return enum_values_[id]; | |
175 return ""; | |
176 } | |
177 | |
178 StructDefinition::~StructDefinition() { | |
179 for (size_t i = 0; i < fields_.size(); i++) | |
180 delete fields_[i]; | |
181 fields_.clear(); | |
182 } | |
183 | |
184 void StructDefinition::AddFieldDefinition(StructFieldDefinition* def) { | |
185 fields_.push_back(def); | |
186 } | |
187 | |
188 size_t StructDefinition::GetFieldNum() const { | |
189 return fields_.size(); | |
190 } | |
191 | |
192 StructFieldDefinition* StructDefinition::GetFieldDefinition(size_t pos) { | |
193 return fields_[pos]; | |
194 } | |
195 | |
196 StructFieldDefinition* StructDefinition::GetFieldDefinition(const std::string& n
ame) { | |
197 size_t num = GetFieldNum(); | |
198 for (size_t i = 0; i < num; i++) { | |
199 StructFieldDefinition* def = GetFieldDefinition(i); | |
200 if (def->name_ == name) | |
201 return def; | |
202 } | |
203 return NULL; | |
204 } | |
205 | |
206 StructDefinitions::StructDefinitions() { | |
207 } | |
208 | |
209 StructDefinitions::~StructDefinitions() { | |
210 std::map<std::string, StructDefinition*>::iterator it = structs_.begin(); | |
211 while (it != structs_.end()) { | |
212 delete it->second; | |
213 ++it; | |
214 } | |
215 } | |
216 | |
217 void StructDefinitions::AddStructDefinition(StructDefinition* def) { | |
218 structs_[def->name_] = def; | |
219 } | |
220 | |
221 StructDefinition* StructDefinitions::FindStructDefinition(const std::string& nam
e) { | |
222 if (structs_.find(name) != structs_.end()) | |
223 return structs_[name]; | |
224 return NULL; | |
225 } | |
226 | |
227 size_t MySafeCopy(void* dest, size_t dest_sz, const void* src) { | |
228 //TODO:implement SAFE copy, i.e. with system exception catching (like access v
iolation) | |
229 strcpy_s(static_cast<char*>(dest), dest_sz, static_cast<const char*>(src)); | |
230 return strlen(static_cast<const char*>(src)); | |
231 } | |
232 | |
233 char* UnicodeToAscii(const void* unicode_str) { | |
234 size_t number_of_converted_chars = 0; | |
235 char ascii_str[4 * 1024] = {0}; | |
236 const wchar_t* in = static_cast<const wchar_t*>(unicode_str); | |
237 mbstate_t mbstate; | |
238 memset(&mbstate, 0, sizeof(mbstate)); | |
239 | |
240 wcsrtombs_s(&number_of_converted_chars, | |
241 ascii_str, | |
242 sizeof(ascii_str) - 1, | |
243 &in, | |
244 _TRUNCATE, | |
245 &mbstate); | |
246 ascii_str[sizeof(ascii_str) - 1] = 0; | |
247 return _strdup(ascii_str); | |
248 } | |
249 | |
250 Value* CreateValueFromStructField(const void* struct_ptr, const char* struct_nam
e, json::StructFieldDefinition& field_def) { | |
251 const char* src = static_cast<const char*>(struct_ptr); | |
252 | |
253 switch (field_def.type_) { | |
254 case StructFieldDefinition::FT_INT: | |
255 case StructFieldDefinition::FT_ENUM: | |
256 case StructFieldDefinition::FT_FLAGS: | |
257 case StructFieldDefinition::FT_HANDLE: { | |
258 Number* val = new Number; | |
259 val->SetInteger(src + field_def.offset_, field_def.size_, false); | |
260 return val; | |
261 } | |
262 case json::StructFieldDefinition::FT_PTR: { | |
263 debug::Blob blob(src + field_def.offset_, field_def.size_); | |
264 blob.Reverse(); // Convert from little-endian to big-endian. | |
265 std::string hex_str = blob.ToHexString(); | |
266 std::string ptr_str = std::string("0x") + hex_str; | |
267 return new json::String(ptr_str); | |
268 } | |
269 case StructFieldDefinition::FT_STR: { | |
270 const void* str_ptr = 0; | |
271 memcpy(&str_ptr, src + field_def.offset_, field_def.size_); //TODO: check
for invalid size | |
272 if (NULL != str_ptr) { | |
273 char copy[16 * 1024]; | |
274 size_t num = MySafeCopy(copy, sizeof(copy) - 1, str_ptr); | |
275 copy[sizeof(copy) - 1] = 0; | |
276 copy[num] = 0; | |
277 return new String(copy); | |
278 } | |
279 break; | |
280 } | |
281 case StructFieldDefinition::FT_USTR: { | |
282 /* | |
283 unsigned short fUnicode = 0; | |
284 memcpy(&fUnicode, src + field_def.unicode_offset_, sizeof(fUnicode)); | |
285 const void* pp_str_ptr = 0; | |
286 memcpy(&pp_str_ptr, src + field_def.offset_, field_def.size_); //TODO: che
ck for invalid size | |
287 // now, pp_str_ptr is an address of string pointer in debugee address spac
e. | |
288 void* str_ptr = 0; | |
289 | |
290 if (NULL != str_ptr) { | |
291 if (0 != fUnicode) { | |
292 char* str = UnicodeToAscii(str_ptr); | |
293 Value* obj = new String(str); | |
294 if (NULL != str) | |
295 free(str); | |
296 return obj; | |
297 } else { | |
298 char copy[16 * 1024]; | |
299 size_t num = MySafeCopy(copy, sizeof(copy) - 1, str_ptr); | |
300 copy[sizeof(copy) - 1] = 0; | |
301 copy[num] = 0; | |
302 return new String(copy); | |
303 } | |
304 } | |
305 */ | |
306 } | |
307 } | |
308 return new Null; | |
309 } | |
310 | |
311 Object* CreateFromStruct(const void* struct_ptr, const char* struct_name, json::
StructDefinitions& defs) { | |
312 const char* src = static_cast<const char*>(struct_ptr); | |
313 json::Object* obj = new json::Object; | |
314 obj->SetProperty("_type", new json::String(struct_name)); | |
315 | |
316 json::StructDefinition* struct_def = defs.FindStructDefinition(struct_name); | |
317 if (NULL != struct_def) { | |
318 size_t field_num = struct_def->GetFieldNum(); | |
319 for (size_t i = 0; i < field_num; i++) { | |
320 json::StructFieldDefinition* field_def = struct_def->GetFieldDefinition(i)
; | |
321 if (NULL != field_def) { | |
322 json::Value* val = CreateValueFromStructField(src, struct_name, *field_d
ef); | |
323 obj->SetProperty(field_def->name_, val); | |
324 } | |
325 } | |
326 } | |
327 return obj; | |
328 } | |
329 | |
330 void AddIntConst(int id, const char* name, std::string* str) { | |
331 char tmp[300]; | |
332 _snprintf_s(tmp, sizeof(tmp), sizeof(tmp) - 1, "%d:%s,", id, name); | |
333 tmp[sizeof(tmp) - 1] = 0; | |
334 str->append(tmp); | |
335 } | |
336 | |
337 } // namespace json | |
OLD | NEW |