void string_resize(StringData** data, int newLength) { if (*data == NULL) { *data = string_create(newLength); return; } // Perform the same check as touch() if ((*data)->refCount == 1) { INCREMENT_STAT(StringResizeInPlace); // Modify in-place *data = (StringData*) realloc(*data, sizeof(StringData) + newLength + 1); (*data)->length = newLength; return; } INCREMENT_STAT(StringResizeCreate); StringData* oldData = *data; StringData* newData = string_create(newLength); memcpy(newData->str, oldData->str, oldData->length + 1); decref(oldData); *data = newData; }
void dynamic_method_call(caStack* stack) { INCREMENT_STAT(DynamicMethodCall); caValue* args = circa_input(stack, 0); caValue* object = circa_index(args, 0); // Lookup method Term* term = (Term*) circa_caller_term(stack); std::string functionName = term->stringProp("syntax:functionName", ""); // Find and dispatch method Term* method = find_method((Block*) circa_caller_block(stack), (Type*) circa_type_of(object), functionName.c_str()); // copy(object, circa_output(stack, 1)); if (method != NULL) { // Grab inputs before pop Value inputs; swap(args, &inputs); pop_frame(stack); push_frame_with_inputs(stack, function_contents(method), &inputs); return; } // Method not found. Raise error. std::string msg; msg += "Method "; msg += functionName; msg += " not found on type "; msg += as_cstring(&circa_type_of(object)->name); circa_output_error(stack, msg.c_str()); }
http_connection* create_http_connection() { http_connection* connection = malloc(sizeof(http_connection)); connection->request = NULL; INCREMENT_STAT(stat_connections_created_total); return connection; }
http_connection* create_http_connection() { http_connection* connection = calloc(1, sizeof(http_connection)); connection->buffer = http_request_buffer_init(config->max_request_size); INCREMENT_STAT(stat_connections_created_total); return connection; }
http_request_context* create_http_context() { http_request_context* context = (http_request_context *)malloc(sizeof(http_request_context)); context->request = NULL; INCREMENT_STAT(stat_connections_created_total); return context; }
// Creates a hard duplicate of a string. Starts off with 1 ref. StringData* string_duplicate(StringData* original) { INCREMENT_STAT(StringDuplicate); StringData* dup = string_create(original->length); memcpy(dup->str, original->str, original->length + 1); return dup; }
void free_http_connection(http_connection* connection) { if (connection->request != NULL) { free_http_request(connection->request); } free(connection); INCREMENT_STAT(stat_connections_destroyed_total); }
// Create a new blank string with the given length. Starts off with 1 ref. StringData* string_create(int length) { INCREMENT_STAT(StringCreate); StringData* result = (StringData*) malloc(sizeof(StringData) + length + 1); result->refCount = 1; result->length = length; result->str[0] = 0; return result; }
http_connection* create_http_connection() { http_connection* connection = malloc(sizeof(http_connection)); connection->request = NULL; connection->current_header_key.length = 0; connection->current_header_value.length = 0; connection->last_was_value = 0; INCREMENT_STAT(stat_connections_created_total); return connection; }
void touch(caValue* value) { INCREMENT_STAT(ValueTouch); Type::Touch touch = value->value_type->touch; if (touch != NULL) touch(value); // Default behavior: no-op. }
void free_http_connection(http_connection* connection) { if (connection->request) { free_http_request(connection->request); } http_request_buffer_destroy(connection->buffer); free(connection); INCREMENT_STAT(stat_connections_destroyed_total); }
void tv_cast(CastResult* result, caValue* value, Type* type, bool checkOnly) { if (!is_list(value)) { result->success = false; return; } int sourceLength = list_length(value); // If the requested type doesn't have a specific size restriction, then // the input data is fine as-is. if (!list_type_has_specific_size(&type->parameter)) { if (!checkOnly) value->value_type = type; return; } List& destTypes = *List::checkCast(list_get_type_list_from_type(type)); // Check for correct number of elements. if (sourceLength != destTypes.length()) { result->success = false; return; } if (!checkOnly) { INCREMENT_STAT(Touch_ListCast); list_touch(value); value->value_type = type; } for (int i=0; i < sourceLength; i++) { caValue* sourceElement = list_get(value, i); Type* expectedType = as_type(destTypes[i]); INCREMENT_STAT(Cast_ListCastElement); cast(result, sourceElement, expectedType, checkOnly); if (!result->success) return; } }
void string_copy(Type* type, caValue* source, caValue* dest) { set_null(dest); StringData* data = (StringData*) source->value_data.ptr; if (data != NULL) incref(data); dest->value_type = source->value_type; dest->value_data.ptr = data; INCREMENT_STAT(StringSoftCopy); }
ListData* list_duplicate(ListData* source) { if (source == NULL) return NULL; INCREMENT_STAT(ListHardCopy); assert_valid_list(source); ListData* result = allocate_empty_list(source->capacity); result->count = source->count; for (int i=0; i < source->count; i++) { INCREMENT_STAT(Copy_ListDuplicate); copy(&source->items[i], &result->items[i]); } return result; }
void make(Type* type, caValue* value) { INCREMENT_STAT(ValueCreates); set_null(value); value->value_type = type; if (type->initialize != NULL) type->initialize(type, value); type->inUse = true; }
void cast(CastResult* result, caValue* value, Type* type, bool checkOnly) { INCREMENT_STAT(ValueCast); result->success = true; // Finish early if value already has this exact type. if (value->value_type == type) { result->success = true; return; } if (type->cast != NULL) { INCREMENT_STAT(ValueCastDispatched); type->cast(result, value, type, checkOnly); return; } // Type has no 'cast' handler, and the type is not exactly the same, so fail. result->success = false; }
void list_copy(caValue* source, caValue* dest) { INCREMENT_STAT(ListSoftCopy); ca_assert(source->value_type->storageType == name_StorageTypeList); // prepare 'dest' change_type(dest, source->value_type); ListData* sourceData = (ListData*) source->value_data.ptr; if (sourceData == NULL) return; list_make_immutable(sourceData); list_incref(sourceData); dest->value_data.ptr = sourceData; }
void copy(caValue* source, caValue* dest) { INCREMENT_STAT(ValueCopies); ca_assert(source); ca_assert(dest); if (source == dest) return; Type::Copy copyFunc = source->value_type->copy; if (copyFunc != NULL) { copyFunc(source->value_type, source, dest); ca_assert(dest->value_type == source->value_type); return; } // Default behavior, shallow assign. set_null(dest); dest->value_type = source->value_type; dest->value_data = source->value_data; }
void for_loop_finish_iteration(Stack* stack, bool enableLoopOutput) { INCREMENT_STAT(LoopFinishIteration); Frame* frame = top_frame(stack); Branch* contents = frame->branch; // Find list length caValue* listInput = get_frame_register(frame, 0); // Increment the loop index caValue* index = get_top_register(stack, for_loop_find_index(contents)); set_int(index, as_int(index) + 1); // Preserve list output if (enableLoopOutput && frame->exitType != name_Discard) { caValue* outputIndex = get_frame_register(frame, for_loop_find_output_index(contents)); Term* outputPlaceholder = get_output_placeholder(contents, 0); caValue* outputList = get_frame_register(frame, outputPlaceholder); caValue* outputValue = find_stack_value_for_term(stack, outputPlaceholder->input(0), 0); if (!is_list(outputList)) set_list(outputList); list_touch(outputList); copy(outputValue, list_get(outputList, as_int(outputIndex))); INCREMENT_STAT(LoopWriteOutput); // Advance output index set_int(outputIndex, as_int(outputIndex) + 1); } // Check if we are finished if (as_int(index) >= list_length(listInput) || frame->exitType == name_Break || frame->exitType == name_Return) { // Possibly truncate output list, in case any elements were discarded. if (enableLoopOutput) { caValue* outputIndex = get_frame_register(frame, for_loop_find_output_index(contents)); Term* outputPlaceholder = get_output_placeholder(contents, 0); caValue* outputList = get_frame_register(frame, outputPlaceholder); list_resize(outputList, as_int(outputIndex)); } else { Term* outputPlaceholder = get_output_placeholder(contents, 0); caValue* outputList = get_frame_register(frame, outputPlaceholder); set_list(outputList, 0); } finish_frame(stack); return; } // If we're not finished yet, copy rebound outputs back to inputs. for (int i=1;; i++) { Term* input = get_input_placeholder(contents, i); if (input == NULL) break; Term* output = get_output_placeholder(contents, i); copy(get_frame_register(frame, output), get_frame_register(frame, input)); INCREMENT_STAT(Copy_LoopCopyRebound); } // Return to start of loop body frame->pc = 0; frame->nextPc = 0; frame->exitType = name_None; }
std::string as_string(caValue* value) { INCREMENT_STAT(StringToStd); return std::string(as_cstring(value)); }