/* | Converts a relative directory path to an absolute. | | Params on Lua stack: | 1: a relative path to directory | | Returns on Lua stack: | The absolute path of directory */ static int l_realdir( lua_State *L ) { luaL_Buffer b; const char *rdir = luaL_checkstring(L, 1); char *adir = get_realpath(rdir); if (!adir) { printlogf(L, "Error", "failure getting absolute path of [%s]", rdir); return 0; } { // makes sure its a directory struct stat st; if (stat(adir, &st)) { printlogf(L, "Error", "cannot get absolute path of dir '%s': %s", rdir, strerror(errno)); free(adir); return 0; } if (!S_ISDIR(st.st_mode)) { printlogf(L, "Error", "cannot get absolute path of dir '%s': is not a directory", rdir); free(adir); return 0; } } // returns absolute path with a concated '/' luaL_buffinit(L, &b); luaL_addstring(&b, adir); luaL_addchar(&b, '/'); luaL_pushresult(&b); free(adir); return 1; }
static int str_concat(lua_State * L) { luaL_Buffer b; size_t lsep; const char *sep = luaL_optlstring(L, 2, "", &lsep); int i = luaL_optint(L, 3, 1); int n = luaL_optint(L, 4, 0); luaL_checktype(L, 1, LUA_TTABLE); if (n == 0) n = luaL_getn(L, 1); luaL_buffinit(L, &b); for (; i <= n; i++) { lua_rawgeti(L, 1, i); luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings"); luaL_addvalue(&b); if (i != n) luaL_addlstring(&b, sep, lsep); } luaL_pushresult(&b); return 1; }
/* Rockbox already defines read_line() */ static int _read_line (lua_State *L, FILE *f, int chop) { luaL_Buffer b; luaL_buffinit(L, &b); for (;;) { size_t l; size_t r; char *p = luaL_prepbuffer(&b); r = rb->read_line((int)f, p, LUAL_BUFFERSIZE); l = strlen(p); if (l == 0 || p[l-1] != '\n') luaL_addsize(&b, l); else { luaL_addsize(&b, l - chop); /* chop 'eol' if needed */ luaL_pushresult(&b); /* close buffer */ return 1; /* read at least an `eol' */ } if (r < LUAL_BUFFERSIZE) { /* eof? */ luaL_pushresult(&b); /* close buffer */ return (lua_rawlen(L, -1) > 0); /* check whether read something */ } } }
static int lz_read_line(lua_State *L, lz_stream *s) { luaL_Buffer b; size_t l = 0, n; luaL_buffinit(L, &b); if (s->o_buffer_len > 0 || !s->eos) do { char *p = s->o_buffer; size_t len = s->o_buffer_len; /* find newline in output buffer */ for (n = 0; n < len; ++n, ++p) { if (*p == '\n' || *p == '\r') { int eat_nl = *p == '\r'; luaL_addlstring(&b, s->o_buffer, n); lzstream_remove(s, n+1); l += n; if (eat_nl && lzstream_inflate_block(L, s)) { if (s->o_buffer_len > 0 && *s->o_buffer == '\n') { lzstream_remove(s, 1); } } luaL_pushresult(&b); return 1; } } if (len > 0) { luaL_addlstring(&b, s->o_buffer, len); lzstream_remove(s, len); l += len; } } while (lzstream_inflate_block(L, s)); luaL_pushresult(&b); return l > 0 || !s->eos || s->o_buffer_len > 0; }
static int str_gsub (lua_State *L) { size_t srcl; const char *src = luaL_checklstring(L, 1, &srcl); const char *p = luaL_checkstring(L, 2); int tr = lua_type(L, 3); int max_s = luaL_optint(L, 4, srcl+1); int anchor = (*p == '^') ? (p++, 1) : 0; int n = 0; MatchState ms; luaL_Buffer b; luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || tr == LUA_TFUNCTION || tr == LUA_TTABLE || tr == LUA_TLIGHTFUNCTION, 3, "string/function/table/lightfunction expected"); luaL_buffinit(L, &b); ms.L = L; ms.src_init = src; ms.src_end = src+srcl; while (n < max_s) { const char *e; ms.level = 0; e = match(&ms, src, p); if (e) { n++; add_value(&ms, &b, src, e); } if (e && e>src) /* non empty match? */ src = e; /* skip it */ else if (src < ms.src_end) luaL_addchar(&b, *src++); else break; if (anchor) break; } luaL_addlstring(&b, src, ms.src_end-src); luaL_pushresult(&b); lua_pushinteger(L, n); /* number of substitutions */ return 2; }
/* pops a string s from the top of the stack and calls mf(t) for pieces t of * s separated by newlines */ static void luaV_msgfunc(lua_State *L, msgfunc_T mf) { luaL_Buffer b; size_t l; const char *p, *s = lua_tolstring(L, -1, &l); luaL_buffinit(L, &b); luaV_addlstring(&b, s, l, 0); luaL_pushresult(&b); /* break string */ p = s = lua_tolstring(L, -1, &l); while (l--) { if (*p++ == '\0') /* break? */ { mf((char_u *) s); s = p; } } mf((char_u *) s); lua_pop(L, 2); /* original and modified strings */ }
/*-------------------------------------------------------------------------*\ * object:receive() interface \*-------------------------------------------------------------------------*/ int buffer_meth_receive(lua_State *L, p_buffer buf) { int err = IO_DONE, top = lua_gettop(L); luaL_Buffer b; size_t size; const char *part = luaL_optlstring(L, 3, "", &size); p_timeout tm = timeout_markstart(buf->tm); /* initialize buffer with optional extra prefix * (useful for concatenating previous partial results) */ luaL_buffinit(L, &b); luaL_addlstring(&b, part, size); /* receive new patterns */ if (!lua_isnumber(L, 2)) { const char *p= luaL_optstring(L, 2, "*l"); if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); else luaL_argcheck(L, 0, 2, "invalid receive pattern"); /* get a fixed number of bytes (minus what was already partially * received) */ } else err = recvraw(buf, (size_t) lua_tonumber(L, 2)-size, &b); /* check if there was an error */ if (err != IO_DONE) { /* we can't push anyting in the stack before pushing the * contents of the buffer. this is the reason for the complication */ luaL_pushresult(&b); lua_pushstring(L, buf->io->error(buf->io->ctx, err)); lua_pushvalue(L, -2); lua_pushnil(L); lua_replace(L, -4); } else { luaL_pushresult(&b); lua_pushnil(L); lua_pushnil(L); } #ifdef BUFFER_DEBUG /* push time elapsed during operation as the last return value */ lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm)); #endif return lua_gettop(L) - top; }
/** * @param: the values (0, 1 or more) * @return: the string */ static int l_temp_repr(lua_State *L, lua_CFunction slice_fn) { if (lua_isnone(L, 1)) { /* no argument, returns empty string */ lua_pushliteral(L, ""); } else if (lua_isnone(L, 2)) { /* single argument, no tuple, directly call repr_slice() with an empty * table */ lua_newtable(L); slice_fn(L); } else { /* multiple argument */ /* argc must be saved because luaL_Buffer will use stack */ int argc = lua_gettop(L)+1; lua_newtable(L); /* save a new table at stack argc */ /* buffer starts here */ luaL_Buffer b; luaL_buffinit(L, &b); for (int i=1; i<argc; i++) { /* from the next element of tuple, add ", " */ if (i != 1) { luaL_addstring(&b, ", "); } /* call repr_slice with standard lua call interface * so that the stack are balanced for luaL_Buffer */ lua_pushcfunction(L, slice_fn); lua_pushvalue(L, i); lua_pushvalue(L, argc); lua_call(L, 2, 1); luaL_addvalue(&b); } luaL_pushresult(&b); /* buffer ends here */ } /* repr() should always return a string */ return 1; }
static const char* luv_thread_dumped(lua_State* L, int idx, size_t* l) { if (lua_isstring(L, idx)) { return lua_tolstring(L, idx, l); } else { const char* buff = NULL; int top = lua_gettop(L); luaL_Buffer b; int test_lua_dump; luaL_checktype(L, idx, LUA_TFUNCTION); lua_pushvalue(L, idx); luaL_buffinit(L, &b); test_lua_dump = (lua_dump(L, thread_dump, &b, 1) == 0); if (test_lua_dump) { luaL_pushresult(&b); buff = lua_tolstring(L, -1, l); } else luaL_error(L, "Error: unable to dump given function"); lua_settop(L, top); return buff; } }
/* ** Fails with error message from ODBC ** Inputs: ** type: type of handle used in operation ** handle: handle used in operation */ static int fail(lua_State *L, const SQLSMALLINT type, const SQLHANDLE handle) { SQLCHAR State[6]; SQLINTEGER NativeError; SQLSMALLINT MsgSize, i; SQLRETURN ret; SQLCHAR Msg[SQL_MAX_MESSAGE_LENGTH]; luaL_Buffer b; lua_pushnil(L); luaL_buffinit(L, &b); i = 1; while (1) { ret = SQLGetDiagRec(type, handle, i, State, &NativeError, Msg, sizeof(Msg), &MsgSize); if (ret == SQL_NO_DATA) break; luaL_addlstring(&b, (char*)Msg, MsgSize); luaL_addchar(&b, '\n'); i++; } luaL_pushresult(&b); return 2; }
static void read_all (lua_State *L, FILE *f) { size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ l_seeknum old, nrlen = 0; /* for testing file size */ luaL_Buffer b; luaL_buffinit(L, &b); /* speed up loading of not too large files: */ old = l_ftell(f); if ((l_fseek(f, 0, SEEK_END) >= 0) && ((nrlen = l_ftell(f)) > 0) && nrlen < 1000 * 1000 * 100) { rlen = nrlen; } l_fseek(f, old, SEEK_SET); for (;;) { char *p = luaL_prepbuffsize(&b, rlen); size_t nr = fread(p, sizeof(char), rlen, f); luaL_addsize(&b, nr); if (nr < rlen) break; /* eof? */ else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ rlen *= 2; /* double buffer size at each iteration */ } luaL_pushresult(&b); /* close buffer */ }
static int Ldecode(lua_State *L) /** decode(s) */ { size_t l; const char *s=luaL_checklstring(L,1,&l); luaL_Buffer b; int n=0; char t[4]; luaL_buffinit(L,&b); for (;;) { int c=*s++; switch (c) { const char *p; default: p=strchr(code,c); if (p==NULL) return 0; t[n++]= p-code; if (n==4) { decode(&b,t[0],t[1],t[2],t[3],4); n=0; } break; case '=': switch (n) { case 1: decode(&b,t[0],0,0,0,1); break; case 2: decode(&b,t[0],t[1],0,0,2); break; case 3: decode(&b,t[0],t[1],t[2],0,3); break; } case 0: luaL_pushresult(&b); return 1; case '\n': case '\r': case '\t': case ' ': case '\f': case '\b': break; } } return 0; }
static int str_gsub(lua_State * L) { size_t srcl; const char *src = luaL_checklstring(L, 1, &srcl); const char *p = luaL_checkstring(L, 2); int max_s = luaL_optint(L, 4, srcl + 1); int anchor = (*p == '^') ? (p++, 1) : 0; int n = 0; MatchState ms; luaL_Buffer b; luaL_argcheck(L, lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), 3, "string or function expected"); luaL_buffinit(L, &b); ms.L = L; ms.src_init = src; ms.src_end = src + srcl; while (n < max_s) { const char *e; ms.level = 0; e = match(&ms, src, p); if (e) { n++; add_s(&ms, &b, src, e); } if (e && e > src) /* non empty match? */ src = e; /* skip it */ else if (src < ms.src_end) luaL_putchar(&b, *src++); else break; if (anchor) break; } luaL_addlstring(&b, src, ms.src_end - src); luaL_pushresult(&b); lua_pushnumber(L, (lua_Number) n); /* number of substitutions */ return 2; }
static void Xml_pushDecode(lua_State* L, const char* s, size_t s_size) { luaL_Buffer b; const char* found = strstr(s, "&#"); size_t start=0, pos, i; if(!s_size) s_size=strlen(s); luaL_buffinit(L, &b); found = strstr(s, "&#"); pos = found ? found-s : s_size; while(found) { char ch = 0; size_t i=0; for(found += 2; i<3; ++i, ++found) if(isdigit(*found)) ch = ch * 10 + (*found - 48); else break; if(*found == ';') { if(pos>start) luaL_addlstring(&b, s+start, pos-start); luaL_addchar(&b, ch); start = pos + 3 + i; } found = strstr(found+1, "&#"); pos = found ? found-s : s_size; } if(pos>start) luaL_addlstring(&b,s+start, pos-start); luaL_pushresult(&b); for(i=sv_code_size-1; i<sv_code_size; i-=2) { luaL_gsub(L, lua_tostring(L,-1), sv_code[i], sv_code[i-1]); lua_remove(L,-2); } }
//------------------------------------------------------------- static int file_g_read( lua_State* L, int n, int16_t end_char ) { if(n< 0 || n>LUAL_BUFFERSIZE) n = LUAL_BUFFERSIZE; if(end_char < 0 || end_char >255) end_char = EOF; int ec = (int)end_char; static luaL_Buffer b; if(FILE_NOT_OPENED==file_fd) return luaL_error(L, "open a file first"); luaL_buffinit(L, &b); char *p = luaL_prepbuffer(&b); int c = EOF; int i = 0; do{ c = EOF; SPIFFS_read(&fs, (spiffs_file)file_fd, &c, 1); if(c==EOF)break; p[i++] = (char)(0xFF & c); }while((c!=EOF) && ((char)c !=(char)ec) && (i<n) ); #if 0 if(i>0 && p[i-1] == '\n') i--; /* do not include `eol' */ #endif if(i==0){ luaL_pushresult(&b); /* close buffer */ return (lua_objlen(L, -1) > 0); /* check whether read something */ } luaL_addsize(&b, i); luaL_pushresult(&b); /* close buffer */ return 1; /* read at least an `eol' */ }
static void pop_lstring(lua_State *L, struct socket_buffer *sb, int sz, int skip) { struct buffer_node * current = sb->head; if (sz < current->sz - sb->offset) { lua_pushlstring(L, current->msg + sb->offset, sz-skip); sb->offset+=sz; return; } if (sz == current->sz - sb->offset) { lua_pushlstring(L, current->msg + sb->offset, sz-skip); return_free_node(L,2,sb); return; } luaL_Buffer b; luaL_buffinit(L, &b); for (;;) { int bytes = current->sz - sb->offset; if (bytes >= sz) { if (sz > skip) { luaL_addlstring(&b, current->msg + sb->offset, sz - skip); } sb->offset += sz; if (bytes == sz) { return_free_node(L,2,sb); } break; } luaL_addlstring(&b, current->msg + sb->offset, (sz - skip < bytes) ? sz - skip : bytes); return_free_node(L,2,sb); sz-=bytes; if (sz==0) break; current = sb->head; assert(current); } luaL_pushresult(&b); }
static int decompress_to_buffer(lua_State *L, bz_userdata *ud) { luaL_Buffer B; luaL_buffinit(L, &B); do { ud->z.next_out = luaL_prepbuffer(&B); ud->z.avail_out = LUAL_BUFFERSIZE; ud->status = BZ2_bzDecompress(&ud->z); if (ud->status != BZ_OK && ud->status != BZ_STREAM_END) break; luaL_addsize(&B, LUAL_BUFFERSIZE - ud->z.avail_out); } while (ud->z.avail_out == 0); if (ud->status == BZ_OK && ud->z.avail_in != 0) return luaL_error(L, "unknown failure in bzDecompress"); /* if (ud->status == BZ_STREAM_END && ud->z.avail_in != 0) return luaL_error(L, "unhandled trailing data in bzip2 stream"); */ luaL_pushresult(&B); return 1; }
static int l_decrypt(lua_State *L) { size_t keyLen, dataLen, outLen, hexDataLen; const char *key = luaL_checklstring(L, 1, &keyLen); const char *hexData = luaL_checklstring(L, 2, &hexDataLen); dataLen = hexDataLen/2; char data[dataLen]; convert_from_hex(hexData, data, dataLen); char decryptBuffer[dataLen]; int res = decrypt_str(decryptBuffer, data, dataLen, key, &outLen); if (res != 1) return luaL_error(L, "Error decrypting value %d, data:%s, dataLen: %d", res, data, dataLen); luaL_Buffer b; luaL_buffinit(L, &b); luaL_addlstring(&b, decryptBuffer, outLen); luaL_pushresult(&b); return 1; }
static int utils_tohex (lua_State *L) { unsigned char buf [3]; // we'll push data into a Lua string buffer luaL_Buffer buffer; // get text to convert size_t textLength; size_t i; const unsigned char * text = luaL_checklstring (L, 1, &textLength); // initialize buffer luaL_buffinit(L, &buffer); for (i = 0; i < textLength; i++) { sprintf (buf, "%02X", text [i]); luaL_addlstring(&buffer, buf, 2); } luaL_pushresult(&buffer); return 1; // number of result fields } // end of utils_tohex
static int Puname(lua_State *L) /** uname([string]) */ { struct utsname u; luaL_Buffer b; const char *s; if (uname(&u) == -1) return pusherror(L, NULL); luaL_buffinit(L, &b); for (s=luaL_optstring(L, 1, "%s %n %r %v %m"); *s; s++) if (*s!='%') luaL_putchar(&b, *s); else switch (*++s) { case '%': luaL_putchar(&b, *s); break; case 'm': luaL_addstring(&b,u.machine); break; case 'n': luaL_addstring(&b,u.nodename); break; case 'r': luaL_addstring(&b,u.release); break; case 's': luaL_addstring(&b,u.sysname); break; case 'v': luaL_addstring(&b,u.version); break; default: badoption(L, 2, "format", *s); break; } luaL_pushresult(&b); return 1; }
int Xml_encode(lua_State *L) { if(lua_gettop(L)!=1) return 0; luaL_checkstring(L,-1); size_t i; for(i=0; i<sv_code_size; i+=2) { luaL_gsub(L, lua_tostring(L,-1), sv_code[i], sv_code[i+1]); lua_remove(L,-2); } char buf[8]; const char* s=lua_tostring(L,1); size_t start, pos; luaL_Buffer b; luaL_buffinit(L, &b); for(start=pos=0; s[pos]!=0; ++pos) if(s[pos]<0) { if(pos>start) luaL_addlstring(&b,s+start, pos-start); luaL_addstring(&b,char2code((unsigned char)(s[pos]),buf)); start=pos+1; } if(pos>start) luaL_addlstring(&b,s+start, pos-start); luaL_pushresult(&b); lua_remove(L,-2); return 1; }
static int llog_print(lua_State *L, logging::level lv) { logging::logger* lg = logging::get(L); if (!lg) { return 0; } int n = lua_gettop(L); luaL_Buffer b; luaL_buffinit(L, &b); for (int i = 1; i <= n; i++) { size_t l; const char* s = lua_tolstring(L, i, &l); if (s == NULL) return luaL_error(L, "'tostring' must return a string to 'print'"); if (i>1) luaL_addchar(&b, '\t'); luaL_addlstring(&b, s, l); } luaL_pushresult(&b); size_t l; const char *s = lua_tolstring(L, -1, &l); LOGGING_STREAM(*lg, lv) << std::string(s, l); return 0; }
static int File_read_chars(lua_State *L, FILE_T ft, size_t n) { size_t rlen; /* how much to read */ size_t nr; /* number of chars actually read */ int nri; /* temp number of chars read, as an int to handle -1 errors */ gchar buff[WSLUA_BUFFERSIZE]; /* for file_read to write to, and we push into Lua */ luaL_Buffer b; rlen = WSLUA_BUFFERSIZE; /* try to read that much each time */ luaL_buffinit(L, &b); /* initialize Lua buffer */ do { if (rlen > n) rlen = n; /* cannot read more than asked */ nri = file_read(buff, (unsigned int)rlen, ft); if (nri < 1) break; nr = (size_t) nri; luaL_addlstring(&b, buff, nr); n -= nr; /* still have to read `n' chars */ } while (n > 0 && nr == rlen); /* until end of count or eof */ luaL_pushresult(&b); /* close buffer */ return (n == 0 || lua_rawlen(L, -1) > 0); }
LB_API int lbind_pushmask(lua_State *L, int evalue, lbind_Enum *et) { luaL_Buffer b; lbind_EnumItem *items; int first = 1; unsigned value = lbind_checkmask(L, 2, et); if (et->items == NULL) { lua_pushliteral(L, ""); return 0; } luaL_buffinit(L, &b); for (items = et->items; items->name != NULL; ++items) { if ((items->value & value) == value) { if (first) first = 0; else luaL_addchar(&b, ' '); luaL_addstring(&b, items->name); value &= ~items->value; } } luaL_pushresult(&b); return 1; }
static int read_chars(lua_State *L, FILE *f, size_t n) { size_t rlen; /* how much to read */ size_t nr; /* number of chars actually read */ luaL_Buffer b; luaL_buffinit(L, &b); rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ do { char *p = luaL_prepbuffer(&b); if(rlen > n) rlen = n; /* cannot read more than asked */ nr = fread(p, sizeof(char), rlen, f); luaL_addsize(&b, nr); n -= nr; /* still have to read `n' chars */ } while(n > 0 && nr == rlen); /* until end of count or eof */ luaL_pushresult(&b); /* close buffer */ return (n == 0 || lua_objlen(L, -1) > 0); }
static int tostring(lua_State *L) { static char hex[16] = "0123456789ABCDEF"; uintptr_t n = (uintptr_t)lua_touserdata(L,1); if (lua_gettop(L) == 1) { luaL_Buffer b; luaL_buffinit(L , &b); luaL_addstring(&b, "int64: 0x"); int i; bool strip = true; for (i=15;i>=0;i--) { int c = (n >> (i*4)) & 0xf; if (strip && c ==0) { continue; } strip = false; luaL_addchar(&b, hex[c]); } if (strip) { luaL_addchar(&b , '0'); } luaL_pushresult(&b); } else {
/* * Fetches a string column. */ void read_string (lua_State *L, mysql_rec *m, int i) { luaL_Buffer b; unsigned long length, offset, count; luaL_buffinit(L, &b); length = m->lengths[i]; offset = 0; m->bind[i].buffer_length = LUAL_BUFFERSIZE; while (offset < length) { m->bind[i].buffer = luaL_prepbuffer(&b); if (mysql_stmt_fetch_column(m->stmt, &m->bind[i], i, offset) != 0) { error(L, m); } count = length - offset; if (count > LUAL_BUFFERSIZE) { count = LUAL_BUFFERSIZE; } luaL_addsize(&b, count); offset += count; } luaL_pushresult(&b); }
static int lmz_compress(lua_State *L, int start, lmz_Comp *c, int flush) { size_t len, offset = 0, output = 0; const char *s = luaL_checklstring(L, start, &len); luaL_Buffer b; luaL_buffinit(L, &b); for (;;) { size_t in_size = len - offset; size_t out_size = LUAL_BUFFERSIZE; tdefl_status status = tdefl_compress(c, s + offset, &in_size, (mz_uint8*)luaL_prepbuffer(&b), &out_size, flush); offset += in_size; output += out_size; luaL_addsize(&b, out_size); if (offset == len || status == TDEFL_STATUS_DONE) { luaL_pushresult(&b); lua_pushboolean(L, status == TDEFL_STATUS_DONE); lua_pushinteger(L, len); lua_pushinteger(L, output); return 4; } else if (status != TDEFL_STATUS_OKAY) luaL_error(L, "compress failure (%d)", status); } }
static int b64_encode_tbl(lua_State *L, const char *tbl) { size_t len, n = 0; const unsigned char *src = (const unsigned char *)luaL_checklstring(L, 1, &len); luaL_Buffer dst; unsigned int triplet = 0; unsigned int pad; char s[4]; luaL_buffinit(L, &dst); while (n < len) { triplet = (triplet << 8) | *src++; pad = 2 - (n % 3); n++; if (pad == 0) { s[0] = tbl[(triplet >> (3*6))]; s[1] = tbl[(triplet >> (2*6)) & 63]; s[2] = tbl[(triplet >> 6) & 63]; s[3] = tbl[triplet & 63]; luaL_addlstring(&dst, s, 4); triplet = 0; } }
static int str_gsub (lua_State *L) { size_t srcl, lp; const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ const char *lastmatch = NULL; /* end of last match */ int tr = lua_type(L, 3); /* replacement type */ lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ int anchor = (*p == '^'); lua_Integer n = 0; /* replacement count */ MatchState ms; luaL_Buffer b; luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, "string/function/table expected"); luaL_buffinit(L, &b); if (anchor) { p++; lp--; /* skip anchor character */ } prepstate(&ms, L, src, srcl, p, lp); while (n < max_s) { const char *e; reprepstate(&ms); /* (re)prepare state for new match */ if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */ n++; add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ src = lastmatch = e; } else if (src < ms.src_end) /* otherwise, skip one character */ luaL_addchar(&b, *src++); else break; /* end of subject */ if (anchor) break; } luaL_addlstring(&b, src, ms.src_end-src); luaL_pushresult(&b); lua_pushinteger(L, n); /* number of substitutions */ return 2; }