diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-04-02 14:01:22 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-04-02 14:01:22 -0300 |
commit | 3a044de5a1df82ed5d76f2c5afdf79677c92800f (patch) | |
tree | ae867901bb5aa2be8bb7bc4b81ddf653317c09d6 /lutf8lib.c | |
parent | 7d514af0bc95b75d7a162331b0e4c1fd7d20c9c7 (diff) | |
download | lua-3a044de5a1df82ed5d76f2c5afdf79677c92800f.tar.gz lua-3a044de5a1df82ed5d76f2c5afdf79677c92800f.tar.bz2 lua-3a044de5a1df82ed5d76f2c5afdf79677c92800f.zip |
new implementation for 'utf8.len'
Diffstat (limited to 'lutf8lib.c')
-rw-r--r-- | lutf8lib.c | 31 |
1 files changed, 18 insertions, 13 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lutf8lib.c,v 1.4 2014/03/20 19:36:02 roberto Exp roberto $ | 2 | ** $Id: lutf8lib.c,v 1.5 2014/04/01 14:39:55 roberto Exp roberto $ |
3 | ** Standard library for UTF-8 manipulation | 3 | ** Standard library for UTF-8 manipulation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -61,25 +61,30 @@ static const char *utf8_decode (const char *o, int *val) { | |||
61 | 61 | ||
62 | 62 | ||
63 | /* | 63 | /* |
64 | ** utf8len(s, [i]) --> number of codepoints in 's' after 'i'; | 64 | ** utf8len(s [, i [, j]]) --> number of codepoints in 's' between 'i'; |
65 | ** nil if 's' not well formed | 65 | ** nil + current position if 's' not well formed |
66 | */ | 66 | */ |
67 | static int utflen (lua_State *L) { | 67 | static int utflen (lua_State *L) { |
68 | int n = 0; | 68 | int n = 0; |
69 | const char *ends; | ||
70 | size_t len; | 69 | size_t len; |
71 | const char *s = luaL_checklstring(L, 1, &len); | 70 | const char *s = luaL_checklstring(L, 1, &len); |
72 | lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), 1); | 71 | lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); |
73 | luaL_argcheck(L, 1 <= posi && posi <= (lua_Integer)len, 1, | 72 | lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); |
73 | luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, | ||
74 | "initial position out of string"); | 74 | "initial position out of string"); |
75 | ends = s + len; | 75 | luaL_argcheck(L, --posj < (lua_Integer)len, 3, |
76 | s += posi - 1; | 76 | "final position out of string"); |
77 | while (s < ends && (s = utf8_decode(s, NULL)) != NULL) | 77 | while (posi <= posj) { |
78 | const char *s1 = utf8_decode(s + posi, NULL); | ||
79 | if (s1 == NULL) { /* conversion error? */ | ||
80 | lua_pushnil(L); /* return nil ... */ | ||
81 | lua_pushinteger(L, posi + 1); /* ... and current position */ | ||
82 | return 2; | ||
83 | } | ||
84 | posi = s1 - s; | ||
78 | n++; | 85 | n++; |
79 | if (s == ends) | 86 | } |
80 | lua_pushinteger(L, n); | 87 | lua_pushinteger(L, n); |
81 | else | ||
82 | lua_pushnil(L); | ||
83 | return 1; | 88 | return 1; |
84 | } | 89 | } |
85 | 90 | ||