bool _corto_delegate_compatible( corto_delegate _this, corto_type type) { static corto_uint32 _methodId; corto_method _method; bool _result; corto_interface _abstract; _abstract = corto_interface(corto_typeof(_this)); /* Determine methodId once, then cache it for subsequent calls. */ if (!_methodId) { _methodId = corto_interface_resolveMethodId(_abstract, "compatible(type type)"); } corto_assert(_methodId, "virtual 'compatible(type type)' not found in '%s'%s%s", corto_fullpath(NULL, _abstract), corto_lasterr() ? ": " : "", corto_lasterr() ? corto_lasterr() : ""); /* Lookup method-object. */ _method = corto_interface_resolveMethodById(_abstract, _methodId); corto_assert(_method != NULL, "unresolved method '%s::compatible(type type)@%d'", corto_idof(_this), _methodId); if (corto_function(_method)->kind == CORTO_PROCEDURE_CDECL) { _result = ((bool ___ (*)(corto_object, corto_type))((corto_function)_method)->fptr)(_this, type); } else { corto_call(corto_function(_method), &_result, _this, type); } return _result; }
/* Resolve dependency, decrease refcount */ static int g_itemResolveDependency(void* o, void* userData) { g_dependency dep; corto_depresolver data; dep = o; data = userData; if (!dep->processed) { switch(dep->kind) { case CORTO_DECLARED: dep->item->declareCount--; corto_assert(dep->item->declareCount >= 0, "negative declareCount for item '%s'.", corto_nameof(dep->item->o)); if (!dep->item->declareCount) { corto_llInsert(data->toPrint, dep->item); } break; case CORTO_DEFINED: dep->item->defineCount--; corto_assert(dep->item->defineCount >= 0, "negative defineCount for item '%s'.", corto_nameof(dep->item->o)); if (!dep->item->defineCount) { corto_llInsert(data->toPrint, dep->item); } break; } } dep->processed = TRUE; return 1; }
void cdiff_file_headerBegin(cdiff_file file) { corto_assert(file != NULL, "NULL specified for file"); corto_assert(file->cur != NULL, "select element before starting header"); corto_assert(file->writeTo != 2, "end body before start writing to header"); file->writeTo = 1; file->writeBuffer = CORTO_BUFFER_INIT; }
void cdiff_file_bodyEnd(cdiff_file file) { corto_assert(file != NULL, "NULL specified for file"); corto_assert(file->writeTo == 2, "not writing to body"); file->cur->body = corto_buffer_str(&file->writeBuffer); file->writeTo = 0; file->isChanged = TRUE; }
void cdiff_file_headerEnd(cdiff_file file) { corto_assert(file != NULL, "NULL specified for file"); corto_assert(file->writeTo == 1, "not writing to header"); char *header = corto_buffer_str(&file->writeBuffer); if (!file->cur->header) { file->cur->header = header; } else if (strcmp(header, file->cur->header)) { corto_ptr_setstr(&file->cur->header, header); file->isChanged = TRUE; } file->writeTo = 0; }
int16_t cdiff_file_bodyBegin(cdiff_file file) { corto_assert(file != NULL, "NULL specified for file"); corto_assert(file->cur != NULL, "select element before starting body"); corto_assert(file->writeTo != 1, "end header before start writing to body"); /* Test if body is already set */ if (file->cur->body) { return 1; } file->writeBuffer = CORTO_BUFFER_INIT; file->writeTo = 2; return 0; }
void cdiff_file_write( cdiff_file file, char *fmt, ...) { corto_assert(file != NULL, "NULL specified for file"); if (file->newLine && file->indent) { int i; for (i = 0; i < file->indent * 4; i++) { corto_buffer_appendstrn(&file->writeBuffer, " ", 1); } } va_list args; va_start(args, fmt); corto_buffer_vappend(&file->writeBuffer, fmt, args); va_end(args); /* If no element specified for writing, write to new text element. */ if (!file->cur && file->isNew) { cdiff_elem *el = corto_calloc(sizeof(cdiff_elem)); el->kind = CDIFF_TEXT; el->body = corto_buffer_str(&file->writeBuffer); if (!file->elements) { file->elements = corto_ll_new(); } corto_ll_append(file->elements, el); file->writeBuffer = CORTO_BUFFER_INIT; } file->newLine = fmt[strlen(fmt) - 1] == '\n'; }
static corto_int16 json_deserCollection(void* p, corto_type t, JSON_Value *v) { corto_assert(t->kind == CORTO_COLLECTION, "not deserializing composite"); corto_type elementType = corto_collection(t)->elementType; /* Deserialize elements */ JSON_Array* a = json_value_get_array(v); if (!a) { corto_seterr("invalid array"); goto error; } size_t count = json_array_get_count(a); size_t i; for (i = 0; i < count; i++) { void *elementPtr = json_deser_allocElem(p, corto_collection(t), i); JSON_Value *elem = json_array_get_value(a, i); if (json_deserType(elementPtr, elementType, elem)) { goto error; } } return 0; error: return -1; }
void corto_valueSetValue(corto_value* val, corto_void* v) { switch(val->kind) { case CORTO_OBJECT: val->is.object.o = v; /* Dangerous, but allowed */ break; case CORTO_BASE: val->is.base.v = v; break; case CORTO_MEMBER: val->is.member.v = v; break; case CORTO_CONSTANT: val->is.constant.v = v; break; case CORTO_ELEMENT: val->is.element.v = v; break; case CORTO_MAP_ELEMENT: val->is.mapElement.v = v; break; case CORTO_VALUE: case CORTO_MEM: val->is.value.v = v; // ?? break; default: corto_assert(0, "corto_valueSetValue: invalid valueKind %d.", val->kind); break; } }
/* Resolve cycles for dependency */ static void g_itemResolveDependencyCycles(g_dependency dep, struct corto_depresolver_s* data) { corto_uint32 sp; /* If item is already marked, there is no need to investigate it further. */ if (!dep->marked) { /* If dependency is not on stack, scan further, if on stack, a cycle is found. */ if (!(sp = g_dependencyOnStack(dep, data))) { data->stack[data->sp] = dep; data->sp++; corto_assert(data->sp < CYCLE_DEPTH, "stack-bound overflow."); /* Forward item and mark it. */ g_itemResolveCycles(dep->item, data); dep->marked = TRUE; data->sp--; /* If a cycle is found, look on the stack for a weak dependency. */ } else { corto_uint32 i; for(i=sp-1; i<data->sp; i++) { /* Break first weak dependency */ if (data->stack[i]->weak && data->stack[i]->dependency->declared) { g_itemResolveDependency(data->stack[i], data); /* This dependency is already weakened, it cannot be weakened again. */ data->stack[i]->weak = FALSE; break; } } } } }
/* Walk members, look it up */ corto_int16 ast_Initializer_findMember(corto_serializer s, corto_value* v, void* userData) { corto_uint32 result; ast_Initializer_findMember_t* data; result = 0; data = userData; switch(v->kind) { case CORTO_MEMBER: if (v->is.member.t->id == (corto_uint32)-1) { result = corto_serializeValue(s, v, userData); } else { if ((data->lookForLocation >= 0) && ((corto_uint32)data->lookForLocation == data->count)) { data->m = v->is.member.t; data->id = data->count; goto found; } else if (data->lookForString && !strcmp(data->lookForString, corto_idof(v->is.member.t))) { data->m = v->is.member.t; data->id = data->count; if (data->current >= data->count) { goto found; } } data->count++; } break; default: corto_assert(0, "invalid valueKind for member-callback."); break; } return result; found: return -1; }
corto_int16 json_deserialize(corto_value *v, corto_string s) { corto_assert(v != NULL, "NULL passed to json_deserialize"); char *json = s; if ((json[0] != '{') && (json[1] != '[') && (json[0] != '[')) { corto_asprintf(&json, "{\"value\": %s}", json); } JSON_Value *jsonValue = json_parse_string(json); if (!jsonValue) { corto_seterr("invalid JSON '%s'", json); goto error; } corto_type type = corto_value_getType(v); if (type->kind == CORTO_PRIMITIVE) { JSON_Object* jsonObj = json_value_get_object(jsonValue); if (!jsonObj) { corto_seterr("json: invalid JSON for primitive value '%s'", json); goto error; } JSON_Value *jsonValue = json_object_get_value(jsonObj, "value"); if (!jsonValue) { corto_seterr("json: missing 'value' field for primitive value '%s'", json); goto error; } } if (json_deserialize_from_JSON_Value(v, jsonValue)) { goto error; } if (json != s) { corto_dealloc(json); } return 0; error: if (json != s) { corto_dealloc(json); } if (jsonValue) { json_value_free(jsonValue); } return -1; }
corto_object md_resolve(int level, corto_string name, corto_object *parent, md_parseData* data) { corto_assert(level >= 1 && level <= 6, "Level must be between 1 and 6"); corto_object o = NULL, current = NULL; corto_object previous = NULL; if (level == 1) { previous = data->destination; } else { corto_uint32 i = level - 1; while (i && !(previous = md_Doc(data->headers[i]))) { i--; } previous = data->headers[i]; } if (previous == NULL) { goto notFound; } if (corto_instanceof(md_Doc_o, previous)) { current = md_Doc(previous)->o; } if (parent) { *parent = previous; } if (current || (level == 1)) { o = corto_resolve(current, name); if (o == NULL) { goto notFound; } if (!md_isAncestor(current, o)) { o = NULL; } } /* Clean up the lower levels of the doc hierarchy */ int i = 6; do { data->headers[i] = NULL; } while (i-- > level); return o; notFound: return NULL; }
void cdiff_file_elemBegin(cdiff_file file, char *fmt, ...) { corto_assert(file != NULL, "NULL specified for file"); if (!file->elements) { file->elements = corto_ll_new(); } cdiff_elem *el = NULL; char *id = NULL; if (fmt) { va_list args; va_start(args, fmt); corto_vasprintf(&id, fmt, args); va_end(args); el = cdiff_file_elemFind(file->elements, id); if (!el && file->legacyElements) { el = cdiff_file_elemFind(file->legacyElements, id); } } if (!el) { el = malloc (sizeof(cdiff_elem)); el->id = id; el->header = NULL; el->body = NULL; el->kind = id ? CDIFF_FUNCTION : CDIFF_TEXT; file->isChanged = true; if (!file->elements) { file->elements = corto_ll_new(); } corto_ll_append(file->elements, el); } else { free(id); } file->cur = el; file->writeTo = 0; }
corto_bool json_deserPrimitive(void* p, corto_type t, JSON_Value *v) { corto_assert(t->kind == CORTO_PRIMITIVE, "not deserializing primitive"); corto_primitive ptype = corto_primitive(t); switch (ptype->kind) { case CORTO_BOOLEAN: if (json_deserBoolean(p, ptype, v)) { goto error; } break; case CORTO_CHARACTER: break; case CORTO_INTEGER: case CORTO_UINTEGER: case CORTO_FLOAT: case CORTO_BINARY: if (json_deserNumber(p, ptype, v)) { goto error; } break; case CORTO_TEXT: if (json_deserText(p, ptype, v)) { goto error; } case CORTO_ENUM: case CORTO_BITMASK: if (json_deserConstant(p, ptype, v)) { goto error; } break; } return 0; error: return 0; }
/* Reverse list */ void corto_llReverse(corto_ll list) { corto_uint32 i, size = corto_llSize(list); corto_llNode start = list->first; corto_llNode end = list->last; corto_llNode ptr; for(i=0; i<size / 2; i++) { void *tmp = start->data; start->data = end->data; end->data = tmp; start = start->next; /* Do in-place reverse, find node that precedes 'end' */ if (start != end) { ptr = start; while(ptr && (ptr->next != end)) { ptr = ptr->next; } corto_assert(ptr != NULL, "linked list corrupt"); end = ptr; } } }
corto_int16 corto_valueExpr_getTypeForBinary( corto_type leftType, corto_bool t1ByRef, corto_type rightType, corto_bool t2ByRef, corto_operatorKind _operator, corto_type *operandType, corto_type *resultType) { corto_type castType = NULL; corto_bool equal = FALSE; corto_assert(operandType != NULL, "NULL provided for out-parameter operandType"); corto_assert(resultType != NULL, "NULL provided for out-parameter resultType"); /* If operator is condition result type is a boolean */ if (corto_valueExpr_isOperatorConditional(_operator)) { *resultType = corto_type(corto_bool_o); } /* Get leftType and rightType */ if (!(leftType = corto_valueExpr_getType(leftType, NULL, FALSE))) { goto error; } if (!(rightType = corto_valueExpr_getType(rightType, leftType, t1ByRef))) { goto error; } if (!leftType) { leftType = rightType; } /* If objects are not scoped, verify whether they're equal */ if (!corto_checkAttr(leftType, CORTO_ATTR_NAMED) && !corto_checkAttr(rightType, CORTO_ATTR_NAMED)) { if (corto_compare(leftType, rightType) == CORTO_EQ) { equal = TRUE; } } else { equal = leftType == rightType; } if (_operator == CORTO_DIV) { castType = corto_type(corto_float64_o); } else if (!equal) { /* Can only cast between primitive types */ if ((leftType->kind == CORTO_PRIMITIVE ) && (rightType->kind == CORTO_PRIMITIVE)) { corto_primitive ltype = corto_primitive(leftType), rtype = corto_primitive(rightType); corto_int8 lscore, rscore; corto_int8 lCastScore, rCastScore; lscore = corto_valueExpr_getTypeScore(ltype); rscore = corto_valueExpr_getTypeScore(rtype); lCastScore = corto_valueExpr_getCastScore(ltype); rCastScore = corto_valueExpr_getCastScore(rtype); /* If expression is an assignment, always take type of lvalue. * Otherwise determine based on expressibility score which type to * cast to. */ if (corto_valueExpr_isOperatorAssignment(_operator)) { if (lCastScore == rCastScore) { if (ltype->width != rtype->width) { castType = leftType; } } else { castType = leftType; } } else { if (lCastScore == rCastScore) { if (ltype->width == rtype->width) { /* If width and kind are equal, no conversion is required. */ if (lscore > rscore) { *operandType = leftType; } else if (lscore < rscore) { *operandType = rightType; } } else { /* If lvalue has a larger width than rvalue, cast rvalue to leftType (and vice versa) */ if (ltype->width > rtype->width) { castType = leftType; } else { castType = rightType; } } /* If kinds do not match figure a cast is potentially needed. Figure out which type to cast to */ } else { if (lscore > rscore) { castType = leftType; } else { castType = rightType; } } } } else if (leftType->reference && rightType->reference) { castType = NULL; /* Check if types are compatible */ } else if ((rightType->reference || (t2ByRef)) && !leftType->reference) { if (corto_type_castable(leftType, corto_object_o)) { castType = leftType; } } else { corto_seterr("cannot cast from '%s' to '%s'", corto_fullpath(NULL, leftType), corto_fullpath(NULL, rightType)); goto error; } } else if ((rightType->reference || (t2ByRef)) && !leftType->reference) { if (corto_type_castable(leftType, corto_object_o)) { castType = leftType; } } if (!castType) { castType = leftType; } if (castType) { *operandType = castType; } if (!*resultType) { *resultType = *operandType; } return 0; error: return -1; }
static corto_int16 json_deserComposite(void* p, corto_type t, JSON_Value *v) { corto_assert(t->kind == CORTO_COMPOSITE, "not deserializing composite"); if (json_value_get_type(v) != JSONObject) { corto_seterr("expected object, got %s", json_valueTypeToString(v)); goto error; } JSON_Object* o = json_value_get_object(v); size_t count = json_object_get_count(o); size_t i; corto_bool isUnion = corto_interface(t)->kind == CORTO_UNION; corto_int32 discriminator = 0; corto_member unionMember = NULL; for (i = 0; i < count; i++) { const char* memberName = json_object_get_name(o, i); corto_member member_o; if (!strcmp(memberName, "super")) { JSON_Value* value = json_object_get_value(o, memberName); if (json_deserItem(p, corto_type(corto_interface(t)->base), value)) { goto error; } } else if (!strcmp(memberName, "_d") && isUnion) { JSON_Value* value = json_object_get_value(o, memberName); if (json_deserPrimitive(&discriminator, corto_union(t)->discriminator, value)) { goto error; } unionMember = corto_union_findCase(t, discriminator); if (!unionMember) { corto_seterr("discriminator '%d' invalid for union '%s'", discriminator, corto_fullpath(NULL, t)); } } else { member_o = corto_interface_resolveMember(t, (char*)memberName); /* Ensure that we're not resolving members from a base type */ if (!member_o || (corto_parentof(member_o) != t)) { corto_seterr( "cannot find member '%s' in type '%s'", memberName, corto_fullpath(NULL, t)); goto error; } if (isUnion && (unionMember != member_o)) { corto_seterr( "member '%s' does not match discriminator '%d' (expected member '%s')", memberName, discriminator, corto_idof(unionMember)); goto error; } else if (isUnion) { corto_int32 prev = *(corto_int32*)p; if (prev != discriminator) { corto_member prevMember = corto_union_findCase(t, prev); corto_deinitp(CORTO_OFFSET(p, prevMember->offset), prevMember->type); memset(CORTO_OFFSET(p, member_o->offset), 0, member_o->type->size); } *(corto_int32*)p = discriminator; } if (!json_deserMustSkip(member_o, p)) { JSON_Value* value = json_object_get_value(o, memberName); void *offset = CORTO_OFFSET(p, member_o->offset); if (member_o->modifiers & CORTO_OBSERVABLE) { offset = *(void**)offset; if (json_deserType(offset, member_o->type, value)) { goto error; } } else { if (member_o->modifiers & CORTO_OPTIONAL) { if (*(void**)offset) { corto_deinitp(*(void**)offset, member_o->type); memset(*(void**)offset, 0, member_o->type->size); } else { *(void**)offset = corto_calloc(member_o->type->size); } offset = *(void**)offset; } if (json_deserItem(offset, member_o->type, value)) { goto error; } } } } } return 0; error: return -1; }
void cdiff_file_indent(cdiff_file file) { corto_assert(file != NULL, "NULL specified for file"); file->indent ++; }
void cdiff_file_dedent(cdiff_file file) { corto_assert(file != NULL, "NULL specified for file"); corto_assert(file->indent != 0, "too many dedents"); file->indent --; }
void cdiff_file_elemEnd(cdiff_file file) { corto_assert(file != NULL, "NULL specified for file"); corto_assert(file->writeTo == 0, "finish header or body before closing element"); file->cur = NULL; }