static bool _dispatch_transform_buffer_new(dispatch_transform_buffer_s *buffer, size_t required, size_t size) { size_t remaining = buffer->size - (buffer->ptr.u8 - buffer->start); if (required == 0 || remaining < required) { if (buffer->start) { if (buffer->ptr.u8 > buffer->start) { dispatch_data_t _new = dispatch_data_create(buffer->start, buffer->ptr.u8 - buffer->start, NULL, DISPATCH_DATA_DESTRUCTOR_FREE); dispatch_data_t _concat = dispatch_data_create_concat( buffer->data, _new); dispatch_release(_new); dispatch_release(buffer->data); buffer->data = _concat; } else { free(buffer->start); } } buffer->size = required + size; buffer->start = NULL; if (buffer->size > 0) { if (buffer->size > BUFFER_MALLOC_MAX) { return false; } buffer->start = (uint8_t*)malloc(buffer->size); if (buffer->start == NULL) { return false; } } buffer->ptr.u8 = buffer->start; } return true; }
static void test_concat(void) { dispatch_group_enter(g); dispatch_async(dispatch_get_main_queue(), ^{ char* buffer1 = "This is buffer1 "; size_t size1 = 17; char* buffer2 = "This is buffer2 "; size_t size2 = 17; __block bool buffer2_destroyed = false; dispatch_data_t data1 = dispatch_data_create(buffer1, size1, NULL, NULL); dispatch_data_t data2 = dispatch_data_create(buffer2, size2, dispatch_get_main_queue(), ^{ buffer2_destroyed = true; }); dispatch_data_t concat = dispatch_data_create_concat(data1, data2); dispatch_release(data1); dispatch_release(data2); test_long("Data size of concatenated dispatch data", dispatch_data_get_size(concat), 34); const void* contig; size_t contig_size; dispatch_data_t contig_data = dispatch_data_create_map(concat, &contig, &contig_size); dispatch_release(concat); dispatch_release(contig_data); test_long("Contiguous memory size", contig_size, 34); dispatch_async(dispatch_get_main_queue(), ^{ test_long("buffer2 destroyed", buffer2_destroyed, true); dispatch_group_leave(g); });
dispatch_group_t g = dispatch_group_create(); dispatch_group_enter(g); dispatch_read(fd, size, dispatch_get_global_queue(0, 0), ^(dispatch_data_t d1, int error) { test_errno("Client-dict-read error", error, 0); test_long("Client-dict-dispatch data size", dispatch_data_get_size(d1), size); dispatch_retain(d1); g_d1 = d1; dispatch_group_leave(g); }); __block void (^b)(dispatch_data_t, int); b = Block_copy(^(dispatch_data_t d2, int error) { dispatch_data_t concat = dispatch_data_create_concat(g_d2, d2); dispatch_release(g_d2); g_d2 = concat; if (!error && dispatch_data_get_size(d2)) { dispatch_read(sockfd, SIZE_MAX, dispatch_get_global_queue(0, 0), b); } else { g_error = error; dispatch_group_leave(g); } }); dispatch_group_enter(g); dispatch_read(sockfd, SIZE_MAX, dispatch_get_global_queue(0, 0), b); test_group_wait(g); test_errno("Client-read error", g_error, 0); test_long("Client-dispatch data size", dispatch_data_get_size(g_d2),