lua_cjson.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. /* CJSON - JSON support for Lua
  2. *
  3. * Copyright (c) 2010-2011 Mark Pulford <[email protected]>
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining
  6. * a copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sublicense, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be
  14. * included in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. /* Caveats:
  25. * - JSON "null" values are represented as lightuserdata since Lua
  26. * tables cannot contain "nil". Compare with cjson.null.
  27. * - Invalid UTF-8 characters are not detected and will be passed
  28. * untouched. If required, UTF-8 error checking should be done
  29. * outside this library.
  30. * - Javascript comments are not part of the JSON spec, and are not
  31. * currently supported.
  32. *
  33. * Note: Decoding is slower than encoding. Lua spends significant
  34. * time (30%) managing tables when parsing JSON since it is
  35. * difficult to know object/array sizes ahead of time.
  36. */
  37. #include <assert.h>
  38. #include <string.h>
  39. #include <math.h>
  40. #include <lua.h>
  41. #include <lauxlib.h>
  42. #include "strbuf.h"
  43. #define DEFAULT_SPARSE_CONVERT 0
  44. #define DEFAULT_SPARSE_RATIO 2
  45. #define DEFAULT_SPARSE_SAFE 10
  46. #define DEFAULT_MAX_DEPTH 20
  47. #define DEFAULT_ENCODE_REFUSE_BADNUM 1
  48. #define DEFAULT_DECODE_REFUSE_BADNUM 0
  49. #define DEFAULT_ENCODE_KEEP_BUFFER 1
  50. typedef enum {
  51. T_OBJ_BEGIN,
  52. T_OBJ_END,
  53. T_ARR_BEGIN,
  54. T_ARR_END,
  55. T_STRING,
  56. T_NUMBER,
  57. T_BOOLEAN,
  58. T_NULL,
  59. T_COLON,
  60. T_COMMA,
  61. T_END,
  62. T_WHITESPACE,
  63. T_ERROR,
  64. T_UNKNOWN
  65. } json_token_type_t;
  66. static const char *json_token_type_name[] = {
  67. "T_OBJ_BEGIN",
  68. "T_OBJ_END",
  69. "T_ARR_BEGIN",
  70. "T_ARR_END",
  71. "T_STRING",
  72. "T_NUMBER",
  73. "T_BOOLEAN",
  74. "T_NULL",
  75. "T_COLON",
  76. "T_COMMA",
  77. "T_END",
  78. "T_WHITESPACE",
  79. "T_ERROR",
  80. "T_UNKNOWN",
  81. NULL
  82. };
  83. typedef struct {
  84. json_token_type_t ch2token[256];
  85. char escape2char[256]; /* Decoding */
  86. #if 0
  87. char escapes[35][8]; /* Pre-generated escape string buffer */
  88. char *char2escape[256]; /* Encoding */
  89. #endif
  90. strbuf_t encode_buf;
  91. char number_fmt[8]; /* "%.XXg\0" */
  92. int current_depth;
  93. int encode_sparse_convert;
  94. int encode_sparse_ratio;
  95. int encode_sparse_safe;
  96. int encode_max_depth;
  97. int encode_refuse_badnum;
  98. int decode_refuse_badnum;
  99. int encode_keep_buffer;
  100. int encode_number_precision;
  101. } json_config_t;
  102. typedef struct {
  103. const char *data;
  104. int index;
  105. strbuf_t *tmp; /* Temporary storage for strings */
  106. json_config_t *cfg;
  107. } json_parse_t;
  108. typedef struct {
  109. json_token_type_t type;
  110. int index;
  111. union {
  112. const char *string;
  113. double number;
  114. int boolean;
  115. } value;
  116. int string_len;
  117. } json_token_t;
  118. static const char *char2escape[256] = {
  119. "\\u0000", "\\u0001", "\\u0002", "\\u0003",
  120. "\\u0004", "\\u0005", "\\u0006", "\\u0007",
  121. "\\b", "\\t", "\\n", "\\u000b",
  122. "\\f", "\\r", "\\u000e", "\\u000f",
  123. "\\u0010", "\\u0011", "\\u0012", "\\u0013",
  124. "\\u0014", "\\u0015", "\\u0016", "\\u0017",
  125. "\\u0018", "\\u0019", "\\u001a", "\\u001b",
  126. "\\u001c", "\\u001d", "\\u001e", "\\u001f",
  127. NULL, NULL, "\\\"", NULL, NULL, NULL, NULL, NULL,
  128. NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\/",
  129. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  130. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  131. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  132. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  133. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  134. NULL, NULL, NULL, NULL, "\\\\", NULL, NULL, NULL,
  135. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  136. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  137. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  138. NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\u007f",
  139. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  140. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  141. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  142. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  143. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  144. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  145. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  146. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  147. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  148. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  149. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  150. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  151. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  152. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  153. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  154. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  155. };
  156. static int json_config_key;
  157. /* ===== CONFIGURATION ===== */
  158. static json_config_t *json_fetch_config(lua_State *l)
  159. {
  160. json_config_t *cfg;
  161. lua_pushlightuserdata(l, &json_config_key);
  162. lua_gettable(l, LUA_REGISTRYINDEX);
  163. cfg = lua_touserdata(l, -1);
  164. if (!cfg)
  165. luaL_error(l, "BUG: Unable to fetch CJSON configuration");
  166. lua_pop(l, 1);
  167. return cfg;
  168. }
  169. static void json_verify_arg_count(lua_State *l, int args)
  170. {
  171. luaL_argcheck(l, lua_gettop(l) <= args, args + 1,
  172. "found too many arguments");
  173. }
  174. /* Configures handling of extremely sparse arrays:
  175. * convert: Convert extremely sparse arrays into objects? Otherwise error.
  176. * ratio: 0: always allow sparse; 1: never allow sparse; >1: use ratio
  177. * safe: Always use an array when the max index <= safe */
  178. static int json_cfg_encode_sparse_array(lua_State *l)
  179. {
  180. json_config_t *cfg;
  181. int val;
  182. json_verify_arg_count(l, 3);
  183. cfg = json_fetch_config(l);
  184. switch (lua_gettop(l)) {
  185. case 3:
  186. val = luaL_checkinteger(l, 3);
  187. luaL_argcheck(l, val >= 0, 3, "expected integer >= 0");
  188. cfg->encode_sparse_safe = val;
  189. case 2:
  190. val = luaL_checkinteger(l, 2);
  191. luaL_argcheck(l, val >= 0, 2, "expected integer >= 0");
  192. cfg->encode_sparse_ratio = val;
  193. case 1:
  194. luaL_argcheck(l, lua_isboolean(l, 1), 1, "expected boolean");
  195. cfg->encode_sparse_convert = lua_toboolean(l, 1);
  196. }
  197. lua_pushboolean(l, cfg->encode_sparse_convert);
  198. lua_pushinteger(l, cfg->encode_sparse_ratio);
  199. lua_pushinteger(l, cfg->encode_sparse_safe);
  200. return 3;
  201. }
  202. /* Configures the maximum number of nested arrays/objects allowed when
  203. * encoding */
  204. static int json_cfg_encode_max_depth(lua_State *l)
  205. {
  206. json_config_t *cfg;
  207. int depth;
  208. json_verify_arg_count(l, 1);
  209. cfg = json_fetch_config(l);
  210. if (lua_gettop(l)) {
  211. depth = luaL_checkinteger(l, 1);
  212. luaL_argcheck(l, depth > 0, 1, "expected positive integer");
  213. cfg->encode_max_depth = depth;
  214. }
  215. lua_pushinteger(l, cfg->encode_max_depth);
  216. return 1;
  217. }
  218. static void json_set_number_precision(json_config_t *cfg, int prec)
  219. {
  220. cfg->encode_number_precision = prec;
  221. sprintf(cfg->number_fmt, "%%.%dg", prec);
  222. }
  223. /* Configures number precision when converting doubles to text */
  224. static int json_cfg_encode_number_precision(lua_State *l)
  225. {
  226. json_config_t *cfg;
  227. int precision;
  228. json_verify_arg_count(l, 1);
  229. cfg = json_fetch_config(l);
  230. if (lua_gettop(l)) {
  231. precision = luaL_checkinteger(l, 1);
  232. luaL_argcheck(l, 1 <= precision && precision <= 14, 1,
  233. "expected integer between 1 and 14");
  234. json_set_number_precision(cfg, precision);
  235. }
  236. lua_pushinteger(l, cfg->encode_number_precision);
  237. return 1;
  238. }
  239. /* Configures JSON encoding buffer persistence */
  240. static int json_cfg_encode_keep_buffer(lua_State *l)
  241. {
  242. json_config_t *cfg;
  243. json_verify_arg_count(l, 1);
  244. cfg = json_fetch_config(l);
  245. if (lua_gettop(l)) {
  246. luaL_checktype(l, 1, LUA_TBOOLEAN);
  247. cfg->encode_keep_buffer = lua_toboolean(l, 1);
  248. }
  249. lua_pushboolean(l, cfg->encode_keep_buffer);
  250. return 1;
  251. }
  252. /* On argument: decode enum and set config variables
  253. * **options must point to a NULL terminated array of 4 enums
  254. * Returns: current enum value */
  255. static void json_enum_option(lua_State *l, const char **options,
  256. int *opt1, int *opt2)
  257. {
  258. int setting;
  259. if (lua_gettop(l)) {
  260. if (lua_isboolean(l, 1))
  261. setting = lua_toboolean(l, 1) * 3;
  262. else
  263. setting = luaL_checkoption(l, 1, NULL, options);
  264. *opt1 = setting & 1 ? 1 : 0;
  265. *opt2 = setting & 2 ? 1 : 0;
  266. } else {
  267. setting = *opt1 | (*opt2 << 1);
  268. }
  269. if (setting)
  270. lua_pushstring(l, options[setting]);
  271. else
  272. lua_pushboolean(l, 0);
  273. }
  274. /* When enabled, rejects: NaN, Infinity, hexidecimal numbers */
  275. static int json_cfg_refuse_invalid_numbers(lua_State *l)
  276. {
  277. static const char *options_enc_dec[] = { "none", "encode", "decode",
  278. "both", NULL };
  279. json_config_t *cfg;
  280. json_verify_arg_count(l, 1);
  281. cfg = json_fetch_config(l);
  282. json_enum_option(l, options_enc_dec,
  283. &cfg->encode_refuse_badnum,
  284. &cfg->decode_refuse_badnum);
  285. return 1;
  286. }
  287. static int json_destroy_config(lua_State *l)
  288. {
  289. json_config_t *cfg;
  290. cfg = lua_touserdata(l, 1);
  291. if (cfg)
  292. strbuf_free(&cfg->encode_buf);
  293. cfg = NULL;
  294. return 0;
  295. }
  296. static void json_create_config(lua_State *l)
  297. {
  298. json_config_t *cfg;
  299. int i;
  300. cfg = lua_newuserdata(l, sizeof(*cfg));
  301. /* Create GC method to clean up strbuf */
  302. lua_newtable(l);
  303. lua_pushcfunction(l, json_destroy_config);
  304. lua_setfield(l, -2, "__gc");
  305. lua_setmetatable(l, -2);
  306. strbuf_init(&cfg->encode_buf, 0);
  307. cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT;
  308. cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO;
  309. cfg->encode_sparse_safe = DEFAULT_SPARSE_SAFE;
  310. cfg->encode_max_depth = DEFAULT_MAX_DEPTH;
  311. cfg->encode_refuse_badnum = DEFAULT_ENCODE_REFUSE_BADNUM;
  312. cfg->decode_refuse_badnum = DEFAULT_DECODE_REFUSE_BADNUM;
  313. cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER;
  314. json_set_number_precision(cfg, 14);
  315. /* Decoding init */
  316. /* Tag all characters as an error */
  317. for (i = 0; i < 256; i++)
  318. cfg->ch2token[i] = T_ERROR;
  319. /* Set tokens that require no further processing */
  320. cfg->ch2token['{'] = T_OBJ_BEGIN;
  321. cfg->ch2token['}'] = T_OBJ_END;
  322. cfg->ch2token['['] = T_ARR_BEGIN;
  323. cfg->ch2token[']'] = T_ARR_END;
  324. cfg->ch2token[','] = T_COMMA;
  325. cfg->ch2token[':'] = T_COLON;
  326. cfg->ch2token['\0'] = T_END;
  327. cfg->ch2token[' '] = T_WHITESPACE;
  328. cfg->ch2token['\t'] = T_WHITESPACE;
  329. cfg->ch2token['\n'] = T_WHITESPACE;
  330. cfg->ch2token['\r'] = T_WHITESPACE;
  331. /* Update characters that require further processing */
  332. cfg->ch2token['f'] = T_UNKNOWN; /* false? */
  333. cfg->ch2token['i'] = T_UNKNOWN; /* inf, ininity? */
  334. cfg->ch2token['I'] = T_UNKNOWN;
  335. cfg->ch2token['n'] = T_UNKNOWN; /* null, nan? */
  336. cfg->ch2token['N'] = T_UNKNOWN;
  337. cfg->ch2token['t'] = T_UNKNOWN; /* true? */
  338. cfg->ch2token['"'] = T_UNKNOWN; /* string? */
  339. cfg->ch2token['+'] = T_UNKNOWN; /* number? */
  340. cfg->ch2token['-'] = T_UNKNOWN;
  341. for (i = 0; i < 10; i++)
  342. cfg->ch2token['0' + i] = T_UNKNOWN;
  343. /* Lookup table for parsing escape characters */
  344. for (i = 0; i < 256; i++)
  345. cfg->escape2char[i] = 0; /* String error */
  346. cfg->escape2char['"'] = '"';
  347. cfg->escape2char['\\'] = '\\';
  348. cfg->escape2char['/'] = '/';
  349. cfg->escape2char['b'] = '\b';
  350. cfg->escape2char['t'] = '\t';
  351. cfg->escape2char['n'] = '\n';
  352. cfg->escape2char['f'] = '\f';
  353. cfg->escape2char['r'] = '\r';
  354. cfg->escape2char['u'] = 'u'; /* Unicode parsing required */
  355. #if 0
  356. /* Initialise separate storage for pre-generated escape codes.
  357. * Escapes 0-31 map directly, 34, 92, 127 follow afterwards to
  358. * save memory. */
  359. for (i = 0 ; i < 32; i++)
  360. sprintf(cfg->escapes[i], "\\u%04x", i);
  361. strcpy(cfg->escapes[8], "\b"); /* Override simpler escapes */
  362. strcpy(cfg->escapes[9], "\t");
  363. strcpy(cfg->escapes[10], "\n");
  364. strcpy(cfg->escapes[12], "\f");
  365. strcpy(cfg->escapes[13], "\r");
  366. strcpy(cfg->escapes[32], "\\\""); /* chr(34) */
  367. strcpy(cfg->escapes[33], "\\\\"); /* chr(92) */
  368. sprintf(cfg->escapes[34], "\\u%04x", 127); /* char(127) */
  369. /* Initialise encoding escape lookup table */
  370. for (i = 0; i < 32; i++)
  371. cfg->char2escape[i] = cfg->escapes[i];
  372. for (i = 32; i < 256; i++)
  373. cfg->char2escape[i] = NULL;
  374. cfg->char2escape[34] = cfg->escapes[32];
  375. cfg->char2escape[92] = cfg->escapes[33];
  376. cfg->char2escape[127] = cfg->escapes[34];
  377. #endif
  378. }
  379. /* ===== ENCODING ===== */
  380. static void json_encode_exception(lua_State *l, json_config_t *cfg, int lindex,
  381. const char *reason)
  382. {
  383. if (!cfg->encode_keep_buffer)
  384. strbuf_free(&cfg->encode_buf);
  385. luaL_error(l, "Cannot serialise %s: %s",
  386. lua_typename(l, lua_type(l, lindex)), reason);
  387. }
  388. /* json_append_string args:
  389. * - lua_State
  390. * - JSON strbuf
  391. * - String (Lua stack index)
  392. *
  393. * Returns nothing. Doesn't remove string from Lua stack */
  394. static void json_append_string(lua_State *l, strbuf_t *json, int lindex)
  395. {
  396. const char *escstr;
  397. int i;
  398. const char *str;
  399. size_t len;
  400. str = lua_tolstring(l, lindex, &len);
  401. /* Worst case is len * 6 (all unicode escapes).
  402. * This buffer is reused constantly for small strings
  403. * If there are any excess pages, they won't be hit anyway.
  404. * This gains ~5% speedup. */
  405. strbuf_ensure_empty_length(json, len * 6 + 2);
  406. strbuf_append_char_unsafe(json, '\"');
  407. for (i = 0; i < len; i++) {
  408. escstr = char2escape[(unsigned char)str[i]];
  409. if (escstr)
  410. strbuf_append_string(json, escstr);
  411. else
  412. strbuf_append_char_unsafe(json, str[i]);
  413. }
  414. strbuf_append_char_unsafe(json, '\"');
  415. }
  416. /* Find the size of the array on the top of the Lua stack
  417. * -1 object (not a pure array)
  418. * >=0 elements in array
  419. */
  420. static int lua_array_length(lua_State *l, json_config_t *cfg)
  421. {
  422. double k;
  423. int max;
  424. int items;
  425. max = 0;
  426. items = 0;
  427. lua_pushnil(l);
  428. /* table, startkey */
  429. while (lua_next(l, -2) != 0) {
  430. /* table, key, value */
  431. if (lua_isnumber(l, -2) &&
  432. (k = lua_tonumber(l, -2))) {
  433. /* Integer >= 1 ? */
  434. if (floor(k) == k && k >= 1) {
  435. if (k > max)
  436. max = k;
  437. items++;
  438. lua_pop(l, 1);
  439. continue;
  440. }
  441. }
  442. /* Must not be an array (non integer key) */
  443. lua_pop(l, 2);
  444. return -1;
  445. }
  446. /* Encode very sparse arrays as objects (if enabled) */
  447. if (cfg->encode_sparse_ratio > 0 &&
  448. max > items * cfg->encode_sparse_ratio &&
  449. max > cfg->encode_sparse_safe) {
  450. if (!cfg->encode_sparse_convert)
  451. json_encode_exception(l, cfg, -1, "excessively sparse array");
  452. return -1;
  453. }
  454. return max;
  455. }
  456. static void json_encode_descend(lua_State *l, json_config_t *cfg)
  457. {
  458. cfg->current_depth++;
  459. if (cfg->current_depth > cfg->encode_max_depth) {
  460. if (!cfg->encode_keep_buffer)
  461. strbuf_free(&cfg->encode_buf);
  462. luaL_error(l, "Cannot serialise, excessive nesting (%d)",
  463. cfg->current_depth);
  464. }
  465. }
  466. static void json_append_data(lua_State *l, json_config_t *cfg, strbuf_t *json);
  467. /* json_append_array args:
  468. * - lua_State
  469. * - JSON strbuf
  470. * - Size of passwd Lua array (top of stack) */
  471. static void json_append_array(lua_State *l, json_config_t *cfg, strbuf_t *json,
  472. int array_length)
  473. {
  474. int comma, i;
  475. json_encode_descend(l, cfg);
  476. strbuf_append_char(json, '[');
  477. comma = 0;
  478. for (i = 1; i <= array_length; i++) {
  479. if (comma)
  480. strbuf_append_char(json, ',');
  481. else
  482. comma = 1;
  483. lua_rawgeti(l, -1, i);
  484. json_append_data(l, cfg, json);
  485. lua_pop(l, 1);
  486. }
  487. strbuf_append_char(json, ']');
  488. cfg->current_depth--;
  489. }
  490. static void json_append_number(lua_State *l, strbuf_t *json, int index,
  491. json_config_t *cfg)
  492. {
  493. double num = lua_tonumber(l, index);
  494. if (cfg->encode_refuse_badnum && (isinf(num) || isnan(num)))
  495. json_encode_exception(l, cfg, index, "must not be NaN or Inf");
  496. /* Lowest double printed with %.14g is 21 characters long:
  497. * -1.7976931348623e+308
  498. *
  499. * Use 32 to include the \0, and a few extra just in case..
  500. */
  501. strbuf_append_fmt(json, 32, cfg->number_fmt, num);
  502. }
  503. static void json_append_object(lua_State *l, json_config_t *cfg,
  504. strbuf_t *json)
  505. {
  506. int comma, keytype;
  507. json_encode_descend(l, cfg);
  508. /* Object */
  509. strbuf_append_char(json, '{');
  510. lua_pushnil(l);
  511. /* table, startkey */
  512. comma = 0;
  513. while (lua_next(l, -2) != 0) {
  514. if (comma)
  515. strbuf_append_char(json, ',');
  516. else
  517. comma = 1;
  518. /* table, key, value */
  519. keytype = lua_type(l, -2);
  520. if (keytype == LUA_TNUMBER) {
  521. strbuf_append_char(json, '"');
  522. json_append_number(l, json, -2, cfg);
  523. strbuf_append_mem(json, "\":", 2);
  524. } else if (keytype == LUA_TSTRING) {
  525. json_append_string(l, json, -2);
  526. strbuf_append_char(json, ':');
  527. } else {
  528. json_encode_exception(l, cfg, -2,
  529. "table key must be a number or string");
  530. /* never returns */
  531. }
  532. /* table, key, value */
  533. json_append_data(l, cfg, json);
  534. lua_pop(l, 1);
  535. /* table, key */
  536. }
  537. strbuf_append_char(json, '}');
  538. cfg->current_depth--;
  539. }
  540. /* Serialise Lua data into JSON string. */
  541. static void json_append_data(lua_State *l, json_config_t *cfg, strbuf_t *json)
  542. {
  543. int len;
  544. switch (lua_type(l, -1)) {
  545. case LUA_TSTRING:
  546. json_append_string(l, json, -1);
  547. break;
  548. case LUA_TNUMBER:
  549. json_append_number(l, json, -1, cfg);
  550. break;
  551. case LUA_TBOOLEAN:
  552. if (lua_toboolean(l, -1))
  553. strbuf_append_mem(json, "true", 4);
  554. else
  555. strbuf_append_mem(json, "false", 5);
  556. break;
  557. case LUA_TTABLE:
  558. len = lua_array_length(l, cfg);
  559. if (len > 0)
  560. json_append_array(l, cfg, json, len);
  561. else
  562. json_append_object(l, cfg, json);
  563. break;
  564. case LUA_TNIL:
  565. strbuf_append_mem(json, "null", 4);
  566. break;
  567. case LUA_TLIGHTUSERDATA:
  568. if (lua_touserdata(l, -1) == NULL) {
  569. strbuf_append_mem(json, "null", 4);
  570. break;
  571. }
  572. default:
  573. /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD,
  574. * and LUA_TLIGHTUSERDATA) cannot be serialised */
  575. json_encode_exception(l, cfg, -1, "type not supported");
  576. /* never returns */
  577. }
  578. }
  579. static int json_encode(lua_State *l)
  580. {
  581. json_config_t *cfg;
  582. char *json;
  583. int len;
  584. /* Can't use json_verify_arg_count() since we need to ensure
  585. * there is only 1 argument */
  586. luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
  587. cfg = json_fetch_config(l);
  588. cfg->current_depth = 0;
  589. /* Reset the persistent buffer if it exists.
  590. * Otherwise allocate a new buffer. */
  591. if (strbuf_allocated(&cfg->encode_buf))
  592. strbuf_reset(&cfg->encode_buf);
  593. else
  594. strbuf_init(&cfg->encode_buf, 0);
  595. json_append_data(l, cfg, &cfg->encode_buf);
  596. json = strbuf_string(&cfg->encode_buf, &len);
  597. lua_pushlstring(l, json, len);
  598. if (!cfg->encode_keep_buffer)
  599. strbuf_free(&cfg->encode_buf);
  600. return 1;
  601. }
  602. /* ===== DECODING ===== */
  603. static void json_process_value(lua_State *l, json_parse_t *json,
  604. json_token_t *token);
  605. static int hexdigit2int(char hex)
  606. {
  607. if ('0' <= hex && hex <= '9')
  608. return hex - '0';
  609. /* Force lowercase */
  610. hex |= 0x20;
  611. if ('a' <= hex && hex <= 'f')
  612. return 10 + hex - 'a';
  613. return -1;
  614. }
  615. static int decode_hex4(const char *hex)
  616. {
  617. int digit[4];
  618. int i;
  619. /* Convert ASCII hex digit to numeric digit
  620. * Note: this returns an error for invalid hex digits, including
  621. * NULL */
  622. for (i = 0; i < 4; i++) {
  623. digit[i] = hexdigit2int(hex[i]);
  624. if (digit[i] < 0) {
  625. return -1;
  626. }
  627. }
  628. return (digit[0] << 12) +
  629. (digit[1] << 8) +
  630. (digit[2] << 4) +
  631. digit[3];
  632. }
  633. /* Converts a Unicode codepoint to UTF-8.
  634. * Returns UTF-8 string length, and up to 4 bytes in *utf8 */
  635. static int codepoint_to_utf8(char *utf8, int codepoint)
  636. {
  637. /* 0xxxxxxx */
  638. if (codepoint <= 0x7F) {
  639. utf8[0] = codepoint;
  640. return 1;
  641. }
  642. /* 110xxxxx 10xxxxxx */
  643. if (codepoint <= 0x7FF) {
  644. utf8[0] = (codepoint >> 6) | 0xC0;
  645. utf8[1] = (codepoint & 0x3F) | 0x80;
  646. return 2;
  647. }
  648. /* 1110xxxx 10xxxxxx 10xxxxxx */
  649. if (codepoint <= 0xFFFF) {
  650. utf8[0] = (codepoint >> 12) | 0xE0;
  651. utf8[1] = ((codepoint >> 6) & 0x3F) | 0x80;
  652. utf8[2] = (codepoint & 0x3F) | 0x80;
  653. return 3;
  654. }
  655. /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  656. if (codepoint <= 0x1FFFFF) {
  657. utf8[0] = (codepoint >> 18) | 0xF0;
  658. utf8[1] = ((codepoint >> 12) & 0x3F) | 0x80;
  659. utf8[2] = ((codepoint >> 6) & 0x3F) | 0x80;
  660. utf8[3] = (codepoint & 0x3F) | 0x80;
  661. return 4;
  662. }
  663. return 0;
  664. }
  665. /* Called when index pointing to beginning of UTF-16 code escape: \uXXXX
  666. * \u is guaranteed to exist, but the remaining hex characters may be
  667. * missing.
  668. * Translate to UTF-8 and append to temporary token string.
  669. * Must advance index to the next character to be processed.
  670. * Returns: 0 success
  671. * -1 error
  672. */
  673. static int json_append_unicode_escape(json_parse_t *json)
  674. {
  675. char utf8[4]; /* Surrogate pairs require 4 UTF-8 bytes */
  676. int codepoint;
  677. int surrogate_low;
  678. int len;
  679. int escape_len = 6;
  680. /* Fetch UTF-16 code unit */
  681. codepoint = decode_hex4(&json->data[json->index + 2]);
  682. if (codepoint < 0)
  683. return -1;
  684. /* UTF-16 surrogate pairs take the following 2 byte form:
  685. * 11011 x yyyyyyyyyy
  686. * When x = 0: y is the high 10 bits of the codepoint
  687. * x = 1: y is the low 10 bits of the codepoint
  688. *
  689. * Check for a surrogate pair (high or low) */
  690. if ((codepoint & 0xF800) == 0xD800) {
  691. /* Error if the 1st surrogate is not high */
  692. if (codepoint & 0x400)
  693. return -1;
  694. /* Ensure the next code is a unicode escape */
  695. if (json->data[json->index + escape_len] != '\\' ||
  696. json->data[json->index + escape_len + 1] != 'u') {
  697. return -1;
  698. }
  699. /* Fetch the next codepoint */
  700. surrogate_low = decode_hex4(&json->data[json->index + 2 + escape_len]);
  701. if (surrogate_low < 0)
  702. return -1;
  703. /* Error if the 2nd code is not a low surrogate */
  704. if ((surrogate_low & 0xFC00) != 0xDC00)
  705. return -1;
  706. /* Calculate Unicode codepoint */
  707. codepoint = (codepoint & 0x3FF) << 10;
  708. surrogate_low &= 0x3FF;
  709. codepoint = (codepoint | surrogate_low) + 0x10000;
  710. escape_len = 12;
  711. }
  712. /* Convert codepoint to UTF-8 */
  713. len = codepoint_to_utf8(utf8, codepoint);
  714. if (!len)
  715. return -1;
  716. /* Append bytes and advance parse index */
  717. strbuf_append_mem_unsafe(json->tmp, utf8, len);
  718. json->index += escape_len;
  719. return 0;
  720. }
  721. static void json_set_token_error(json_token_t *token, json_parse_t *json,
  722. const char *errtype)
  723. {
  724. token->type = T_ERROR;
  725. token->index = json->index;
  726. token->value.string = errtype;
  727. }
  728. static void json_next_string_token(json_parse_t *json, json_token_t *token)
  729. {
  730. char *escape2char = json->cfg->escape2char;
  731. char ch;
  732. /* Caller must ensure a string is next */
  733. assert(json->data[json->index] == '"');
  734. /* Skip " */
  735. json->index++;
  736. /* json->tmp is the temporary strbuf used to accumulate the
  737. * decoded string value. */
  738. strbuf_reset(json->tmp);
  739. while ((ch = json->data[json->index]) != '"') {
  740. if (!ch) {
  741. /* Premature end of the string */
  742. json_set_token_error(token, json, "unexpected end of string");
  743. return;
  744. }
  745. /* Handle escapes */
  746. if (ch == '\\') {
  747. /* Fetch escape character */
  748. ch = json->data[json->index + 1];
  749. /* Translate escape code and append to tmp string */
  750. ch = escape2char[(unsigned char)ch];
  751. if (ch == 'u') {
  752. if (json_append_unicode_escape(json) == 0)
  753. continue;
  754. json_set_token_error(token, json,
  755. "invalid unicode escape code");
  756. return;
  757. }
  758. if (!ch) {
  759. json_set_token_error(token, json, "invalid escape code");
  760. return;
  761. }
  762. /* Skip '\' */
  763. json->index++;
  764. }
  765. /* Append normal character or translated single character
  766. * Unicode escapes are handled above */
  767. strbuf_append_char_unsafe(json->tmp, ch);
  768. json->index++;
  769. }
  770. json->index++; /* Eat final quote (") */
  771. strbuf_ensure_null(json->tmp);
  772. token->type = T_STRING;
  773. token->value.string = strbuf_string(json->tmp, &token->string_len);
  774. }
  775. /* JSON numbers should take the following form:
  776. * -?(0|[1-9]|[1-9][0-9]+)(.[0-9]+)?([eE][-+]?[0-9]+)?
  777. *
  778. * json_next_number_token() uses strtod() which allows other forms:
  779. * - numbers starting with '+'
  780. * - NaN, -NaN, infinity, -infinity
  781. * - hexidecimal numbers
  782. * - numbers with leading zeros
  783. *
  784. * json_is_invalid_number() detects "numbers" which may pass strtod()'s
  785. * error checking, but should not be allowed with strict JSON.
  786. *
  787. * json_is_invalid_number() may pass numbers which cause strtod()
  788. * to generate an error.
  789. */
  790. static int json_is_invalid_number(json_parse_t *json)
  791. {
  792. int i = json->index;
  793. /* Reject numbers starting with + */
  794. if (json->data[i] == '+')
  795. return 1;
  796. /* Skip minus sign if it exists */
  797. if (json->data[i] == '-')
  798. i++;
  799. /* Reject numbers starting with 0x, or leading zeros */
  800. if (json->data[i] == '0') {
  801. int ch2 = json->data[i + 1];
  802. if ((ch2 | 0x20) == 'x' || /* Hex */
  803. ('0' <= ch2 && ch2 <= '9')) /* Leading zero */
  804. return 1;
  805. return 0;
  806. } else if (json->data[i] <= '9') {
  807. return 0; /* Ordinary number */
  808. }
  809. /* Reject inf/nan */
  810. if (!strncasecmp(&json->data[i], "inf", 3))
  811. return 1;
  812. if (!strncasecmp(&json->data[i], "nan", 3))
  813. return 1;
  814. /* Pass all other numbers which may still be invalid, but
  815. * strtod() will catch them. */
  816. return 0;
  817. }
  818. static void json_next_number_token(json_parse_t *json, json_token_t *token)
  819. {
  820. const char *startptr;
  821. char *endptr;
  822. token->type = T_NUMBER;
  823. startptr = &json->data[json->index];
  824. token->value.number = strtod(&json->data[json->index], &endptr);
  825. if (startptr == endptr)
  826. json_set_token_error(token, json, "invalid number");
  827. else
  828. json->index += endptr - startptr; /* Skip the processed number */
  829. return;
  830. }
  831. /* Fills in the token struct.
  832. * T_STRING will return a pointer to the json_parse_t temporary string
  833. * T_ERROR will leave the json->index pointer at the error.
  834. */
  835. static void json_next_token(json_parse_t *json, json_token_t *token)
  836. {
  837. json_token_type_t *ch2token = json->cfg->ch2token;
  838. int ch;
  839. /* Eat whitespace. FIXME: UGLY */
  840. token->type = ch2token[(unsigned char)json->data[json->index]];
  841. while (token->type == T_WHITESPACE)
  842. token->type = ch2token[(unsigned char)json->data[++json->index]];
  843. token->index = json->index;
  844. /* Don't advance the pointer for an error or the end */
  845. if (token->type == T_ERROR) {
  846. json_set_token_error(token, json, "invalid token");
  847. return;
  848. }
  849. if (token->type == T_END) {
  850. return;
  851. }
  852. /* Found a known single character token, advance index and return */
  853. if (token->type != T_UNKNOWN) {
  854. json->index++;
  855. return;
  856. }
  857. /* Process characters which triggered T_UNKNOWN */
  858. ch = json->data[json->index];
  859. /* Must use strncmp() to match the front of the JSON string.
  860. * JSON identifier must be lowercase.
  861. * When strict_numbers if disabled, either case is allowed for
  862. * Infinity/NaN (since we are no longer following the spec..) */
  863. if (ch == '"') {
  864. json_next_string_token(json, token);
  865. return;
  866. } else if (ch == '-' || ('0' <= ch && ch <= '9')) {
  867. if (json->cfg->decode_refuse_badnum && json_is_invalid_number(json)) {
  868. json_set_token_error(token, json, "invalid number");
  869. return;
  870. }
  871. json_next_number_token(json, token);
  872. return;
  873. } else if (!strncmp(&json->data[json->index], "true", 4)) {
  874. token->type = T_BOOLEAN;
  875. token->value.boolean = 1;
  876. json->index += 4;
  877. return;
  878. } else if (!strncmp(&json->data[json->index], "false", 5)) {
  879. token->type = T_BOOLEAN;
  880. token->value.boolean = 0;
  881. json->index += 5;
  882. return;
  883. } else if (!strncmp(&json->data[json->index], "null", 4)) {
  884. token->type = T_NULL;
  885. json->index += 4;
  886. return;
  887. } else if (!json->cfg->decode_refuse_badnum &&
  888. json_is_invalid_number(json)) {
  889. /* When refuse_badnum is disabled, only attempt to process
  890. * numbers we know are invalid JSON (Inf, NaN, hex)
  891. * This is required to generate an appropriate token error,
  892. * otherwise all bad tokens will register as "invalid number"
  893. */
  894. json_next_number_token(json, token);
  895. return;
  896. }
  897. /* Token starts with t/f/n but isn't recognised above. */
  898. json_set_token_error(token, json, "invalid token");
  899. }
  900. /* This function does not return.
  901. * DO NOT CALL WITH DYNAMIC MEMORY ALLOCATED.
  902. * The only supported exception is the temporary parser string
  903. * json->tmp struct.
  904. * json and token should exist on the stack somewhere.
  905. * luaL_error() will long_jmp and release the stack */
  906. static void json_throw_parse_error(lua_State *l, json_parse_t *json,
  907. const char *exp, json_token_t *token)
  908. {
  909. const char *found;
  910. strbuf_free(json->tmp);
  911. if (token->type == T_ERROR)
  912. found = token->value.string;
  913. else
  914. found = json_token_type_name[token->type];
  915. /* Note: token->index is 0 based, display starting from 1 */
  916. luaL_error(l, "Expected %s but found %s at character %d",
  917. exp, found, token->index + 1);
  918. }
  919. static void json_decode_checkstack(lua_State *l, json_parse_t *json, int n)
  920. {
  921. if (lua_checkstack(l, n))
  922. return;
  923. strbuf_free(json->tmp);
  924. luaL_error(l, "Too many nested data structures");
  925. }
  926. static void json_parse_object_context(lua_State *l, json_parse_t *json)
  927. {
  928. json_token_t token;
  929. /* 3 slots required:
  930. * .., table, key, value */
  931. json_decode_checkstack(l, json, 3);
  932. lua_newtable(l);
  933. json_next_token(json, &token);
  934. /* Handle empty objects */
  935. if (token.type == T_OBJ_END) {
  936. return;
  937. }
  938. while (1) {
  939. if (token.type != T_STRING)
  940. json_throw_parse_error(l, json, "object key string", &token);
  941. /* Push key */
  942. lua_pushlstring(l, token.value.string, token.string_len);
  943. json_next_token(json, &token);
  944. if (token.type != T_COLON)
  945. json_throw_parse_error(l, json, "colon", &token);
  946. /* Fetch value */
  947. json_next_token(json, &token);
  948. json_process_value(l, json, &token);
  949. /* Set key = value */
  950. lua_rawset(l, -3);
  951. json_next_token(json, &token);
  952. if (token.type == T_OBJ_END)
  953. return;
  954. if (token.type != T_COMMA)
  955. json_throw_parse_error(l, json, "comma or object end", &token);
  956. json_next_token(json, &token);
  957. }
  958. }
  959. /* Handle the array context */
  960. static void json_parse_array_context(lua_State *l, json_parse_t *json)
  961. {
  962. json_token_t token;
  963. int i;
  964. /* 2 slots required:
  965. * .., table, value */
  966. json_decode_checkstack(l, json, 2);
  967. lua_newtable(l);
  968. json_next_token(json, &token);
  969. /* Handle empty arrays */
  970. if (token.type == T_ARR_END)
  971. return;
  972. for (i = 1; ; i++) {
  973. json_process_value(l, json, &token);
  974. lua_rawseti(l, -2, i); /* arr[i] = value */
  975. json_next_token(json, &token);
  976. if (token.type == T_ARR_END)
  977. return;
  978. if (token.type != T_COMMA)
  979. json_throw_parse_error(l, json, "comma or array end", &token);
  980. json_next_token(json, &token);
  981. }
  982. }
  983. /* Handle the "value" context */
  984. static void json_process_value(lua_State *l, json_parse_t *json,
  985. json_token_t *token)
  986. {
  987. switch (token->type) {
  988. case T_STRING:
  989. lua_pushlstring(l, token->value.string, token->string_len);
  990. break;;
  991. case T_NUMBER:
  992. lua_pushnumber(l, token->value.number);
  993. break;;
  994. case T_BOOLEAN:
  995. lua_pushboolean(l, token->value.boolean);
  996. break;;
  997. case T_OBJ_BEGIN:
  998. json_parse_object_context(l, json);
  999. break;;
  1000. case T_ARR_BEGIN:
  1001. json_parse_array_context(l, json);
  1002. break;;
  1003. case T_NULL:
  1004. /* In Lua, setting "t[k] = nil" will delete k from the table.
  1005. * Hence a NULL pointer lightuserdata object is used instead */
  1006. lua_pushlightuserdata(l, NULL);
  1007. break;;
  1008. default:
  1009. json_throw_parse_error(l, json, "value", token);
  1010. }
  1011. }
  1012. /* json_text must be null terminated string */
  1013. static void lua_json_decode(lua_State *l, const char *json_text, int json_len)
  1014. {
  1015. json_parse_t json;
  1016. json_token_t token;
  1017. json.cfg = json_fetch_config(l);
  1018. json.data = json_text;
  1019. json.index = 0;
  1020. /* Ensure the temporary buffer can hold the entire string.
  1021. * This means we no longer need to do length checks since the decoded
  1022. * string must be smaller than the entire json string */
  1023. json.tmp = strbuf_new(json_len);
  1024. json_next_token(&json, &token);
  1025. json_process_value(l, &json, &token);
  1026. /* Ensure there is no more input left */
  1027. json_next_token(&json, &token);
  1028. if (token.type != T_END)
  1029. json_throw_parse_error(l, &json, "the end", &token);
  1030. strbuf_free(json.tmp);
  1031. }
  1032. static int json_decode(lua_State *l)
  1033. {
  1034. const char *json;
  1035. size_t len;
  1036. json_verify_arg_count(l, 1);
  1037. json = luaL_checklstring(l, 1, &len);
  1038. /* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3)
  1039. *
  1040. * CJSON can support any simple data type, hence only the first
  1041. * character is guaranteed to be ASCII (at worst: '"'). This is
  1042. * still enough to detect whether the wrong encoding is in use. */
  1043. if (len >= 2 && (!json[0] || !json[1]))
  1044. luaL_error(l, "JSON parser does not support UTF-16 or UTF-32");
  1045. lua_json_decode(l, json, len);
  1046. return 1;
  1047. }
  1048. /* ===== INITIALISATION ===== */
  1049. int luaopen_cjson(lua_State *l)
  1050. {
  1051. luaL_Reg reg[] = {
  1052. { "encode", json_encode },
  1053. { "decode", json_decode },
  1054. { "encode_sparse_array", json_cfg_encode_sparse_array },
  1055. { "encode_max_depth", json_cfg_encode_max_depth },
  1056. { "encode_number_precision", json_cfg_encode_number_precision },
  1057. { "encode_keep_buffer", json_cfg_encode_keep_buffer },
  1058. { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers },
  1059. { NULL, NULL }
  1060. };
  1061. /* Use json_fetch_config as a pointer.
  1062. * It's faster than using a config string, and more unique */
  1063. lua_pushlightuserdata(l, &json_config_key);
  1064. json_create_config(l);
  1065. lua_settable(l, LUA_REGISTRYINDEX);
  1066. luaL_register(l, "cjson", reg);
  1067. /* Set cjson.null */
  1068. lua_pushlightuserdata(l, NULL);
  1069. lua_setfield(l, -2, "null");
  1070. /* Set cjson.version */
  1071. lua_pushliteral(l, VERSION);
  1072. lua_setfield(l, -2, "version");
  1073. /* Return cjson table */
  1074. return 1;
  1075. }
  1076. /* vi:ai et sw=4 ts=4:
  1077. */