/* lightuserdata pattern string format "ixrsmb" integer size */ static int _pattern_pack(lua_State *L) { struct pbc_pattern * pat = lua_touserdata(L,1); size_t format_sz = 0; const char * format = lua_tolstring(L,2,&format_sz); int size = lua_tointeger(L,3); char data[size]; memset(data, 0 ,size); char * ptr = data; int i; for (i=0;i<format_sz;i++) { if (format[i] >= 'a' && format[i] <='z') { ptr = _get_value(L, 4+i, ptr, format[i]); } else { if (!lua_istable(L,4+i)) { luaL_error(L,"need table for array type"); } int j; int n = lua_rawlen(L,4+i); for (j=0;j<n;j++) { lua_rawgeti(L,4+i,j); _get_array_value(L,(void *)ptr,format[i]); lua_pop(L,1); } ptr += sizeof(pbc_array); } } luaL_Buffer b; luaL_buffinit(L, &b); int cap = 128; do { char * temp = luaL_prepbuffsize(&b , cap); struct pbc_slice slice; slice.buffer = temp; slice.len = cap; int ret = pbc_pattern_pack(pat, data, &slice); if (ret < 0) { cap = cap * 2; _Free(temp); continue; } luaL_addsize(&b , slice.len); } while (0); luaL_pushresult(&b); pbc_pattern_close_arrays(pat, data); return 1; }
/* lightuserdata pattern string format "ixrsmbp" integer size */ static int _pattern_pack(lua_State *L) { struct pbc_pattern * pat = (struct pbc_pattern *)checkuserdata(L,1); if (pat == NULL) { return luaL_error(L, "pack pattern is NULL"); } size_t format_sz = 0; const char * format = lua_tolstring(L,2,&format_sz); int size = lua_tointeger(L,3); char * data = (char *)alloca(size); // A trick , we don't need default value. zero buffer for array and message field. // pbc_pattern_set_default(pat, data); memset(data, 0 , size); char * ptr = data; int i; for (i=0;i<format_sz;i++) { if (format[i] >= 'a' && format[i] <='z') { ptr = _get_value(L, 4+i, ptr, format[i]); } else { if (!lua_istable(L,4+i)) { luaL_error(L,"need table for array type"); } int j; int n = lua_rawlen(L,4+i); for (j=0;j<n;j++) { lua_rawgeti(L,4+i,j+1); _get_array_value(L,(struct _pbc_array *)ptr,format[i]); lua_pop(L,1); } ptr += sizeof(pbc_array); } } luaL_Buffer b; luaL_buffinit(L, &b); int cap = 128; for (;;) { char * temp = (char *)luaL_prepbuffsize(&b , cap); struct pbc_slice slice; slice.buffer = temp; slice.len = cap; int ret = pbc_pattern_pack(pat, data, &slice); if (ret < 0) { cap = cap * 2; continue; } luaL_addsize(&b , slice.len); break; } luaL_pushresult(&b); pbc_pattern_close_arrays(pat, data); return 1; }