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 <string.h>
21 #include <stdio.h>
22
23 #include <thrift/c_glib/thrift.h>
24 #include <thrift/c_glib/protocol/thrift_protocol.h>
25 #include <thrift/c_glib/protocol/thrift_compact_protocol.h>
26
27 #include <thrift/config.h>
28
29 /*
30 * *_to_zigzag depend on the fact that the right shift
31 * operator on a signed integer is an arithmetic (sign-extending) shift.
32 * If this is not the case, the current implementation will not work.
33 */
34 #if !defined(SIGNED_RIGHT_SHIFT_IS) || !defined(ARITHMETIC_RIGHT_SHIFT)
35 # error "Unable to determine the behavior of a signed right shift"
36 #endif
37 #if SIGNED_RIGHT_SHIFT_IS != ARITHMETIC_RIGHT_SHIFT
38 # error "thrift_compact_protocol only works if signed right shift is arithmetic"
39 #endif
40
41 /* object properties */
42 enum _ThriftCompactProtocolProperties
43 {
44 PROP_0,
45 PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT,
46 PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT
47 };
48
49 G_DEFINE_TYPE (ThriftCompactProtocol, thrift_compact_protocol,
50 THRIFT_TYPE_PROTOCOL)
51
52 static const gint8 PROTOCOL_ID = (gint8)0x82u;
53 static const gint8 VERSION_N = 1;
54 static const gint8 VERSION_MASK = 0x1f; /* 0001 1111 */
55 static const gint8 TYPE_MASK = (gint8)0xe0u; /* 1110 0000 */
56 static const gint8 TYPE_BITS = 0x07; /* 0000 0111 */
57 static const gint32 TYPE_SHIFT_AMOUNT = 5;
58
59 enum Types {
60 CT_STOP = 0x00,
61 CT_BOOLEAN_TRUE = 0x01,
62 CT_BOOLEAN_FALSE = 0x02,
63 CT_BYTE = 0x03,
64 CT_I16 = 0x04,
65 CT_I32 = 0x05,
66 CT_I64 = 0x06,
67 CT_DOUBLE = 0x07,
68 CT_BINARY = 0x08,
69 CT_LIST = 0x09,
70 CT_SET = 0x0A,
71 CT_MAP = 0x0B,
72 CT_STRUCT = 0x0C
73 };
74
75 static const gint8 TTypeToCType[16] = {
76 CT_STOP, /* T_STOP */
77 0, /* unused */
78 CT_BOOLEAN_TRUE, /* T_BOOL */
79 CT_BYTE, /* T_BYTE */
80 CT_DOUBLE, /* T_DOUBLE */
81 0, /* unused */
82 CT_I16, /* T_I16 */
83 0, /* unused */
84 CT_I32, /* T_I32 */
85 0, /* unused */
86 CT_I64, /* T_I64 */
87 CT_BINARY, /* T_STRING */
88 CT_STRUCT, /* T_STRUCT */
89 CT_MAP, /* T_MAP */
90 CT_SET, /* T_SET */
91 CT_LIST, /* T_LIST */
92 };
93
94 static guint64
thrift_bitwise_cast_guint64(const gdouble v)95 thrift_bitwise_cast_guint64 (const gdouble v)
96 {
97 union {
98 gdouble from;
99 guint64 to;
100 } u;
101 u.from = v;
102 return u.to;
103 }
104
105 static gdouble
thrift_bitwise_cast_gdouble(const guint64 v)106 thrift_bitwise_cast_gdouble (const guint64 v)
107 {
108 union {
109 guint64 from;
110 gdouble to;
111 } u;
112 u.from = v;
113 return u.to;
114 }
115
116 /**
117 * Convert l into a zigzag long. This allows negative numbers to be
118 * represented compactly as a varint.
119 */
120 static guint64
i64_to_zigzag(const gint64 l)121 i64_to_zigzag (const gint64 l)
122 {
123 return (((guint64)l) << 1) ^ (l >> 63);
124 }
125
126 /**
127 * Convert n into a zigzag int. This allows negative numbers to be
128 * represented compactly as a varint.
129 */
130 static guint32
i32_to_zigzag(const gint32 n)131 i32_to_zigzag (const gint32 n)
132 {
133 return (((guint32)n) << 1) ^ (n >> 31);
134 }
135
136 /**
137 * Convert from zigzag int to int.
138 */
139 static gint32
zigzag_to_i32(guint32 n)140 zigzag_to_i32 (guint32 n)
141 {
142 return (n >> 1) ^ (guint32) (-(gint32) (n & 1));
143 }
144
145 /**
146 * Convert from zigzag long to long.
147 */
148 static gint64
zigzag_to_i64(guint64 n)149 zigzag_to_i64 (guint64 n)
150 {
151 return (n >> 1) ^ (guint64) (-(gint64) (n & 1));
152 }
153
thrift_compact_protocol_get_ttype(ThriftCompactProtocol * protocol,const gint8 type,GError ** error)154 ThriftType thrift_compact_protocol_get_ttype (ThriftCompactProtocol *protocol,
155 const gint8 type, GError **error)
156 {
157 THRIFT_UNUSED_VAR (protocol);
158
159 switch (type) {
160 case T_STOP:
161 return T_STOP;
162 case CT_BOOLEAN_FALSE:
163 case CT_BOOLEAN_TRUE:
164 return T_BOOL;
165 case CT_BYTE:
166 return T_BYTE;
167 case CT_I16:
168 return T_I16;
169 case CT_I32:
170 return T_I32;
171 case CT_I64:
172 return T_I64;
173 case CT_DOUBLE:
174 return T_DOUBLE;
175 case CT_BINARY:
176 return T_STRING;
177 case CT_LIST:
178 return T_LIST;
179 case CT_SET:
180 return T_SET;
181 case CT_MAP:
182 return T_MAP;
183 case CT_STRUCT:
184 return T_STRUCT;
185 default:
186 g_set_error (error, THRIFT_PROTOCOL_ERROR,
187 THRIFT_PROTOCOL_ERROR_INVALID_DATA,
188 "unrecognized type");
189 return -1;
190 }
191 }
192
193 /**
194 * Write an i32 as a varint. Results in 1-5 bytes on the wire.
195 */
196 gint32
thrift_compact_protocol_write_varint32(ThriftCompactProtocol * protocol,const guint32 n,GError ** error)197 thrift_compact_protocol_write_varint32 (ThriftCompactProtocol *protocol,
198 const guint32 n,
199 GError **error)
200 {
201 guint8 buf[5];
202 gint32 xfer;
203 guint32 m;
204
205 THRIFT_UNUSED_VAR (error);
206
207 xfer = 0;
208 m = n;
209
210 while (TRUE) {
211 if ((m & ~0x7F) == 0) {
212 buf[xfer++] = (gint8)m;
213 break;
214 } else {
215 buf[xfer++] = (gint8)((m & 0x7F) | 0x80);
216 m >>= 7;
217 }
218 }
219
220 if (thrift_transport_write (THRIFT_PROTOCOL (protocol)->transport,
221 (const gpointer) buf, xfer, error)) {
222 return xfer;
223 } else {
224 return -1;
225 }
226 }
227
228 /**
229 * Write an i64 as a varint. Results in 1-10 bytes on the wire.
230 */
231 gint32
thrift_compact_protocol_write_varint64(ThriftCompactProtocol * protocol,const guint64 n,GError ** error)232 thrift_compact_protocol_write_varint64 (ThriftCompactProtocol *protocol,
233 const guint64 n,
234 GError **error)
235 {
236 guint8 buf[10];
237 gint32 xfer;
238 guint64 m;
239
240 THRIFT_UNUSED_VAR (error);
241
242 xfer = 0;
243 m = n;
244
245 while (TRUE) {
246 if ((m & ~0x7FL) == 0) {
247 buf[xfer++] = (gint8)m;
248 break;
249 } else {
250 buf[xfer++] = (gint8)((m & 0x7F) | 0x80);
251 m >>= 7;
252 }
253 }
254
255 if (thrift_transport_write (THRIFT_PROTOCOL (protocol)->transport,
256 (const gpointer) buf, xfer, error)) {
257 return xfer;
258 } else {
259 return -1;
260 }
261 }
262
263 /**
264 * Read an i64 from the wire as a proper varint. The MSB of each byte is set
265 * if there is another byte to follow. This can read up to 10 bytes.
266 */
267 gint32
thrift_compact_protocol_read_varint64(ThriftCompactProtocol * protocol,gint64 * i64,GError ** error)268 thrift_compact_protocol_read_varint64 (ThriftCompactProtocol *protocol,
269 gint64 *i64,
270 GError **error)
271 {
272 ThriftProtocol *tp;
273 gint32 ret;
274 gint32 xfer;
275 guint64 val;
276 gint shift;
277 guint8 byte;
278
279 tp = THRIFT_PROTOCOL (protocol);
280 xfer = 0;
281 val = 0;
282 shift = 0;
283 byte = 0;
284
285 while (TRUE) {
286 if ((ret = thrift_transport_read_all (tp->transport,
287 (gpointer) &byte, 1, error)) < 0) {
288 return -1;
289 }
290 ++xfer;
291 val |= (guint64)(byte & 0x7f) << shift;
292 shift += 7;
293 if (!(byte & 0x80)) {
294 *i64 = (gint64) val;
295 return xfer;
296 }
297 if (G_UNLIKELY (xfer == 10)) { /* 7 * 9 < 64 < 7 * 10 */
298 g_set_error (error, THRIFT_PROTOCOL_ERROR,
299 THRIFT_PROTOCOL_ERROR_INVALID_DATA,
300 "variable-length int over 10 bytes");
301 return -1;
302 }
303 }
304 }
305
306 /**
307 * Read an i32 from the wire as a varint. The MSB of each byte is set
308 * if there is another byte to follow. This can read up to 5 bytes.
309 */
310 gint32
thrift_compact_protocol_read_varint32(ThriftCompactProtocol * protocol,gint32 * i32,GError ** error)311 thrift_compact_protocol_read_varint32 (ThriftCompactProtocol *protocol,
312 gint32 *i32,
313 GError **error)
314 {
315 gint64 val;
316 gint32 ret;
317 gint32 xfer;
318
319 xfer = 0;
320
321 if ((ret = thrift_compact_protocol_read_varint64 (protocol, &val,
322 error)) < 0) {
323 return -1;
324 }
325 xfer += ret;
326
327 *i32 = (gint32)val;
328
329 return xfer;
330 }
331
332 gint32
thrift_compact_protocol_write_field_begin_internal(ThriftCompactProtocol * protocol,const gchar * name,const ThriftType field_type,const gint16 field_id,const gint8 type_override,GError ** error)333 thrift_compact_protocol_write_field_begin_internal (ThriftCompactProtocol
334 *protocol,
335 const gchar *name,
336 const ThriftType field_type,
337 const gint16 field_id,
338 const gint8 type_override,
339 GError **error)
340 {
341 gint32 ret;
342 gint32 xfer;
343 gint8 type_to_write;
344
345 THRIFT_UNUSED_VAR (name);
346
347 xfer = 0;
348
349 /* if there's a type override, use that. */
350 type_to_write
351 = (type_override == -1 ? TTypeToCType[field_type] : type_override);
352
353 /* check if we can use delta encoding for the field id */
354 if (field_id > protocol->_last_field_id
355 && field_id - protocol->_last_field_id <= 15) {
356 /* write them together */
357 if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol),
358 (gint8) ((field_id
359 - protocol->_last_field_id)
360 << 4 | type_to_write),
361 error)) < 0) {
362 return -1;
363 }
364 xfer += ret;
365 } else {
366 /* write them separate */
367 if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol),
368 type_to_write, error)) < 0) {
369 return -1;
370 }
371 xfer += ret;
372
373 if ((ret = thrift_protocol_write_i16 (THRIFT_PROTOCOL (protocol), field_id,
374 error)) < 0) {
375 return -1;
376 }
377 xfer += ret;
378 }
379
380 protocol->_last_field_id = field_id;
381 return xfer;
382 }
383
384 /**
385 * Method for writing the start of lists and sets. List and sets on
386 * the wire differ only by the type indicator.
387 */
388 gint32
thrift_compact_protocol_write_collection_begin(ThriftCompactProtocol * protocol,const ThriftType elem_type,guint32 size,GError ** error)389 thrift_compact_protocol_write_collection_begin (ThriftCompactProtocol *protocol,
390 const ThriftType elem_type,
391 guint32 size, GError **error)
392 {
393 gint32 ret;
394 gint32 xfer;
395
396 xfer = 0;
397
398 if (size <= 14) {
399 if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol),
400 (gint8) (size << 4
401 | TTypeToCType[elem_type]),
402 error)) < 0) {
403 return -1;
404 }
405 xfer += ret;
406 } else {
407 if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol),
408 (gint8) (0xf0
409 | TTypeToCType[elem_type]),
410 error)) < 0) {
411 return -1;
412 }
413 xfer += ret;
414
415 if ((ret = thrift_compact_protocol_write_varint32 (protocol,
416 (guint32) size,
417 error)) < 0) {
418 return -1;
419 }
420 xfer += ret;
421 }
422
423 return xfer;
424 }
425
426 /*
427 * public methods
428 */
429
430 gint32
thrift_compact_protocol_write_message_begin(ThriftProtocol * protocol,const gchar * name,const ThriftMessageType message_type,const gint32 seqid,GError ** error)431 thrift_compact_protocol_write_message_begin (ThriftProtocol *protocol,
432 const gchar *name,
433 const ThriftMessageType
434 message_type,
435 const gint32 seqid, GError **error)
436 {
437 gint8 version;
438 gint32 ret;
439 gint32 xfer;
440
441 ThriftCompactProtocol *cp;
442
443 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
444
445 cp = THRIFT_COMPACT_PROTOCOL (protocol);
446
447 version = (VERSION_N & VERSION_MASK)
448 | (((gint32) message_type << TYPE_SHIFT_AMOUNT) & TYPE_MASK);
449 xfer = 0;
450
451 if ((ret = thrift_protocol_write_byte (protocol, PROTOCOL_ID, error)) < 0) {
452 return -1;
453 }
454 xfer += ret;
455
456 if ((ret = thrift_protocol_write_byte (protocol, version, error)) < 0) {
457 return -1;
458 }
459 xfer += ret;
460
461 if ((ret = thrift_compact_protocol_write_varint32 (cp,
462 (guint32) seqid,
463 error)) < 0) {
464 return -1;
465 }
466 xfer += ret;
467
468 if ((ret = thrift_protocol_write_string (protocol, name, error)) < 0) {
469 return -1;
470 }
471 xfer += ret;
472
473 return xfer;
474 }
475
476 gint32
thrift_compact_protocol_write_message_end(ThriftProtocol * protocol,GError ** error)477 thrift_compact_protocol_write_message_end (ThriftProtocol *protocol,
478 GError **error)
479 {
480 /* satisfy -Wall */
481 THRIFT_UNUSED_VAR (protocol);
482 THRIFT_UNUSED_VAR (error);
483 return 0;
484 }
485
486 gint32
thrift_compact_protocol_write_struct_begin(ThriftProtocol * protocol,const gchar * name,GError ** error)487 thrift_compact_protocol_write_struct_begin (ThriftProtocol *protocol,
488 const gchar *name,
489 GError **error)
490 {
491 ThriftCompactProtocol *cp;
492 GQueue *q;
493
494 /* satisfy -Wall */
495 THRIFT_UNUSED_VAR (name);
496 THRIFT_UNUSED_VAR (error);
497
498 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
499
500 cp = THRIFT_COMPACT_PROTOCOL (protocol);
501 q = &(cp->_last_field);
502
503 g_queue_push_tail (q, GINT_TO_POINTER ((gint) cp->_last_field_id));
504 cp->_last_field_id = 0;
505 return 0;
506 }
507
508 gint32
thrift_compact_protocol_write_struct_end(ThriftProtocol * protocol,GError ** error)509 thrift_compact_protocol_write_struct_end (ThriftProtocol *protocol,
510 GError **error)
511 {
512 ThriftCompactProtocol *cp;
513 GQueue *q;
514
515 /* satisfy -Wall */
516 THRIFT_UNUSED_VAR (error);
517
518 cp = THRIFT_COMPACT_PROTOCOL (protocol);
519 q = &(cp->_last_field);
520
521 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
522
523 cp->_last_field_id = (gint16) GPOINTER_TO_INT (g_queue_pop_tail (q));
524 return 0;
525 }
526
527 gint32
thrift_compact_protocol_write_field_begin(ThriftProtocol * protocol,const gchar * name,const ThriftType field_type,const gint16 field_id,GError ** error)528 thrift_compact_protocol_write_field_begin (ThriftProtocol *protocol,
529 const gchar *name,
530 const ThriftType field_type,
531 const gint16 field_id,
532 GError **error)
533 {
534 ThriftCompactProtocol *cp;
535
536 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
537
538 cp = THRIFT_COMPACT_PROTOCOL (protocol);
539
540 if (field_type == T_BOOL) {
541 cp->_bool_field_name = name;
542 cp->_bool_field_type = field_type;
543 cp->_bool_field_id = field_id;
544 return 0;
545 } else {
546 return thrift_compact_protocol_write_field_begin_internal (cp, name,
547 field_type,
548 field_id, -1,
549 error);
550 }
551 }
552
553 gint32
thrift_compact_protocol_write_field_end(ThriftProtocol * protocol,GError ** error)554 thrift_compact_protocol_write_field_end (ThriftProtocol *protocol,
555 GError **error)
556 {
557 /* satisfy -Wall */
558 THRIFT_UNUSED_VAR (protocol);
559 THRIFT_UNUSED_VAR (error);
560 return 0;
561 }
562
563 gint32
thrift_compact_protocol_write_field_stop(ThriftProtocol * protocol,GError ** error)564 thrift_compact_protocol_write_field_stop (ThriftProtocol *protocol,
565 GError **error)
566 {
567 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
568 return thrift_protocol_write_byte (protocol, (gint8) T_STOP, error);
569 }
570
571 gint32
thrift_compact_protocol_write_map_begin(ThriftProtocol * protocol,const ThriftType key_type,const ThriftType value_type,const guint32 size,GError ** error)572 thrift_compact_protocol_write_map_begin (ThriftProtocol *protocol,
573 const ThriftType key_type,
574 const ThriftType value_type,
575 const guint32 size,
576 GError **error)
577 {
578 gint32 ret;
579 gint32 xfer;
580
581 ThriftCompactProtocol *cp;
582
583 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
584
585 cp = THRIFT_COMPACT_PROTOCOL (protocol);
586
587 xfer = 0;
588
589 if ((ret = thrift_compact_protocol_write_varint32 (cp, (guint32) size,
590 error)) < 0) {
591 return -1;
592 }
593 xfer += ret;
594
595 if (size > 0) {
596 if ((ret = thrift_protocol_write_byte (protocol,
597 (gint8) (TTypeToCType[key_type] << 4
598 | TTypeToCType[value_type]),
599 error)) < 0) {
600 return -1;
601 }
602 xfer += ret;
603 }
604
605 return xfer;
606 }
607
608 gint32
thrift_compact_protocol_write_map_end(ThriftProtocol * protocol,GError ** error)609 thrift_compact_protocol_write_map_end (ThriftProtocol *protocol,
610 GError **error)
611 {
612 THRIFT_UNUSED_VAR (protocol);
613 THRIFT_UNUSED_VAR (error);
614 return 0;
615 }
616
617 gint32
thrift_compact_protocol_write_list_begin(ThriftProtocol * protocol,const ThriftType element_type,const guint32 size,GError ** error)618 thrift_compact_protocol_write_list_begin (ThriftProtocol *protocol,
619 const ThriftType element_type,
620 const guint32 size,
621 GError **error)
622 {
623 ThriftCompactProtocol *cp;
624
625 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
626
627 cp = THRIFT_COMPACT_PROTOCOL (protocol);
628
629 return thrift_compact_protocol_write_collection_begin (cp, element_type,
630 size, error);
631 }
632
633 gint32
thrift_compact_protocol_write_list_end(ThriftProtocol * protocol,GError ** error)634 thrift_compact_protocol_write_list_end (ThriftProtocol *protocol,
635 GError **error)
636 {
637 THRIFT_UNUSED_VAR (protocol);
638 THRIFT_UNUSED_VAR (error);
639 return 0;
640 }
641
642 gint32
thrift_compact_protocol_write_set_begin(ThriftProtocol * protocol,const ThriftType element_type,const guint32 size,GError ** error)643 thrift_compact_protocol_write_set_begin (ThriftProtocol *protocol,
644 const ThriftType element_type,
645 const guint32 size,
646 GError **error)
647 {
648 ThriftCompactProtocol *cp;
649
650 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
651
652 cp = THRIFT_COMPACT_PROTOCOL (protocol);
653
654 return thrift_compact_protocol_write_collection_begin (cp, element_type,
655 size, error);
656 }
657
658 gint32
thrift_compact_protocol_write_set_end(ThriftProtocol * protocol,GError ** error)659 thrift_compact_protocol_write_set_end (ThriftProtocol *protocol, GError **error)
660 {
661 THRIFT_UNUSED_VAR (protocol);
662 THRIFT_UNUSED_VAR (error);
663 return 0;
664 }
665
666 gint32
thrift_compact_protocol_write_bool(ThriftProtocol * protocol,const gboolean value,GError ** error)667 thrift_compact_protocol_write_bool (ThriftProtocol *protocol,
668 const gboolean value, GError **error)
669 {
670 ThriftCompactProtocol *cp;
671
672 gint32 ret;
673 gint32 xfer;
674
675 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
676
677 cp = THRIFT_COMPACT_PROTOCOL (protocol);
678
679 xfer = 0;
680
681 if (cp->_bool_field_name != NULL) {
682 /* we haven't written the field header yet */
683 if ((ret = thrift_compact_protocol_write_field_begin_internal (cp,
684 cp->_bool_field_name,
685 cp->_bool_field_type,
686 cp->_bool_field_id,
687 (gint8) (value
688 ? CT_BOOLEAN_TRUE : CT_BOOLEAN_FALSE),
689 error)) < 0) {
690 return -1;
691 }
692 xfer += ret;
693
694 cp->_bool_field_name = NULL;
695 } else {
696 /* we're not part of a field, so just write the value */
697 if ((ret = thrift_protocol_write_byte (protocol,
698 (gint8) (value ? CT_BOOLEAN_TRUE
699 : CT_BOOLEAN_FALSE),
700 error)) < 0) {
701 return -1;
702 }
703 xfer += ret;
704 }
705 return xfer;
706 }
707
708 gint32
thrift_compact_protocol_write_byte(ThriftProtocol * protocol,const gint8 value,GError ** error)709 thrift_compact_protocol_write_byte (ThriftProtocol *protocol, const gint8 value,
710 GError **error)
711 {
712 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
713
714 if (thrift_transport_write (protocol->transport,
715 (const gpointer) &value, 1, error)) {
716 return 1;
717 } else {
718 return -1;
719 }
720 }
721
722 gint32
thrift_compact_protocol_write_i16(ThriftProtocol * protocol,const gint16 value,GError ** error)723 thrift_compact_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value,
724 GError **error)
725 {
726 ThriftCompactProtocol *cp;
727
728 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
729
730 cp = THRIFT_COMPACT_PROTOCOL (protocol);
731
732 return thrift_compact_protocol_write_varint32 (cp,
733 i32_to_zigzag ((gint32) value),
734 error);
735 }
736
737 gint32
thrift_compact_protocol_write_i32(ThriftProtocol * protocol,const gint32 value,GError ** error)738 thrift_compact_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value,
739 GError **error)
740 {
741 ThriftCompactProtocol *cp;
742
743 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
744
745 cp = THRIFT_COMPACT_PROTOCOL (protocol);
746
747 return thrift_compact_protocol_write_varint32 (cp,
748 i32_to_zigzag (value),
749 error);
750 }
751
752 gint32
thrift_compact_protocol_write_i64(ThriftProtocol * protocol,const gint64 value,GError ** error)753 thrift_compact_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value,
754 GError **error)
755 {
756 ThriftCompactProtocol *cp;
757
758 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
759
760 cp = THRIFT_COMPACT_PROTOCOL (protocol);
761
762 return thrift_compact_protocol_write_varint64 (cp,
763 i64_to_zigzag (value),
764 error);
765 }
766
767 gint32
thrift_compact_protocol_write_double(ThriftProtocol * protocol,const gdouble value,GError ** error)768 thrift_compact_protocol_write_double (ThriftProtocol *protocol,
769 const gdouble value, GError **error)
770 {
771 guint64 bits;
772
773 g_assert (sizeof (gdouble) == sizeof (guint64));
774
775 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
776
777 bits = GUINT64_TO_LE (thrift_bitwise_cast_guint64 (value));
778 if (thrift_transport_write (protocol->transport,
779 (const gpointer) &bits, 8, error)) {
780 return 8;
781 } else {
782 return -1;
783 }
784 }
785
786 gint32
thrift_compact_protocol_write_string(ThriftProtocol * protocol,const gchar * str,GError ** error)787 thrift_compact_protocol_write_string (ThriftProtocol *protocol,
788 const gchar *str, GError **error)
789 {
790 size_t len;
791
792 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
793
794 len = str != NULL ? strlen (str) : 0;
795 if (len > G_MAXINT32) {
796 g_set_error (error, THRIFT_PROTOCOL_ERROR,
797 THRIFT_PROTOCOL_ERROR_SIZE_LIMIT,
798 "string size (guess: %lu) is too large", (unsigned long) len);
799 return -1;
800 }
801
802 /* write the string length + 1 which includes the null terminator */
803 return thrift_protocol_write_binary (protocol, (const gpointer) str,
804 (const guint32) len, error);
805 }
806
807 gint32
thrift_compact_protocol_write_binary(ThriftProtocol * protocol,const gpointer buf,const guint32 len,GError ** error)808 thrift_compact_protocol_write_binary (ThriftProtocol *protocol,
809 const gpointer buf,
810 const guint32 len, GError **error)
811 {
812 ThriftCompactProtocol *cp;
813
814 gint32 ret;
815 gint32 xfer;
816
817 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
818
819 cp = THRIFT_COMPACT_PROTOCOL (protocol);
820
821 xfer = 0;
822
823 if ((ret = thrift_compact_protocol_write_varint32 (cp, len, error)) < 0) {
824 return -1;
825 }
826 xfer += ret;
827
828 if (len > 0) {
829 /* checking len + xfer > uint_max, but we don't want to overflow while
830 * checking for overflows. transforming to len > uint_max - xfer.
831 */
832 if (len > (guint32) (G_MAXINT32 - xfer)) {
833 g_set_error (error, THRIFT_PROTOCOL_ERROR,
834 THRIFT_PROTOCOL_ERROR_SIZE_LIMIT,
835 "size %d + %d is too large", len, xfer);
836 return -1;
837 }
838
839 if (thrift_transport_write (protocol->transport,
840 (const gpointer) buf, len, error) == FALSE) {
841 return -1;
842 }
843 xfer += len;
844 }
845
846 return xfer;
847 }
848
849 gint32
thrift_compact_protocol_read_message_begin(ThriftProtocol * protocol,gchar ** name,ThriftMessageType * message_type,gint32 * seqid,GError ** error)850 thrift_compact_protocol_read_message_begin (ThriftProtocol *protocol,
851 gchar **name,
852 ThriftMessageType *message_type,
853 gint32 *seqid, GError **error)
854 {
855 ThriftCompactProtocol *cp;
856
857 gint32 ret;
858 gint32 xfer;
859
860 gint8 protocol_id, version_and_type, version;
861
862 xfer = 0;
863
864 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
865
866 cp = THRIFT_COMPACT_PROTOCOL (protocol);
867
868 if ((ret = thrift_protocol_read_byte (protocol, &protocol_id, error)) < 0) {
869 return -1;
870 }
871 xfer += ret;
872
873 if (protocol_id != PROTOCOL_ID) {
874 g_set_error (error, THRIFT_PROTOCOL_ERROR,
875 THRIFT_PROTOCOL_ERROR_BAD_VERSION,
876 "bad protocol id");
877 return -1;
878 }
879
880 if ((ret = thrift_protocol_read_byte (protocol, &version_and_type,
881 error)) < 0) {
882 return -1;
883 }
884 xfer += ret;
885
886 version = (gint8)(version_and_type & VERSION_MASK);
887 if (version != VERSION_N) {
888 g_set_error (error, THRIFT_PROTOCOL_ERROR,
889 THRIFT_PROTOCOL_ERROR_BAD_VERSION,
890 "bad version and/or type");
891 return -1;
892 }
893
894 *message_type
895 = (ThriftMessageType)((version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS);
896
897 if ((ret = thrift_compact_protocol_read_varint32 (cp, seqid, error)) < 0) {
898 return -1;
899 }
900 xfer += ret;
901
902 if ((ret = thrift_protocol_read_string (protocol, name, error)) < 0) {
903 return -1;
904 }
905 xfer += ret;
906
907 return xfer;
908 }
909
910 gint32
thrift_compact_protocol_read_message_end(ThriftProtocol * protocol,GError ** error)911 thrift_compact_protocol_read_message_end (ThriftProtocol *protocol,
912 GError **error)
913 {
914 THRIFT_UNUSED_VAR (protocol);
915 THRIFT_UNUSED_VAR (error);
916 return 0;
917 }
918
919 gint32
thrift_compact_protocol_read_struct_begin(ThriftProtocol * protocol,gchar ** name,GError ** error)920 thrift_compact_protocol_read_struct_begin (ThriftProtocol *protocol,
921 gchar **name,
922 GError **error)
923 {
924 ThriftCompactProtocol *cp;
925 GQueue *q;
926
927 THRIFT_UNUSED_VAR (error);
928
929 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
930
931 cp = THRIFT_COMPACT_PROTOCOL (protocol);
932 q = &(cp->_last_field);
933
934 *name = NULL;
935
936 g_queue_push_tail (q, GINT_TO_POINTER ((gint) cp->_last_field_id));
937 cp->_last_field_id = 0;
938
939 return 0;
940 }
941
942 gint32
thrift_compact_protocol_read_struct_end(ThriftProtocol * protocol,GError ** error)943 thrift_compact_protocol_read_struct_end (ThriftProtocol *protocol,
944 GError **error)
945 {
946 ThriftCompactProtocol *cp;
947 GQueue *q;
948
949 THRIFT_UNUSED_VAR (error);
950
951 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
952
953 cp = THRIFT_COMPACT_PROTOCOL (protocol);
954 q = &(cp->_last_field);
955
956 cp->_last_field_id = (gint16) GPOINTER_TO_INT (g_queue_pop_tail (q));
957
958 return 0;
959 }
960
961 gint32
thrift_compact_protocol_read_field_begin(ThriftProtocol * protocol,gchar ** name,ThriftType * field_type,gint16 * field_id,GError ** error)962 thrift_compact_protocol_read_field_begin (ThriftProtocol *protocol,
963 gchar **name,
964 ThriftType *field_type,
965 gint16 *field_id,
966 GError **error)
967 {
968 ThriftCompactProtocol *cp;
969
970 gint32 ret;
971 gint32 xfer;
972
973 gint16 modifier;
974 gint8 byte;
975 gint8 type;
976
977 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
978
979 cp = THRIFT_COMPACT_PROTOCOL (protocol);
980
981 THRIFT_UNUSED_VAR (name);
982
983 xfer = 0;
984
985 if ((ret = thrift_protocol_read_byte (protocol, &byte, error)) < 0) {
986 return -1;
987 }
988 xfer += ret;
989
990 type = (byte & 0x0f);
991
992 /* if it's a stop, then we can return immediately, as the struct is over. */
993 if (type == T_STOP) {
994 *field_type = T_STOP;
995 *field_id = 0;
996 return xfer;
997 }
998
999 /* mask off the 4 MSB of the type header.
1000 * it could contain a field id delta.
1001 */
1002 modifier = (gint16)(((guint8)byte & 0xf0) >> 4);
1003 if (modifier == 0) {
1004 /* not a delta, look ahead for the zigzag varint field id. */
1005 if ((ret = thrift_protocol_read_i16 (protocol, field_id, error)) < 0) {
1006 return -1;
1007 }
1008 xfer += ret;
1009 } else {
1010 *field_id = (gint16)(cp->_last_field_id + modifier);
1011 }
1012 if ((ret = thrift_compact_protocol_get_ttype (cp, type, error)) < 0) {
1013 return -1;
1014 }
1015 *field_type = ret;
1016
1017 /* if this happens to be a boolean field, the value is encoded in the type */
1018 if (type == CT_BOOLEAN_TRUE || type == CT_BOOLEAN_FALSE) {
1019 /* save the boolean value in a special instance variable. */
1020 cp->_has_bool_value = TRUE;
1021 cp->_bool_value =
1022 (type == CT_BOOLEAN_TRUE ? TRUE : FALSE);
1023 }
1024
1025 /* push the new field onto the field stack so we can keep the deltas going. */
1026 cp->_last_field_id = *field_id;
1027
1028 return xfer;
1029 }
1030
1031 gint32
thrift_compact_protocol_read_field_end(ThriftProtocol * protocol,GError ** error)1032 thrift_compact_protocol_read_field_end (ThriftProtocol *protocol,
1033 GError **error)
1034 {
1035 THRIFT_UNUSED_VAR (protocol);
1036 THRIFT_UNUSED_VAR (error);
1037 return 0;
1038 }
1039
1040 gint32
thrift_compact_protocol_read_map_begin(ThriftProtocol * protocol,ThriftType * key_type,ThriftType * value_type,guint32 * size,GError ** error)1041 thrift_compact_protocol_read_map_begin (ThriftProtocol *protocol,
1042 ThriftType *key_type,
1043 ThriftType *value_type,
1044 guint32 *size,
1045 GError **error)
1046 {
1047 gint32 ret;
1048 gint32 xfer;
1049
1050 gint8 kv_type;
1051 gint32 msize;
1052
1053 ThriftCompactProtocol *cp;
1054 ThriftProtocol *tp = THRIFT_PROTOCOL (protocol);
1055 ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (tp->transport);
1056
1057 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1058
1059 kv_type = 0;
1060 msize = 0;
1061
1062 cp = THRIFT_COMPACT_PROTOCOL (protocol);
1063
1064 xfer = 0;
1065
1066 if ((ret = thrift_compact_protocol_read_varint32 (cp, &msize, error)) <0) {
1067 return -1;
1068 }
1069 xfer += ret;
1070
1071 /* still read the kv byte if negative size */
1072 if (msize != 0) {
1073 if ((ret = thrift_protocol_read_byte (protocol, &kv_type, error)) < 0) {
1074 return -1;
1075 }
1076 xfer += ret;
1077 }
1078
1079 if (cp->container_limit > 0 && msize > cp->container_limit) {
1080 g_set_error (error, THRIFT_PROTOCOL_ERROR,
1081 THRIFT_PROTOCOL_ERROR_SIZE_LIMIT,
1082 "got size over limit (%d > %d)", msize, cp->container_limit);
1083 return -1;
1084 } else if (msize > 0) {
1085 if ((ret = thrift_compact_protocol_get_ttype (cp,
1086 (gint8)((guint8)kv_type
1087 >> 4),
1088 error)) < 0) {
1089 return -1;
1090 }
1091 *key_type = ret;
1092 if ((ret = thrift_compact_protocol_get_ttype (cp,
1093 (gint8)((guint8)kv_type
1094 & 0xf),
1095 error)) < 0) {
1096 return -1;
1097 }
1098 *value_type = ret;
1099 *size = (guint32) msize;
1100 } else if (msize == 0) {
1101 *key_type = 0;
1102 *value_type = 0;
1103 *size = 0;
1104 } else {
1105 g_set_error (error, THRIFT_PROTOCOL_ERROR,
1106 THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE,
1107 "got negative size of %d", msize);
1108 return -1;
1109 }
1110
1111 if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport),
1112 msize * thrift_protocol_get_min_serialized_size (protocol, *key_type, error) +
1113 msize * thrift_protocol_get_min_serialized_size (protocol, *value_type, error),
1114 error))
1115 {
1116 return -1;
1117 }
1118
1119 return xfer;
1120 }
1121
1122 gint32
thrift_compact_protocol_read_map_end(ThriftProtocol * protocol,GError ** error)1123 thrift_compact_protocol_read_map_end (ThriftProtocol *protocol,
1124 GError **error)
1125 {
1126 THRIFT_UNUSED_VAR (protocol);
1127 THRIFT_UNUSED_VAR (error);
1128 return 0;
1129 }
1130
1131 gint32
thrift_compact_protocol_read_list_begin(ThriftProtocol * protocol,ThriftType * element_type,guint32 * size,GError ** error)1132 thrift_compact_protocol_read_list_begin (ThriftProtocol *protocol,
1133 ThriftType *element_type,
1134 guint32 *size, GError **error)
1135 {
1136 ThriftCompactProtocol *cp;
1137 ThriftProtocol *tp = THRIFT_PROTOCOL (protocol);
1138 ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (tp->transport);
1139 gint32 ret;
1140 gint32 xfer;
1141
1142 gint8 size_and_type;
1143 gint32 lsize;
1144
1145 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1146
1147 cp = THRIFT_COMPACT_PROTOCOL (protocol);
1148
1149 size_and_type = 0;
1150
1151 xfer = 0;
1152
1153 if ((ret = thrift_protocol_read_byte (protocol, &size_and_type, error)) < 0) {
1154 return -1;
1155 }
1156 xfer += ret;
1157
1158 lsize = ((guint8)size_and_type >> 4) & 0x0f;
1159 if (lsize == 15) {
1160 if ((ret = thrift_compact_protocol_read_varint32 (cp, &lsize, error)) < 0) {
1161 return -1;
1162 }
1163 xfer += ret;
1164 }
1165
1166 if (lsize < 0) {
1167 g_set_error (error, THRIFT_PROTOCOL_ERROR,
1168 THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE,
1169 "got negative size of %d", lsize);
1170 return -1;
1171 } else if (cp->container_limit > 0 && lsize > cp->container_limit) {
1172 g_set_error (error, THRIFT_PROTOCOL_ERROR,
1173 THRIFT_PROTOCOL_ERROR_SIZE_LIMIT,
1174 "got size over limit (%d > %d)", lsize, cp->container_limit);
1175 return -1;
1176 }
1177
1178 if ((ret = thrift_compact_protocol_get_ttype (cp,
1179 (gint8)(size_and_type & 0x0f),
1180 error)) < 0) {
1181 return -1;
1182 }
1183 *element_type = ret;
1184 *size = (guint32) lsize;
1185
1186 if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport),
1187 (lsize * thrift_protocol_get_min_serialized_size (protocol, *element_type, error)),
1188 error))
1189 {
1190 return -1;
1191 }
1192
1193 return xfer;
1194 }
1195
1196 gint32
thrift_compact_protocol_read_list_end(ThriftProtocol * protocol,GError ** error)1197 thrift_compact_protocol_read_list_end (ThriftProtocol *protocol,
1198 GError **error)
1199 {
1200 THRIFT_UNUSED_VAR (protocol);
1201 THRIFT_UNUSED_VAR (error);
1202 return 0;
1203 }
1204
1205 gint32
thrift_compact_protocol_read_set_begin(ThriftProtocol * protocol,ThriftType * element_type,guint32 * size,GError ** error)1206 thrift_compact_protocol_read_set_begin (ThriftProtocol *protocol,
1207 ThriftType *element_type,
1208 guint32 *size, GError **error)
1209 {
1210 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1211
1212 return thrift_protocol_read_list_begin (protocol, element_type, size, error);
1213 }
1214
1215 gint32
thrift_compact_protocol_read_set_end(ThriftProtocol * protocol,GError ** error)1216 thrift_compact_protocol_read_set_end (ThriftProtocol *protocol,
1217 GError **error)
1218 {
1219 THRIFT_UNUSED_VAR (protocol);
1220 THRIFT_UNUSED_VAR (error);
1221 return 0;
1222 }
1223
1224 gint32
thrift_compact_protocol_read_bool(ThriftProtocol * protocol,gboolean * value,GError ** error)1225 thrift_compact_protocol_read_bool (ThriftProtocol *protocol, gboolean *value,
1226 GError **error)
1227 {
1228 ThriftCompactProtocol *cp;
1229
1230 gint32 ret;
1231 gint32 xfer;
1232
1233 gint8 val;
1234
1235 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1236
1237 cp = THRIFT_COMPACT_PROTOCOL (protocol);
1238
1239 xfer = 0;
1240
1241 if (cp->_has_bool_value == TRUE) {
1242 *value = cp->_bool_value;
1243 cp->_has_bool_value = FALSE;
1244 return 0;
1245 } else {
1246 if ((ret = thrift_protocol_read_byte (protocol, &val, error)) < 0) {
1247 return -1;
1248 }
1249 xfer += ret;
1250
1251 *value = (val == CT_BOOLEAN_TRUE);
1252 return xfer;
1253 }
1254 }
1255
1256 gint32
thrift_compact_protocol_read_byte(ThriftProtocol * protocol,gint8 * value,GError ** error)1257 thrift_compact_protocol_read_byte (ThriftProtocol *protocol, gint8 *value,
1258 GError **error)
1259 {
1260 gint32 ret;
1261 gpointer b[1];
1262
1263 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1264
1265 if ((ret =
1266 thrift_transport_read_all (protocol->transport,
1267 b, 1, error)) < 0) {
1268 return -1;
1269 }
1270 *value = *(gint8 *) b;
1271 return ret;
1272 }
1273
1274 gint32
thrift_compact_protocol_read_i16(ThriftProtocol * protocol,gint16 * value,GError ** error)1275 thrift_compact_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value,
1276 GError **error)
1277 {
1278 ThriftCompactProtocol *cp;
1279
1280 gint32 ret;
1281 gint32 val;
1282 gint32 xfer;
1283
1284 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1285
1286 cp = THRIFT_COMPACT_PROTOCOL (protocol);
1287
1288 xfer = 0;
1289
1290 if ((ret = thrift_compact_protocol_read_varint32 (cp, &val, error)) < 0) {
1291 return -1;
1292 }
1293 xfer += ret;
1294
1295 *value = (gint16) zigzag_to_i32 ((guint32) val);
1296
1297 return xfer;
1298 }
1299
1300 gint32
thrift_compact_protocol_read_i32(ThriftProtocol * protocol,gint32 * value,GError ** error)1301 thrift_compact_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value,
1302 GError **error)
1303 {
1304 ThriftCompactProtocol *cp;
1305
1306 gint32 ret;
1307 gint32 val;
1308 gint32 xfer;
1309
1310 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1311
1312 cp = THRIFT_COMPACT_PROTOCOL (protocol);
1313
1314 xfer = 0;
1315
1316 if ((ret = thrift_compact_protocol_read_varint32 (cp, &val, error)) < 0) {
1317 return -1;
1318 }
1319 xfer += ret;
1320
1321 *value = zigzag_to_i32 ((guint32) val);
1322
1323 return xfer;
1324 }
1325
1326 gint32
thrift_compact_protocol_read_i64(ThriftProtocol * protocol,gint64 * value,GError ** error)1327 thrift_compact_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value,
1328 GError **error)
1329 {
1330 ThriftCompactProtocol *cp;
1331
1332 gint32 ret;
1333 gint64 val;
1334 gint32 xfer;
1335
1336 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1337
1338 cp = THRIFT_COMPACT_PROTOCOL (protocol);
1339
1340 xfer = 0;
1341
1342 if ((ret = thrift_compact_protocol_read_varint64 (cp, &val, error)) < 0) {
1343 return -1;
1344 }
1345 xfer += ret;
1346
1347 *value = zigzag_to_i64 ((guint64) val);
1348
1349 return xfer;
1350 }
1351
1352 gint32
thrift_compact_protocol_read_double(ThriftProtocol * protocol,gdouble * value,GError ** error)1353 thrift_compact_protocol_read_double (ThriftProtocol *protocol,
1354 gdouble *value, GError **error)
1355 {
1356 gint32 ret;
1357 union {
1358 guint64 bits;
1359 guint8 b[8];
1360 } u;
1361
1362 g_assert (sizeof (gdouble) == sizeof (guint64));
1363
1364 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1365
1366 if ((ret =
1367 thrift_transport_read_all (protocol->transport,
1368 u.b, 8, error)) < 0) {
1369 return -1;
1370 }
1371 u.bits = GUINT64_FROM_LE (u.bits);
1372 *value = thrift_bitwise_cast_gdouble (u.bits);
1373 return ret;
1374 }
1375
1376 gint32
thrift_compact_protocol_read_string(ThriftProtocol * protocol,gchar ** str,GError ** error)1377 thrift_compact_protocol_read_string (ThriftProtocol *protocol,
1378 gchar **str, GError **error)
1379 {
1380 ThriftCompactProtocol *cp;
1381
1382 gint32 ret;
1383 gint32 xfer;
1384
1385 gint32 read_len;
1386
1387 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1388
1389 cp = THRIFT_COMPACT_PROTOCOL (protocol);
1390
1391 xfer = 0;
1392 read_len = 0;
1393
1394 /* read the length into read_len */
1395 if ((ret =
1396 thrift_compact_protocol_read_varint32 (cp, &read_len, error)) < 0) {
1397 return -1;
1398 }
1399 xfer += ret;
1400
1401 if (cp->string_limit > 0 && read_len > cp->string_limit) {
1402 g_set_error (error, THRIFT_PROTOCOL_ERROR,
1403 THRIFT_PROTOCOL_ERROR_SIZE_LIMIT,
1404 "got size over limit (%d > %d)", read_len, cp->string_limit);
1405 *str = NULL;
1406 return -1;
1407 }
1408
1409 if (read_len < 0) {
1410 g_set_error (error, THRIFT_PROTOCOL_ERROR,
1411 THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE,
1412 "got negative size of %d", read_len);
1413 *str = NULL;
1414 return -1;
1415 }
1416
1417 /* allocate the memory as an array of unsigned char for binary data */
1418 *str = g_new0 (gchar, read_len + 1);
1419 if (read_len > 0) {
1420 if ((ret =
1421 thrift_transport_read_all (protocol->transport,
1422 *str, read_len, error)) < 0) {
1423 g_free (*str);
1424 *str = NULL;
1425 return -1;
1426 }
1427 xfer += ret;
1428 } else {
1429 **str = 0;
1430 }
1431
1432 return xfer;
1433 }
1434
1435 gint32
thrift_compact_protocol_read_binary(ThriftProtocol * protocol,gpointer * buf,guint32 * len,GError ** error)1436 thrift_compact_protocol_read_binary (ThriftProtocol *protocol,
1437 gpointer *buf, guint32 *len,
1438 GError **error)
1439 {
1440 ThriftCompactProtocol *cp;
1441
1442 gint32 ret;
1443 gint32 xfer;
1444
1445 gint32 read_len;
1446
1447 g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1);
1448
1449 cp = THRIFT_COMPACT_PROTOCOL (protocol);
1450
1451 xfer = 0;
1452 read_len = 0;
1453
1454 /* read the length into read_len */
1455 if ((ret =
1456 thrift_compact_protocol_read_varint32 (cp, &read_len, error)) < 0) {
1457 return -1;
1458 }
1459 xfer += ret;
1460
1461 if (cp->string_limit > 0 && read_len > cp->string_limit) {
1462 g_set_error (error, THRIFT_PROTOCOL_ERROR,
1463 THRIFT_PROTOCOL_ERROR_SIZE_LIMIT,
1464 "got size over limit (%d > %d)", read_len, cp->string_limit);
1465 *buf = NULL;
1466 *len = 0;
1467 return -1;
1468 }
1469
1470 if (read_len > 0) {
1471 /* allocate the memory as an array of unsigned char for binary data */
1472 *len = (guint32) read_len;
1473 *buf = g_new (guchar, *len);
1474 if ((ret =
1475 thrift_transport_read_all (protocol->transport,
1476 *buf, *len, error)) < 0) {
1477 g_free (*buf);
1478 *buf = NULL;
1479 *len = 0;
1480 return -1;
1481 }
1482 xfer += ret;
1483
1484 } else if (read_len == 0) {
1485 *len = (guint32) read_len;
1486 *buf = NULL;
1487
1488 } else {
1489 g_set_error (error, THRIFT_PROTOCOL_ERROR,
1490 THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE,
1491 "got negative size of %d", read_len);
1492 *buf = NULL;
1493 *len = 0;
1494 return -1;
1495 }
1496
1497 return xfer;
1498 }
1499
1500 gint
thrift_compact_protocol_get_min_serialized_size(ThriftProtocol * protocol,ThriftType type,GError ** error)1501 thrift_compact_protocol_get_min_serialized_size (ThriftProtocol *protocol, ThriftType type, GError **error)
1502 {
1503 THRIFT_UNUSED_VAR (protocol);
1504
1505 switch (type)
1506 {
1507 case T_STOP:
1508 return 0;
1509 case T_VOID:
1510 return 0;
1511 case T_BOOL:
1512 return sizeof(gint8);
1513 case T_DOUBLE:
1514 return 8;
1515 case T_BYTE:
1516 return sizeof(gint8);
1517 case T_I16:
1518 return sizeof(gint8);
1519 case T_I32:
1520 return sizeof(gint8);
1521 case T_I64:
1522 return sizeof(gint8);
1523 case T_STRING:
1524 return sizeof(gint8);
1525 case T_STRUCT:
1526 return 0;
1527 case T_MAP:
1528 return sizeof(gint8);
1529 case T_SET:
1530 return sizeof(gint8);
1531 case T_LIST:
1532 return sizeof(gint8);
1533 default:
1534 g_set_error(error,
1535 THRIFT_PROTOCOL_ERROR,
1536 THRIFT_PROTOCOL_ERROR_INVALID_DATA,
1537 "unrecognized type");
1538 return -1;
1539 }
1540 }
1541
1542 /* property accessor */
1543 void
thrift_compact_protocol_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)1544 thrift_compact_protocol_get_property (GObject *object, guint property_id,
1545 GValue *value, GParamSpec *pspec)
1546 {
1547 ThriftCompactProtocol *tc;
1548
1549 THRIFT_UNUSED_VAR (pspec);
1550
1551 tc = THRIFT_COMPACT_PROTOCOL (object);
1552
1553 switch (property_id) {
1554 case PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT:
1555 g_value_set_int (value, tc->string_limit);
1556 break;
1557 case PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT:
1558 g_value_set_int (value, tc->container_limit);
1559 break;
1560 }
1561 }
1562
1563 /* property mutator */
1564 void
thrift_compact_protocol_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)1565 thrift_compact_protocol_set_property (GObject *object, guint property_id,
1566 const GValue *value, GParamSpec *pspec)
1567 {
1568 ThriftCompactProtocol *tc;
1569
1570 THRIFT_UNUSED_VAR (pspec);
1571
1572 tc = THRIFT_COMPACT_PROTOCOL (object);
1573
1574 switch (property_id) {
1575 case PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT:
1576 tc->string_limit = g_value_get_int (value);
1577 break;
1578 case PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT:
1579 tc->container_limit = g_value_get_int (value);
1580 break;
1581 }
1582 }
1583
1584 /* initialize the class */
1585 static void
thrift_compact_protocol_class_init(ThriftCompactProtocolClass * klass)1586 thrift_compact_protocol_class_init (ThriftCompactProtocolClass *klass)
1587 {
1588 ThriftProtocolClass *cls;
1589 GObjectClass *gobject_class;
1590 GParamSpec *param_spec;
1591
1592 cls = THRIFT_PROTOCOL_CLASS (klass);
1593 gobject_class = G_OBJECT_CLASS (klass);
1594 param_spec = NULL;
1595
1596 /* setup accessors and mutators */
1597 gobject_class->get_property = thrift_compact_protocol_get_property;
1598 gobject_class->set_property = thrift_compact_protocol_set_property;
1599
1600 param_spec = g_param_spec_int ("string_limit",
1601 "Max allowed string size",
1602 "Set the max string limit",
1603 0, /* min */
1604 G_MAXINT32, /* max */
1605 0, /* default value */
1606 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1607 g_object_class_install_property (gobject_class,
1608 PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT,
1609 param_spec);
1610
1611 param_spec = g_param_spec_int ("container_limit",
1612 "Max allowed container size",
1613 "Set the max container limit",
1614 0, /* min */
1615 G_MAXINT32, /* max */
1616 0, /* default value */
1617 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1618 g_object_class_install_property (gobject_class,
1619 PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT,
1620 param_spec);
1621
1622 cls->write_message_begin = thrift_compact_protocol_write_message_begin;
1623 cls->write_message_end = thrift_compact_protocol_write_message_end;
1624 cls->write_struct_begin = thrift_compact_protocol_write_struct_begin;
1625 cls->write_struct_end = thrift_compact_protocol_write_struct_end;
1626 cls->write_field_begin = thrift_compact_protocol_write_field_begin;
1627 cls->write_field_end = thrift_compact_protocol_write_field_end;
1628 cls->write_field_stop = thrift_compact_protocol_write_field_stop;
1629 cls->write_map_begin = thrift_compact_protocol_write_map_begin;
1630 cls->write_map_end = thrift_compact_protocol_write_map_end;
1631 cls->write_list_begin = thrift_compact_protocol_write_list_begin;
1632 cls->write_list_end = thrift_compact_protocol_write_list_end;
1633 cls->write_set_begin = thrift_compact_protocol_write_set_begin;
1634 cls->write_set_end = thrift_compact_protocol_write_set_end;
1635 cls->write_bool = thrift_compact_protocol_write_bool;
1636 cls->write_byte = thrift_compact_protocol_write_byte;
1637 cls->write_i16 = thrift_compact_protocol_write_i16;
1638 cls->write_i32 = thrift_compact_protocol_write_i32;
1639 cls->write_i64 = thrift_compact_protocol_write_i64;
1640 cls->write_double = thrift_compact_protocol_write_double;
1641 cls->write_string = thrift_compact_protocol_write_string;
1642 cls->write_binary = thrift_compact_protocol_write_binary;
1643 cls->read_message_begin = thrift_compact_protocol_read_message_begin;
1644 cls->read_message_end = thrift_compact_protocol_read_message_end;
1645 cls->read_struct_begin = thrift_compact_protocol_read_struct_begin;
1646 cls->read_struct_end = thrift_compact_protocol_read_struct_end;
1647 cls->read_field_begin = thrift_compact_protocol_read_field_begin;
1648 cls->read_field_end = thrift_compact_protocol_read_field_end;
1649 cls->read_map_begin = thrift_compact_protocol_read_map_begin;
1650 cls->read_map_end = thrift_compact_protocol_read_map_end;
1651 cls->read_list_begin = thrift_compact_protocol_read_list_begin;
1652 cls->read_list_end = thrift_compact_protocol_read_list_end;
1653 cls->read_set_begin = thrift_compact_protocol_read_set_begin;
1654 cls->read_set_end = thrift_compact_protocol_read_set_end;
1655 cls->read_bool = thrift_compact_protocol_read_bool;
1656 cls->read_byte = thrift_compact_protocol_read_byte;
1657 cls->read_i16 = thrift_compact_protocol_read_i16;
1658 cls->read_i32 = thrift_compact_protocol_read_i32;
1659 cls->read_i64 = thrift_compact_protocol_read_i64;
1660 cls->read_double = thrift_compact_protocol_read_double;
1661 cls->read_string = thrift_compact_protocol_read_string;
1662 cls->read_binary = thrift_compact_protocol_read_binary;
1663 cls->get_min_serialized_size = thrift_compact_protocol_get_min_serialized_size;
1664 }
1665
1666 static void
thrift_compact_protocol_init(ThriftCompactProtocol * self)1667 thrift_compact_protocol_init (ThriftCompactProtocol *self)
1668 {
1669 g_queue_init (&(self->_last_field));
1670 }
1671