corto_string corto_buffer_str(corto_buffer *b) { corto_string result = NULL; if (b->elementCount) { if (b->buf) { result = corto_strdup(b->buf); } else { void *next = NULL; corto_uint32 len = (b->elementCount - 1) * CORTO_BUFFER_ELEMENT_SIZE + b->current->pos + 1; corto_buffer_element *e = &b->firstElement; result = corto_alloc(len); corto_string ptr = result; do { memcpy(ptr, e->buf, e->pos); ptr += e->pos; next = e->next; if (e != &b->firstElement) { corto_dealloc(e); } } while ((e = next)); result[len - 1] = '\0'; } } else { result = NULL; } b->elementCount = 0; return result; }
corto_iter corto_llIterAlloc(corto_ll list) { corto_iter result; corto_llIter_s *udata = corto_alloc(sizeof(corto_llIter_s)); result = _corto_llIter(list, udata); result.release = corto_llIterRelease; return result; }
/* Register a filetype */ int corto_load_register(corto_string ext, corto_loadAction handler, void* userData) { struct corto_fileHandler* h; /* Check if extension is already registered */ corto_mutexLock(&corto_adminLock); if ((h = corto_lookupExt(ext))) { if (h->load != handler) { corto_error("corto_load_register: extension '%s' is already registered with another loader.", ext); abort(); goto error; } } else { h = corto_alloc(sizeof(struct corto_fileHandler)); h->ext = ext; h->load = handler; h->userData = userData; if (!fileHandlers) { fileHandlers = corto_ll_new(); } corto_ll_append(fileHandlers, h); } corto_mutexUnlock(&corto_adminLock); return 0; error: return -1; }
corto_err corto_logv(corto_err kind, unsigned int level, char* fmt, va_list arg, FILE* f) { char buff[CORTO_MAX_LOG + 1]; size_t n = 0; corto_string alloc = NULL; corto_string msg = buff; va_list argcpy; va_copy(argcpy, arg); /* Make copy of arglist in * case vsnprintf needs to be called twice */ CORTO_UNUSED(level); if ((n = (vsnprintf(buff, CORTO_MAX_LOG, fmt, arg) + 1)) > CORTO_MAX_LOG) { alloc = corto_alloc(n + 2); vsnprintf(alloc, n, fmt, argcpy); msg = alloc; } n = strlen(msg); strcat(msg, "\n"); n++; if (f == stderr) { fprintf(f, "%s%s%s", RED, msg, NORMAL); } else { fprintf(f, "%s", msg); } if (alloc) { corto_dealloc(alloc); } return kind; }
corto_fileMonitor* cortotool_monitorNew(char *file, char *lib) { corto_fileMonitor *mon = corto_alloc(sizeof(corto_fileMonitor)); mon->file = corto_strdup(file); mon->lib = lib ? corto_strdup(lib) : NULL; mon->mtime = 0; return mon; }
static void CORTO_NAME_BINARYOP(string,add)(void* op1, void* op2, void* result) { corto_uint32 len = strlen(*(corto_string*)op1) + strlen(*(corto_string*)op2); if (*(corto_string*)result) { corto_dealloc(*(corto_string*)result); } *(corto_string*)result = corto_alloc(len + 1); sprintf(*(corto_string*)result, "%s%s", *(corto_string*)op1, *(corto_string*)op2); }
/* Add an extra element to the buffer */ static void corto_buffer_grow(corto_buffer *b) { /* Allocate new element */ corto_buffer_element *e = corto_alloc(sizeof(corto_buffer_element)); b->current->next = e; b->current = e; e->pos = 0; e->next = NULL; b->elementCount ++; }
/* Walk objects in correct dependency order. */ corto_depresolver corto_depresolverCreate(corto_depresolver_action onDeclare, corto_depresolver_action onDefine, void* userData) { corto_depresolver result; result = corto_alloc(sizeof(struct corto_depresolver_s)); result->items = corto_llNew(); result->toPrint = corto_llNew(); result->onDeclare = onDeclare; result->onDefine = onDefine; result->userData = userData; return result; }
static corto_errThreadData* corto_getThreadData(void){ corto_errThreadData* result; if (!corto_errKey) { corto_threadTlsKey(&corto_errKey, corto_lasterrorFree); } result = corto_threadTlsGet(corto_errKey); if (!result) { result = corto_alloc(sizeof(corto_errThreadData)); memset(result, 0, sizeof(corto_errThreadData)); corto_threadTlsSet(corto_errKey, result); } return result; }
/* Create new item */ g_item g_itemNew(corto_object o, corto_depresolver data) { g_item result; result = corto_alloc(sizeof(struct g_item)); result->o = o; result->declared = FALSE; result->defined = FALSE; result->declareCount = 0; result->defineCount = 0; result->onDeclared = NULL; result->onDefined = NULL; if (o == root_o) { result->declared = TRUE; result->defined = TRUE; } corto_llInsert(data->items, result); return result; }
/* Do metawalk on type */ int16_t _corto_metawalk( corto_walk_opt* s, corto_type type, void* userData) { corto__object* o; int16_t result; /* Since we potentially overwrite some callbacks, make private copy */ corto_walk_opt private = *s; ut_assert(type != NULL, "corto_metawalk called with NULL type"); /* Instantiate dummy-object */ o = corto_alloc(sizeof(corto__object) + type->size); memset(o, 0, sizeof(corto__object) + type->size); o->type = corto_type(type); o->refcount = 1; #ifndef NDEBUG o->magic = CORTO_MAGIC; #endif private.visitAllCases = TRUE;
/* Add indexInfo to indextable for each primitive */ static corto_int16 corto_string_deserBuildIndexPrimitive(corto_walk_opt* s, corto_value* v, void* userData) { corto_string_deser_t* data; struct corto_string_deserIndexInfo *newInfo; corto_member m; CORTO_UNUSED(s); data = userData; /* Lookup member */ m = v->is.member.t; /* Create new info-object */ newInfo = corto_alloc(sizeof(struct corto_string_deserIndexInfo)); newInfo->m = m; newInfo->type = m->type; newInfo->parsed = FALSE; /* Insert indexInfo into index */ corto_string_deserIndexInsert(data, newInfo); return 0; }
/* Parse scope */ static corto_string corto_string_deserParseScope(corto_string str, struct corto_string_deserIndexInfo* info, corto_string_deser_t* data) { struct corto_string_deserIndexInfo rootInfo; corto_typeKind kind; void *ptr = data->ptr; if (data->allocValue) { ptr = data->allocValue(ptr, data); } /* Prepare privateData */ corto_string_deser_t privateData = { .out = data->out, .scope = data->scope, .anonymousObjects = data->anonymousObjects, .type = data->type, .isObject = data->isObject, .members = {0, NULL} }; /* Offset the scope-members with the current offset */ if (info && info->m) { ptr = corto_getMemberPtr(data->isObject ? data->out : NULL, ptr, info->m); } privateData.ptr = ptr; /* Open scope of type */ if (!info) { if (!data->type) { rootInfo.type = corto_typeof(data->out); } else { rootInfo.type = data->type; } rootInfo.m = NULL; rootInfo.parsed = FALSE; info = &rootInfo; } /* Check if type is any, composite or collection */ kind = info->type->kind; if ((kind != CORTO_COMPOSITE) && (kind != CORTO_COLLECTION) && (kind != CORTO_ANY)) { corto_seterr("'{' unexpected for type '%s'", corto_fullpath(NULL, info->type)); goto error; } /* Build index for type */ if (info->type->kind == CORTO_COMPOSITE) { if (corto_interface(info->type)->kind == CORTO_UNION) { /* Parse discriminator */ struct corto_string_deserIndexInfo dInfo; dInfo.type = (corto_type)corto_int32_o; dInfo.parsed = FALSE; dInfo.m = NULL; str = corto_string_deserParse(str + 1, &dInfo, &privateData); if (!str) { goto error; } /* Find corresponding union case */ corto_int32 d = *(corto_int32*)ptr; corto_member m = safe_corto_union_findCase(info->type, d); if (!m) { corto_seterr("discriminator '%d' invalid for union '%s'", d, corto_fullpath(NULL, info->type)); goto error; } /* Build index for one member */ struct corto_string_deserIndexInfo *caseInfo = corto_alloc(sizeof(struct corto_string_deserIndexInfo)); caseInfo->type = m->type; caseInfo->parsed = FALSE; caseInfo->m = m; corto_string_deserIndexInsert(&privateData, caseInfo); } else { corto_walk_opt s = corto_string_deserBuildIndex(); s.members = data->members; if (s.members.length) { s.access = 0; } if (corto_metawalk(&s, info->type, &privateData)) { goto error; } } /* Create iterator for index */ if (privateData.index) { privateData.currentIter = _corto_ll_iter(privateData.index, &privateData.iterData); } /* If type is a collection, build index with one node for element */ } else if (info->type->kind == CORTO_COLLECTION) { struct corto_string_deserIndexInfo *elementNode; elementNode = corto_alloc(sizeof(struct corto_string_deserIndexInfo)); elementNode->m = NULL; elementNode->parsed = FALSE; elementNode->type = corto_collection(info->type)->elementType; corto_string_deserIndexInsert(&privateData, elementNode); /* Create iterator for index */ privateData.currentIter = _corto_ll_iter(privateData.index, &privateData.iterData); privateData.allocValue = corto_string_deserAllocElem; privateData.allocUdata = info->type; if (ptr) { switch(corto_collection(info->type)->kind) { case CORTO_ARRAY: case CORTO_SEQUENCE: break; case CORTO_LIST: if (!*(corto_ll*)ptr) { *(corto_ll*)ptr = corto_ll_new(); } else { corto_ll_clear(*(corto_ll*)ptr); } privateData.ptr = ptr; break; default: break; } } } else if (info->type->kind == CORTO_ANY) { struct corto_string_deserIndexInfo *anyNode; anyNode = corto_alloc(sizeof(struct corto_string_deserIndexInfo)); anyNode->m = NULL; anyNode->parsed = FALSE; anyNode->type = corto_type(corto_type_o); corto_string_deserIndexInsert(&privateData, anyNode); privateData.currentIter = _corto_ll_iter(privateData.index, &privateData.iterData); privateData.allocValue = corto_string_deserAllocAny; privateData.allocUdata = anyNode; } /* Parse scope */ if (!(str = corto_string_deserParse(str+1, info, &privateData))) { goto error; } corto_string_deserFreeIndex(&privateData); data->anonymousObjects = privateData.anonymousObjects; return str; error: return NULL; } /* Get pointer to current destination value */ corto_int16 corto_string_getDestinationPtr( struct corto_string_deserIndexInfo* info, corto_string_deser_t* data, void **ptr_out) { void *result = data->ptr; *ptr_out = NULL; if (!info) { corto_seterr("excess elements in string"); goto error; } if (data->allocValue) { result = data->allocValue(result, data); } if (info->m) { result = corto_getMemberPtr(data->isObject ? data->out : NULL, data->ptr, info->m); } *ptr_out = result; return 0; error: return -1; }
* web_SockJsServer_Connection.c * * Only code written between the begin and end tags will be preserved * when the file is regenerated. */ #include "web.h" /* $header() */ #include "mongoose.h" /* $end */ corto_void _web_SockJsServer_Connection_send(web_SockJsServer_Connection this, corto_string msg) { /* $begin(::corto::web::SockJsServer::Connection::send) */ int escapedLength; corto_string sockJsMsg; /* Escape & pack message in SockJS header */ escapedLength = stresc(NULL, 0, msg); sockJsMsg = corto_alloc(escapedLength + strlen("a[\"\"]") + 1); sprintf(sockJsMsg, "a[\"%*s\"]", escapedLength, " "); stresc(sockJsMsg + 3, escapedLength, msg); if (this->conn) { mg_websocket_printf((struct mg_connection *)this->conn, WEBSOCKET_OPCODE_TEXT, sockJsMsg); } corto_dealloc(sockJsMsg); /* $end */ }
/* Find existing parts in the code that must not be overwritten. */ static corto_ll cdiff_parseLegacy(char *code) { char *ptr = NULL; corto_ll result = corto_ll_new(); ptr = code; while((ptr = strchr(ptr, '$'))) { cdiff_elemKind kind = CDIFF_TEXT; if (!memcmp(ptr, "$begin", 6)) { ptr += 6; kind = CDIFF_FUNCTION_LEGACY; } else if (!memcmp(ptr, "$header", 7)) { ptr += 7; } else { ptr ++; continue; } /* Find begin of identifier */ if (*ptr == '(') { char *endptr; /* Find end of identifier */ endptr = strstr(ptr, ") */"); if (endptr) { corto_id identifier; /* Copy identifier string */ *endptr = '\0'; endptr += 3; if (strlen(ptr) >= sizeof(corto_id)) { corto_seterr( "%s: identifier of code-snippet exceeds %d characters", sizeof(corto_id)); goto error; } strcpy(identifier, ptr + 1); ptr = endptr + 1; /* Find $end */ endptr = strstr(ptr, "$end"); endptr -= 3; /* include comment begin token */ if (endptr) { cdiff_elem* el; corto_string src; if (kind != CDIFF_TEXT) { endptr[0] = '}'; endptr[1] = '\n'; endptr[2] = '\0'; endptr += 3; } else { endptr[0] = '\n'; endptr[1] = '\0'; endptr += 2; } src = corto_strdup(ptr); if(strstr(src, "$begin")) { corto_seterr("code-snippet '%s' contains nested $begin (did you forget an $end?)", identifier); corto_dealloc(src); goto error; } el = corto_alloc(sizeof(cdiff_elem)); el->kind = kind; el->id = corto_strdup(identifier); el->header = NULL; el->body = src; corto_ll_append(result, el); ptr = endptr + 1; } else { corto_warning("generator: missing $end after $begin(%s)", identifier); } } else { corto_warning("generator: missing ')' after $begin/$header"); } } else { corto_warning("generator: missing '(' after $begin/$header"); } } return result; error: if (result) { corto_ll_free(result); } printf("error!\n"); return NULL; }
/* 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; }
/* strdup is not a standard C function, so provide own implementation. */ char* corto_strdup(const char* str) { char *result = corto_alloc(strlen(str) + 1); strcpy(result, str); return result; }
/* $CORTO_GENERATED * * web_DDPServer_Session.c * * Only code written between the begin and end tags will be preserved * when the file is regenerated. */ #include "web.h" /* $header() */ corto_void web_DDPServer_Session_nosub(web_DDPServer_Session this, corto_string id) { int msgLength = snprintf(NULL, 0, "{\"msg\":\"nosub\",\"id\":\"%s\"}", id); corto_string msg = corto_alloc(msgLength + 1); sprintf(msg, "{\"msg\":\"nosub\",\"id\":\"%s\"}", id); web_SockJsServer_Connection_send(this->conn, msg); corto_dealloc(msg); } /* $end */ corto_void _web_DDPServer_Session_connected(web_DDPServer_Session this) { /* $begin(::corto::web::DDPServer::Session::connected) */ int msgLength = snprintf(NULL, 0, "{\"msg\":\"connected\",\"session\":\"%s\"}", corto_nameof(this)); corto_string msg = corto_alloc(msgLength + 1); sprintf(msg, "{\"msg\":\"connected\",\"session\":\"%s\"}", corto_nameof(this)); web_SockJsServer_Connection_send(this->conn, msg); corto_dealloc(msg); /* $end */ } corto_int16 _web_DDPServer_Session_construct(web_DDPServer_Session this) {
/* Append a format string to a buffer */ static corto_bool corto_buffer_appendIntern( corto_buffer *b, corto_string str, void *data, corto_uint32 ___ (*copy)(char *dst, char *str, corto_int32 len, void *data)) { corto_bool result = TRUE; if (!str) { return result; } corto_buffer_init(b); corto_int32 spaceLeftInElement = corto_buffer_spaceLeftInCurrentElement(b); corto_int32 spaceLeft = corto_buffer_spaceLeft(b); /* Compute the memory required to add the string to the buffer */ corto_int32 memRequired = copy( corto_buffer_ptr(b), str, (b->max && (spaceLeft < spaceLeftInElement)) ? spaceLeft : spaceLeftInElement + 1, data); if (b->max && (spaceLeft < memRequired)) { result = FALSE; } /* If the string required more memory than was available in the element, * grow the buffer */ else if (memRequired >= spaceLeftInElement) { /* If writing to a user-provided buffer, the max is reached and append * should return false. Otherwise, the buffer needs to grow with extra * elements. */ b->current->pos += spaceLeftInElement; if (!b->buf) { /* If the extra required memory doesn't exceed the elementsize, grow * a new element, vsnprintf into the element and then memmove to * truncate the part that was already added to the previous * element */ if (memRequired < CORTO_BUFFER_ELEMENT_SIZE) { corto_buffer_grow(b); corto_int32 len = 0; if (b->max && (spaceLeft < CORTO_BUFFER_ELEMENT_SIZE)) { len = spaceLeft; result = FALSE; } else { len = memRequired - spaceLeftInElement; } copy(corto_buffer_ptr(b), str, CORTO_BUFFER_ELEMENT_SIZE, data); memmove( corto_buffer_ptr(b), corto_buffer_ptr(b) + spaceLeftInElement, len); b->current->pos = len; /* If the extra memory required exceeds the elementSize, allocate a * temporary string that will hold the full value, then distribute * the results over the new elements */ } else { corto_string dst = corto_alloc(memRequired + 1); char *ptr = dst + spaceLeftInElement; corto_int32 memLeft = memRequired - spaceLeftInElement; /* Copy entire string to heap memory */ copy(dst, str, memRequired + 1, data); /* Copy string to elements */ while (memLeft > 0) { corto_buffer_grow(b); if (memLeft > CORTO_BUFFER_ELEMENT_SIZE) { corto_buffer_copy(b, ptr, CORTO_BUFFER_ELEMENT_SIZE); ptr += CORTO_BUFFER_ELEMENT_SIZE; memLeft -= CORTO_BUFFER_ELEMENT_SIZE; } else { corto_buffer_copy(b, ptr, memLeft); memLeft = 0; } } corto_dealloc(dst); } } else { result = FALSE; } } else { b->current->pos += memRequired; } return result; }