aboutsummaryrefslogtreecommitdiff
path: root/lstrlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-10-17 07:55:28 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-10-17 07:55:28 -0300
commitc172a4f7c2d452035f9cbb4285f2e6761ab7a68b (patch)
treeb89c21784842759f91664787258576bcf3e32a31 /lstrlib.c
parentf8e0d33b25bcff35a40b1f7493fc660b435119d9 (diff)
downloadlua-c172a4f7c2d452035f9cbb4285f2e6761ab7a68b.tar.gz
lua-c172a4f7c2d452035f9cbb4285f2e6761ab7a68b.tar.bz2
lua-c172a4f7c2d452035f9cbb4285f2e6761ab7a68b.zip
'dumpint' and related functions replaced by 'string.pack'/'string.unpack'
Diffstat (limited to 'lstrlib.c')
-rw-r--r--lstrlib.c497
1 files changed, 340 insertions, 157 deletions
diff --git a/lstrlib.c b/lstrlib.c
index eb40995f..dfb1f8c1 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.201 2014/08/20 22:06:41 roberto Exp roberto $ 2** $Id: lstrlib.c,v 1.202 2014/10/01 11:54:56 roberto Exp roberto $
3** Standard library for string operations and pattern-matching 3** Standard library for string operations and pattern-matching
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -950,214 +950,399 @@ static int str_format (lua_State *L) {
950*/ 950*/
951 951
952 952
953/* maximum size for the binary representation of an integer */
954#define MAXINTSIZE 16
955
953/* number of bits in a character */ 956/* number of bits in a character */
954#define NB CHAR_BIT 957#define NB CHAR_BIT
955 958
956/* mask for one character (NB 1's) */ 959/* mask for one character (NB 1's) */
957#define MC ((1 << NB) - 1) 960#define MC ((1 << NB) - 1)
958 961
959/* mask for one character without sign bit ((NB - 1) 1's) */
960#define SM (MC >> 1)
961
962/* size of a lua_Integer */ 962/* size of a lua_Integer */
963#define SZINT ((int)sizeof(lua_Integer)) 963#define SZINT ((int)sizeof(lua_Integer))
964 964
965/* maximum size for the binary representation of an integer */ 965/* mask for all ones in last byte in a lua Integer */
966#define MAXINTSIZE 12 966#define HIGHERBYTE ((lua_Unsigned)MC << (NB * (SZINT - 1)))
967 967
968 968
969static union { 969/* dummy union to get native endianness */
970static const union {
970 int dummy; 971 int dummy;
971 char little; /* true iff machine is little endian */ 972 char little; /* true iff machine is little endian */
972} const nativeendian = {1}; 973} nativeendian = {1};
973 974
974 975
975static int getendian (lua_State *L, int arg) { 976/* dummy structure to get native alignment requirements */
976 const char *endian = luaL_optstring(L, arg, 977struct cD {
977 (nativeendian.little ? "l" : "b")); 978 char c;
978 if (*endian == 'n') /* native? */ 979 union { double d; void *p; lua_Integer i; lua_Number n; } u;
979 return nativeendian.little; 980};
980 luaL_argcheck(L, *endian == 'l' || *endian == 'b', arg,
981 "endianness must be 'l'/'b'/'n'");
982 return (*endian == 'l');
983}
984 981
982#define MAXALIGN (offsetof(struct cD, u))
985 983
986static int getintsize (lua_State *L, int arg) {
987 lua_Integer size = luaL_optinteger(L, arg, 0);
988 if (size == 0) size = SZINT;
989 luaL_argcheck(L, 1 <= size && size <= MAXINTSIZE, arg,
990 "integer size out of valid range");
991 return (int)size;
992}
993 984
985/*
986** Union for serializing floats
987*/
988typedef union Ftypes {
989 float f;
990 double d;
991 lua_Number n;
992 char buff[5 * sizeof(lua_Number)]; /* enough for any float type */
993} Ftypes;
994 994
995/* mask for all ones in last byte in a lua Integer */
996#define HIGHERBYTE ((lua_Unsigned)MC << (NB * (SZINT - 1)))
997 995
996/*
997** information to pack/unpack stuff
998*/
999typedef struct Header {
1000 lua_State *L;
1001 int islittle;
1002 int maxalign;
1003} Header;
998 1004
999static int dumpint (char *buff, lua_Integer m, int littleendian, int size) { 1005
1000 int i; 1006typedef enum KOption {Kint, Kuint, Kfloat, Kchar, Kstring, Kstring0,
1001 lua_Unsigned n = (lua_Unsigned)m; 1007 Kspace, Kpadding, Kpaddalig} KOption;
1002 lua_Unsigned mask = (m >= 0) ? 0 : HIGHERBYTE; /* sign extension */ 1008
1003 if (littleendian) { 1009
1004 for (i = 0; i < size - 1; i++) { 1010/*
1005 buff[i] = (n & MC); 1011** Read an integer numeral from string 'fmt' or return 'df' if
1006 n = (n >> NB) | mask; 1012** there is no numeral
1007 } 1013*/
1008 } 1014static int digit (int c) { return '0' <= c && c <= '9'; }
1015
1016static int getnum (const char **fmt, int df) {
1017 if (!digit(**fmt)) /* no number? */
1018 return df; /* return default value */
1009 else { 1019 else {
1010 for (i = size - 1; i > 0; i--) { 1020 int a = 0;
1011 buff[i] = (n & MC); 1021 do {
1012 n = (n >> NB) | mask; 1022 a = a*10 + *((*fmt)++) - '0';
1013 } 1023 } while (digit(**fmt) && a < (INT_MAX/10 - 10));
1014 } 1024 return a;
1015 buff[i] = (n & MC); /* last byte */
1016 if (size < SZINT) { /* need test for overflow? */
1017 /* OK if there are only zeros left in higher bytes,
1018 or only ones left (excluding non-signal bits in last byte) */
1019 return ((n & ~(lua_Unsigned)MC) == 0 ||
1020 (n | SM) == ~(lua_Unsigned)0);
1021 } 1025 }
1022 else return 1; /* no overflow can occur with full size */
1023} 1026}
1024 1027
1025 1028
1026static int dumpint_l (lua_State *L) { 1029/*
1027 char buff[MAXINTSIZE]; 1030** Read an integer numeral and raises an error if it is larger
1028 lua_Integer n = luaL_checkinteger(L, 1); 1031** than the maximum size for integers.
1029 int size = getintsize(L, 2); 1032*/
1030 int endian = getendian(L, 3); 1033static int getnumlimit (Header *h, const char **fmt, int df) {
1031 if (dumpint(buff, n, endian, size)) 1034 int sz = getnum(fmt, df);
1032 lua_pushlstring(L, buff, size); 1035 if (sz > MAXINTSIZE || sz <= 0)
1033 else 1036 luaL_error(h->L, "integral size (%d) out of limits [1,%d]", sz, MAXINTSIZE);
1034 luaL_error(L, "integer does not fit into given size (%d)", size); 1037 return sz;
1035 return 1;
1036} 1038}
1037 1039
1038 1040
1039/* mask to check higher-order byte + signal bit of next (lower) byte */ 1041/*
1040#define HIGHERBYTE1 (HIGHERBYTE | (HIGHERBYTE >> 1)) 1042** Reads an option endianness indication ('<'/'>') and
1043** returns true if operation should use little endian.
1044*/
1045static int getendian (const char **fmt) {
1046 if (**fmt == '<' || **fmt == '>') /* explicit endianness? */
1047 return (*((*fmt)++) == '<'); /* true iff little endian */
1048 else /* no endian indication */
1049 return nativeendian.little; /* use native */
1050}
1041 1051
1042 1052
1043static int undumpint (const char *buff, lua_Integer *res, 1053/*
1044 int littleendian, int size) { 1054** Read and return maximum alignment to be used
1045 lua_Unsigned n = 0; 1055*/
1046 int i; 1056static int getalignment (Header *h, const char **fmt) {
1047 for (i = 0; i < size; i++) { 1057 if (**fmt == '!') { /* explicit alignment? */
1048 if (i >= SZINT) { /* will throw away a byte? */ 1058 (*fmt)++; /* skip '!' */
1049 /* check for overflow: it is OK to throw away leading zeros for a 1059 return getnumlimit(h, fmt, MAXALIGN);
1050 positive number, leading ones for a negative number, and a
1051 leading zero byte to allow unsigned integers with a 1 in
1052 its "signal bit" */
1053 if (!((n & HIGHERBYTE1) == 0 || /* zeros for positive number */
1054 (n & HIGHERBYTE1) == HIGHERBYTE1 || /* ones for negative number */
1055 (i == size - 1 && (n & HIGHERBYTE) == 0))) /* leading zero */
1056 return 0; /* overflow */
1057 }
1058 n <<= NB;
1059 n |= (lua_Unsigned)(unsigned char)buff[littleendian ? size - 1 - i : i];
1060 }
1061 if (size < SZINT) { /* need sign extension? */
1062 lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
1063 *res = (lua_Integer)((n ^ mask) - mask); /* do sign extension */
1064 } 1060 }
1065 else 1061 else
1066 *res = (lua_Integer)n; 1062 return 1; /* default is no alignment */
1067 return 1;
1068} 1063}
1069 1064
1070 1065
1071static int undumpint_l (lua_State *L) { 1066/*
1072 lua_Integer res; 1067** Read optional endianness and alignment indications
1073 size_t len; 1068*/
1074 const char *s = luaL_checklstring(L, 1, &len); 1069static void getheader (lua_State *L, Header *h, const char **fmt) {
1075 lua_Integer pos = posrelat(luaL_optinteger(L, 2, 1), len); 1070 h->L = L;
1076 int size = getintsize(L, 3); 1071 h->islittle = getendian(fmt);
1077 int endian = getendian(L, 4); 1072 h->maxalign = getalignment(h, fmt);
1078 luaL_argcheck(L, 1 <= pos && (size_t)pos + size - 1 <= len, 1,
1079 "string too short");
1080 if(undumpint(s + pos - 1, &res, endian, size))
1081 lua_pushinteger(L, res);
1082 else
1083 luaL_error(L, "result does not fit into a Lua integer");
1084 return 1;
1085} 1073}
1086 1074
1087 1075
1088static void correctendianness (lua_State *L, char *b, int size, int endianarg) { 1076/*
1089 int endian = getendian(L, endianarg); 1077** Read and classify next option. 'size' is filled with option's size.
1090 if (endian != nativeendian.little) { /* not native endianness? */ 1078*/
1091 int i = 0; 1079static KOption getoption (Header *h, const char **fmt, int *size) {
1092 while (i < --size) { 1080 int opt = *((*fmt)++);
1093 char temp = b[i]; 1081 switch (opt) {
1094 b[i++] = b[size]; 1082 case 'b': *size = sizeof(char); return Kint;
1095 b[size] = temp; 1083 case 'B': *size = sizeof(char); return Kuint;
1084 case 'h': *size = sizeof(short); return Kint;
1085 case 'H': *size = sizeof(short); return Kuint;
1086 case 'l': *size = sizeof(long); return Kint;
1087 case 'L': *size = sizeof(long); return Kuint;
1088 case 'j': *size = sizeof(lua_Integer); return Kint;
1089 case 'J': *size = sizeof(lua_Integer); return Kuint;
1090 case 'T': *size = sizeof(size_t); return Kuint;
1091 case 'f': *size = sizeof(float); return Kfloat;
1092 case 'd': *size = sizeof(double); return Kfloat;
1093 case 'n': *size = sizeof(lua_Number); return Kfloat;
1094 case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint;
1095 case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint;
1096 case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring;
1097 case 'c': *size = getnum(fmt, 1); return Kchar;
1098 case 'z': *size = 0; return Kstring0;
1099 case 'x': *size = 1; return Kpadding;
1100 case 'X': *size = 0; return Kpaddalig;
1101 case ' ': *size = 0; return Kspace;
1102 default: {
1103 *size = 0; /* to avoid warnings */
1104 luaL_error(h->L, "invalid format option '%c'", opt);
1105 return (KOption)0;
1096 } 1106 }
1097 } 1107 }
1098} 1108}
1099 1109
1100 1110
1101static int getfloatsize (lua_State *L, int arg) { 1111/*
1102 const char *size = luaL_optstring(L, arg, "n"); 1112** Read, classify, and fill other details about the next option.
1103 if (*size == 'n') return sizeof(lua_Number); 1113** 'psize' is filled with option's size, 'notoalign' with its
1104 luaL_argcheck(L, *size == 'd' || *size == 'f', arg, 1114** alignment requirements.
1105 "size must be 'f'/'d'/'n'"); 1115** Local variable 'size' gets the size to be aligned. (Kpadal option
1106 return (*size == 'd' ? sizeof(double) : sizeof(float)); 1116** always gets its full alignment, other options are limited by
1117** the maximum alignment ('maxalign). Kchar option needs no aligment
1118** despite its size.
1119*/
1120static KOption getdetails (Header *h, size_t totalsize,
1121 const char **fmt, int *psize, int *ntoalign) {
1122 KOption opt = getoption(h, fmt, psize);
1123 int align = *psize; /* usually, alignment follows size */
1124 if (opt == Kpaddalig) {
1125 if (**fmt == '\0' || strchr("Xc ", **fmt) != NULL)
1126 luaL_argerror(h->L, 1, "invalid next option for option 'X'");
1127 getoption(h, fmt, &align); /* get next element's size for alignment */
1128 }
1129 if (align <= 1 || opt == Kchar) /* need no alignment? */
1130 *ntoalign = 0;
1131 else {
1132 if (align > h->maxalign)
1133 align = h->maxalign;
1134 if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */
1135 luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
1136 *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
1137 }
1138 return opt;
1107} 1139}
1108 1140
1109 1141
1110static int dumpfloat_l (lua_State *L) { 1142static void packint (luaL_Buffer *b, lua_Unsigned n,
1111 float f; double d; 1143 int islittle, int size, lua_Unsigned mask) {
1112 char *pn; /* pointer to number */ 1144 char *buff = luaL_prepbuffsize(b, size);
1113 lua_Number n = luaL_checknumber(L, 1); 1145 int i;
1114 int size = getfloatsize(L, 2); 1146 for (i = 0; i < size - 1; i++) {
1115 if (size == sizeof(lua_Number)) 1147 buff[islittle ? i : size - 1 - i] = (n & MC);
1116 pn = (char*)&n; 1148 n = (n >> NB) | mask;
1117 else if (size == sizeof(float)) {
1118 f = (float)n;
1119 pn = (char*)&f;
1120 }
1121 else { /* native lua_Number may be neither float nor double */
1122 lua_assert(size == sizeof(double));
1123 d = (double)n;
1124 pn = (char*)&d;
1125 } 1149 }
1126 correctendianness(L, pn, size, 3); 1150 buff[islittle ? i : size - 1 - i] = (n & MC);
1127 lua_pushlstring(L, pn, size); 1151 luaL_addsize(b, size); /* add result to buffer */
1128 return 1;
1129} 1152}
1130 1153
1131 1154
1132static int undumpfloat_l (lua_State *L) { 1155/*
1133 lua_Number res; 1156** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
1134 size_t len; 1157** given 'islittle' is different from native endianness.
1135 const char *s = luaL_checklstring(L, 1, &len); 1158*/
1136 lua_Integer pos = posrelat(luaL_optinteger(L, 2, 1), len); 1159static void copywithendian (volatile char *dest, volatile const char *src,
1137 int size = getfloatsize(L, 3); 1160 int size, int islittle) {
1138 luaL_argcheck(L, 1 <= pos && (size_t)pos + size - 1 <= len, 1, 1161 if (islittle == nativeendian.little) {
1139 "string too short"); 1162 while (size-- != 0)
1140 if (size == sizeof(lua_Number)) { 1163 *(dest++) = *(src++);
1141 memcpy(&res, s + pos - 1, size);
1142 correctendianness(L, (char*)&res, size, 4);
1143 } 1164 }
1144 else if (size == sizeof(float)) { 1165 else {
1145 float f; 1166 dest += size - 1;
1146 memcpy(&f, s + pos - 1, size); 1167 while (size-- != 0)
1147 correctendianness(L, (char*)&f, size, 4); 1168 *(dest--) = *(src++);
1148 res = (lua_Number)f; 1169 }
1149 } 1170}
1150 else { /* native lua_Number may be neither float nor double */ 1171
1151 double d; 1172
1152 lua_assert(size == sizeof(double)); 1173static int str_pack (lua_State *L) {
1153 memcpy(&d, s + pos - 1, size); 1174 luaL_Buffer b;
1154 correctendianness(L, (char*)&d, size, 4); 1175 Header h;
1155 res = (lua_Number)d; 1176 const char *fmt = luaL_checkstring(L, 1); /* format string */
1177 int arg = 1; /* current argument to pack */
1178 size_t totalsize = 0; /* accumulate total size of result */
1179 getheader(L, &h, &fmt);
1180 lua_pushnil(L); /* mark to separate arguments from string buffer */
1181 luaL_buffinit(L, &b);
1182 while (*fmt != '\0') {
1183 int size, ntoalign;
1184 KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1185 totalsize += ntoalign + size;
1186 while (ntoalign-- > 0) luaL_addchar(&b, '\0'); /* fill alignment */
1187 arg++;
1188 switch (opt) {
1189 case Kint: { /* signed integers */
1190 lua_Integer n = luaL_checkinteger(L, arg);
1191 lua_Unsigned mask = (n < 0) ? HIGHERBYTE : 0; /* sign extension */
1192 if (size < SZINT) { /* need overflow check? */
1193 lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1);
1194 luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
1195 }
1196 packint(&b, (lua_Unsigned)n, h.islittle, size, mask);
1197 break;
1198 }
1199 case Kuint: { /* unsigned integers */
1200 lua_Integer n = luaL_checkinteger(L, arg);
1201 if (size < SZINT) /* need overflow check? */
1202 luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)),
1203 arg, "unsigned overflow");
1204 packint(&b, (lua_Unsigned)n, h.islittle, size, 0);
1205 break;
1206 }
1207 case Kfloat: { /* floating-point options */
1208 volatile Ftypes u;
1209 char *buff = luaL_prepbuffsize(&b, size);
1210 lua_Number n = luaL_checknumber(L, arg); /* get argument */
1211 if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */
1212 else if (size == sizeof(u.d)) u.d = (double)n;
1213 else u.n = n;
1214 /* move 'u' to final result, correcting endianness if needed */
1215 copywithendian(buff, u.buff, size, h.islittle);
1216 luaL_addsize(&b, size);
1217 break;
1218 }
1219 case Kchar: { /* fixed-size string */
1220 size_t len;
1221 const char *s = luaL_checklstring(L, arg, &len);
1222 luaL_argcheck(L, len == (size_t)size, arg, "wrong length");
1223 luaL_addlstring(&b, s, size);
1224 break;
1225 }
1226 case Kstring: { /* strings with length count */
1227 size_t len;
1228 const char *s = luaL_checklstring(L, arg, &len);
1229 luaL_argcheck(L, size >= (int)sizeof(size_t) ||
1230 len < ((size_t)1 << (size * NB)),
1231 arg, "string length does not fit in given size");
1232 packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */
1233 luaL_addlstring(&b, s, len);
1234 totalsize += len;
1235 break;
1236 }
1237 case Kstring0: { /* zero-terminated string */
1238 size_t len;
1239 const char *s = luaL_checklstring(L, arg, &len);
1240 luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
1241 luaL_addlstring(&b, s, len);
1242 luaL_addchar(&b, '\0'); /* add zero at the end */
1243 totalsize += len + 1;
1244 break;
1245 }
1246 case Kpadding: luaL_addchar(&b, '\0'); /* go through */
1247 case Kpaddalig: case Kspace:
1248 arg--; /* undo increment */
1249 break;
1250 }
1156 } 1251 }
1157 lua_pushnumber(L, res); 1252 luaL_pushresult(&b);
1158 return 1; 1253 return 1;
1159} 1254}
1160 1255
1256
1257static lua_Integer unpackint (lua_State *L, const char *str,
1258 int islittle, int size, int issigned) {
1259 lua_Unsigned res = 0;
1260 int i;
1261 int limit = (size <= SZINT) ? size : SZINT;
1262 for (i = limit - 1; i >= 0; i--) {
1263 res <<= NB;
1264 res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i];
1265 }
1266 if (size < SZINT) { /* real size smaller than lua_Integer? */
1267 if (issigned) { /* needs sign extension? */
1268 lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
1269 res = ((res ^ mask) - mask); /* do sign extension */
1270 }
1271 }
1272 else { /* must check unread bytes */
1273 int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC;
1274 for (i = limit; i < size; i++) {
1275 if ((unsigned char)str[islittle ? i : size - 1 - i] != mask)
1276 luaL_error(L, "%d-bit integer does not fit into Lua Integer", size);
1277 }
1278 }
1279 return (lua_Integer)res;
1280}
1281
1282
1283static int str_unpack (lua_State *L) {
1284 Header h;
1285 const char *fmt = luaL_checkstring(L, 1);
1286 size_t ld;
1287 const char *data = luaL_checklstring(L, 2, &ld);
1288 size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1;
1289 int n = 0; /* number of results */
1290 luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
1291 getheader(L, &h, &fmt);
1292 while (*fmt) {
1293 int size, ntoalign;
1294 KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
1295 if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld)
1296 luaL_argerror(L, 2, "data string too short");
1297 pos += ntoalign;
1298 /* stack space for item + next position */
1299 luaL_checkstack(L, 2, "too many results");
1300 n++;
1301 switch (opt) {
1302 case Kint:
1303 case Kuint: {
1304 lua_Integer res = unpackint(L, data + pos, h.islittle, size,
1305 (opt == Kint));
1306 lua_pushinteger(L, res);
1307 break;
1308 }
1309 case Kfloat: {
1310 volatile Ftypes u;
1311 lua_Number num;
1312 copywithendian(u.buff, data + pos, size, h.islittle);
1313 if (size == sizeof(u.f)) num = (lua_Number)u.f;
1314 else if (size == sizeof(u.d)) num = (lua_Number)u.d;
1315 else num = u.n;
1316 lua_pushnumber(L, num);
1317 break;
1318 }
1319 case Kchar: {
1320 lua_pushlstring(L, data + pos, size);
1321 break;
1322 }
1323 case Kstring: {
1324 size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
1325 luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short");
1326 lua_pushlstring(L, data + pos + size, len);
1327 pos += len;
1328 break;
1329 }
1330 case Kstring0: {
1331 size_t len = (int)strlen(data + pos);
1332 lua_pushlstring(L, data + pos, len);
1333 pos += len + 1; /* skip final '\0' */
1334 break;
1335 }
1336 case Kpaddalig: case Kpadding: case Kspace:
1337 n--; /* undo increment */
1338 break;
1339 }
1340 pos += size;
1341 }
1342 lua_pushinteger(L, pos + 1); /* next position */
1343 return n + 1;
1344}
1345
1161/* }====================================================== */ 1346/* }====================================================== */
1162 1347
1163 1348
@@ -1176,10 +1361,8 @@ static const luaL_Reg strlib[] = {
1176 {"reverse", str_reverse}, 1361 {"reverse", str_reverse},
1177 {"sub", str_sub}, 1362 {"sub", str_sub},
1178 {"upper", str_upper}, 1363 {"upper", str_upper},
1179 {"dumpfloat", dumpfloat_l}, 1364 {"pack", str_pack},
1180 {"dumpinteger", dumpint_l}, 1365 {"unpack", str_unpack},
1181 {"undumpfloat", undumpfloat_l},
1182 {"undumpinteger", undumpint_l},
1183 {NULL, NULL} 1366 {NULL, NULL}
1184}; 1367};
1185 1368