Subversion Repositories SmartDukaan

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
30 ashish 1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements. See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership. The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License. You may obtain a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied. See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
 
20
#include "TDebugProtocol.h"
21
 
22
#include <cassert>
23
#include <cctype>
24
#include <cstdio>
25
#include <stdexcept>
26
#include <boost/static_assert.hpp>
27
#include <boost/lexical_cast.hpp>
28
 
29
using std::string;
30
 
31
 
32
static string byte_to_hex(const uint8_t byte) {
33
  char buf[3];
34
  int ret = std::sprintf(buf, "%02x", (int)byte);
35
  assert(ret == 2);
36
  assert(buf[2] == '\0');
37
  return buf;
38
}
39
 
40
 
41
namespace apache { namespace thrift { namespace protocol {
42
 
43
string TDebugProtocol::fieldTypeName(TType type) {
44
  switch (type) {
45
    case T_STOP   : return "stop"   ;
46
    case T_VOID   : return "void"   ;
47
    case T_BOOL   : return "bool"   ;
48
    case T_BYTE   : return "byte"   ;
49
    case T_I16    : return "i16"    ;
50
    case T_I32    : return "i32"    ;
51
    case T_U64    : return "u64"    ;
52
    case T_I64    : return "i64"    ;
53
    case T_DOUBLE : return "double" ;
54
    case T_STRING : return "string" ;
55
    case T_STRUCT : return "struct" ;
56
    case T_MAP    : return "map"    ;
57
    case T_SET    : return "set"    ;
58
    case T_LIST   : return "list"   ;
59
    case T_UTF8   : return "utf8"   ;
60
    case T_UTF16  : return "utf16"  ;
61
    default: return "unknown";
62
  }
63
}
64
 
65
void TDebugProtocol::indentUp() {
66
  indent_str_ += string(indent_inc, ' ');
67
}
68
 
69
void TDebugProtocol::indentDown() {
70
  if (indent_str_.length() < (string::size_type)indent_inc) {
71
    throw TProtocolException(TProtocolException::INVALID_DATA);
72
  }
73
  indent_str_.erase(indent_str_.length() - indent_inc);
74
}
75
 
76
uint32_t TDebugProtocol::writePlain(const string& str) {
77
  trans_->write((uint8_t*)str.data(), str.length());
78
  return str.length();
79
}
80
 
81
uint32_t TDebugProtocol::writeIndented(const string& str) {
82
  trans_->write((uint8_t*)indent_str_.data(), indent_str_.length());
83
  trans_->write((uint8_t*)str.data(), str.length());
84
  return indent_str_.length() + str.length();
85
}
86
 
87
uint32_t TDebugProtocol::startItem() {
88
  uint32_t size;
89
 
90
  switch (write_state_.back()) {
91
    case UNINIT:
92
      // XXX figure out what to do here.
93
      //throw TProtocolException(TProtocolException::INVALID_DATA);
94
      //return writeIndented(str);
95
      return 0;
96
    case STRUCT:
97
      return 0;
98
    case SET:
99
      return writeIndented("");
100
    case MAP_KEY:
101
      return writeIndented("");
102
    case MAP_VALUE:
103
      return writePlain(" -> ");
104
    case LIST:
105
      size = writeIndented(
106
          "[" + boost::lexical_cast<string>(list_idx_.back()) + "] = ");
107
      list_idx_.back()++;
108
      return size;
109
    default:
110
      throw std::logic_error("Invalid enum value.");
111
  }
112
}
113
 
114
uint32_t TDebugProtocol::endItem() {
115
  //uint32_t size;
116
 
117
  switch (write_state_.back()) {
118
    case UNINIT:
119
      // XXX figure out what to do here.
120
      //throw TProtocolException(TProtocolException::INVALID_DATA);
121
      //return writeIndented(str);
122
      return 0;
123
    case STRUCT:
124
      return writePlain(",\n");
125
    case SET:
126
      return writePlain(",\n");
127
    case MAP_KEY:
128
      write_state_.back() = MAP_VALUE;
129
      return 0;
130
    case MAP_VALUE:
131
      write_state_.back() = MAP_KEY;
132
      return writePlain(",\n");
133
    case LIST:
134
      return writePlain(",\n");
135
    default:
136
      throw std::logic_error("Invalid enum value.");
137
  }
138
}
139
 
140
uint32_t TDebugProtocol::writeItem(const std::string& str) {
141
  uint32_t size = 0;
142
  size += startItem();
143
  size += writePlain(str);
144
  size += endItem();
145
  return size;
146
}
147
 
148
uint32_t TDebugProtocol::writeMessageBegin(const std::string& name,
149
                                           const TMessageType messageType,
150
                                           const int32_t seqid) {
151
  string mtype;
152
  switch (messageType) {
153
    case T_CALL      : mtype = "call"  ; break;
154
    case T_REPLY     : mtype = "reply" ; break;
155
    case T_EXCEPTION : mtype = "exn"   ; break;
156
  }
157
 
158
  uint32_t size = writeIndented("(" + mtype + ") " + name + "(");
159
  indentUp();
160
  return size;
161
}
162
 
163
uint32_t TDebugProtocol::writeMessageEnd() {
164
  indentDown();
165
  return writeIndented(")\n");
166
}
167
 
168
uint32_t TDebugProtocol::writeStructBegin(const char* name) {
169
  uint32_t size = 0;
170
  size += startItem();
171
  size += writePlain(string(name) + " {\n");
172
  indentUp();
173
  write_state_.push_back(STRUCT);
174
  return size;
175
}
176
 
177
uint32_t TDebugProtocol::writeStructEnd() {
178
  indentDown();
179
  write_state_.pop_back();
180
  uint32_t size = 0;
181
  size += writeIndented("}");
182
  size += endItem();
183
  return size;
184
}
185
 
186
uint32_t TDebugProtocol::writeFieldBegin(const char* name,
187
                                         const TType fieldType,
188
                                         const int16_t fieldId) {
189
  // sprintf(id_str, "%02d", fieldId);
190
  string id_str = boost::lexical_cast<string>(fieldId);
191
  if (id_str.length() == 1) id_str = '0' + id_str;
192
 
193
  return writeIndented(
194
      id_str + ": " +
195
      name + " (" +
196
      fieldTypeName(fieldType) + ") = ");
197
}
198
 
199
uint32_t TDebugProtocol::writeFieldEnd() {
200
  assert(write_state_.back() == STRUCT);
201
  return 0;
202
}
203
 
204
uint32_t TDebugProtocol::writeFieldStop() {
205
  return 0;
206
    //writeIndented("***STOP***\n");
207
}
208
 
209
uint32_t TDebugProtocol::writeMapBegin(const TType keyType,
210
                                       const TType valType,
211
                                       const uint32_t size) {
212
  // TODO(dreiss): Optimize short maps?
213
  uint32_t bsize = 0;
214
  bsize += startItem();
215
  bsize += writePlain(
216
      "map<" + fieldTypeName(keyType) + "," + fieldTypeName(valType) + ">"
217
      "[" + boost::lexical_cast<string>(size) + "] {\n");
218
  indentUp();
219
  write_state_.push_back(MAP_KEY);
220
  return bsize;
221
}
222
 
223
uint32_t TDebugProtocol::writeMapEnd() {
224
  indentDown();
225
  write_state_.pop_back();
226
  uint32_t size = 0;
227
  size += writeIndented("}");
228
  size += endItem();
229
  return size;
230
}
231
 
232
uint32_t TDebugProtocol::writeListBegin(const TType elemType,
233
                                        const uint32_t size) {
234
  // TODO(dreiss): Optimize short arrays.
235
  uint32_t bsize = 0;
236
  bsize += startItem();
237
  bsize += writePlain(
238
      "list<" + fieldTypeName(elemType) + ">"
239
      "[" + boost::lexical_cast<string>(size) + "] {\n");
240
  indentUp();
241
  write_state_.push_back(LIST);
242
  list_idx_.push_back(0);
243
  return bsize;
244
}
245
 
246
uint32_t TDebugProtocol::writeListEnd() {
247
  indentDown();
248
  write_state_.pop_back();
249
  list_idx_.pop_back();
250
  uint32_t size = 0;
251
  size += writeIndented("}");
252
  size += endItem();
253
  return size;
254
}
255
 
256
uint32_t TDebugProtocol::writeSetBegin(const TType elemType,
257
                                       const uint32_t size) {
258
  // TODO(dreiss): Optimize short sets.
259
  uint32_t bsize = 0;
260
  bsize += startItem();
261
  bsize += writePlain(
262
      "set<" + fieldTypeName(elemType) + ">"
263
      "[" + boost::lexical_cast<string>(size) + "] {\n");
264
  indentUp();
265
  write_state_.push_back(SET);
266
  return bsize;
267
}
268
 
269
uint32_t TDebugProtocol::writeSetEnd() {
270
  indentDown();
271
  write_state_.pop_back();
272
  uint32_t size = 0;
273
  size += writeIndented("}");
274
  size += endItem();
275
  return size;
276
}
277
 
278
uint32_t TDebugProtocol::writeBool(const bool value) {
279
  return writeItem(value ? "true" : "false");
280
}
281
 
282
uint32_t TDebugProtocol::writeByte(const int8_t byte) {
283
  return writeItem("0x" + byte_to_hex(byte));
284
}
285
 
286
uint32_t TDebugProtocol::writeI16(const int16_t i16) {
287
  return writeItem(boost::lexical_cast<string>(i16));
288
}
289
 
290
uint32_t TDebugProtocol::writeI32(const int32_t i32) {
291
  return writeItem(boost::lexical_cast<string>(i32));
292
}
293
 
294
uint32_t TDebugProtocol::writeI64(const int64_t i64) {
295
  return writeItem(boost::lexical_cast<string>(i64));
296
}
297
 
298
uint32_t TDebugProtocol::writeDouble(const double dub) {
299
  return writeItem(boost::lexical_cast<string>(dub));
300
}
301
 
302
 
303
uint32_t TDebugProtocol::writeString(const string& str) {
304
  // XXX Raw/UTF-8?
305
 
306
  string to_show = str;
307
  if (to_show.length() > (string::size_type)string_limit_) {
308
    to_show = str.substr(0, string_prefix_size_);
309
    to_show += "[...](" + boost::lexical_cast<string>(str.length()) + ")";
310
  }
311
 
312
  string output = "\"";
313
 
314
  for (string::const_iterator it = to_show.begin(); it != to_show.end(); ++it) {
315
    if (*it == '\\') {
316
      output += "\\\\";
317
    } else if (*it == '"') {
318
      output += "\\\"";
319
    } else if (std::isprint(*it)) {
320
      output += *it;
321
    } else {
322
      switch (*it) {
323
        case '\a': output += "\\a"; break;
324
        case '\b': output += "\\b"; break;
325
        case '\f': output += "\\f"; break;
326
        case '\n': output += "\\n"; break;
327
        case '\r': output += "\\r"; break;
328
        case '\t': output += "\\t"; break;
329
        case '\v': output += "\\v"; break;
330
        default:
331
          output += "\\x";
332
          output += byte_to_hex(*it);
333
      }
334
    }
335
  }
336
 
337
  output += '\"';
338
  return writeItem(output);
339
}
340
 
341
uint32_t TDebugProtocol::writeBinary(const string& str) {
342
  // XXX Hex?
343
  return TDebugProtocol::writeString(str);
344
}
345
 
346
}}} // apache::thrift::protocol