Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
static corto_string doc_parse(corto_string input) {
    corto_string result = NULL;
    corto_function f = corto_function(corto_resolve(NULL, "md::parse"));
    if (corto_checkState(f, CORTO_DEFINED)) {
        corto_call(f, &result, input);
    }
    return result;
}
Exemplo n.º 3
0
corto_int16 corto_genMain(g_generator g) {
    htmlData_t data = {
        g,
        "doc",
        NULL,
        CORTO_BUFFER_INIT,
        CORTO_BUFFER_INIT,
        corto_resolve(NULL, "corto/md/Doc"),
        0
    };

    if (corto_mkdir(data.output)) {
        goto error;
    }

    if (html_copyFiles(&data)) {
        goto error;
    }

    if (!g_getCurrent(g)) {
        corto_object doc = corto_resolve(NULL, "doc");
        if (doc) {
            corto_id file;
            corto_string include;

            corto_scopeWalk(doc, html_walkDocChilds, &data);

            if ((include = g_getAttribute(data.g, "include"))) {
                char *ext;
                sprintf(file, "doc/%s", include);

                /* Quick & dirty way to replace extension .md with .html */
                ext = strchr(file, '.');
                if (ext) {
                    strcpy(ext, ".html");
                } else {
                    strcat(file, ".html");
                }
            } else {
                sprintf(file, "doc/doc.html");
            }

            corto_id template;
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
/* 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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
/* 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;
}
Exemplo n.º 8
0
#include <test.h>

corto_void _test_Packages_tc_class(
    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);
Exemplo n.º 9
0
static void mqtt_onMessage(
    struct mosquitto *client,
    void *data,
    const struct mosquitto_message *msg)
{
    corto_id nameBuffer;
    char *name = nameBuffer;
    corto_object o = NULL;
    mqtt_Connector this = data;
    corto_bool isDelete = FALSE;

    /* If the payload has been serialized as a corto string, the typename is
     * potentially prefixed to the value */
    char *valueStr = strchr(msg->payload, '{');

    /* mqtt is the owner of this thread. This ensures that all subsequent create
     * update / delete actions are performed with the right owner. Ownership
     * ensures to not trigger on own updates, and to only forward data from
     * other connectors (or the application). */
    corto_object prevOwner = corto_setOwner(this);

    /* Remove topic from name, so that name is relative to mount point. */
    strcpy(name, msg->topic);
    if (this->topic) {
        name += strlen(this->topic) + 1;
    }

    char *lastElem = strrchr(name, '/');
    if (lastElem && !strcmp(lastElem, "/_d")) {
        *lastElem = '\0';
        isDelete = TRUE;
    }

    corto_debug("mqtt: %s: received '%s'", msg->topic, msg->payload);

    /* If object doesn't yet exist in the store, create it */
    if (!(o = corto_lookup(corto_mount(this)->mount, name)) && !isDelete) {
        corto_id buffer;
        corto_debug("mqtt: creating new object for '%s'", name);

        /* If the mount has been configured with a fixed type, use that type to
         * create a new object. Otherwise, look for type in payload. */
        if (corto_observer(this)->type) {
            strcpy(buffer, corto_observer(this)->type);
        } else {
            char *typeStr = strchr(msg->payload, '{');
            memcpy(buffer, msg->payload, typeStr - (char*)msg->payload);
            buffer[typeStr - (char*)msg->payload] = '\0';
        }

        /* Resolve type. If type wasn't yet loaded in corto, corto_resolve will
         * do a lookup on the package repository. If it doesn't exist there
         * either throw an error. Currently, the MQTT connector does not align
         * types. */
        corto_type type = corto_resolve(NULL, buffer);
        if (!type) {
            corto_error("mqtt: type '%s' not found", buffer);
            goto error;
        }

        corto_debug("mqtt: creating '%s' with type '%s'", name, buffer);

        /* Create a new object under the mountpoint. The name is derived from
         * the MQTT topic name. */
        o = corto_declareChild(corto_mount(this)->mount, name, type);
        if (!o) {
            corto_error("mqtt: failed to create object '%s'", name);
            goto error;
        }
    } else {
        corto_debug("mqtt: found '%s' for '%s'", corto_fullpath(NULL, o), name);
    }

    /* Only continue updating object when it is owned by mqtt */
    if (o && corto_owned(o)) {
        if (isDelete) {
            if (corto_delete(o)) {
                corto_error("mqtt: failed to delete '%s': %s", name, corto_lasterr());
            }
            corto_release(o);
        } else {
            /* Start updating object (takes a writelock) */
            if (!corto_updateBegin(o)) {
                /* Serialize value from JSON string */
                if (corto_fromcontent(o, "text/json", valueStr)) {
                    corto_error("mqtt: failed to deserialize for %s: %s (%s)\n",
                        name,
                        corto_lasterr(),
                        msg->payload);

                    /* If deserialization fails, cancel the update. No notification
                     * will be sent. */
                    corto_updateCancel(o);
                    goto error;
                }
                /* Successful update. Send notification and unlock object */
                if (corto_updateEnd(o)) {
                    corto_error("mqtt: failed to update '%s': %s", name, corto_lasterr());
                    goto error;
                }
            } else {
                /* For some reason, couldn't start updating object */
                corto_error("mqtt: failed to start updating '%s': %s", name, corto_lasterr());
                goto error;
            }
        }
    } else if (o) {
        corto_debug("mqtt: '%s' not owned by me (%s, defined = %d), ignoring",
            corto_fullpath(NULL, o),
            corto_ownerof(o) ? corto_fullpath(NULL, o) : "local",
            corto_checkState(o, CORTO_DEFINED));
    }

error:
    /* Restore previous owner */
    corto_setOwner(prevOwner);
}