github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/testdata/lua-5.3.3-tests/utf8.lua (about)

     1  -- $Id: utf8.lua,v 1.11 2014/12/26 17:20:53 roberto Exp $
     2  
     3  print "testing UTF-8 library"
     4  
     5  local utf8 = require'utf8'
     6  
     7  
     8  local function checkerror (msg, f, ...)
     9    local s, err = pcall(f, ...)
    10    assert(not s and string.find(err, msg))
    11  end
    12  
    13  
    14  local function len (s)
    15    return #string.gsub(s, "[\x80-\xBF]", "")
    16  end
    17  
    18  
    19  local justone = "^" .. utf8.charpattern .. "$"
    20  
    21  -- 't' is the list of codepoints of 's'
    22  local function checksyntax (s, t)
    23    local ts = {"return '"}
    24    for i = 1, #t do ts[i + 1] = string.format("\\u{%x}", t[i]) end
    25    ts[#t + 2] = "'"
    26    ts = table.concat(ts)
    27    assert(assert(load(ts))() == s)
    28  end
    29  
    30  assert(utf8.offset("alo", 5) == nil)
    31  assert(utf8.offset("alo", -4) == nil)
    32  
    33  -- 't' is the list of codepoints of 's'
    34  local function check (s, t)
    35    local l = utf8.len(s)
    36    assert(#t == l and len(s) == l)
    37    assert(utf8.char(table.unpack(t)) == s)
    38  
    39    assert(utf8.offset(s, 0) == 1)
    40  
    41    checksyntax(s, t)
    42  
    43    local t1 = {utf8.codepoint(s, 1, -1)}
    44    assert(#t == #t1)
    45    for i = 1, #t do assert(t[i] == t1[i]) end
    46  
    47    for i = 1, l do
    48      local pi = utf8.offset(s, i)        -- position of i-th char
    49      local pi1 = utf8.offset(s, 2, pi)   -- position of next char
    50      assert(string.find(string.sub(s, pi, pi1 - 1), justone))
    51      assert(utf8.offset(s, -1, pi1) == pi)
    52      assert(utf8.offset(s, i - l - 1) == pi)
    53      assert(pi1 - pi == #utf8.char(utf8.codepoint(s, pi)))
    54      for j = pi, pi1 - 1 do
    55        assert(utf8.offset(s, 0, j) == pi)
    56      end
    57      for j = pi + 1, pi1 - 1 do
    58        assert(not utf8.len(s, j))
    59      end
    60     assert(utf8.len(s, pi, pi) == 1)
    61     assert(utf8.len(s, pi, pi1 - 1) == 1)
    62     assert(utf8.len(s, pi) == l - i + 1)
    63     assert(utf8.len(s, pi1) == l - i)
    64     assert(utf8.len(s, 1, pi) == i)
    65    end
    66  
    67    local i = 0
    68    for p, c in utf8.codes(s) do
    69      i = i + 1
    70      assert(c == t[i] and p == utf8.offset(s, i))
    71      assert(utf8.codepoint(s, p) == c)
    72    end
    73    assert(i == #t)
    74  
    75    i = 0
    76    for p, c in utf8.codes(s) do
    77      i = i + 1
    78      assert(c == t[i] and p == utf8.offset(s, i))
    79    end
    80    assert(i == #t)
    81  
    82    i = 0
    83    for c in string.gmatch(s, utf8.charpattern) do
    84      i = i + 1
    85      assert(c == utf8.char(t[i]))
    86    end
    87    assert(i == #t)
    88  
    89    for i = 1, l do
    90      assert(utf8.offset(s, i) == utf8.offset(s, i - l - 1, #s + 1))
    91    end
    92  
    93  end
    94  
    95  
    96  do    -- error indication in utf8.len
    97    local function check (s, p)
    98      local a, b = utf8.len(s)
    99      assert(not a and b == p)
   100    end
   101    check("abc\xE3def", 4)
   102    check("汉字\x80", #("汉字") + 1)
   103    check("\xF4\x9F\xBF", 1)
   104    check("\xF4\x9F\xBF\xBF", 1)
   105  end
   106  
   107  -- error in utf8.codes
   108  checkerror("invalid UTF%-8 code",
   109    function ()
   110      local s = "ab\xff"
   111      for c in utf8.codes(s) do assert(c) end
   112    end)
   113  
   114  
   115  -- error in initial position for offset
   116  checkerror("position out of range", utf8.offset, "abc", 1, 5)
   117  checkerror("position out of range", utf8.offset, "abc", 1, -4)
   118  checkerror("position out of range", utf8.offset, "", 1, 2)
   119  checkerror("position out of range", utf8.offset, "", 1, -1)
   120  checkerror("continuation byte", utf8.offset, "𦧺", 1, 2)
   121  checkerror("continuation byte", utf8.offset, "𦧺", 1, 2)
   122  checkerror("continuation byte", utf8.offset, "\x80", 1)
   123  
   124  
   125  
   126  local s = "hello World"
   127  local t = {string.byte(s, 1, -1)}
   128  for i = 1, utf8.len(s) do assert(t[i] == string.byte(s, i)) end
   129  check(s, t)
   130  
   131  check("汉字/漢字", {27721, 23383, 47, 28450, 23383,})
   132  
   133  do
   134    local s = "áéí\128"
   135    local t = {utf8.codepoint(s,1,#s - 1)}
   136    assert(#t == 3 and t[1] == 225 and t[2] == 233 and t[3] == 237)
   137    checkerror("invalid UTF%-8 code", utf8.codepoint, s, 1, #s)
   138    checkerror("out of range", utf8.codepoint, s, #s + 1)
   139    t = {utf8.codepoint(s, 4, 3)}
   140    assert(#t == 0)
   141    checkerror("out of range", utf8.codepoint, s, -(#s + 1), 1)
   142    checkerror("out of range", utf8.codepoint, s, 1, #s + 1)
   143  end
   144  
   145  assert(utf8.char() == "")
   146  assert(utf8.char(97, 98, 99) == "abc")
   147  
   148  assert(utf8.codepoint(utf8.char(0x10FFFF)) == 0x10FFFF)
   149  
   150  checkerror("value out of range", utf8.char, 0x10FFFF + 1)
   151  
   152  local function invalid (s)
   153    checkerror("invalid UTF%-8 code", utf8.codepoint, s)
   154    assert(not utf8.len(s))
   155  end
   156  
   157  -- UTF-8 representation for 0x11ffff (value out of valid range)
   158  invalid("\xF4\x9F\xBF\xBF")
   159  
   160  -- overlong sequences
   161  invalid("\xC0\x80")          -- zero
   162  invalid("\xC1\xBF")          -- 0x7F (should be coded in 1 byte)
   163  invalid("\xE0\x9F\xBF")      -- 0x7FF (should be coded in 2 bytes)
   164  invalid("\xF0\x8F\xBF\xBF")  -- 0xFFFF (should be coded in 3 bytes)
   165  
   166  
   167  -- invalid bytes
   168  invalid("\x80")  -- continuation byte
   169  invalid("\xBF")  -- continuation byte
   170  invalid("\xFE")  -- invalid byte
   171  invalid("\xFF")  -- invalid byte
   172  
   173  
   174  -- empty string
   175  check("", {})
   176  
   177  -- minimum and maximum values for each sequence size
   178  s = "\0 \x7F\z
   179       \xC2\x80 \xDF\xBF\z
   180       \xE0\xA0\x80 \xEF\xBF\xBF\z
   181       \xF0\x90\x80\x80  \xF4\x8F\xBF\xBF"
   182  s = string.gsub(s, " ", "")
   183  check(s, {0,0x7F, 0x80,0x7FF, 0x800,0xFFFF, 0x10000,0x10FFFF})
   184  
   185  x = "日本語a-4\0éó"
   186  check(x, {26085, 26412, 35486, 97, 45, 52, 0, 233, 243})
   187  
   188  
   189  -- Supplementary Characters
   190  check("𣲷𠜎𠱓𡁻𠵼ab𠺢",
   191        {0x23CB7, 0x2070E, 0x20C53, 0x2107B, 0x20D7C, 0x61, 0x62, 0x20EA2,})
   192  
   193  check("𨳊𩶘𦧺𨳒𥄫𤓓\xF4\x8F\xBF\xBF",
   194        {0x28CCA, 0x29D98, 0x269FA, 0x28CD2, 0x2512B, 0x244D3, 0x10ffff})
   195  
   196  
   197  local i = 0
   198  for p, c in string.gmatch(x, "()(" .. utf8.charpattern .. ")") do
   199    i = i + 1
   200    assert(utf8.offset(x, i) == p)
   201    assert(utf8.len(x, p) == utf8.len(x) - i + 1)
   202    assert(utf8.len(c) == 1)
   203    for j = 1, #c - 1 do
   204      assert(utf8.offset(x, 0, p + j - 1) == p)
   205    end
   206  end
   207  
   208  print'ok'
   209