Line data Source code
1 : /*
2 : * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <cassert>
6 : #include <cctype>
7 : #include <cstdio>
8 : #include <stdexcept>
9 : #include <boost/static_assert.hpp>
10 : #include <boost/algorithm/string/replace.hpp>
11 :
12 : #include <base/logging.h>
13 : #include <base/util.h>
14 : #include <base/string_util.h>
15 :
16 : #include "TJSONProtocol.h"
17 :
18 : using std::string;
19 :
20 : #ifdef TJSONPROTOCOL_DEBUG_PRETTY_PRINT
21 : static const string endl = "\n";
22 : #else
23 : static const string endl = "";
24 : #endif // !TJSONPROTOCOL_DEBUG_PRETTY_PRINT
25 :
26 : namespace contrail { namespace sandesh { namespace protocol {
27 :
28 : // Static data
29 :
30 : static const std::string kJSONTagO("{");
31 : static const std::string kJSONTagC("}");
32 : static const std::string kJSONType("type");
33 : static const std::string kJSONIdentifier("identifier");
34 : static const std::string kJSONName("name");
35 : static const std::string kJSONKey("key");
36 : static const std::string kJSONValue("value");
37 : static const std::string kJSONSize("size");
38 : static const std::string kJSONBoolTrue("true");
39 : static const std::string kJSONBoolFalse("false");
40 : static const std::string kJSONCDATAO("<![CDATA[");
41 : static const std::string kJSONCDATAC("]]>");
42 :
43 : static const std::string kTypeNameBool("bool");
44 : static const std::string kTypeNameByte("byte");
45 : static const std::string kTypeNameI16("i16");
46 : static const std::string kTypeNameI32("i32");
47 : static const std::string kTypeNameI64("i64");
48 : static const std::string kTypeNameU16("u16");
49 : static const std::string kTypeNameU32("u32");
50 : static const std::string kTypeNameU64("u64");
51 : static const std::string kTypeNameIPV4("ipv4");
52 : static const std::string kTypeNameIPADDR("ipaddr");
53 : static const std::string kTypeNameDouble("double");
54 : static const std::string kTypeNameStruct("struct");
55 : static const std::string kTypeNameString("string");
56 : static const std::string kTypeNameXML("xml");
57 : static const std::string kTypeNameUUID("uuid_t");
58 : static const std::string kTypeNameMap("map");
59 : static const std::string kTypeNameList("list");
60 : static const std::string kTypeNameSet("set");
61 : static const std::string kTypeNameSandesh("sandesh");
62 : static const std::string kTypeNameUnknown("unknown");
63 :
64 : static const std::string kAttrTypeSandesh("type=\"sandesh\"");
65 : static const std::string kJSONListTagO("<list ");
66 : static const std::string kJSONListTagC("</list>" + endl);
67 : static const std::string kJSONSetTagO("<set ");
68 : static const std::string kJSONSetTagC("</set>" + endl);
69 : static const std::string kJSONMapTagO("<map ");
70 : static const std::string kJSONMapTagC("</map>" + endl);
71 : static const std::string kType("\"TYPE\":");
72 : static const std::string kTYPEStruct("TYPE: STRUCT");
73 : static const std::string kFieldId("\"ID\":");
74 : static const std::string kVal("\"VAL\":");
75 :
76 0 : const std::string& TJSONProtocol::fieldTypeName(TType type) {
77 0 : switch (type) {
78 0 : case T_BOOL : return kTypeNameBool ;
79 0 : case T_BYTE : return kTypeNameByte ;
80 0 : case T_I16 : return kTypeNameI16 ;
81 0 : case T_I32 : return kTypeNameI32 ;
82 0 : case T_I64 : return kTypeNameI64 ;
83 0 : case T_U16 : return kTypeNameU16 ;
84 0 : case T_U32 : return kTypeNameU32 ;
85 0 : case T_U64 : return kTypeNameU64 ;
86 0 : case T_IPV4 : return kTypeNameIPV4 ;
87 0 : case T_IPADDR : return kTypeNameIPADDR ;
88 0 : case T_DOUBLE : return kTypeNameDouble ;
89 0 : case T_STRING : return kTypeNameString ;
90 0 : case T_STRUCT : return kTypeNameStruct ;
91 0 : case T_MAP : return kTypeNameMap ;
92 0 : case T_SET : return kTypeNameSet ;
93 0 : case T_LIST : return kTypeNameList ;
94 0 : case T_SANDESH: return kTypeNameSandesh;
95 0 : case T_XML : return kTypeNameXML ;
96 0 : case T_UUID : return kTypeNameUUID ;
97 0 : default: return kTypeNameUnknown;
98 : }
99 : }
100 :
101 0 : TType TJSONProtocol::getTypeIDForTypeName(const std::string &name) {
102 0 : TType result = T_STOP; // Sentinel value
103 0 : if (name.length() > 1) {
104 0 : switch (name[0]) {
105 0 : case 'b':
106 0 : switch (name[1]) {
107 0 : case 'o':
108 0 : result = T_BOOL;
109 0 : break;
110 0 : case 'y':
111 0 : result = T_BYTE;
112 0 : break;
113 : }
114 0 : break;
115 0 : case 'd':
116 0 : result = T_DOUBLE;
117 0 : break;
118 0 : case 'i':
119 0 : switch (name[1]) {
120 0 : case '1':
121 0 : result = T_I16;
122 0 : break;
123 0 : case '3':
124 0 : result = T_I32;
125 0 : break;
126 0 : case '6':
127 0 : result = T_I64;
128 0 : break;
129 0 : case 'p':
130 0 : switch (name[2]) {
131 0 : case 'a':
132 0 : result = T_IPADDR;
133 0 : break;
134 0 : case 'v':
135 0 : result = T_IPV4;
136 0 : break;
137 : }
138 0 : break;
139 : }
140 0 : break;
141 0 : case 'l':
142 0 : result = T_LIST;
143 0 : break;
144 0 : case 'm':
145 0 : result = T_MAP;
146 0 : break;
147 0 : case 's':
148 0 : switch (name[1]) {
149 0 : case 'a':
150 0 : result = T_SANDESH;
151 0 : break;
152 0 : case 'e':
153 0 : result = T_SET;
154 0 : break;
155 0 : case 't':
156 0 : switch (name[3]) {
157 0 : case 'i':
158 0 : result = T_STRING;
159 0 : break;
160 0 : case 'u':
161 0 : result = T_STRUCT;
162 0 : break;
163 : }
164 0 : break;
165 : }
166 0 : break;
167 0 : case 'u':
168 0 : switch(name[1]) {
169 0 : case '1':
170 0 : result = T_U16;
171 0 : break;
172 0 : case '3':
173 0 : result = T_U32;
174 0 : break;
175 0 : case '6':
176 0 : result = T_U64;
177 0 : break;
178 0 : case 'u':
179 0 : result = T_UUID;
180 0 : break;
181 : }
182 0 : break;
183 0 : case 'x':
184 0 : result = T_XML;
185 0 : break;
186 : }
187 : }
188 0 : if (result == T_STOP) {
189 0 : LOG(ERROR, __func__ << "Unrecognized type: " << name);
190 : }
191 0 : return result;
192 : }
193 :
194 : static inline void formJSONAttr(std::string &dest, const std::string& name,
195 : const std::string & value) {
196 : dest += name;
197 : dest += "=\"";
198 : dest += value;
199 : dest += "\"";
200 : }
201 :
202 0 : void TJSONProtocol::indentUp() {
203 : #if TJSONPROTOCOL_DEBUG_PRETTY_PRINT
204 : indent_str_ += string(indent_inc, ' ');
205 : #endif // !TJSONPROTOCOL_DEBUG_PRETTY_PRINT
206 0 : }
207 :
208 0 : void TJSONProtocol::indentDown() {
209 : #if TJSONPROTOCOL_DEBUG_PRETTY_PRINT
210 : if (indent_str_.length() < (string::size_type)indent_inc) {
211 : LOG(ERROR, __func__ << "Indent string length " <<
212 : indent_str_.length() << " less than indent length " <<
213 : (string::size_type)indent_inc);
214 : return;
215 : }
216 : indent_str_.erase(indent_str_.length() - indent_inc);
217 : #endif // !TJSONPROTOOL_DEBUG_PRETTY_PRINT
218 0 : }
219 :
220 : // Returns the number of bytes written on success, -1 otherwise
221 0 : int32_t TJSONProtocol::writePlain(const string& str) {
222 0 : int ret = trans_->write((uint8_t*)str.data(), str.length());
223 0 : if (ret) {
224 0 : return -1;
225 : }
226 0 : return str.length();
227 : }
228 :
229 : // Returns the number of bytes written on success, -1 otherwise
230 0 : int32_t TJSONProtocol::writeIndented(const string& str) {
231 : int ret;
232 : #if TJSONPROTOCOL_DEBUG_PRETTY_PRINT
233 : ret = trans_->write((uint8_t*)indent_str_.data(), indent_str_.length());
234 : if (ret) {
235 : return -1;
236 : }
237 : #endif // !TJSONPROTOCOL_DEBUG_PRETTY_PRINT
238 0 : ret = trans_->write((uint8_t*)str.data(), str.length());
239 0 : if (ret) {
240 0 : return -1;
241 : }
242 0 : return indent_str_.length() + str.length();
243 : }
244 :
245 0 : int32_t TJSONProtocol::writeMessageBegin(const std::string& name,
246 : const TMessageType messageType,
247 : const int32_t seqid) {
248 0 : return 0;
249 : }
250 :
251 0 : int32_t TJSONProtocol::writeMessageEnd() {
252 0 : return 0;
253 : }
254 :
255 :
256 : /*
257 : * As a part of structBegin call, we open 2 {{
258 : * Inside the outer bracket, we will have
259 : * meta data about the structure itself.
260 : * Inside the inner bracket, we will have the
261 : * actual fields of the structure
262 : */
263 0 : int32_t TJSONProtocol::writeStructBegin(const char* name) {
264 0 : int32_t size = 0, ret;
265 0 : string sname(name);
266 0 : string json;
267 0 : json.reserve(512);
268 :
269 : // Handle list of struct
270 0 : if (is_first_element_context_.size() > 0 &&
271 0 : !is_first_element_context_.back() &&
272 0 : current_sandesh_context_.back() == "LIST") {
273 0 : json += ",";
274 0 : } else if (!is_first_element_context_.empty()) {
275 0 : is_first_element_context_.back() = false;
276 : }
277 :
278 0 : json += "{";
279 0 : if(current_sandesh_context_.back() == "SANDESH") {
280 0 : json += "\"STAT_TYPE\":";
281 0 : json += "\""+sname+"\"";
282 0 : json += ",";
283 : }
284 0 : current_sandesh_context_.push_back("STRUCT");
285 0 : is_first_element_context_.push_back(true);
286 0 : is_primitive_element_list_.push_back(false);
287 0 : json += "\"VAL\":";
288 0 : json += kJSONTagO;
289 0 : indentUp();
290 : // Write to transport
291 0 : if ((ret = writeIndented(json)) < 0) {
292 0 : LOG(ERROR, __func__ << ": " << sname << " FAILED");
293 0 : return ret;
294 : }
295 : // push a value to is_struct_begin
296 0 : is_struct_begin_list_.push_back(true);
297 0 : size += ret;
298 0 : return size;
299 0 : }
300 :
301 : /*
302 : * Close the brackets that were opened as part of
303 : * struct begin. Some variables are maintained to
304 : * identify if we are in struct context or not.
305 : */
306 0 : int32_t TJSONProtocol::writeStructEnd() {
307 0 : int32_t size = 0, ret;
308 0 : indentDown();
309 0 : string json;
310 0 : json.reserve(128);
311 0 : json += kJSONTagC;
312 0 : indentDown();
313 0 : json += endl;
314 0 : json += kJSONTagC;
315 0 : json += endl;
316 0 : indentDown();
317 : // Write to transport
318 0 : if ((ret = writeIndented(json)) < 0) {
319 0 : LOG(ERROR, __func__ << ": " << json << " FAILED");
320 0 : return ret;
321 : }
322 0 : size += ret;
323 :
324 0 : current_sandesh_context_.pop_back();
325 0 : is_first_element_context_.pop_back();
326 0 : if(is_first_element_context_.size() > 0) {
327 0 : is_first_element_context_.back() = false;
328 : }
329 0 : is_primitive_element_list_.pop_back();
330 0 : return size;
331 0 : }
332 :
333 : /*
334 : * Open a couple of brackets when this call is made
335 : * The first bracket to store metadata about the
336 : * sandesh. The second bracket to store the actual
337 : * fields of the sandesh.
338 : */
339 0 : int32_t TJSONProtocol::writeSandeshBegin(const char* name) {
340 0 : int32_t size = 0, ret;
341 0 : string sname(name);
342 0 : string json;
343 0 : current_sandesh_context_.push_back("SANDESH");
344 0 : is_first_element_context_.push_back(true);
345 0 : json.reserve(512);
346 0 : json += kJSONTagO;
347 0 : json += endl;
348 0 : indentUp();
349 0 : json += "\"";
350 0 : json += name;
351 0 : json += "\"";
352 0 : json += ":";
353 0 : json += kJSONTagO;
354 0 : json += endl;
355 0 : indentUp();
356 : // Write to transport
357 0 : ret = writeIndented(json);
358 0 : if (ret < 0) {
359 0 : LOG(ERROR, __func__ << ": " << sname << " FAILED");
360 0 : return ret;
361 : }
362 0 : size += ret;
363 0 : is_primitive_element_list_.push_back(false);
364 0 : indentUp();
365 0 : return size;
366 0 : }
367 :
368 0 : int32_t TJSONProtocol::writeSandeshEnd() {
369 :
370 0 : int32_t size = 0, ret;
371 0 : indentDown();
372 0 : string json;
373 0 : json.reserve(128);
374 : //indentDown();
375 0 : json += kJSONTagC;
376 0 : json += endl;
377 0 : indentDown();
378 0 : json += ",";
379 0 : json += "\"TIMESTAMP\":";
380 0 : std::stringstream ss;
381 0 : std::string t_s;
382 0 : ss << UTCTimestampUsec();
383 0 : ss >> t_s;
384 0 : json += t_s;
385 0 : json += kJSONTagC;
386 0 : json += endl;
387 : // Write to transport
388 0 : if ((ret = writeIndented(json)) < 0) {
389 0 : LOG(ERROR, __func__ << ": " << json << " FAILED");
390 0 : return ret;
391 : }
392 0 : size += ret;
393 0 : current_sandesh_context_.pop_back();
394 0 : is_first_element_context_.pop_back();
395 0 : is_primitive_element_list_.pop_back();
396 0 : return size;
397 0 : }
398 :
399 0 : int32_t TJSONProtocol::writeContainerElementBegin() {
400 0 : int32_t size = 0, ret;
401 0 : indentDown();
402 0 : string json;
403 0 : json.reserve(128);
404 :
405 0 : if (!is_first_element_context_.back()) {
406 : // could be in map or list context, print , only in case of map val
407 0 : if (current_sandesh_context_.back() == "MAP") {
408 0 : if (!in_map_val_context_.back()) {
409 : // print only before keys
410 0 : json += ",";
411 : }
412 : } else {
413 0 : json += ",";
414 : }
415 : } else {
416 0 : is_first_element_context_.back() = false;
417 : }
418 :
419 0 : if (current_sandesh_context_.back() == "LIST" &&
420 0 : is_primitive_element_list_.back()) {
421 0 : if(is_list_elem_string_) {
422 0 : json += "\"";
423 : }
424 : }
425 :
426 0 : if (current_sandesh_context_.back() == "MAP") {
427 0 : if (is_primitive_element_list_.back()) {
428 0 : json+= "\"";
429 : }
430 : }
431 0 : return writeIndented(json);
432 : //return writeIndented(kJSONElementTagO);
433 0 : }
434 :
435 : /*
436 : * This fn will be called for primitive
437 : * types.
438 : */
439 0 : int32_t TJSONProtocol::writeContainerElementEnd() {
440 0 : int32_t size = 0, ret;
441 0 : indentDown();
442 0 : string json;
443 0 : json.reserve(128);
444 :
445 0 : if (current_sandesh_context_.back() == "MAP") {
446 0 : if (is_primitive_element_list_.back()) {
447 0 : json += "\"";
448 : }
449 : // print : if its map key else dont
450 0 : if (in_map_val_context_.back()) {
451 0 : in_map_val_context_.back() = false;
452 : } else {
453 : // In map key context
454 0 : json += ":";
455 0 : if (is_map_val_primitive_.back()) {
456 0 : in_map_val_context_.back() = true;
457 : }
458 : }
459 : }
460 :
461 0 : if (current_sandesh_context_.back() == "LIST" &&
462 0 : is_primitive_element_list_.back()) {
463 0 : if (is_list_elem_string_) {
464 0 : json += "\"";
465 : }
466 : }
467 :
468 0 : return writeIndented(json);
469 0 : }
470 :
471 :
472 : /*
473 : * This function is called for every field
474 : * of type struct. JSON uses "," seperated
475 : * entries to hold list of values. We
476 : * maintain state variables to add comma or
477 : * not after each entry.
478 : * First we write meta data about the field,
479 : * then we store the actual value under the
480 : * tag "VAL". The new stats collections are
481 : * decided based on the annotations of the individual
482 : * fields.
483 : */
484 0 : int32_t TJSONProtocol::writeFieldBegin(const char *name,
485 : const TType fieldType,
486 : const int16_t fieldId,
487 : const std::map<std::string, std::string> *const amap) {
488 0 : int32_t size = 0, ret;
489 0 : string sname(name);
490 0 : string json;
491 0 : json.reserve(512);
492 :
493 0 : if (!is_first_element_context_.back() &&
494 0 : current_sandesh_context_.back() != "MAP") {
495 0 : json += ",";
496 : } else {
497 0 : is_first_element_context_.back() = false;
498 : }
499 :
500 0 : json += "\"";
501 0 : json += sname;
502 0 : json += "\"";
503 0 : json += ":";
504 0 : json += kJSONTagO; // : {
505 0 : json += endl;
506 0 : indentUp();
507 0 : json += kType; // "TYPE":
508 0 : json += "\"";
509 0 : json += fieldTypeName(fieldType);
510 0 : json += "\"";
511 0 : json += ",";
512 0 : json += endl;
513 :
514 0 : if(amap != NULL) {
515 0 : json += "\"ANNOTATION\":";
516 0 : json += "{";
517 0 : std::map<std::string, std::string>::const_iterator it;
518 0 : for(it = amap->begin(); it != amap->end(); it++) {
519 0 : json += "\""+it->first+"\"";
520 0 : json += ":";
521 0 : json += "\""+it->second+"\"";
522 0 : json += ",";
523 : }
524 0 : json.erase(json.size()-1);
525 0 : json += "},";
526 : }
527 :
528 0 : json += "\"VAL\":";
529 : //If field type is string quote it
530 0 : if(fieldType == T_STRING || fieldType == T_IPADDR || fieldType == T_UUID) {
531 0 : is_string_begin_ = true;
532 0 : json += "\"";
533 : }
534 0 : json += endl;
535 : // Write to transport
536 0 : if ((ret = writeIndented(json)) < 0) {
537 0 : LOG(ERROR, __func__ << ": " << json << " FAILED");
538 0 : return ret;
539 : }
540 0 : size += ret;
541 0 : return size;
542 0 : }
543 :
544 0 : int32_t TJSONProtocol::writeFieldEnd() {
545 0 : int32_t size = 0, ret;
546 0 : string json;
547 0 : indentDown();
548 0 : if(is_string_begin_) {
549 0 : is_string_begin_ = false;
550 0 : json += "\"";
551 : }
552 0 : json += "}";
553 0 : if ((ret = writeIndented(json)) < 0) {
554 0 : LOG(ERROR, __func__ << ": " << json << " FAILED");
555 0 : return ret;
556 : }
557 0 : size += ret;
558 0 : return size;
559 0 : }
560 :
561 0 : int32_t TJSONProtocol::writeFieldStop() {
562 0 : return 0;
563 : }
564 :
565 0 : int32_t TJSONProtocol::writeMapBegin(const TType keyType,
566 : const TType valType,
567 : const uint32_t size) {
568 :
569 0 : int32_t bsize = 0, ret;
570 0 : string json;
571 0 : json.reserve(256);
572 0 : current_sandesh_context_.push_back("MAP");
573 0 : is_first_element_context_.push_back(true);
574 0 : json += "{";
575 0 : json += endl;
576 0 : json += "\"VALUE\":";
577 0 : json += "\"";
578 0 : json += fieldTypeName(valType);
579 0 : json += "\"";
580 0 : json += ",";
581 0 : json += "\"VAL\":";
582 0 : json += "{";
583 :
584 0 : indentUp();
585 : // Write to transport
586 0 : ret = writeIndented(json);
587 0 : if (ret < 0) {
588 0 : LOG(ERROR, __func__ << ": Key: " << fieldTypeName(keyType) <<
589 : " Value: " << fieldTypeName(valType) << " FAILED");
590 0 : return ret;
591 : }
592 :
593 0 : if (keyType == T_MAP || keyType == T_STRUCT || keyType == T_LIST) {
594 0 : is_primitive_element_list_.push_back(false);
595 : } else {
596 0 : is_primitive_element_list_.push_back(true);
597 : }
598 :
599 0 : if(valType == T_MAP || valType == T_STRUCT || valType == T_LIST) {
600 0 : in_non_primitive_map_context_ = true;
601 0 : is_map_val_primitive_.push_back(false);
602 0 : in_map_val_context_.push_back(false);
603 : } else {
604 0 : is_map_primitive_ = true;
605 0 : is_map_val_primitive_.push_back(true);
606 0 : in_map_val_context_.push_back(false);
607 : }
608 :
609 0 : bsize += ret;
610 0 : indentUp();
611 0 : return bsize;
612 :
613 0 : }
614 :
615 0 : int32_t TJSONProtocol::writeMapEnd() {
616 0 : int32_t size = 0, ret;
617 0 : string json;
618 0 : json.reserve(256);
619 0 : indentDown();
620 0 : json += "}";
621 0 : json += endl;
622 :
623 0 : indentDown();
624 0 : json += "}";
625 0 : json += endl;
626 :
627 :
628 0 : if ((ret = writeIndented(json)) < 0) {
629 0 : LOG(ERROR, __func__ << " FAILED");
630 0 : return ret;
631 : }
632 0 : current_sandesh_context_.pop_back();
633 0 : is_first_element_context_.pop_back();
634 0 : if (is_first_element_context_.size() > 0) {
635 0 : is_first_element_context_.back() = false;
636 : }
637 0 : is_primitive_element_list_.pop_back();
638 0 : in_map_val_context_.pop_back();
639 0 : is_map_val_primitive_.pop_back();
640 0 : size += ret;
641 0 : return size;
642 0 : }
643 :
644 0 : int32_t TJSONProtocol::writeListBegin(const TType elemType,
645 : const uint32_t size) {
646 0 : int32_t bsize = 0, ret;
647 0 : string json;
648 0 : json.reserve(256);
649 :
650 0 : if (is_first_element_context_.size() > 0 &&
651 0 : !is_first_element_context_.back() &&
652 0 : current_sandesh_context_.back() == "LIST") {
653 0 : json += ",";
654 0 : } else if (is_first_element_context_.size() > 0) {
655 0 : is_first_element_context_.back() = false;
656 : }
657 :
658 0 : current_sandesh_context_.push_back("LIST");
659 0 : is_first_element_context_.push_back(true);
660 0 : json += "{";
661 0 : json += "\"VAL\":";
662 0 : json += "[";
663 0 : json += endl;
664 : // Write to transport
665 0 : ret = writeIndented(json);
666 0 : if (ret < 0) {
667 0 : LOG(ERROR, __func__ << ": " << fieldTypeName(elemType) <<
668 : " FAILED");
669 0 : return ret;
670 : }
671 0 : is_list_begin_list_.push_back(true);
672 0 : if(elemType != T_STRUCT || elemType != T_MAP ) {
673 : //primitive type
674 0 : if(elemType == T_STRING || elemType == T_IPADDR || elemType == T_UUID) {
675 0 : is_list_elem_string_ = true;
676 : }
677 0 : is_primitive_element_list_.push_back(true);
678 : //in_list_context_ = true;
679 : } else {
680 0 : is_primitive_element_list_.push_back(false);
681 : }
682 0 : bsize += ret;
683 0 : indentUp();
684 0 : return bsize;
685 0 : }
686 :
687 0 : int32_t TJSONProtocol::writeListEnd() {
688 0 : int32_t size = 0, ret;
689 0 : string json;
690 0 : json.reserve(32);
691 0 : indentDown();
692 0 : json += "]";
693 0 : indentDown();
694 0 : json += "}";
695 0 : ret = writeIndented(json);
696 :
697 0 : if (ret < 0) {
698 0 : LOG(ERROR, __func__ << " FAILED");
699 0 : return ret;
700 : }
701 0 : size += ret;
702 0 : current_sandesh_context_.pop_back();
703 0 : is_first_element_context_.pop_back();
704 0 : if (is_first_element_context_.size() > 0) {
705 0 : is_first_element_context_.back() = false;
706 : }
707 0 : is_primitive_element_list_.pop_back();
708 0 : return size;
709 0 : }
710 :
711 0 : int32_t TJSONProtocol::writeSetBegin(const TType elemType,
712 : const uint32_t size) {
713 0 : int32_t bsize = 0, ret;
714 0 : string json;
715 0 : json.reserve(256);
716 :
717 0 : if (is_first_element_context_.size() > 0 &&
718 0 : !is_first_element_context_.back() &&
719 0 : current_sandesh_context_.back() == "SET") {
720 0 : json += ",";
721 0 : } else if (is_first_element_context_.size() > 0) {
722 0 : is_first_element_context_.back() = false;
723 : }
724 :
725 0 : current_sandesh_context_.push_back("SET");
726 0 : is_first_element_context_.push_back(true);
727 0 : json += "{";
728 0 : json += "\"VAL\":";
729 0 : json += "[";
730 0 : json += endl;
731 : // Write to transport
732 0 : ret = writeIndented(json);
733 0 : if (ret < 0) {
734 0 : LOG(ERROR, __func__ << ": " << fieldTypeName(elemType) <<
735 : " FAILED");
736 0 : return ret;
737 : }
738 0 : is_list_begin_list_.push_back(true);
739 0 : if(elemType != T_STRUCT || elemType != T_MAP ) {
740 : //primitive type
741 0 : if(elemType == T_STRING || elemType == T_IPADDR || elemType == T_UUID) {
742 0 : is_list_elem_string_ = true;
743 : }
744 0 : is_primitive_element_list_.push_back(true);
745 : //in_list_context_ = true;
746 : } else {
747 0 : is_primitive_element_list_.push_back(false);
748 : }
749 0 : bsize += ret;
750 0 : indentUp();
751 0 : return bsize;
752 0 : }
753 :
754 0 : int32_t TJSONProtocol::writeSetEnd() {
755 0 : int32_t size = 0, ret;
756 0 : string json;
757 0 : json.reserve(32);
758 0 : indentDown();
759 0 : json += "]";
760 0 : indentDown();
761 0 : json += "}";
762 0 : ret = writeIndented(json);
763 :
764 0 : if (ret < 0) {
765 0 : LOG(ERROR, __func__ << " FAILED");
766 0 : return ret;
767 : }
768 0 : size += ret;
769 0 : current_sandesh_context_.pop_back();
770 0 : is_first_element_context_.pop_back();
771 0 : if (is_first_element_context_.size() > 0) {
772 0 : is_first_element_context_.back() = false;
773 : }
774 0 : is_primitive_element_list_.pop_back();
775 0 : return size;
776 0 : }
777 :
778 0 : int32_t TJSONProtocol::writeBool(const bool value) {
779 0 : int32_t size = 0, ret;
780 0 : return writePlain(value ? kJSONBoolTrue : kJSONBoolFalse);
781 : }
782 :
783 0 : int32_t TJSONProtocol::writeByte(const int8_t byte) {
784 0 : return writePlain(integerToString(byte));
785 : }
786 :
787 0 : int32_t TJSONProtocol::writeI16(const int16_t i16) {
788 0 : return writePlain(integerToString(i16));
789 : }
790 :
791 0 : int32_t TJSONProtocol::writeI32(const int32_t i32) {
792 0 : int32_t size = 0, ret;
793 0 : string json;
794 0 : json.reserve(512);
795 0 : json += integerToString(i32);
796 0 : return writePlain(json);
797 0 : }
798 :
799 0 : int32_t TJSONProtocol::writeI64(const int64_t i64) {
800 0 : return writePlain(integerToString(i64));
801 : }
802 :
803 0 : int32_t TJSONProtocol::writeU16(const uint16_t u16) {
804 0 : return writePlain(integerToString(u16));
805 : }
806 :
807 0 : int32_t TJSONProtocol::writeU32(const uint32_t u32) {
808 0 : return writePlain(integerToString(u32));
809 : }
810 :
811 0 : int32_t TJSONProtocol::writeU64(const uint64_t u64) {
812 0 : return writePlain(integerToString(u64));
813 : }
814 :
815 0 : int32_t TJSONProtocol::writeIPV4(const uint32_t ip4) {
816 0 : return writePlain(integerToString(ip4));
817 : }
818 :
819 0 : int32_t TJSONProtocol::writeIPADDR(const boost::asio::ip::address& ipaddress) {
820 0 : return writePlain(ipaddress.to_string());
821 : }
822 :
823 0 : int32_t TJSONProtocol::writeDouble(const double dub) {
824 0 : return writePlain(integerToString(dub));
825 : }
826 :
827 0 : int32_t TJSONProtocol::writeString(const string& str) {
828 0 : int32_t size = 0, ret;
829 0 : string json;
830 0 : json.reserve(512);
831 0 : json += str;
832 : // Escape JSON control characters in the string before writing
833 0 : return writePlain(escapeJSONControlChars(json));
834 0 : }
835 :
836 0 : int32_t TJSONProtocol::writeBinary(const string& str) {
837 : // XXX Hex?
838 0 : return writeString(str);
839 : }
840 :
841 0 : int32_t TJSONProtocol::writeUUID(const boost::uuids::uuid& uuid) {
842 0 : const std::string str = boost::uuids::to_string(uuid);
843 0 : return writeString(str);
844 0 : }
845 :
846 : }}} // contrail::sandesh::protocol
|