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