char* corto_value_exprStr(corto_value* v, char* buffer, unsigned int length) { corto_member m; corto_value* parents[CORTO_MAX_INHERITANCE_DEPTH]; corto_int32 parentCount, i; corto_value* vptr; *buffer = '\0'; /* Collect parents */ parentCount = 0; vptr = v; do{ if (vptr->kind != CORTO_OBJECT) { parents[parentCount] = vptr; parentCount++; } }while((vptr = vptr->parent)); /* Put name of member or branch in buffer */ for(i=parentCount-1; i>=0; i--) { vptr = parents[i]; m = NULL; switch(vptr->kind) { case CORTO_LITERAL: case CORTO_VALUE: case CORTO_MEM: break; case CORTO_BASE: break; case CORTO_MEMBER: m = vptr->is.member.t; break; case CORTO_ELEMENT: sprintf(buffer, "%s[%d]", buffer, vptr->is.element.t.index); m = NULL; break; default: corto_trace("corto_value_exprStr: unhandled '%s'", corto_valueKindString[vptr->kind]); m = NULL; goto error; } if (m) { if ((strlen(buffer) + strlen(corto_idof(m)) + 1) >= length) { corto_error("buffer passed to corto_strving is too short for member name"); } else { strcat(buffer, "."); strcat(buffer, corto_idof(m)); } } } return buffer; error: return NULL; }
corto_void _test_compositeApi_tc_define( test_compositeApi _this) { /* $begin(test/compositeApi/tc_define) */ corto_int16 result; test_compositeType *o = test_compositeTypeDeclareChild(root_o, "o"); test_assert(o != NULL); test_assert(corto_typeof(o) == corto_type(test_compositeType_o)); test_assert(!corto_checkState(o, CORTO_DEFINED)); test_assert(corto_checkAttr(o, CORTO_ATTR_SCOPED)); test_assert(corto_parentof(o) == root_o); test_assert(!strcmp(corto_idof(o), "o")); test_assert(o->x == 1); test_assert(o->y == 2); result = test_compositeTypeDefine(o, 10, 20); test_assert(result == 0); test_assert(corto_checkState(o, CORTO_DEFINED)); test_assert(o->x == 10); test_assert(o->y == 20); test_assert(!corto_delete(o)); /* $end */ }
/* 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; }
bool _corto_collection_castable( corto_collection _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, "castable(type type)"); } corto_assert(_methodId, "virtual 'castable(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::castable(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; }
/* Lookup index */ static struct corto_string_deserIndexInfo* corto_string_deserIndexLookup( corto_string member, corto_string_deser_t* data) { corto_iter iter; struct corto_string_deserIndexInfo* info; corto_bool found; info = NULL; found = FALSE; if (data->index) { iter = corto_ll_iter(data->index); /* Lookup member in index */ while(corto_iter_hasNext(&iter)) { info = corto_iter_next(&iter); /* Ambiguous members must always be referenced from their own scope. * Even if the current scope does not have a member with the * specified name, implicit referencing is not allowed. */ if (!strcmp(corto_idof(info->m), member) && (!info->parsed)) { found = TRUE; data->iterData = *(corto_ll_iter_s*)iter.ctx; data->currentIter = iter; data->currentIter.ctx = &data->iterData; break; } } if (!found) info = NULL; } return info; }
corto_void _test_compositeUnionApi_tc_defineDefault( test_compositeUnionApi _this) { /* $begin(test/compositeUnionApi/tc_defineDefault) */ corto_int16 result; test_compositeUnionType *o = test_compositeUnionTypeDeclareChild(root_o, "o"); test_assert(o != NULL); test_assert(corto_typeof(o) == corto_type(test_compositeUnionType_o)); test_assert(!corto_checkState(o, CORTO_DEFINED)); test_assert(corto_checkAttr(o, CORTO_ATTR_SCOPED)); test_assert(corto_parentof(o) == root_o); test_assert(!strcmp(corto_idof(o), "o")); test_assert(o->d == 2); test_assertstr(o->is.str, "foo"); result = test_compositeUnionTypeDefine_other(o, 4, 10); test_assert(result == 0); test_assert(corto_checkState(o, CORTO_DEFINED)); test_assert(o->d == 4); test_assert(o->is.other == 10); test_assert(!corto_delete(o)); /* $end */ }
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; }
static corto_int16 cpp_fluent_visitMember(corto_serializer s, corto_value *info, void *userData) { cpp_classWalk_t *data = userData; corto_type t = corto_value_getType(info); corto_member m = info->is.member.t; corto_id id, cId; cpp_typeId(data->g, t, Cpp_Return, Cpp_ByVal, id); cpp_typeId(data->g, corto_parentof(m), Cpp_Return, Cpp_ByCRef, cId); /* Write implementation */ g_fileWrite(data->header, "T& %s(%s value)", corto_idof(m), id); g_fileWrite(data->header, "{ ((%s)this->m_ptr)->%s = value; return this->m_this; }\n", cId, corto_idof(m)); return 0; }
corto_bool json_deserMustSkip(corto_member m, void *ptr) { if (corto_instanceof(corto_target_o, corto_parentof(m))) { corto_bool owned = corto_owned(ptr); corto_bool isActual = !strcmp("actual", corto_idof(m)); if ((owned && !isActual) || (!owned && isActual)) { return TRUE; } } return FALSE; }
corto_void _test_voidReferenceApi_tc_createChildAuto( test_voidReferenceApi _this) { /* $begin(test/voidReferenceApi/tc_createChildAuto) */ test_voidReferenceTypeCreateChild_auto(root_o, o); test_assert(o != NULL); test_assert(corto_typeof(o) == test_voidReferenceType_o); test_assert(corto_checkState(o, CORTO_DEFINED)); test_assert(corto_checkAttr(o, CORTO_ATTR_SCOPED)); test_assert(corto_parentof(o) == root_o); test_assert(!strcmp(corto_idof(o), "o")); test_assert(!corto_delete(o)); /* $end */ }
corto_void _test_OptionalStringApi_tc_createChildNotSet( test_OptionalStringApi _this) { /* $begin(test/OptionalStringApi/tc_createChildNotSet) */ test_OptionalString *o = test_OptionalStringCreateChild( root_o, "a", NotSet, "Bar"); test_assert(o != NULL); test_assert(corto_checkAttr(o, CORTO_ATTR_SCOPED)); test_assertstr(corto_idof(o), "a"); test_assert(corto_parentof(o) == root_o); test_assert(o->a == NULL); test_assertstr(o->b, "Bar"); /* $end */ }
corto_void _test_OptionalStringApi_tc_declareChild( test_OptionalStringApi _this) { /* $begin(test/OptionalStringApi/tc_declareChild) */ test_OptionalString *o = test_OptionalStringDeclareChild(root_o, "a"); test_assert(o != NULL); test_assert(!corto_checkState(o, CORTO_DEFINED)); test_assert(corto_checkAttr(o, CORTO_ATTR_SCOPED)); test_assertstr(corto_idof(o), "a"); test_assert(corto_parentof(o) == root_o); test_assert(o->a == NULL); test_assert(o->b == NULL); /* $end */ }
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; }
corto_void _test_compositeUnionApi_tc_declareChildAuto( test_compositeUnionApi _this) { /* $begin(test/compositeUnionApi/tc_declareChildAuto) */ test_compositeUnionTypeDeclareChild_auto(root_o, o); test_assert(o != NULL); test_assert(corto_typeof(o) == corto_type(test_compositeUnionType_o)); test_assert(!corto_checkState(o, CORTO_DEFINED)); test_assert(corto_checkAttr(o, CORTO_ATTR_SCOPED)); test_assert(corto_parentof(o) == root_o); test_assert(!strcmp(corto_idof(o), "o")); test_assert(o->d == 2); test_assertstr(o->is.str, "foo"); test_assert(!corto_delete(o)); /* $end */ }
corto_void _test_compositeApi_tc_createChildAuto( test_compositeApi _this) { /* $begin(test/compositeApi/tc_createChildAuto) */ test_compositeTypeCreateChild_auto(root_o, o, 10, 20); test_assert(o != NULL); test_assert(corto_typeof(o) == corto_type(test_compositeType_o)); test_assert(corto_checkState(o, CORTO_DEFINED)); test_assert(corto_checkAttr(o, CORTO_ATTR_SCOPED)); test_assert(corto_parentof(o) == root_o); test_assert(!strcmp(corto_idof(o), "o")); test_assert(o->x == 10); test_assert(o->y == 20); test_assert(!corto_delete(o)); /* $end */ }
corto_void _test_compositeUnionApi_tc_createChildAutoDefault( test_compositeUnionApi _this) { /* $begin(test/compositeUnionApi/tc_createChildAutoDefault) */ test_compositeUnionTypeCreateChild_other_auto( root_o, o, 4, 10); test_assert(o != NULL); test_assert(corto_typeof(o) == corto_type(test_compositeUnionType_o)); test_assert(corto_checkState(o, CORTO_DEFINED)); test_assert(corto_checkAttr(o, CORTO_ATTR_SCOPED)); test_assert(corto_parentof(o) == root_o); test_assert(!strcmp(corto_idof(o), "o")); test_assert(o->d == 4); test_assert(o->is.other == 10); test_assert(!corto_delete(o)); /* $end */ }
corto_void _test_compositeUnionApi_tc_createChild( test_compositeUnionApi _this) { /* $begin(test/compositeUnionApi/tc_createChild) */ test_compositeUnionType *o = test_compositeUnionTypeCreateChild_flt( root_o, "o", 1, 10.5); test_assert(o != NULL); test_assert(corto_typeof(o) == corto_type(test_compositeUnionType_o)); test_assert(corto_checkState(o, CORTO_DEFINED)); test_assert(corto_checkAttr(o, CORTO_ATTR_SCOPED)); test_assert(corto_parentof(o) == root_o); test_assert(!strcmp(corto_idof(o), "o")); test_assert(o->d == 1); test_assert(o->is.flt == 10.5); test_assert(!corto_delete(o)); /* $end */ }
corto_int16 corto_ser_initObservable(corto_walk_opt* s, corto_value* v, void* userData) { corto_member m = v->is.member.t; /* Initialize member to a new object of member type */ corto_type t = corto_value_typeof(v); corto_object p = corto_value_objectof(v); void* ptr = corto_value_ptrof(v); /* Create observable that is not added to the scope of its parent */ corto_attr prev = corto_setAttr(CORTO_OBSERVABLE); corto_object o = corto_createOrphan(p, corto_idof(m), t); corto_setAttr(prev); if (!o) { goto error; } *(corto_object*)ptr = o; return corto_walk_observable(s, v, userData); 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; }
/* objects * * This example shows basic usage of core API functions to create, update * and delete objects. */ /* Callback for observer */ void onUpdate( corto_object this, corto_eventMask event, corto_object o, corto_observer observer) { /* Show information about the object that triggered the observer */ printf("update received for id='%s' parent='%s' type='%s' value='%d'\n", corto_idof(o), corto_fullpath(NULL, corto_parentof(o)), corto_fullpath(NULL, corto_typeof(o)), *corto_int32(o)); } int objectsMain(int argc, char *argv[]) { /* Create a signed integer object in the global object hierarchy */ corto_int32 *i = corto_createChild(root_o, "i", corto_int32_o); if (!i) { goto error; } /* Observe the object for updates */ corto_observer observer = corto_observe(CORTO_ON_UPDATE, i).callback(onUpdate);
test_Packages this) { /* $begin(test/Packages/tc_class) */ char text[] = "# test::Package0\n" "## Class0\n" "Description of class\n" ; md_parseToCorto(test_docs_o, text); corto_object h1 = corto_resolve(test_docs_o, "test_Package0"); test_assert(h1 != NULL); test_assert(corto_instanceof(md_Doc_o, h1)); test_assert(md_Doc(h1)->o != NULL); test_assert(!strcmp(corto_idof(md_Doc(h1)->o), "Package0")); test_assert(corto_parentof(md_Doc(h1)->o) == test_o); test_assert(md_Doc(h1)->text == NULL); test_assert(md_Doc(h1)->level == 1); corto_release(h1); corto_object h2 = corto_resolve(test_docs_o, "test_Package0::Class0"); test_assert(h2 != NULL); test_assert(corto_instanceof(md_Doc_o, h2)); test_assert(md_Doc(h2)->o != NULL); test_assert(!strcmp(corto_idof(md_Doc(h2)->o), "Class0")); test_assert(corto_parentof(md_Doc(h2)->o) == md_Doc(h1)->o); test_assert(!strcmp(md_Doc(h2)->description, "Description of class\n")); test_assert(md_Doc(h2)->level == 2); corto_release(h2);
/* Parse value */ static corto_int16 corto_string_deserParseValue( corto_string value, struct corto_string_deserIndexInfo* info, corto_string_deser_t* data) { void *offset; if (corto_string_getDestinationPtr(info, data, &offset)) { corto_seterr("%s: %s", value, corto_lasterr()); goto error; } /* No more elements where available in the index, meaning an excess element */ if (!info) { corto_seterr("excess elements in scope @ '%s'", value); goto error; } /* Can typically occur when mixing short with default notation. */ if (info->parsed) { corto_seterr("member '%s' is already parsed", corto_idof(info->m)); goto error; } /* Only parse references and primitives */ if (info->type->reference) { corto_object o = NULL; corto_uint32 index = 0; /* Resolve object */ if (corto_string_deserParseAnonymousId(value, &index)) { if (!index) { if (data->isObject) { o = data->out; corto_claim(o); } else { corto_seterr("cannot refer to self (<0>), not deserializing an object"); goto error; } } else if (data->anonymousObjects && (index <= corto_ll_size(data->anonymousObjects))) { o = corto_ll_get(data->anonymousObjects, index - 1); corto_claim(o); } else { corto_seterr("undefined anonymous identifier '%s'", value); goto error; } } else { o = corto_resolve(data->scope, value); } if (o || !strcmp(value, "null")) { if (offset) corto_ptr_setref(offset, o); if (o) corto_release(o); } else { corto_seterr("unresolved reference to '%s' for member '%s'", value, corto_fullpath(NULL, info->m)); goto error; } } else /* Convert string to primitive value */ if (offset && (info->type->kind == CORTO_PRIMITIVE)) { if (corto_primitive(info->type)->kind != CORTO_TEXT) { if (corto_ptr_cast(corto_primitive(corto_string_o), &value, corto_primitive(info->type), offset)) { goto error; } } else { corto_uint32 length; corto_string deserialized; if (strcmp(value, "null")) { length = strlen(value); deserialized = corto_alloc(length+1); memcpy(deserialized, value, length); deserialized[length] = '\0'; } else { deserialized = NULL; } corto_ptr_setstr(offset, deserialized); } } /* Members are only parsed once */ if (info->m) { info->parsed = TRUE; } return 0; error: return -1; }
static int html_walkDocChilds(corto_object o, void *userData) { htmlData_t *data = userData; corto_string description = doc_getDescriptionFromDoc(o, data); corto_string text = doc_getTextFromDoc(o, data); corto_string niceName = doc_getNiceNameFromDoc(o, data); corto_object *docs = corto_alloc(sizeof(corto_object) * corto_scopeSize(o)); corto_id index; corto_object stack[CORTO_MAX_SCOPE_DEPTH]; corto_object ptr = o; corto_int32 sp = data->level; corto_id link; corto_bool noIndex = FALSE; corto_id upper; strcpy(upper, niceName); corto_strupper(upper); if (niceName[0] == '#') { noIndex = TRUE; niceName ++; } corto_string parentId = corto_idof(corto_parentof(o)); if (parentId[0] == '#') parentId++; strcpy(link, parentId); strcat(link, "_"); if (corto_idof(o)[0] == '#') { strcat(link, corto_idof(o) + 1); } else { strcat(link, corto_idof(o)); } /* If level is 0, parse heading as title */ if (!data->level) { data->title = niceName; } else { /* Add index number to header */ index[0] = '\0'; if ((sp > 1) && !noIndex) { while (--sp) { stack[sp - 1] = ptr; ptr = corto_parentof(ptr); } for (; sp < data->level - 1; sp ++) { char num[15]; sprintf(num, "%d", doc_getIndexFromDoc(stack[sp], data)); strcat(index, num); strcat(index, "."); } if (data->level > 2) { index[strlen(index) - 1] = '\0'; } strcat(index, " "); } if (data->level == 1) { corto_buffer_append(&data->content, "<a name=\"%s\"></a>\n<p class=\"section\">%s</p>\n", link, niceName); } else { corto_buffer_append(&data->content, "<a name=\"%s\"></a>\n<h%d>%s%s</h%d>\n", link, data->level, index, niceName, data->level); } if (data->level < 3) { corto_buffer_append(&data->index, "<li class=\"index-h%d\" onclick=\"window.location='#%s'\">%s</li>\n", data->level, link, data->level == 1 ? upper : niceName); } corto_buffer_append(&data->content, "<div class=\"indent\">\n"); if (description && strlen(description)) { if (data->level < 3) { corto_buffer_append(&data->content, "<p class=\"description\">%s</p>\n", description); } else { corto_buffer_append(&data->content, "<p>%s</p>\n", description); } } corto_string parsedText = doc_parse(text); corto_buffer_append(&data->content, "%s\n", parsedText); corto_dealloc(parsedText); } /* Collect documents in order */ corto_objectseq seq = corto_scopeClaim(o); corto_objectseqForeach(seq, doc) { docs[doc_getIndexFromDoc(doc, data) - 1] = doc; } corto_scopeRelease(seq); /* Walk documents in order */ data->level ++; int i; for (i = 0; i < corto_scopeSize(o); i ++) { if (!html_walkDocChilds(docs[i], userData)) { goto error; } } data->level --; corto_buffer_append(&data->content, "</div>\n"); corto_dealloc(docs); return 1; error: return 0; }
* object, the application can be notified that the data has gone stale. */ /* Callback for observer */ void onNotify( corto_object this, corto_eventMask event, corto_object o, corto_observer observer) { switch(event) { case CORTO_ON_DEFINE: printf("DEFINE "); break; case CORTO_ON_INVALIDATE: printf("INVALIDATE "); break; default: return; } printf("'%s'\n", corto_idof(o)); } void printValid(corto_object o) { /* The checkstate function can be used to check for validity */ printf("object '%s' is %svalid\n", corto_idof(o), corto_checkState(o, CORTO_VALID) ? "" : "not "); } int objects_invalidMain(int argc, char *argv[]) { /* Create a new object */ corto_object *o = corto_createChild(root_o, "o", corto_void_o); if (!o) { goto error;
#include "shapes.h" void onUpdate(corto_object this, corto_eventMask event, corto_object shape, corto_observer observer) { printf("Update %s %s = %s\n", corto_idof(corto_parentof(shape)), corto_idof(shape), corto_contentof(NULL, "text/json", shape)); } int shapesMain(int argc, char *argv[]) { if (argc < 3) { printf("Usage: shapes [topic] [color]\n"); printf(" Example: shapes Circle RED\n"); return -1; } /* Connect shape topic */ ospl_Connector connector = ospl_ConnectorCreateChild( root_o, /* create connector in root */ argv[1], /* object name of connector (same as topic) */ NULL, /* store instances in scope of connector */ "/ShapeType", /* type */ NULL, /* default policy */ argv[1], /* topic */ "color" /* keylist */ ); /* Observe updates in connector scope */ corto_observe(CORTO_ON_UPDATE|CORTO_ON_SCOPE, connector).callback(onUpdate); /* Create shape */ ShapeType *s = ShapeTypeDeclareChild(connector, argv[2]);