├── .gitignore ├── AUTHORS ├── COPYRIGHT ├── HISTORY ├── README.md ├── TODO ├── etc └── replay.lua ├── make.sh ├── rockspec ├── luatexts-0.1-1.rockspec ├── luatexts-0.1.1-1.rockspec ├── luatexts-0.1.2-1.rockspec ├── luatexts-0.1.3-1.rockspec ├── luatexts-0.1.4-1.rockspec ├── luatexts-0.1.5-1.rockspec └── luatexts-scm-1.rockspec ├── src ├── c │ ├── luainternals.c │ ├── luainternals.h │ └── luatexts.c ├── js │ ├── luatexts.js │ └── luatexts.min.js ├── lua │ └── luatexts │ │ └── lua.lua └── php │ └── luatexts.php ├── test ├── data │ ├── empty.luatexts │ ├── garbage.luatexts │ ├── good.luatexts │ ├── noeol.luatexts │ ├── truncated.luatexts │ └── truncated2.luatexts ├── luatexts.js ├── luatexts.min.js ├── test.html ├── test.lua ├── test.min.html └── test.php └── tmp └── .keepme /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .*~ 3 | \#*\# 4 | .\#*\# 5 | 6 | .DS_Store 7 | ._.DS_Store 8 | .project 9 | .settings 10 | 11 | *.o 12 | *.so 13 | 14 | tmp/* 15 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | luatexts authors: 2 | ----------------- 3 | 4 | Alexander Gladysh 5 | Mikhail Nazarov 6 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | luatexts license 2 | ---------------- 3 | 4 | luatexts is licensed under the terms of the MIT license 5 | reproduced below. This means that luatexts is free software and can be used 6 | for both academic and commercial purposes at absolutely no cost. 7 | 8 | =============================================================================== 9 | 10 | Copyright (C) 2011-2013, luatexts authors 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | THE SOFTWARE. 29 | 30 | =============================================================================== 31 | 32 | (end of COPYRIGHT) 33 | -------------------------------------------------------------------------------- /HISTORY: -------------------------------------------------------------------------------- 1 | Version 0.1.5 (2012-06-17) 2 | ========================== 3 | 4 | * Fixed compilation for LuaJIT 2. 5 | 6 | Version 0.1.4 (2012-04-23) 7 | ========================== 8 | 9 | * New data types: 10 | * Stream-friendly table 11 | * Unsigned integer, base 16 12 | * Unsigned integer, base 36 13 | * New C module function: `load_from_file(filename)` 14 | * C `load()` now handles unsigned integers up to 4294967295 15 | * New Lua module functions: 16 | * `load()` 17 | * `load_from_buffer()` to read from streams 18 | * `save_cat()` to save to streams (files, stdout etc.) 19 | * UTF-8 string length is given in codepoints, not characters 20 | * Optimized C code 21 | * Some improvements in documentation 22 | * Some improvements in implementation 23 | * Some improvements in tests 24 | 25 | Version 0.1.3 (2011-06-03) 26 | ========================== 27 | 28 | * Fixed array serialization in PHP library 29 | (now arrays are implicitly converted to be 1-based, as it is done in JS) 30 | 31 | Version 0.1.2 (2011-05-17) 32 | ========================== 33 | 34 | * PHP library (save() only). 35 | * Fixed string serialization in JS library. 36 | 37 | Version 0.1.1 (2011-04-18) 38 | ========================== 39 | 40 | * UTF-8 support improved: better detection of invalid byte sequences. 41 | Kudos to Jonathan Leffler for code review and suggestions: 42 | 43 | http://codereview.stackexchange.com/q/1624/234 44 | 45 | Version 0.1 (2011-04-03) 46 | ======================== 47 | 48 | Initial release. 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | luatexts: Trivial Lua human-readable binary-safe serialization library 2 | ====================================================================== 3 | 4 | See the copyright information in the file named `COPYRIGHT`. 5 | 6 | Why not... 7 | ---------- 8 | 9 | * XML — large and unwieldy 10 | * JSON — not Lua-aware (can't encode table-as-key and other fancy values) 11 | * Lua code — needs sandboxing, slower load times 12 | * Luabins — is too binary for some languages 13 | * ... 14 | 15 | Inspired by 16 | ----------- 17 | 18 | * Luabins: http://github.com/agladysh/luabins/ 19 | * Redis transport protocol format: http://redis.io/topics/protocol 20 | 21 | Supported data types 22 | -------------------- 23 | 24 | * `nil` 25 | * `boolean` 26 | * `number` 27 | * `string` 28 | * `table` (no references) 29 | 30 | Format 31 | ------ 32 | 33 | ### Note on human-readability 34 | 35 | Note that while human-readability is one of design goals, 36 | nobody claims that the actual data is easy to read or write by hand. 37 | 38 | You can do it, but you're better off using some API instead. 39 | 40 | If you often need to work with luatexts data manually for purposes 41 | other than debugging, consider using something more friendly like 42 | JSON or XML or sandboxed Lua code. 43 | 44 | ### Definition 45 | 46 | The luatexts format is defined as follows: 47 | 48 | \n 49 | \n 50 | 51 | ... 52 | \n 53 | 54 | 55 | *`\n` here and below may be either `LF` or `CRLF`* 56 | 57 | ### Types 58 | 59 | * Nil 60 | * type: `-` 61 | * data: *(none)* 62 | * Boolean (false) 63 | * type: `0` 64 | * data: *(none)* 65 | * Boolean (true) 66 | * type: `1` 67 | * data: *(none)* 68 | * Number (double) 69 | * type: `N` 70 | * data: *plain string representation, readable by `strtod`*\n 71 | * Number (unsigned integer, base 10, max: 4294967295) 72 | * type: `U` 73 | * data: *[0-9]+*\n 74 | * Number (unsigned integer, base 16, max: 4294967295) 75 | * type: `H` 76 | * data: *plain string representation, readable by `strtoul`*\n 77 | * Number (unsigned integer, base 36, max: 4294967295) 78 | * type: `Z` 79 | * data: *plain string representation, readable by `strtoul`*\n 80 | * String (regular) 81 | * type: `S` 82 | * data: 83 | 84 | \n 85 | \n 86 | 87 | * String (UTF-8) 88 | * type: `8` 89 | * data: 90 | 91 | \n 92 | \n 93 | 94 | * Fixed-size table 95 | * type: `T` 96 | * data: 97 | 98 | \n 99 | \n 100 | 101 | ... 102 | 103 | 104 | 105 | ... 106 | 107 | 108 | 109 | * Streaming-friendly table 110 | * type: `t` 111 | * data: 112 | 113 | \n 114 | \n 115 | ... 116 | 117 | 118 | 119 | 120 | ### Notes on table data type: 121 | 122 | * Nested tables are supported; 123 | * references in tables are not supported (saved as separate tables); 124 | * if table references itself, it can not be saved; 125 | * array/hash separation is optional, encoder can opt to use hash part only, 126 | (but decoder must support both); 127 | * array part may include `nil` values (hash values may be `nil` as well); 128 | * table keys may not be `NaN` or `nil`. 129 | 130 | ### Examples 131 | 132 | *Everything on the line after `\n` is comments, do not put them into your data.* 133 | 134 | * Zero-sized tuple 135 | 136 | In Lua: 137 | 138 | return 139 | 140 | In luatexts: 141 | 142 | 0\n ; == Tuple size == 143 | 144 | * Mutiple values in tuple 145 | 146 | In Lua: 147 | 148 | return 42, "Hello, world!\n", true 149 | 150 | In luatexts: 151 | 152 | 3\n ; == Tuple size == 153 | N\n ; -- Number -- 154 | 42\n ; Number value 155 | S\n ; -- String -- 156 | 13\n ; String size in bytes 157 | Hello, world!\n\n ; String data 158 | 1\n ; -- Boolean true -- 159 | 160 | * Simple table 161 | 162 | In Lua: 163 | 164 | return { 42 } 165 | 166 | In luatexts: 167 | 168 | 1\n ; == Tuple size == 169 | T\n ; -- Table -- 170 | 1\n ; Array part size 171 | 0\n ; Hash part size 172 | N\n ; [1]: -- Number -- 173 | 42\n ; [1]: Number value 174 | 175 | In luatexts (equivalent): 176 | 177 | 1\n ; == Tuple size == 178 | T\n ; -- Table -- 179 | 0\n ; Array part size 180 | 1\n ; Hash part size 181 | N\n ; Key: -- Number -- 182 | 1\n ; Key: Number value 183 | N\n ; Value: -- Number -- 184 | 42\n ; Value: Number value 185 | 186 | ### Array vs. hash parts of a table 187 | 188 | Note that, as far as Lua implementation is concerned, 189 | it does not matter much if you put a value in array part or in hash part 190 | of a table in your luatexts data. 191 | 192 | As in Lua table constructor, you can even put a value for the same key both 193 | in array and in hash part of a table: 194 | 195 | In Lua: 196 | 197 | return { 3.14, [1] = 2.71 } 198 | 199 | In luatexts: 200 | 201 | 1\n ; == Tuple size == 202 | T\n ; -- Table -- 203 | 1\n ; Array part size 204 | 1\n ; Hash part size 205 | N\n ; [1]: -- Number -- 206 | 3.14\n ; [1]: Number value 207 | N\n ; Key: -- Number -- 208 | 1\n ; Key: Number value 209 | N\n ; Value: -- Number -- 210 | 2.71\n ; Value: Number value 211 | 212 | As in Lua, it is not defined which one of values would end up 213 | in the loaded table. 214 | 215 | ### Regular strings vs. UTF-8 strings 216 | 217 | Regular strings are treated just as a blob of bytes. Their size 218 | is specified *in bytes*, and reader implementation never looks 219 | inside the string data. You can pass any data, including something binary 220 | as a regular string. (Obviously, you can also pass UTF-8 strings 221 | as regular strings.) 222 | 223 | UTF-8 strings are honestly treated as UTF-8 data. Their size is 224 | specified *in codepoints*, and reader implementation does read UTF-8 225 | codepoints one-by-one, doing the full validation. You can only pass valid 226 | UTF-8 text data as an UTF-8 string. 227 | 228 | Apart from validation, in Lua implementation it does not matter much, 229 | if you used regular string or UTF-8 string type to represent your data. 230 | But UTF-8 strings are handy if you compose your data payload from the 231 | language that does not know anything about bytes. 232 | 233 | Security notes 234 | -------------- 235 | 236 | Protect from memory attacks by limiting the payload string size. 237 | Luatexts does not do that for you. 238 | 239 | Mini-FAQ 240 | -------- 241 | 242 | 1. Why no `load()` in other language versions? 243 | 244 | Did not have time to write them yet. Do not need them personally, 245 | because I always try to feed the data to the consumer 246 | in the format consumer understands best. 247 | 248 | 2. What if I need one of these missing functions? 249 | 250 | * Use luabins or other feature-complete serialization library. 251 | 252 | * Write it yourself (it is easy!) and send @agladysh a pull request. 253 | 254 | * Ask @agladysh nicely. 255 | 256 | 3. When to use luatexts and when luabins? 257 | 258 | * Use either of them when data consumer is Lua code. 259 | Outside of that both formats are of limited usefulness, 260 | since they follow Lua-specific data semantics closely. 261 | 262 | * If data producer language does have luabins or luatexts bindings, use them. 263 | If both are available, prefer luabins for speed, 264 | luatexts for human-readability. 265 | 266 | * If data producer language does not have existing bindings 267 | and it is C-aware, use luabins, as it has Lua-less C serialization API. 268 | I would appreciate if you would share your bindings code with 269 | the community, but it is not mandatory. 270 | 271 | * Otherwise, if data producer language is not C-aware, use luatexts, 272 | as luatexts format writer it is more trivial to implement 273 | (see JS API for an example). Again, I would greatly appreciate if you 274 | will share your implementation with the community, 275 | but it is not mandatory. 276 | 277 | 4. Should I use "length in characters" or "length in codepoints" 278 | for String (UTF-8)? 279 | 280 | Use length in codepoints (UTF-8 is complex). In JavaScript 281 | `String.length()` returns length in codepoints, so that is not a problem. 282 | 283 | If unsure which is which (and using something more aware about bytes 284 | that JavaScript), just use String (regular). 285 | 286 | API 287 | --- 288 | 289 | ### Lua (C API) 290 | 291 | local luatexts = require 'luatexts' 292 | 293 | * `luatexts.load(data : string) : true, ... / nil, err` 294 | 295 | Returns unserialized data tuple (as multiple return values). 296 | Tuples may be of zero values. 297 | 298 | ### Lua (Plain) 299 | 300 | This module is primarily used in tests. It may be considered as a reference 301 | implementation of luatexts data serializer. 302 | 303 | local luatexts_lua = require 'luatexts.lua' 304 | 305 | * `luatexts_lua.save(...) : string / nil, err` 306 | 307 | Serializes given data tuple. Returns `nil, err` on error. 308 | 309 | Uses fixed-table data type to serialize tables. 310 | 311 | Issues: 312 | 313 | * Throws `error()` on self-referencing tables. 314 | * Asserts if detects non-serializable value inside a table. 315 | 316 | (Both issues to be fixed in later revisions.) 317 | 318 | * `luatexts_lua.save_cat(cat : function, ...) : cat / nil, err` 319 | 320 | Serializes given data tuple to `cat()` function. Throws on error. 321 | 322 | cat(v : string|number) : cat 323 | 324 | Uses streaming-friendly-table data type to serialize tables. 325 | Useful for serialization to streams (e.g. files / `stdout`). 326 | 327 | * `luatexts_lua.load(data : string) : true, ... / nil, err` 328 | 329 | Returns unserialized data tuple (as multiple return values). 330 | Tuples may be of zero values. 331 | 332 | Issues (to be fixed in later revisions): 333 | 334 | * Does not support loading UTF-8 string value type. 335 | Use ordinary string value data to pass UTF-8 data instead. 336 | (You'll need to know its size in bytes, of course.) 337 | 338 | * `luatexts_lua.load_from_buffer(buf : buffer) : true, ... / nil, err` 339 | 340 | Returns unserialized data tuple (as multiple return values). 341 | Tuples may be of zero values. 342 | 343 | The `buffer` object must have following methods: 344 | 345 | * `buf:read(bytes : number) : string / nil` 346 | 347 | Reads specified number of bytes from the buffer and returns them as string. 348 | 349 | Returns nil and sets buffer state to failed on error. 350 | 351 | * `buf:readpattern(lua_pattern : string) : string / nil` 352 | 353 | Reads specified Lua pattern from the buffer, 354 | and returns captures. 355 | 356 | Pattern is guaranteed to have at least one capture (including `()` 357 | positional capture), and to terminate with '\n' character. 358 | 359 | Returns `nil` and sets buffer state to failed on error 360 | (including the case when pattern does not match anything, 361 | or if there is any unread data in the buffer before pattern). 362 | 363 | * `buf:good() : boolean` 364 | 365 | Returns false if buffer state is failed, true otherwise. 366 | 367 | * `buf:fail(error_message : string) : none` 368 | 369 | Sets buffer state to failed with a given `error_message`. 370 | 371 | * `buf:result() : true | nil, error_message` 372 | 373 | Returns `true` if buffer state is good. 374 | Returns `nil, error_message` if buffer state is failed. 375 | 376 | You may find a reference implementation of `buffer` object 377 | in the Lua module source code. 378 | 379 | Issues (to be fixed in later revisions): 380 | 381 | * Does not support loading UTF-8 string value type. 382 | Use ordinary string value data to pass UTF-8 data instead. 383 | (You'll need to know its size in bytes, of course.) 384 | 385 | ### JavaScript 386 | 387 | * `LUATEXTS.save(...) : string` 388 | 389 | Serializes its arguments and returns them as a string. 390 | If does not know how to serialize value, throws `Exception`. 391 | Call without arguments produces a zero-sized tuple. 392 | 393 | Type conversion rules for JS --> Lua: 394 | 395 | * `undefined` --> `nil` 396 | * `null` --> `nil` 397 | * `boolean` --> `boolean` 398 | * `number` --> `number` 399 | * `string` --> `string` (assuming UTF-8 encoding) 400 | * `object` --> `table` with hash part 401 | * `array` --> `table` with array part (implicitly saved as 1-based) 402 | * `function` --> not supported 403 | 404 | Nested objects / arrays are supported. 405 | 406 | **Warning:** For JavaScript client code to work consistently between browsers, 407 | you must specify the encoding of the page that the code is executed in. 408 | Otherwise each browser will assume its own default encoding. 409 | Make sure that the encoding does match whatever your server-side code 410 | does expect. 411 | 412 | To specify the encoding you may either send correct `Content-Encoding` 413 | HTTP header, or put this tag into the page's ``: 414 | 415 | 416 | 417 | Current JavaScript library implementation works *only* with UTF-8 strings. 418 | It is up to user to ensure that string encoding is correct. 419 | 420 | ### PHP 421 | 422 | * `Luatexts::save( ... ) : string` 423 | 424 | Serializes its arguments and returns them as a string. 425 | If does not know how to serialize value, throws `Exception`. 426 | Call without arguments produces a zero-sized tuple. 427 | 428 | Type conversion rules for JS --> Lua: 429 | 430 | * `null` --> `nil` 431 | * `boolean` --> `boolean` 432 | * `number` --> `number` 433 | * `string` --> `string` (assuming UTF-8 encoding) 434 | * `array` --> `table` with array part (implicitly saved as 1-based) 435 | * `function` --> not supported 436 | * `object` --> not supported 437 | 438 | Nested arrays are supported. 439 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | TODO: 2 | ----- 3 | 4 | -- Deal with LuaJIT2 bug (http://thread.gmane.org/gmane.comp.lang.lua.general/89951) 5 | -- Run splint all over the C code. 6 | -- Add a luajit.ffi implementation. 7 | -- luatexts.lua.save() should not throw error() or use assert(). 8 | -- Write JS load(). 9 | -- Run benchmarks against Luabins, JSON, XML and Lua source. 10 | -- Run benchmarks against msgpack and other popular formats. 11 | -- Add generative and mutational tests for the UTF-8 data. 12 | -- Write better tests. 13 | -------------------------------------------------------------------------------- /etc/replay.lua: -------------------------------------------------------------------------------- 1 | pcall(require, 'luarocks.require') 2 | require 'lua-nucleo.module' 3 | require 'lua-nucleo.strict' 4 | require = import 'lua-nucleo/require_and_declare.lua' { 'require_and_declare' } 5 | 6 | math.randomseed(12345) 7 | 8 | local ensure, 9 | ensure_equals, 10 | ensure_tequals, 11 | ensure_tdeepequals, 12 | ensure_strequals, 13 | ensure_error, 14 | ensure_error_with_substring, 15 | ensure_fails_with_substring, 16 | ensure_returns 17 | = import 'lua-nucleo/ensure.lua' 18 | { 19 | 'ensure', 20 | 'ensure_equals', 21 | 'ensure_tequals', 22 | 'ensure_tdeepequals', 23 | 'ensure_strequals', 24 | 'ensure_error', 25 | 'ensure_error_with_substring', 26 | 'ensure_fails_with_substring', 27 | 'ensure_returns' 28 | } 29 | 30 | local split_by_char = import 'lua-nucleo/string.lua' { 'split_by_char' } 31 | 32 | local tset = import 'lua-nucleo/table-utils.lua' { 'tset' } 33 | 34 | local tpretty = import 'lua-nucleo/tpretty.lua' { 'tpretty' } 35 | 36 | local tstr = import 'lua-nucleo/tstr.lua' { 'tstr' } 37 | 38 | local tserialize = import 'lua-nucleo/tserialize.lua' { 'tserialize' } 39 | 40 | local tdeepequals = import 'lua-nucleo/tdeepequals.lua' { 'tdeepequals' } 41 | 42 | local find_all_files, 43 | read_file 44 | = import 'lua-aplicado/filesystem.lua' 45 | { 46 | 'find_all_files', 47 | 'read_file' 48 | } 49 | 50 | -------------------------------------------------------------------------------- 51 | 52 | -- TODO: ?! UGH! #3836 53 | declare 'inf' 54 | inf = 1/0 55 | 56 | -------------------------------------------------------------------------------- 57 | 58 | local PREFIX = select(1, ...) or "tmp" 59 | local OFFSET = tonumber(select(2, ...) or 1) or 1 60 | local MODE = (select(3, ...) or "c"):lower() 61 | 62 | local luatexts 63 | if MODE == "c" then 64 | luatexts = require 'luatexts' 65 | elseif MODE == "lua" then 66 | luatexts = require 'luatexts.lua' 67 | else 68 | error("unknown mode") 69 | end 70 | 71 | io.stderr:write( 72 | "replay.lua:", 73 | " PREFIX: ", PREFIX, 74 | " OFFSET: ", OFFSET, 75 | " MODE: ", MODE, 76 | "\n" 77 | ) 78 | io.stderr:flush() 79 | 80 | -------------------------------------------------------------------------------- 81 | 82 | local filenames = find_all_files(PREFIX, ".*%d+%.luatexts$") 83 | table.sort(filenames) 84 | 85 | local n_str 86 | 87 | for i = 1, #filenames do 88 | local filename = filenames[i] 89 | n_str = assert(filename:match("^"..PREFIX.."/(%d+).luatexts$")) 90 | 91 | local n = assert(tonumber(n_str, 10)) 92 | if n >= OFFSET then 93 | local tuple, tuple_size = assert(dofile(PREFIX.."/"..n_str..".lua")) 94 | local data = assert(read_file(filename)) 95 | 96 | ensure_returns( 97 | "load " .. n_str, 98 | tuple_size + 1, { true, unpack(tuple, 1, tuple_size) }, 99 | luatexts.load(data) 100 | ) 101 | end 102 | end 103 | 104 | io.stdout:flush() 105 | print("OK") 106 | -------------------------------------------------------------------------------- /make.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -e 4 | 5 | if ([ -z "${CLOSURE}" ]); then 6 | CLOSURE="$(luarocks show --rock-dir pk-core-js.google-closure-compiler)" 7 | fi 8 | 9 | echo "----> Going pedantic all over the source" 10 | 11 | echo "--> c89..." 12 | gcc -O2 -fPIC -I/usr/include/lua5.1 -c src/c/luatexts.c -o /dev/null -Isrc/c/ -Wall --pedantic -Werror --std=c89 13 | 14 | echo "--> c99..." 15 | gcc -O2 -fPIC -I/usr/include/lua5.1 -c src/c/luatexts.c -o /dev/null -Isrc/c/ -Wall --pedantic -Werror --std=c99 16 | 17 | echo "--> c++98..." 18 | gcc -xc++ -O2 -fPIC -I/usr/include/lua5.1 -c src/c/luatexts.c -o /dev/null -Isrc/c/ -Wall --pedantic -Werror --std=c++98 19 | 20 | echo "----> Making rock" 21 | sudo luarocks make rockspec/luatexts-scm-1.rockspec 22 | 23 | HEADER='// LUATEXTS JavaScript module (v. 0.1.5) 24 | // https://github.com/agladysh/luatexts/ 25 | // Copyright (c) LUATEXTS authors. Licensed under the terms of the MIT license: 26 | // https://github.com/agladysh/luatexts/tree/master/COPYRIGHT 27 | %output% 28 | ' 29 | 30 | echo "----> Minifying js" 31 | java -jar \ 32 | "${CLOSURE}/tools/closure-compiler/compiler.jar" \ 33 | --charset=UTF-8 \ 34 | --compilation_level=SIMPLE_OPTIMIZATIONS \ 35 | --js=src/js/luatexts.js \ 36 | --js_output_file=src/js/luatexts.min.js \ 37 | --output_wrapper "${HEADER}" 38 | 39 | echo "----> OK" 40 | -------------------------------------------------------------------------------- /rockspec/luatexts-0.1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "luatexts" 2 | version = "0.1-1" 3 | source = { 4 | url = "git://github.com/agladysh/luatexts.git", 5 | branch = "v0.1" 6 | } 7 | description = { 8 | summary = "Trivial Lua human-readable binary-safe serialization library", 9 | homepage = "http://github.com/agladysh/luatexts", 10 | license = "MIT/X11", 11 | maintainer = "Alexander Gladysh " 12 | } 13 | dependencies = { 14 | "lua >= 5.1" 15 | } 16 | build = { 17 | type = "builtin", 18 | modules = { 19 | luatexts = { 20 | sources = { 21 | "src/c/luatexts.c", 22 | "src/c/luainternals.c" 23 | }, 24 | incdirs = { 25 | "src/c/" 26 | } 27 | }, 28 | ["luatexts.lua"] = "src/lua/luatexts/lua.lua" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rockspec/luatexts-0.1.1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "luatexts" 2 | version = "0.1.1-1" 3 | source = { 4 | url = "git://github.com/agladysh/luatexts.git", 5 | branch = "v0.1.1" 6 | } 7 | description = { 8 | summary = "Trivial Lua human-readable binary-safe serialization library", 9 | homepage = "http://github.com/agladysh/luatexts", 10 | license = "MIT/X11", 11 | maintainer = "Alexander Gladysh " 12 | } 13 | dependencies = { 14 | "lua >= 5.1" 15 | } 16 | build = { 17 | type = "builtin", 18 | modules = { 19 | luatexts = { 20 | sources = { 21 | "src/c/luatexts.c", 22 | "src/c/luainternals.c" 23 | }, 24 | incdirs = { 25 | "src/c/" 26 | } 27 | }, 28 | ["luatexts.lua"] = "src/lua/luatexts/lua.lua" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rockspec/luatexts-0.1.2-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "luatexts" 2 | version = "0.1.2-1" 3 | source = { 4 | url = "git://github.com/agladysh/luatexts.git", 5 | branch = "v0.1.2" 6 | } 7 | description = { 8 | summary = "Trivial Lua human-readable binary-safe serialization library", 9 | homepage = "http://github.com/agladysh/luatexts", 10 | license = "MIT/X11", 11 | maintainer = "Alexander Gladysh " 12 | } 13 | dependencies = { 14 | "lua >= 5.1" 15 | } 16 | build = { 17 | type = "builtin", 18 | modules = { 19 | luatexts = { 20 | sources = { 21 | "src/c/luatexts.c", 22 | "src/c/luainternals.c" 23 | }, 24 | incdirs = { 25 | "src/c/" 26 | } 27 | }, 28 | ["luatexts.lua"] = "src/lua/luatexts/lua.lua" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rockspec/luatexts-0.1.3-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "luatexts" 2 | version = "0.1.3-1" 3 | source = { 4 | url = "git://github.com/agladysh/luatexts.git", 5 | branch = "v0.1.3" 6 | } 7 | description = { 8 | summary = "Trivial Lua human-readable binary-safe serialization library", 9 | homepage = "http://github.com/agladysh/luatexts", 10 | license = "MIT/X11", 11 | maintainer = "Alexander Gladysh " 12 | } 13 | dependencies = { 14 | "lua >= 5.1" 15 | } 16 | build = { 17 | type = "builtin", 18 | modules = { 19 | luatexts = { 20 | sources = { 21 | "src/c/luatexts.c", 22 | "src/c/luainternals.c" 23 | }, 24 | incdirs = { 25 | "src/c/" 26 | } 27 | }, 28 | ["luatexts.lua"] = "src/lua/luatexts/lua.lua" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rockspec/luatexts-0.1.4-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "luatexts" 2 | version = "0.1.4-1" 3 | source = { 4 | url = "git://github.com/agladysh/luatexts.git", 5 | branch = "v0.1.4" 6 | } 7 | description = { 8 | summary = "Trivial Lua human-readable binary-safe serialization library", 9 | homepage = "http://github.com/agladysh/luatexts", 10 | license = "MIT/X11", 11 | maintainer = "Alexander Gladysh " 12 | } 13 | dependencies = { 14 | "lua >= 5.1" 15 | } 16 | build = { 17 | type = "builtin", 18 | modules = { 19 | luatexts = { 20 | sources = { 21 | "src/c/luatexts.c", 22 | "src/c/luainternals.c" 23 | }, 24 | incdirs = { 25 | "src/c/" 26 | } 27 | }, 28 | ["luatexts.lua"] = "src/lua/luatexts/lua.lua" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rockspec/luatexts-0.1.5-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "luatexts" 2 | version = "0.1.5-1" 3 | source = { 4 | url = "git://github.com/agladysh/luatexts.git", 5 | branch = "v0.1.5" 6 | } 7 | description = { 8 | summary = "Trivial Lua human-readable binary-safe serialization library", 9 | homepage = "http://github.com/agladysh/luatexts", 10 | license = "MIT/X11", 11 | maintainer = "Alexander Gladysh " 12 | } 13 | dependencies = { 14 | "lua >= 5.1" 15 | } 16 | build = { 17 | type = "builtin", 18 | modules = { 19 | luatexts = { 20 | sources = { 21 | "src/c/luatexts.c", 22 | "src/c/luainternals.c" 23 | }, 24 | incdirs = { 25 | "src/c/" 26 | } 27 | }, 28 | ["luatexts.lua"] = "src/lua/luatexts/lua.lua" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rockspec/luatexts-scm-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "luatexts" 2 | version = "scm-1" 3 | source = { 4 | url = "git://github.com/agladysh/luatexts.git", 5 | branch = "master" 6 | } 7 | description = { 8 | summary = "Trivial Lua human-readable binary-safe serialization library", 9 | homepage = "http://github.com/agladysh/luatexts", 10 | license = "MIT/X11", 11 | maintainer = "Alexander Gladysh " 12 | } 13 | dependencies = { 14 | "lua >= 5.1" 15 | } 16 | build = { 17 | type = "builtin", 18 | modules = { 19 | luatexts = { 20 | sources = { 21 | "src/c/luatexts.c", 22 | "src/c/luainternals.c" 23 | }, 24 | incdirs = { 25 | "src/c/" 26 | } 27 | }, 28 | ["luatexts.lua"] = "src/lua/luatexts/lua.lua" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/c/luainternals.c: -------------------------------------------------------------------------------- 1 | /* 2 | * luainternals.c 3 | * Code quoted from MIT-licensed Lua 5.1.4 internals 4 | * See copyright notice in lua.h 5 | */ 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif /* __cplusplus */ 10 | 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif /* __cplusplus */ 17 | 18 | #include "luainternals.h" 19 | 20 | /* 21 | * BEGIN COPY-PASTE FROM Lua 5.1.4 llimits.h 22 | */ 23 | 24 | /* chars used as small naturals (so that `char' is reserved for characters) */ 25 | typedef unsigned char lu_byte; 26 | 27 | /* 28 | * END COPY-PASTE FROM Lua 5.1.4 llimits.h 29 | */ 30 | 31 | /* 32 | * BEGIN COPY-PASTE FROM Lua 5.1.4 lobject.c 33 | */ 34 | 35 | int luaO_log2 (unsigned int x) { 36 | static const lu_byte log_2[256] = { 37 | 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 38 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 39 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 40 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 41 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 42 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 43 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 44 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 45 | }; 46 | int l = -1; 47 | while (x >= 256) { l += 8; x >>= 8; } 48 | return l + log_2[x]; 49 | 50 | } 51 | 52 | /* 53 | * END COPY-PASTE FROM Lua 5.1.4 lobject.c 54 | */ 55 | -------------------------------------------------------------------------------- /src/c/luainternals.h: -------------------------------------------------------------------------------- 1 | /* 2 | * luainternals.h 3 | * Code quoted from MIT-licensed Lua 5.1.4 internals 4 | * See copyright notice in lua.h 5 | */ 6 | 7 | #ifndef LUATEXTS_LUAINTERNALS_H_INCLUDED_ 8 | #define LUATEXTS_LUAINTERNALS_H_INCLUDED_ 9 | 10 | /* 11 | * BEGIN COPY-PASTE FROM Lua 5.1.4 luaconf.h 12 | * WARNING: If your Lua config differs, fix this! 13 | */ 14 | 15 | #define luai_numeq(a,b) ((a)==(b)) 16 | #define luai_numisnan(a) (!luai_numeq((a), (a))) 17 | 18 | /* 19 | * END COPY-PASTE FROM Lua 5.1.4 luaconf.h 20 | */ 21 | 22 | /* 23 | * BEGIN COPY-PASTE FROM Lua 5.1.4 lobject.h 24 | */ 25 | 26 | int luaO_log2 (unsigned int x); 27 | 28 | #define ceillog2(x) (luaO_log2((x)-1) + 1) 29 | 30 | /* 31 | * END COPY-PASTE FROM Lua 5.1.4 lobject.h 32 | */ 33 | 34 | /* 35 | * BEGIN COPY-PASTE FROM Lua 5.1.4 ltable.c 36 | */ 37 | 38 | #ifdef LUAI_BITSINT 39 | /* 40 | ** max size of array part is 2^MAXBITS 41 | */ 42 | #if LUAI_BITSINT > 26 43 | #define MAXBITS 26 44 | #else 45 | #define MAXBITS (LUAI_BITSINT-2) 46 | #endif 47 | 48 | /* 49 | * END COPY-PASTE FROM Lua 5.1.4 ltable.c 50 | */ 51 | 52 | #else 53 | /* LuaJIT does not have LUAI_BITSINT defined */ 54 | #define MAXBITS 26 55 | #endif 56 | 57 | /* 58 | * BEGIN COPY-PASTE FROM Lua 5.1.4 ltable.c 59 | */ 60 | 61 | #define MAXASIZE (1 << MAXBITS) 62 | 63 | /* 64 | * END COPY-PASTE FROM Lua 5.1.4 ltable.c 65 | */ 66 | 67 | #endif /* LUATEXTS_LUAINTERNALS_H_INCLUDED_ */ 68 | -------------------------------------------------------------------------------- /src/c/luatexts.c: -------------------------------------------------------------------------------- 1 | /* 2 | * luatexts.c: Trivial Lua human-readable binary-safe serialization library 3 | * See copyright information in file COPYRIGHT. 4 | */ 5 | 6 | #if defined (__cplusplus) 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "luainternals.h" 16 | 17 | /* TODO: Hide this mmap stuff in a separate file */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #if defined (__cplusplus) 26 | } 27 | #endif 28 | 29 | #define DO_XSPAM 0 30 | #define DO_XESPAM 0 31 | #define DO_SPAM 0 32 | #define DO_ESPAM 0 33 | 34 | /* Really spammy SPAM */ 35 | #if DO_XSPAM 36 | #include 37 | #define XSPAM(a) printf a 38 | #else 39 | #define XSPAM(a) (void)0 40 | #endif 41 | 42 | /* Really spammy error-message SPAM */ 43 | #if DO_XESPAM 44 | #include 45 | #define XESPAM(a) printf a 46 | #else 47 | #define XESPAM(a) (void)0 48 | #endif 49 | 50 | /* Regular SPAM */ 51 | #if DO_SPAM 52 | #include 53 | #define SPAM(a) printf a 54 | #else 55 | #define SPAM(a) (void)0 56 | #endif 57 | 58 | /* Error-message SPAM */ 59 | #if DO_ESPAM 60 | #include 61 | #define ESPAM(a) printf a 62 | #else 63 | #define ESPAM(a) (void)0 64 | #endif 65 | 66 | #define LUATEXTS_VERSION "luatexts 0.1.5" 67 | #define LUATEXTS_COPYRIGHT "Copyright (C) 2011-2013, luatexts authors" 68 | #define LUATEXTS_DESCRIPTION \ 69 | "Trivial Lua human-readable binary-safe serialization library" 70 | 71 | #define LUATEXTS_ESUCCESS (0) 72 | #define LUATEXTS_EFAILURE (1) 73 | #define LUATEXTS_EBADSIZE (2) 74 | #define LUATEXTS_EBADDATA (3) 75 | #define LUATEXTS_EBADTYPE (4) 76 | #define LUATEXTS_EGARBAGE (5) 77 | #define LUATEXTS_ETOOHUGE (6) 78 | #define LUATEXTS_EBADUTF8 (7) 79 | #define LUATEXTS_ECLIPPED (8) 80 | 81 | #define LUATEXTS_CNIL '-' /* 0x2D (45) */ 82 | #define LUATEXTS_CFALSE '0' /* 0x30 (48) */ 83 | #define LUATEXTS_CTRUE '1' /* 0x31 (49) */ 84 | #define LUATEXTS_CNUMBER 'N' /* 0x4E (78) */ 85 | #define LUATEXTS_CUINT 'U' /* 0x55 (85) */ 86 | #define LUATEXTS_CUINTHEX 'H' /* 0x48 (48) */ 87 | #define LUATEXTS_CUINT36 'Z' /* 0x5A (90) */ 88 | #define LUATEXTS_CSTRING 'S' /* 0x53 (83) */ 89 | #define LUATEXTS_CFIXEDTABLE 'T' /* 0x54 (84) */ 90 | #define LUATEXTS_CSTREAMTABLE 't' /* 0x74 (116) */ 91 | #define LUATEXTS_CSTRINGUTF8 '8' /* 0x38 (56) */ 92 | 93 | /* WARNING: Make sure these match your luaconf.h */ 94 | typedef lua_Number LUATEXTS_NUMBER; 95 | typedef unsigned long LUATEXTS_UINT; 96 | 97 | #define luatexts_tonumber strtod 98 | 99 | #if defined(__GNUC__) 100 | 101 | #define LUATEXTS_LIKELY(x) __builtin_expect(!!(x), 1) 102 | #define LUATEXTS_UNLIKELY(x) __builtin_expect(!!(x), 0) 103 | 104 | #endif /* defined(__GNUC__) */ 105 | 106 | #ifndef LUATEXTS_LIKELY 107 | 108 | #define LUATEXTS_LIKELY(x) (x) 109 | #define LUATEXTS_UNLIKELY(x) (x) 110 | 111 | #endif /* !defined(LUATEXTS_LIKELY) */ 112 | 113 | #define LUATEXTS_CONCAT_(lhs, rhs) lhs ## rhs 114 | #define LUATEXTS_CONCAT(lhs, rhs) LUATEXTS_CONCAT_(lhs, rhs) 115 | 116 | #define LUATEXTS_STRINGIFY_(a) #a 117 | #define LUATEXTS_STRINGIFY(a) LUATEXTS_STRINGIFY_(a) 118 | 119 | typedef struct lts_LoadState 120 | { 121 | const unsigned char * pos; 122 | size_t unread; 123 | } lts_LoadState; 124 | 125 | static void ltsLS_init( 126 | lts_LoadState * ls, 127 | const unsigned char * data, 128 | size_t len 129 | ) 130 | { 131 | ls->pos = (len > 0) ? data : NULL; 132 | ls->unread = len; 133 | } 134 | 135 | #define ltsLS_good(ls) \ 136 | ((ls)->pos != NULL) 137 | 138 | #define ltsLS_unread(ls) \ 139 | ((ls)->unread) 140 | 141 | #define ltsLS_close(ls) \ 142 | do { \ 143 | (ls)->unread = 0; \ 144 | (ls)->pos = NULL; \ 145 | } while (0) 146 | 147 | static const unsigned char * ltsLS_eat(lts_LoadState * ls, size_t len) 148 | { 149 | const unsigned char * result = NULL; 150 | if (LUATEXTS_LIKELY(ltsLS_good(ls))) 151 | { 152 | if (LUATEXTS_LIKELY(ltsLS_unread(ls) >= len)) 153 | { 154 | result = ls->pos; 155 | ls->pos += len; 156 | ls->unread -= len; 157 | } 158 | else 159 | { 160 | ltsLS_close(ls); 161 | return NULL; 162 | } 163 | } 164 | 165 | return result; 166 | } 167 | 168 | #define LUATEXTS_FAIL(ls, status, msg) \ 169 | do { \ 170 | ESPAM(msg); \ 171 | ltsLS_close(ls); \ 172 | return (status); \ 173 | } while (0) 174 | 175 | #define LUATEXTS_ENSURE(ls, x, status, msg) \ 176 | do { \ 177 | if (LUATEXTS_UNLIKELY(!(x))) \ 178 | { \ 179 | LUATEXTS_FAIL(ls, status, msg); \ 180 | } \ 181 | } while (0) 182 | 183 | #define EAT_CHAR(ls, msg) \ 184 | do { \ 185 | LUATEXTS_ENSURE(ls, \ 186 | ltsLS_unread((ls)) > 0, \ 187 | LUATEXTS_ECLIPPED, (msg ": clipped\n") \ 188 | ); \ 189 | ++(ls)->pos; \ 190 | --(ls)->unread; \ 191 | } while (0) 192 | 193 | #define EAT_NEWLINE(ls, msg) \ 194 | do { \ 195 | if (*(ls)->pos == '\r') \ 196 | { \ 197 | EAT_CHAR((ls), msg); \ 198 | } \ 199 | LUATEXTS_ENSURE((ls), \ 200 | *(ls)->pos == '\n', \ 201 | LUATEXTS_EGARBAGE, (msg ": garbage\n") \ 202 | ); \ 203 | EAT_CHAR((ls), msg); \ 204 | } while (0); 205 | 206 | /* 207 | * UTF-8 handling implemented based on information here: 208 | * http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 209 | * 210 | * Updated with the information here: 211 | * 212 | * http://codereview.stackexchange.com/q/1624/234 213 | */ 214 | 215 | static const signed char utf8_char_len[256] = 216 | { 217 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 218 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 219 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 220 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 221 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 222 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 223 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 224 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 225 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 226 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 227 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 228 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 229 | 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 230 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 231 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 232 | 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 233 | }; 234 | 235 | /* 236 | * (From Chapter 3 of the 6.0.0 Unicode Standard) 237 | * 238 | * Table 3-7. Well-Formed UTF-8 Byte Sequences 239 | * Code Points First Byte Second Byte Third Byte Fourth Byte 240 | * U+0000..U+007F 00..7F 241 | * U+0080..U+07FF C2..DF 80..BF 242 | * U+0800..U+0FFF E0 A0..BF 80..BF 243 | * U+1000..U+CFFF E1..EC 80..BF 80..BF 244 | * U+D000..U+D7FF ED 80..9F 80..BF 245 | * U+E000..U+FFFF EE..EF 80..BF 80..BF 246 | * U+10000..U+3FFFF F0 90..BF 80..BF 80..BF 247 | * U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF 248 | * U+100000..U+10FFFF F4 80..8F 80..BF 80..BF 249 | */ 250 | 251 | /* 252 | * *Increments* len_bytes by the number of bytes read. 253 | * Fails on invalid UTF-8 characters. 254 | */ 255 | static int ltsLS_eatutf8char(lts_LoadState * ls, size_t * len_bytes) 256 | { 257 | unsigned char b = 0; 258 | signed char exp_len = 0; 259 | int i = 0; 260 | const unsigned char * origin = ls->pos; 261 | 262 | /* Check if we have any data in the buffer */ 263 | LUATEXTS_ENSURE(ls, 264 | ltsLS_good(ls) && ltsLS_unread(ls) >= 1, 265 | LUATEXTS_ECLIPPED, ("eatutf8char: no buffer to start with\n") 266 | ); 267 | 268 | /* We have at least one byte in the buffer, let's check it out. */ 269 | b = *ls->pos; 270 | 271 | /* We did just eat a byte, no matter what happens next. */ 272 | ++ls->pos; 273 | --ls->unread; 274 | 275 | /* Get an expected length of a character. */ 276 | exp_len = utf8_char_len[b]; 277 | XSPAM(( 278 | "eatutf8char: first byte 0x%X (%d) expected length: %d\n", 279 | b, b, exp_len 280 | )); 281 | 282 | /* Check if it was a valid first byte. */ 283 | LUATEXTS_ENSURE(ls, 284 | exp_len >= 1, 285 | LUATEXTS_EBADUTF8, ("eatutf8char: invalid start byte 0x%X (%d)\n", b, b) 286 | ); 287 | 288 | /* If it was a single-byte ASCII character, return right away. */ 289 | if (LUATEXTS_LIKELY(exp_len == 1)) 290 | { 291 | XSPAM(("eatutf8char: ascii 0x%X (%d)\n", b, b)); 292 | 293 | *len_bytes += exp_len; 294 | 295 | return LUATEXTS_ESUCCESS; 296 | } 297 | 298 | /* 299 | * It was a multi-byte character. Check if we have enough bytes unread. 300 | * Note that we've eaten one byte already. 301 | */ 302 | LUATEXTS_ENSURE(ls, 303 | ltsLS_unread(ls) + 1 >= (unsigned char)exp_len, 304 | LUATEXTS_ECLIPPED, ("eatutf8char: multibyte character clipped") 305 | ); 306 | 307 | /* Let's eat the rest of characters */ 308 | for (i = 1; i < exp_len; ++i) 309 | { 310 | b = *ls->pos; 311 | 312 | /* We did just eat a byte, no matter what happens next. */ 313 | ++ls->pos; 314 | --ls->unread; 315 | 316 | XSPAM(("eatutf8char: cont 0x%X (%d)\n", b, b)); 317 | 318 | /* Check if it is a continuation byte */ 319 | LUATEXTS_ENSURE(ls, 320 | utf8_char_len[b] == -1, 321 | LUATEXTS_EBADUTF8, 322 | ("eatutf8char: invalid continuation byte 0x%X (%d)\n", b, b) 323 | ); 324 | } 325 | 326 | /* All bytes are correct; check out for overlong forms and surrogates */ 327 | LUATEXTS_ENSURE(ls, 328 | !( 329 | (exp_len == 2 && ((origin[0] & 0xFE) == 0xC0)) || 330 | (exp_len == 3 && (origin[0] == 0xE0 && (origin[1] & 0xE0) == 0x80)) || 331 | (exp_len == 4 && (origin[0] == 0xF0 && (origin[1] & 0xF0) == 0x80)) || 332 | (exp_len == 4 && (origin[0] == 0xF4 && (origin[1] > 0x8F))) || 333 | (exp_len == 3 && (origin[0] == 0xED && (origin[1] & 0xE0) != 0x80)) 334 | ), 335 | LUATEXTS_EBADUTF8, ("eatutf8char: overlong or surrogate detected\n") 336 | ); 337 | 338 | /* Reject BOM non-characters: U+FFFE and U+FFFF */ 339 | LUATEXTS_ENSURE(ls, 340 | !( 341 | exp_len == 3 && ( 342 | (origin[0] == 0xEF && origin[1] == 0xBF && origin[2] == 0xBE) || 343 | (origin[0] == 0xEF && origin[1] == 0xBF && origin[2] == 0xBF) 344 | ) 345 | ), 346 | LUATEXTS_EBADUTF8, ("eatutf8char: BOM detected\n") 347 | ); 348 | 349 | /* Phew. All done, the UTF-8 character is valid. */ 350 | 351 | XSPAM(("eatutf8char: read one char successfully\n")); 352 | 353 | *len_bytes += exp_len; 354 | 355 | return LUATEXTS_ESUCCESS; 356 | } 357 | 358 | /* 359 | * Eats specified number of UTF-8 characters. Returns NULL if failed. 360 | * Fails on invalid UTF-8 characters. 361 | */ 362 | static int ltsLS_eatutf8( 363 | lts_LoadState * ls, 364 | size_t num_chars, 365 | const unsigned char ** dest, 366 | size_t * len_bytes 367 | ) 368 | { 369 | const unsigned char * origin = ls->pos; 370 | size_t num_bytes = 0; 371 | size_t i = 0; 372 | int result = LUATEXTS_ESUCCESS; 373 | 374 | for (i = 0; i < num_chars; ++i) 375 | { 376 | result = ltsLS_eatutf8char(ls, &num_bytes); 377 | 378 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 379 | { 380 | ESPAM(("eatutf8: failed to eat char %lu\n", (long unsigned int)i)); 381 | return result; 382 | } 383 | } 384 | 385 | *dest = origin; 386 | *len_bytes = num_bytes; 387 | 388 | return LUATEXTS_ESUCCESS; 389 | } 390 | 391 | /* 392 | * Returned length does not include trailing '\r\n' (or '\n' if '\r' is missing). 393 | * It is guaranteed that on success it is safe to read byte at (*dest + len + 1) 394 | * and that byte is either '\r' or '\n'. 395 | */ 396 | static int ltsLS_readline( 397 | lts_LoadState * ls, 398 | const unsigned char ** dest, 399 | size_t * len 400 | ) 401 | { 402 | const unsigned char * origin = ls->pos; 403 | const unsigned char * last = NULL; 404 | size_t read = 0; 405 | 406 | while (ltsLS_good(ls)) 407 | { 408 | if (LUATEXTS_LIKELY(ltsLS_unread(ls) > 0)) 409 | { 410 | const unsigned char * cur = ls->pos; 411 | ++ls->pos; 412 | --ls->unread; 413 | 414 | if (LUATEXTS_UNLIKELY(*cur == '\n')) 415 | { 416 | *dest = origin; 417 | *len = (last != NULL && *last == '\r') ? read - 1 : read; 418 | 419 | return LUATEXTS_ESUCCESS; 420 | } 421 | 422 | last = cur; 423 | ++read; 424 | } 425 | else 426 | { 427 | ltsLS_close(ls); 428 | break; 429 | } 430 | } 431 | 432 | ESPAM(("readline: clipped\n")); 433 | 434 | return LUATEXTS_ECLIPPED; 435 | } 436 | 437 | static const signed char uint_lookup_table_10[256] = 438 | { 439 | /* 0*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 440 | /* 16*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 441 | /* 32*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 442 | /* 48*/ 0, 1, 2, 3, 4, 5, 6, 7, 8 , 9 ,-1, -1, -1, -1, -1, -1, 443 | /* 64*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 444 | /* 80*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 445 | /* 96*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 446 | /*112*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 447 | /*128*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 448 | /*144*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 449 | /*160*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 450 | /*176*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 451 | /*192*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 452 | /*208*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 453 | /*224*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 454 | /*240*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1 455 | }; 456 | 457 | static const signed char uint_lookup_table_16[256] = 458 | { 459 | /* 0*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 460 | /* 16*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 461 | /* 32*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 462 | /* 48*/ 0, 1, 2, 3, 4, 5, 6, 7, 8 , 9 ,-1, -1, -1, -1, -1, -1, 463 | /* 64*/ -1, 10, 11, 12, 13, 14, 15, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 464 | /* 80*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 465 | /* 96*/ -1, 10, 11, 12, 13, 14, 15, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 466 | /*112*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 467 | /*128*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 468 | /*144*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 469 | /*160*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 470 | /*176*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 471 | /*192*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 472 | /*208*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 473 | /*224*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 474 | /*240*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1 475 | }; 476 | 477 | static const signed char uint_lookup_table_36[256] = 478 | { 479 | /* 0*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 480 | /* 16*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 481 | /* 32*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 482 | /* 48*/ 0, 1, 2, 3, 4, 5, 6, 7, 8 , 9 ,-1, -1, -1, -1, -1, -1, 483 | /* 64*/ -1, 10, 11, 12, 13, 14, 15, 16, 17 ,18 ,19, 20, 21, 22, 23, 24, 484 | /* 80*/ 25, 26, 27, 28, 29, 30, 31, 32, 33 ,34 ,35, -1, -1, -1, -1, -1, 485 | /* 96*/ -1, 10, 11, 12, 13, 14, 15, 16, 17 ,18 ,19, 20, 21, 22, 23, 24, 486 | /*112*/ 25, 26, 27, 28, 29, 30, 31, 32, 33 ,34 ,35, -1, -1, -1, -1, -1, 487 | /*128*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 488 | /*144*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 489 | /*160*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 490 | /*176*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 491 | /*192*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 492 | /*208*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 493 | /*224*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1, 494 | /*240*/ -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1 ,-1, -1, -1, -1, -1, -1 495 | }; 496 | 497 | /* 498 | Not supporting leading '-' (this is unsigned int) 499 | and not eating leading whitespace 500 | (it is accidental that strtoul eats it, 501 | luatexts format formally does not support this). 502 | */ 503 | #define DECLARE_READUINT(ltsLS_readuint, BASE, LIMIT, TAIL) \ 504 | static int LUATEXTS_CONCAT(ltsLS_readuint, BASE)( \ 505 | lts_LoadState * ls, \ 506 | LUATEXTS_UINT * dest \ 507 | ) \ 508 | { \ 509 | LUATEXTS_UINT k = 0; \ 510 | if (LUATEXTS_UNLIKELY(!ltsLS_good(ls))) \ 511 | { \ 512 | ESPAM((LUATEXTS_STRINGIFY(LUATEXTS_CONCAT(ltsLS_readuint, BASE)) \ 513 | ": clipped\n")); \ 514 | return LUATEXTS_ECLIPPED; \ 515 | } \ 516 | LUATEXTS_ENSURE(ls, \ 517 | LUATEXTS_CONCAT(uint_lookup_table_, BASE)[*ls->pos] >= 0, \ 518 | LUATEXTS_EBADDATA, \ 519 | (LUATEXTS_STRINGIFY(LUATEXTS_CONCAT(ltsLS_readuint, BASE)) \ 520 | ": first character is not a number\n") \ 521 | ); \ 522 | while (LUATEXTS_CONCAT(uint_lookup_table_, BASE)[*ls->pos] >= 0) \ 523 | { \ 524 | LUATEXTS_ENSURE(ls, \ 525 | !( \ 526 | (k >= LIMIT) && \ 527 | ( \ 528 | k != LIMIT || \ 529 | LUATEXTS_CONCAT(uint_lookup_table_, BASE)[*ls->pos] > TAIL \ 530 | ) \ 531 | ), \ 532 | LUATEXTS_ETOOHUGE, \ 533 | (LUATEXTS_STRINGIFY(LUATEXTS_CONCAT(ltsLS_readuint, BASE)) \ 534 | ": value does not fit to uint32_t\n") \ 535 | ); \ 536 | k = k * BASE + LUATEXTS_CONCAT(uint_lookup_table_, BASE)[*ls->pos]; \ 537 | EAT_CHAR(ls, LUATEXTS_STRINGIFY(LUATEXTS_CONCAT(ltsLS_readuint, BASE))); \ 538 | } \ 539 | EAT_NEWLINE( \ 540 | ls, LUATEXTS_STRINGIFY(LUATEXTS_CONCAT(ltsLS_readuint, BASE)) \ 541 | ); \ 542 | *dest = k; \ 543 | return LUATEXTS_ESUCCESS; \ 544 | } 545 | 546 | DECLARE_READUINT(ltsLS_readuint, 10, 429496729, 5) 547 | DECLARE_READUINT(ltsLS_readuint, 16, 0xFFFFFFF, 0xF) 548 | DECLARE_READUINT(ltsLS_readuint, 36, 119304647, 3) 549 | 550 | #undef DECLARE_READUINT 551 | 552 | static int ltsLS_readnumber(lts_LoadState * ls, LUATEXTS_NUMBER * dest) 553 | { 554 | size_t len = 0; 555 | const unsigned char * data = NULL; 556 | int result = ltsLS_readline(ls, &data, &len); 557 | char * endptr = NULL; 558 | LUATEXTS_NUMBER value = 0; 559 | 560 | if (result != LUATEXTS_ESUCCESS) 561 | { 562 | ESPAM(("readnumber: failed to read line")); 563 | return result; 564 | } 565 | 566 | LUATEXTS_ENSURE(ls, 567 | len > 0, 568 | LUATEXTS_EBADDATA, ("readnumber: empty line instead of number\n") 569 | ); 570 | 571 | /* 572 | * This is safe, since we're guaranteed to have 573 | * at least one non-numeric trailing byte. 574 | */ 575 | value = strtod((const char *)data, &endptr); 576 | LUATEXTS_ENSURE(ls, 577 | (const unsigned char *)endptr == data + len, 578 | LUATEXTS_EGARBAGE, ("readnumber: garbage before eol\n") 579 | ); 580 | 581 | *dest = value; 582 | 583 | return LUATEXTS_ESUCCESS; 584 | } 585 | 586 | static int load_value(lua_State * L, lts_LoadState * ls); 587 | 588 | /* 589 | * TODO: generalize with load_stream_table. 590 | */ 591 | static int load_fixed_table(lua_State * L, lts_LoadState * ls) 592 | { 593 | LUATEXTS_UINT array_size = 0; 594 | LUATEXTS_UINT hash_size = 0; 595 | 596 | LUATEXTS_UINT i = 0; 597 | 598 | int result = ltsLS_readuint10(ls, &array_size); 599 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 600 | { 601 | ESPAM(("load_fixed_table: failed to read array size")); 602 | return result; 603 | } 604 | 605 | result = ltsLS_readuint10(ls, &hash_size); 606 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 607 | { 608 | ESPAM(("load_fixed_table: failed to read hash size")); 609 | return result; 610 | } 611 | 612 | LUATEXTS_ENSURE(ls, 613 | array_size >= 0 && array_size <= MAXASIZE && 614 | hash_size >= 0 && 615 | (hash_size == 0 || ceillog2((unsigned int)hash_size) <= MAXBITS) && 616 | /* 617 | * Simplification: Assuming minimum value size is one byte. 618 | */ 619 | ltsLS_unread(ls) >= (array_size + hash_size * 2), 620 | LUATEXTS_ETOOHUGE, ("load_fixed_table: too huge\n") 621 | ); 622 | SPAM(( 623 | "load_fixed_table: size: %lu array + %lu hash = %lu total\n", 624 | array_size, hash_size, array_size + hash_size 625 | )); 626 | 627 | lua_createtable(L, array_size, hash_size); 628 | 629 | for (i = 0; i < array_size; ++i) 630 | { 631 | result = load_value(L, ls); /* Load value. */ 632 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 633 | { 634 | ESPAM(("load_fixed_table: failed to read array part value\n")); 635 | return result; 636 | } 637 | 638 | lua_rawseti(L, -2, i + 1); 639 | } 640 | 641 | for (i = 0; i < hash_size; ++i) 642 | { 643 | int key_type = LUA_TNONE; 644 | 645 | result = load_value(L, ls); /* Load key. */ 646 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 647 | { 648 | ESPAM(("load_fixed_table: failed to read key\n")); 649 | return result; 650 | } 651 | 652 | /* Table key can't be nil or NaN */ 653 | key_type = lua_type(L, -1); 654 | LUATEXTS_ENSURE(ls, 655 | key_type != LUA_TNIL && 656 | !(key_type == LUA_TNUMBER && luai_numisnan(lua_tonumber(L, -1))), 657 | LUATEXTS_EBADDATA, ("load_fixed_table: key is nil or nan\n") 658 | ); 659 | 660 | result = load_value(L, ls); /* Load value. */ 661 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 662 | { 663 | ESPAM(("load_fixed_table: failed to read value\n")); 664 | return result; 665 | } 666 | 667 | lua_rawset(L, -3); 668 | } 669 | 670 | return LUATEXTS_ESUCCESS; 671 | } 672 | 673 | /* 674 | * TODO: generalize with load_fixed_table. 675 | */ 676 | static int load_stream_table(lua_State * L, lts_LoadState * ls) 677 | { 678 | lua_newtable(L); 679 | 680 | while (1) /* We're limited by buffer length */ 681 | { 682 | int key_type = LUA_TNONE; 683 | 684 | int result = load_value(L, ls); /* Load key. */ 685 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 686 | { 687 | ESPAM(("load_stream_table: failed to read key\n")); 688 | return result; 689 | } 690 | 691 | /* If "key" is nil, this is the end of table (no value expected). */ 692 | key_type = lua_type(L, -1); 693 | if (key_type == LUA_TNIL) 694 | { 695 | lua_pop(L, 1); /* Pop terminating nil */ 696 | break; 697 | } 698 | 699 | LUATEXTS_ENSURE(ls, 700 | !(key_type == LUA_TNUMBER && luai_numisnan(lua_tonumber(L, -1))), 701 | LUATEXTS_EBADDATA, ("load_stream_table: key is nan\n") 702 | ); 703 | 704 | result = load_value(L, ls); /* Load value. */ 705 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 706 | { 707 | ESPAM(("load_stream_table: failed to read value\n")); 708 | return result; 709 | } 710 | 711 | lua_rawset(L, -3); 712 | } 713 | 714 | return LUATEXTS_ESUCCESS; 715 | } 716 | 717 | static int load_value(lua_State * L, lts_LoadState * ls) 718 | { 719 | size_t len = 0; 720 | const unsigned char * type = NULL; 721 | 722 | int result = LUATEXTS_ESUCCESS; 723 | 724 | if (LUATEXTS_UNLIKELY(!ltsLS_good(ls))) 725 | { 726 | ESPAM(("load_value: clipped\n")); 727 | return LUATEXTS_ECLIPPED; 728 | } 729 | 730 | /* Read value type */ 731 | type = ls->pos; 732 | 733 | EAT_CHAR(ls, "ltsLS_readuint10"); 734 | 735 | EAT_NEWLINE(ls, "ltsLS_readuint10"); 736 | 737 | /* Read value data if any, and push the value to Lua state */ 738 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 739 | { 740 | SPAM(( 741 | "load_value: value type '%c' 0x%X (%d)\n", 742 | isgraph(*type) ? *type : '?', *type, *type 743 | )); 744 | 745 | luaL_checkstack(L, 1, "load-value"); 746 | 747 | switch (*type) 748 | { 749 | case LUATEXTS_CNIL: 750 | lua_pushnil(L); 751 | break; 752 | 753 | case LUATEXTS_CFALSE: 754 | lua_pushboolean(L, 0); 755 | break; 756 | 757 | case LUATEXTS_CTRUE: 758 | lua_pushboolean(L, 1); 759 | break; 760 | 761 | case LUATEXTS_CNUMBER: 762 | { 763 | lua_Number value; 764 | 765 | result = ltsLS_readnumber(ls, &value); 766 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 767 | { 768 | lua_pushnumber(L, value); 769 | } 770 | } 771 | break; 772 | 773 | case LUATEXTS_CUINT: 774 | { 775 | LUATEXTS_UINT value; 776 | 777 | result = ltsLS_readuint10(ls, &value); 778 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 779 | { 780 | /* TODO: Maybe do lua_pushinteger if value fits? */ 781 | lua_pushnumber(L, value); 782 | } 783 | } 784 | break; 785 | 786 | case LUATEXTS_CUINTHEX: 787 | { 788 | LUATEXTS_UINT value; 789 | 790 | result = ltsLS_readuint16(ls, &value); 791 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 792 | { 793 | /* TODO: Maybe do lua_pushinteger if value fits? */ 794 | lua_pushnumber(L, value); 795 | } 796 | } 797 | break; 798 | 799 | case LUATEXTS_CUINT36: 800 | { 801 | LUATEXTS_UINT value; 802 | 803 | result = ltsLS_readuint36(ls, &value); 804 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 805 | { 806 | /* TODO: Maybe do lua_pushinteger if value fits? */ 807 | lua_pushnumber(L, value); 808 | } 809 | } 810 | break; 811 | 812 | case LUATEXTS_CSTRING: 813 | { 814 | const unsigned char * str = NULL; 815 | 816 | /* Read string size */ 817 | LUATEXTS_UINT len = 0; 818 | result = ltsLS_readuint10(ls, &len); 819 | 820 | /* Check size */ 821 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 822 | { 823 | /* Implementation detail */ 824 | if (LUATEXTS_UNLIKELY((lua_Integer)len < 0)) 825 | { 826 | ESPAM(("string: value does not fit to lua_Integer\n")); 827 | ltsLS_close(ls); 828 | result = LUATEXTS_ETOOHUGE; 829 | } 830 | } 831 | 832 | /* Read string data */ 833 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 834 | { 835 | str = ltsLS_eat(ls, len); 836 | if (LUATEXTS_UNLIKELY(str == NULL)) 837 | { 838 | ESPAM(("load_value: bad string size\n")); 839 | ltsLS_close(ls); 840 | result = LUATEXTS_EBADSIZE; 841 | } 842 | } 843 | 844 | /* Eat newline after string data */ 845 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 846 | { 847 | size_t empty = 0; 848 | const unsigned char * nl = NULL; 849 | result = ltsLS_readline(ls, &nl, &empty); 850 | if ( 851 | LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS) 852 | && LUATEXTS_UNLIKELY(empty != 0) 853 | ) 854 | { 855 | ESPAM(("load_value: string: garbage before eol\n")); 856 | ltsLS_close(ls); 857 | result = LUATEXTS_EGARBAGE; 858 | } 859 | } 860 | 861 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 862 | { 863 | lua_pushlstring(L, (const char *)str, len); 864 | } 865 | } 866 | break; 867 | 868 | case LUATEXTS_CSTRINGUTF8: 869 | { 870 | const unsigned char * str = NULL; 871 | 872 | /* Read string size */ 873 | LUATEXTS_UINT len_chars = 0; 874 | size_t len_bytes = 0; 875 | result = ltsLS_readuint10(ls, &len_chars); 876 | 877 | /* Check size */ 878 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 879 | { 880 | /* Implementation detail */ 881 | if (LUATEXTS_UNLIKELY((lua_Integer)len < 0)) 882 | { 883 | ESPAM(("stringutf8: value does not fit to lua_Integer\n")); 884 | ltsLS_close(ls); 885 | result = LUATEXTS_ETOOHUGE; 886 | } 887 | } 888 | 889 | /* Read string data */ 890 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 891 | { 892 | result = ltsLS_eatutf8(ls, len_chars, &str, &len_bytes); 893 | } 894 | 895 | /* Eat newline after string data */ 896 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 897 | { 898 | size_t empty = 0; 899 | const unsigned char * nl = NULL; 900 | result = ltsLS_readline(ls, &nl, &empty); 901 | if ( 902 | LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS) 903 | && LUATEXTS_UNLIKELY(empty != 0) 904 | ) 905 | { 906 | ESPAM(("load_value: utf8: garbage before eol\n")); 907 | ltsLS_close(ls); 908 | result = LUATEXTS_EGARBAGE; 909 | } 910 | } 911 | 912 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 913 | { 914 | lua_pushlstring(L, (const char *)str, len_bytes); 915 | } 916 | } 917 | break; 918 | 919 | case LUATEXTS_CFIXEDTABLE: 920 | result = load_fixed_table(L, ls); 921 | break; 922 | 923 | case LUATEXTS_CSTREAMTABLE: 924 | result = load_stream_table(L, ls); 925 | break; 926 | 927 | default: 928 | ESPAM(("load_value: unknown type char 0x%X (%d)\n", type[0], type[0])); 929 | ltsLS_close(ls); 930 | result = LUATEXTS_EBADTYPE; 931 | break; 932 | } 933 | } 934 | 935 | return result; 936 | } 937 | 938 | static int luatexts_load( 939 | lua_State * L, 940 | const unsigned char * buf, 941 | size_t len, 942 | size_t * count 943 | ) 944 | { 945 | int result = LUATEXTS_ESUCCESS; 946 | lts_LoadState ls; 947 | 948 | LUATEXTS_UINT tuple_size = 0; 949 | LUATEXTS_UINT i = 0; 950 | 951 | int base = lua_gettop(L); 952 | 953 | ltsLS_init(&ls, buf, len); 954 | 955 | /* 956 | * Security note: not checking tuple_size for sanity. 957 | * Motivation: too complicated; we will fail if buffer is too small anyway. 958 | */ 959 | 960 | result = ltsLS_readuint10(&ls, &tuple_size); 961 | /* Check size */ 962 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 963 | { 964 | /* Implementation detail */ 965 | if (LUATEXTS_UNLIKELY((lua_Integer)tuple_size < 0)) 966 | { 967 | ESPAM(("tuple: size does not fit to lua_Integer\n")); 968 | ltsLS_close(&ls); 969 | result = LUATEXTS_ETOOHUGE; 970 | } 971 | } 972 | 973 | for (i = 0; i < tuple_size && result == LUATEXTS_ESUCCESS; ++i) 974 | { 975 | SPAM(("load_tuple: loading value %lu of %lu\n", i + 1, tuple_size)); 976 | result = load_value(L, &ls); 977 | } 978 | 979 | /* 980 | * Security note: ignoring unread bytes if any. 981 | * Motivation: more casual, this is a text format after all. 982 | */ 983 | 984 | if (LUATEXTS_LIKELY(result == LUATEXTS_ESUCCESS)) 985 | { 986 | *count = tuple_size; 987 | } 988 | else 989 | { 990 | XESPAM(("load_tuple: error %d\n", result)); 991 | 992 | lua_settop(L, base); /* Discard intermediate results */ 993 | 994 | luaL_checkstack(L, 1, "load-err"); 995 | 996 | switch (result) 997 | { 998 | case LUATEXTS_EBADSIZE: 999 | lua_pushliteral(L, "load failed: corrupt data, bad size"); 1000 | break; 1001 | 1002 | case LUATEXTS_EBADDATA: 1003 | lua_pushliteral(L, "load failed: corrupt data"); 1004 | break; 1005 | 1006 | case LUATEXTS_EBADTYPE: 1007 | lua_pushliteral(L, "load failed: unknown data type"); 1008 | break; 1009 | 1010 | case LUATEXTS_EGARBAGE: 1011 | lua_pushliteral(L, "load failed: garbage before newline"); 1012 | break; 1013 | 1014 | case LUATEXTS_ETOOHUGE: 1015 | lua_pushliteral(L, "load failed: value too huge"); 1016 | break; 1017 | 1018 | case LUATEXTS_EBADUTF8: 1019 | lua_pushliteral(L, "load failed: invalid utf-8 data"); 1020 | break; 1021 | 1022 | case LUATEXTS_ECLIPPED: 1023 | lua_pushliteral(L, "load failed: corrupt data, truncated"); 1024 | break; 1025 | 1026 | /* should not happen */ 1027 | case LUATEXTS_EFAILURE: 1028 | default: 1029 | lua_pushliteral(L, "load failed: internal error"); 1030 | break; 1031 | } 1032 | } 1033 | 1034 | return result; 1035 | } 1036 | 1037 | static int lload(lua_State * L) 1038 | { 1039 | size_t len = 0; 1040 | const unsigned char * buf = (const unsigned char *)luaL_checklstring( 1041 | L, 1, &len 1042 | ); 1043 | size_t tuple_size = 0; 1044 | int result = 0; 1045 | 1046 | luaL_checkstack(L, 1, "lload"); 1047 | lua_pushboolean(L, 1); 1048 | 1049 | result = luatexts_load(L, buf, len, &tuple_size); 1050 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 1051 | { 1052 | luaL_checkstack(L, 1, "lload-err"); 1053 | lua_pushnil(L); 1054 | lua_replace(L, -3); /* Replace pre-pushed true with nil */ 1055 | return 2; /* Error message already on stack */ 1056 | } 1057 | 1058 | return tuple_size + 1; 1059 | } 1060 | 1061 | /* TODO: Hide this mmap stuff in a separate file */ 1062 | /* TODO: Support fd as an argument instead of a filename */ 1063 | /* 1064 | * TODO: Not quite exception-safe. 1065 | * Must put close() and unmap() calls to __gc somewhere, 1066 | * so they would be called on error. 1067 | */ 1068 | static int lload_from_file(lua_State * L) 1069 | { 1070 | const char * filename = (const char *)luaL_checkstring(L, 1); 1071 | 1072 | size_t tuple_size = 0; 1073 | int result = 0; 1074 | 1075 | const unsigned char * buf = NULL; 1076 | 1077 | struct stat sb; 1078 | 1079 | int fd = open(filename, O_RDONLY); 1080 | if (fd == -1) 1081 | { 1082 | luaL_checkstack(L, 2, "lloadff-err"); 1083 | lua_pushnil(L); 1084 | lua_pushfstring( 1085 | L, "load_from_file failed: can't open " LUA_QL("%s") " for reading: %s", 1086 | filename, strerror(errno) 1087 | ); 1088 | return 2; 1089 | } 1090 | 1091 | if (fstat(fd, &sb) == -1) 1092 | { 1093 | luaL_checkstack(L, 2, "lloadff-err"); 1094 | lua_pushnil(L); 1095 | lua_pushfstring( 1096 | L, "load_from_file failed: can't stat " LUA_QL("%s") ": %s", 1097 | filename, strerror(errno) 1098 | ); 1099 | close(fd); 1100 | return 2; 1101 | } 1102 | 1103 | if (!S_ISREG(sb.st_mode)) 1104 | { 1105 | luaL_checkstack(L, 2, "lloadff-err"); 1106 | lua_pushnil(L); 1107 | lua_pushfstring( 1108 | L, "load_from_file failed: " LUA_QL("%s") " is not a file", 1109 | filename 1110 | ); 1111 | close(fd); 1112 | return 2; 1113 | } 1114 | 1115 | if (sb.st_size == 0) 1116 | { 1117 | luaL_checkstack(L, 2, "lloadff-err"); 1118 | lua_pushnil(L); 1119 | lua_pushfstring( 1120 | L, "load_from_file failed: " LUA_QL("%s") " is empty", 1121 | filename 1122 | ); 1123 | close(fd); 1124 | return 2; 1125 | } 1126 | 1127 | buf = (const unsigned char *)mmap( 1128 | 0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0 1129 | ); 1130 | if (buf == MAP_FAILED) 1131 | { 1132 | luaL_checkstack(L, 2, "lloadff-err"); 1133 | lua_pushnil(L); 1134 | lua_pushfstring( 1135 | L, "load_from_file failed: " LUA_QL("%s") " mmap failed: %s", 1136 | filename, strerror(errno) 1137 | ); 1138 | close(fd); 1139 | return 2; 1140 | } 1141 | 1142 | close(fd); 1143 | 1144 | luaL_checkstack(L, 1, "lloadff"); 1145 | lua_pushboolean(L, 1); 1146 | 1147 | result = luatexts_load(L, buf, sb.st_size, &tuple_size); 1148 | if (LUATEXTS_UNLIKELY(result != LUATEXTS_ESUCCESS)) 1149 | { 1150 | luaL_checkstack(L, 1, "lloadff-err"); 1151 | lua_pushnil(L); 1152 | lua_replace(L, -3); /* Replace pre-pushed true with nil */ 1153 | return 2; /* Error message already on stack */ 1154 | } 1155 | 1156 | if (munmap((void *)buf, sb.st_size) == -1) 1157 | { 1158 | ESPAM(("lloadff: munmap failed")); 1159 | /* What else can we do? */ 1160 | } 1161 | 1162 | return tuple_size + 1; 1163 | } 1164 | 1165 | /* Lua module API */ 1166 | static const struct luaL_reg R[] = 1167 | { 1168 | { "load", lload }, 1169 | { "load_from_file", lload_from_file }, 1170 | 1171 | { NULL, NULL } 1172 | }; 1173 | 1174 | #ifdef __cplusplus 1175 | extern "C" { 1176 | #endif 1177 | 1178 | LUALIB_API int luaopen_luatexts(lua_State * L) 1179 | { 1180 | /* 1181 | * Register module 1182 | */ 1183 | luaL_register(L, "luatexts", R); 1184 | 1185 | /* 1186 | * Register module information 1187 | */ 1188 | lua_pushliteral(L, LUATEXTS_VERSION); 1189 | lua_setfield(L, -2, "_VERSION"); 1190 | 1191 | lua_pushliteral(L, LUATEXTS_COPYRIGHT); 1192 | lua_setfield(L, -2, "_COPYRIGHT"); 1193 | 1194 | lua_pushliteral(L, LUATEXTS_DESCRIPTION); 1195 | lua_setfield(L, -2, "_DESCRIPTION"); 1196 | 1197 | return 1; 1198 | } 1199 | 1200 | #ifdef __cplusplus 1201 | } 1202 | #endif 1203 | -------------------------------------------------------------------------------- /src/js/luatexts.js: -------------------------------------------------------------------------------- 1 | // LUATEXTS JavaScript module (v. 0.1.5) 2 | // https://github.com/agladysh/luatexts/ 3 | // Copyright (c) LUATEXTS authors. Licensed under the terms of the MIT license: 4 | // https://github.com/agladysh/luatexts/tree/master/COPYRIGHT 5 | 6 | // ----------------------------------------------------------------------------- 7 | 8 | var LUATEXTS = (function(LUATEXTS) { 9 | 10 | // ----------------------------------------------------------------------------- 11 | 12 | function my_typeof(v) { 13 | var type = typeof v; 14 | if (type !== "object") { 15 | return type; 16 | } else if (v === null) { 17 | return "null"; 18 | } else if (v.constructor == Array) { 19 | return "array"; 20 | } 21 | return "object"; 22 | } 23 | 24 | function save_nil(v) { 25 | return '-\n'; 26 | } 27 | 28 | function save_boolean(v) { 29 | return (v) ? '1\n' : '0\n'; 30 | } 31 | 32 | // TODO: Ensure this always save number in required format 33 | function save_number(v) { 34 | return 'N\n' + v.toString() + '\n'; 35 | } 36 | 37 | // TODO: Ensure the string is in UTF-8 somehow. 38 | function save_string(v) { 39 | return '8\n' + v.length + '\n' + v + '\n'; 40 | } 41 | 42 | function save_object(v) { 43 | var size = 0; 44 | var result = ''; 45 | 46 | for (var k in v) { 47 | result += save_value(k) + save_value(v[k]); 48 | ++size; 49 | } 50 | 51 | return 'T\n0\n' + size + '\n' + result; 52 | } 53 | 54 | // Saves array as one-based table. 55 | function save_array(v) { 56 | var result = 'T\n' + v.length + '\n0\n'; 57 | for (var i = 0; i < v.length; ++i) { 58 | result += save_value(v[i]); 59 | } 60 | return result; 61 | } 62 | 63 | function not_supported(v) { 64 | throw new Error( 65 | "luatexts does not support values of type " + my_typeof(v) 66 | ); 67 | } 68 | 69 | var save_by_type = { 70 | "undefined": save_nil, 71 | "null": save_nil, 72 | "boolean": save_boolean, 73 | "number": save_number, 74 | "string": save_string, 75 | "object": save_object, 76 | "array": save_array, 77 | "function": not_supported 78 | } 79 | 80 | function save_value(v) { 81 | var save_fn = save_by_type[my_typeof(v)] || not_supported; 82 | return save_fn(v); 83 | } 84 | 85 | LUATEXTS.save = function() { 86 | var result = arguments.length.toString() + "\n"; 87 | 88 | for (var i = 0; i < arguments.length; ++i) { 89 | result += save_value(arguments[i]); 90 | } 91 | 92 | return result; 93 | } 94 | 95 | // Sorry, no LUATEXTS.load() yet. Patches are welcome. 96 | 97 | // ----------------------------------------------------------------------------- 98 | 99 | return LUATEXTS; 100 | } (LUATEXTS || { })); 101 | 102 | // ----------------------------------------------------------------------------- 103 | -------------------------------------------------------------------------------- /src/js/luatexts.min.js: -------------------------------------------------------------------------------- 1 | // LUATEXTS JavaScript module (v. 0.1.5) 2 | // https://github.com/agladysh/luatexts/ 3 | // Copyright (c) LUATEXTS authors. Licensed under the terms of the MIT license: 4 | // https://github.com/agladysh/luatexts/tree/master/COPYRIGHT 5 | var LUATEXTS=function(f){function g(a){var b=typeof a;if(b!=="object")return b;else if(a===null)return"null";else if(a.constructor==Array)return"array";return"object"}function h(){return"-\n"}function i(a){throw Error("luatexts does not support values of type "+g(a));}function d(a){return(j[g(a)]||i)(a)}var j={undefined:h,"null":h,"boolean":function(a){return a?"1\n":"0\n"},number:function(a){return"N\n"+a.toString()+"\n"},string:function(a){return"8\n"+a.length+"\n"+a+"\n"},object:function(a){var b= 6 | 0,c="",e;for(e in a)c+=d(e)+d(a[e]),++b;return"T\n0\n"+b+"\n"+c},array:function(a){for(var b="T\n"+a.length+"\n0\n",c=0;c array_size or k < 1 or -- integer key in hash part of the table 76 | k % 1 ~= 0 -- non-integer key 77 | then 78 | hash_size = hash_size + 1 79 | -- TODO: return nil, err on failure instead of asserting 80 | assert(handle_value(cat, k, visited, buf)) 81 | assert(handle_value(cat, v, visited, buf)) 82 | end 83 | end 84 | 85 | buf[hash_size_pos] = hash_size 86 | else -- Streaming mode 87 | cat "t" "\n" 88 | 89 | for k, v in pairs(t) do 90 | assert(handle_value(cat, k, visited, buf)) 91 | assert(handle_value(cat, v, visited, buf)) 92 | end 93 | 94 | handle_value(cat, nil, visited, buf) 95 | end 96 | 97 | visited[t] = nil 98 | 99 | return cat 100 | end 101 | 102 | local impl = function(buf, cat, ...) 103 | local nargs = select("#", ...) 104 | 105 | cat (nargs) "\n" 106 | 107 | for i = 1, nargs do 108 | handle_value(cat, select(i, ...), { }, buf) 109 | end 110 | 111 | return cat 112 | end 113 | 114 | save_cat = function(cat, ...) 115 | return impl(nil, cat, ...) 116 | end 117 | 118 | save = function(...) 119 | local buf = { } 120 | local function cat(s) buf[#buf + 1] = s; return cat end 121 | 122 | impl(buf, cat, ...) 123 | 124 | return table_concat(buf) 125 | end 126 | end 127 | 128 | -------------------------------------------------------------------------------- 129 | 130 | local load, load_from_buffer 131 | do 132 | local make_read_buf 133 | do 134 | local read = function(self, bytes) 135 | local off = self.next_ + bytes - 1 136 | 137 | if off > #self.str_ then 138 | self:fail("load failed: read: not enough data in buffer") 139 | return nil 140 | end 141 | 142 | local result = self.str_:sub(self.next_, off) 143 | 144 | self.next_ = off + 1 145 | 146 | return result 147 | end 148 | 149 | local readpattern = function(self, pattern) 150 | if self.next_ > #self.str_ then 151 | self:fail("load failed: readpattern: not enough data in buffer") 152 | return nil 153 | end 154 | 155 | local start, off, result = self.str_:find(pattern, self.next_) 156 | if not result then 157 | self:fail("load failed: readpattern: not found") 158 | return nil 159 | end 160 | 161 | if start ~= self.next_ then 162 | self:fail("load failed: readpattern: garbage before pattern") 163 | return nil 164 | end 165 | 166 | self.next_ = off + 1 167 | 168 | return result 169 | end 170 | 171 | local good = function(self) 172 | return not self.failed_ 173 | end 174 | 175 | local fail = function(self, msg) 176 | self.failed_ = msg -- overriding old error 177 | end 178 | 179 | local result = function(self) 180 | if self:good() then 181 | return true 182 | end 183 | 184 | return nil, self.failed_ 185 | end 186 | 187 | make_read_buf = function(str) 188 | 189 | return 190 | { 191 | read = read; 192 | readpattern = readpattern; 193 | -- 194 | good = good; 195 | fail = fail; 196 | result = result; 197 | -- 198 | str_ = str; 199 | next_ = 1; 200 | failed_ = false; 201 | } 202 | end 203 | 204 | end 205 | 206 | local invariant = function(v) 207 | return function() 208 | return v 209 | end 210 | end 211 | 212 | local number = function(base) 213 | return function(buf) 214 | local v = buf:readpattern("(.-)\r?\n") 215 | if not buf:good() then 216 | return nil 217 | end 218 | v = tonumber(v, base) 219 | if not v then 220 | buf:fail("load failed: not a number") 221 | end 222 | return v 223 | end 224 | end 225 | 226 | local uint_patterns = 227 | { 228 | [10] = "([0-9]-)\r?\n"; 229 | [16] = "([0-9a-fA-F]-)\r?\n"; 230 | [36] = "([0-9a-zA-Z]-)\r?\n"; 231 | } 232 | 233 | local uint = function(base) 234 | local pattern = assert(uint_patterns[base]) 235 | 236 | return function(buf) 237 | local v = buf:readpattern(pattern) 238 | if not buf:good() then 239 | return nil 240 | end 241 | v = tonumber(v, base) 242 | if not v then -- Should not happen 243 | buf:fail("load failed: not a number") 244 | return nil 245 | end 246 | if v ~= v then 247 | buf:fail("load failed: uint is nan") 248 | return nil 249 | end 250 | if v < 0 then 251 | buf:fail("load failed: negative uint") 252 | return nil 253 | end 254 | if v > 4294967295 then 255 | buf:fail("load failed: uint is too huge") 256 | return nil 257 | end 258 | if v % 1 ~= 0 then 259 | buf:fail("load failed: fractional uint") 260 | return nil 261 | end 262 | 263 | return v 264 | end 265 | end 266 | 267 | local read_uint10 = uint(10) 268 | 269 | local read_utf8 270 | do 271 | -- Based on MIT-licensed Flexible and Economical UTF-8 Decoder 272 | -- by Bjoern Hoehrmann 273 | -- http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ 274 | 275 | local UTF8_ACCEPT = 0 276 | local UTF8_REJECT = 1 277 | 278 | local utf8d = 279 | { 280 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -- 00..1f 281 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -- 20..3f 282 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -- 40..5f 283 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -- 60..7f 284 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, -- 80..9f 285 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, -- a0..bf 286 | 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -- c0..df 287 | 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, -- e0..ef 288 | 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, -- f0..ff 289 | 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, -- s0..s0 290 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, -- s1..s2 291 | 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, -- s3..s4 292 | 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, -- s5..s6 293 | 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -- s7..s8 294 | } 295 | 296 | -- Note: Keeping code as close to the C original as possible. 297 | -- Thus the magic numbers without constants. 298 | local decode = function(state, codep, byte) 299 | local byte_type = utf8d[byte + 1] 300 | 301 | codep = (state ~= UTF8_ACCEPT) 302 | and 303 | ( 304 | bit_bor( 305 | bit_band(byte, 0x3f), 306 | bit_lshift(codep, 6) 307 | ) 308 | ) 309 | or 310 | ( 311 | bit_band( 312 | bit_rshift(0xff, byte_type), 313 | byte 314 | ) 315 | ) 316 | 317 | return utf8d[256 + state * 16 + byte_type + 1], codep 318 | end 319 | 320 | read_utf8 = function(buf) 321 | local length = read_uint10(buf) 322 | if not buf:good() then 323 | return nil 324 | end 325 | 326 | local result 327 | if length == 0 then 328 | result = "" 329 | else 330 | result = { } 331 | 332 | local codepoint = 0 333 | local state = UTF8_ACCEPT 334 | while length > 0 do 335 | local char = buf:read(1) 336 | if not buf:good() then 337 | return nil 338 | end 339 | 340 | result[#result + 1] = char 341 | 342 | state, codepoint = decode(state, codepoint, char:byte()) 343 | if state == UTF8_ACCEPT then 344 | length = length - 1 345 | elseif state == UTF8_REJECT then 346 | buf:fail("load failed: invalid utf-8 data") 347 | return nil 348 | end 349 | end 350 | 351 | result = table_concat(result) 352 | end 353 | 354 | -- Eat EOL after data 355 | buf:readpattern("()\r?\n") 356 | if not buf:good() then 357 | return nil 358 | end 359 | 360 | return result 361 | end 362 | end 363 | 364 | local unsupported = function(buf) 365 | buf:fail("load failed: unsupported value type") 366 | end 367 | 368 | local read_value 369 | 370 | local value_readers = 371 | { 372 | ['-'] = invariant(nil); 373 | ['0'] = invariant(false); 374 | ['1'] = invariant(true); 375 | ['N'] = number(10); 376 | ['U'] = read_uint10; 377 | ['H'] = uint(16); 378 | ['Z'] = uint(36); 379 | 380 | ['S'] = function(buf) 381 | local length = read_uint10(buf) 382 | if not buf:good() then 383 | return nil 384 | end 385 | 386 | local v = buf:read(length) 387 | if not buf:good() then 388 | return nil 389 | end 390 | 391 | -- Eat EOL after data 392 | local empty = buf:readpattern("()\r?\n") 393 | if not buf:good() then 394 | return nil 395 | end 396 | 397 | return v 398 | end; 399 | 400 | ['8'] = read_utf8; 401 | 402 | ['T'] = function(buf) 403 | local array_size = read_uint10(buf) 404 | if not buf:good() then 405 | return 406 | end 407 | 408 | local hash_size = read_uint10(buf) 409 | if not buf:good() then 410 | return 411 | end 412 | 413 | local r = { } 414 | 415 | for i = 1, array_size do 416 | if not buf:good() then 417 | return 418 | end 419 | 420 | r[i] = read_value(buf) 421 | end 422 | 423 | for i = 1, hash_size do 424 | if not buf:good() then 425 | return 426 | end 427 | 428 | local k = read_value(buf) 429 | if buf:good() then 430 | if k == nil then 431 | buf:fail("load failed: table key is nil") 432 | else 433 | r[k] = read_value(buf) 434 | end 435 | end 436 | end 437 | 438 | return r 439 | end; 440 | 441 | ['t'] = function(buf) 442 | local r = { } 443 | 444 | while buf:good() do 445 | local k = read_value(buf) 446 | if buf:good() then 447 | if k == nil then 448 | break -- end of table 449 | else 450 | r[k] = read_value(buf) 451 | end 452 | end 453 | end 454 | 455 | return r 456 | end; 457 | } 458 | 459 | read_value = function(buf) 460 | local value_type = buf:readpattern("(.)\r?\n") 461 | if not buf:good() then 462 | return 463 | end 464 | 465 | local reader = value_readers[value_type] 466 | if not reader then 467 | buf:fail("load failed: unknown value type") 468 | return 469 | end 470 | 471 | return reader(buf) 472 | end 473 | 474 | -- TODO: Cover this with separate tests. 475 | -- Most importantly, test that readpattern's pattern 476 | -- always ends with '\n' 477 | load_from_buffer = function(buf) 478 | local n = read_uint10(buf) 479 | if not buf:good() then 480 | return buf:result() 481 | end 482 | 483 | -- TODO: Use recursion instead? 484 | local r = { } 485 | for i = 1, n do 486 | r[i] = read_value(buf) 487 | 488 | if not buf:good() then 489 | return buf:result() 490 | end 491 | end 492 | 493 | return true, unpack(r, 1, n) 494 | end 495 | 496 | load = function(str) 497 | if type(str) ~= "string" then -- TODO: Support io.file? 498 | -- Imitating C API to simplify tests 499 | error( 500 | "bad argument #1 to 'load' (string expected)" 501 | ) 502 | end 503 | 504 | return load_from_buffer( 505 | make_read_buf(str) 506 | ) 507 | end 508 | end 509 | 510 | -------------------------------------------------------------------------------- 511 | 512 | return 513 | { 514 | _VERSION = "luatexts-lua 0.1.5"; 515 | _COPYRIGHT = "Copyright (C) 2011-2013, luatexts authors"; 516 | _DESCRIPTION = "Trivial Lua human-readable binary-safe serialization library"; 517 | -- 518 | save = save; 519 | save_cat = save_cat; 520 | load = load; 521 | load_from_buffer = load_from_buffer; 522 | } 523 | -------------------------------------------------------------------------------- /src/php/luatexts.php: -------------------------------------------------------------------------------- 1 | $value) 54 | { 55 | if (strtolower(gettype($key)) == 'integer') 56 | { 57 | if ($key >= 0 && $key <= $max_arr_key) 58 | { 59 | continue; // Saved this value above 60 | } 61 | else 62 | { 63 | // Incrementing the key for data to be consistent. 64 | ++$key; 65 | } 66 | } 67 | 68 | $result .= self::save_value($key) . self::save_value($value); 69 | ++$hash_size; 70 | } 71 | 72 | return "T\n" . $arr_size . "\n" . $hash_size . "\n" . $result; 73 | } 74 | 75 | private static function save_null($v) 76 | { 77 | return "-\n"; 78 | } 79 | 80 | private static $supported_types = array( 81 | 'boolean', 'integer', 'double', 'string', 'array', 'null' 82 | ); 83 | 84 | private static function save_value($v) 85 | { 86 | $type = strtolower(gettype($v)); 87 | $handler = 'save_' . $type; 88 | 89 | if (!in_array($type, self::$supported_types)) 90 | { 91 | throw new Exception("luatexts does not support values of type \"$type\""); 92 | } 93 | 94 | return self::$handler($v); 95 | } 96 | 97 | public static function save() 98 | { 99 | $args = func_get_args(); 100 | $num_args = count($args); 101 | 102 | $result = $num_args . "\n"; 103 | 104 | for ($i = 0; $i < $num_args; $i++) 105 | { 106 | $result .= self::save_value($args[$i]); 107 | } 108 | 109 | return $result; 110 | } 111 | } 112 | ?> 113 | -------------------------------------------------------------------------------- /test/data/empty.luatexts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agladysh/luatexts/2ca61795384aa9a9685776527515266894d3471b/test/data/empty.luatexts -------------------------------------------------------------------------------- /test/data/garbage.luatexts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agladysh/luatexts/2ca61795384aa9a9685776527515266894d3471b/test/data/garbage.luatexts -------------------------------------------------------------------------------- /test/data/good.luatexts: -------------------------------------------------------------------------------- 1 | 1 2 | N 3 | 42 4 | -------------------------------------------------------------------------------- /test/data/noeol.luatexts: -------------------------------------------------------------------------------- 1 | 1 2 | U 3 | 14 -------------------------------------------------------------------------------- /test/data/truncated.luatexts: -------------------------------------------------------------------------------- 1 | 1024 2 | N 3 | 42 4 | -------------------------------------------------------------------------------- /test/data/truncated2.luatexts: -------------------------------------------------------------------------------- 1 | 1 2 | N 3 | -------------------------------------------------------------------------------- /test/luatexts.js: -------------------------------------------------------------------------------- 1 | ../src/js/luatexts.js -------------------------------------------------------------------------------- /test/luatexts.min.js: -------------------------------------------------------------------------------- 1 | ../src/js/luatexts.min.js -------------------------------------------------------------------------------- /test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | luatexts.js ad-hoc tests 4 | 5 | 6 | 7 | 8 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /test/test.lua: -------------------------------------------------------------------------------- 1 | -- TODO: Scrap these hacks and write a proper test suite. 2 | 3 | pcall(require, 'luarocks.require') 4 | require 'lua-nucleo.module' 5 | require 'lua-nucleo.strict' 6 | require = import 'lua-nucleo/require_and_declare.lua' { 'require_and_declare' } 7 | 8 | math.randomseed(12345) 9 | 10 | local luatexts = require 'luatexts' 11 | local luatexts_lua = require 'luatexts.lua' 12 | 13 | local ensure, 14 | ensure_equals, 15 | ensure_tequals, 16 | ensure_tdeepequals, 17 | ensure_strequals, 18 | ensure_error, 19 | ensure_error_with_substring, 20 | ensure_fails_with_substring, 21 | ensure_returns 22 | = import 'lua-nucleo/ensure.lua' 23 | { 24 | 'ensure', 25 | 'ensure_equals', 26 | 'ensure_tequals', 27 | 'ensure_tdeepequals', 28 | 'ensure_strequals', 29 | 'ensure_error', 30 | 'ensure_error_with_substring', 31 | 'ensure_fails_with_substring', 32 | 'ensure_returns' 33 | } 34 | 35 | local split_by_char = import 'lua-nucleo/string.lua' { 'split_by_char' } 36 | 37 | local tset = import 'lua-nucleo/table-utils.lua' { 'tset' } 38 | 39 | local tpretty = import 'lua-nucleo/tpretty.lua' { 'tpretty' } 40 | 41 | local tserialize = import 'lua-nucleo/tserialize.lua' { 'tserialize' } 42 | 43 | -------------------------------------------------------------------------------- 44 | 45 | -- This is this file: http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt 46 | local UTF8_TEST_DATA = (function() return 47 | "\085\084\070\045\056\032\100\101\099\111\100\101\114\032\099\097\112\097" .. 48 | "\098\105\108\105\116\121\032\097\110\100\032\115\116\114\101\115\115\032" .. 49 | "\116\101\115\116\010\045\045\045\045\045\045\045\045\045\045\045\045\045" .. 50 | "\045\045\045\045\045\045\045\045\045\045\045\045\045\045\045\045\045\045" .. 51 | "\045\045\045\045\045\045\045\045\045\010\010\077\097\114\107\117\115\032" .. 52 | "\075\117\104\110\032\060\104\116\116\112\058\047\047\119\119\119\046\099" .. 53 | "\108\046\099\097\109\046\097\099\046\117\107\047\126\109\103\107\050\053" .. 54 | "\047\062\032\045\032\050\048\048\051\045\048\050\045\049\057\010\010\084" .. 55 | "\104\105\115\032\116\101\115\116\032\102\105\108\101\032\099\097\110\032" .. 56 | "\104\101\108\112\032\121\111\117\032\101\120\097\109\105\110\101\044\032" .. 57 | "\104\111\119\032\121\111\117\114\032\085\084\070\045\056\032\100\101\099" .. 58 | "\111\100\101\114\032\104\097\110\100\108\101\115\010\118\097\114\105\111" .. 59 | "\117\115\032\116\121\112\101\115\032\111\102\032\099\111\114\114\101\099" .. 60 | "\116\044\032\109\097\108\102\111\114\109\101\100\044\032\111\114\032\111" .. 61 | "\116\104\101\114\119\105\115\101\032\105\110\116\101\114\101\115\116\105" .. 62 | "\110\103\032\085\084\070\045\056\010\115\101\113\117\101\110\099\101\115" .. 63 | "\046\032\084\104\105\115\032\102\105\108\101\032\105\115\032\110\111\116" .. 64 | "\032\109\101\097\110\116\032\116\111\032\098\101\032\097\032\099\111\110" .. 65 | "\102\111\114\109\097\110\099\101\032\116\101\115\116\046\032\073\116\032" .. 66 | "\100\111\101\115\010\110\111\116\032\112\114\101\115\099\114\105\098\101" .. 67 | "\115\032\097\110\121\032\112\097\114\116\105\099\117\108\097\114\032\111" .. 68 | "\117\116\099\111\109\101\032\097\110\100\032\116\104\101\114\101\102\111" .. 69 | "\114\101\032\116\104\101\114\101\032\105\115\032\110\111\032\119\097\121" .. 70 | "\032\116\111\010\034\112\097\115\115\034\032\111\114\032\034\102\097\105" .. 71 | "\108\034\032\116\104\105\115\032\116\101\115\116\032\102\105\108\101\044" .. 72 | "\032\101\118\101\110\032\116\104\111\117\103\104\032\116\104\101\032\116" .. 73 | "\101\120\116\115\032\115\117\103\103\101\115\116\115\032\097\010\112\114" .. 74 | "\101\102\101\114\097\098\108\101\032\100\101\099\111\100\101\114\032\098" .. 75 | "\101\104\097\118\105\111\117\114\032\097\116\032\115\111\109\101\032\112" .. 76 | "\108\097\099\101\115\046\032\084\104\101\032\097\105\109\032\105\115\032" .. 77 | "\105\110\115\116\101\097\100\032\116\111\010\104\101\108\112\032\121\111" .. 78 | "\117\032\116\104\105\110\107\032\097\098\111\117\116\032\097\110\100\032" .. 79 | "\116\101\115\116\032\116\104\101\032\098\101\104\097\118\105\111\117\114" .. 80 | "\032\111\102\032\121\111\117\114\032\085\084\070\045\056\032\111\110\032" .. 81 | "\097\010\115\121\115\116\101\109\097\116\105\099\032\099\111\108\108\101" .. 82 | "\099\116\105\111\110\032\111\102\032\117\110\117\115\117\097\108\032\105" .. 83 | "\110\112\117\116\115\046\032\069\120\112\101\114\105\101\110\099\101\032" .. 84 | "\115\111\032\102\097\114\032\115\117\103\103\101\115\116\115\010\116\104" .. 85 | "\097\116\032\109\111\115\116\032\102\105\114\115\116\045\116\105\109\101" .. 86 | "\032\097\117\116\104\111\114\115\032\111\102\032\085\084\070\045\056\032" .. 87 | "\100\101\099\111\100\101\114\115\032\102\105\110\100\032\097\116\032\108" .. 88 | "\101\097\115\116\032\111\110\101\010\115\101\114\105\111\117\115\032\112" .. 89 | "\114\111\098\108\101\109\032\105\110\032\116\104\101\105\114\032\100\101" .. 90 | "\099\111\100\101\114\032\098\121\032\117\115\105\110\103\032\116\104\105" .. 91 | "\115\032\102\105\108\101\046\010\010\084\104\101\032\116\101\115\116\032" .. 92 | "\108\105\110\101\115\032\098\101\108\111\119\032\099\111\118\101\114\032" .. 93 | "\098\111\117\110\100\097\114\121\032\099\111\110\100\105\116\105\111\110" .. 94 | "\115\044\032\109\097\108\102\111\114\109\101\100\032\085\084\070\045\056" .. 95 | "\010\115\101\113\117\101\110\099\101\115\032\097\115\032\119\101\108\108" .. 96 | "\032\097\115\032\099\111\114\114\101\099\116\108\121\032\101\110\099\111" .. 97 | "\100\101\100\032\085\084\070\045\056\032\115\101\113\117\101\110\099\101" .. 98 | "\115\032\111\102\032\085\110\105\099\111\100\101\032\099\111\100\101\010" .. 99 | "\112\111\105\110\116\115\032\116\104\097\116\032\115\104\111\117\108\100" .. 100 | "\032\110\101\118\101\114\032\111\099\099\117\114\032\105\110\032\097\032" .. 101 | "\099\111\114\114\101\099\116\032\085\084\070\045\056\032\102\105\108\101" .. 102 | "\046\010\010\065\099\099\111\114\100\105\110\103\032\116\111\032\073\083" .. 103 | "\079\032\049\048\054\052\054\045\049\058\050\048\048\048\044\032\115\101" .. 104 | "\099\116\105\111\110\115\032\068\046\055\032\097\110\100\032\050\046\051" .. 105 | "\099\044\032\097\032\100\101\118\105\099\101\010\114\101\099\101\105\118" .. 106 | "\105\110\103\032\085\084\070\045\056\032\115\104\097\108\108\032\105\110" .. 107 | "\116\101\114\112\114\101\116\032\097\032\034\109\097\108\102\111\114\109" .. 108 | "\101\100\032\115\101\113\117\101\110\099\101\032\105\110\032\116\104\101" .. 109 | "\032\115\097\109\101\032\119\097\121\010\116\104\097\116\032\105\116\032" .. 110 | "\105\110\116\101\114\112\114\101\116\115\032\097\032\099\104\097\114\097" .. 111 | "\099\116\101\114\032\116\104\097\116\032\105\115\032\111\117\116\115\105" .. 112 | "\100\101\032\116\104\101\032\097\100\111\112\116\101\100\032\115\117\098" .. 113 | "\115\101\116\034\032\097\110\100\010\034\099\104\097\114\097\099\116\101" .. 114 | "\114\115\032\116\104\097\116\032\097\114\101\032\110\111\116\032\119\105" .. 115 | "\116\104\105\110\032\116\104\101\032\097\100\111\112\116\101\100\032\115" .. 116 | "\117\098\115\101\116\032\115\104\097\108\108\032\098\101\032\105\110\100" .. 117 | "\105\099\097\116\101\100\010\116\111\032\116\104\101\032\117\115\101\114" .. 118 | "\034\032\098\121\032\097\032\114\101\099\101\105\118\105\110\103\032\100" .. 119 | "\101\118\105\099\101\046\032\065\032\113\117\105\116\101\032\099\111\109" .. 120 | "\109\111\110\108\121\032\117\115\101\100\032\097\112\112\114\111\097\099" .. 121 | "\104\032\105\110\010\085\084\070\045\056\032\100\101\099\111\100\101\114" .. 122 | "\115\032\105\115\032\116\111\032\114\101\112\108\097\099\101\032\097\110" .. 123 | "\121\032\109\097\108\102\111\114\109\101\100\032\085\084\070\045\056\032" .. 124 | "\115\101\113\117\101\110\099\101\032\098\121\032\097\010\114\101\112\108" .. 125 | "\097\099\101\109\101\110\116\032\099\104\097\114\097\099\116\101\114\032" .. 126 | "\040\085\043\070\070\070\068\041\044\032\119\104\105\099\104\032\108\111" .. 127 | "\111\107\115\032\097\032\098\105\116\032\108\105\107\101\032\097\110\032" .. 128 | "\105\110\118\101\114\116\101\100\010\113\117\101\115\116\105\111\110\032" .. 129 | "\109\097\114\107\044\032\111\114\032\097\032\115\105\109\105\108\097\114" .. 130 | "\032\115\121\109\098\111\108\046\032\073\116\032\109\105\103\104\116\032" .. 131 | "\098\101\032\097\032\103\111\111\100\032\105\100\101\097\032\116\111\010" .. 132 | "\118\105\115\117\097\108\108\121\032\100\105\115\116\105\110\103\117\105" .. 133 | "\115\104\032\097\032\109\097\108\102\111\114\109\101\100\032\085\084\070" .. 134 | "\045\056\032\115\101\113\117\101\110\099\101\032\102\114\111\109\032\097" .. 135 | "\032\099\111\114\114\101\099\116\108\121\010\101\110\099\111\100\101\100" .. 136 | "\032\085\110\105\099\111\100\101\032\099\104\097\114\097\099\116\101\114" .. 137 | "\032\116\104\097\116\032\105\115\032\106\117\115\116\032\110\111\116\032" .. 138 | "\097\118\097\105\108\097\098\108\101\032\105\110\032\116\104\101\032\099" .. 139 | "\117\114\114\101\110\116\010\102\111\110\116\032\098\117\116\032\111\116" .. 140 | "\104\101\114\119\105\115\101\032\102\117\108\108\121\032\108\101\103\097" .. 141 | "\108\044\032\101\118\101\110\032\116\104\111\117\103\104\032\073\083\079" .. 142 | "\032\049\048\054\052\054\045\049\032\100\111\101\115\110\039\116\010\109" .. 143 | "\097\110\100\097\116\101\032\116\104\105\115\046\032\073\110\032\097\110" .. 144 | "\121\032\099\097\115\101\044\032\106\117\115\116\032\105\103\110\111\114" .. 145 | "\105\110\103\032\109\097\108\102\111\114\109\101\100\032\115\101\113\117" .. 146 | "\101\110\099\101\115\032\111\114\010\117\110\097\118\097\105\108\097\098" .. 147 | "\108\101\032\099\104\097\114\097\099\116\101\114\115\032\100\111\101\115" .. 148 | "\032\110\111\116\032\099\111\110\102\111\114\109\032\116\111\032\073\083" .. 149 | "\079\032\049\048\054\052\054\044\032\119\105\108\108\032\109\097\107\101" .. 150 | "\010\100\101\098\117\103\103\105\110\103\032\109\111\114\101\032\100\105" .. 151 | "\102\102\105\099\117\108\116\044\032\097\110\100\032\099\097\110\032\108" .. 152 | "\101\097\100\032\116\111\032\117\115\101\114\032\099\111\110\102\117\115" .. 153 | "\105\111\110\046\010\010\080\108\101\097\115\101\032\099\104\101\099\107" .. 154 | "\044\032\119\104\101\116\104\101\114\032\097\032\109\097\108\102\111\114" .. 155 | "\109\101\100\032\085\084\070\045\056\032\115\101\113\117\101\110\099\101" .. 156 | "\032\105\115\032\040\049\041\032\114\101\112\114\101\115\101\110\116\101" .. 157 | "\100\032\097\116\010\097\108\108\044\032\040\050\041\032\114\101\112\114" .. 158 | "\101\115\101\110\116\101\100\032\098\121\032\101\120\097\099\116\108\121" .. 159 | "\032\111\110\101\032\115\105\110\103\108\101\032\114\101\112\108\097\099" .. 160 | "\101\109\101\110\116\032\099\104\097\114\097\099\116\101\114\032\040\111" .. 161 | "\114\010\101\113\117\105\118\097\108\101\110\116\032\115\105\103\110\097" .. 162 | "\108\041\044\032\097\110\100\032\040\051\041\032\116\104\101\032\102\111" .. 163 | "\108\108\111\119\105\110\103\032\113\117\111\116\097\116\105\111\110\032" .. 164 | "\109\097\114\107\032\097\102\116\101\114\032\097\110\010\105\108\108\101" .. 165 | "\103\097\108\032\085\084\070\045\056\032\115\101\113\117\101\110\099\101" .. 166 | "\032\105\115\032\099\111\114\114\101\099\116\108\121\032\100\105\115\112" .. 167 | "\108\097\121\101\100\044\032\105\046\101\046\032\112\114\111\112\101\114" .. 168 | "\010\114\101\115\121\110\099\104\114\111\110\105\122\097\116\105\111\110" .. 169 | "\032\116\097\107\101\115\032\112\108\097\099\101\032\105\109\109\097\103" .. 170 | "\101\097\116\101\108\121\032\097\102\116\101\114\032\097\110\121\032\109" .. 171 | "\097\108\102\111\114\109\101\100\010\115\101\113\117\101\110\099\101\046" .. 172 | "\032\084\104\105\115\032\102\105\108\101\032\115\097\121\115\032\034\084" .. 173 | "\072\069\032\069\078\068\034\032\105\110\032\116\104\101\032\108\097\115" .. 174 | "\116\032\108\105\110\101\044\032\115\111\032\105\102\032\121\111\117\032" .. 175 | "\100\111\110\039\116\010\115\101\101\032\116\104\097\116\044\032\121\111" .. 176 | "\117\114\032\100\101\099\111\100\101\114\032\099\114\097\115\104\101\100" .. 177 | "\032\115\111\109\101\104\111\119\032\098\101\102\111\114\101\044\032\119" .. 178 | "\104\105\099\104\032\115\104\111\117\108\100\032\097\108\119\097\121\115" .. 179 | "\032\098\101\010\099\097\117\115\101\032\102\111\114\032\099\111\110\099" .. 180 | "\101\114\110\046\010\010\065\108\108\032\108\105\110\101\115\032\105\110" .. 181 | "\032\116\104\105\115\032\102\105\108\101\032\097\114\101\032\101\120\097" .. 182 | "\099\116\108\121\032\055\057\032\099\104\097\114\097\099\116\101\114\115" .. 183 | "\032\108\111\110\103\032\040\112\108\117\115\032\116\104\101\032\108\105" .. 184 | "\110\101\010\102\101\101\100\041\046\032\073\110\032\097\100\100\105\116" .. 185 | "\105\111\110\044\032\097\108\108\032\108\105\110\101\115\032\101\110\100" .. 186 | "\032\119\105\116\104\032\034\124\034\044\032\101\120\099\101\112\116\032" .. 187 | "\102\111\114\032\116\104\101\032\116\119\111\032\116\101\115\116\010\108" .. 188 | "\105\110\101\115\032\050\046\049\046\049\032\097\110\100\032\050\046\050" .. 189 | "\046\049\044\032\119\104\105\099\104\032\099\111\110\116\097\105\110\032" .. 190 | "\110\111\110\045\112\114\105\110\116\097\098\108\101\032\065\083\067\073" .. 191 | "\073\032\099\111\110\116\114\111\108\115\010\085\043\048\048\048\048\032" .. 192 | "\097\110\100\032\085\043\048\048\055\070\046\032\073\102\032\121\111\117" .. 193 | "\032\100\105\115\112\108\097\121\032\116\104\105\115\032\102\105\108\101" .. 194 | "\032\119\105\116\104\032\097\032\102\105\120\101\100\045\119\105\100\116" .. 195 | "\104\032\102\111\110\116\044\010\116\104\101\115\101\032\034\124\034\032" .. 196 | "\099\104\097\114\097\099\116\101\114\115\032\115\104\111\117\108\100\032" .. 197 | "\097\108\108\032\108\105\110\101\032\117\112\032\105\110\032\099\111\108" .. 198 | "\117\109\110\032\055\057\032\040\114\105\103\104\116\032\109\097\114\103" .. 199 | "\105\110\041\046\010\084\104\105\115\032\097\108\108\111\119\115\032\121" .. 200 | "\111\117\032\116\111\032\116\101\115\116\032\113\117\105\099\107\108\121" .. 201 | "\044\032\119\104\101\116\104\101\114\032\121\111\117\114\032\085\084\070" .. 202 | "\045\056\032\100\101\099\111\100\101\114\032\102\105\110\100\115\032\116" .. 203 | "\104\101\010\099\111\114\114\101\099\116\032\110\117\109\098\101\114\032" .. 204 | "\111\102\032\099\104\097\114\097\099\116\101\114\115\032\105\110\032\101" .. 205 | "\118\101\114\121\032\108\105\110\101\044\032\116\104\097\116\032\105\115" .. 206 | "\032\119\104\101\116\104\101\114\032\101\097\099\104\010\109\097\108\102" .. 207 | "\111\114\109\101\100\032\115\101\113\117\101\110\099\101\115\032\105\115" .. 208 | "\032\114\101\112\108\097\099\101\100\032\098\121\032\097\032\115\105\110" .. 209 | "\103\108\101\032\114\101\112\108\097\099\101\109\101\110\116\032\099\104" .. 210 | "\097\114\097\099\116\101\114\046\010\010\078\111\116\101\032\116\104\097" .. 211 | "\116\032\097\115\032\097\110\032\097\108\116\101\114\110\097\116\105\118" .. 212 | "\101\032\116\111\032\116\104\101\032\110\111\116\105\111\110\032\111\102" .. 213 | "\032\109\097\108\102\111\114\109\101\100\032\115\101\113\117\101\110\099" .. 214 | "\101\032\117\115\101\100\010\104\101\114\101\044\032\105\116\032\105\115" .. 215 | "\032\097\108\115\111\032\097\032\112\101\114\102\101\099\116\108\121\032" .. 216 | "\097\099\099\101\112\116\097\098\108\101\032\040\097\110\100\032\105\110" .. 217 | "\032\115\111\109\101\032\115\105\116\117\097\116\105\111\110\115\032\101" .. 218 | "\118\101\110\010\112\114\101\102\101\114\097\098\108\101\041\032\115\111" .. 219 | "\108\117\116\105\111\110\032\116\111\032\114\101\112\114\101\115\101\110" .. 220 | "\116\032\101\097\099\104\032\105\110\100\105\118\105\100\117\097\108\032" .. 221 | "\098\121\116\101\032\111\102\032\097\032\109\097\108\102\111\114\109\101" .. 222 | "\100\010\115\101\113\117\101\110\099\101\032\098\121\032\097\032\114\101" .. 223 | "\112\108\097\099\101\109\101\110\116\032\099\104\097\114\097\099\116\101" .. 224 | "\114\046\032\073\102\032\121\111\117\032\102\111\108\108\111\119\032\116" .. 225 | "\104\105\115\032\115\116\114\097\116\101\103\121\032\105\110\010\121\111" .. 226 | "\117\114\032\100\101\099\111\100\101\114\044\032\116\104\101\110\032\112" .. 227 | "\108\101\097\115\101\032\105\103\110\111\114\101\032\116\104\101\032\034" .. 228 | "\124\034\032\099\111\108\117\109\110\046\010\010\010\072\101\114\101\032" .. 229 | "\099\111\109\101\032\116\104\101\032\116\101\115\116\115\058\032\032\032" .. 230 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 231 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 232 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 233 | "\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 234 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 235 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 236 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 237 | "\032\032\032\032\032\032\032\032\032\124\010\049\032\032\083\111\109\101" .. 238 | "\032\099\111\114\114\101\099\116\032\085\084\070\045\056\032\116\101\120" .. 239 | "\116\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 240 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" 241 | end)() .. (function() return 242 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 243 | "\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 244 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 245 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 246 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 247 | "\032\032\032\032\032\032\032\124\010\089\111\117\032\115\104\111\117\108" .. 248 | "\100\032\115\101\101\032\116\104\101\032\071\114\101\101\107\032\119\111" .. 249 | "\114\100\032\039\107\111\115\109\101\039\058\032\032\032\032\032\032\032" .. 250 | "\034\206\186\225\189\185\207\131\206\188\206\181\034\032\032\032\032\032" .. 251 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 252 | "\032\032\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 253 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 254 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 255 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 256 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\050\032\032\066\111" .. 257 | "\117\110\100\097\114\121\032\099\111\110\100\105\116\105\111\110\032\116" .. 258 | "\101\115\116\032\099\097\115\101\115\032\032\032\032\032\032\032\032\032" .. 259 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 260 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 261 | "\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 262 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 263 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 264 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 265 | "\032\032\032\032\032\032\032\032\032\124\010\050\046\049\032\032\070\105" .. 266 | "\114\115\116\032\112\111\115\115\105\098\108\101\032\115\101\113\117\101" .. 267 | "\110\099\101\032\111\102\032\097\032\099\101\114\116\097\105\110\032\108" .. 268 | "\101\110\103\116\104\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 269 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 270 | "\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 271 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 272 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 273 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 274 | "\032\032\032\032\032\032\032\124\010\050\046\049\046\049\032\032\049\032" .. 275 | "\098\121\116\101\032\032\040\085\045\048\048\048\048\048\048\048\048\041" .. 276 | "\058\032\032\032\032\032\032\032\032\034\000\034\032\032\032\032\032\032" .. 277 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 278 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\010\050" .. 279 | "\046\049\046\050\032\032\050\032\098\121\116\101\115\032\040\085\045\048" .. 280 | "\048\048\048\048\048\056\048\041\058\032\032\032\032\032\032\032\032\034" .. 281 | "\194\128\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 282 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 283 | "\032\032\032\032\032\032\124\010\050\046\049\046\051\032\032\051\032\098" .. 284 | "\121\116\101\115\032\040\085\045\048\048\048\048\048\056\048\048\041\058" .. 285 | "\032\032\032\032\032\032\032\032\034\224\160\128\034\032\032\032\032\032" .. 286 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 287 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 288 | "\050\046\049\046\052\032\032\052\032\098\121\116\101\115\032\040\085\045" .. 289 | "\048\048\048\049\048\048\048\048\041\058\032\032\032\032\032\032\032\032" .. 290 | "\034\240\144\128\128\034\032\032\032\032\032\032\032\032\032\032\032\032" .. 291 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 292 | "\032\032\032\032\032\032\032\032\032\124\010\050\046\049\046\053\032\032" .. 293 | "\053\032\098\121\116\101\115\032\040\085\045\048\048\050\048\048\048\048" .. 294 | "\048\041\058\032\032\032\032\032\032\032\032\034\248\136\128\128\128\034" .. 295 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 296 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 297 | "\032\032\032\124\010\050\046\049\046\054\032\032\054\032\098\121\116\101" .. 298 | "\115\032\040\085\045\048\052\048\048\048\048\048\048\041\058\032\032\032" .. 299 | "\032\032\032\032\032\034\252\132\128\128\128\128\034\032\032\032\032\032" .. 300 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 301 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 302 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 303 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 304 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 305 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 306 | "\032\032\032\032\032\032\124\010\050\046\050\032\032\076\097\115\116\032" .. 307 | "\112\111\115\115\105\098\108\101\032\115\101\113\117\101\110\099\101\032" .. 308 | "\111\102\032\097\032\099\101\114\116\097\105\110\032\108\101\110\103\116" .. 309 | "\104\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 310 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032" .. 311 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 312 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 313 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 314 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 315 | "\032\032\032\032\124\010\050\046\050\046\049\032\032\049\032\098\121\116" .. 316 | "\101\032\032\040\085\045\048\048\048\048\048\048\055\070\041\058\032\032" .. 317 | "\032\032\032\032\032\032\034\127\034\032\032\032\032\032\032\032\032\032" .. 318 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 319 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\010\050\046\050\046" .. 320 | "\050\032\032\050\032\098\121\116\101\115\032\040\085\045\048\048\048\048" .. 321 | "\048\055\070\070\041\058\032\032\032\032\032\032\032\032\034\223\191\034" .. 322 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 323 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 324 | "\032\032\032\124\010\050\046\050\046\051\032\032\051\032\098\121\116\101" .. 325 | "\115\032\040\085\045\048\048\048\048\070\070\070\070\041\058\032\032\032" .. 326 | "\032\032\032\032\032\034\239\191\191\034\032\032\032\032\032\032\032\032" .. 327 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 328 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\050\046\050" .. 329 | "\046\052\032\032\052\032\098\121\116\101\115\032\040\085\045\048\048\049" .. 330 | "\070\070\070\070\070\041\058\032\032\032\032\032\032\032\032\034\247\191" .. 331 | "\191\191\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 332 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 333 | "\032\032\032\032\032\032\124\010\050\046\050\046\053\032\032\053\032\098" .. 334 | "\121\116\101\115\032\040\085\045\048\051\070\070\070\070\070\070\041\058" .. 335 | "\032\032\032\032\032\032\032\032\034\251\191\191\191\191\034\032\032\032" .. 336 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 337 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 338 | "\124\010\050\046\050\046\054\032\032\054\032\098\121\116\101\115\032\040" .. 339 | "\085\045\055\070\070\070\070\070\070\070\041\058\032\032\032\032\032\032" .. 340 | "\032\032\034\253\191\191\191\191\191\034\032\032\032\032\032\032\032\032" .. 341 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 342 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 343 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 344 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 345 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 346 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 347 | "\032\032\032\124\010\050\046\051\032\032\079\116\104\101\114\032\098\111" .. 348 | "\117\110\100\097\114\121\032\099\111\110\100\105\116\105\111\110\115\032" .. 349 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 350 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 351 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032" .. 352 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 353 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 354 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 355 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 356 | "\032\124\010\050\046\051\046\049\032\032\085\045\048\048\048\048\068\055" .. 357 | "\070\070\032\061\032\101\100\032\057\102\032\098\102\032\061\032\034\237" .. 358 | "\159\191\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 359 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 360 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\050\046\051\046\050" .. 361 | "\032\032\085\045\048\048\048\048\069\048\048\048\032\061\032\101\101\032" .. 362 | "\056\048\032\056\048\032\061\032\034\238\128\128\034\032\032\032\032\032" .. 363 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 364 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 365 | "\032\032\032\124\010\050\046\051\046\051\032\032\085\045\048\048\048\048" .. 366 | "\070\070\070\068\032\061\032\101\102\032\098\102\032\098\100\032\061\032" .. 367 | "\034\239\191\189\034\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 368 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 369 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\050\046\051" .. 370 | "\046\052\032\032\085\045\048\048\049\048\070\070\070\070\032\061\032\102" .. 371 | "\052\032\056\102\032\098\102\032\098\102\032\061\032\034\244\143\191\191" .. 372 | "\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 373 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 374 | "\032\032\032\032\032\032\124\010\050\046\051\046\053\032\032\085\045\048" .. 375 | "\048\049\049\048\048\048\048\032\061\032\102\052\032\057\048\032\056\048" .. 376 | "\032\056\048\032\061\032\034\244\144\128\128\034\032\032\032\032\032\032" .. 377 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 378 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 379 | "\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 380 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 381 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 382 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 383 | "\032\032\032\032\032\032\032\124\010\051\032\032\077\097\108\102\111\114" .. 384 | "\109\101\100\032\115\101\113\117\101\110\099\101\115\032\032\032\032\032" .. 385 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 386 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 387 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032" .. 388 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 389 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 390 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 391 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 392 | "\032\032\032\032\032\124\010\051\046\049\032\032\085\110\101\120\112\101" .. 393 | "\099\116\101\100\032\099\111\110\116\105\110\117\097\116\105\111\110\032" .. 394 | "\098\121\116\101\115\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 395 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 396 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 397 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 398 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 399 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 400 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 401 | "\032\032\032\124\010\069\097\099\104\032\117\110\101\120\112\101\099\116" .. 402 | "\101\100\032\099\111\110\116\105\110\117\097\116\105\111\110\032\098\121" .. 403 | "\116\101\032\115\104\111\117\108\100\032\098\101\032\115\101\112\097\114" .. 404 | "\097\116\101\108\121\032\115\105\103\110\097\108\108\101\100\032\097\115" .. 405 | "\032\097\032\032\032\032\032\032\032\032\032\124\010\109\097\108\102\111" .. 406 | "\114\109\101\100\032\115\101\113\117\101\110\099\101\032\111\102\032\105" .. 407 | "\116\115\032\111\119\110\046\032\032\032\032\032\032\032\032\032\032\032" .. 408 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 409 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 410 | "\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 411 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 412 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 413 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 414 | "\032\032\032\032\032\032\032\032\032\124\010\051\046\049\046\049\032\032" .. 415 | "\070\105\114\115\116\032\099\111\110\116\105\110\117\097\116\105\111\110" .. 416 | "\032\098\121\116\101\032\048\120\056\048\058\032\034\128\034\032\032\032" .. 417 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 418 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 419 | "\010\051\046\049\046\050\032\032\076\097\115\116\032\032\099\111\110\116" .. 420 | "\105\110\117\097\116\105\111\110\032\098\121\116\101\032\048\120\098\102" .. 421 | "\058\032\034\191\034\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 422 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 423 | "\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032" .. 424 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 425 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 426 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 427 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\051" .. 428 | "\046\049\046\051\032\032\050\032\099\111\110\116\105\110\117\097\116\105" .. 429 | "\111\110\032\098\121\116\101\115\058\032\034\128\191\034\032\032\032\032" .. 430 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 431 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 432 | "\032\032\032\032\032\124\010\051\046\049\046\052\032\032\051\032\099\111" .. 433 | "\110\116\105\110\117\097\116\105\111\110\032\098\121\116\101\115\058\032" .. 434 | "\034\128\191\128\034\032\032\032\032\032\032\032\032\032\032\032\032\032" 435 | end)() .. (function() return 436 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 437 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\051\046\049" .. 438 | "\046\053\032\032\052\032\099\111\110\116\105\110\117\097\116\105\111\110" .. 439 | "\032\098\121\116\101\115\058\032\034\128\191\128\191\034\032\032\032\032" .. 440 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 441 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 442 | "\032\032\032\124\010\051\046\049\046\054\032\032\053\032\099\111\110\116" .. 443 | "\105\110\117\097\116\105\111\110\032\098\121\116\101\115\058\032\034\128" .. 444 | "\191\128\191\128\034\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 445 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 446 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\051\046\049\046\055" .. 447 | "\032\032\054\032\099\111\110\116\105\110\117\097\116\105\111\110\032\098" .. 448 | "\121\116\101\115\058\032\034\128\191\128\191\128\191\034\032\032\032\032" .. 449 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 450 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 451 | "\032\124\010\051\046\049\046\056\032\032\055\032\099\111\110\116\105\110" .. 452 | "\117\097\116\105\111\110\032\098\121\116\101\115\058\032\034\128\191\128" .. 453 | "\191\128\191\128\034\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 454 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 455 | "\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032" .. 456 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 457 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 458 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 459 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 460 | "\010\051\046\049\046\057\032\032\083\101\113\117\101\110\099\101\032\111" .. 461 | "\102\032\097\108\108\032\054\052\032\112\111\115\115\105\098\108\101\032" .. 462 | "\099\111\110\116\105\110\117\097\116\105\111\110\032\098\121\116\101\115" .. 463 | "\032\040\048\120\056\048\045\048\120\098\102\041\058\032\032\032\032\032" .. 464 | "\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032" .. 465 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 466 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 467 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 468 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032" .. 469 | "\032\032\034\128\129\130\131\132\133\134\135\136\137\138\139\140\141\142" .. 470 | "\143\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 471 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 472 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 473 | "\032\032\032\032\032\124\010\032\032\032\032\144\145\146\147\148\149\150" .. 474 | "\151\152\153\154\155\156\157\158\159\032\032\032\032\032\032\032\032\032" .. 475 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 476 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 477 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 478 | "\032\160\161\162\163\164\165\166\167\168\169\170\171\172\173\174\175\032" .. 479 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 480 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 481 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 482 | "\032\032\032\124\010\032\032\032\032\176\177\178\179\180\181\182\183\184" .. 483 | "\185\186\187\188\189\190\191\034\032\032\032\032\032\032\032\032\032\032" .. 484 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 485 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 486 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032" .. 487 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 488 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 489 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 490 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 491 | "\032\124\010\051\046\050\032\032\076\111\110\101\108\121\032\115\116\097" .. 492 | "\114\116\032\099\104\097\114\097\099\116\101\114\115\032\032\032\032\032" .. 493 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 494 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 495 | "\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032" .. 496 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 497 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 498 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 499 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 500 | "\010\051\046\050\046\049\032\032\065\108\108\032\051\050\032\102\105\114" .. 501 | "\115\116\032\098\121\116\101\115\032\111\102\032\050\045\098\121\116\101" .. 502 | "\032\115\101\113\117\101\110\099\101\115\032\040\048\120\099\048\045\048" .. 503 | "\120\100\102\041\044\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 504 | "\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\101\097" .. 505 | "\099\104\032\102\111\108\108\111\119\101\100\032\098\121\032\097\032\115" .. 506 | "\112\097\099\101\032\099\104\097\114\097\099\116\101\114\058\032\032\032" .. 507 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 508 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032" .. 509 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 510 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 511 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 512 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 513 | "\032\032\032\032\032\124\010\032\032\032\034\192\032\193\032\194\032\195" .. 514 | "\032\196\032\197\032\198\032\199\032\200\032\201\032\202\032\203\032\204" .. 515 | "\032\205\032\206\032\207\032\032\032\032\032\032\032\032\032\032\032\032" .. 516 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 517 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 518 | "\032\208\032\209\032\210\032\211\032\212\032\213\032\214\032\215\032\216" .. 519 | "\032\217\032\218\032\219\032\220\032\221\032\222\032\223\032\034\032\032" .. 520 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 521 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 522 | "\032\032\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 523 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 524 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 525 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 526 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\051\046\050\046\050" .. 527 | "\032\032\065\108\108\032\049\054\032\102\105\114\115\116\032\098\121\116" .. 528 | "\101\115\032\111\102\032\051\045\098\121\116\101\032\115\101\113\117\101" .. 529 | "\110\099\101\115\032\040\048\120\101\048\045\048\120\101\102\041\044\032" .. 530 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 531 | "\032\124\010\032\032\032\032\032\032\032\101\097\099\104\032\102\111\108" .. 532 | "\108\111\119\101\100\032\098\121\032\097\032\115\112\097\099\101\032\099" .. 533 | "\104\097\114\097\099\116\101\114\058\032\032\032\032\032\032\032\032\032" .. 534 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 535 | "\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032" .. 536 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 537 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 538 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 539 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 540 | "\010\032\032\032\034\224\032\225\032\226\032\227\032\228\032\229\032\230" .. 541 | "\032\231\032\232\032\233\032\234\032\235\032\236\032\237\032\238\032\239" .. 542 | "\032\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 543 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 544 | "\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032" .. 545 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 546 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 547 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 548 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\051" .. 549 | "\046\050\046\051\032\032\065\108\108\032\056\032\102\105\114\115\116\032" .. 550 | "\098\121\116\101\115\032\111\102\032\052\045\098\121\116\101\032\115\101" .. 551 | "\113\117\101\110\099\101\115\032\040\048\120\102\048\045\048\120\102\055" .. 552 | "\041\044\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 553 | "\032\032\032\032\032\124\010\032\032\032\032\032\032\032\101\097\099\104" .. 554 | "\032\102\111\108\108\111\119\101\100\032\098\121\032\097\032\115\112\097" .. 555 | "\099\101\032\099\104\097\114\097\099\116\101\114\058\032\032\032\032\032" .. 556 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 557 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 558 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 559 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 560 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 561 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 562 | "\032\032\032\124\010\032\032\032\034\240\032\241\032\242\032\243\032\244" .. 563 | "\032\245\032\246\032\247\032\034\032\032\032\032\032\032\032\032\032\032" .. 564 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 565 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 566 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032" .. 567 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 568 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 569 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 570 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 571 | "\032\124\010\051\046\050\046\052\032\032\065\108\108\032\052\032\102\105" .. 572 | "\114\115\116\032\098\121\116\101\115\032\111\102\032\053\045\098\121\116" .. 573 | "\101\032\115\101\113\117\101\110\099\101\115\032\040\048\120\102\056\045" .. 574 | "\048\120\102\098\041\044\032\032\032\032\032\032\032\032\032\032\032\032" .. 575 | "\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032" .. 576 | "\101\097\099\104\032\102\111\108\108\111\119\101\100\032\098\121\032\097" .. 577 | "\032\115\112\097\099\101\032\099\104\097\114\097\099\116\101\114\058\032" .. 578 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 579 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 580 | "\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 581 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 582 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 583 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 584 | "\032\032\032\032\032\032\032\124\010\032\032\032\034\248\032\249\032\250" .. 585 | "\032\251\032\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 586 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 587 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 588 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032" .. 589 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 590 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 591 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 592 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 593 | "\032\032\032\032\032\124\010\051\046\050\046\053\032\032\065\108\108\032" .. 594 | "\050\032\102\105\114\115\116\032\098\121\116\101\115\032\111\102\032\054" .. 595 | "\045\098\121\116\101\032\115\101\113\117\101\110\099\101\115\032\040\048" .. 596 | "\120\102\099\045\048\120\102\100\041\044\032\032\032\032\032\032\032\032" .. 597 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 598 | "\032\032\032\032\101\097\099\104\032\102\111\108\108\111\119\101\100\032" .. 599 | "\098\121\032\097\032\115\112\097\099\101\032\099\104\097\114\097\099\116" .. 600 | "\101\114\058\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 601 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 602 | "\032\032\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 603 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 604 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 605 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 606 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032\034\252" .. 607 | "\032\253\032\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 608 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 609 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 610 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 611 | "\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 612 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 613 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 614 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 615 | "\032\032\032\032\032\032\032\032\032\124\010\051\046\051\032\032\083\101" .. 616 | "\113\117\101\110\099\101\115\032\119\105\116\104\032\108\097\115\116\032" .. 617 | "\099\111\110\116\105\110\117\097\116\105\111\110\032\098\121\116\101\032" .. 618 | "\109\105\115\115\105\110\103\032\032\032\032\032\032\032\032\032\032\032" .. 619 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 620 | "\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 621 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 622 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 623 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 624 | "\032\032\032\032\032\032\032\124\010\065\108\108\032\098\121\116\101\115" .. 625 | "\032\111\102\032\097\110\032\105\110\099\111\109\112\108\101\116\101\032" .. 626 | "\115\101\113\117\101\110\099\101\032\115\104\111\117\108\100\032\098\101" .. 627 | "\032\115\105\103\110\097\108\108\101\100\032\097\115\032\097\032\115\105" 628 | end)() .. (function() return 629 | "\110\103\108\101\032\032\032\032\032\032\032\032\032\032\032\124\010\109" .. 630 | "\097\108\102\111\114\109\101\100\032\115\101\113\117\101\110\099\101\044" .. 631 | "\032\105\046\101\046\044\032\121\111\117\032\115\104\111\117\108\100\032" .. 632 | "\115\101\101\032\111\110\108\121\032\097\032\115\105\110\103\108\101\032" .. 633 | "\114\101\112\108\097\099\101\109\101\110\116\032\032\032\032\032\032\032" .. 634 | "\032\032\032\032\032\124\010\099\104\097\114\097\099\116\101\114\032\105" .. 635 | "\110\032\101\097\099\104\032\111\102\032\116\104\101\032\110\101\120\116" .. 636 | "\032\049\048\032\116\101\115\116\115\046\032\040\067\104\097\114\097\099" .. 637 | "\116\101\114\115\032\097\115\032\105\110\032\115\101\099\116\105\111\110" .. 638 | "\032\050\041\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 639 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 640 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 641 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 642 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 643 | "\032\032\032\124\010\051\046\051\046\049\032\032\050\045\098\121\116\101" .. 644 | "\032\115\101\113\117\101\110\099\101\032\119\105\116\104\032\108\097\115" .. 645 | "\116\032\098\121\116\101\032\109\105\115\115\105\110\103\032\040\085\043" .. 646 | "\048\048\048\048\041\058\032\032\032\032\032\034\192\034\032\032\032\032" .. 647 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\051\046\051\046\050" .. 648 | "\032\032\051\045\098\121\116\101\032\115\101\113\117\101\110\099\101\032" .. 649 | "\119\105\116\104\032\108\097\115\116\032\098\121\116\101\032\109\105\115" .. 650 | "\115\105\110\103\032\040\085\043\048\048\048\048\041\058\032\032\032\032" .. 651 | "\032\034\224\128\034\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 652 | "\032\032\124\010\051\046\051\046\051\032\032\052\045\098\121\116\101\032" .. 653 | "\115\101\113\117\101\110\099\101\032\119\105\116\104\032\108\097\115\116" .. 654 | "\032\098\121\116\101\032\109\105\115\115\105\110\103\032\040\085\043\048" .. 655 | "\048\048\048\041\058\032\032\032\032\032\034\240\128\128\034\032\032\032" .. 656 | "\032\032\032\032\032\032\032\032\032\032\032\032\124\010\051\046\051\046" .. 657 | "\052\032\032\053\045\098\121\116\101\032\115\101\113\117\101\110\099\101" .. 658 | "\032\119\105\116\104\032\108\097\115\116\032\098\121\116\101\032\109\105" .. 659 | "\115\115\105\110\103\032\040\085\043\048\048\048\048\041\058\032\032\032" .. 660 | "\032\032\034\248\128\128\128\034\032\032\032\032\032\032\032\032\032\032" .. 661 | "\032\032\032\032\032\124\010\051\046\051\046\053\032\032\054\045\098\121" .. 662 | "\116\101\032\115\101\113\117\101\110\099\101\032\119\105\116\104\032\108" .. 663 | "\097\115\116\032\098\121\116\101\032\109\105\115\115\105\110\103\032\040" .. 664 | "\085\043\048\048\048\048\041\058\032\032\032\032\032\034\252\128\128\128" .. 665 | "\128\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 666 | "\010\051\046\051\046\054\032\032\050\045\098\121\116\101\032\115\101\113" .. 667 | "\117\101\110\099\101\032\119\105\116\104\032\108\097\115\116\032\098\121" .. 668 | "\116\101\032\109\105\115\115\105\110\103\032\040\085\045\048\048\048\048" .. 669 | "\048\055\070\070\041\058\032\034\223\034\032\032\032\032\032\032\032\032" .. 670 | "\032\032\032\032\032\032\032\124\010\051\046\051\046\055\032\032\051\045" .. 671 | "\098\121\116\101\032\115\101\113\117\101\110\099\101\032\119\105\116\104" .. 672 | "\032\108\097\115\116\032\098\121\116\101\032\109\105\115\115\105\110\103" .. 673 | "\032\040\085\045\048\048\048\048\070\070\070\070\041\058\032\034\239\191" .. 674 | "\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 675 | "\051\046\051\046\056\032\032\052\045\098\121\116\101\032\115\101\113\117" .. 676 | "\101\110\099\101\032\119\105\116\104\032\108\097\115\116\032\098\121\116" .. 677 | "\101\032\109\105\115\115\105\110\103\032\040\085\045\048\048\049\070\070" .. 678 | "\070\070\070\041\058\032\034\247\191\191\034\032\032\032\032\032\032\032" .. 679 | "\032\032\032\032\032\032\032\032\124\010\051\046\051\046\057\032\032\053" .. 680 | "\045\098\121\116\101\032\115\101\113\117\101\110\099\101\032\119\105\116" .. 681 | "\104\032\108\097\115\116\032\098\121\116\101\032\109\105\115\115\105\110" .. 682 | "\103\032\040\085\045\048\051\070\070\070\070\070\070\041\058\032\034\251" .. 683 | "\191\191\191\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 684 | "\032\124\010\051\046\051\046\049\048\032\054\045\098\121\116\101\032\115" .. 685 | "\101\113\117\101\110\099\101\032\119\105\116\104\032\108\097\115\116\032" .. 686 | "\098\121\116\101\032\109\105\115\115\105\110\103\032\040\085\045\055\070" .. 687 | "\070\070\070\070\070\070\041\058\032\034\253\191\191\191\191\034\032\032" .. 688 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 689 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 690 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 691 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 692 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 693 | "\032\032\032\124\010\051\046\052\032\032\067\111\110\099\097\116\101\110" .. 694 | "\097\116\105\111\110\032\111\102\032\105\110\099\111\109\112\108\101\116" .. 695 | "\101\032\115\101\113\117\101\110\099\101\115\032\032\032\032\032\032\032" .. 696 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 697 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032" .. 698 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 699 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 700 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 701 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 702 | "\032\124\010\065\108\108\032\116\104\101\032\049\048\032\115\101\113\117" .. 703 | "\101\110\099\101\115\032\111\102\032\051\046\051\032\099\111\110\099\097" .. 704 | "\116\101\110\097\116\101\100\044\032\121\111\117\032\115\104\111\117\108" .. 705 | "\100\032\115\101\101\032\049\048\032\109\097\108\102\111\114\109\101\100" .. 706 | "\032\032\032\032\032\032\032\032\032\124\010\115\101\113\117\101\110\099" .. 707 | "\101\115\032\098\101\105\110\103\032\115\105\103\110\097\108\108\101\100" .. 708 | "\058\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 709 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 710 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 711 | "\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 712 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 713 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 714 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 715 | "\032\032\032\032\032\032\032\124\010\032\032\032\034\192\224\128\240\128" .. 716 | "\128\248\128\128\128\252\128\128\128\128\223\239\191\247\191\191\251\191" .. 717 | "\191\191\253\191\191\191\191\034\032\032\032\032\032\032\032\032\032\032" .. 718 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 719 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 720 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 721 | "\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 722 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 723 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 724 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 725 | "\032\032\032\032\032\032\032\124\010\051\046\053\032\032\073\109\112\111" .. 726 | "\115\115\105\098\108\101\032\098\121\116\101\115\032\032\032\032\032\032" .. 727 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 728 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 729 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032" .. 730 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 731 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 732 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 733 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 734 | "\032\032\032\032\032\124\010\084\104\101\032\102\111\108\108\111\119\105" .. 735 | "\110\103\032\116\119\111\032\098\121\116\101\115\032\099\097\110\110\111" .. 736 | "\116\032\097\112\112\101\097\114\032\105\110\032\097\032\099\111\114\114" .. 737 | "\101\099\116\032\085\084\070\045\056\032\115\116\114\105\110\103\032\032" .. 738 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 739 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 740 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 741 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 742 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 743 | "\032\032\032\124\010\051\046\053\046\049\032\032\102\101\032\061\032\034" .. 744 | "\254\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 745 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 746 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 747 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\051\046\053\046\050" .. 748 | "\032\032\102\102\032\061\032\034\255\034\032\032\032\032\032\032\032\032" .. 749 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 750 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 751 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 752 | "\032\124\010\051\046\053\046\051\032\032\102\101\032\102\101\032\102\102" .. 753 | "\032\102\102\032\061\032\034\254\254\255\255\034\032\032\032\032\032\032" .. 754 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 755 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 756 | "\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032" .. 757 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 758 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 759 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 760 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 761 | "\010\052\032\032\079\118\101\114\108\111\110\103\032\115\101\113\117\101" .. 762 | "\110\099\101\115\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 763 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 764 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 765 | "\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032" .. 766 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 767 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 768 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 769 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\084" .. 770 | "\104\101\032\102\111\108\108\111\119\105\110\103\032\115\101\113\117\101" .. 771 | "\110\099\101\115\032\097\114\101\032\110\111\116\032\109\097\108\102\111" .. 772 | "\114\109\101\100\032\097\099\099\111\114\100\105\110\103\032\116\111\032" .. 773 | "\116\104\101\032\108\101\116\116\101\114\032\111\102\032\032\032\032\032" .. 774 | "\032\032\032\032\032\124\010\116\104\101\032\085\110\105\099\111\100\101" .. 775 | "\032\050\046\048\032\115\116\097\110\100\097\114\100\046\032\072\111\119" .. 776 | "\101\118\101\114\044\032\116\104\101\121\032\097\114\101\032\108\111\110" .. 777 | "\103\101\114\032\116\104\101\110\032\110\101\099\101\115\115\097\114\121" .. 778 | "\032\097\110\100\032\032\032\032\032\032\032\032\032\124\010\097\032\099" .. 779 | "\111\114\114\101\099\116\032\085\084\070\045\056\032\101\110\099\111\100" .. 780 | "\101\114\032\105\115\032\110\111\116\032\097\108\108\111\119\101\100\032" .. 781 | "\116\111\032\112\114\111\100\117\099\101\032\116\104\101\109\046\032\065" .. 782 | "\032\034\115\097\102\101\032\085\084\070\045\056\032\032\032\032\032\032" .. 783 | "\032\032\032\124\010\100\101\099\111\100\101\114\034\032\115\104\111\117" .. 784 | "\108\100\032\114\101\106\101\099\116\032\116\104\101\109\032\106\117\115" .. 785 | "\116\032\108\105\107\101\032\109\097\108\102\111\114\109\101\100\032\115" .. 786 | "\101\113\117\101\110\099\101\115\032\102\111\114\032\116\119\111\032\032" .. 787 | "\032\032\032\032\032\032\032\032\032\032\032\124\010\114\101\097\115\111" .. 788 | "\110\115\058\032\040\049\041\032\073\116\032\104\101\108\112\115\032\116" .. 789 | "\111\032\100\101\098\117\103\032\097\112\112\108\105\099\097\116\105\111" .. 790 | "\110\115\032\105\102\032\111\118\101\114\108\111\110\103\032\115\101\113" .. 791 | "\117\101\110\099\101\115\032\097\114\101\032\032\032\032\032\032\032\032" .. 792 | "\032\124\010\110\111\116\032\116\114\101\097\116\101\100\032\097\115\032" .. 793 | "\118\097\108\105\100\032\114\101\112\114\101\115\101\110\116\097\116\105" .. 794 | "\111\110\115\032\111\102\032\099\104\097\114\097\099\116\101\114\115\044" .. 795 | "\032\098\101\099\097\117\115\101\032\116\104\105\115\032\104\101\108\112" .. 796 | "\115\032\032\032\032\032\032\032\032\124\010\116\111\032\115\112\111\116" .. 797 | "\032\112\114\111\098\108\101\109\115\032\109\111\114\101\032\113\117\105" .. 798 | "\099\107\108\121\046\032\040\050\041\032\079\118\101\114\108\111\110\103" .. 799 | "\032\115\101\113\117\101\110\099\101\115\032\112\114\111\118\105\100\101" .. 800 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 801 | "\010\097\108\116\101\114\110\097\116\105\118\101\032\114\101\112\114\101" .. 802 | "\115\101\110\116\097\116\105\111\110\115\032\111\102\032\099\104\097\114" .. 803 | "\097\099\116\101\114\115\044\032\116\104\097\116\032\099\111\117\108\100" .. 804 | "\032\109\097\108\105\099\105\111\117\115\108\121\032\098\101\032\032\032" .. 805 | "\032\032\032\032\032\032\032\124\010\117\115\101\100\032\116\111\032\098" .. 806 | "\121\112\097\115\115\032\102\105\108\116\101\114\115\032\116\104\097\116" .. 807 | "\032\099\104\101\099\107\032\111\110\108\121\032\102\111\114\032\065\083" .. 808 | "\067\073\073\032\099\104\097\114\097\099\116\101\114\115\046\032\070\111" .. 809 | "\114\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\105" .. 810 | "\110\115\116\097\110\099\101\044\032\097\032\050\045\098\121\116\101\032" .. 811 | "\101\110\099\111\100\101\100\032\108\105\110\101\032\102\101\101\100\032" .. 812 | "\040\076\070\041\032\119\111\117\108\100\032\110\111\116\032\098\101\032" .. 813 | "\099\097\117\103\104\116\032\098\121\032\097\032\032\032\032\032\032\032" .. 814 | "\032\032\032\032\032\124\010\108\105\110\101\032\099\111\117\110\116\101" .. 815 | "\114\032\116\104\097\116\032\099\111\117\110\116\115\032\111\110\108\121" .. 816 | "\032\048\120\048\097\032\098\121\116\101\115\044\032\098\117\116\032\105" .. 817 | "\116\032\119\111\117\108\100\032\115\116\105\108\108\032\098\101\032\032" .. 818 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\112\114\111" .. 819 | "\099\101\115\115\101\100\032\097\115\032\097\032\108\105\110\101\032\102" 820 | end)() .. (function() return 821 | "\101\101\100\032\098\121\032\097\110\032\117\110\115\097\102\101\032\085" .. 822 | "\084\070\045\056\032\100\101\099\111\100\101\114\032\108\097\116\101\114" .. 823 | "\032\105\110\032\116\104\101\032\032\032\032\032\032\032\032\032\032\032" .. 824 | "\032\032\032\124\010\112\105\112\101\108\105\110\101\046\032\070\114\111" .. 825 | "\109\032\097\032\115\101\099\117\114\105\116\121\032\112\111\105\110\116" .. 826 | "\032\111\102\032\118\105\101\119\044\032\065\083\067\073\073\032\099\111" .. 827 | "\109\112\097\116\105\098\105\108\105\116\121\032\111\102\032\085\084\070" .. 828 | "\045\056\032\032\032\032\032\032\032\032\032\124\010\115\101\113\117\101" .. 829 | "\110\099\101\115\032\109\101\097\110\115\032\097\108\115\111\044\032\116" .. 830 | "\104\097\116\032\065\083\067\073\073\032\099\104\097\114\097\099\116\101" .. 831 | "\114\115\032\097\114\101\032\042\111\110\108\121\042\032\097\108\108\111" .. 832 | "\119\101\100\032\116\111\032\098\101\032\032\032\032\032\032\032\032\032" .. 833 | "\032\124\010\114\101\112\114\101\115\101\110\116\101\100\032\098\121\032" .. 834 | "\065\083\067\073\073\032\098\121\116\101\115\032\105\110\032\116\104\101" .. 835 | "\032\114\097\110\103\101\032\048\120\048\048\045\048\120\055\102\046\032" .. 836 | "\084\111\032\101\110\115\117\114\101\032\116\104\105\115\032\032\032\032" .. 837 | "\032\032\032\032\032\032\032\032\032\124\010\097\115\112\101\099\116\032" .. 838 | "\111\102\032\065\083\067\073\073\032\099\111\109\112\097\116\105\098\105" .. 839 | "\108\105\116\121\044\032\117\115\101\032\111\110\108\121\032\034\115\097" .. 840 | "\102\101\032\085\084\070\045\056\032\100\101\099\111\100\101\114\115\034" .. 841 | "\032\116\104\097\116\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 842 | "\010\114\101\106\101\099\116\032\111\118\101\114\108\111\110\103\032\085" .. 843 | "\084\070\045\056\032\115\101\113\117\101\110\099\101\115\032\102\111\114" .. 844 | "\032\119\104\105\099\104\032\097\032\115\104\111\114\116\101\114\032\101" .. 845 | "\110\099\111\100\105\110\103\032\101\120\105\115\116\115\046\032\032\032" .. 846 | "\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032" .. 847 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 848 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 849 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 850 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\052" .. 851 | "\046\049\032\032\069\120\097\109\112\108\101\115\032\111\102\032\097\110" .. 852 | "\032\111\118\101\114\108\111\110\103\032\065\083\067\073\073\032\099\104" .. 853 | "\097\114\097\099\116\101\114\032\032\032\032\032\032\032\032\032\032\032" .. 854 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 855 | "\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032\032\032" .. 856 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 857 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 858 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 859 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\087\105\116" .. 860 | "\104\032\097\032\115\097\102\101\032\085\084\070\045\056\032\100\101\099" .. 861 | "\111\100\101\114\044\032\097\108\108\032\111\102\032\116\104\101\032\102" .. 862 | "\111\108\108\111\119\105\110\103\032\102\105\118\101\032\111\118\101\114" .. 863 | "\108\111\110\103\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 864 | "\032\032\032\124\010\114\101\112\114\101\115\101\110\116\097\116\105\111" .. 865 | "\110\115\032\111\102\032\116\104\101\032\065\083\067\073\073\032\099\104" .. 866 | "\097\114\097\099\116\101\114\032\115\108\097\115\104\032\040\034\047\034" .. 867 | "\041\032\115\104\111\117\108\100\032\098\101\032\114\101\106\101\099\116" .. 868 | "\101\100\032\032\032\032\032\032\032\032\032\124\010\108\105\107\101\032" .. 869 | "\097\032\109\097\108\102\111\114\109\101\100\032\085\084\070\045\056\032" .. 870 | "\115\101\113\117\101\110\099\101\044\032\102\111\114\032\105\110\115\116" .. 871 | "\097\110\099\101\032\098\121\032\115\117\098\115\116\105\116\117\116\105" .. 872 | "\110\103\032\105\116\032\119\105\116\104\032\032\032\032\032\032\032\032" .. 873 | "\032\124\010\097\032\114\101\112\108\097\099\101\109\101\110\116\032\099" .. 874 | "\104\097\114\097\099\116\101\114\046\032\073\102\032\121\111\117\032\115" .. 875 | "\101\101\032\097\032\115\108\097\115\104\032\098\101\108\111\119\044\032" .. 876 | "\121\111\117\032\100\111\032\110\111\116\032\104\097\118\101\032\097\032" .. 877 | "\032\032\032\032\032\032\032\032\032\124\010\115\097\102\101\032\085\084" .. 878 | "\070\045\056\032\100\101\099\111\100\101\114\033\032\032\032\032\032\032" .. 879 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 880 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 881 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 882 | "\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 883 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 884 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 885 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 886 | "\032\032\032\032\032\032\032\124\010\052\046\049\046\049\032\085\043\048" .. 887 | "\048\050\070\032\061\032\099\048\032\097\102\032\032\032\032\032\032\032" .. 888 | "\032\032\032\032\032\032\061\032\034\192\175\034\032\032\032\032\032\032" .. 889 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 890 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 891 | "\052\046\049\046\050\032\085\043\048\048\050\070\032\061\032\101\048\032" .. 892 | "\056\048\032\097\102\032\032\032\032\032\032\032\032\032\032\061\032\034" .. 893 | "\224\128\175\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 894 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 895 | "\032\032\032\032\032\032\032\032\124\010\052\046\049\046\051\032\085\043" .. 896 | "\048\048\050\070\032\061\032\102\048\032\056\048\032\056\048\032\097\102" .. 897 | "\032\032\032\032\032\032\032\061\032\034\240\128\128\175\034\032\032\032" .. 898 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 899 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 900 | "\032\124\010\052\046\049\046\052\032\085\043\048\048\050\070\032\061\032" .. 901 | "\102\056\032\056\048\032\056\048\032\056\048\032\097\102\032\032\032\032" .. 902 | "\061\032\034\248\128\128\128\175\034\032\032\032\032\032\032\032\032\032" .. 903 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 904 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\052\046\049" .. 905 | "\046\053\032\085\043\048\048\050\070\032\061\032\102\099\032\056\048\032" .. 906 | "\056\048\032\056\048\032\056\048\032\097\102\032\061\032\034\252\128\128" .. 907 | "\128\128\175\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 908 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 909 | "\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032" .. 910 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 911 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 912 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 913 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 914 | "\052\046\050\032\032\077\097\120\105\109\117\109\032\111\118\101\114\108" .. 915 | "\111\110\103\032\115\101\113\117\101\110\099\101\115\032\032\032\032\032" .. 916 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 917 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 918 | "\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032\032" .. 919 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 920 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 921 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 922 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\066\101" .. 923 | "\108\111\119\032\121\111\117\032\115\101\101\032\116\104\101\032\104\105" .. 924 | "\103\104\101\115\116\032\085\110\105\099\111\100\101\032\118\097\108\117" .. 925 | "\101\032\116\104\097\116\032\105\115\032\115\116\105\108\108\032\114\101" .. 926 | "\115\117\108\116\105\110\103\032\105\110\032\097\110\032\032\032\032\032" .. 927 | "\032\032\032\032\124\010\111\118\101\114\108\111\110\103\032\115\101\113" .. 928 | "\117\101\110\099\101\032\105\102\032\114\101\112\114\101\115\101\110\116" .. 929 | "\101\100\032\119\105\116\104\032\116\104\101\032\103\105\118\101\110\032" .. 930 | "\110\117\109\098\101\114\032\111\102\032\098\121\116\101\115\046\032\084" .. 931 | "\104\105\115\032\032\032\032\032\032\032\032\032\124\010\105\115\032\097" .. 932 | "\032\098\111\117\110\100\097\114\121\032\116\101\115\116\032\102\111\114" .. 933 | "\032\115\097\102\101\032\085\084\070\045\056\032\100\101\099\111\100\101" .. 934 | "\114\115\046\032\065\108\108\032\102\105\118\101\032\099\104\097\114\097" .. 935 | "\099\116\101\114\115\032\115\104\111\117\108\100\032\032\032\032\032\032" .. 936 | "\032\032\124\010\098\101\032\114\101\106\101\099\116\101\100\032\108\105" .. 937 | "\107\101\032\109\097\108\102\111\114\109\101\100\032\085\084\070\045\056" .. 938 | "\032\115\101\113\117\101\110\099\101\115\046\032\032\032\032\032\032\032" .. 939 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 940 | "\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032" .. 941 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 942 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 943 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 944 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 945 | "\124\010\052\046\050\046\049\032\032\085\045\048\048\048\048\048\048\055" .. 946 | "\070\032\061\032\099\049\032\098\102\032\032\032\032\032\032\032\032\032" .. 947 | "\032\032\032\032\061\032\034\193\191\034\032\032\032\032\032\032\032\032" .. 948 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 949 | "\032\032\032\032\032\032\032\032\032\124\010\052\046\050\046\050\032\032" .. 950 | "\085\045\048\048\048\048\048\055\070\070\032\061\032\101\048\032\057\102" .. 951 | "\032\098\102\032\032\032\032\032\032\032\032\032\032\061\032\034\224\159" .. 952 | "\191\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 953 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 954 | "\032\124\010\052\046\050\046\051\032\032\085\045\048\048\048\048\070\070" .. 955 | "\070\070\032\061\032\102\048\032\056\102\032\098\102\032\098\102\032\032" .. 956 | "\032\032\032\032\032\061\032\034\240\143\191\191\034\032\032\032\032\032" .. 957 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 958 | "\032\032\032\032\032\032\032\032\032\032\032\032\124\010\052\046\050\046" .. 959 | "\052\032\032\085\045\048\048\049\070\070\070\070\070\032\061\032\102\056" .. 960 | "\032\056\055\032\098\102\032\098\102\032\098\102\032\032\032\032\061\032" .. 961 | "\034\248\135\191\191\191\034\032\032\032\032\032\032\032\032\032\032\032" .. 962 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 963 | "\032\032\032\032\032\032\124\010\052\046\050\046\053\032\032\085\045\048" .. 964 | "\051\070\070\070\070\070\070\032\061\032\102\099\032\056\051\032\098\102" .. 965 | "\032\098\102\032\098\102\032\098\102\032\061\032\034\252\131\191\191\191" .. 966 | "\191\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 967 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 968 | "\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 969 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 970 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 971 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 972 | "\032\032\032\032\032\032\032\032\032\124\010\052\046\051\032\032\079\118" .. 973 | "\101\114\108\111\110\103\032\114\101\112\114\101\115\101\110\116\097\116" .. 974 | "\105\111\110\032\111\102\032\116\104\101\032\078\085\076\032\099\104\097" .. 975 | "\114\097\099\116\101\114\032\032\032\032\032\032\032\032\032\032\032\032" .. 976 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124" .. 977 | "\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 978 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 979 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 980 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 981 | "\032\032\032\032\032\032\032\124\010\084\104\101\032\102\111\108\108\111" .. 982 | "\119\105\110\103\032\102\105\118\101\032\115\101\113\117\101\110\099\101" .. 983 | "\115\032\115\104\111\117\108\100\032\097\108\115\111\032\098\101\032\114" .. 984 | "\101\106\101\099\116\101\100\032\108\105\107\101\032\109\097\108\102\111" .. 985 | "\114\109\101\100\032\032\032\032\032\032\032\032\032\032\032\124\010\085" .. 986 | "\084\070\045\056\032\115\101\113\117\101\110\099\101\115\032\097\110\100" .. 987 | "\032\115\104\111\117\108\100\032\110\111\116\032\098\101\032\116\114\101" .. 988 | "\097\116\101\100\032\108\105\107\101\032\116\104\101\032\065\083\067\073" .. 989 | "\073\032\078\085\076\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 990 | "\032\032\032\032\032\124\010\099\104\097\114\097\099\116\101\114\046\032" .. 991 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 992 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 993 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 994 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032" .. 995 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 996 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 997 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 998 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 999 | "\032\032\032\124\010\052\046\051\046\049\032\032\085\043\048\048\048\048" .. 1000 | "\032\061\032\099\048\032\056\048\032\032\032\032\032\032\032\032\032\032" .. 1001 | "\032\032\032\061\032\034\192\128\034\032\032\032\032\032\032\032\032\032" .. 1002 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1003 | "\032\032\032\032\032\032\032\032\032\032\032\032\124\010\052\046\051\046" .. 1004 | "\050\032\032\085\043\048\048\048\048\032\061\032\101\048\032\056\048\032" .. 1005 | "\056\048\032\032\032\032\032\032\032\032\032\032\061\032\034\224\128\128" .. 1006 | "\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1007 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1008 | "\032\032\032\032\124\010\052\046\051\046\051\032\032\085\043\048\048\048" .. 1009 | "\048\032\061\032\102\048\032\056\048\032\056\048\032\056\048\032\032\032" .. 1010 | "\032\032\032\032\061\032\034\240\128\128\128\034\032\032\032\032\032\032" 1011 | end)() .. (function() return 1012 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1013 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\052" .. 1014 | "\046\051\046\052\032\032\085\043\048\048\048\048\032\061\032\102\056\032" .. 1015 | "\056\048\032\056\048\032\056\048\032\056\048\032\032\032\032\061\032\034" .. 1016 | "\248\128\128\128\128\034\032\032\032\032\032\032\032\032\032\032\032\032" .. 1017 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1018 | "\032\032\032\032\032\032\032\032\032\124\010\052\046\051\046\053\032\032" .. 1019 | "\085\043\048\048\048\048\032\061\032\102\099\032\056\048\032\056\048\032" .. 1020 | "\056\048\032\056\048\032\056\048\032\061\032\034\252\128\128\128\128\128" .. 1021 | "\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1022 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1023 | "\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032" .. 1024 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1025 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1026 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1027 | "\032\032\032\032\032\032\032\032\032\032\032\032\124\010\053\032\032\073" .. 1028 | "\108\108\101\103\097\108\032\099\111\100\101\032\112\111\115\105\116\105" .. 1029 | "\111\110\115\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1030 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1031 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1032 | "\032\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1033 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1034 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1035 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1036 | "\032\032\032\032\032\032\032\032\032\032\124\010\084\104\101\032\102\111" .. 1037 | "\108\108\111\119\105\110\103\032\085\084\070\045\056\032\115\101\113\117" .. 1038 | "\101\110\099\101\115\032\115\104\111\117\108\100\032\098\101\032\114\101" .. 1039 | "\106\101\099\116\101\100\032\108\105\107\101\032\109\097\108\102\111\114" .. 1040 | "\109\101\100\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1041 | "\124\010\115\101\113\117\101\110\099\101\115\044\032\098\101\099\097\117" .. 1042 | "\115\101\032\116\104\101\121\032\110\101\118\101\114\032\114\101\112\114" .. 1043 | "\101\115\101\110\116\032\118\097\108\105\100\032\073\083\079\032\049\048" .. 1044 | "\054\052\054\032\099\104\097\114\097\099\116\101\114\115\032\097\110\100" .. 1045 | "\032\032\032\032\032\032\032\032\124\010\097\032\085\084\070\045\056\032" .. 1046 | "\100\101\099\111\100\101\114\032\116\104\097\116\032\097\099\099\101\112" .. 1047 | "\116\115\032\116\104\101\109\032\109\105\103\104\116\032\105\110\116\114" .. 1048 | "\111\100\117\099\101\032\115\101\099\117\114\105\116\121\032\112\114\111" .. 1049 | "\098\108\101\109\115\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 1050 | "\099\111\109\112\097\114\097\098\108\101\032\116\111\032\111\118\101\114" .. 1051 | "\108\111\110\103\032\085\084\070\045\056\032\115\101\113\117\101\110\099" .. 1052 | "\101\115\046\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1053 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1054 | "\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032\032" .. 1055 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1056 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1057 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1058 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\053\046" .. 1059 | "\049\032\083\105\110\103\108\101\032\085\084\070\045\049\054\032\115\117" .. 1060 | "\114\114\111\103\097\116\101\115\032\032\032\032\032\032\032\032\032\032" .. 1061 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1062 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1063 | "\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032" .. 1064 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1065 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1066 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1067 | "\032\032\032\032\032\032\032\032\032\032\032\032\124\010\053\046\049\046" .. 1068 | "\049\032\032\085\043\068\056\048\048\032\061\032\101\100\032\097\048\032" .. 1069 | "\056\048\032\061\032\034\237\160\128\034\032\032\032\032\032\032\032\032" .. 1070 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1071 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1072 | "\032\032\032\032\124\010\053\046\049\046\050\032\032\085\043\068\066\055" .. 1073 | "\070\032\061\032\101\100\032\097\100\032\098\102\032\061\032\034\237\173" .. 1074 | "\191\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1075 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1076 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010\053\046" .. 1077 | "\049\046\051\032\032\085\043\068\066\056\048\032\061\032\101\100\032\097" .. 1078 | "\101\032\056\048\032\061\032\034\237\174\128\034\032\032\032\032\032\032" .. 1079 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1080 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1081 | "\032\032\032\032\032\032\124\010\053\046\049\046\052\032\032\085\043\068" .. 1082 | "\066\070\070\032\061\032\101\100\032\097\102\032\098\102\032\061\032\034" .. 1083 | "\237\175\191\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1084 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1085 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 1086 | "\053\046\049\046\053\032\032\085\043\068\067\048\048\032\061\032\101\100" .. 1087 | "\032\098\048\032\056\048\032\061\032\034\237\176\128\034\032\032\032\032" .. 1088 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1089 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1090 | "\032\032\032\032\032\032\032\032\124\010\053\046\049\046\054\032\032\085" .. 1091 | "\043\068\070\056\048\032\061\032\101\100\032\098\101\032\056\048\032\061" .. 1092 | "\032\034\237\190\128\034\032\032\032\032\032\032\032\032\032\032\032\032" .. 1093 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1094 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1095 | "\124\010\053\046\049\046\055\032\032\085\043\068\070\070\070\032\061\032" .. 1096 | "\101\100\032\098\102\032\098\102\032\061\032\034\237\191\191\034\032\032" .. 1097 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1098 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1099 | "\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032" .. 1100 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1101 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1102 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1103 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1104 | "\124\010\053\046\050\032\080\097\105\114\101\100\032\085\084\070\045\049" .. 1105 | "\054\032\115\117\114\114\111\103\097\116\101\115\032\032\032\032\032\032" .. 1106 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1107 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1108 | "\032\032\032\032\032\032\032\032\124\010\032\032\032\032\032\032\032\032" .. 1109 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1110 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1111 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1112 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 1113 | "\053\046\050\046\049\032\032\085\043\068\056\048\048\032\085\043\068\067" .. 1114 | "\048\048\032\061\032\101\100\032\097\048\032\056\048\032\101\100\032\098" .. 1115 | "\048\032\056\048\032\061\032\034\237\160\128\237\176\128\034\032\032\032" .. 1116 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1117 | "\032\032\032\032\032\032\032\032\032\032\124\010\053\046\050\046\050\032" .. 1118 | "\032\085\043\068\056\048\048\032\085\043\068\070\070\070\032\061\032\101" .. 1119 | "\100\032\097\048\032\056\048\032\101\100\032\098\102\032\098\102\032\061" .. 1120 | "\032\034\237\160\128\237\191\191\034\032\032\032\032\032\032\032\032\032" .. 1121 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1122 | "\032\032\032\032\124\010\053\046\050\046\051\032\032\085\043\068\066\055" .. 1123 | "\070\032\085\043\068\067\048\048\032\061\032\101\100\032\097\100\032\098" .. 1124 | "\102\032\101\100\032\098\048\032\056\048\032\061\032\034\237\173\191\237" .. 1125 | "\176\128\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1126 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 1127 | "\053\046\050\046\052\032\032\085\043\068\066\055\070\032\085\043\068\070" .. 1128 | "\070\070\032\061\032\101\100\032\097\100\032\098\102\032\101\100\032\098" .. 1129 | "\102\032\098\102\032\061\032\034\237\173\191\237\191\191\034\032\032\032" .. 1130 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1131 | "\032\032\032\032\032\032\032\032\032\032\124\010\053\046\050\046\053\032" .. 1132 | "\032\085\043\068\066\056\048\032\085\043\068\067\048\048\032\061\032\101" .. 1133 | "\100\032\097\101\032\056\048\032\101\100\032\098\048\032\056\048\032\061" .. 1134 | "\032\034\237\174\128\237\176\128\034\032\032\032\032\032\032\032\032\032" .. 1135 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1136 | "\032\032\032\032\124\010\053\046\050\046\054\032\032\085\043\068\066\056" .. 1137 | "\048\032\085\043\068\070\070\070\032\061\032\101\100\032\097\101\032\056" .. 1138 | "\048\032\101\100\032\098\102\032\098\102\032\061\032\034\237\174\128\237" .. 1139 | "\191\191\034\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1140 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\124\010" .. 1141 | "\053\046\050\046\055\032\032\085\043\068\066\070\070\032\085\043\068\067" .. 1142 | "\048\048\032\061\032\101\100\032\097\102\032\098\102\032\101\100\032\098" .. 1143 | "\048\032\056\048\032\061\032\034\237\175\191\237\176\128\034\032\032\032" .. 1144 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1145 | "\032\032\032\032\032\032\032\032\032\032\124\010\053\046\050\046\056\032" .. 1146 | "\032\085\043\068\066\070\070\032\085\043\068\070\070\070\032\061\032\101" .. 1147 | "\100\032\097\102\032\098\102\032\101\100\032\098\102\032\098\102\032\061" .. 1148 | "\032\034\237\175\191\237\191\191\034\032\032\032\032\032\032\032\032\032" .. 1149 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1150 | "\032\032\032\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032" .. 1151 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1152 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1153 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1154 | "\032\032\032\032\032\032\032\032\032\032\032\032\124\010\053\046\051\032" .. 1155 | "\079\116\104\101\114\032\105\108\108\101\103\097\108\032\099\111\100\101" .. 1156 | "\032\112\111\115\105\116\105\111\110\115\032\032\032\032\032\032\032\032" .. 1157 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1158 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1159 | "\032\032\124\010\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1160 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1161 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1162 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1163 | "\032\032\032\032\032\032\032\032\032\032\124\010\053\046\051\046\049\032" .. 1164 | "\032\085\043\070\070\070\069\032\061\032\101\102\032\098\102\032\098\101" .. 1165 | "\032\061\032\034\239\191\190\034\032\032\032\032\032\032\032\032\032\032" .. 1166 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1167 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1168 | "\032\032\124\010\053\046\051\046\050\032\032\085\043\070\070\070\070\032" .. 1169 | "\061\032\101\102\032\098\102\032\098\102\032\061\032\034\239\191\191\034" .. 1170 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1171 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1172 | "\032\032\032\032\032\032\032\032\032\032\032\032\124\010\032\032\032\032" .. 1173 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1174 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1175 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1176 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1177 | "\032\032\124\010\084\072\069\032\069\078\068\032\032\032\032\032\032\032" .. 1178 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1179 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1180 | "\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032\032" .. 1181 | "\032\032\032\032\032\032\032\032\032\032\124\010" 1182 | end)() 1183 | 1184 | -------------------------------------------------------------------------------- 1185 | 1186 | for LOAD_NAME, LOAD in pairs { C = luatexts.load, LUA = luatexts_lua.load } do 1187 | for NAME, NL in pairs { 1188 | [LOAD_NAME .. "-" .. "LF"] = "\n", [LOAD_NAME .. "-" .. "CRLF"] = "\r\n" 1189 | } 1190 | do 1191 | print("===== BEGIN core tests", NAME, "=====") 1192 | 1193 | ensure_fails_with_substring( 1194 | "load without args", 1195 | function() return LOAD() end, 1196 | "bad argument #1 to '.-' %(string expected.-%)" 1197 | ) 1198 | 1199 | ensure_error_with_substring( 1200 | "empty string", 1201 | "load failed: ", 1202 | LOAD('') 1203 | ) 1204 | 1205 | ensure_returns( 1206 | "zero-sized tuple " .. NAME, 1207 | 1, { true }, 1208 | LOAD('0' .. NL) 1209 | ) 1210 | 1211 | ensure_returns( 1212 | "zero-sized tuple tail garbage ignored" .. NAME, 1213 | 1, { true }, 1214 | LOAD('0' .. NL .. "yada yada!") 1215 | ) 1216 | 1217 | ensure_error_with_substring( 1218 | "no data " .. NAME, 1219 | "load failed: ", 1220 | LOAD('' .. NL) 1221 | ) 1222 | 1223 | ensure_error_with_substring( 1224 | "negative size " .. NAME, 1225 | "load failed: ", 1226 | LOAD('-1' .. NL) 1227 | ) 1228 | 1229 | ensure_error_with_substring( 1230 | "tuple size too large (empty) " .. NAME, 1231 | "load failed: ", 1232 | LOAD('1' .. NL) 1233 | ) 1234 | 1235 | ensure_error_with_substring( 1236 | "tuple size, no newline", 1237 | "load failed: ", 1238 | LOAD('1') 1239 | ) 1240 | 1241 | ensure_returns( 1242 | "nil " .. NAME, 1243 | 2, { true, nil }, 1244 | LOAD('1' .. NL .. '-' .. NL) 1245 | ) 1246 | 1247 | ensure_error_with_substring( 1248 | "no newline after type " .. NAME, 1249 | "load failed: ", 1250 | LOAD('1' .. NL .. '-') 1251 | ) 1252 | ensure_error_with_substring( 1253 | "tuple size too large (nil) " .. NAME, 1254 | "load failed: ", 1255 | LOAD('2' .. NL .. '-' .. NL) 1256 | ) 1257 | 1258 | ensure_error_with_substring( 1259 | "fractional tuple size " .. NAME, 1260 | "load failed: ", 1261 | LOAD('3.14' .. NL .. '-' .. NL) 1262 | ) 1263 | 1264 | ensure_error_with_substring( 1265 | "bad type " .. NAME, 1266 | "load failed: ", 1267 | LOAD('1' .. NL .. 'X' .. NL) 1268 | ) 1269 | 1270 | ensure_error_with_substring( 1271 | "no newline after type " .. NAME, 1272 | "load failed: ", 1273 | LOAD('1' .. NL .. '-') 1274 | ) 1275 | 1276 | ensure_error_with_substring( 1277 | "no newline after type and garbage " .. NAME, 1278 | "load failed: ", 1279 | LOAD('1' .. NL .. '- yada yada') 1280 | ) 1281 | 1282 | ensure_returns( 1283 | "nil tail garbage ignored " .. NAME, 1284 | 2, { true, nil }, 1285 | LOAD('1' .. NL .. '-' .. NL .. "yada yada!") 1286 | ) 1287 | 1288 | ensure_returns( 1289 | "false " .. NAME, 1290 | 2, { true, false }, 1291 | LOAD('1' .. NL .. '0' .. NL) 1292 | ) 1293 | 1294 | ensure_returns( 1295 | "true " .. NAME, 1296 | 2, { true, true }, 1297 | LOAD('1' .. NL .. '1' .. NL) 1298 | ) 1299 | 1300 | ensure_returns( 1301 | "true-nil-false " .. NAME, 1302 | 4, { true, true, nil, false }, 1303 | LOAD( 1304 | '3' .. NL 1305 | .. '1' .. NL 1306 | .. '-' .. NL 1307 | .. '0' .. NL 1308 | ) 1309 | ) 1310 | 1311 | print("===== END core tests", NAME, "=====") 1312 | 1313 | for _, BASE in ipairs({ "U", "H", "Z" }) do 1314 | local PARAM = 1315 | ({ 1316 | U = 1317 | { 1318 | max = '4294967295', trunc = '4294967296'; 1319 | noneg = true, notrunc = true; 1320 | }; 1321 | H = 1322 | { 1323 | max = 'FFFFFFFF', trunc = '100000000'; 1324 | noneg = true, notrunc = true; 1325 | }; 1326 | Z = 1327 | { 1328 | max = '1Z141Z3', trunc = '1Z141Z4'; 1329 | noneg = true, notrunc = true; 1330 | }; 1331 | })[BASE] 1332 | 1333 | local NAME = BASE .. " " .. NAME 1334 | 1335 | print("===== BEGIN uint tests", NAME, "=====") 1336 | 1337 | ensure_returns( 1338 | "zero uint " .. NAME, 1339 | 2, { true, 0 }, 1340 | LOAD( 1341 | '1' .. NL 1342 | .. BASE .. NL 1343 | .. '0' .. NL 1344 | ) 1345 | ) 1346 | 1347 | ensure_returns( 1348 | "one uint " .. NAME, 1349 | 2, { true, 1 }, 1350 | LOAD( 1351 | '1' .. NL 1352 | .. BASE .. NL 1353 | .. '1' .. NL 1354 | ) 1355 | ) 1356 | 1357 | if not PARAM.noneg then 1358 | -- Implementation detail; should fail actually. 1359 | ensure_returns( 1360 | "negative uint " .. NAME, 1361 | 2, { true, 4294967295 }, -- Exact value is an implementation detail 1362 | LOAD( 1363 | '1' .. NL 1364 | .. BASE .. NL 1365 | .. '-1' .. NL 1366 | ) 1367 | ) 1368 | else 1369 | -- Exact error message is an implementation detail 1370 | ensure_error_with_substring( 1371 | "negative uint " .. NAME, 1372 | "load failed: ", 1373 | LOAD( 1374 | '1' .. NL 1375 | .. BASE .. NL 1376 | .. '-1' .. NL 1377 | ) 1378 | ) 1379 | end 1380 | 1381 | ensure_error_with_substring( 1382 | "fractional uint " .. NAME, 1383 | "load failed: ", 1384 | LOAD( 1385 | '1' .. NL 1386 | .. BASE .. NL 1387 | .. '1.1' .. NL 1388 | ) 1389 | ) 1390 | 1391 | ensure_error_with_substring( 1392 | "uint: missing newline " .. NAME, 1393 | "load failed: ", 1394 | LOAD( 1395 | '1' .. NL 1396 | .. BASE .. NL 1397 | .. '1' 1398 | ) 1399 | ) 1400 | 1401 | ensure_error_with_substring( 1402 | "uint: missing newline and garbage " .. NAME, 1403 | "load failed: ", 1404 | LOAD( 1405 | '1' .. NL 1406 | .. BASE .. NL 1407 | .. '1 yada yada' 1408 | ) 1409 | ) 1410 | 1411 | ensure_returns( 1412 | "huge uint " .. NAME, 1413 | 2, { true, 4294967295 }, 1414 | LOAD( 1415 | '1' .. NL 1416 | .. BASE .. NL 1417 | .. PARAM.max .. NL 1418 | ) 1419 | ) 1420 | 1421 | if not PARAM.notrunc then 1422 | -- Implementation detail; should fail actually. 1423 | ensure_returns( 1424 | "huge uint truncated " .. NAME, 1425 | 2, { true, 4294967295 }, -- implementation detail 1426 | LOAD( 1427 | '1' .. NL 1428 | .. BASE .. NL 1429 | .. PARAM.trunc .. NL 1430 | ) 1431 | ) 1432 | else 1433 | ensure_error_with_substring( 1434 | "huge uint: too huge " .. NAME, 1435 | "load failed: ", 1436 | LOAD( 1437 | '1' .. NL 1438 | .. BASE .. NL 1439 | .. PARAM.trunc .. NL 1440 | ) 1441 | ) 1442 | end 1443 | 1444 | print("===== END uint tests", NAME, "=====") 1445 | end 1446 | print("===== BEGIN number tests", NAME, "=====") 1447 | 1448 | ensure_returns( 1449 | "number zero " .. NAME, 1450 | 2, { true, 0 }, 1451 | LOAD( 1452 | '1' .. NL 1453 | .. 'N' .. NL 1454 | .. '0' .. NL 1455 | ) 1456 | ) 1457 | 1458 | ensure_returns( 1459 | "number one " .. NAME, 1460 | 2, { true, 1 }, 1461 | LOAD( 1462 | '1' .. NL 1463 | .. 'N' .. NL 1464 | .. '1' .. NL 1465 | ) 1466 | ) 1467 | 1468 | ensure_returns( 1469 | "number pi " .. NAME, 1470 | 2, { true, 3.141592653589793115997963468544185161590576171875 }, 1471 | LOAD( 1472 | '1' .. NL 1473 | .. 'N' .. NL 1474 | .. '3.141592653589793115997963468544185161590576171875' .. NL 1475 | ) 1476 | ) 1477 | 1478 | ensure_returns( 1479 | "-number pi " .. NAME, 1480 | 2, { true, -3.141592653589793115997963468544185161590576171875 }, 1481 | LOAD( 1482 | '1' .. NL 1483 | .. 'N' .. NL 1484 | .. '-3.141592653589793115997963468544185161590576171875' .. NL 1485 | ) 1486 | ) 1487 | 1488 | ensure_returns( 1489 | "inf " .. NAME, 1490 | 2, { true, 1/0 }, 1491 | LOAD( 1492 | '1' .. NL 1493 | .. 'N' .. NL 1494 | .. 'inf' .. NL 1495 | ) 1496 | ) 1497 | 1498 | ensure_returns( 1499 | "-inf " .. NAME, 1500 | 2, { true, -1/0 }, 1501 | LOAD( 1502 | '1' .. NL 1503 | .. 'N' .. NL 1504 | .. '-inf' .. NL 1505 | ) 1506 | ) 1507 | 1508 | do 1509 | local ok, value = LOAD( 1510 | '1' .. NL 1511 | .. 'N' .. NL 1512 | .. 'nan' .. NL 1513 | ) 1514 | ensure_equals("nan ok", ok, true) 1515 | ensure("nan value", value ~= value) 1516 | end 1517 | 1518 | ensure_error_with_substring( 1519 | "number: garbage " .. NAME, 1520 | "load failed: ", 1521 | LOAD( 1522 | '1' .. NL 1523 | .. 'N' .. NL 1524 | .. '1.1 yada yada!' .. NL 1525 | ) 1526 | ) 1527 | 1528 | ensure_error_with_substring( 1529 | "number: missing newline " .. NAME, 1530 | "load failed: ", 1531 | LOAD( 1532 | '1' .. NL 1533 | .. 'N' .. NL 1534 | .. '1.1' 1535 | ) 1536 | ) 1537 | 1538 | ensure_error_with_substring( 1539 | "number: missing newline and garbage " .. NAME, 1540 | "load failed: ", 1541 | LOAD( 1542 | '1' .. NL 1543 | .. 'N' .. NL 1544 | .. '1.1 yada yada' 1545 | ) 1546 | ) 1547 | 1548 | print("===== END number tests", NAME, "=====") 1549 | print("===== BEGIN string tests", NAME, "=====") 1550 | 1551 | ensure_returns( 1552 | "empty string " .. NAME, 1553 | 2, { true, "" }, 1554 | LOAD( 1555 | '1' .. NL 1556 | .. 'S' .. NL 1557 | .. '0' .. NL 1558 | .. NL 1559 | ) 1560 | ) 1561 | 1562 | ensure_error_with_substring( 1563 | "empty string with data " .. NAME, 1564 | "load failed: ", 1565 | LOAD( 1566 | '1' .. NL 1567 | .. 'S' .. NL 1568 | .. '0' .. NL 1569 | .. 'A' .. NL 1570 | ) 1571 | ) 1572 | 1573 | ensure_returns( 1574 | "single char string " .. NAME, 1575 | 2, { true, "A" }, 1576 | LOAD( 1577 | '1' .. NL 1578 | .. 'S' .. NL 1579 | .. '1' .. NL 1580 | .. 'A' .. NL 1581 | ) 1582 | ) 1583 | 1584 | ensure_returns( 1585 | "\\0 " .. NAME, 1586 | 2, { true, "\0" }, 1587 | LOAD( 1588 | '1' .. NL 1589 | .. 'S' .. NL 1590 | .. '1' .. NL 1591 | .. '\0' .. NL 1592 | ) 1593 | ) 1594 | 1595 | ensure_returns( 1596 | "Embedded\\0Zero " .. NAME, 1597 | 2, { true, "Embedded\0Zero" }, 1598 | LOAD( 1599 | '1' .. NL 1600 | .. 'S' .. NL 1601 | .. '13' .. NL 1602 | .. 'Embedded\0Zero' .. NL 1603 | ) 1604 | ) 1605 | 1606 | ensure_error_with_substring( 1607 | "empty string no second nl " .. NAME, 1608 | "load failed: ", 1609 | LOAD( 1610 | '1' .. NL 1611 | .. 'S' .. NL 1612 | .. '0' .. NL 1613 | ) 1614 | ) 1615 | 1616 | ensure_error_with_substring( 1617 | "string size too large (empty, no nl) " .. NAME, 1618 | "load failed: ", 1619 | LOAD( 1620 | '1' .. NL 1621 | .. 'S' .. NL 1622 | .. '1' .. NL 1623 | ) 1624 | ) 1625 | 1626 | ensure_error_with_substring( 1627 | "string size too large (empty, nl) " .. NAME, 1628 | "load failed: ", 1629 | LOAD( 1630 | '1' .. NL 1631 | .. 'S' .. NL 1632 | .. (NL == "\r\n" and '2' or '1') .. NL 1633 | .. NL 1634 | ) 1635 | ) 1636 | 1637 | ensure_error_with_substring( 1638 | "string size too large (non-empty) " .. NAME, 1639 | "load failed: ", 1640 | LOAD( 1641 | '1' .. NL 1642 | .. 'S' .. NL 1643 | .. (NL == "\r\n" and '3' or '2') .. NL 1644 | .. 'A' .. NL 1645 | ) 1646 | ) 1647 | 1648 | do 1649 | local len = 1 * 1024 * 1024 -- 1 MB 1650 | 1651 | local s = (function() 1652 | local b = { } 1653 | for i = 1, len do 1654 | b[#b + 1] = string.char(math.random(0, 255)) 1655 | end 1656 | return table.concat(b) 1657 | end)() 1658 | 1659 | ensure_returns( 1660 | "Large binary garbage " .. NAME, 1661 | 2, { true, s }, 1662 | LOAD( 1663 | '1' .. NL 1664 | .. 'S' .. NL 1665 | .. len .. NL 1666 | .. s .. NL 1667 | ) 1668 | ) 1669 | end 1670 | 1671 | print("===== END string tests", NAME, "=====") 1672 | 1673 | print("===== BEGIN utf8 tests", NAME, "=====") 1674 | 1675 | ensure_returns( 1676 | "empty utf8 " .. NAME, 1677 | 2, { true, "" }, 1678 | LOAD( 1679 | '1' .. NL 1680 | .. '8' .. NL 1681 | .. '0' .. NL 1682 | .. NL 1683 | ) 1684 | ) 1685 | 1686 | ensure_error_with_substring( 1687 | "empty utf8 with data " .. NAME, 1688 | "load failed: ", 1689 | LOAD( 1690 | '1' .. NL 1691 | .. '8' .. NL 1692 | .. '0' .. NL 1693 | .. 'A' .. NL 1694 | ) 1695 | ) 1696 | 1697 | ensure_returns( 1698 | "single char utf8 " .. NAME, 1699 | 2, { true, "A" }, 1700 | LOAD( 1701 | '1' .. NL 1702 | .. '8' .. NL 1703 | .. '1' .. NL 1704 | .. 'A' .. NL 1705 | ) 1706 | ) 1707 | 1708 | ensure_returns( 1709 | "\\0 utf8 " .. NAME, 1710 | 2, { true, "\0" }, 1711 | LOAD( 1712 | '1' .. NL 1713 | .. '8' .. NL 1714 | .. '1' .. NL 1715 | .. '\0' .. NL 1716 | ) 1717 | ) 1718 | 1719 | ensure_returns( 1720 | "Embedded\\0Zero utf8 " .. NAME, 1721 | 2, { true, "Embedded\0Zero" }, 1722 | LOAD( 1723 | '1' .. NL 1724 | .. '8' .. NL 1725 | .. '13' .. NL 1726 | .. 'Embedded\0Zero' .. NL 1727 | ) 1728 | ) 1729 | ensure_returns( 1730 | "Встроенный\\0Ноль utf8 " .. NAME, 1731 | 2, { true, "Встроенный\0Ноль" }, 1732 | LOAD( 1733 | '1' .. NL 1734 | .. '8' .. NL 1735 | .. '15' .. NL 1736 | .. 'Встроенный\0Ноль' .. NL 1737 | ) 1738 | ) 1739 | 1740 | ensure_error_with_substring( 1741 | "empty utf8 no second nl " .. NAME, 1742 | "load failed: ", 1743 | LOAD( 1744 | '1' .. NL 1745 | .. '8' .. NL 1746 | .. '0' .. NL 1747 | ) 1748 | ) 1749 | 1750 | ensure_error_with_substring( 1751 | "utf8 size too large (empty, no nl) " .. NAME, 1752 | "load failed: ", 1753 | LOAD( 1754 | '1' .. NL 1755 | .. '8' .. NL 1756 | .. '1' .. NL 1757 | ) 1758 | ) 1759 | 1760 | ensure_error_with_substring( 1761 | "utf8 size too large (empty, nl) " .. NAME, 1762 | "load failed: ", 1763 | LOAD( 1764 | '1' .. NL 1765 | .. '8' .. NL 1766 | .. (NL == "\r\n" and '2' or '1') .. NL 1767 | .. NL 1768 | ) 1769 | ) 1770 | 1771 | ensure_error_with_substring( 1772 | "utf8 size too large (non-empty) " .. NAME, 1773 | "load failed: ", 1774 | LOAD( 1775 | '1' .. NL 1776 | .. '8' .. NL 1777 | .. (NL == "\r\n" and '3' or '2') .. NL 1778 | .. 'A' .. NL 1779 | ) 1780 | ) 1781 | 1782 | for i = 1, 1e3 do 1783 | local b = { } 1784 | for i = 1, 1024 do 1785 | b[#b + 1] = "A" 1786 | end 1787 | 1788 | for i = 1, 10 do 1789 | b[math.random(1, #b)] = string.char(math.random(128, 255)) -- bad code 1790 | end 1791 | 1792 | local s = table.concat(b) 1793 | 1794 | -- There is a small probability that above code 1795 | -- will generate correct UTF-8. 1796 | ensure_error_with_substring( 1797 | "bogus utf8 #" .. i .. " " .. NAME, 1798 | "load failed: invalid utf-8 data", -- Important detail 1799 | LOAD( 1800 | '1' .. NL 1801 | .. '8' .. NL 1802 | .. #s .. NL -- Note that size is also wrong 1803 | .. s .. NL 1804 | ) 1805 | ) 1806 | end 1807 | 1808 | ensure_error_with_substring( 1809 | "whole utf-8 test data " .. NAME, 1810 | "load failed: invalid utf-8 data", -- Important detail 1811 | LOAD( 1812 | '1' .. NL 1813 | .. '8' .. NL 1814 | .. #UTF8_TEST_DATA .. NL -- Note that size is also wrong 1815 | .. UTF8_TEST_DATA .. NL 1816 | ) 1817 | ) 1818 | 1819 | -- Lines with bad UTF-8 in the above document. 1820 | local expected_errors = 1821 | { 1822 | -- 1823 | -- Original list of lines with bad UTF-8 sequences 1824 | -- 1825 | 102, 103, 105, 106, 107, 108, 109, 110, 114, 115, 1826 | 116, 117, 124, 125, 130, 135, 140, 145, 153, 154, 1827 | 155, 156, 157, 158, 159, 160, 161, 162, 169, 175, 1828 | 176, 177, 207, 208, 209, 210, 211, 220, 221, 222, 1829 | 223, 224, 232, 233, 234, 235, 236, 247, 248, 249, 1830 | 250, 251, 252, 253, 257, 258, 259, 260, 261, 262, 1831 | 263, 264; 1832 | -- 1833 | -- Additional bad lines 1834 | -- TODO: Add more tests to compensate for these 1835 | -- (as some of this checks are for boundary conditions). 1836 | -- 1837 | 75; -- 5-byte sequence is illegal 1838 | 76; -- 6-byte sequence is illegal 1839 | -- First byte 0xF7 (247) may not occur anywhere in valid UTF-8 byte seq. 1840 | 83; 1841 | 84; -- 5-byte sequence is illegal 1842 | 85; -- 6-byte sequence is illegal 1843 | 93; -- Overlong form 1844 | -- 1845 | -- C-only 1846 | -- 1847 | -- BOM non-character sequence is legitimately rejected by C reader, 1848 | -- Lua reader does not care (should it be fixed to?). 1849 | (LOAD_NAME == "C") and 82 or nil; 1850 | -- TODO: Why do these two pass? 1851 | (LOAD_NAME == "C") and 268 or nil; 1852 | (LOAD_NAME == "C") and 269 or nil; 1853 | } 1854 | 1855 | table.sort(expected_errors) 1856 | 1857 | local lines = split_by_char(UTF8_TEST_DATA, "\n") 1858 | local actual_errors = { } 1859 | for i = 1, #lines do 1860 | local res, err = LOAD( 1861 | '1' .. NL 1862 | .. '8' .. NL 1863 | .. (#lines[i] < 79 and #lines[i] or 79) .. NL 1864 | .. lines[i] .. NL 1865 | ) 1866 | if res then 1867 | ensure_equals("loaded", err, lines[i]) 1868 | else 1869 | ensure_equals( 1870 | "correct error " .. i, err, 1871 | "load failed: invalid utf-8 data" -- Important detail 1872 | ) 1873 | actual_errors[#actual_errors + 1] = i 1874 | end 1875 | end 1876 | ensure_tequals( 1877 | "failure lines must match expected", 1878 | actual_errors, 1879 | expected_errors 1880 | ) 1881 | 1882 | print("===== END utf8 tests", NAME, "=====") 1883 | 1884 | print("===== BEGIN fixed table tests", NAME, "=====") 1885 | 1886 | ensure_returns( 1887 | "empty table " .. NAME, 1888 | 2, { true, { } }, 1889 | LOAD( 1890 | '1' .. NL 1891 | .. 'T' .. NL 1892 | .. '0' .. NL 1893 | .. '0' .. NL 1894 | ) 1895 | ) 1896 | 1897 | ensure_returns( 1898 | "some data " .. NAME, 1899 | 2, 1900 | { 1901 | true, 1902 | { false, 0.36978798469984341945604455759166739881038665771484375 } 1903 | }, 1904 | LOAD( 1905 | '1' .. NL 1906 | .. 'T' .. NL 1907 | .. '2' .. NL 1908 | .. '0' .. NL 1909 | .. '0' .. NL 1910 | .. 'N' .. NL 1911 | .. '0.36978798469984341945604455759166739881038665771484375' .. NL 1912 | ) 1913 | ) 1914 | 1915 | ensure_error_with_substring( 1916 | "table, no sizes, no nl " .. NAME, 1917 | "load failed: ", 1918 | LOAD( 1919 | '1' .. NL 1920 | .. 'T' .. NL 1921 | ) 1922 | ) 1923 | 1924 | ensure_error_with_substring( 1925 | "table, no sizes, one nl " .. NAME, 1926 | "load failed: ", 1927 | LOAD( 1928 | '1' .. NL 1929 | .. 'T' .. NL 1930 | .. NL 1931 | ) 1932 | ) 1933 | 1934 | ensure_error_with_substring( 1935 | "table, no sizes, two nls " .. NAME, 1936 | "load failed: ", 1937 | LOAD( 1938 | '1' .. NL 1939 | .. 'T' .. NL 1940 | .. NL 1941 | .. NL 1942 | ) 1943 | ) 1944 | 1945 | ensure_error_with_substring( 1946 | "table, garbage array size " .. NAME, 1947 | "load failed: ", 1948 | LOAD( 1949 | '1' .. NL 1950 | .. 'T' .. NL 1951 | .. 'a' .. NL 1952 | .. '0' .. NL 1953 | ) 1954 | ) 1955 | 1956 | ensure_error_with_substring( 1957 | "table, garbage hash size " .. NAME, 1958 | "load failed: ", 1959 | LOAD( 1960 | '1' .. NL 1961 | .. 'T' .. NL 1962 | .. '0' .. NL 1963 | .. 'a' .. NL 1964 | ) 1965 | ) 1966 | 1967 | ensure_error_with_substring( 1968 | "table, garbage after sizes " .. NAME, 1969 | "load failed: ", 1970 | LOAD( 1971 | '1' .. NL 1972 | .. 'T' .. NL 1973 | .. '1' .. NL 1974 | .. '0' .. NL 1975 | .. 'yada yada!' .. NL 1976 | ) 1977 | ) 1978 | 1979 | ensure_error_with_substring( 1980 | "table, array size too large " .. NAME, 1981 | "load failed: ", 1982 | LOAD( 1983 | '1' .. NL 1984 | .. 'T' .. NL 1985 | .. '2' .. NL 1986 | .. '0' .. NL 1987 | .. 'N' .. NL 1988 | .. '42' .. NL 1989 | ) 1990 | ) 1991 | 1992 | ensure_error_with_substring( 1993 | "table, hash size too large " .. NAME, 1994 | "load failed: ", 1995 | LOAD( 1996 | '1' .. NL 1997 | .. 'T' .. NL 1998 | .. '0' .. NL 1999 | .. '2' .. NL 2000 | .. 'N' .. NL 2001 | .. '42' .. NL 2002 | .. 'N' .. NL 2003 | .. '42' .. NL 2004 | ) 2005 | ) 2006 | 2007 | ensure_error_with_substring( 2008 | "table, hash missing " .. NAME, 2009 | "load failed: ", 2010 | LOAD( 2011 | '1' .. NL 2012 | .. 'T' .. NL 2013 | .. '1' .. NL 2014 | .. '1' .. NL 2015 | .. 'N' .. NL 2016 | .. '42' .. NL 2017 | ) 2018 | ) 2019 | 2020 | ensure_error_with_substring( 2021 | "table, hash value missing " .. NAME, 2022 | "load failed: ", 2023 | LOAD( 2024 | '1' .. NL 2025 | .. 'T' .. NL 2026 | .. '1' .. NL 2027 | .. '1' .. NL 2028 | .. 'N' .. NL 2029 | .. '42' .. NL 2030 | .. 'N' .. NL 2031 | .. '42' .. NL 2032 | ) 2033 | ) 2034 | 2035 | ensure_error_with_substring( 2036 | "table, huge array size " .. NAME, 2037 | "load failed: ", 2038 | LOAD( 2039 | '1' .. NL 2040 | .. 'T' .. NL 2041 | .. '65234375' .. NL 2042 | .. '0' .. NL 2043 | .. '-' .. NL 2044 | ) 2045 | ) 2046 | 2047 | ensure_error_with_substring( 2048 | "table, huge hash size " .. NAME, 2049 | "load failed: ", 2050 | LOAD( 2051 | '1' .. NL 2052 | .. 'T' .. NL 2053 | .. '0' .. NL 2054 | .. '65234375' .. NL 2055 | .. '1' .. NL 2056 | .. '-' .. NL 2057 | ) 2058 | ) 2059 | 2060 | ensure_error_with_substring( 2061 | "table, huge array and hash size " .. NAME, 2062 | "load failed: ", 2063 | LOAD( 2064 | '1' .. NL 2065 | .. 'T' .. NL 2066 | .. '65234375' .. NL 2067 | .. '65234375' .. NL 2068 | .. '-' .. NL 2069 | ) 2070 | ) 2071 | 2072 | print("===== END fixed table tests", NAME, "=====") 2073 | 2074 | print("===== BEGIN stream table tests", NAME, "=====") 2075 | 2076 | ensure_returns( 2077 | "empty table " .. NAME, 2078 | 2, { true, { } }, 2079 | LOAD( 2080 | '1' .. NL 2081 | .. 't' .. NL 2082 | .. '-' .. NL 2083 | ) 2084 | ) 2085 | 2086 | ensure_returns( 2087 | "nested tables " .. NAME, 2088 | 2, { true, { [ { 42 } ] = { 24 } } }, 2089 | LOAD( 2090 | '1' .. NL 2091 | .. 't' .. NL 2092 | .. 't' .. NL 2093 | .. 'N' .. NL 2094 | .. '1' .. NL 2095 | .. 'N' .. NL 2096 | .. '42' .. NL 2097 | .. '-' .. NL 2098 | .. 't' .. NL 2099 | .. 'N' .. NL 2100 | .. '1' .. NL 2101 | .. 'N' .. NL 2102 | .. '24' .. NL 2103 | .. '-' .. NL 2104 | .. '-' .. NL 2105 | ) 2106 | ) 2107 | 2108 | ensure_returns( 2109 | "some data " .. NAME, 2110 | 2, 2111 | { 2112 | true, 2113 | { false, 0.36978798469984341945604455759166739881038665771484375 } 2114 | }, 2115 | LOAD( 2116 | '1' .. NL 2117 | .. 't' .. NL 2118 | .. 'N' .. NL 2119 | .. '1' .. NL 2120 | .. '0' .. NL 2121 | .. 'N' .. NL 2122 | .. '2' .. NL 2123 | .. 'N' .. NL 2124 | .. '0.36978798469984341945604455759166739881038665771484375' .. NL 2125 | .. '-' .. NL 2126 | ) 2127 | ) 2128 | 2129 | ensure_error_with_substring( 2130 | "table, no nil " .. NAME, 2131 | "load failed: ", 2132 | LOAD( 2133 | '1' .. NL 2134 | .. 't' .. NL 2135 | ) 2136 | ) 2137 | 2138 | ensure_error_with_substring( 2139 | "table, nil, no nl " .. NAME, 2140 | "load failed: ", 2141 | LOAD( 2142 | '1' .. NL 2143 | .. 't' .. NL 2144 | .. '-' 2145 | ) 2146 | ) 2147 | 2148 | ensure_error_with_substring( 2149 | "table, hash value missing " .. NAME, 2150 | "load failed: ", 2151 | LOAD( 2152 | '1' .. NL 2153 | .. 't' .. NL 2154 | .. 'N' .. NL 2155 | .. '42' .. NL 2156 | ) 2157 | ) 2158 | 2159 | print("===== END stream table tests", NAME, "=====") 2160 | 2161 | print("===== BEGIN generative tests", NAME, "=====") 2162 | 2163 | do 2164 | local constructors = { } 2165 | 2166 | local construct = function(nesting) 2167 | return constructors[math.random(1, #constructors)](nesting) 2168 | end 2169 | 2170 | constructors[#constructors + 1] = function() 2171 | return nil 2172 | end 2173 | 2174 | constructors[#constructors + 1] = function() 2175 | return false 2176 | end 2177 | 2178 | constructors[#constructors + 1] = function() 2179 | return true 2180 | end 2181 | 2182 | constructors[#constructors + 1] = function() 2183 | return 0 2184 | end 2185 | 2186 | constructors[#constructors + 1] = function() 2187 | return 42 2188 | end 2189 | 2190 | constructors[#constructors + 1] = function() 2191 | return 3.14 2192 | end 2193 | 2194 | constructors[#constructors + 1] = function() 2195 | return 1/0 2196 | end 2197 | 2198 | constructors[#constructors + 1] = function() 2199 | return math.random() 2200 | end 2201 | 2202 | constructors[#constructors + 1] = function() 2203 | return math.random(-1000, 1000) 2204 | end 2205 | 2206 | constructors[#constructors + 1] = function() 2207 | return "" 2208 | end 2209 | 2210 | constructors[#constructors + 1] = function() 2211 | return "luatexts" 2212 | end 2213 | 2214 | constructors[#constructors + 1] = function() 2215 | return { } 2216 | end 2217 | 2218 | constructors[#constructors + 1] = function(nesting) 2219 | nesting = (nesting or 0) + 1 2220 | 2221 | if nesting > 10 then 2222 | return { } 2223 | end 2224 | 2225 | local r = { } 2226 | 2227 | for i = 1, math.random(0, 10) do 2228 | r[i] = construct(nesting) 2229 | end 2230 | 2231 | for i = 1, math.random(0, 10) do 2232 | local k = construct(nesting) 2233 | if k == nil then 2234 | k = "(nil)" 2235 | end 2236 | 2237 | r[k] = construct(nesting) 2238 | end 2239 | 2240 | return r 2241 | end 2242 | 2243 | local mutators = { } 2244 | 2245 | local mutate = function(str, nesting) 2246 | return mutators[math.random(1, #mutators)](str, nesting) 2247 | end 2248 | 2249 | -- truncate at end 2250 | mutators[#mutators + 1] = function(str) 2251 | local pos = math.random(1, #str) 2252 | return str:sub(1, pos) 2253 | end 2254 | 2255 | -- truncate at beginning 2256 | mutators[#mutators + 1] = function(str) 2257 | local pos = math.random(1, #str) 2258 | return str:sub(-pos) 2259 | end 2260 | 2261 | -- cut out the middle 2262 | mutators[#mutators + 1] = function(str) 2263 | local from = math.random(1, #str) 2264 | local to = math.random(from, #str) 2265 | return str:sub(1, from) .. str:sub(to) 2266 | end 2267 | 2268 | -- swap two halves 2269 | mutators[#mutators + 1] = function(str) 2270 | local pos = math.random(1, #str) 2271 | return str:sub(pos + 1, #str) .. str:sub(1, pos) 2272 | end 2273 | 2274 | -- swap two characters 2275 | mutators[#mutators + 1] = function(str) 2276 | local pa, pb = math.random(1, #str), math.random(1, #str) 2277 | local a, b = str:sub(pa, pa), str:sub(pb, pb) 2278 | return 2279 | str:sub(1, pa - 1) .. 2280 | a .. 2281 | str:sub(pa + 1, pb - 1) .. 2282 | b .. 2283 | str:sub(pb + 1, #str) 2284 | end 2285 | 2286 | -- replace one character 2287 | mutators[#mutators + 1] = function(str) 2288 | local pos = math.random(1, #str) 2289 | return 2290 | str:sub(1, pos - 1) .. 2291 | string.char(math.random(0, 255)) .. 2292 | str:sub(pos + 1, #str) 2293 | end 2294 | 2295 | -- increment one character 2296 | mutators[#mutators + 1] = function(str) 2297 | local pos = math.random(1, #str) 2298 | local b = str:byte(pos, pos) + 1 2299 | if b > 255 then 2300 | b = 0 2301 | end 2302 | return 2303 | str:sub(1, pos - 1) .. 2304 | string.char(b) .. 2305 | str:sub(pos + 1, #str) 2306 | end 2307 | 2308 | -- decrement one character 2309 | mutators[#mutators + 1] = function(str) 2310 | local pos = math.random(1, #str) 2311 | local b = str:byte(pos, pos) - 1 2312 | if b < 0 then 2313 | b = 255 2314 | end 2315 | return 2316 | str:sub(1, pos - 1) .. 2317 | string.char(b) .. 2318 | str:sub(pos + 1, #str) 2319 | end 2320 | 2321 | local mutated_ok = 0 2322 | local mutated_fail = 0 2323 | 2324 | local C = 1 2325 | assert(os.execute("rm tmp/*")) 2326 | 2327 | local num_steps = 1e4 2328 | for i = 1, num_steps do 2329 | if i % 500 == 0 --[[or (i >= 8732 and NL == "\n")--]] then 2330 | print("step", i, "of", num_steps) 2331 | end 2332 | 2333 | local n = math.random(0, 10) 2334 | local tuple = { } 2335 | for i = 1, n do 2336 | tuple[i] = construct() 2337 | end 2338 | 2339 | local data = ensure("save", luatexts_lua.save(unpack(tuple, 1, n))) 2340 | 2341 | local N = ("%08d"):format(C) 2342 | local f = assert(io.open("tmp/".. N .. ".lua", "w")) 2343 | f:write( 2344 | tserialize(tuple), ",", n 2345 | ) 2346 | f:close() 2347 | local f = assert(io.open("tmp/".. N .. ".luatexts", "w")) 2348 | f:write(data) 2349 | f:close() 2350 | C = C + 1 2351 | 2352 | --[[ 2353 | print("dataset #" .. i .. ", " .. #data .. " bytes") 2354 | local c = 0 2355 | print("tuple: ", tpretty(tuple, ' ', 80)) 2356 | print("data:", data) 2357 | print( 2358 | "0000 : " .. data:gsub( 2359 | "\n", function() 2360 | c = c + 1 2361 | return (" : CRLF\n%04d : "):format(c) 2362 | end 2363 | ) 2364 | ) 2365 | --]] 2366 | 2367 | -- TODO: This does not cover utf-8. It should! 2368 | ensure_returns( 2369 | "load", 2370 | n + 1, { true, unpack(tuple, 1, n) }, 2371 | LOAD(data) 2372 | ) 2373 | 2374 | -- Now trying to mutate 2375 | -- (ignoring results, the point is not to crash) 2376 | local num_steps = 100 2377 | for j = 1, num_steps do 2378 | --[[ 2379 | local dump = false 2380 | if i >= 8732 and j >= 12 and NL == "\n" then 2381 | print("mutation", i..":"..j, "of", num_steps) 2382 | dump = true 2383 | end 2384 | --]] 2385 | data = mutate(data) 2386 | --[[ 2387 | if dump then 2388 | print("MUTATED", data) 2389 | print("GC size:", collectgarbage("count")) 2390 | end 2391 | --]] 2392 | local res = LOAD(data) 2393 | if res then 2394 | mutated_ok = mutated_ok + 1 2395 | else 2396 | mutated_fail = mutated_fail + 1 2397 | end 2398 | 2399 | collectgarbage("step") 2400 | end 2401 | end 2402 | 2403 | print("mutated ok:", mutated_ok) 2404 | print("mutated fail:", mutated_fail) 2405 | end 2406 | 2407 | print("===== END generative tests", NAME, "=====") 2408 | end 2409 | end 2410 | 2411 | local NAME = "" 2412 | 2413 | print("===== BEGIN file tests", NAME, "=====") 2414 | 2415 | ensure_error_with_substring( 2416 | "/dev/null " .. NAME, 2417 | "load_from_file failed: '/dev/null' is not a file", 2418 | luatexts.load_from_file("/dev/null") 2419 | ) 2420 | 2421 | ensure_error_with_substring( 2422 | "missing file " .. NAME, 2423 | "load_from_file failed:" 2424 | .. " can't open './test/data/no-such-file.luatexts' for reading:" 2425 | .. " No such file or directory", 2426 | luatexts.load_from_file("./test/data/no-such-file.luatexts") 2427 | ) 2428 | 2429 | ensure_error_with_substring( 2430 | "directory " .. NAME, 2431 | "load_from_file failed: './test/data/' is not a file", 2432 | luatexts.load_from_file("./test/data/") 2433 | ) 2434 | 2435 | ensure_error_with_substring( 2436 | "empty " .. NAME, 2437 | "load_from_file failed: './test/data/empty.luatexts' is empty", 2438 | luatexts.load_from_file("./test/data/empty.luatexts") 2439 | ) 2440 | 2441 | ensure_error_with_substring( 2442 | "random garbage " .. NAME, 2443 | "load failed: ", 2444 | luatexts.load_from_file("./test/data/garbage.luatexts") 2445 | ) 2446 | 2447 | ensure_error_with_substring( 2448 | "truncated-1 " .. NAME, 2449 | "load failed: ", 2450 | luatexts.load_from_file("./test/data/truncated.luatexts") 2451 | ) 2452 | 2453 | ensure_error_with_substring( 2454 | "truncated-2 " .. NAME, 2455 | "load failed: ", 2456 | luatexts.load_from_file("./test/data/truncated2.luatexts") 2457 | ) 2458 | 2459 | ensure_error_with_substring( 2460 | "noeol " .. NAME, 2461 | "load failed: ", 2462 | luatexts.load_from_file("./test/data/noeol.luatexts") 2463 | ) 2464 | 2465 | ensure_returns( 2466 | "good " .. NAME, 2467 | 2, { true, 42 }, 2468 | luatexts.load_from_file("./test/data/good.luatexts") 2469 | ) 2470 | 2471 | print("===== END file tests", NAME, "=====") 2472 | 2473 | print("OK") 2474 | -------------------------------------------------------------------------------- /test/test.min.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | luatexts.js ad-hoc tests (minified) 4 | 5 | 6 | 7 | 8 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /test/test.php: -------------------------------------------------------------------------------- 1 | array(), 11 | "array" => array( 12 | 0.5, 1, 'null', null, 'undefined', true, false, array() 13 | ), 14 | "utf" => "ЭЭХ! Naïve?" 15 | ); 16 | print_r($a); 17 | $required = array("1", 18 | "T", 19 | "0", 20 | "3", 21 | "8", 22 | "3", 23 | "obj", 24 | "T", 25 | "0", 26 | "0", 27 | "8", 28 | "5", 29 | "array", 30 | "T", 31 | "3", // null counts as a hole. 32 | "5", 33 | "N", 34 | "0.5", 35 | "N", 36 | "1", 37 | "8", 38 | "4", 39 | "null", 40 | "N", 41 | "4", 42 | "-", 43 | "N", 44 | "5", 45 | "8", 46 | "9", 47 | "undefined", 48 | "N", 49 | "6", 50 | "1", 51 | "N", 52 | "7", 53 | "0", 54 | "N", 55 | "8", 56 | "T", 57 | "0", 58 | "0", 59 | "8", 60 | "3", 61 | "utf", 62 | "8", 63 | "11", 64 | "ЭЭХ! Naïve?"); 65 | $required = implode("\n", $required)."\n"; 66 | $lt_result = Luatexts::save($a); 67 | echo "RESULT: " . ($required == $lt_result ? "OK\n" : "ERROR\n"); 68 | 69 | if ($required != $lt_result){ 70 | $required = explode("\n", $required); 71 | $lt_result = explode("\n", $lt_result); 72 | 73 | $count = max(count($required), count($lt_result)); 74 | for($i=0;$i<$count;$i++){ 75 | echo @$required[$i]."\t".@$lt_result[$i].(@$required[$i] != @$lt_result[$i] ? "\t<< ERROR\n" : "\n"); 76 | } 77 | } 78 | 79 | print("\n\n"); 80 | print("Serialize many arguments: 123, 'test string', array(1, 'test' => 123)\n"); 81 | $lt_result = Luatexts::save(123, 'test string', array(1, 'test' => 123)); 82 | $required = array("3", 83 | "N", 84 | "123", 85 | "8", 86 | "11", 87 | "test string", 88 | "T", 89 | "1", 90 | "1", 91 | "N", 92 | "1", 93 | "8", 94 | "4", 95 | "test", 96 | "N", 97 | "123"); 98 | $required = implode("\n", $required)."\n"; 99 | echo "RESULT: " . ($required == $lt_result ? "OK\n" : "ERROR\n"); 100 | 101 | if ($required != $lt_result){ 102 | $required = explode("\n", $required); 103 | $lt_result = explode("\n", $lt_result); 104 | 105 | $count = max(count($required), count($lt_result)); 106 | for($i=0;$i<$count;$i++){ 107 | echo @$required[$i]."\t".@$lt_result[$i].(@$required[$i] != @$lt_result[$i] ? "\t<< ERROR\n" : "\n"); 108 | } 109 | } 110 | 111 | print("\n\n"); 112 | $a = new Test; 113 | print_r($a); 114 | $caught = false; 115 | try { 116 | $lt_result = Luatexts::save($a); 117 | } catch (Exception $e) { 118 | $caught = true; 119 | echo "EXCEPTION caught as expected\n"; 120 | } 121 | 122 | if (!$caught) { 123 | echo "ERROR: No exception on object serialization"; 124 | } 125 | } catch (Exception $e) { 126 | echo "\nEXCEPTION: ".$e->getMessage()."\n"; 127 | } 128 | ?> 129 | -------------------------------------------------------------------------------- /tmp/.keepme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agladysh/luatexts/2ca61795384aa9a9685776527515266894d3471b/tmp/.keepme --------------------------------------------------------------------------------