diff options
author | Mark Slee <mcslee@apache.org> | 2007-09-10 21:00:23 +0000 |
---|---|---|
committer | Mark Slee <mcslee@apache.org> | 2007-09-10 21:00:23 +0000 |
commit | 7e9eea48711d015a2764f119ea5e78d8b6447476 (patch) | |
tree | 31dfc7318f598f30fc8ccc15b573fd8aaba5a24d /lib/cocoa | |
parent | 979ff958c125adaae29d3f93d89243f7b9e68b24 (diff) | |
download | thrift-7e9eea48711d015a2764f119ea5e78d8b6447476.tar.gz |
Adding Cocoa generator to Thrift
Summary: Thanks to Andrew McGeachie for doing this
Reviewed By: dreiss
Test Plan: No merge/build issues. Will solicit McGeachie for additions to test/cocoa in the future
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665254 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'lib/cocoa')
-rw-r--r-- | lib/cocoa/TApplicationException.h | 19 | ||||
-rw-r--r-- | lib/cocoa/TBinaryProtocol.h | 16 | ||||
-rw-r--r-- | lib/cocoa/TBinaryProtocol.m | 399 | ||||
-rw-r--r-- | lib/cocoa/TException.h | 9 | ||||
-rw-r--r-- | lib/cocoa/TNSStreamTransport.h | 19 | ||||
-rw-r--r-- | lib/cocoa/TNSStreamTransport.m | 67 | ||||
-rw-r--r-- | lib/cocoa/TProtocol.h | 126 | ||||
-rw-r--r-- | lib/cocoa/TProtocolUtil.h | 10 | ||||
-rw-r--r-- | lib/cocoa/TProtocolUtil.m | 85 | ||||
-rw-r--r-- | lib/cocoa/TTransport.h | 17 |
10 files changed, 767 insertions, 0 deletions
diff --git a/lib/cocoa/TApplicationException.h b/lib/cocoa/TApplicationException.h new file mode 100644 index 000000000..bb6428205 --- /dev/null +++ b/lib/cocoa/TApplicationException.h @@ -0,0 +1,19 @@ +enum { + TApplicationException_UNKNOWN = 0, + TApplicationException_UNKNOWN_METHOD = 1, + TApplicationException_INVALID_MESSAGE_TYPE = 2, + TApplicationException_WRONG_METHOD_NAME = 3, + TApplicationException_BAD_SEQUENCE_ID = 4, + TApplicationException_MISSING_RESULT = 5 +}; + +// FIXME +@interface TApplicationException : NSException { +} + ++ (TApplicationException *) read: (id <TProtocol>) protocol; + ++ (TApplicationException *) exceptionWithType: (int) type + message: (NSString *) message; + +@end diff --git a/lib/cocoa/TBinaryProtocol.h b/lib/cocoa/TBinaryProtocol.h new file mode 100644 index 000000000..ac8bc579d --- /dev/null +++ b/lib/cocoa/TBinaryProtocol.h @@ -0,0 +1,16 @@ +#import "TProtocol.h" +#import "TTransport.h" + +@interface TBinaryProtocol : NSObject <TProtocol> { + id <TTransport> mTransport; + BOOL mStrictRead; + BOOL mStrictWrite; +} + +- (id) initWithTransport: (id <TTransport>) transport; + +- (id) initWithTransport: (id <TTransport>) transport + strictRead: (BOOL) strictRead + strictWrite: (BOOL) strictWrite; + +@end; diff --git a/lib/cocoa/TBinaryProtocol.m b/lib/cocoa/TBinaryProtocol.m new file mode 100644 index 000000000..cd239dee8 --- /dev/null +++ b/lib/cocoa/TBinaryProtocol.m @@ -0,0 +1,399 @@ +#import "TBinaryProtocol.h" + +int32_t VERSION_1 = 0x80010000; +int32_t VERSION_MASK = 0xffff0000; + + +@implementation TBinaryProtocol + +- (id) initWithTransport: (id <TTransport>) transport +{ + return [self initWithTransport: transport strictRead: NO strictWrite: NO]; +} + +- (id) initWithTransport: (id <TTransport>) transport + strictRead: (BOOL) strictRead + strictWrite: (BOOL) strictWrite +{ + self = [super init]; + mTransport = [transport retain]; + mStrictRead = strictRead; + mStrictWrite = strictWrite; + return self; +} + + +- (id <TTransport>) transport +{ + return mTransport; +} + + +- (NSString *) readStringBody: (int) size +{ + char buff[size+1]; + [mTransport readAll: (uint8_t *) buff offset: 0 length: size]; + buff[size] = 0; + return [NSString stringWithUTF8String: buff]; +} + + +- (void) readMessageBeginWithName: (NSString **) name + type: (int *) type + sequenceID: (int *) sequenceID +{ + int size = [self readI32]; + if (size < 0) { + int version = size & VERSION_MASK; + if (version != VERSION_1) { + @throw [NSException exceptionWithName: @"TProtocolException" + reason: @"Bad version in readMessageBegin" + userInfo: nil]; + } + if (type != NULL) { + *type = version & 0x00FF; + } + NSString * messageName = [self readString]; + if (name != NULL) { + *name = messageName; + } + int seqID = [self readI32]; + if (sequenceID != NULL) { + *sequenceID = seqID; + } + } else { + if (mStrictRead) { + @throw [NSException exceptionWithName: @"TProtocolException" + reason: @"Missing version in readMessageBegin, old client?" + userInfo: nil]; + } + NSString * messageName = [self readStringBody: size]; + if (name != NULL) { + *name = messageName; + } + int messageType = [self readByte]; + if (type != NULL) { + *type = messageType; + } + int seqID = [self readI32]; + if (sequenceID != NULL) { + *sequenceID = seqID; + } + } +} + + +- (void) readMessageEnd {} + + +- (void) readStructBeginWithName: (NSString **) name +{ + if (name != NULL) { + *name = nil; + } +} + + +- (void) readStructEnd {} + + +- (void) readFieldBeginWithName: (NSString **) name + type: (int *) fieldType + fieldID: (int *) fieldID +{ + if (name != NULL) { + *name = nil; + } + int ft = [self readByte]; + if (fieldType != NULL) { + *fieldType = ft; + } + if (ft != TType_STOP) { + int fid = [self readI16]; + if (fieldID != NULL) { + *fieldID = fid; + } + } +} + + +- (void) readFieldEnd {} + + +- (int32_t) readI32 +{ + uint8_t i32rd[4]; + [mTransport readAll: i32rd offset: 0 length: 4]; + return + ((i32rd[0] & 0xff) << 24) | + ((i32rd[1] & 0xff) << 16) | + ((i32rd[2] & 0xff) << 8) | + ((i32rd[3] & 0xff)); +} + + +- (NSString *) readString +{ + int size = [self readI32]; + return [self readStringBody: size]; +} + + +- (BOOL) readBool +{ + return [self readByte] == 1; +} + +- (uint8_t) readByte +{ + uint8_t myByte; + [mTransport readAll: &myByte offset: 0 length: 1]; + return myByte; +} + +- (short) readI16 +{ + uint8_t buff[2]; + [mTransport readAll: buff offset: 0 length: 2]; + return (short) + (((buff[0] & 0xff) << 8) | + ((buff[1] & 0xff))); + return 0; +} + +- (int64_t) readI64; +{ + uint8_t i64rd[8]; + [mTransport readAll: i64rd offset: 0 length: 8]; + return + ((int64_t)(i64rd[0] & 0xff) << 56) | + ((int64_t)(i64rd[1] & 0xff) << 48) | + ((int64_t)(i64rd[2] & 0xff) << 40) | + ((int64_t)(i64rd[3] & 0xff) << 32) | + ((int64_t)(i64rd[4] & 0xff) << 24) | + ((int64_t)(i64rd[5] & 0xff) << 16) | + ((int64_t)(i64rd[6] & 0xff) << 8) | + ((int64_t)(i64rd[7] & 0xff)); +} + +- (double) readDouble; +{ + // FIXME - will this get us into trouble on PowerPC? + int64_t ieee754 = [self readI64]; + return *((double *) &ieee754); +} + + +- (NSData *) readBinary +{ + int32_t size = [self readI32]; + uint8_t * buff = malloc(size); + if (buff == NULL) { + @throw [NSException exceptionWithName: @"Out of memory" + reason: [NSString stringWithFormat: @"Unable to allocate %d bytes trying to read binary data.", + size] + userInfo: nil]; + } + [mTransport readAll: buff offset: 0 length: size]; + return [NSData dataWithBytesNoCopy: buff length: size]; +} + + +- (void) readMapBeginWithKeyType: (int *) keyType + valueType: (int *) valueType + size: (int *) size +{ + int kt = [self readByte]; + int vt = [self readByte]; + int s = [self readI32]; + if (keyType != NULL) { + *keyType = kt; + } + if (valueType != NULL) { + *valueType = vt; + } + if (size != NULL) { + *size = s; + } +} + +- (void) readMapEnd {} + + +- (void) readSetBeginWithElementType: (int *) elementType + size: (int *) size +{ + int et = [self readByte]; + int s = [self readI32]; + if (elementType != NULL) { + *elementType = et; + } + if (size != NULL) { + *size = s; + } +} + + +- (void) readSetEnd {} + + +- (void) readListBeginWithElementType: (int *) elementType + size: (int *) size +{ + int et = [self readByte]; + int s = [self readI32]; + if (elementType != NULL) { + *elementType = et; + } + if (size != NULL) { + *size = s; + } +} + + +- (void) readListEnd {} + + +- (void) writeByte: (uint8_t) value +{ + [mTransport write: &value offset: 0 length: 1]; +} + + +- (void) writeMessageBeginWithName: (NSString *) name + type: (int) messageType + sequenceID: (int) sequenceID +{ + if (mStrictWrite) { + int version = VERSION_1 | messageType; + [self writeI32: version]; + [self writeString: name]; + [self writeI32: sequenceID]; + } else { + [self writeString: name]; + [self writeByte: messageType]; + [self writeI32: sequenceID]; + } +} + + +- (void) writeMessageEnd {} + + +- (void) writeStructBeginWithName: (NSString *) name {} + + +- (void) writeStructEnd {} + + +- (void) writeFieldBeginWithName: (NSString *) name + type: (int) fieldType + fieldID: (int) fieldID +{ + [self writeByte: fieldType]; + [self writeI16: fieldID]; +} + + +- (void) writeI32: (int32_t) value +{ + uint8_t buff[4]; + buff[0] = 0xFF & (value >> 24); + buff[1] = 0xFF & (value >> 16); + buff[2] = 0xFF & (value >> 8); + buff[3] = 0xFF & value; + [mTransport write: buff offset: 0 length: 4]; +} + +- (void) writeI16: (short) value +{ + uint8_t buff[2]; + buff[0] = 0xff & (value >> 8); + buff[1] = 0xff & value; + [mTransport write: buff offset: 0 length: 2]; +} + + +- (void) writeI64: (int64_t) value +{ + uint8_t buff[8]; + buff[0] = 0xFF & (value >> 56); + buff[1] = 0xFF & (value >> 48); + buff[2] = 0xFF & (value >> 40); + buff[3] = 0xFF & (value >> 32); + buff[4] = 0xFF & (value >> 24); + buff[5] = 0xFF & (value >> 16); + buff[6] = 0xFF & (value >> 8); + buff[7] = 0xFF & value; + [mTransport write: buff offset: 0 length: 8]; +} + +- (void) writeDouble: (double) value +{ + // spit out IEEE 754 bits - FIXME - will this get us in trouble on + // PowerPC? + [self writeI64: *((int64_t *) &value)]; +} + +- (void) writeString: (NSString *) value +{ + const char * utf8Bytes = [value UTF8String]; + size_t length = strlen(utf8Bytes); + [self writeI32: length]; + [mTransport write: (uint8_t *) utf8Bytes offset: 0 length: length]; +} + + +- (void) writeBinary: (NSData *) data +{ + [self writeI32: [data length]]; + [mTransport write: [data bytes] offset: 0 length: [data length]]; +} + +- (void) writeFieldStop +{ + [self writeByte: TType_STOP]; +} + + +- (void) writeFieldEnd {} + + +- (void) writeMapBeginWithKeyType: (int) keyType + valueType: (int) valueType + size: (int) size +{ + [self writeByte: keyType]; + [self writeByte: valueType]; + [self writeI32: size]; +} + +- (void) writeMapEnd {} + + +- (void) writeSetBeginWithElementType: (int) elementType + size: (int) size +{ + [self writeByte: elementType]; + [self writeI32: size]; +} + +- (void) writeSetEnd {} + + +- (void) writeListBeginWithElementType: (int) elementType + size: (int) size +{ + [self writeByte: elementType]; + [self writeI32: size]; +} + +- (void) writeListEnd {} + + +- (void) writeBool: (BOOL) value +{ + [self writeByte: (value ? 1 : 0)]; +} + +@end diff --git a/lib/cocoa/TException.h b/lib/cocoa/TException.h new file mode 100644 index 000000000..95eaa8348 --- /dev/null +++ b/lib/cocoa/TException.h @@ -0,0 +1,9 @@ +#import <Cocoa/Cocoa.h> + +@interface TException : NSException { +} + +- (id) initWithType: (int) type + message: (NSString *) message; + +@end diff --git a/lib/cocoa/TNSStreamTransport.h b/lib/cocoa/TNSStreamTransport.h new file mode 100644 index 000000000..5f567717a --- /dev/null +++ b/lib/cocoa/TNSStreamTransport.h @@ -0,0 +1,19 @@ +#import <Cocoa/Cocoa.h> +#import "TTransport.h" + +@interface TNSStreamTransport : NSObject <TTransport> { + NSInputStream * mInput; + NSOutputStream * mOutput; +} + +- (id) initWithInputStream: (NSInputStream *) input + outputStream: (NSOutputStream *) output; + +- (id) initWithInputStream: (NSInputStream *) input; + +- (id) initWithOutputStream: (NSOutputStream *) output; + +@end + + + diff --git a/lib/cocoa/TNSStreamTransport.m b/lib/cocoa/TNSStreamTransport.m new file mode 100644 index 000000000..8130a8b58 --- /dev/null +++ b/lib/cocoa/TNSStreamTransport.m @@ -0,0 +1,67 @@ +#import "TNSStreamTransport.h" + +@implementation TNSStreamTransport + +- (id) initWithInputStream: (NSInputStream *) input + outputStream: (NSOutputStream *) output +{ + [super init]; + mInput = [input retain]; + mOutput = [output retain]; + return self; +} + +- (id) initWithInputStream: (NSInputStream *) input +{ + return [self initWithInputStream: input outputStream: nil]; +} + +- (id) initWithOutputStream: (NSOutputStream *) output +{ + return [self initWithInputStream: nil outputStream: output]; +} + + +- (int) readAll: (uint8_t *) buf offset: (int) off length: (int) len +{ + int got = 0; + int ret = 0; + while (got < len) { + ret = [mInput read: buf+off+got maxLength: len-got]; + if (ret <= 0) { + @throw [NSException exceptionWithName: @"TTransportException" + reason: @"Cannot read. Remote side has closed." + userInfo: nil]; + } + got += ret; + } + return got; +} + + +- (void) write: (uint8_t *) data offset: (unsigned int) offset length: (unsigned int) length +{ + int result = [mOutput write: data+offset maxLength: length]; + if (result == -1) { + NSDictionary * errorInfo = [NSDictionary dictionaryWithObject: [mOutput streamError] + forKey: @"error"]; + @throw [NSException exceptionWithName: @"TTransportException" + reason: [NSString stringWithFormat: @"Error writing to transport output stream (%@).", [mOutput streamError]] + userInfo: errorInfo]; + } else if (result == 0) { + @throw [NSException exceptionWithName: @"TTransportException" + reason: @"End of output stream." + userInfo: nil]; + } else if (result != length) { + @throw [NSException exceptionWithName: @"TTransportException" + reason: @"Output stream did not write all of our data." + userInfo: nil]; + } +} + +- (void) flush +{ + // no flush for you! +} + +@end diff --git a/lib/cocoa/TProtocol.h b/lib/cocoa/TProtocol.h new file mode 100644 index 000000000..96d3af6af --- /dev/null +++ b/lib/cocoa/TProtocol.h @@ -0,0 +1,126 @@ +#import <Cocoa/Cocoa.h> + +#import "TTransport.h" + + +enum { + TMessageType_CALL = 1, + TMessageType_REPLY = 2, + TMessageType_EXCEPTION = 3 +}; + +enum { + TType_STOP = 0, + TType_VOID = 1, + TType_BOOL = 2, + TType_BYTE = 3, + TType_DOUBLE = 4, + TType_I16 = 6, + TType_I32 = 8, + TType_I64 = 10, + TType_STRING = 11, + TType_STRUCT = 12, + TType_MAP = 13, + TType_SET = 14, + TType_LIST = 15 +}; + + +@protocol TProtocol <NSObject> + +- (id <TTransport>) transport; + +- (void) readMessageBeginWithName: (NSString **) name + type: (int *) type + sequenceID: (int *) sequenceID; +- (void) readMessageEnd; + +- (void) readStructBeginWithName: (NSString **) name; +- (void) readStructEnd; + +- (void) readFieldBeginWithName: (NSString **) name + type: (int *) fieldType + fieldID: (int *) fieldID; +- (void) readFieldEnd; + +- (NSString *) readString; + +- (BOOL) readBool; + +- (unsigned char) readByte; + +- (short) readI16; + +- (int32_t) readI32; + +- (int64_t) readI64; + +- (double) readDouble; + +- (NSData *) readBinary; + +- (void) readMapBeginWithKeyType: (int *) keyType + valueType: (int *) valueType + size: (int *) size; +- (void) readMapEnd; + + +- (void) readSetBeginWithElementType: (int *) elementType + size: (int *) size; +- (void) readSetEnd; + + +- (void) readListBeginWithElementType: (int *) elementType + size: (int *) size; +- (void) readListEnd; + + +- (void) writeMessageBeginWithName: (NSString *) name + type: (int) messageType + sequenceID: (int) sequenceID; +- (void) writeMessageEnd; + +- (void) writeStructBeginWithName: (NSString *) name; +- (void) writeStructEnd; + +- (void) writeFieldBeginWithName: (NSString *) name + type: (int) fieldType + fieldID: (int) fieldID; + +- (void) writeI32: (int32_t) value; + +- (void) writeI64: (int64_t) value; + +- (void) writeI16: (short) value; + +- (void) writeByte: (uint8_t) value; + +- (void) writeString: (NSString *) value; + +- (void) writeDouble: (double) value; + +- (void) writeBinary: (NSData *) data; + +- (void) writeFieldStop; + +- (void) writeFieldEnd; + +- (void) writeMapBeginWithKeyType: (int) keyType + valueType: (int) valueType + size: (int) size; +- (void) writeMapEnd; + + +- (void) writeSetBeginWithElementType: (int) elementType + size: (int) size; +- (void) writeSetEnd; + + +- (void) writeListBeginWithElementType: (int) elementType + size: (int) size; + +- (void) writeListEnd; + + +@end + diff --git a/lib/cocoa/TProtocolUtil.h b/lib/cocoa/TProtocolUtil.h new file mode 100644 index 000000000..638d0fad1 --- /dev/null +++ b/lib/cocoa/TProtocolUtil.h @@ -0,0 +1,10 @@ +#import "TProtocol.h" +#import "TTransport.h" + +@interface TProtocolUtil : NSObject { + +} + ++ (void) skipType: (int) type onProtocol: (id <TProtocol>) protocol; + +@end; diff --git a/lib/cocoa/TProtocolUtil.m b/lib/cocoa/TProtocolUtil.m new file mode 100644 index 000000000..746790f57 --- /dev/null +++ b/lib/cocoa/TProtocolUtil.m @@ -0,0 +1,85 @@ +#import "TProtocolUtil.h" + +@implementation TProtocolUtil + ++ (void) skipType: (int) type onProtocol: (id <TProtocol>) protocol +{ + switch (type) { + case TType_BOOL: + [protocol readBool]; + break; + case TType_BYTE: + [protocol readByte]; + break; + case TType_I16: + [protocol readI16]; + break; + case TType_I32: + [protocol readI32]; + break; + case TType_I64: + [protocol readI64]; + break; + case TType_DOUBLE: + [protocol readDouble]; + break; + case TType_STRING: + [protocol readString]; + break; + case TType_STRUCT: + [protocol readStructBeginWithName: NULL]; + while (true) { + int fieldType; + [protocol readFieldBeginWithName: nil type: &fieldType fieldID: nil]; + if (fieldType == TType_STOP) { + break; + } + [TProtocolUtil skipType: fieldType onProtocol: protocol]; + [protocol readFieldEnd]; + } + [protocol readStructEnd]; + break; + case TType_MAP: + { + int keyType; + int valueType; + int size; + [protocol readMapBeginWithKeyType: &keyType valueType: &valueType size: &size]; + int i; + for (i = 0; i < size; i++) { + [TProtocolUtil skipType: keyType onProtocol: protocol]; + [TProtocolUtil skipType: valueType onProtocol: protocol]; + } + [protocol readMapEnd]; + } + break; + case TType_SET: + { + int elemType; + int size; + [protocol readSetBeginWithElementType: &elemType size: &size]; + int i; + for (i = 0; i < size; i++) { + [TProtocolUtil skipType: elemType onProtocol: protocol]; + } + [protocol readSetEnd]; + } + break; + case TType_LIST: + { + int elemType; + int size; + [protocol readListBeginWithElementType: &elemType size: &size]; + int i; + for (i = 0; i < size; i++) { + [TProtocolUtil skipType: elemType onProtocol: protocol]; + } + [protocol readListEnd]; + } + break; + default: + return; + } +} + +@end diff --git a/lib/cocoa/TTransport.h b/lib/cocoa/TTransport.h new file mode 100644 index 000000000..bb0270e05 --- /dev/null +++ b/lib/cocoa/TTransport.h @@ -0,0 +1,17 @@ +@protocol TTransport <NSObject> + + /** + * Guarantees that all of len bytes are + * + * @param buf Array to read into + * @param off Index to start reading at + * @param len Maximum number of bytes to read + * @return The number of bytes actually read, which must be equal to len + * @throws TTransportException if there was an error reading data + */ +- (int) readAll: (uint8_t *) buf offset: (int) off length: (int) len; + +- (void) write: (const uint8_t *) data offset: (unsigned int) offset length: (unsigned int) length; + +- (void) flush; +@end |