blob: ba7808c2cb50031d1f864c1e217593b2eff9f73f [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
8@implementation TBinaryProtocol
9
10- (id) initWithTransport: (id <TTransport>) transport
11{
12 return [self initWithTransport: transport strictRead: NO strictWrite: NO];
13}
14
15- (id) initWithTransport: (id <TTransport>) transport
16 strictRead: (BOOL) strictRead
17 strictWrite: (BOOL) strictWrite
18{
19 self = [super init];
20 mTransport = [transport retain];
21 mStrictRead = strictRead;
22 mStrictWrite = strictWrite;
23 return self;
24}
25
26
Mark Sleeaa3c5a82007-09-19 21:12:52 +000027- (void) dealloc
28{
29 [mTransport release];
30 [super dealloc];
31}
32
33
Mark Slee7e9eea42007-09-10 21:00:23 +000034- (id <TTransport>) transport
35{
36 return mTransport;
37}
38
39
40- (NSString *) readStringBody: (int) size
41{
42 char buff[size+1];
43 [mTransport readAll: (uint8_t *) buff offset: 0 length: size];
44 buff[size] = 0;
45 return [NSString stringWithUTF8String: buff];
46}
47
48
Mark Slee33a7d892007-09-14 19:44:30 +000049- (void) readMessageBeginReturningName: (NSString **) name
50 type: (int *) type
51 sequenceID: (int *) sequenceID
Mark Slee7e9eea42007-09-10 21:00:23 +000052{
53 int size = [self readI32];
54 if (size < 0) {
55 int version = size & VERSION_MASK;
56 if (version != VERSION_1) {
Mark Slee33a7d892007-09-14 19:44:30 +000057 @throw [TProtocolException exceptionWithName: @"Bad version in readMessageBegin"];
Mark Slee7e9eea42007-09-10 21:00:23 +000058 }
59 if (type != NULL) {
60 *type = version & 0x00FF;
61 }
62 NSString * messageName = [self readString];
63 if (name != NULL) {
64 *name = messageName;
65 }
66 int seqID = [self readI32];
67 if (sequenceID != NULL) {
68 *sequenceID = seqID;
69 }
70 } else {
71 if (mStrictRead) {
Mark Slee33a7d892007-09-14 19:44:30 +000072 @throw [TProtocolException exceptionWithName: @"Missing version in readMessageBegin, old client?"];
Mark Slee7e9eea42007-09-10 21:00:23 +000073 }
74 NSString * messageName = [self readStringBody: size];
75 if (name != NULL) {
76 *name = messageName;
77 }
78 int messageType = [self readByte];
79 if (type != NULL) {
80 *type = messageType;
81 }
82 int seqID = [self readI32];
83 if (sequenceID != NULL) {
84 *sequenceID = seqID;
85 }
86 }
87}
88
89
90- (void) readMessageEnd {}
91
92
Mark Slee33a7d892007-09-14 19:44:30 +000093- (void) readStructBeginReturningName: (NSString **) name
Mark Slee7e9eea42007-09-10 21:00:23 +000094{
95 if (name != NULL) {
96 *name = nil;
97 }
98}
99
100
101- (void) readStructEnd {}
102
103
Mark Slee33a7d892007-09-14 19:44:30 +0000104- (void) readFieldBeginReturningName: (NSString **) name
105 type: (int *) fieldType
106 fieldID: (int *) fieldID
Mark Slee7e9eea42007-09-10 21:00:23 +0000107{
108 if (name != NULL) {
109 *name = nil;
110 }
111 int ft = [self readByte];
112 if (fieldType != NULL) {
113 *fieldType = ft;
114 }
115 if (ft != TType_STOP) {
116 int fid = [self readI16];
117 if (fieldID != NULL) {
118 *fieldID = fid;
119 }
120 }
121}
122
123
124- (void) readFieldEnd {}
125
126
127- (int32_t) readI32
128{
129 uint8_t i32rd[4];
130 [mTransport readAll: i32rd offset: 0 length: 4];
131 return
132 ((i32rd[0] & 0xff) << 24) |
133 ((i32rd[1] & 0xff) << 16) |
134 ((i32rd[2] & 0xff) << 8) |
135 ((i32rd[3] & 0xff));
136}
137
138
139- (NSString *) readString
140{
141 int size = [self readI32];
142 return [self readStringBody: size];
143}
144
145
146- (BOOL) readBool
147{
148 return [self readByte] == 1;
149}
150
151- (uint8_t) readByte
152{
153 uint8_t myByte;
154 [mTransport readAll: &myByte offset: 0 length: 1];
155 return myByte;
156}
157
158- (short) readI16
159{
160 uint8_t buff[2];
161 [mTransport readAll: buff offset: 0 length: 2];
162 return (short)
163 (((buff[0] & 0xff) << 8) |
164 ((buff[1] & 0xff)));
165 return 0;
166}
167
168- (int64_t) readI64;
169{
170 uint8_t i64rd[8];
171 [mTransport readAll: i64rd offset: 0 length: 8];
172 return
173 ((int64_t)(i64rd[0] & 0xff) << 56) |
174 ((int64_t)(i64rd[1] & 0xff) << 48) |
175 ((int64_t)(i64rd[2] & 0xff) << 40) |
176 ((int64_t)(i64rd[3] & 0xff) << 32) |
177 ((int64_t)(i64rd[4] & 0xff) << 24) |
178 ((int64_t)(i64rd[5] & 0xff) << 16) |
179 ((int64_t)(i64rd[6] & 0xff) << 8) |
180 ((int64_t)(i64rd[7] & 0xff));
181}
182
183- (double) readDouble;
184{
185 // FIXME - will this get us into trouble on PowerPC?
186 int64_t ieee754 = [self readI64];
187 return *((double *) &ieee754);
188}
189
190
191- (NSData *) readBinary
192{
193 int32_t size = [self readI32];
194 uint8_t * buff = malloc(size);
195 if (buff == NULL) {
Mark Slee33a7d892007-09-14 19:44:30 +0000196 @throw [TProtocolException
197 exceptionWithName: @"Out of memory"
198 reason: [NSString stringWithFormat: @"Unable to allocate %d bytes trying to read binary data.",
199 size]];
Mark Slee7e9eea42007-09-10 21:00:23 +0000200 }
201 [mTransport readAll: buff offset: 0 length: size];
202 return [NSData dataWithBytesNoCopy: buff length: size];
203}
204
205
Mark Slee33a7d892007-09-14 19:44:30 +0000206- (void) readMapBeginReturningKeyType: (int *) keyType
207 valueType: (int *) valueType
208 size: (int *) size
Mark Slee7e9eea42007-09-10 21:00:23 +0000209{
210 int kt = [self readByte];
211 int vt = [self readByte];
212 int s = [self readI32];
213 if (keyType != NULL) {
214 *keyType = kt;
215 }
216 if (valueType != NULL) {
217 *valueType = vt;
218 }
219 if (size != NULL) {
220 *size = s;
221 }
222}
223
224- (void) readMapEnd {}
225
226
Mark Slee33a7d892007-09-14 19:44:30 +0000227- (void) readSetBeginReturningElementType: (int *) elementType
228 size: (int *) size
Mark Slee7e9eea42007-09-10 21:00:23 +0000229{
230 int et = [self readByte];
231 int s = [self readI32];
232 if (elementType != NULL) {
233 *elementType = et;
234 }
235 if (size != NULL) {
236 *size = s;
237 }
238}
239
240
241- (void) readSetEnd {}
242
243
Mark Slee33a7d892007-09-14 19:44:30 +0000244- (void) readListBeginReturningElementType: (int *) elementType
245 size: (int *) size
Mark Slee7e9eea42007-09-10 21:00:23 +0000246{
247 int et = [self readByte];
248 int s = [self readI32];
249 if (elementType != NULL) {
250 *elementType = et;
251 }
252 if (size != NULL) {
253 *size = s;
254 }
255}
256
257
258- (void) readListEnd {}
259
260
261- (void) writeByte: (uint8_t) value
262{
263 [mTransport write: &value offset: 0 length: 1];
264}
265
266
267- (void) writeMessageBeginWithName: (NSString *) name
268 type: (int) messageType
269 sequenceID: (int) sequenceID
270{
271 if (mStrictWrite) {
272 int version = VERSION_1 | messageType;
273 [self writeI32: version];
274 [self writeString: name];
275 [self writeI32: sequenceID];
276 } else {
277 [self writeString: name];
278 [self writeByte: messageType];
279 [self writeI32: sequenceID];
280 }
281}
282
283
284- (void) writeMessageEnd {}
285
286
287- (void) writeStructBeginWithName: (NSString *) name {}
288
289
290- (void) writeStructEnd {}
291
292
293- (void) writeFieldBeginWithName: (NSString *) name
294 type: (int) fieldType
295 fieldID: (int) fieldID
296{
297 [self writeByte: fieldType];
298 [self writeI16: fieldID];
299}
300
301
302- (void) writeI32: (int32_t) value
303{
304 uint8_t buff[4];
305 buff[0] = 0xFF & (value >> 24);
306 buff[1] = 0xFF & (value >> 16);
307 buff[2] = 0xFF & (value >> 8);
308 buff[3] = 0xFF & value;
309 [mTransport write: buff offset: 0 length: 4];
310}
311
312- (void) writeI16: (short) value
313{
314 uint8_t buff[2];
315 buff[0] = 0xff & (value >> 8);
316 buff[1] = 0xff & value;
317 [mTransport write: buff offset: 0 length: 2];
318}
319
320
321- (void) writeI64: (int64_t) value
322{
323 uint8_t buff[8];
324 buff[0] = 0xFF & (value >> 56);
325 buff[1] = 0xFF & (value >> 48);
326 buff[2] = 0xFF & (value >> 40);
327 buff[3] = 0xFF & (value >> 32);
328 buff[4] = 0xFF & (value >> 24);
329 buff[5] = 0xFF & (value >> 16);
330 buff[6] = 0xFF & (value >> 8);
331 buff[7] = 0xFF & value;
332 [mTransport write: buff offset: 0 length: 8];
333}
334
335- (void) writeDouble: (double) value
336{
337 // spit out IEEE 754 bits - FIXME - will this get us in trouble on
338 // PowerPC?
339 [self writeI64: *((int64_t *) &value)];
340}
341
Mark Sleeaa3c5a82007-09-19 21:12:52 +0000342
Mark Slee7e9eea42007-09-10 21:00:23 +0000343- (void) writeString: (NSString *) value
344{
Mark Sleeaa3c5a82007-09-19 21:12:52 +0000345 if (value != nil) {
346 const char * utf8Bytes = [value UTF8String];
347 size_t length = strlen(utf8Bytes);
348 [self writeI32: length];
349 [mTransport write: (uint8_t *) utf8Bytes offset: 0 length: length];
350 } else {
351 // instead of crashing when we get null, let's write out a zero length string
352 [self writeI32: 0];
353 }
Mark Slee7e9eea42007-09-10 21:00:23 +0000354}
355
356
357- (void) writeBinary: (NSData *) data
358{
359 [self writeI32: [data length]];
360 [mTransport write: [data bytes] offset: 0 length: [data length]];
361}
362
363- (void) writeFieldStop
364{
365 [self writeByte: TType_STOP];
366}
367
368
369- (void) writeFieldEnd {}
370
371
372- (void) writeMapBeginWithKeyType: (int) keyType
373 valueType: (int) valueType
374 size: (int) size
375{
376 [self writeByte: keyType];
377 [self writeByte: valueType];
378 [self writeI32: size];
379}
380
381- (void) writeMapEnd {}
382
383
384- (void) writeSetBeginWithElementType: (int) elementType
385 size: (int) size
386{
387 [self writeByte: elementType];
388 [self writeI32: size];
389}
390
391- (void) writeSetEnd {}
392
393
394- (void) writeListBeginWithElementType: (int) elementType
395 size: (int) size
396{
397 [self writeByte: elementType];
398 [self writeI32: size];
399}
400
401- (void) writeListEnd {}
402
403
404- (void) writeBool: (BOOL) value
405{
406 [self writeByte: (value ? 1 : 0)];
407}
408
409@end