0006-luci-lib-jsonc-Add-ltn12-compatible-sink-factory.patch 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. From: Jan-Philipp Litza <janphilipp@litza.de>
  2. Date: Tue, 1 Sep 2015 16:17:23 +0200
  3. Subject: luci-lib-jsonc: Add ltn12-compatible sink factory
  4. To use the luci-lib-jsonc parser as sink for an ltn12 pump (for example
  5. from stdin), the following code will now do:
  6. require 'luci.ltn12'
  7. require 'luci.jsonc'
  8. local parser = luci.jsonc.new()
  9. luci.ltn12.pump.all(luci.ltn12.source.file(io.input()), parser:sink())
  10. print(parser:get())
  11. Signed-off-by: Jan-Philipp Litza <janphilipp@litza.de>
  12. diff --git a/libs/luci-lib-jsonc/src/jsonc.c b/libs/luci-lib-jsonc/src/jsonc.c
  13. index b857c97..ef11101 100644
  14. --- a/libs/luci-lib-jsonc/src/jsonc.c
  15. +++ b/libs/luci-lib-jsonc/src/jsonc.c
  16. @@ -328,6 +328,76 @@ static int json_parse_set(lua_State *L)
  17. return 0;
  18. }
  19. +static int json_parse_sink_closure(lua_State *L)
  20. +{
  21. + bool finished = lua_toboolean(L, lua_upvalueindex(2));
  22. + if (lua_isnil(L, 1))
  23. + {
  24. + // no more data available
  25. + if (finished)
  26. + {
  27. + // we were finished parsing
  28. + lua_pushboolean(L, true);
  29. + return 1;
  30. + }
  31. + else
  32. + {
  33. + lua_pushnil(L);
  34. + lua_pushstring(L, "Incomplete JSON data");
  35. + return 2;
  36. + }
  37. + }
  38. + else
  39. + {
  40. + if (finished)
  41. + {
  42. + lua_pushnil(L);
  43. + lua_pushstring(L, "Unexpected data after complete JSON object");
  44. + return 2;
  45. + }
  46. + else
  47. + {
  48. + // luci.jsonc.parser.chunk()
  49. + lua_pushcfunction(L, json_parse_chunk);
  50. + // parser object from closure
  51. + lua_pushvalue(L, lua_upvalueindex(1));
  52. + // chunk
  53. + lua_pushvalue(L, 1);
  54. + lua_call(L, 2, 2);
  55. +
  56. + if (lua_isnil(L, -2))
  57. + {
  58. + // an error occurred, leave (nil, errmsg) on the stack and return it
  59. + return 2;
  60. + }
  61. + else if (lua_toboolean(L, -2))
  62. + {
  63. + // finished reading, set finished=true and return nil to prevent further input
  64. + lua_pop(L, 2);
  65. + lua_pushboolean(L, true);
  66. + lua_replace(L, lua_upvalueindex(2));
  67. + lua_pushnil(L);
  68. + return 1;
  69. + }
  70. + else
  71. + {
  72. + // not finished reading, return true
  73. + lua_pop(L, 2);
  74. + lua_pushboolean(L, true);
  75. + return 1;
  76. + }
  77. + }
  78. + }
  79. +}
  80. +
  81. +static int json_parse_sink(lua_State *L)
  82. +{
  83. + luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
  84. + lua_pushboolean(L, false);
  85. + lua_pushcclosure(L, json_parse_sink_closure, 2);
  86. + return 1;
  87. +}
  88. +
  89. static int json_tostring(lua_State *L)
  90. {
  91. struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
  92. @@ -367,6 +437,7 @@ static const luaL_reg jsonc_parser_methods[] = {
  93. { "parse", json_parse_chunk },
  94. { "get", json_parse_get },
  95. { "set", json_parse_set },
  96. + { "sink", json_parse_sink },
  97. { "stringify", json_tostring },
  98. { "__gc", json_gc },
  99. diff --git a/libs/luci-lib-jsonc/src/jsonc.luadoc b/libs/luci-lib-jsonc/src/jsonc.luadoc
  100. index 2ee9ceb..720b17d 100644
  101. --- a/libs/luci-lib-jsonc/src/jsonc.luadoc
  102. +++ b/libs/luci-lib-jsonc/src/jsonc.luadoc
  103. @@ -121,10 +121,22 @@ parser:set({ "some", "data" })`
  104. ]]
  105. ---[[
  106. -Serialize current parser state as JSON.
  107. +Generate an ltn12-compatible sink.
  108. @class function
  109. @sort 4
  110. +@name parser.sink
  111. +@return Returns a function that can be used as an ltn12 sink.
  112. +@usage `parser = luci.jsonc.new()
  113. +ltn12.pump.all(ltn12.source.file(io.input()), parser:sink())
  114. +print(parser:get())`
  115. +]]
  116. +
  117. +---[[
  118. +Serialize current parser state as JSON.
  119. +
  120. +@class function
  121. +@sort 5
  122. @name parser.stringify
  123. @param pretty A boolean value indicating whether the resulting JSON should be pretty printed.
  124. @return Returns the serialized JSON data of this parser instance.