wi_speed_calculator_t * wi_speed_calculator_init_with_capacity(wi_speed_calculator_t *speed_calculator, wi_uinteger_t capacity) { speed_calculator->length = capacity; speed_calculator->bytes = wi_malloc(capacity * sizeof(*speed_calculator->bytes)); speed_calculator->times = wi_malloc(capacity * sizeof(*speed_calculator->times)); return speed_calculator; }
wi_runtime_instance_t * wi_autorelease(wi_runtime_instance_t *instance) { wi_pool_t *pool; _wi_pool_array_t *array, *new_array; if(!instance) return NULL; pool = _wi_pool_pool(); if(!pool) { wi_log_warn(WI_STR("Instance %@ autoreleased with no pool in place - just leaking"), instance); return instance; } array = pool->array; if(array->length >= _WI_POOL_ARRAY_SIZE) { new_array = wi_malloc(sizeof(_wi_pool_array_t)); new_array->next = array; array = new_array; pool->array = array; } array->instances[array->length] = instance; array->length++; return instance; }
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; }
wi_pool_t * wi_pool_init(wi_pool_t *pool) { _wi_pool_add_pool(pool); pool->array = wi_malloc(sizeof(_wi_pool_array_t)); return pool; }
int wi_vasprintf(char **buffer, const char *fmt, va_list ap) { #ifdef HAVE_VASPRINTF return vasprintf(buffer, fmt, ap); #else FILE *tmp; char *string; int bytes; tmp = wi_tmpfile(); if(!tmp) return -1; bytes = vfprintf(tmp, fmt, ap); if(bytes < 0) { fclose(tmp); return -1; } string = wi_malloc(bytes + 1); fseek(tmp, 0, SEEK_SET); fread(string, 1, bytes, tmp); fclose(tmp); string[bytes] = '\0'; *buffer = string; return bytes; #endif }
wi_data_t * wi_data_init_with_capacity(wi_data_t *data, wi_uinteger_t capacity) { data->capacity = WI_MAX(wi_exp2m1(wi_log2(capacity) + 1), _WI_DATA_MIN_SIZE); data->bytes = wi_malloc(data->capacity); data->free = true; return data; }
wi_boolean_t wi_cipher_decrypt_bytes(wi_cipher_t *cipher, const void *encrypted_buffer, wi_uinteger_t encrypted_length, void **out_buffer, wi_uinteger_t *out_length) { void *decrypted_buffer; int decrypted_length, padded_length; decrypted_buffer = wi_malloc(encrypted_length + EVP_CIPHER_block_size(cipher->cipher)); if(EVP_DecryptUpdate(&cipher->decrypt_ctx, decrypted_buffer, &decrypted_length, encrypted_buffer, encrypted_length) != 1) { wi_error_set_openssl_error(); wi_free(decrypted_buffer); return false; } if(EVP_DecryptFinal_ex(&cipher->decrypt_ctx, decrypted_buffer + decrypted_length, &padded_length) != 1) { wi_error_set_openssl_error(); wi_free(decrypted_buffer); return false; } if(EVP_DecryptInit_ex(&cipher->decrypt_ctx, NULL, NULL, NULL, NULL) != 1) { wi_error_set_openssl_error(); wi_free(decrypted_buffer); return false; } *out_buffer = decrypted_buffer; *out_length = decrypted_length + padded_length; 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; }
wi_p7_message_t * wi_p7_message_init_with_name(wi_p7_message_t *p7_message, wi_string_t *message_name, wi_p7_socket_t *p7_socket) { p7_message = wi_p7_message_init(p7_message, p7_socket); if(p7_message->serialization == WI_P7_BINARY) { p7_message->binary_capacity = _WI_P7_MESSAGE_BINARY_BUFFER_INITIAL_SIZE; p7_message->binary_buffer = wi_malloc(p7_message->binary_capacity); p7_message->binary_size = _WI_P7_MESSAGE_BINARY_HEADER_SIZE; } else { p7_message->xml_doc = xmlNewDoc((xmlChar *) "1.0"); p7_message->xml_root_node = xmlNewNode(NULL, (xmlChar *) "message"); xmlDocSetRootElement(p7_message->xml_doc, p7_message->xml_root_node); p7_message->xml_ns = xmlNewNs(p7_message->xml_root_node, (xmlChar *) "http://www.zankasoftware.com/P7/Message", (xmlChar *) "p7"); xmlSetNs(p7_message->xml_root_node, p7_message->xml_ns); } if(!wi_p7_message_set_name(p7_message, message_name)) { wi_release(p7_message); return NULL; } return p7_message; }
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; }
char * wr_readline_command_generator(const char *text, int state) { static wi_integer_t i, max, length; const char *name; char *match; wi_integer_t bytes; wi_boolean_t help; if(state == 0) { i = 0; max = WI_ARRAY_SIZE(wr_commands); length = strlen(text); } while(i < max) { name = wr_commands[i].name; help = wr_commands[i].help; i++; if(*text == '/') { if(help && strncasecmp(name, text + 1, length - 1) == 0) { bytes = strlen(name) + 2; match = wi_malloc(bytes); snprintf(match, bytes, "/%s", name); return match; } } else { if(help && strncasecmp(name, text, length) == 0) return strdup(name); } } return NULL; }
wi_string_t * wi_string_init_with_capacity(wi_string_t *string, wi_uinteger_t capacity) { string->capacity = WI_MAX(wi_exp2m1(wi_log2(capacity) + 1), _WI_STRING_MIN_SIZE); string->string = wi_malloc(string->capacity); string->length = 0; string->free = true; return string; }
wi_data_t * wi_random_data(wi_uinteger_t length) { void *buffer; buffer = wi_malloc(length); wi_random_get_bytes(buffer, length); return wi_data_with_bytes_no_copy(buffer, length, true); }
int32_t wi_p7_socket_read_oobdata(wi_p7_socket_t *p7_socket, wi_time_interval_t timeout, void *out_buffer, uint32_t out_size) { void *receive_buffer = NULL, *decrypted_buffer, *decompressed_buffer; char length_buffer[_WI_P7_SOCKET_LENGTH_SIZE]; uint32_t receive_size, decompressed_size, decrypted_size; int32_t result = -1; if(wi_socket_read_buffer(p7_socket->socket, timeout, length_buffer, sizeof(length_buffer)) <= 0) goto end; receive_size = wi_read_swap_big_to_host_int32(length_buffer, 0); receive_buffer = wi_malloc(receive_size); result = wi_socket_read_buffer(p7_socket->socket, timeout, receive_buffer, receive_size); if(result <= 0) goto end; if(p7_socket->encryption_enabled) { if(!wi_cipher_decrypt_bytes(p7_socket->cipher, receive_buffer, receive_size, &decrypted_buffer, &decrypted_size)) { goto end; } wi_free(receive_buffer); receive_size = decrypted_size; receive_buffer = decrypted_buffer; } if(p7_socket->compression_enabled) { if(!_wi_p7_socket_xcompress_buffer(p7_socket, _WI_P7_SOCKET_DECOMPRESS, receive_buffer, receive_size, &decompressed_buffer, &decompressed_size)) { goto end; } wi_free(receive_buffer); receive_size = decompressed_size; receive_buffer = decompressed_buffer; } memcpy(out_buffer, receive_buffer, receive_size); result = receive_size; end: wi_free(receive_buffer); return result; }
wi_array_t * wi_array_init_with_capacity_and_callbacks(wi_array_t *array, wi_uinteger_t capacity, wi_array_callbacks_t callbacks) { array->callbacks = callbacks; array->item_chunks_offset = _wi_array_items_per_page; array->items_count = WI_MAX(wi_exp2m1(wi_log2(capacity) + 1), _WI_ARRAY_MIN_COUNT); array->min_count = array->items_count; array->items = wi_malloc(array->items_count * sizeof(_wi_array_item_t *)); array->lock = wi_rwlock_init(wi_rwlock_alloc()); return array; }
wi_set_t * wi_set_init_with_capacity_and_callbacks(wi_set_t *set, wi_uinteger_t capacity, wi_set_callbacks_t callbacks) { set->callbacks = callbacks; set->bucket_chunks_offset = _wi_set_buckets_per_page; set->min_count = WI_MAX(wi_exp2m1(wi_log2(capacity) + 1), _WI_SET_MIN_COUNT); set->buckets_count = set->min_count; set->buckets = wi_malloc(set->buckets_count * sizeof(_wi_set_bucket_t *)); set->lock = wi_rwlock_init(wi_rwlock_alloc()); return set; }
wi_dictionary_t * wi_dictionary_init_with_capacity_and_callbacks(wi_dictionary_t *dictionary, wi_uinteger_t capacity, wi_dictionary_key_callbacks_t key_callbacks, wi_dictionary_value_callbacks_t value_callbacks) { dictionary->key_callbacks = key_callbacks; dictionary->value_callbacks = value_callbacks; dictionary->bucket_chunks_offset = _wi_dictionary_buckets_per_page; dictionary->min_count = WI_MAX(wi_exp2m1(wi_log2(capacity) + 1), _WI_DICTIONARY_MIN_COUNT); dictionary->buckets_count = dictionary->min_count; dictionary->buckets = wi_malloc(dictionary->buckets_count * sizeof(_wi_dictionary_bucket_t *)); return dictionary; }
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; }
wi_p7_message_t * wi_p7_message_init_with_name(wi_p7_message_t *p7_message, wi_string_t *message_name, wi_p7_spec_t *p7_spec) { p7_message->spec = wi_retain(p7_spec); p7_message->binary_capacity = _WI_P7_MESSAGE_BINARY_BUFFER_INITIAL_SIZE; p7_message->binary_buffer = wi_malloc(p7_message->binary_capacity); p7_message->binary_size = WI_P7_MESSAGE_BINARY_HEADER_SIZE; if(!wi_p7_message_set_name(p7_message, message_name)) { wi_release(p7_message); return NULL; } return p7_message; }
wi_boolean_t wi_thread_create_thread_with_priority(wi_thread_func_t *function, wi_runtime_instance_t *argument, double priority) { #ifdef WI_PTHREADS #if defined(HAVE_PTHREAD_ATTR_SETSCHEDPOLICY) && defined(HAVE_SCHED_GET_PRIORITY_MIN) && defined(HAVE_SCHED_GET_PRIORITY_MAX) struct sched_param param; int min, max; #endif pthread_t thread; pthread_attr_t attr; void **vector; int err; vector = wi_malloc(2 * sizeof(void *)); vector[0] = function; vector[1] = wi_retain(argument); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); #if defined(HAVE_PTHREAD_ATTR_SETSCHEDPOLICY) && defined(HAVE_SCHED_GET_PRIORITY_MIN) && defined(HAVE_SCHED_GET_PRIORITY_MAX) min = sched_get_priority_min(SCHED_OTHER); max = sched_get_priority_max(SCHED_OTHER); if(min > 0 && max > 0) param.sched_priority = min + ((max - min) * priority); else param.sched_priority = 0; pthread_attr_setschedpolicy(&attr, SCHED_OTHER); pthread_attr_setschedparam(&attr, ¶m); #endif err = pthread_create(&thread, &attr, _wi_thread_trampoline, vector); pthread_attr_destroy(&attr); if(err != 0) { wi_error_set_errno(err); wi_release(vector[1]); wi_free(vector); return false; } return true; #else wi_error_set_errno(WI_ERROR_THREADS_NOTSUPP); return false; #endif }
static void _wi_pool_add_pool(wi_pool_t *pool) { _wi_pool_stack_t *stack; stack = _wi_pool_poolstack(NULL); if(!stack) { stack = wi_malloc(sizeof(_wi_pool_stack_t)); stack->thread = wi_thread_current_thread(); _wi_pool_add_poolstack(stack); } _wi_pool_add_pool_to_poolstack(pool, stack); }
wi_array_t * wi_dictionary_keys_sorted_by_value(wi_dictionary_t *dictionary, wi_compare_func_t *compare) { wi_mutable_array_t *array, *buckets; _wi_dictionary_bucket_t *bucket; wi_array_callbacks_t callbacks; void **data; wi_uinteger_t i; if(dictionary->key_count == 0) return wi_autorelease(wi_array_init(wi_array_alloc())); callbacks.retain = NULL; callbacks.release = NULL; callbacks.is_equal = NULL; callbacks.description = NULL; buckets = wi_array_init_with_capacity_and_callbacks(wi_mutable_array_alloc(), dictionary->key_count, callbacks); for(i = 0; i < dictionary->buckets_count; i++) { for(bucket = dictionary->buckets[i]; bucket; bucket = bucket->next) wi_mutable_array_add_data(buckets, bucket); } data = wi_malloc(sizeof(void *) * dictionary->key_count); wi_array_get_data(buckets, data); #ifdef _WI_DICTIONARY_USE_QSORT_R qsort_r(data, dictionary->key_count, sizeof(void *), compare, _wi_dictionary_compare_buckets); #else wi_lock_lock(_wi_dictionary_sort_lock); _wi_dictionary_sort_function = compare; qsort(data, dictionary->key_count, sizeof(void *), _wi_dictionary_compare_buckets); wi_lock_unlock(_wi_dictionary_sort_lock); #endif callbacks.retain = dictionary->key_callbacks.retain; callbacks.release = dictionary->key_callbacks.release; callbacks.is_equal = dictionary->key_callbacks.is_equal; callbacks.description = dictionary->key_callbacks.description; array = wi_array_init_with_capacity_and_callbacks(wi_mutable_array_alloc(), dictionary->key_count, callbacks); for(i = 0; i < dictionary->key_count; i++) wi_mutable_array_add_data(array, ((_wi_dictionary_bucket_t *) data[i])->key); wi_free(data); wi_release(buckets); wi_runtime_make_immutable(array); return wi_autorelease(array); }
int32_t wi_socket_recvfrom(wi_socket_t *socket, wi_socket_context_t *context, char *buffer, size_t length, wi_address_t **address) { struct sockaddr_storage ss; char *inbuffer = NULL; socklen_t sslength; int bytes; sslength = sizeof(ss); #ifdef WI_SSL if(context && context->priv_rsa) { inbuffer = wi_malloc(length); bytes = recvfrom(socket->sd, inbuffer, length, 0, (struct sockaddr *) &ss, &sslength); if(bytes < 0) { wi_error_set_errno(errno); goto end; } bytes = RSA_private_decrypt(bytes, (unsigned char *) inbuffer, (unsigned char *) buffer, context->priv_rsa, RSA_PKCS1_OAEP_PADDING); if(bytes < 0) { wi_error_set_ssl_error(); goto end; } } else { #endif bytes = recvfrom(socket->sd, buffer, length, 0, (struct sockaddr *) &ss, &sslength); if(bytes < 0) { wi_error_set_errno(errno); goto end; } #ifdef WI_SSL } #endif end: *address = (sslength > 0) ? wi_autorelease(wi_address_init_with_sa(wi_address_alloc(), (struct sockaddr *) &ss)) : NULL; if(inbuffer) wi_free(inbuffer); return bytes; }
wi_data_t * wi_cipher_decrypt(wi_cipher_t *cipher, wi_data_t *encrypted_data) { const void *encrypted_buffer; void *decrypted_buffer; wi_uinteger_t encrypted_length; wi_integer_t decrypted_length; encrypted_buffer = wi_data_bytes(encrypted_data); encrypted_length = wi_data_length(encrypted_data); decrypted_buffer = wi_malloc(wi_cipher_block_size(cipher) + encrypted_length); decrypted_length = wi_cipher_decrypt_bytes(cipher, encrypted_buffer, encrypted_length, decrypted_buffer); if(decrypted_length < 0) return NULL; return wi_data_with_bytes_no_copy(decrypted_buffer, decrypted_length, true); }
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; }
wi_boolean_t wi_rsa_decrypt_bytes(wi_rsa_t *rsa, const void *encrypted_buffer, wi_uinteger_t encrypted_length, void **out_buffer, wi_uinteger_t *out_length) { void *decrypted_buffer; int32_t decrypted_length; decrypted_buffer = wi_malloc(RSA_size(rsa->rsa)); decrypted_length = RSA_private_decrypt(encrypted_length, encrypted_buffer, decrypted_buffer, rsa->rsa, RSA_PKCS1_PADDING); if(decrypted_length == -1) { wi_error_set_openssl_error(); wi_free(decrypted_buffer); return false; } *out_buffer = decrypted_buffer; *out_length = decrypted_length; return true; }
int32_t wi_socket_sendto_buffer(wi_socket_t *socket, wi_socket_context_t *context, const char *buffer, size_t length) { wi_address_t *address; char *outbuffer = NULL; int bytes; address = wi_socket_address(socket); #ifdef WI_SSL if(context && context->pub_rsa) { outbuffer = wi_malloc(RSA_size(context->pub_rsa)); bytes = RSA_public_encrypt(length, (unsigned char *) buffer, (unsigned char *) outbuffer, context->pub_rsa, RSA_PKCS1_OAEP_PADDING); if(bytes < 0) { wi_error_set_ssl_error(); goto end; } bytes = sendto(socket->sd, outbuffer, bytes, 0, wi_address_sa(address), wi_address_sa_length(address)); } else { #endif bytes = sendto(socket->sd, buffer, length, 0, wi_address_sa(address), wi_address_sa_length(address)); #ifdef WI_SSL } #endif if(bytes < 0) { wi_error_set_errno(errno); goto end; } end: if(outbuffer) wi_free(outbuffer); return bytes; }
wi_p7_message_t * wi_p7_message_init_with_bytes(wi_p7_message_t *p7_message, const void *bytes, wi_uinteger_t length, wi_p7_serialization_t serialization, wi_p7_spec_t *p7_spec) { p7_message->spec = wi_retain(p7_spec); p7_message->binary_size = length; p7_message->binary_capacity = p7_message->binary_size; p7_message->binary_buffer = wi_malloc(p7_message->binary_capacity); memcpy(p7_message->binary_buffer, bytes, p7_message->binary_size); wi_p7_message_deserialize(p7_message, WI_P7_BINARY); if(!p7_message->name) { wi_error_set_libwired_error(WI_ERROR_P7_UNKNOWNMESSAGE); wi_release(p7_message); return NULL; } return p7_message; }
static void _wi_set_resize(wi_set_t *set) { _wi_set_bucket_t **buckets, *bucket, *next_bucket; wi_uinteger_t i, index, capacity, buckets_count; capacity = wi_exp2m1(wi_log2(set->data_count) + 1); buckets_count = WI_CLAMP(capacity, set->min_count, _WI_SET_MAX_COUNT); buckets = wi_malloc(buckets_count * sizeof(_wi_set_bucket_t *)); for(i = 0; i < set->buckets_count; i++) { for(bucket = set->buckets[i]; bucket; bucket = next_bucket) { next_bucket = bucket->next; index = _WI_SET_HASH(set, bucket->data) % buckets_count; bucket->next = buckets[index]; buckets[index] = bucket; } } wi_free(set->buckets); set->buckets = buckets; set->buckets_count = buckets_count; }