|
|
@ -39,17 +39,19 @@ |
|
|
|
|
|
|
|
|
|
|
|
// TODO(jcanizales): Move these two incantations to the C library. |
|
|
|
// TODO(jcanizales): Move these two incantations to the C library. |
|
|
|
|
|
|
|
|
|
|
|
static void CopyByteBufferToCharArray(grpc_byte_buffer *buffer, char *array) { |
|
|
|
static void MallocAndCopyByteBufferToCharArray(grpc_byte_buffer *buffer, |
|
|
|
size_t offset = 0; |
|
|
|
size_t *length, char **array) { |
|
|
|
grpc_byte_buffer_reader reader; |
|
|
|
grpc_byte_buffer_reader reader; |
|
|
|
grpc_byte_buffer_reader_init(&reader, buffer); |
|
|
|
grpc_byte_buffer_reader_init(&reader, buffer); |
|
|
|
gpr_slice next; |
|
|
|
gpr_slice slice = grpc_byte_buffer_reader_readall(&reader); |
|
|
|
while (grpc_byte_buffer_reader_next(&reader, &next) != 0){ |
|
|
|
size_t uncompressed_length = GPR_SLICE_LENGTH(slice); |
|
|
|
memcpy(array + offset, GPR_SLICE_START_PTR(next), |
|
|
|
char *result = malloc(uncompressed_length); |
|
|
|
(size_t)GPR_SLICE_LENGTH(next)); |
|
|
|
if (result) { |
|
|
|
offset += GPR_SLICE_LENGTH(next); |
|
|
|
memcpy(result, GPR_SLICE_START_PTR(slice), uncompressed_length); |
|
|
|
gpr_slice_unref(next); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
gpr_slice_unref(slice); |
|
|
|
|
|
|
|
*array = result; |
|
|
|
|
|
|
|
*length = uncompressed_length; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, |
|
|
|
static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, |
|
|
@ -65,8 +67,9 @@ static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, |
|
|
|
if (buffer == NULL) { |
|
|
|
if (buffer == NULL) { |
|
|
|
return nil; |
|
|
|
return nil; |
|
|
|
} |
|
|
|
} |
|
|
|
NSUInteger length = grpc_byte_buffer_length(buffer); |
|
|
|
char *array; |
|
|
|
char *array = malloc(length * sizeof(*array)); |
|
|
|
NSUInteger length; |
|
|
|
|
|
|
|
MallocAndCopyByteBufferToCharArray(buffer, &length, &array); |
|
|
|
if (!array) { |
|
|
|
if (!array) { |
|
|
|
// TODO(jcanizales): grpc_byte_buffer is reference-counted, so we can |
|
|
|
// TODO(jcanizales): grpc_byte_buffer is reference-counted, so we can |
|
|
|
// prevent this memory problem by implementing a subclass of NSData |
|
|
|
// prevent this memory problem by implementing a subclass of NSData |
|
|
@ -74,7 +77,6 @@ static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, |
|
|
|
// can be implemented using a grpc_byte_buffer_reader. |
|
|
|
// can be implemented using a grpc_byte_buffer_reader. |
|
|
|
return nil; |
|
|
|
return nil; |
|
|
|
} |
|
|
|
} |
|
|
|
CopyByteBufferToCharArray(buffer, array); |
|
|
|
|
|
|
|
return [self dataWithBytesNoCopy:array length:length freeWhenDone:YES]; |
|
|
|
return [self dataWithBytesNoCopy:array length:length freeWhenDone:YES]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -85,8 +87,10 @@ static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, |
|
|
|
// The following implementation is thus not optimal, sometimes requiring two |
|
|
|
// The following implementation is thus not optimal, sometimes requiring two |
|
|
|
// copies (one by self.bytes and another by gpr_slice_from_copied_buffer). |
|
|
|
// copies (one by self.bytes and another by gpr_slice_from_copied_buffer). |
|
|
|
// If it turns out to be an issue, we can use enumerateByteRangesUsingblock: |
|
|
|
// If it turns out to be an issue, we can use enumerateByteRangesUsingblock: |
|
|
|
// to create an array of gpr_slice objects to pass to grpc_raw_byte_buffer_create. |
|
|
|
// to create an array of gpr_slice objects to pass to |
|
|
|
|
|
|
|
// grpc_raw_byte_buffer_create. |
|
|
|
// That would make it do exactly one copy, always. |
|
|
|
// That would make it do exactly one copy, always. |
|
|
|
return CopyCharArrayToNewByteBuffer((const char *)self.bytes, (size_t)self.length); |
|
|
|
return CopyCharArrayToNewByteBuffer((const char *)self.bytes, |
|
|
|
|
|
|
|
(size_t)self.length); |
|
|
|
} |
|
|
|
} |
|
|
|
@end |
|
|
|
@end |
|
|
|