浏览代码

new implementation for 'utf8.len'

Roberto Ierusalimschy 11 年之前
父节点
当前提交
3a044de5a1
共有 1 个文件被更改,包括 18 次插入13 次删除
  1. 18 13
      lutf8lib.c

+ 18 - 13
lutf8lib.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lutf8lib.c,v 1.4 2014/03/20 19:36:02 roberto Exp roberto $
+** $Id: lutf8lib.c,v 1.5 2014/04/01 14:39:55 roberto Exp roberto $
 ** Standard library for UTF-8 manipulation
 ** Standard library for UTF-8 manipulation
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -61,25 +61,30 @@ static const char *utf8_decode (const char *o, int *val) {
 
 
 
 
 /*
 /*
-** utf8len(s, [i])   --> number of codepoints in 's' after 'i';
-** nil if 's' not well formed
+** utf8len(s [, i [, j]])   --> number of codepoints in 's' between 'i';
+** nil + current position if 's' not well formed
 */
 */
 static int utflen (lua_State *L) {
 static int utflen (lua_State *L) {
   int n = 0;
   int n = 0;
-  const char *ends;
   size_t len;
   size_t len;
   const char *s = luaL_checklstring(L, 1, &len);
   const char *s = luaL_checklstring(L, 1, &len);
-  lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), 1);
-  luaL_argcheck(L, 1 <= posi && posi <= (lua_Integer)len, 1,
+  lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
+  lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
+  luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2,
                    "initial position out of string");
                    "initial position out of string");
-  ends = s + len;
-  s += posi - 1;
-  while (s < ends && (s = utf8_decode(s, NULL)) != NULL)
+  luaL_argcheck(L, --posj < (lua_Integer)len, 3,
+                   "final position out of string");
+  while (posi <= posj) {
+    const char *s1 = utf8_decode(s + posi, NULL);
+    if (s1 == NULL) {  /* conversion error? */
+      lua_pushnil(L);  /* return nil ... */
+      lua_pushinteger(L, posi + 1);  /* ... and current position */
+      return 2;
+    }
+    posi = s1 - s;
     n++;
     n++;
-  if (s == ends)
-    lua_pushinteger(L, n);
-  else
-    lua_pushnil(L);
+  }
+  lua_pushinteger(L, n);
   return 1;
   return 1;
 }
 }