static int corto_selectParse(corto_selectData *data) { char *ptr, *start, ch; int op = 0; ptr = data->expr; for (; (ch = *ptr); data->program[op].start = ptr, ptr++) { start = ptr; switch(ch) { case '.': if (ptr[1] == '.') { data->program[op].token = TOKEN_PARENT; ptr++; } else { data->program[op].token = TOKEN_TREE; } break; case ':': if (ptr[1] == ':') { data->program[op].token = TOKEN_SCOPE; ptr++; } else { corto_seterr("invalid usage of ':'"); goto error; } break; default: while((ch = *ptr++) && (isalnum(ch) || (ch == '*') || (ch == '?'))) {} ptr--; /* Go back one character to adjust for lookahead of one */ int len = ptr - start; if (len) { if (len == 1) { if (*(ptr - 1) == '?') { data->program[op].token = TOKEN_WILDCARD; } else if (*(ptr - 1) == '*') { data->program[op].token = TOKEN_ASTERISK; } else { data->program[op].token = TOKEN_IDENTIFIER; } } else { data->program[op].token = TOKEN_IDENTIFIER; } } else { corto_seterr("invalid character '%c", ch); goto error; } break; } data->program[op].start = start; if (++op == CORTO_SELECT_MAX_OP) { corto_seterr("expression is too long"); goto error; } } data->programSize = op; return 0; error: return -1; }
corto_int16 corto_ptr_binaryOp(corto_type type, corto_operatorKind operator, void *operand1, void *operand2, void *result) { if (type->kind == CORTO_PRIMITIVE) { corto__binaryOperator impl = corto_binaryOps[corto_primitive(type)->convertId][operator]; if (impl) { impl(operand1, operand2, result); } else { corto_seterr("binary operator '%s' is not implemented for type '%s'", corto_idof(corto_enum_constant(corto_operatorKind_o, operator)), corto_fullpath(NULL, type)); goto error; } } else if (operator == CORTO_ASSIGN) { corto_ptr_copy(operand1, type, operand2); if (result && result != operand1) { corto_ptr_copy(result, type, operand1); } } else { corto_seterr("invalid operand for non-scalar type"); goto error; } return 0; error: return -1; }
corto_int16 json_deserReference(void* p, corto_type t, JSON_Value* v) { switch(json_value_get_type(v)) { case JSONString: { const char* reference = json_value_get_string(v); corto_object o = corto_resolve(NULL, (corto_string)reference); if (!o) { corto_error("unresolved reference \"%s\"", reference); goto error; } if (!corto_instanceof(t, o)) { corto_error("%s is not an instance of %s", reference, corto_idof(t)); } corto_setref(p, o); corto_release(o); break; } case JSONObject: { JSON_Object* obj = json_value_get_object(v); JSON_Value* type = json_object_get_value(obj, "type"); if (json_value_get_type(type) != JSONString) { corto_seterr("type parameter of anonymous object must be a string"); goto error; } corto_type cortoType = corto_resolve(NULL, (char*)json_value_get_string(type)); if (!cortoType) { corto_seterr("type '%s' not found for anonymous object", json_value_get_string(type)); goto error; } corto_object cortoObj = *(corto_object*)p; if (!cortoObj || (corto_typeof(cortoObj) != cortoType)) { cortoObj = corto_create(cortoType); corto_setref(p, cortoObj); corto_release(cortoObj); } corto_release(cortoType); JSON_Value* value = json_object_get_value(obj, "value"); if (json_deserType(cortoObj, cortoType, value)) { goto error; } break; } case JSONNull: corto_setref(p, NULL); break; default: corto_seterr("expected string, null or object (reference), got %s", json_valueTypeToString(v)); break; } return 0; error: return -1; }
/* Run a command for multiple projects */ corto_int16 cortotool_runcmd( corto_ll dirs, char *argv[], corto_bool silent, corto_bool mute) { corto_iter iter; corto_id cwd; corto_int8 ret = 0; strcpy(cwd, corto_cwd()); if (dirs) { iter = corto_llIter(dirs); } do { corto_pid pid = 0; corto_int32 sig = 0; if (dirs) { corto_string dir = corto_iterNext(&iter); /* Change working directory to project */ if (corto_chdir(dir)) { goto error; } } if (mute) { pid = corto_procrunRedirect(argv[0], argv, stdin, NULL, NULL); } else if (silent) { pid = corto_procrunRedirect(argv[0], argv, stdin, NULL, stderr); } else { pid = corto_procrun(argv[0], argv); } if (!pid) { corto_seterr("failed to start process %s", argv[0]); goto error; } if ((sig = corto_procwait(pid, &ret)) || ret) { corto_seterr("%s failed (%s %d)", argv[0], sig ? "signal" : "returncode", sig ? sig : ret); goto error; } /* Reset to previous CWD if there is more than one project to build */ corto_chdir(cwd); } while (dirs && corto_iterHasNext(&iter)); return 0; error: return -1; }
corto_int16 corto_value_memberExpr(corto_value *val, corto_string member, corto_value *out) { corto_type t = corto_value_typeof(val); corto_object o = corto_value_objectof(val); void *ptr = corto_value_ptrof(val); corto_id tokens; strncpy(tokens, member, sizeof(corto_id)); char *cur = tokens, *prev = tokens; do { if (cur && (cur = strchr(cur + 1, '.'))) *cur = '\0'; if (!corto_instanceof(corto_interface_o, t)) { corto_seterr( "cannot get member from a non-composite value (type is '%s')", corto_fullpath(NULL, t)); goto error; } if (!strcmp(prev, "super")) { if (!(t = (corto_type)corto_interface(t)->base)) { corto_seterr("super unpexpected: interface '%s' does not have a base", corto_fullpath(NULL, t)); goto error; } else { *out = corto_value_base(ptr, t); } } else { corto_member m = corto_interface_resolveMember(t, prev); if (!m) { corto_seterr( "unresolved member '%s' in type '%s'", prev, corto_fullpath(NULL, t)); goto error; } ptr = CORTO_OFFSET(ptr, m->offset); t = m->type; *out = corto_value_member(o, m, ptr); } prev = cur + 1; } while (cur); return 0; error: 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_int16 corto_value_ptrset(corto_value *val, void *ptr) { switch(val->kind) { case CORTO_OBJECT: val->is.object.o = ptr; break; case CORTO_BASE: val->is.base.v = ptr; break; case CORTO_VALUE: case CORTO_MEM: val->is.value.v = ptr; break; case CORTO_MEMBER: val->is.member.v = ptr; break; case CORTO_CONSTANT: val->is.constant.v = ptr; break; case CORTO_ELEMENT: val->is.element.v = ptr; break; case CORTO_MAP_ELEMENT: val->is.mapElement.v = ptr; break; case CORTO_LITERAL: corto_seterr("cannot set pointer for literal"); goto error; default: corto_critical("corto_value_ptrset: invalid corto_valueKind(%d).", val->kind); break; } return 0; error: return -1; }
static corto_int16 json_deserType(void *p, corto_type t, JSON_Value *v) { switch (t->kind) { case CORTO_VOID: /* Nothing to deserialize */ break; case CORTO_PRIMITIVE: if (json_deserPrimitive(p, t, v)) { goto error; } break; case CORTO_COMPOSITE: if (json_deserComposite(p, t, v)) { goto error; } break; case CORTO_COLLECTION: if (json_deserCollection(p, t, v)) { goto error; } break; default: corto_seterr( "unsupported type, can't serialize JSON"); break; } return 0; error: return -1; }
static corto_type corto_valueExpr_getType(corto_type src, corto_type target, corto_bool targetIsRef) { corto_type result = src; if (!src) { if (target) { if (target->reference) { result = target; } else if ((target->kind == CORTO_PRIMITIVE) && (corto_primitive(target)->kind == CORTO_TEXT)) { result = corto_type(corto_string_o); } else { if (targetIsRef) { result = target; } else { corto_seterr( "invalid usage of null with non-string and non-reference type '%s'", corto_fullpath(NULL, target)); goto error; } } } else { result = corto_void_o; } } else if ((target && (target->kind == CORTO_VOID) && target->reference)) { result = corto_object_o; } return result; error: return NULL; }
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* _dDDS_getEntity(corto_object o, corto_type type) { void* result = NULL; if (o && corto_instanceof(type, o)) { result = corto_olsGet(o, DDDS_ENTITY_HANDLE); if (!result) { corto_seterr("%s contains an invalid handle", corto_fullpath(NULL, o)); } } else { corto_seterr("%s is not of type %s", corto_fullpath(NULL, o), corto_fullpath(NULL, type)); } return result; }
static corto_dl corto_load_validLibrary(corto_string fileName, corto_string *build_out) { corto_dl result = NULL; corto_string ___ (*build)(void); corto_string ___ (*library)(void); if (build_out) { *build_out = NULL; } if (!(result = corto_dlOpen(fileName))) { corto_seterr("%s", corto_dlError()); goto error; } /* Lookup build function */ build = (corto_string ___ (*)(void))corto_dlProc(result, "corto_getBuild"); library = (corto_string ___ (*)(void))corto_dlProc(result, "corto_getLibrary"); /* Validate version */ if (build && strcmp(build(), corto_getBuild())) { corto_seterr( "corto: library '%s' links with conflicting corto library\n" " links with: '%s' (%s)\n" " current: '%s' (%s)\n", fileName, library ? library() : "???", build(), corto_getLibrary(), corto_getBuild()); /* Library is linked with different Corto version */ if (build_out) { *build_out = corto_strdup(build()); } goto error; } else if (build) { corto_debug( "loader: '%s' links with correct corto library\n build: '%s'\n library: '%s'\n", fileName, build(), library()); } else { corto_trace("loader: found '%s' which doesn't link with corto", fileName); } /* If no build function is available, the library is not linked with * Corto, and probably represents a --nocorto package */ return result; error: if (result) corto_dlClose(result); return NULL; }
static int corto_selectValidate(corto_selectData *data) { int op; corto_selectToken t, tprev = TOKEN_NONE; for (op = 0; op < data->programSize; op++) { t = data->program[op].token; switch(t) { case TOKEN_IDENTIFIER: switch(tprev) { case TOKEN_IDENTIFIER: case TOKEN_ASTERISK: case TOKEN_WILDCARD: case TOKEN_PARENT: goto error; default: break; } break; case TOKEN_SCOPE: switch(tprev) { case TOKEN_SCOPE: goto error; default: break; } break; case TOKEN_TREE: case TOKEN_PARENT: switch(tprev) { case TOKEN_TREE: case TOKEN_PARENT: goto error; default: break; } break; case TOKEN_WILDCARD: case TOKEN_ASTERISK: switch(tprev) { case TOKEN_IDENTIFIER: case TOKEN_PARENT: case TOKEN_ASTERISK: case TOKEN_WILDCARD: goto error; default: break; } break; default: break; } tprev = t; } return 0; error: corto_seterr("unexpected '%s' after '%s'", corto_selectTokenStr(t), corto_selectTokenStr(tprev)); return -1; }
/* Load from a dynamic library */ static int corto_load_fromDl(corto_dl dl, char *fileName, int argc, char *argv[]) { int (*proc)(int argc, char* argv[]); corto_debug("loader: invoke cortomain of '%s' with %d arguments", fileName, argc); /* Lookup main function */ proc = (int(*)(int,char*[]))corto_dlProc(dl, "cortomain"); if (proc) { /* Call main */ if (proc(argc, argv)) { if (!corto_lasterr()) { corto_seterr("cortomain failed"); } goto error; } } else { corto_string ___ (*build)(void); /* Lookup build function */ build = (corto_string ___ (*)(void))corto_dlProc(dl, "corto_getBuild"); if (build) { corto_seterr("library '%s' linked with corto but does not have a cortomain", fileName); goto error; } } /* Add library to libraries list */ corto_mutexLock (&corto_adminLock); if (!libraries) { libraries = corto_ll_new(); } corto_ll_insert(libraries, dl); corto_mutexUnlock (&corto_adminLock); corto_debug("loader: loaded '%s'", fileName); return 0; error: return -1; }
corto_int16 corto_secure_registerLock(corto_secure_lock lock) { if (corto_secure_mainThread == corto_threadSelf()) { corto_int16 depth = corto_secure_getObjectDepth(lock->mount); if (depth >= CORTO_MAX_SCOPE_DEPTH) { corto_seterr("invalid identifier for mount-member of lock"); goto error; } if (!corto_secure_locks[depth]) { corto_secure_locks[depth] = corto_ll_new(); } corto_ll_append(corto_secure_locks[depth], lock); } else { corto_seterr("locks can only be created in mainthread"); goto error; } return 0; error: return -1; }
corto_function corto_valueFunction(corto_value* val) { corto_function result; switch(val->kind) { case CORTO_OBJECT: if (corto_class_instanceof(corto_procedure_o, corto_typeof(val->is.object.o))) { result = val->is.object.o; } else { corto_seterr("object '%s' in value is not a function", corto_fullpath(NULL, val->is.object.o)); result = NULL; } break; default: corto_seterr("value does not represent a function"); result = NULL; break; } return result; }
corto_int16 corto_select(corto_object scope, corto_string expr, corto_iter *iter_out) { corto_selectData *data = corto_selectDataGet(); CORTO_UNUSED(scope); strcpy(data->expr, expr); iter_out->hasNext = corto_selectHasNext; iter_out->next = corto_selectNext; if (corto_selectParse(data)) { corto_seterr("select '%s' failed: %s", expr, corto_lasterr()); goto error; } if (corto_selectValidate(data)) { corto_seterr("select '%s' failed: %s", expr, corto_lasterr()); goto error; } return 0; error: return -1; }
/* * Load a Corto library * Receives the absolute path to the lib<name>.so file. */ static int corto_loadLibrary(corto_string fileName, corto_bool validated, corto_dl *dl_out, int argc, char* argv[]) { corto_dl dl = NULL; corto_string build = NULL; corto_seterr(NULL); if (!validated) { dl = corto_load_validLibrary(fileName, &build); } else { dl = corto_dlOpen(fileName); } if (!dl) { if (build) { corto_seterr("%s: uses a different corto build (%s)", fileName, build); } else { if (corto_lasterr()) { corto_seterr("%s", corto_lasterr()); } else { corto_seterr("%s: %s", fileName, corto_dlError()); } } goto error; } if (corto_load_fromDl(dl, fileName, argc, argv)) { goto error; } if (dl_out) { *dl_out = dl; } return 0; error: if (dl) corto_dlClose(dl); return -1; }
static corto_int16 json_deserBoolean(void* o, corto_primitive t, JSON_Value *v) { CORTO_UNUSED(t); if (json_value_get_type(v) != JSONBoolean) { corto_seterr("expected boolean, got %s", json_valueTypeToString(v)); goto error; } *(corto_bool *)o = json_value_get_boolean(v); return 0; error: return -1; }
corto_int16 corto_value_fromcontent(corto_value *v, corto_string contentType, corto_string content) { corto_contentType ct = corto_loadContentType(contentType); if (!ct) { corto_seterr("unknown contentType '%s'", contentType); goto error; } if (ct->toValue(v, (corto_word)content)) { goto error; } return 0; error: return -1; }
static corto_int16 json_deserText(void* p, corto_primitive t, JSON_Value *v) { const char *s = json_value_get_string(v); CORTO_UNUSED(t); if (json_value_get_type(v) != JSONString) { corto_seterr("expected string, got %s", json_valueTypeToString(v)); goto error; } corto_setstr(p, (corto_string)s); return 0; error: return -1; }
corto_string corto_value_contentof(corto_value *v, corto_string contentType) { corto_contentType ct = corto_loadContentType(contentType); corto_string result; if (!ct) { corto_seterr("unknown contentType '%s'", contentType); goto error; } if (!(result = (corto_string)ct->fromValue(v))) { goto error; } return result; error: return NULL; }
corto_int16 corto_binaryOperator(corto_type type, corto_operatorKind operator, void *operand1, void *operand2, void *result) { if (type->kind == CORTO_PRIMITIVE) { corto__binaryOperator impl = corto_binaryOps[corto_primitive(type)->convertId][operator]; if (impl) { impl(operand1, operand2, result); } else { corto_seterr("binary operator '%s' is not implemented for type '%s'", corto_idof(corto_enum_constant(corto_operatorKind_o, operator)), corto_fullpath(NULL, type)); goto error; } } return 0; error: return -1; }
static corto_int16 json_deserConstant(void* p, corto_primitive t, JSON_Value *v) { const char *s = json_value_get_string(v); CORTO_UNUSED(t); if (json_value_get_type(v) != JSONString) { corto_seterr("expected string, got %s", json_valueTypeToString(v)); goto error; } if (corto_convert(corto_string_o, (corto_string*)&s, t, p)) { goto error; } return 0; error: return -1; }
static corto_int16 json_deserNumber(void* o, corto_primitive t, JSON_Value *v) { if (json_value_get_type(v) != JSONNumber) { corto_seterr("expected number, got %s", json_valueTypeToString(v)); goto error; } corto_float64 number = json_value_get_number(v); corto_convert( corto_primitive(corto_float64_o), &number, t, o); return 0; error: return -1; }
int tc_lookupAllWalk(corto_object o, void *ctx) { CORTO_UNUSED(ctx); corto_id id; corto_object r; corto_path(id, NULL, o, "/"); r = corto_lookup(NULL, id); /* Set errormessage to ease debugging */ if (!r) corto_seterr("failed to lookup %s", id); test_assert(r != NULL); test_assert(r == o); corto_release(r); corto_objectseq scope = corto_scopeClaim(o); int i; for (i = 0; i < scope.length; i ++) { tc_lookupAllWalk(scope.buffer[i], NULL); } corto_scopeRelease(scope); return 1; }
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; }
/* Deserialize string in object */ corto_string corto_string_deser(corto_string str, corto_string_deser_t* data) { corto_char *ptr; corto_bool createdNew = FALSE; { corto_id buffer; corto_char *bptr, ch; /* Parse typename that potentially precedes string */ bptr = buffer; ptr = str; while((ch = *ptr) && (ch != '{')) { if (!((ch == ' ') || (ch == '\n') || (ch == '\t'))) { *bptr = ch; bptr++; } ptr++; } *bptr = '\0'; /* If no type is found, reset ptr */ if ((ch != '{') || (ptr == str)) { ptr = str; } else { corto_object type; /* If no out is provided create an object of the specified type */ if ((bptr != buffer)) { type = corto_resolve(NULL, buffer); if (type) { if (data->type && (type != data->type)) { corto_seterr( "type of object ('%s') does not match string ('%s')", corto_fullpath(NULL, data->type), corto_fullpath(NULL, type)); corto_release(type); goto error; } if (corto_instanceof(corto_type(corto_type_o), type)) { if (!data->out) { data->out = corto_declare(type); createdNew = TRUE; } data->type = type; } else { corto_seterr("'%s' is not a type", buffer); corto_release(type); goto error; } corto_release(type); } else { corto_seterr("unknown type '%s'", buffer); goto error; } } else { type = data->type; } if (type && (corto_type(type)->kind == CORTO_PRIMITIVE)) { ptr++; } } } data->current = 0; data->index = NULL; data->ptr = data->out; data->anonymousObjects = NULL; data->allocValue = NULL; data->allocUdata = NULL; if (data->out && data->isObject) { if (!data->type) { data->type = corto_typeof(data->out); } else if (!corto_instanceofType(corto_typeof(data->out), data->type)) { corto_seterr("object '%s' of type '%s' is not an instance of type '%s'", corto_fullpath(NULL, data->out), corto_fullpath(NULL, corto_typeof(data->out)), corto_fullpath(NULL, data->type)); goto error; } } if (!data->type) { corto_seterr("no type provided for '%s'", str); goto error; } if (data->type->kind == CORTO_PRIMITIVE) { ptr = corto_string_deserParse(ptr, NULL, data); } else { ptr = corto_string_deserParseScope(ptr, NULL, data); if (ptr) { ptr ++; } } if (!ptr) { if (!corto_lasterr()) { corto_seterr("failed to deserialize '%s'", str); } else { corto_seterr("failed to deserialize '%s': %s", str, corto_lasterr()); } goto error; } if (data->anonymousObjects) { corto_ll_free(data->anonymousObjects); } return ptr; error: if (data->out) { if (createdNew) { corto_release(data->out); } data->out = NULL; } return NULL; }
/* Parse string */ static corto_string corto_string_deserParse( corto_string str, struct corto_string_deserIndexInfo* info, corto_string_deser_t* data) { corto_char ch; corto_char *ptr, *bptr, *nonWs; corto_char buffer[CORTO_STRING_DESER_TOKEN_MAX]; /* TODO: dangerous in a recursive function */ corto_bool proceed, excess; struct corto_string_deserIndexInfo* memberInfo; CORTO_UNUSED(info); ptr = str; bptr = buffer; nonWs = bptr; proceed = TRUE; excess = FALSE; memberInfo = NULL; if (info) { memberInfo = corto_string_deserIndexNext(data); } /* If ptr == NULL, an error has occurred. If proceed == FALSE, this function * has finished processing the current value. */ while(ptr && (ch = *ptr) && proceed) { switch(ch) { case '=': /* Explicit member assignment */ excess = FALSE; if (buffer == bptr) { corto_seterr("missing member identifier"); goto error; } else { *nonWs = '\0'; memberInfo = corto_string_deserIndexLookup(buffer, data); bptr = buffer; nonWs = bptr; if (!memberInfo) { corto_seterr("member '%s' not found in type '%s'", buffer, corto_fullpath(NULL, data->type)); goto error; } break; } case '{': /* Scope open */ if (bptr == buffer) { if (!(ptr = corto_string_deserParseScope( ptr, memberInfo, data))) { goto error; } } else { *bptr = '\0'; if (!(ptr = corto_string_parseAnonymous( ptr, buffer, memberInfo, data))) { goto error; } bptr = buffer; } break; case '}': /* Scope close and end of value */ if (buffer != bptr) { *nonWs = '\0'; if (memberInfo && (data->type->kind != CORTO_PRIMITIVE)) { if (corto_string_deserParseValue(buffer, memberInfo, data)) { goto error; } bptr = buffer; nonWs = bptr; } } proceed = FALSE; ptr--; break; case '(': /* If a value is being parsed, the '(' is part of an argument list. * Parse up until the matching ')' */ if (bptr != buffer) { char *start = ptr; /* Parse until matching '} */ do { *bptr = ch; bptr++; ptr++; } while((ch = *ptr) && (ch == ')')); ptr--; nonWs = bptr; /* ptr must always end with a '}' */ if (*ptr != ')') { corto_seterr("missing ')' at '%s' (%s)", start, ptr); goto error; } } case '"': if (!(ptr = corto_string_deserParseString(ptr, buffer, &bptr))) { goto error; } nonWs = bptr; ptr--; break; case '\'': if (!(ptr = corto_string_deserParseCharacter(ptr+1, buffer))) { goto error; } *(++bptr) = '\0'; nonWs = bptr; break; case '\n': case '\t': case ' ': if (bptr != buffer) { *bptr = ch; bptr++; } break; case ',': /* End of value */ if (buffer != bptr) { *nonWs = '\0'; if (corto_string_deserParseValue(buffer, memberInfo ? memberInfo : info, data)) { goto error; } bptr = buffer; nonWs = bptr; } /* If memberInfo contains a member, get next member, otherwise it contains * an element. The same information applies to each element therefore it is only present * once in the index. */ if (memberInfo) { if (memberInfo->m) { memberInfo = corto_string_deserIndexNext(data); if (!memberInfo) { excess = TRUE; } } data->current++; } else { /* A comma without memberInfo means that a discriminator of a * union was parsed */ proceed = FALSE; } break; default: *bptr = ch; bptr++; nonWs = bptr; break; } if (ptr && *ptr) ptr++; } if (bptr != buffer) { struct corto_string_deserIndexInfo info; *nonWs = '\0'; info.type = data->type; info.parsed = FALSE; info.m = NULL; if (corto_string_deserParseValue(buffer, &info, data)) { goto error; } } if (excess) { corto_seterr("excess elements in string"); goto error; } return ptr; error: return NULL; }
static corto_string corto_string_parseAnonymous( corto_string str, corto_string value, struct corto_string_deserIndexInfo *info, corto_string_deser_t *data) { corto_object o = NULL; char *ptr = str; char *valuePtr = value; corto_uint32 index = 0; void *offset; if (corto_string_getDestinationPtr(info, data, &offset)) { corto_seterr("%s: %s", str, corto_lasterr()); goto error; } /* Check if this is a 'named' anonymous object in which case it is * prefixed with <[id]> */ if ((valuePtr = corto_string_deserParseAnonymousId(valuePtr, &index))) { if (data->anonymousObjects && (index <= corto_ll_size(data->anonymousObjects))) { if (!*valuePtr) { o = corto_ll_get(data->anonymousObjects, index - 1); corto_claim(o); } else { /* If the <n> is followed up with more data, a new anonymous * object is being created while one existed already with the * specified number */ corto_seterr("identifier <%d> is already defined (%s)", index, value); goto error; } } } else { valuePtr = value; } /* If no object has been referenced, create an anonymous object */ if (!o && *valuePtr) { corto_object type = corto_resolve(NULL, valuePtr); if (!type) { corto_seterr("unresolved type '%s'", valuePtr); goto error; } if (offset) { o = *(corto_object*)offset; if (!o || (type != corto_typeof(o))) { if (!corto_instanceof(corto_type_o, type)) { corto_seterr("'%s' is not a type", corto_fullpath(NULL, type)); goto error; } o = corto_declare(type); if (!o) { corto_seterr("failed to declare %s: %s", value, corto_lasterr()); goto error; } } else { corto_claim(o); } } corto_string_deser_t privateData = { .out = data->out, // Preserve original out to determine ownership .ptr = o, .type = type, .anonymousObjects = data->anonymousObjects, .scope = data->scope, .isObject = data->isObject }; if (corto_type(type)->kind == CORTO_PRIMITIVE) { ptr ++; if (!(ptr = corto_string_deserParse(ptr, NULL, &privateData))) { goto error; } } else { if (!(ptr = corto_string_deserParseScope(ptr, NULL, &privateData))) { goto error; } } if (o) { if (corto_define(o)) { goto error; } data->anonymousObjects = privateData.anonymousObjects; if (!data->anonymousObjects) { data->anonymousObjects = corto_ll_new(); } corto_ll_append(data->anonymousObjects, o); } } if (offset) corto_ptr_setref(offset, o); if (o) corto_release(o); return ptr; error: if (o) corto_release(o); return NULL; }