| David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 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 |  | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 20 | #import "TBinaryProtocol.h" | 
| Mark Slee | 33a7d89 | 2007-09-14 19:44:30 +0000 | [diff] [blame] | 21 | #import "TProtocolException.h" | 
| Jake Farrell | 9689d89 | 2011-12-06 01:07:17 +0000 | [diff] [blame] | 22 | #import "TObjective-C.h" | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 23 |  | 
| Jens Geyer | 2aa04bf | 2015-04-17 18:44:37 +0200 | [diff] [blame] | 24 | /* In the modern protocol, version is stored in the high half of an int32. | 
 | 25 |  * The low half contains type info. */ | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 26 | static const uint16_t VERSION_1 = 0x8001; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 27 |  | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 28 | NS_INLINE size_t | 
 | 29 | CheckedCastInt32ToSizeT(int32_t size) | 
 | 30 | { | 
 | 31 |   if (size < 0) { | 
 | 32 |     NSString *reason = [NSString stringWithFormat: | 
 | 33 |                         @"%s: refusing to read data with negative size: %"PRId32, | 
 | 34 |                         __func__, size]; | 
 | 35 |     @throw [TProtocolException | 
 | 36 |             exceptionWithName: @"TProtocolException" | 
 | 37 |             reason: reason]; | 
 | 38 |   } | 
 | 39 |   size_t checkedSize = (size_t)size; | 
 | 40 |   return checkedSize; | 
 | 41 | } | 
 | 42 |  | 
 | 43 | NS_INLINE int32_t | 
 | 44 | CheckedCastSizeTToInt32(size_t size) | 
 | 45 | { | 
 | 46 |   if (size > INT32_MAX) { | 
 | 47 |     NSString *reason = [NSString stringWithFormat: | 
 | 48 |                         @"%s: data size exceeds values representable by a 32-bit signed integer: %zu", | 
 | 49 |                         __func__, size]; | 
 | 50 |     @throw [TProtocolException | 
 | 51 |             exceptionWithName: @"TProtocolException" | 
 | 52 |             reason: reason]; | 
 | 53 |   } | 
 | 54 |   int32_t checkedSize = (int32_t)size; | 
 | 55 |   return checkedSize; | 
 | 56 | } | 
 | 57 |  | 
 | 58 | NS_INLINE uint8_t | 
 | 59 | CheckedCastIntToUInt8(int size) | 
 | 60 | { | 
 | 61 |   if (size > UINT8_MAX) { | 
 | 62 |     NSString *reason = [NSString stringWithFormat: | 
 | 63 |                         @"%s: data size exceeds values representable by a 8-bit unsigned integer: %d", | 
 | 64 |                         __func__, size]; | 
 | 65 |     @throw [TProtocolException | 
 | 66 |             exceptionWithName: @"TProtocolException" | 
 | 67 |             reason: reason]; | 
 | 68 |   } | 
 | 69 |   uint8_t checkedSize = (uint8_t)size; | 
 | 70 |   return checkedSize; | 
 | 71 | } | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 72 |  | 
| Mark Slee | 77575e6 | 2007-09-24 19:24:53 +0000 | [diff] [blame] | 73 | static TBinaryProtocolFactory * gSharedFactory = nil; | 
 | 74 |  | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 75 | @implementation TBinaryProtocolFactory | 
| Mark Slee | 77575e6 | 2007-09-24 19:24:53 +0000 | [diff] [blame] | 76 |  | 
 | 77 | + (TBinaryProtocolFactory *) sharedFactory { | 
 | 78 |   if (gSharedFactory == nil) { | 
 | 79 |     gSharedFactory = [[TBinaryProtocolFactory alloc] init]; | 
 | 80 |   } | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 81 |  | 
| Mark Slee | 77575e6 | 2007-09-24 19:24:53 +0000 | [diff] [blame] | 82 |   return gSharedFactory; | 
 | 83 | } | 
 | 84 |  | 
 | 85 | - (TBinaryProtocol *) newProtocolOnTransport: (id <TTransport>) transport { | 
| Andrew McGeachie | da50d55 | 2010-07-21 19:14:44 +0000 | [diff] [blame] | 86 |   return [[TBinaryProtocol alloc] initWithTransport: transport]; | 
| Mark Slee | 77575e6 | 2007-09-24 19:24:53 +0000 | [diff] [blame] | 87 | } | 
 | 88 |  | 
 | 89 | @end | 
 | 90 |  | 
 | 91 |  | 
 | 92 |  | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 93 | @implementation TBinaryProtocol | 
 | 94 |  | 
 | 95 | - (id) initWithTransport: (id <TTransport>) transport | 
 | 96 | { | 
| Carl Yeksigian | f029345 | 2013-08-13 18:09:59 -0400 | [diff] [blame] | 97 |   return [self initWithTransport: transport strictRead: NO strictWrite: YES]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 98 | } | 
 | 99 |  | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 100 | - (id) initWithTransport: (id <TTransport>) transport | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 101 |               strictRead: (BOOL) strictRead | 
 | 102 |              strictWrite: (BOOL) strictWrite | 
 | 103 | { | 
 | 104 |   self = [super init]; | 
| Jake Farrell | 9689d89 | 2011-12-06 01:07:17 +0000 | [diff] [blame] | 105 |   mTransport = [transport retain_stub]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 106 |   mStrictRead = strictRead; | 
 | 107 |   mStrictWrite = strictWrite; | 
 | 108 |   return self; | 
 | 109 | } | 
 | 110 |  | 
 | 111 |  | 
| Mark Slee | 8440605 | 2007-11-20 01:39:25 +0000 | [diff] [blame] | 112 | - (int32_t) messageSizeLimit | 
 | 113 | { | 
 | 114 |   return mMessageSizeLimit; | 
 | 115 | } | 
 | 116 |  | 
 | 117 |  | 
 | 118 | - (void) setMessageSizeLimit: (int32_t) sizeLimit | 
 | 119 | { | 
 | 120 |   mMessageSizeLimit = sizeLimit; | 
 | 121 | } | 
 | 122 |  | 
 | 123 |  | 
| Mark Slee | aa3c5a8 | 2007-09-19 21:12:52 +0000 | [diff] [blame] | 124 | - (void) dealloc | 
 | 125 | { | 
| Jake Farrell | 9689d89 | 2011-12-06 01:07:17 +0000 | [diff] [blame] | 126 |   [mTransport release_stub]; | 
 | 127 |   [super dealloc_stub]; | 
| Mark Slee | aa3c5a8 | 2007-09-19 21:12:52 +0000 | [diff] [blame] | 128 | } | 
 | 129 |  | 
 | 130 |  | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 131 | - (id <TTransport>) transport | 
 | 132 | { | 
 | 133 |   return mTransport; | 
 | 134 | } | 
 | 135 |  | 
 | 136 |  | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 137 | - (NSString *) readStringBody: (int) rawSize | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 138 | { | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 139 |   size_t size = CheckedCastInt32ToSizeT(rawSize); | 
| Andrew McGeachie | 061722b | 2009-07-23 18:12:18 +0000 | [diff] [blame] | 140 |   char * buffer = malloc(size+1); | 
 | 141 |   if (!buffer) { | 
 | 142 |     @throw [TProtocolException exceptionWithName: @"TProtocolException" | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 143 |                                           reason: [NSString stringWithFormat: @"Unable to allocate memory in %s, size: %zu", | 
| Andrew McGeachie | 061722b | 2009-07-23 18:12:18 +0000 | [diff] [blame] | 144 |                                                    __PRETTY_FUNCTION__, | 
 | 145 |                                                    size]];; | 
 | 146 |   } | 
 | 147 |   [mTransport readAll: (uint8_t *) buffer offset: 0 length: size]; | 
 | 148 |   buffer[size] = 0; | 
 | 149 |   NSString * result = [NSString stringWithUTF8String: buffer]; | 
 | 150 |   free(buffer); | 
 | 151 |   return result; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 152 | } | 
 | 153 |  | 
 | 154 |  | 
| Mark Slee | 33a7d89 | 2007-09-14 19:44:30 +0000 | [diff] [blame] | 155 | - (void) readMessageBeginReturningName: (NSString **) name | 
 | 156 |                                   type: (int *) type | 
 | 157 |                             sequenceID: (int *) sequenceID | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 158 | { | 
| Mark Slee | 8440605 | 2007-11-20 01:39:25 +0000 | [diff] [blame] | 159 |   int32_t size = [self readI32]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 160 |   if (size < 0) { | 
| Jens Geyer | 2aa04bf | 2015-04-17 18:44:37 +0200 | [diff] [blame] | 161 |     /* Version (unsigned) is stored in the high halfword. */ | 
 | 162 |     uint16_t version = (size >> 16) & 0xFFFF; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 163 |     if (version != VERSION_1) { | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 164 |       NSString *reason = [NSString stringWithFormat: | 
 | 165 |                           @"%s: Expected version %"PRIu16", instead found: %"PRIu16, | 
 | 166 |                           __func__, VERSION_1, version]; | 
| Mark Slee | 77575e6 | 2007-09-24 19:24:53 +0000 | [diff] [blame] | 167 |       @throw [TProtocolException exceptionWithName: @"TProtocolException" | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 168 |                                  reason: reason]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 169 |     } | 
 | 170 |     if (type != NULL) { | 
| Roger Meier | ff951bd | 2013-03-22 22:12:19 +0100 | [diff] [blame] | 171 |       *type = size & 0x00FF; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 172 |     } | 
 | 173 |     NSString * messageName = [self readString]; | 
 | 174 |     if (name != NULL) { | 
 | 175 |       *name = messageName; | 
 | 176 |     } | 
 | 177 |     int seqID = [self readI32]; | 
 | 178 |     if (sequenceID != NULL) { | 
 | 179 |       *sequenceID = seqID; | 
 | 180 |     } | 
 | 181 |   } else { | 
 | 182 |     if (mStrictRead) { | 
| Mark Slee | 77575e6 | 2007-09-24 19:24:53 +0000 | [diff] [blame] | 183 |       @throw [TProtocolException exceptionWithName: @"TProtocolException" | 
 | 184 |                                  reason: @"Missing version in readMessageBegin, old client?"]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 185 |     } | 
| Mark Slee | 8440605 | 2007-11-20 01:39:25 +0000 | [diff] [blame] | 186 |     if ([self messageSizeLimit] > 0 && size > [self messageSizeLimit]) { | 
 | 187 |       @throw [TProtocolException exceptionWithName: @"TProtocolException" | 
 | 188 |                                             reason: [NSString stringWithFormat: @"Message too big.  Size limit is: %d Message size is: %d", | 
 | 189 |                                                      mMessageSizeLimit, | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 190 |                                                      size]]; | 
| Mark Slee | 8440605 | 2007-11-20 01:39:25 +0000 | [diff] [blame] | 191 |     } | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 192 |     NSString * messageName = [self readStringBody: size]; | 
 | 193 |     if (name != NULL) { | 
 | 194 |       *name = messageName; | 
 | 195 |     } | 
 | 196 |     int messageType = [self readByte]; | 
 | 197 |     if (type != NULL) { | 
 | 198 |       *type = messageType; | 
 | 199 |     } | 
 | 200 |     int seqID = [self readI32]; | 
 | 201 |     if (sequenceID != NULL) { | 
 | 202 |       *sequenceID = seqID; | 
 | 203 |     } | 
 | 204 |   } | 
 | 205 | } | 
 | 206 |  | 
 | 207 |  | 
 | 208 | - (void) readMessageEnd {} | 
 | 209 |  | 
 | 210 |  | 
| Mark Slee | 33a7d89 | 2007-09-14 19:44:30 +0000 | [diff] [blame] | 211 | - (void) readStructBeginReturningName: (NSString **) name | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 212 | { | 
 | 213 |   if (name != NULL) { | 
 | 214 |     *name = nil; | 
 | 215 |   } | 
 | 216 | } | 
 | 217 |  | 
 | 218 |  | 
 | 219 | - (void) readStructEnd {} | 
 | 220 |  | 
 | 221 |  | 
| Mark Slee | 33a7d89 | 2007-09-14 19:44:30 +0000 | [diff] [blame] | 222 | - (void) readFieldBeginReturningName: (NSString **) name | 
 | 223 |                                 type: (int *) fieldType | 
 | 224 |                              fieldID: (int *) fieldID | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 225 | { | 
 | 226 |   if (name != NULL) { | 
 | 227 |     *name = nil; | 
 | 228 |   } | 
 | 229 |   int ft = [self readByte]; | 
 | 230 |   if (fieldType != NULL) { | 
 | 231 |     *fieldType = ft; | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 232 |   } | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 233 |   if (ft != TType_STOP) { | 
 | 234 |     int fid = [self readI16]; | 
 | 235 |     if (fieldID != NULL) { | 
 | 236 |       *fieldID = fid; | 
 | 237 |     } | 
 | 238 |   } | 
 | 239 | } | 
 | 240 |  | 
 | 241 |  | 
 | 242 | - (void) readFieldEnd {} | 
 | 243 |  | 
 | 244 |  | 
 | 245 | - (int32_t) readI32 | 
 | 246 | { | 
 | 247 |   uint8_t i32rd[4]; | 
 | 248 |   [mTransport readAll: i32rd offset: 0 length: 4]; | 
 | 249 |   return | 
 | 250 |     ((i32rd[0] & 0xff) << 24) | | 
 | 251 |     ((i32rd[1] & 0xff) << 16) | | 
 | 252 |     ((i32rd[2] & 0xff) <<  8) | | 
 | 253 |     ((i32rd[3] & 0xff)); | 
 | 254 | } | 
 | 255 |  | 
 | 256 |  | 
 | 257 | - (NSString *) readString | 
 | 258 | { | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 259 |   int32_t size = [self readI32]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 260 |   return [self readStringBody: size]; | 
 | 261 | } | 
 | 262 |  | 
 | 263 |  | 
 | 264 | - (BOOL) readBool | 
 | 265 | { | 
 | 266 |   return [self readByte] == 1; | 
 | 267 | } | 
 | 268 |  | 
 | 269 | - (uint8_t) readByte | 
 | 270 | { | 
 | 271 |   uint8_t myByte; | 
 | 272 |   [mTransport readAll: &myByte offset: 0 length: 1]; | 
 | 273 |   return myByte; | 
 | 274 | } | 
 | 275 |  | 
 | 276 | - (short) readI16 | 
 | 277 | { | 
 | 278 |   uint8_t buff[2]; | 
 | 279 |   [mTransport readAll: buff offset: 0 length: 2]; | 
 | 280 |   return (short) | 
 | 281 |     (((buff[0] & 0xff) << 8) | | 
 | 282 |      ((buff[1] & 0xff))); | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 283 | } | 
 | 284 |  | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 285 | - (int64_t) readI64 | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 286 | { | 
 | 287 |   uint8_t i64rd[8]; | 
 | 288 |   [mTransport readAll: i64rd offset: 0 length: 8]; | 
 | 289 |   return | 
 | 290 |     ((int64_t)(i64rd[0] & 0xff) << 56) | | 
 | 291 |     ((int64_t)(i64rd[1] & 0xff) << 48) | | 
 | 292 |     ((int64_t)(i64rd[2] & 0xff) << 40) | | 
 | 293 |     ((int64_t)(i64rd[3] & 0xff) << 32) | | 
 | 294 |     ((int64_t)(i64rd[4] & 0xff) << 24) | | 
 | 295 |     ((int64_t)(i64rd[5] & 0xff) << 16) | | 
 | 296 |     ((int64_t)(i64rd[6] & 0xff) <<  8) | | 
 | 297 |     ((int64_t)(i64rd[7] & 0xff)); | 
 | 298 | } | 
 | 299 |  | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 300 | - (double) readDouble | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 301 | { | 
 | 302 |   // FIXME - will this get us into trouble on PowerPC? | 
 | 303 |   int64_t ieee754 = [self readI64]; | 
 | 304 |   return *((double *) &ieee754); | 
 | 305 | } | 
 | 306 |  | 
 | 307 |  | 
 | 308 | - (NSData *) readBinary | 
 | 309 | { | 
 | 310 |   int32_t size = [self readI32]; | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 311 |   size_t binarySize = CheckedCastInt32ToSizeT(size); | 
 | 312 |   uint8_t * buff = malloc(binarySize); | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 313 |   if (buff == NULL) { | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 314 |     @throw [TProtocolException | 
| Mark Slee | 77575e6 | 2007-09-24 19:24:53 +0000 | [diff] [blame] | 315 |              exceptionWithName: @"TProtocolException" | 
 | 316 |              reason: [NSString stringWithFormat: @"Out of memory.  Unable to allocate %d bytes trying to read binary data.", | 
| Mark Slee | 33a7d89 | 2007-09-14 19:44:30 +0000 | [diff] [blame] | 317 |                                size]]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 318 |   } | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 319 |   [mTransport readAll: buff offset: 0 length: binarySize]; | 
 | 320 |   return [NSData dataWithBytesNoCopy: buff length: binarySize]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 321 | } | 
 | 322 |  | 
 | 323 |  | 
| Mark Slee | 33a7d89 | 2007-09-14 19:44:30 +0000 | [diff] [blame] | 324 | - (void) readMapBeginReturningKeyType: (int *) keyType | 
 | 325 |                             valueType: (int *) valueType | 
 | 326 |                                  size: (int *) size | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 327 | { | 
 | 328 |   int kt = [self readByte]; | 
 | 329 |   int vt = [self readByte]; | 
 | 330 |   int s = [self readI32]; | 
 | 331 |   if (keyType != NULL) { | 
 | 332 |     *keyType = kt; | 
 | 333 |   } | 
 | 334 |   if (valueType != NULL) { | 
 | 335 |     *valueType = vt; | 
 | 336 |   } | 
 | 337 |   if (size != NULL) { | 
 | 338 |     *size = s; | 
 | 339 |   } | 
 | 340 | } | 
 | 341 |  | 
 | 342 | - (void) readMapEnd {} | 
 | 343 |  | 
 | 344 |  | 
| Mark Slee | 33a7d89 | 2007-09-14 19:44:30 +0000 | [diff] [blame] | 345 | - (void) readSetBeginReturningElementType: (int *) elementType | 
 | 346 |                                      size: (int *) size | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 347 | { | 
 | 348 |   int et = [self readByte]; | 
 | 349 |   int s = [self readI32]; | 
 | 350 |   if (elementType != NULL) { | 
 | 351 |     *elementType = et; | 
 | 352 |   } | 
 | 353 |   if (size != NULL) { | 
 | 354 |     *size = s; | 
 | 355 |   } | 
 | 356 | } | 
 | 357 |  | 
 | 358 |  | 
 | 359 | - (void) readSetEnd {} | 
 | 360 |  | 
 | 361 |  | 
| Mark Slee | 33a7d89 | 2007-09-14 19:44:30 +0000 | [diff] [blame] | 362 | - (void) readListBeginReturningElementType: (int *) elementType | 
 | 363 |                                       size: (int *) size | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 364 | { | 
 | 365 |   int et = [self readByte]; | 
 | 366 |   int s = [self readI32]; | 
 | 367 |   if (elementType != NULL) { | 
 | 368 |     *elementType = et; | 
 | 369 |   } | 
 | 370 |   if (size != NULL) { | 
 | 371 |     *size = s; | 
 | 372 |   } | 
 | 373 | } | 
 | 374 |  | 
 | 375 |  | 
 | 376 | - (void) readListEnd {} | 
 | 377 |  | 
 | 378 |  | 
 | 379 | - (void) writeByte: (uint8_t) value | 
 | 380 | { | 
 | 381 |   [mTransport write: &value offset: 0 length: 1]; | 
 | 382 | } | 
 | 383 |  | 
 | 384 |  | 
 | 385 | - (void) writeMessageBeginWithName: (NSString *) name | 
 | 386 |                               type: (int) messageType | 
 | 387 |                         sequenceID: (int) sequenceID | 
 | 388 | { | 
 | 389 |   if (mStrictWrite) { | 
| Jens Geyer | 2aa04bf | 2015-04-17 18:44:37 +0200 | [diff] [blame] | 390 |     int version = (VERSION_1 << 16) | messageType; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 391 |     [self writeI32: version]; | 
 | 392 |     [self writeString: name]; | 
 | 393 |     [self writeI32: sequenceID]; | 
 | 394 |   } else { | 
 | 395 |     [self writeString: name]; | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 396 |     [self writeByte: CheckedCastIntToUInt8(messageType)]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 397 |     [self writeI32: sequenceID]; | 
 | 398 |   } | 
 | 399 | } | 
 | 400 |  | 
 | 401 |  | 
 | 402 | - (void) writeMessageEnd {} | 
 | 403 |  | 
 | 404 |  | 
 | 405 | - (void) writeStructBeginWithName: (NSString *) name {} | 
 | 406 |  | 
 | 407 |  | 
 | 408 | - (void) writeStructEnd {} | 
 | 409 |  | 
 | 410 |  | 
 | 411 | - (void) writeFieldBeginWithName: (NSString *) name | 
 | 412 |                             type: (int) fieldType | 
 | 413 |                          fieldID: (int) fieldID | 
 | 414 | { | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 415 |   [self writeByte: CheckedCastIntToUInt8(fieldType)]; | 
 | 416 |   [self writeI16: CheckedCastIntToUInt8(fieldID)]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 417 | } | 
 | 418 |  | 
 | 419 |  | 
 | 420 | - (void) writeI32: (int32_t) value | 
 | 421 | { | 
 | 422 |   uint8_t buff[4]; | 
 | 423 |   buff[0] = 0xFF & (value >> 24); | 
 | 424 |   buff[1] = 0xFF & (value >> 16); | 
 | 425 |   buff[2] = 0xFF & (value >> 8); | 
 | 426 |   buff[3] = 0xFF & value; | 
 | 427 |   [mTransport write: buff offset: 0 length: 4]; | 
 | 428 | } | 
 | 429 |  | 
 | 430 | - (void) writeI16: (short) value | 
 | 431 | { | 
 | 432 |   uint8_t buff[2]; | 
 | 433 |   buff[0] = 0xff & (value >> 8); | 
 | 434 |   buff[1] = 0xff & value; | 
 | 435 |   [mTransport write: buff offset: 0 length: 2]; | 
 | 436 | } | 
 | 437 |  | 
 | 438 |  | 
 | 439 | - (void) writeI64: (int64_t) value | 
 | 440 | { | 
 | 441 |   uint8_t buff[8]; | 
 | 442 |   buff[0] = 0xFF & (value >> 56); | 
 | 443 |   buff[1] = 0xFF & (value >> 48); | 
 | 444 |   buff[2] = 0xFF & (value >> 40); | 
 | 445 |   buff[3] = 0xFF & (value >> 32); | 
 | 446 |   buff[4] = 0xFF & (value >> 24); | 
 | 447 |   buff[5] = 0xFF & (value >> 16); | 
 | 448 |   buff[6] = 0xFF & (value >> 8); | 
 | 449 |   buff[7] = 0xFF & value; | 
 | 450 |   [mTransport write: buff offset: 0 length: 8]; | 
 | 451 | } | 
 | 452 |  | 
 | 453 | - (void) writeDouble: (double) value | 
 | 454 | { | 
 | 455 |   // spit out IEEE 754 bits - FIXME - will this get us in trouble on | 
 | 456 |   // PowerPC? | 
 | 457 |   [self writeI64: *((int64_t *) &value)]; | 
 | 458 | } | 
 | 459 |  | 
| Mark Slee | aa3c5a8 | 2007-09-19 21:12:52 +0000 | [diff] [blame] | 460 |  | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 461 | - (void) writeString: (NSString *) value | 
 | 462 | { | 
| Mark Slee | aa3c5a8 | 2007-09-19 21:12:52 +0000 | [diff] [blame] | 463 |   if (value != nil) { | 
 | 464 |     const char * utf8Bytes = [value UTF8String]; | 
 | 465 |     size_t length = strlen(utf8Bytes); | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 466 |     int32_t size = CheckedCastSizeTToInt32(length); | 
 | 467 |     [self writeI32: size]; | 
| Mark Slee | aa3c5a8 | 2007-09-19 21:12:52 +0000 | [diff] [blame] | 468 |     [mTransport write: (uint8_t *) utf8Bytes offset: 0 length: length]; | 
 | 469 |   } else { | 
| Mark Slee | 77575e6 | 2007-09-24 19:24:53 +0000 | [diff] [blame] | 470 |     // instead of crashing when we get null, let's write out a zero | 
 | 471 |     // length string | 
| Mark Slee | aa3c5a8 | 2007-09-19 21:12:52 +0000 | [diff] [blame] | 472 |     [self writeI32: 0]; | 
 | 473 |   } | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 474 | } | 
 | 475 |  | 
 | 476 |  | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 477 | - (void) writeBinary: (NSData *) data | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 478 | { | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 479 |   int32_t size = CheckedCastSizeTToInt32([data length]); | 
 | 480 |   [self writeI32: size]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 481 |   [mTransport write: [data bytes] offset: 0 length: [data length]]; | 
 | 482 | } | 
 | 483 |  | 
 | 484 | - (void) writeFieldStop | 
 | 485 | { | 
 | 486 |   [self writeByte: TType_STOP]; | 
 | 487 | } | 
 | 488 |  | 
 | 489 |  | 
 | 490 | - (void) writeFieldEnd {} | 
 | 491 |  | 
 | 492 |  | 
 | 493 | - (void) writeMapBeginWithKeyType: (int) keyType | 
 | 494 |                         valueType: (int) valueType | 
 | 495 |                              size: (int) size | 
 | 496 | { | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 497 |   [self writeByte: CheckedCastIntToUInt8(keyType)]; | 
 | 498 |   [self writeByte: CheckedCastIntToUInt8(valueType)]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 499 |   [self writeI32: size]; | 
 | 500 | } | 
 | 501 |  | 
 | 502 | - (void) writeMapEnd {} | 
 | 503 |  | 
 | 504 |  | 
 | 505 | - (void) writeSetBeginWithElementType: (int) elementType | 
 | 506 |                                  size: (int) size | 
 | 507 | { | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 508 |   [self writeByte: CheckedCastIntToUInt8(elementType)]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 509 |   [self writeI32: size]; | 
 | 510 | } | 
 | 511 |  | 
 | 512 | - (void) writeSetEnd {} | 
 | 513 |  | 
 | 514 |  | 
 | 515 | - (void) writeListBeginWithElementType: (int) elementType | 
 | 516 |                                   size: (int) size | 
 | 517 | { | 
| Roger Meier | 6b61601 | 2015-03-01 12:32:50 +0100 | [diff] [blame] | 518 |   [self writeByte: CheckedCastIntToUInt8(elementType)]; | 
| Mark Slee | 7e9eea4 | 2007-09-10 21:00:23 +0000 | [diff] [blame] | 519 |   [self writeI32: size]; | 
 | 520 | } | 
 | 521 |  | 
 | 522 | - (void) writeListEnd {} | 
 | 523 |  | 
 | 524 |  | 
 | 525 | - (void) writeBool: (BOOL) value | 
 | 526 | { | 
 | 527 |   [self writeByte: (value ? 1 : 0)]; | 
 | 528 | } | 
 | 529 |  | 
 | 530 | @end |