static wi_boolean_t _wi_p7_message_get_binary_buffer_for_writing_for_id(wi_p7_message_t *p7_message, uint32_t field_id, uint32_t length, unsigned char **out_buffer) { wi_p7_spec_field_t *field; uint32_t field_size, new_size; new_size = sizeof(field_id); field = wi_p7_spec_field_with_id(p7_message->spec, field_id); field_size = wi_p7_spec_field_size(field); if(field_size == 0) { field_size = length; new_size += sizeof(uint32_t); } new_size += field_size; if(_wi_p7_message_get_binary_buffer_for_reading_for_id(p7_message, field_id, NULL, NULL)) return false; if(p7_message->binary_size + new_size > p7_message->binary_capacity) { p7_message->binary_capacity = p7_message->binary_size + new_size; p7_message->binary_buffer = wi_realloc(p7_message->binary_buffer, p7_message->binary_capacity); } if(out_buffer) *out_buffer = p7_message->binary_buffer + p7_message->binary_size; p7_message->binary_size += new_size; return true; }
static _wi_set_bucket_t * _wi_set_bucket_create(wi_set_t *set) { _wi_set_bucket_t *bucket, *bucket_block; size_t size; if(!set->bucket_free_list) { if(set->bucket_chunks_offset == _wi_set_buckets_per_page) { set->bucket_chunks_count++; size = set->bucket_chunks_count * sizeof(_wi_set_bucket_t *); set->bucket_chunks = wi_realloc(set->bucket_chunks, size); size = _wi_set_buckets_per_page * sizeof(_wi_set_bucket_t); set->bucket_chunks[set->bucket_chunks_count - 1] = wi_malloc(size); set->bucket_chunks_offset = 0; } bucket_block = set->bucket_chunks[set->bucket_chunks_count - 1]; set->bucket_free_list = &bucket_block[set->bucket_chunks_offset++]; set->bucket_free_list->link = NULL; } bucket = set->bucket_free_list; set->bucket_free_list = bucket->link; return bucket; }
static void _wi_pool_add_poolstack(_wi_pool_stack_t *stack) { uint32_t index, capacity, length; index = wi_hash_pointer(stack->thread) % _WI_POOL_STACKS_BUCKETS; wi_lock_lock(_wi_pool_stacks_lock); capacity = _wi_pool_stacks_capacities[index]; length = _wi_pool_stacks_lengths[index]; if(length >= capacity) { capacity += capacity; if(capacity < _WI_POOL_STACKS_INITIAL_SIZE) capacity = _WI_POOL_STACKS_INITIAL_SIZE; _wi_pool_stacks[index] = wi_realloc(_wi_pool_stacks[index], capacity * sizeof(_wi_pool_stack_t)); _wi_pool_stacks_capacities[index] = capacity; } _wi_pool_stacks[index][length] = stack; _wi_pool_stacks_lengths[index] = ++length; wi_lock_unlock(_wi_pool_stacks_lock); }
static _wi_dictionary_bucket_t * _wi_dictionary_bucket_create(wi_dictionary_t *dictionary) { _wi_dictionary_bucket_t *bucket, *bucket_block; size_t size; if(!dictionary->bucket_free_list) { if(dictionary->bucket_chunks_offset == _wi_dictionary_buckets_per_page) { dictionary->bucket_chunks_count++; size = dictionary->bucket_chunks_count * sizeof(_wi_dictionary_bucket_t *); dictionary->bucket_chunks = wi_realloc(dictionary->bucket_chunks, size); size = _wi_dictionary_buckets_per_page * sizeof(_wi_dictionary_bucket_t); dictionary->bucket_chunks[dictionary->bucket_chunks_count - 1] = wi_malloc(size); dictionary->bucket_chunks_offset = 0; } bucket_block = dictionary->bucket_chunks[dictionary->bucket_chunks_count - 1]; dictionary->bucket_free_list = &bucket_block[dictionary->bucket_chunks_offset++]; dictionary->bucket_free_list->link = NULL; } bucket = dictionary->bucket_free_list; dictionary->bucket_free_list = bucket->link; return bucket; }
static wi_list_node_t * _wi_list_node_create(wi_list_t *list) { wi_list_node_t *node, *node_block; size_t size; if(!list->node_free_list) { if(list->node_chunks_offset == _wi_list_nodes_per_page) { list->node_chunks_count++; size = list->node_chunks_count * sizeof(wi_list_node_t *); list->node_chunks = wi_realloc(list->node_chunks, size); size = _wi_list_nodes_per_page * sizeof(wi_list_node_t); list->node_chunks[list->node_chunks_count - 1] = wi_malloc(size); list->node_chunks_offset = 0; } node_block = list->node_chunks[list->node_chunks_count - 1]; list->node_free_list = &node_block[list->node_chunks_offset++]; list->node_free_list->link = NULL; } node = list->node_free_list; list->node_free_list = node->link; return node; }
static _wi_array_item_t * _wi_array_create_item(wi_array_t *array) { _wi_array_item_t *item, *item_block; size_t size; if(!array->item_free_list) { if(array->item_chunks_offset == _wi_array_items_per_page) { array->item_chunks_count++; size = array->item_chunks_count * sizeof(_wi_array_item_t *); array->item_chunks = wi_realloc(array->item_chunks, size); size = _wi_array_items_per_page * sizeof(_wi_array_item_t); array->item_chunks[array->item_chunks_count - 1] = wi_malloc(size); array->item_chunks_offset = 0; } item_block = array->item_chunks[array->item_chunks_count - 1]; array->item_free_list = &item_block[array->item_chunks_offset++]; array->item_free_list->link = NULL; } item = array->item_free_list; array->item_free_list = item->link; return item; }
static void _wi_array_optimize(wi_array_t *array) { wi_uinteger_t items_count; items_count = WI_CLAMP(array->data_count, array->min_count, _WI_ARRAY_MAX_COUNT); array->items = wi_realloc(array->items, items_count * sizeof(_wi_array_item_t *)); array->items_count = items_count; }
static void _wi_array_grow(wi_array_t *array, wi_uinteger_t index) { wi_uinteger_t items_count; items_count = (wi_uinteger_t) ((double) ((index + 1) * 3) / 2.0); array->items = wi_realloc(array->items, items_count * sizeof(_wi_array_item_t *)); array->items_count = items_count; }
static void _wi_data_append_bytes(wi_mutable_data_t *data, const void *bytes, wi_uinteger_t length) { if(data->length + length > data->capacity) { data->capacity = data->length + length; data->bytes = wi_realloc(data->bytes, data->capacity); } memcpy(data->bytes + data->length, bytes, length); data->length += length; }
static void _wi_string_grow(wi_string_t *string, wi_uinteger_t capacity) { capacity = WI_MAX(wi_exp2m1(wi_log2(capacity) + 1), _WI_STRING_MIN_SIZE); if(string->free) { string->string = wi_realloc(string->string, capacity); } else { string->string = wi_malloc(capacity); string->free = true; } string->capacity = capacity; }
static void _wi_pool_add_pool_to_poolstack(wi_pool_t *pool, _wi_pool_stack_t *stack) { if(stack->length >= stack->capacity) { stack->capacity += stack->capacity; if(stack->capacity < _WI_POOL_STACK_INITIAL_SIZE) stack->capacity = _WI_POOL_STACK_INITIAL_SIZE; stack->pools = wi_realloc(stack->pools, stack->capacity * sizeof(wi_pool_t *)); } stack->pools[stack->length] = pool; stack->length++; }
static wi_boolean_t _wi_p7_socket_xcompress_buffer(wi_p7_socket_t *p7_socket, _wi_p7_socket_compression_t compression, const void *in_buffer, uint32_t in_size, void **out_buffer, uint32_t *out_size) { const void *input; void *output, *working_buffer; z_stream *stream; uint32_t offset, input_size, input_processed, output_size, working_size, total_working_size; int err; stream = (compression == _WI_P7_SOCKET_COMPRESS) ? &p7_socket->compression_stream : &p7_socket->decompression_stream; working_size = (compression == _WI_P7_SOCKET_COMPRESS) ? in_size : 4 * in_size; working_buffer = wi_malloc(working_size); input = in_buffer; input_size = in_size; output = working_buffer; output_size = working_size; total_working_size = 0; while(true) { err = _wi_p7_socket_xflate_buffer(stream, compression, input, input_size, &input_processed, output, &output_size); if(err != Z_OK) { wi_error_set_zlib_error(err); wi_free(working_buffer); return false; } total_working_size += output_size; if(stream->avail_out > 0) break; offset = (output - working_buffer) + output_size; working_size *= 4; working_buffer = wi_realloc(working_buffer, working_size); output = working_buffer + offset; output_size = working_size - offset; input += input_processed; input_size -= input_processed; } *out_buffer = working_buffer; *out_size = total_working_size; return true; }
static wi_boolean_t _wi_p7_message_get_binary_buffer_for_writing_for_name(wi_p7_message_t *p7_message, wi_string_t *field_name, uint32_t length, unsigned char **out_buffer, uint32_t *out_field_id) { uint32_t field_id, field_size, old_size, new_size; field_id = wi_p7_spec_field_id(p7_message->spec, field_name); if(field_id == WI_P7_SPEC_FIELD_ID_NULL) { wi_error_set_libwired_p7_error(WI_ERROR_P7_UNKNOWNFIELD, WI_STR("No id found for field \"%@\""), field_name); return false; } if(length > 0) field_size = length; else field_size = wi_p7_spec_field_size(p7_message->spec, field_id); if(_wi_p7_message_get_binary_buffer_for_reading_for_id(p7_message, field_id, 0, out_buffer, &old_size)) { if(field_size == old_size) return true; } new_size = sizeof(field_id) + field_size; if(length > 0) new_size += sizeof(length); if(p7_message->binary_size + new_size > p7_message->binary_capacity) { p7_message->binary_capacity *= 2; p7_message->binary_buffer = wi_realloc(p7_message->binary_buffer, p7_message->binary_capacity); } if(out_buffer) *out_buffer = p7_message->binary_buffer + p7_message->binary_size; if(out_field_id) *out_field_id = field_id; p7_message->binary_size += new_size; return true; }
static wi_p7_message_t * _wi_p7_socket_read_binary_message(wi_p7_socket_t *p7_socket, wi_time_interval_t timeout, uint32_t message_size) { wi_p7_message_t *p7_message; void *decompressed_buffer, *decrypted_buffer; unsigned char local_checksum_buffer[_WI_P7_SOCKET_CHECKSUM_LENGTH]; unsigned char remote_checksum_buffer[_WI_P7_SOCKET_CHECKSUM_LENGTH]; uint32_t decompressed_size, decrypted_size; int32_t length; p7_message = wi_autorelease(wi_p7_message_init(wi_p7_message_alloc(), p7_socket)); if(!p7_message->binary_buffer) { p7_message->binary_capacity = message_size; p7_message->binary_buffer = wi_malloc(p7_message->binary_capacity); } else if(message_size > p7_message->binary_capacity) { p7_message->binary_capacity = message_size; p7_message->binary_buffer = wi_realloc(p7_message->binary_buffer, message_size); } length = wi_socket_read_buffer(p7_socket->socket, timeout, p7_message->binary_buffer, message_size); if(length <= 0) return NULL; p7_message->binary_size = length; p7_socket->read_raw_bytes += p7_message->binary_size; if(p7_socket->encryption_enabled) { if(!wi_cipher_decrypt_bytes(p7_socket->cipher, p7_message->binary_buffer, p7_message->binary_size, &decrypted_buffer, &decrypted_size)) { return NULL; } wi_free(p7_message->binary_buffer); p7_message->binary_size = decrypted_size; p7_message->binary_capacity = decrypted_size; p7_message->binary_buffer = decrypted_buffer; } if(p7_socket->compression_enabled) { if(!_wi_p7_socket_xcompress_buffer(p7_socket, _WI_P7_SOCKET_DECOMPRESS, p7_message->binary_buffer, p7_message->binary_size, &decompressed_buffer, &decompressed_size)) { return NULL; } wi_free(p7_message->binary_buffer); p7_message->binary_size = decompressed_size; p7_message->binary_capacity = decompressed_size; p7_message->binary_buffer = decompressed_buffer; } p7_socket->read_processed_bytes += p7_message->binary_size; if(p7_socket->checksum_enabled) { length = wi_socket_read_buffer(p7_socket->socket, timeout, remote_checksum_buffer, p7_socket->checksum_length); if(length <= 0) return NULL; _wi_p7_socket_checksum_binary_message(p7_socket, p7_message, local_checksum_buffer); if(memcmp(remote_checksum_buffer, local_checksum_buffer, p7_socket->checksum_length) != 0) { wi_error_set_libwired_p7_error(WI_ERROR_P7_CHECKSUMMISMATCH, WI_STR("")); return NULL; } } return p7_message; }