#include "lib.h" #include #include #ifdef __INLINE_PSYC_RENDER static inline #endif psycRenderListRC psyc_render_list (psycList *list, char *buffer, size_t buflen) { size_t i, cur = 0; psycString *elem; if (list->length > buflen) // return error if list doesn't fit in buffer return PSYC_RENDER_LIST_ERROR; if (list->flag == PSYC_LIST_NEED_LENGTH) { for (i = 0; i < list->num_elems; i++) { elem = &list->elems[i]; if (i > 0) buffer[cur++] = '|'; cur += itoa(elem->length, buffer + cur, 10); buffer[cur++] = ' '; memcpy(buffer + cur, elem->ptr, elem->length); cur += elem->length; } } else { for (i = 0; i < list->num_elems; i++) { elem = &list->elems[i]; buffer[cur++] = '|'; memcpy(buffer + cur, elem->ptr, elem->length); cur += elem->length; } } // actual length should be equal to pre-calculated length at this point assert(cur == list->length); return PSYC_RENDER_LIST_SUCCESS; } static inline size_t psyc_render_modifier (psycModifier *mod, char *buffer) { size_t cur = 0; buffer[cur++] = mod->oper; memcpy(buffer + cur, mod->name.ptr, mod->name.length); cur += mod->name.length; if (cur <= 1) return cur; // error, name can't be empty if (mod->flag == PSYC_MODIFIER_NEED_LENGTH) { buffer[cur++] = ' '; cur += itoa(mod->value.length, buffer + cur, 10); } buffer[cur++] = '\t'; memcpy(buffer + cur, mod->value.ptr, mod->value.length); cur += mod->value.length; buffer[cur++] = '\n'; return cur; } #ifdef __INLINE_PSYC_RENDER static inline #endif psycRenderRC psyc_render (psycPacket *packet, char *buffer, size_t buflen) { size_t i, cur = 0, len; if (packet->length > buflen) // return error if packet doesn't fit in buffer return PSYC_RENDER_ERROR; // render routing modifiers for (i = 0; i < packet->routing.lines; i++) { len = psyc_render_modifier(&packet->routing.modifiers[i], buffer + cur); cur += len; if (len <= 1) return PSYC_RENDER_ERROR_MODIFIER_NAME_MISSING; } // add length if needed if (packet->flag == PSYC_PACKET_NEED_LENGTH) cur += itoa(packet->contentLength, buffer + cur, 10); if (packet->flag == PSYC_PACKET_NEED_LENGTH || packet->content.length || packet->entity.lines || packet->method.length || packet->data.length) buffer[cur++] = '\n'; // start of content part if there's content or length if (packet->content.length) // render raw content if present { memcpy(buffer + cur, packet->content.ptr, packet->content.length); cur += packet->content.length; } else { // render entity modifiers for (i = 0; i < packet->entity.lines; i++) cur += psyc_render_modifier(&packet->entity.modifiers[i], buffer + cur); if (packet->method.length) // add method\n { memcpy(buffer + cur, packet->method.ptr, packet->method.length); cur += packet->method.length; buffer[cur++] = '\n'; if (packet->data.length) // add data\n { memcpy(buffer + cur, packet->data.ptr, packet->data.length); cur += packet->data.length; buffer[cur++] = '\n'; } } else if (packet->data.length) // error, we have data but no modifier return PSYC_RENDER_ERROR_METHOD_MISSING; } // add packet delimiter buffer[cur++] = C_GLYPH_PACKET_DELIMITER; buffer[cur++] = '\n'; // actual length should be equal to pre-calculated length at this point assert(cur == packet->length); return PSYC_RENDER_SUCCESS; }