| 291 | |
| 292 | |
| 293 | void luaV_concat (lua_State *L, int total) { |
| 294 | lua_assert(total >= 2); |
| 295 | do { |
| 296 | StkId top = L->top; |
| 297 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
| 298 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { |
| 299 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) |
| 300 | luaG_concaterror(L, top-2, top-1); |
| 301 | } |
| 302 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ |
| 303 | (void)tostring(L, top - 2); /* result is first operand */ |
| 304 | else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { |
| 305 | setobjs2s(L, top - 2, top - 1); /* result is second op. */ |
| 306 | } |
| 307 | else { |
| 308 | /* at least two non-empty string values; get as many as possible */ |
| 309 | size_t tl = tsvalue(top-1)->len; |
| 310 | char *buffer; |
| 311 | int i; |
| 312 | /* collect total length */ |
| 313 | for (i = 1; i < total && tostring(L, top-i-1); i++) { |
| 314 | size_t l = tsvalue(top-i-1)->len; |
| 315 | if (l >= (MAX_SIZET/sizeof(char)) - tl) |
| 316 | luaG_runerror(L, "string length overflow"); |
| 317 | tl += l; |
| 318 | } |
| 319 | buffer = luaZ_openspace(L, &G(L)->buff, tl); |
| 320 | tl = 0; |
| 321 | n = i; |
| 322 | do { /* concat all strings */ |
| 323 | size_t l = tsvalue(top-i)->len; |
| 324 | memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); |
| 325 | tl += l; |
| 326 | } while (--i > 0); |
| 327 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); |
| 328 | } |
| 329 | total -= n-1; /* got 'n' strings to create 1 new */ |
| 330 | L->top -= n-1; /* popped 'n' strings and pushed one */ |
| 331 | } while (total > 1); /* repeat until only 1 result left */ |
| 332 | } |
| 333 | |
| 334 | |
| 335 | void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { |
no test coverage detected