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