/* Do metawalk on type */ cx_int16 cx_metaWalk(cx_serializer s, cx_type type, void* userData) { cx__object* o; cx_int16 result; /* Instantiate dummy-object */ o = cx_malloc(sizeof(cx__object) + type->size); /* alloca is dangerous here because objects can get large, causing stack overflows. */ memset(o, 0, sizeof(cx__object) + type->size); o->type = cx_type(type); o->refcount = 1; result = cx_serialize(s, CX_OFFSET(o, sizeof(cx__object)), userData); cx_dealloc(o); return result; }
/* Write all parents to connection so that a reply is self-containing */ static int web_printParents(struct mg_connection *conn, cx_object o) { int result = 0; struct cx_serializer_s serializer = cx_json_ser(CX_PRIVATE, CX_NOT, CX_SERIALIZER_TRACE_NEVER); if (o) { cx_json_ser_t jsonData = {NULL, NULL, 0, 0, 0, TRUE, FALSE, FALSE, TRUE}; if (cx_parentof(o)) { result += web_printParents(conn, cx_parentof(o)); } if (result) { mg_printf_data(conn, ","); } cx_serialize(&serializer, o, &jsonData); mg_printf_data(conn, "%s\n", jsonData.buffer); cx_dealloc(jsonData.buffer); result++; } return result; }
/* Serve a Cortex object */ static int web_serveObject(struct mg_connection *conn) { cx_object o = NULL; /* Resolve object based on URI */ o = cx_resolve(NULL, (cx_string)conn->uri + 2); if (!o) { mg_send_status(conn, 404); mg_printf_data(conn, "404: resource '%s' not found\n", conn->uri); } else { char option[6]; cx_bool value = 0; cx_bool meta = 0; cx_bool scope = 0; /* Set correct content type */ mg_send_header(conn, "Content-Type", "application/json; charset=utf-8"); /* Determine what to show */ mg_get_var(conn, "value", option, sizeof(option)); if (!strcmp(option, "true")) { value = TRUE; } mg_get_var(conn, "meta", option, sizeof(option)); if (!strcmp(option, "true")) { meta = TRUE; } mg_get_var(conn, "scope", option, sizeof(option)); if (!strcmp(option, "true")) { scope = TRUE; } if (!(value || meta || scope)) { value = TRUE; } { /* Serialize object-value to JSON */ struct cx_serializer_s serializer = cx_json_ser(CX_PRIVATE, CX_NOT, CX_SERIALIZER_TRACE_NEVER); if ((cx_typeof(o)->kind == CX_VOID) && (!meta && !scope)) { mg_printf_data(conn, "\n"); } else { mg_printf_data(conn, "["); /* Serialize metadata of parents */ if (meta) { if (web_printParents(conn, cx_parentof(o))) { mg_printf_data(conn, ","); } } /* Serialize value */ { cx_json_ser_t jsonData = {NULL, NULL, 0, 0, 0, meta, value, scope, TRUE}; cx_serialize(&serializer, o, &jsonData); mg_printf_data(conn, "%s", jsonData.buffer); cx_dealloc(jsonData.buffer); } mg_printf_data(conn, "]\n"); } } cx_free(o); } return MG_TRUE; }
/* Build dependency-administration for object */ int cx_genDepBuildAction(cx_object o, void* userData) { g_itemWalk_t data; struct g_depWalk_t walkData; struct cx_serializer_s s; int result; cx_object parent = NULL; if (cx_checkAttr(o, CX_ATTR_SCOPED)) { parent = cx_parentof(o); } data = userData; /* If object is cortex_lang_o, signal that a bootstrap is found, indicating * that dependencies should be disregarded. */ if (o == cortex_lang_o) { data->bootstrap = TRUE; result = 0; } else { /* Insert type-dependency: object can be declared only after it's type is defined. */ if (g_mustParse(data->g, cx_typeof(o))) { cx_depresolver_depend(data->resolver, o, CX_DECLARED, cx_typeof(o), CX_DEFINED); } /* TODO: this is not nice */ if (cx_class_instanceof(cx_procedure_o, cx_typeof(o))) { /* Insert base-dependency: methods may only be declared after the base of a class has been defined. */ if (cx_typeof(o) != cx_type(cx_function_o)) { if (cx_class_instanceof(cx_class_o, parent) && cx_interface(parent)->base) { if (g_mustParse(data->g, cx_interface(parent)->base)) { cx_depresolver_depend(data->resolver, o, CX_DECLARED, cx_interface(parent)->base, CX_DEFINED); } } } /* Add dependencies on function parameters - types must be declared before function is declared. */ if (cx_genDepBuildProc(cx_function(o), data)) { goto error; } } /* Insert dependency on parent */ if (cx_checkAttr(o, CX_ATTR_SCOPED)) { if (parent != root_o) { /* Root is always available */ cx_int8 parentState = cx_type(cx_typeof(o))->parentState; cx_depresolver_depend(data->resolver, o, CX_DECLARED, parent, parentState); if (parentState == CX_DECLARED) { cx_depresolver_depend(data->resolver, parent, CX_DEFINED, o, CX_DEFINED); } } } /* Insert dependencies on references in the object-value */ walkData.o = o; walkData.data = data; s = cx_genDepSerializer(); if (cx_serialize(&s, o, &walkData)) { goto error; } result = 1; } return result; error: return 0; }
/* Decrease references */ static void cx_decreaseRef(cx_object o) { struct cx_serializer_s s; s = cx_ser_free(CX_LOCAL, CX_NOT, CX_SERIALIZER_TRACE_ON_FAIL); cx_serialize(&s, o, NULL); }
/* Update references */ static void cx_updateRef(cx_object o) { struct cx_serializer_s s; s = cx_ser_keep(CX_LOCAL, CX_NOT, CX_SERIALIZER_TRACE_ON_FAIL); cx_serialize(&s, o, NULL); }