static int lxs_tablib_joinall(lua_State* const L) { lxs_assert_stack_begin(L); size_t dlen; const char* delim = luaL_checklstring(L, 1, &dlen); int top = lua_gettop(L); if (top <= 2) luaL_argerror(L, 2, "need at least 2 arguments"); else if (lua_isnoneornil(L, 2)) luaL_argerror(L, 2, "cannot be nil"); xbuf_decl(b); xbuf_init(L, b); for (int i = 2; i <= top; ++i) { size_t elen; const char* estr = luaL_checklstring(L, i, &elen); if (elen > 0) xbuf_addlstring(L, b, estr, elen); if (dlen > 0 && i + 1 <= top) xbuf_addlstring(L, b, delim, dlen); } xbuf_pushresult(L, b); #if LUAXS_STR_PERSISTENT_BUFFER lxs_assert_stack_end(L, 1); #else lxs_assert_stack_end(L, 1 + (b.lvl - 1)); #endif return 1; }
static void pipeline_lua_init(const char *name) { indigo_core_message_listener_register(message_listener); xbuf_init(&upload_chunks); pipeline_lua_stats_init(); ind_ovs_pktin_socket_register(&pktin_soc, process_pktin, PKTIN_INTERVAL, PKTIN_BURST_SIZE); reset_lua(); }
WRAP_API int wrap_mvwinsnstr(WINDOW *win, int y, int x, uchar2 *str, int n) { #if defined(CURSES_WIDE) && SIZEOF_WCHAR_T == 2 return mvwins_nwstr(win, y, x, str, n); #elif defined(CURSES_WIDE) wchar_t stackbuf[BUFFER_SIZE]; xbuffer xinput, xoutput; int ret; xbuf_init_uc(&xinput, str, n, XBUF_FILL); xbuf_init_wc(&xoutput, stackbuf, BUFFER_SIZE, XBUF_EXPANDABLE); ret = unicode_to_wchar(&xinput, &xoutput); if (ret < 0) goto do_exit; ret = xbuf_tzero_wc(&xoutput); if (ret < 0) goto do_exit; ret = mvwins_nwstr(win, y, x, xbuf_data_wc(&xoutput), xbuf_len_wc(&xoutput)); do_exit: xbuf_free(&xoutput); return ret; #else char stackbuf[BUFFER_SIZE]; xbuffer xinput, xoutput; int ret; xbuf_init_uc(&xinput, str, n, XBUF_FILL); xbuf_init(&xoutput, stackbuf, BUFFER_SIZE, XBUF_EXPANDABLE); ret = unicode_to_char(&xinput, &xoutput); if (ret < 0) goto do_exit; ret = xbuf_tzero(&xoutput); if (ret < 0) goto do_exit; ret = mvwinsnstr(win, y, x, xbuf_data(&xoutput), xbuf_len(&xoutput)); do_exit: xbuf_free(&xoutput); return ret; #endif }
int main(int argc, char *argv[]) { xbuf_t data; xbuf_init(&data); xbuf_cat(&data, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sit amet " "quam purus, vitae fermentum turpis. Nam in augue mi. Donec suscipit moles" "tie felis, eget rhoncus risus pharetra in. Sed id diam id felis fringilla" " adipiscing non vitae odio. Etiam vulputate tristique elit, nec eleifend" " mauris scelerisque eu. Vestibulum luctus, enim a luctus posuere, mauris" " mauris rutrum mi, eget fermentum massa tortor id enim. Nulla feugiat " "porta urna quis laoreet. Morbi metus ante, commodo quis dictum vitae, " "rhoncus a libero. Cras viverra feugiat orci id interdum. Duis pulvinar " "neque id erat adipiscing facilisis. Maecenas vitae urna risus, euismod" " sollicitudin risus." ); char gzipped[4096]; u32 len = zlib_cmp(data.ptr, 0, data.len, gzipped, sizeof(gzipped), 1); printf("Original length: %i\n", data.len); printf("Gzipped length: %i\n\n", len); xbuf_t *reply = get_reply(argv); xbuf_xcat(reply, "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: %i\r\n" "Content-Encoding: gzip\r\n\r\n", len ); xbuf_ncat(reply, gzipped, len); xbuf_free(&data); return -1; //custom headers }
/// table.join(table[, delimiter]) /// /// Concatenables all entries of a *table*, optionally separating them using a /// *delimiter* string. /// The table is traversed using *next* and which means traversal order is /// undefined or the non-vector part of the table. /// /// Usage example: /// table.join({ '' }, ',') --> '' /// table.join({ '', '' }, ',') --> ',' /// table.join({ 'a', 'b' }, ',') --> 'a,b' static int libE_join(lua_State* const L) { lxs_assert_stack_begin(L); luaL_checktype(L, 1, LUA_TTABLE); size_t dlen; const char* delim = luaL_optlstring(L, 2, NULL, &dlen); xbuf_decl(b); xbuf_init(L, b); bool add_delim = false; lua_pushnil(L); while (lua_next(L, 1)) { if (add_delim) xbuf_addlstring(L, b, delim, dlen); else if (dlen > 0) add_delim = true; size_t elen; const char* estr = luaL_checklstring(L, -1, &elen); if (elen > 0) xbuf_addlstring(L, b, estr, elen); lua_pop(L, 1); } xbuf_pushresult(L, b); #if LUAXS_STR_PERSISTENT_BUFFER lxs_assert_stack_end(L, 1); #else lxs_assert_stack_end(L, 1 + (b.lvl - 1)); #endif return 1; }
int list_threads(kv_item *item, xbuf_t *reply) { Thread *thread = (Thread*)item->val; xbuf_t thread_li; xbuf_init(&thread_li); //using sprintf-like formatting xbuf_xcat(&thread_li, "<li>" "<a href='/?forum_simple/act=t/id=%llu'>%s</a> (%lu)" "</li>", thread->id, thread->title.ptr, thread->posts.nbr_items ); char *pos = (char*)xbuf_findstr(reply, "<!--tpl-->"); if (pos) xbuf_insert(reply, pos, thread_li.len, thread_li.ptr); xbuf_free(&thread_li); return 1; }
/// table.joini(table[, delimiter]) /// /// Concatenables all entries of a *table*, optionally separating them using a /// *delimiter* string. /// Only the vector part of a table is traversed. /// /// Usage example: /// table.joini({ '' }, ',') --> '' /// table.joini({ '', '' }, ',') --> ',' /// table.joini({ 'a', 'b' }, ',') --> 'a,b' static int libE_joini(lua_State* const L) { lxs_assert_stack_begin(L); luaL_checktype(L, 1, LUA_TTABLE); size_t dlen; const char* delim = luaL_optlstring(L, 2, NULL, &dlen); xbuf_decl(b); xbuf_init(L, b); int vlen = lua_objlen(L, 1); for (int i = 1; i <= vlen; ++i) { lua_rawgeti(L, 1, i); size_t elen; const char* estr = luaL_checklstring(L, -1, &elen); if (elen > 0) xbuf_addlstring(L, b, estr, elen); if (dlen > 0 && i + 1 <= vlen) xbuf_addlstring(L, b, delim, dlen); lua_pop(L, 1); } xbuf_pushresult(L, b); #if LUAXS_STR_PERSISTENT_BUFFER lxs_assert_stack_end(L, 1); #else lxs_assert_stack_end(L, 1 + (b.lvl - 1)); #endif return 1; }
int main(int argc, char *argv[]) { //initialize Key-Value store-------------------------------------------------- kv_t **vhost_ptr = (kv_t**)get_env(argv, US_VHOST_DATA), //persistent ptr *forum_store = 0; //convenience pointer (var->m instead of (*var)->m) if (vhost_ptr && !*vhost_ptr) { *vhost_ptr = (kv_t*)malloc(sizeof(kv_t)); //threads and posts stored here kv_init(*vhost_ptr, "forum_store", 1024, 0, 0, 0); } forum_store = *vhost_ptr; //---------------------------------------------------------------------------- //setup GET and POST variables------------------------------------------------ char *act = "", *id = "", *title = "", *body = ""; get_arg("act=", &act, argc, argv); //action ('t' or 'p') get_arg("id=", &id, argc, argv); //id of thread get_arg("title=", &title, argc, argv); //title of thread get_arg("body=", &body, argc, argv); //body of post char *end = 0; u64 int_id = strtoll(id, &end, 10); //string to integer if (*end) int_id = 0; //require a numeric ID //---------------------------------------------------------------------------- //response sent to browser is stored here------------------------------------- //templates are rendered into this buffer xbuf_t *reply = get_reply(argv); xbuf_cat(reply, base_tpl); //set base template //---------------------------------------------------------------------------- //HTTP state of a connection http_t *http = (http_t*)get_env(argv, HTTP_HEADERS); redirect: //simulate HTTP, <meta>, or JavaScript redirect without page reload //choose what to do based on the value of 'act'------------------------------- switch (*act) { //regarding a post case 'p': { switch (http->h_method) //GET or POST { //new post-------------------------------------------------------------- case HTTP_POST: { //get the thread to which this post belongs Thread *thread = (Thread*)kv_get(forum_store, (char*)&int_id, sizeof(int_id)); if (!thread) //thread not found { xbuf_repl(reply, "<!--tpl-->", http_error(404)); return 404; } //allocate memory Post *post = calloc(1, sizeof(*post)); //initialize members xbuf_init(&post->body); //define members post->id = thread->posts.nbr_items + 1; xbuf_cat(&post->body, *body ? body : " "); //add post to thread kv_add(&thread->posts, &(kv_item) { .key = (char*)&post->id, .klen = sizeof(post->id), .val = (char*)post, .flags = 0, }); //setup redirect http->h_method = HTTP_GET; *act = 't'; goto redirect; } break; //---------------------------------------------------------------------- } } break; //regarding a thread case 't': { switch (http->h_method) { //view a thread--------------------------------------------------------- case HTTP_GET: { Thread *thread = (Thread*)kv_get(forum_store, (char*)&int_id, sizeof(int_id)); if (!thread) { xbuf_repl(reply, "<!--tpl-->", http_error(404)); return 404; } //replace template variables with dynamic values xbuf_repl(reply, "<!--form-->", post_form); xbuf_repl(reply, "<!--title-->", thread->title.ptr); xbuf_repl(reply, "<!--id-->", id); //for each post, render its template and insert it into reply kv_do(&thread->posts, 0, 0, (kv_proc_t)&list_posts, (void*)reply); } break; //---------------------------------------------------------------------- //create a thread------------------------------------------------------- case HTTP_POST: { Thread *thread = calloc(1, sizeof(*thread)); xbuf_init(&thread->title); kv_init(&thread->posts, "posts", 1024, 0, 0, 0); thread->id = forum_store->nbr_items + 1; xbuf_cat(&thread->title, *title ? title : " "); //add thread to KV store kv_add(forum_store, &(kv_item) { .key = (char*)&thread->id, .klen = sizeof(thread->id), .val = (char*)thread, .flags = 0, }); http->h_method = HTTP_GET; *act = 0; goto redirect; } break; //---------------------------------------------------------------------- } } break;
// ---------------------------------------------------------------------------- // imported functions: // get_reply(): get a pointer on the 'reply' dynamic buffer from the server // getus(): get current time in microseconds (1 millisecond = 1,000 us) // get_env(): get connection's 'environment' variables from the server // xbuf_cat(): like strcat(), but it works in the specified dynamic buffer // gif_build(): build an in-memory GIF image from a bitmap and palette // ---------------------------------------------------------------------------- int main(int argc, char *argv[]) { // ------------------------------------------------------------------------- // get a pointer on the server reply // ------------------------------------------------------------------------- xbuf_t *reply = get_reply(argv); // ------------------------------------------------------------------------- // allocate memory for a raw bitmap // ------------------------------------------------------------------------- int w = 800, h = 800, nbcolors = 256, wXh = w * h; u8 *bmp = (u8*)malloc(wXh); if(!bmp) return 503; // service unavailable // ------------------------------------------------------------------------- // render the Mandelbrot set in our bitmap // ------------------------------------------------------------------------- fractals(bmp, w, h, nbcolors); // ------------------------------------------------------------------------- // display the palette (useful when playing with 'tabcol[]' values) // ------------------------------------------------------------------------- { #define ROUND(a) ((a) > 0 ? (int)((a)+0.5) : -(int)(0.5-(a))) u8 *p = bmp; int i = h, wd20 = w / 20; float color = 0, col = (float)nbcolors / (float)h; while(i--) { color += col; memset(p, ROUND(color) & 255, wd20); p += w; } } // ------------------------------------------------------------------------- // build a smooth multi-gradient color palette from the fixed values below // ------------------------------------------------------------------------- static rgb_t tabcol[]={ { 0, 0, 128}, // Med. Blue { 0, 100, 200}, // Light Blue {100, 160, 160}, // Cyan { 0, 220, 100}, // Green {255, 255, 0}, // Yellow {255, 128, 0}, // Orange {128, 0, 0}, // Med. Red { 64, 0, 0}, // Dark Red {128, 0, 0}, // Med. Red {255, 128, 0}, // Orange {255, 255, 0}, // Yellow { 0, 220, 100}, // Green {100, 160, 160}, // Cyan { 0, 100, 200}, // Light Blue { 0, 0, 128}, // Med. Blue { 64, 0, 0}, // Dark Red {128, 0, 0}, // Med. Red {255, 128, 0}, // Orange {255, 255, 0}, // Yellow { 0, 220, 100}, // Green {100, 160, 160}, // Cyan { 0, 100, 200}, // Light Blue { 0, 0, 128}, // Med. Blue { 0, 0, 64}, // Dark Blue }, *tab = tabcol; // ------------------------------------------------------------------------- // just for fun, select different colors for each call // ------------------------------------------------------------------------- static u32 call = 0; u32 ncols = sizeof(tabcol) / sizeof(rgb_t); switch(call) { case 0: tab = tabcol; ncols = 10; break; // blue case 1: tab = &tabcol[ 4]; ncols = 10; break; // yellow case 2: tab = &tabcol[ 7]; ncols = 7; break; // dark red case 3: tab = &tabcol[ 1]; ncols = 16; break; // rainbow - } call = (call + 1) & 3; // generate the palette with our defined gradient steps u8 pal[768]; dr_gradient(pal, nbcolors, tab, ncols); // nice palete but we want a black body to delimit the mandelbrot set memset(pal + ((nbcolors - (nbcolors / 16)) * 3), 0, (nbcolors / 16) * 3); // ------------------------------------------------------------------------- // create custom HTTP response headers to send a GIF file // ------------------------------------------------------------------------- // (G-WAN automatically generates headers if none are provided but it can't // guess all MIME types so this automatic feature is for 'text/html' only // ...unless you explicitly specify the reply buffer MIME type) #ifdef BUILD_CUSTOM_HEADERS // old way of doing things // get the current HTTP date (like "Wed, 02 Jun 2010 06:49:37 GMT") u8 *date = (u8*)get_env(argv, SERVER_DATE); xbuf_xcat(reply, "HTTP/1.1 200 OK\r\n" "Date: %s\r\n" "Last-Modified: %s\r\n" "Content-type: image/gif\r\n" "Content-Length: \r\n" // make room for the for GIF length "Connection: close\r\n\r\n", date, date); // ------------------------------------------------------------------------- // make sure that we have enough space in the 'reply' buffer // (we are going to fill it directly from gif_build(), not via xbuf_xxx) // ------------------------------------------------------------------------- // (if we have not enough memory, we will get a 'graceful' crash) if(reply->allocated < (wXh / 10)) // very gross approximation { if(!xbuf_growto(reply, wXh / 10)) // resize reply { xbuf_init(reply); xbuf_ncat(reply, " ", 1); reply->len = 0; // discart pointless data, keep allocated memory return 503; // error: we could not allocate enough memory } } // ------------------------------------------------------------------------- // save the place where to patch the void 'Content-Length' HTTP Header // ------------------------------------------------------------------------- char *p = reply->ptr + reply->len - (sizeof("\r\nConnection: close\r\n\r\n") - 1); // ------------------------------------------------------------------------- // append a GIF image (-1:no transparency, 0: no comment) to 'reply' // ------------------------------------------------------------------------- int len = gif_build((u8*)(reply->ptr + reply->len), bmp, w, h, pal, nbcolors, -1, 0); if(len < 0) len = 0; // (len == -1) if gif_build() failed reply->len += len; // add the GIF size to the 'reply' buffer length free(bmp); // ------------------------------------------------------------------------- // store the GIF size in the empty space of the 'Content-Length' header // ------------------------------------------------------------------------- u32toa(p, len); #else // #ifdef BUILD_CUSTOM_HEADERS // works with any supported MIME type // ------------------------------------------------------------------------- // specify a MIME type so we don't have to build custom HTTP headers // ------------------------------------------------------------------------- char *mime = (char*)get_env(argv, REPLY_MIME_TYPE); // note that we setup the FILE EXTENTION, not the MIME type: mime[0] = '.'; mime[1] = 'g'; mime[2] = 'i'; mime[3] = 'f'; mime[4] = 0; // ------------------------------------------------------------------------- // make sure that we have enough space in the 'reply' buffer // (we are going to fill it directly from gif_build(), not via xbuf_xxx) // ------------------------------------------------------------------------- // (if we have not enough memory, we will get a 'graceful' crash) if(reply->allocated < (wXh / 10)) // very gross approximation { if(!xbuf_growto(reply, wXh / 10)) // resize reply { xbuf_init(reply); xbuf_ncat(reply, " ", 1); reply->len = 0; // discart pointless data, keep allocated memory return 503; // error: we could not allocate enough memory } } // ------------------------------------------------------------------------- // append a GIF image (-1:no transparency, 0: no comment) to 'reply' // ------------------------------------------------------------------------- int len = gif_build((u8*)(reply->ptr + reply->len), bmp, w, h, pal, nbcolors, -1, 0); if(len < 0) len = 0; // (len == -1) if gif_build() failed reply->len += len; // add the GIF size to the 'reply' buffer length free(bmp); #endif // #else #ifdef BUILD_CUSTOM_HEADERS return 200; // return an HTTP code (200:'OK') }