fix for working with compressed data. Fixes #6746.

Using correct API that gives length of uncompressed data so correct amount of memory is allocated.
pull/7120/head
Makarand Dharmapurikar 9 years ago
parent fe466b0e17
commit d99a925d52
  1. 30
      src/objective-c/GRPCClient/private/NSData+GRPC.m

@ -39,17 +39,19 @@
// TODO(jcanizales): Move these two incantations to the C library.
static void CopyByteBufferToCharArray(grpc_byte_buffer *buffer, char *array) {
size_t offset = 0;
static void MallocAndCopyByteBufferToCharArray(grpc_byte_buffer *buffer,
size_t *length, char **array) {
grpc_byte_buffer_reader reader;
grpc_byte_buffer_reader_init(&reader, buffer);
gpr_slice next;
while (grpc_byte_buffer_reader_next(&reader, &next) != 0){
memcpy(array + offset, GPR_SLICE_START_PTR(next),
(size_t)GPR_SLICE_LENGTH(next));
offset += GPR_SLICE_LENGTH(next);
gpr_slice_unref(next);
gpr_slice slice = grpc_byte_buffer_reader_readall(&reader);
size_t uncompressed_length = GPR_SLICE_LENGTH(slice);
char *result = malloc(uncompressed_length);
if (result) {
memcpy(result, GPR_SLICE_START_PTR(slice), uncompressed_length);
}
gpr_slice_unref(slice);
*array = result;
*length = uncompressed_length;
}
static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array,
@ -65,8 +67,9 @@ static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array,
if (buffer == NULL) {
return nil;
}
NSUInteger length = grpc_byte_buffer_length(buffer);
char *array = malloc(length * sizeof(*array));
char *array;
NSUInteger length;
MallocAndCopyByteBufferToCharArray(buffer, &length, &array);
if (!array) {
// TODO(jcanizales): grpc_byte_buffer is reference-counted, so we can
// 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.
return nil;
}
CopyByteBufferToCharArray(buffer, array);
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
// 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:
// 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.
return CopyCharArrayToNewByteBuffer((const char *)self.bytes, (size_t)self.length);
return CopyCharArrayToNewByteBuffer((const char *)self.bytes,
(size_t)self.length);
}
@end

Loading…
Cancel
Save