blob: 19db55f9d902db0308bcdb9aa97ea55bfcd91d53 [file] [log] [blame]
Mark Slee7e9eea42007-09-10 21:00:23 +00001#import "TBinaryProtocol.h"
Mark Slee33a7d892007-09-14 19:44:30 +00002#import "TProtocolException.h"
Mark Slee7e9eea42007-09-10 21:00:23 +00003
4int32_t VERSION_1 = 0x80010000;
5int32_t VERSION_MASK = 0xffff0000;
6
7
Mark Slee77575e62007-09-24 19:24:53 +00008static TBinaryProtocolFactory * gSharedFactory = nil;
9
10@implementation TBinaryProtocolFactory
11
12+ (TBinaryProtocolFactory *) sharedFactory {
13 if (gSharedFactory == nil) {
14 gSharedFactory = [[TBinaryProtocolFactory alloc] init];
15 }
16
17 return gSharedFactory;
18}
19
20- (TBinaryProtocol *) newProtocolOnTransport: (id <TTransport>) transport {
21 return [[[TBinaryProtocol alloc] initWithTransport: transport] autorelease];
22}
23
24@end
25
26
27
Mark Slee7e9eea42007-09-10 21:00:23 +000028@implementation TBinaryProtocol
29
30- (id) initWithTransport: (id <TTransport>) transport
31{
32 return [self initWithTransport: transport strictRead: NO strictWrite: NO];
33}
34
35- (id) initWithTransport: (id <TTransport>) transport
36 strictRead: (BOOL) strictRead
37 strictWrite: (BOOL) strictWrite
38{
39 self = [super init];
40 mTransport = [transport retain];
41 mStrictRead = strictRead;
42 mStrictWrite = strictWrite;
43 return self;
44}
45
46
Mark Sleeaa3c5a82007-09-19 21:12:52 +000047- (void) dealloc
48{
49 [mTransport release];
50 [super dealloc];
51}
52
53
Mark Slee7e9eea42007-09-10 21:00:23 +000054- (id <TTransport>) transport
55{
56 return mTransport;
57}
58
59
60- (NSString *) readStringBody: (int) size
61{
62 char buff[size+1];
63 [mTransport readAll: (uint8_t *) buff offset: 0 length: size];
64 buff[size] = 0;
65 return [NSString stringWithUTF8String: buff];
66}
67
68
Mark Slee33a7d892007-09-14 19:44:30 +000069- (void) readMessageBeginReturningName: (NSString **) name
70 type: (int *) type
71 sequenceID: (int *) sequenceID
Mark Slee7e9eea42007-09-10 21:00:23 +000072{
73 int size = [self readI32];
74 if (size < 0) {
75 int version = size & VERSION_MASK;
76 if (version != VERSION_1) {
Mark Slee77575e62007-09-24 19:24:53 +000077 @throw [TProtocolException exceptionWithName: @"TProtocolException"
78 reason: @"Bad version in readMessageBegin"];
Mark Slee7e9eea42007-09-10 21:00:23 +000079 }
80 if (type != NULL) {
81 *type = version & 0x00FF;
82 }
83 NSString * messageName = [self readString];
84 if (name != NULL) {
85 *name = messageName;
86 }
87 int seqID = [self readI32];
88 if (sequenceID != NULL) {
89 *sequenceID = seqID;
90 }
91 } else {
92 if (mStrictRead) {
Mark Slee77575e62007-09-24 19:24:53 +000093 @throw [TProtocolException exceptionWithName: @"TProtocolException"
94 reason: @"Missing version in readMessageBegin, old client?"];
Mark Slee7e9eea42007-09-10 21:00:23 +000095 }
96 NSString * messageName = [self readStringBody: size];
97 if (name != NULL) {
98 *name = messageName;
99 }
100 int messageType = [self readByte];
101 if (type != NULL) {
102 *type = messageType;
103 }
104 int seqID = [self readI32];
105 if (sequenceID != NULL) {
106 *sequenceID = seqID;
107 }
108 }
109}
110
111
112- (void) readMessageEnd {}
113
114
Mark Slee33a7d892007-09-14 19:44:30 +0000115- (void) readStructBeginReturningName: (NSString **) name
Mark Slee7e9eea42007-09-10 21:00:23 +0000116{
117 if (name != NULL) {
118 *name = nil;
119 }
120}
121
122
123- (void) readStructEnd {}
124
125
Mark Slee33a7d892007-09-14 19:44:30 +0000126- (void) readFieldBeginReturningName: (NSString **) name
127 type: (int *) fieldType
128 fieldID: (int *) fieldID
Mark Slee7e9eea42007-09-10 21:00:23 +0000129{
130 if (name != NULL) {
131 *name = nil;
132 }
133 int ft = [self readByte];
134 if (fieldType != NULL) {
135 *fieldType = ft;
136 }
137 if (ft != TType_STOP) {
138 int fid = [self readI16];
139 if (fieldID != NULL) {
140 *fieldID = fid;
141 }
142 }
143}
144
145
146- (void) readFieldEnd {}
147
148
149- (int32_t) readI32
150{
151 uint8_t i32rd[4];
152 [mTransport readAll: i32rd offset: 0 length: 4];
153 return
154 ((i32rd[0] & 0xff) << 24) |
155 ((i32rd[1] & 0xff) << 16) |
156 ((i32rd[2] & 0xff) << 8) |
157 ((i32rd[3] & 0xff));
158}
159
160
161- (NSString *) readString
162{
163 int size = [self readI32];
164 return [self readStringBody: size];
165}
166
167
168- (BOOL) readBool
169{
170 return [self readByte] == 1;
171}
172
173- (uint8_t) readByte
174{
175 uint8_t myByte;
176 [mTransport readAll: &myByte offset: 0 length: 1];
177 return myByte;
178}
179
180- (short) readI16
181{
182 uint8_t buff[2];
183 [mTransport readAll: buff offset: 0 length: 2];
184 return (short)
185 (((buff[0] & 0xff) << 8) |
186 ((buff[1] & 0xff)));
187 return 0;
188}
189
190- (int64_t) readI64;
191{
192 uint8_t i64rd[8];
193 [mTransport readAll: i64rd offset: 0 length: 8];
194 return
195 ((int64_t)(i64rd[0] & 0xff) << 56) |
196 ((int64_t)(i64rd[1] & 0xff) << 48) |
197 ((int64_t)(i64rd[2] & 0xff) << 40) |
198 ((int64_t)(i64rd[3] & 0xff) << 32) |
199 ((int64_t)(i64rd[4] & 0xff) << 24) |
200 ((int64_t)(i64rd[5] & 0xff) << 16) |
201 ((int64_t)(i64rd[6] & 0xff) << 8) |
202 ((int64_t)(i64rd[7] & 0xff));
203}
204
205- (double) readDouble;
206{
207 // FIXME - will this get us into trouble on PowerPC?
208 int64_t ieee754 = [self readI64];
209 return *((double *) &ieee754);
210}
211
212
213- (NSData *) readBinary
214{
215 int32_t size = [self readI32];
216 uint8_t * buff = malloc(size);
217 if (buff == NULL) {
Mark Slee33a7d892007-09-14 19:44:30 +0000218 @throw [TProtocolException
Mark Slee77575e62007-09-24 19:24:53 +0000219 exceptionWithName: @"TProtocolException"
220 reason: [NSString stringWithFormat: @"Out of memory. Unable to allocate %d bytes trying to read binary data.",
Mark Slee33a7d892007-09-14 19:44:30 +0000221 size]];
Mark Slee7e9eea42007-09-10 21:00:23 +0000222 }
223 [mTransport readAll: buff offset: 0 length: size];
224 return [NSData dataWithBytesNoCopy: buff length: size];
225}
226
227
Mark Slee33a7d892007-09-14 19:44:30 +0000228- (void) readMapBeginReturningKeyType: (int *) keyType
229 valueType: (int *) valueType
230 size: (int *) size
Mark Slee7e9eea42007-09-10 21:00:23 +0000231{
232 int kt = [self readByte];
233 int vt = [self readByte];
234 int s = [self readI32];
235 if (keyType != NULL) {
236 *keyType = kt;
237 }
238 if (valueType != NULL) {
239 *valueType = vt;
240 }
241 if (size != NULL) {
242 *size = s;
243 }
244}
245
246- (void) readMapEnd {}
247
248
Mark Slee33a7d892007-09-14 19:44:30 +0000249- (void) readSetBeginReturningElementType: (int *) elementType
250 size: (int *) size
Mark Slee7e9eea42007-09-10 21:00:23 +0000251{
252 int et = [self readByte];
253 int s = [self readI32];
254 if (elementType != NULL) {
255 *elementType = et;
256 }
257 if (size != NULL) {
258 *size = s;
259 }
260}
261
262
263- (void) readSetEnd {}
264
265
Mark Slee33a7d892007-09-14 19:44:30 +0000266- (void) readListBeginReturningElementType: (int *) elementType
267 size: (int *) size
Mark Slee7e9eea42007-09-10 21:00:23 +0000268{
269 int et = [self readByte];
270 int s = [self readI32];
271 if (elementType != NULL) {
272 *elementType = et;
273 }
274 if (size != NULL) {
275 *size = s;
276 }
277}
278
279
280- (void) readListEnd {}
281
282
283- (void) writeByte: (uint8_t) value
284{
285 [mTransport write: &value offset: 0 length: 1];
286}
287
288
289- (void) writeMessageBeginWithName: (NSString *) name
290 type: (int) messageType
291 sequenceID: (int) sequenceID
292{
293 if (mStrictWrite) {
294 int version = VERSION_1 | messageType;
295 [self writeI32: version];
296 [self writeString: name];
297 [self writeI32: sequenceID];
298 } else {
299 [self writeString: name];
300 [self writeByte: messageType];
301 [self writeI32: sequenceID];
302 }
303}
304
305
306- (void) writeMessageEnd {}
307
308
309- (void) writeStructBeginWithName: (NSString *) name {}
310
311
312- (void) writeStructEnd {}
313
314
315- (void) writeFieldBeginWithName: (NSString *) name
316 type: (int) fieldType
317 fieldID: (int) fieldID
318{
319 [self writeByte: fieldType];
320 [self writeI16: fieldID];
321}
322
323
324- (void) writeI32: (int32_t) value
325{
326 uint8_t buff[4];
327 buff[0] = 0xFF & (value >> 24);
328 buff[1] = 0xFF & (value >> 16);
329 buff[2] = 0xFF & (value >> 8);
330 buff[3] = 0xFF & value;
331 [mTransport write: buff offset: 0 length: 4];
332}
333
334- (void) writeI16: (short) value
335{
336 uint8_t buff[2];
337 buff[0] = 0xff & (value >> 8);
338 buff[1] = 0xff & value;
339 [mTransport write: buff offset: 0 length: 2];
340}
341
342
343- (void) writeI64: (int64_t) value
344{
345 uint8_t buff[8];
346 buff[0] = 0xFF & (value >> 56);
347 buff[1] = 0xFF & (value >> 48);
348 buff[2] = 0xFF & (value >> 40);
349 buff[3] = 0xFF & (value >> 32);
350 buff[4] = 0xFF & (value >> 24);
351 buff[5] = 0xFF & (value >> 16);
352 buff[6] = 0xFF & (value >> 8);
353 buff[7] = 0xFF & value;
354 [mTransport write: buff offset: 0 length: 8];
355}
356
357- (void) writeDouble: (double) value
358{
359 // spit out IEEE 754 bits - FIXME - will this get us in trouble on
360 // PowerPC?
361 [self writeI64: *((int64_t *) &value)];
362}
363
Mark Sleeaa3c5a82007-09-19 21:12:52 +0000364
Mark Slee7e9eea42007-09-10 21:00:23 +0000365- (void) writeString: (NSString *) value
366{
Mark Sleeaa3c5a82007-09-19 21:12:52 +0000367 if (value != nil) {
368 const char * utf8Bytes = [value UTF8String];
369 size_t length = strlen(utf8Bytes);
370 [self writeI32: length];
371 [mTransport write: (uint8_t *) utf8Bytes offset: 0 length: length];
372 } else {
Mark Slee77575e62007-09-24 19:24:53 +0000373 // instead of crashing when we get null, let's write out a zero
374 // length string
Mark Sleeaa3c5a82007-09-19 21:12:52 +0000375 [self writeI32: 0];
376 }
Mark Slee7e9eea42007-09-10 21:00:23 +0000377}
378
379
380- (void) writeBinary: (NSData *) data
381{
382 [self writeI32: [data length]];
383 [mTransport write: [data bytes] offset: 0 length: [data length]];
384}
385
386- (void) writeFieldStop
387{
388 [self writeByte: TType_STOP];
389}
390
391
392- (void) writeFieldEnd {}
393
394
395- (void) writeMapBeginWithKeyType: (int) keyType
396 valueType: (int) valueType
397 size: (int) size
398{
399 [self writeByte: keyType];
400 [self writeByte: valueType];
401 [self writeI32: size];
402}
403
404- (void) writeMapEnd {}
405
406
407- (void) writeSetBeginWithElementType: (int) elementType
408 size: (int) size
409{
410 [self writeByte: elementType];
411 [self writeI32: size];
412}
413
414- (void) writeSetEnd {}
415
416
417- (void) writeListBeginWithElementType: (int) elementType
418 size: (int) size
419{
420 [self writeByte: elementType];
421 [self writeI32: size];
422}
423
424- (void) writeListEnd {}
425
426
427- (void) writeBool: (BOOL) value
428{
429 [self writeByte: (value ? 1 : 0)];
430}
431
432@end