ffi-yajl 2.7.5-universal-mingw-ucrt
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +118 -0
- data/bin/ffi-yajl-bench +36 -0
- data/ext/ffi_yajl/ext/dlopen/dlopen.c +40 -0
- data/ext/ffi_yajl/ext/dlopen/extconf.rb +16 -0
- data/ext/ffi_yajl/ext/dlopen/yajl.sym +18 -0
- data/ext/ffi_yajl/ext/encoder/encoder.c +395 -0
- data/ext/ffi_yajl/ext/encoder/extconf.rb +86 -0
- data/ext/ffi_yajl/ext/parser/extconf.rb +86 -0
- data/ext/ffi_yajl/ext/parser/parser.c +240 -0
- data/lib/ffi_yajl/benchmark/MIT-LICENSE +20 -0
- data/lib/ffi_yajl/benchmark/encode.rb +82 -0
- data/lib/ffi_yajl/benchmark/encode_json_and_marshal.rb +42 -0
- data/lib/ffi_yajl/benchmark/encode_json_and_yaml.rb +47 -0
- data/lib/ffi_yajl/benchmark/encode_profile.rb +34 -0
- data/lib/ffi_yajl/benchmark/http.rb +28 -0
- data/lib/ffi_yajl/benchmark/parse.rb +93 -0
- data/lib/ffi_yajl/benchmark/parse_json_and_marshal.rb +50 -0
- data/lib/ffi_yajl/benchmark/parse_json_and_yaml.rb +55 -0
- data/lib/ffi_yajl/benchmark/parse_profile.rb +33 -0
- data/lib/ffi_yajl/benchmark/parse_profile_ruby_prof.rb +34 -0
- data/lib/ffi_yajl/benchmark/parse_stream.rb +54 -0
- data/lib/ffi_yajl/benchmark/subjects/item.json +1 -0
- data/lib/ffi_yajl/benchmark/subjects/ohai.json +1216 -0
- data/lib/ffi_yajl/benchmark/subjects/ohai.marshal_dump +0 -0
- data/lib/ffi_yajl/benchmark/subjects/ohai.yml +975 -0
- data/lib/ffi_yajl/benchmark/subjects/twitter_search.json +1 -0
- data/lib/ffi_yajl/benchmark/subjects/twitter_stream.json +430 -0
- data/lib/ffi_yajl/benchmark/subjects/unicode.json +1 -0
- data/lib/ffi_yajl/benchmark.rb +27 -0
- data/lib/ffi_yajl/encoder.rb +94 -0
- data/lib/ffi_yajl/ext/.keep +0 -0
- data/lib/ffi_yajl/ext.rb +49 -0
- data/lib/ffi_yajl/ffi/encoder.rb +262 -0
- data/lib/ffi_yajl/ffi/parser.rb +163 -0
- data/lib/ffi_yajl/ffi.rb +153 -0
- data/lib/ffi_yajl/map_library_name.rb +109 -0
- data/lib/ffi_yajl/parser.rb +91 -0
- data/lib/ffi_yajl/platform.rb +29 -0
- data/lib/ffi_yajl/version.rb +25 -0
- data/lib/ffi_yajl.rb +50 -0
- metadata +128 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"results":[{"text":"#ruby \u732e\u672c\u30ad\u30bf\u30fc\u30fc\u30fc\u30fc\u30fc\u30fc\uff08\u309c\u2200\u309c\uff09\u30fc\u30fc\u30fc\u30fc\u30fc\u30fc\uff01\uff01 http:\/\/www.amazon.co.jp\/gp\/product\/4863540221","to_user_id":null,"from_user":"rubikitch","id":1843394737,"from_user_id":847295,"iso_language_code":"ja","source":"<a href="http:\/\/www.misuzilla.org\/dist\/net\/twitterircgateway\/">TwitterIrcGateway<\/a>","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Tue, 19 May 2009 03:12:47 +0000"},{"text":"Ruby on Rails\u3068CakePHP\u3001\u3069\u3063\u3061\u3067\u88fd\u9020\u3057\u3088\u3046\u304b\u3057\u3089","to_user_id":null,"from_user":"takkada","id":1842694220,"from_user_id":412519,"iso_language_code":"ja","source":"<a href="http:\/\/twitterfox.net\/">TwitterFox<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/16301882\/62305_4124481745_normal.jpg","created_at":"Tue, 19 May 2009 02:00:08 +0000"},{"text":"Ruby on Rails \u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306f\u30fc\u3058\u307e\u30fc\u308b\u3088\u30fc","to_user_id":null,"from_user":"Tomohiro","id":1842375120,"from_user_id":38704,"iso_language_code":"ja","source":"<a href="http:\/\/www.misuzilla.org\/dist\/net\/twitterircgateway\/">TwitterIrcGateway<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/20970892\/578576_3772887925_normal.jpg","created_at":"Tue, 19 May 2009 01:27:18 +0000"},{"text":"ruby winole.rb\u3067\u547c\u3073\u51fa\u3057\u305f\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u30e1\u30e2\u30ea\u304c\u9069\u5207\u306b\u958b\u653e\u3055\u308c\u3066\u306a\u304b\u3063\u305f\u3002","to_user_id":null,"from_user":"tomofusa","id":1841955169,"from_user_id":35354,"iso_language_code":"ja","source":"<a href="http:\/\/cheebow.info\/chemt\/archives\/2007\/04\/twitterwindowst.html">Twit<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/18213412\/fusa2.0_about53_normal.png","created_at":"Tue, 19 May 2009 00:43:20 +0000"},{"text":"Ruby HTTP\u4e26\u5217\u3092\u51e6\u7406\u3092\u9ad8\u901f\u5316\u3001"Typhoeus"\u767b\u5834 | \u30a8\u30f3\u30bf\u30fc\u30d7\u30e9\u30a4\u30ba | \u30de\u30a4\u30b3\u30df\u30b8\u30e3\u30fc\u30ca\u30eb http:\/\/ff.im\/-31cez","to_user_id":null,"from_user":"MyGReaderFeed","id":1841206557,"from_user_id":11923042,"iso_language_code":"ja","source":"<a href="http:\/\/friendfeed.com\/">FriendFeed<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/141487706\/3379573163_e79dab7511_normal.bmp","created_at":"Mon, 18 May 2009 23:22:26 +0000"},{"text":"\u3044\u305a\u308c\u306b\u3057\u3066\u3082\u3069\u3053\u304b\u306b Ruby 1.9.1 \u74b0\u5883\u306f\u4f5c\u3089\u306a\u3044\u3068\u30c0\u30e1\u304b\u306a\u3041\u3002Debian lenny \u4efb\u305b\u3060\u3068 1.9.0 \u3057\u304b\u8a66\u305b\u306a\u3044\u3063\u307d\u3044\u3057\u3002","to_user_id":null,"from_user":"wtnabe","id":1840166013,"from_user_id":32040,"iso_language_code":"ja","source":"<a href="http:\/\/www.misuzilla.org\/dist\/net\/twitterircgateway\/">TwitterIrcGateway<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/59828670\/200805-wtnabe-film_normal.png","created_at":"Mon, 18 May 2009 21:26:17 +0000"},{"text":"Ruby 1.9 \u3067\u306f URI#decode \u3060\u3051\u3058\u3083\u610f\u5473\u304c\u306a\u3044\u306e\u304b\u306a\uff1f \u3053\u306e\u8fba\u304b\u3089\u5206\u304b\u3089\u306a\u304f\u306a\u3063\u3066\u304f\u308b\u306a\u3002","to_user_id":null,"from_user":"wtnabe","id":1839967007,"from_user_id":32040,"iso_language_code":"ja","source":"<a href="http:\/\/www.misuzilla.org\/dist\/net\/twitterircgateway\/">TwitterIrcGateway<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/59828670\/200805-wtnabe-film_normal.png","created_at":"Mon, 18 May 2009 21:06:06 +0000"},{"text":"Star Ruby \u3067\u30d5\u30ec\u30fc\u30e0\u30b9\u30ad\u30c3\u30d7\u304c\u5b9f\u88c5\u3057\u306b\u304f\u3044\u7406\u7531\u306e\u3072\u3068\u3064\u306b\u3001\u30b9\u30af\u30ea\u30fc\u30f3\u3078\u306e\u63cf\u753b\u304c\u9045\u5ef6\u3067\u304d\u306a\u3044\u3068\u3044\u3046\u306e\u304c\u3042\u308b\u3002 Texture#[] \u306a\u3069\u3067\u30d4\u30af\u30bb\u30eb\u306e\u5024\u3092\u8aad\u307f\u53d6\u3089\u308c\u308b\u53ef\u80fd\u6027\u304c\u3042\u308b\u305f\u3081\u3002\u8aad\u307f\u53d6\u3089\u308c\u308b\u30ae\u30ea\u30ae\u30ea\u307e\u3067\u9045\u5ef6\u3059\u308b\u306e\u3082\u30a2\u30ea\u3060\u304c\u3001\u5b9f\u88c5\u306f\u9762\u5012\u3067\u3042\u308b\u3002","to_user_id":null,"from_user":"hajimehoshi","id":1837784833,"from_user_id":7543,"iso_language_code":"ja","source":"<a href="http:\/\/twitter.com\/">web<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/14446892\/michael_normal.jpg","created_at":"Mon, 18 May 2009 17:21:16 +0000"},{"text":"ruby-gem\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u3066\u3001rails\u306b\u30c1\u30e3\u30ec\u30f3\u30b8","to_user_id":null,"from_user":"tom_a","id":1837459653,"from_user_id":366098,"iso_language_code":"ja","source":"<a href="http:\/\/twitterfox.net\/">TwitterFox<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/16661182\/DSC02701_normal.jpg","created_at":"Mon, 18 May 2009 16:46:36 +0000"},{"text":"@saronpasu \u4e2d\u8eab\u306b\u30a2\u30af\u30bb\u30b9\u3057\u306b\u304f\u3044\u3057\u3001\u4f55\u3088\u308a\u4e0d\u5b89\u5b9a\u3059\u304e\u3067\u3059\u306d\u2026\u4f8b\u5916\u3063\u3066\u30ec\u30d9\u30eb\u3058\u3083\u306a\u304f\u3066 ruby \u5dfb\u304d\u8fbc\u3093\u3067\u843d\u3061\u308b\u306e\u3067\u2026","to_user_id":28082,"to_user":"saronpasu","from_user":"negaton","id":1836710607,"from_user_id":5893,"iso_language_code":"ja","source":"<a href="http:\/\/cheebow.info\/chemt\/archives\/2007\/04\/twitterwindowst.html">Twit<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/35934732\/DSC00338_icon_normal.jpg","created_at":"Mon, 18 May 2009 15:28:25 +0000"},{"text":"\u6628\u65e5 CaboCha-Ruby \u306e token \u306e surface \u3092\u53e9\u3044\u305f\u3089\u843d\u3061\u305f\u306e\u306b\u4eca\u65e5\u306f\u5168\u304f\u540c\u3058\u30b3\u30fc\u30c9\u52d5\u304b\u3057\u3066\u3066\u843d\u3061\u306a\u3044\u3068\u304b\u306a\u3093\u306a\u306e\u2026","to_user_id":null,"from_user":"negaton","id":1836267822,"from_user_id":5893,"iso_language_code":"ja","source":"<a href="http:\/\/cheebow.info\/chemt\/archives\/2007\/04\/twitterwindowst.html">Twit<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/35934732\/DSC00338_icon_normal.jpg","created_at":"Mon, 18 May 2009 14:41:26 +0000"},{"text":"ruby.snippets \u3092\u773a\u3081\u3066\u307f\u3066\u3001\u3053\u308c\u306f\u81ea\u5206\u304c\u4f7f\u3044\u3053\u306a\u305b\u308b\u3082\u306e\u3067\u306f\u306a\u3044\u3068\u308f\u304b\u3063\u305f","to_user_id":null,"from_user":"ursm","id":1835699306,"from_user_id":41919,"iso_language_code":"ja","source":"<a href="http:\/\/www.nambu.com">Nambu<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/28792412\/1153147983506_normal.jpg","created_at":"Mon, 18 May 2009 13:33:59 +0000"},{"text":"\u3068\u3053\u308d\u3067\u3001PHP \u304b\u3089\u306f Ruby \u3063\u3066\u547c\u3079\u308b\u306e\uff1f","to_user_id":null,"from_user":"nov","id":1835354604,"from_user_id":76705,"iso_language_code":"ja","source":"<a href="http:\/\/twitterfon.net\/">TwitterFon<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/60572614\/nov_normal.gif","created_at":"Mon, 18 May 2009 12:47:52 +0000"},{"text":"\u3067\u304d\u3042\u304c\u3063\u305f\u3053\u308d shindig ruby ver. \u51fa\u3066\u305f\u308a\u3057\u305f\u3089\u6ce3\u304f\u3002","to_user_id":null,"from_user":"nov","id":1835155373,"from_user_id":76705,"iso_language_code":"ja","source":"<a href="http:\/\/twitterfon.net\/">TwitterFon<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/60572614\/nov_normal.gif","created_at":"Mon, 18 May 2009 12:17:17 +0000"},{"text":"@papiron ruby-dev\u3067ruby1.9\u306bsqlite\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u6a19\u6e96\u6dfb\u4ed8\u3057\u3088\u3046\u3068\u3044\u3046\u8b70\u8ad6\u304c\u3055\u308c\u3066\u307e\u3059\u3002http:\/\/bit.ly\/Limi9","to_user_id":10226526,"to_user":"papiron","from_user":"taigou","id":1834625775,"from_user_id":3915244,"iso_language_code":"ja","source":"<a href="http:\/\/twitterfox.net\/">TwitterFox<\/a>","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/95583044\/me_normal.png","created_at":"Mon, 18 May 2009 10:38:40 +0000"}],"since_id":1769782474,"max_id":1843394737,"refresh_url":"?since_id=1843394737&q=ruby","results_per_page":15,"next_page":"?page=2&max_id=1843394737&lang=ja&q=ruby","warning":"adjusted since_id, it was older than allowedsince_id removed for pagination.","completed_in":0.052502,"page":1,"query":"ruby"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
require "ffi_yajl/benchmark/encode"
|
|
24
|
+
require "ffi_yajl/benchmark/encode_profile"
|
|
25
|
+
require "ffi_yajl/benchmark/parse"
|
|
26
|
+
require "ffi_yajl/benchmark/parse_profile"
|
|
27
|
+
require "ffi_yajl/benchmark/parse_profile_ruby_prof"
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
module FFI_Yajl
|
|
24
|
+
class EncodeError < StandardError; end
|
|
25
|
+
|
|
26
|
+
class Encoder
|
|
27
|
+
attr_accessor :opts
|
|
28
|
+
|
|
29
|
+
def encode(obj)
|
|
30
|
+
# initialization that we can do in pure ruby
|
|
31
|
+
yajl_gen_opts = {}
|
|
32
|
+
|
|
33
|
+
yajl_gen_opts[:yajl_gen_validate_utf8] = @opts[:validate_utf8] == false ? false : true
|
|
34
|
+
yajl_gen_opts[:yajl_gen_beautify] = false
|
|
35
|
+
yajl_gen_opts[:yajl_gen_indent_string] = " "
|
|
36
|
+
|
|
37
|
+
if opts[:pretty]
|
|
38
|
+
yajl_gen_opts[:yajl_gen_beautify] = true
|
|
39
|
+
yajl_gen_opts[:yajl_gen_indent_string] = opts[:indent] || " "
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# call either the ext or ffi hook
|
|
43
|
+
str = do_yajl_encode(obj, yajl_gen_opts, opts)
|
|
44
|
+
# we can skip cleaning the whole string for utf-8 issues if we have yajl validate as we go
|
|
45
|
+
|
|
46
|
+
str.force_encoding("UTF-8")
|
|
47
|
+
unless yajl_gen_opts[:yajl_gen_validate_utf8]
|
|
48
|
+
if str.respond_to?(:scrub)
|
|
49
|
+
str.scrub!
|
|
50
|
+
else
|
|
51
|
+
str.encode!("UTF-16le", undef: :replace, invalid: :replace).encode!("UTF-8")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
str
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.encode(obj, *args)
|
|
58
|
+
new(*args).encode(obj)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def initialize(opts = {})
|
|
62
|
+
@opts = opts
|
|
63
|
+
@opts ||= {}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def self.raise_error_for_status(status, token = nil)
|
|
67
|
+
# scrub token to valid utf-8 since we may be issuing an exception on an invalid utf-8 token
|
|
68
|
+
token = token.to_s.force_encoding("UTF-8")
|
|
69
|
+
if token.respond_to?(:scrub)
|
|
70
|
+
token.scrub!
|
|
71
|
+
else
|
|
72
|
+
token.encode!("UTF-16le", undef: :replace, invalid: :replace).encode!("UTF-8")
|
|
73
|
+
end
|
|
74
|
+
case status
|
|
75
|
+
when 1 # yajl_gen_keys_must_be_strings
|
|
76
|
+
raise FFI_Yajl::EncodeError, "YAJL internal error: attempted use of non-string object as key"
|
|
77
|
+
when 2 # yajl_max_depth_exceeded
|
|
78
|
+
raise FFI_Yajl::EncodeError, "Max nesting depth exceeded"
|
|
79
|
+
when 3 # yajl_gen_in_error_state
|
|
80
|
+
raise FFI_Yajl::EncodeError, "YAJL internal error: a generator function (yajl_gen_XXX) was called while in an error state"
|
|
81
|
+
when 4 # yajl_gen_generation_complete
|
|
82
|
+
raise FFI_Yajl::EncodeError, "YAJL internal error: attempted to encode to an already-complete document"
|
|
83
|
+
when 5 # yajl_gen_invalid_number
|
|
84
|
+
raise FFI_Yajl::EncodeError, "Invalid number: cannot encode Infinity, -Infinity, or NaN"
|
|
85
|
+
when 6 # yajl_gen_no_buf
|
|
86
|
+
raise FFI_Yajl::EncodeError, "YAJL internal error: yajl_gen_get_buf was called, but a print callback was specified, so no internal buffer is available"
|
|
87
|
+
when 7 # yajl_gen_invalid_string
|
|
88
|
+
raise FFI_Yajl::EncodeError, "Invalid UTF-8 string '#{token}': cannot encode to UTF-8"
|
|
89
|
+
else
|
|
90
|
+
raise FFI_Yajl::EncodeError, "Unknown YAJL Error (#{status}), please report this as a bug"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
File without changes
|
data/lib/ffi_yajl/ext.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
|
2
|
+
# Copyright (c) 2015 Chef Software, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
require "rubygems" unless defined?(Gem)
|
|
24
|
+
|
|
25
|
+
require_relative "encoder"
|
|
26
|
+
require_relative "parser"
|
|
27
|
+
require "ffi_yajl/ext/dlopen"
|
|
28
|
+
require_relative "map_library_name"
|
|
29
|
+
|
|
30
|
+
# needed so the encoder c-code can find these symbols
|
|
31
|
+
require "stringio" unless defined?(StringIO)
|
|
32
|
+
require "date"
|
|
33
|
+
|
|
34
|
+
module FFI_Yajl
|
|
35
|
+
extend FFI_Yajl::MapLibraryName
|
|
36
|
+
extend FFI_Yajl::Ext::Dlopen
|
|
37
|
+
|
|
38
|
+
dlopen_yajl_library
|
|
39
|
+
|
|
40
|
+
class Parser
|
|
41
|
+
require "ffi_yajl/ext/parser"
|
|
42
|
+
include FFI_Yajl::Ext::Parser
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class Encoder
|
|
46
|
+
require "ffi_yajl/ext/encoder"
|
|
47
|
+
include FFI_Yajl::Ext::Encoder
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
|
2
|
+
# Copyright (c) 2015-2017, Chef Software Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
require "date"
|
|
24
|
+
require "stringio" unless defined?(StringIO)
|
|
25
|
+
|
|
26
|
+
module FFI_Yajl
|
|
27
|
+
module FFI
|
|
28
|
+
module Encoder
|
|
29
|
+
def do_yajl_encode(obj, yajl_gen_opts, opts)
|
|
30
|
+
yajl_gen = FFI_Yajl.yajl_gen_alloc(nil)
|
|
31
|
+
|
|
32
|
+
# configure the yajl encoder
|
|
33
|
+
if yajl_gen_opts[:yajl_gen_beautify]
|
|
34
|
+
FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_beautify, :int, 1)
|
|
35
|
+
end
|
|
36
|
+
if yajl_gen_opts[:yajl_gen_validate_utf8]
|
|
37
|
+
FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_validate_utf8, :int, 1)
|
|
38
|
+
end
|
|
39
|
+
indent = yajl_gen_opts[:yajl_gen_indent_string] || " "
|
|
40
|
+
FFI_Yajl.yajl_gen_config(yajl_gen, :yajl_gen_indent_string, :string, indent)
|
|
41
|
+
|
|
42
|
+
# setup our own state
|
|
43
|
+
state = {
|
|
44
|
+
json_opts: opts,
|
|
45
|
+
processing_key: false,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# do the encoding
|
|
49
|
+
obj.ffi_yajl(yajl_gen, state)
|
|
50
|
+
|
|
51
|
+
# get back our encoded JSON
|
|
52
|
+
string_ptr = ::FFI::MemoryPointer.new(:string)
|
|
53
|
+
length_ptr = ::FFI::MemoryPointer.new(:int)
|
|
54
|
+
if ( status = FFI_Yajl.yajl_gen_get_buf(yajl_gen, string_ptr, length_ptr) ) != 0
|
|
55
|
+
FFI_Yajl::Encoder.raise_error_for_status(status)
|
|
56
|
+
end
|
|
57
|
+
string = string_ptr.get_pointer(0).read_string
|
|
58
|
+
|
|
59
|
+
FFI_Yajl.yajl_gen_free(yajl_gen)
|
|
60
|
+
|
|
61
|
+
string
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class Hash
|
|
68
|
+
def ffi_yajl(yajl_gen, state)
|
|
69
|
+
if state[:processing_key]
|
|
70
|
+
str = to_s
|
|
71
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
72
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
if ( status = FFI_Yajl.yajl_gen_map_open(yajl_gen) ) != 0
|
|
76
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, "{")
|
|
77
|
+
end
|
|
78
|
+
each do |key, value|
|
|
79
|
+
# Perf Fix: mutate state hash rather than creating new copy
|
|
80
|
+
state[:processing_key] = true
|
|
81
|
+
key.ffi_yajl(yajl_gen, state)
|
|
82
|
+
state[:processing_key] = false
|
|
83
|
+
value.ffi_yajl(yajl_gen, state)
|
|
84
|
+
end
|
|
85
|
+
if ( status = FFI_Yajl.yajl_gen_map_close(yajl_gen) ) != 0
|
|
86
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, "}")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class Array
|
|
93
|
+
def ffi_yajl(yajl_gen, state)
|
|
94
|
+
if state[:processing_key]
|
|
95
|
+
str = to_s
|
|
96
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
97
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
98
|
+
end
|
|
99
|
+
else
|
|
100
|
+
if ( status = FFI_Yajl.yajl_gen_array_open(yajl_gen) ) != 0
|
|
101
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, "[")
|
|
102
|
+
end
|
|
103
|
+
each do |value|
|
|
104
|
+
value.ffi_yajl(yajl_gen, state)
|
|
105
|
+
end
|
|
106
|
+
if ( status = FFI_Yajl.yajl_gen_array_close(yajl_gen) ) != 0
|
|
107
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, "]")
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
class NilClass
|
|
114
|
+
def ffi_yajl(yajl_gen, state)
|
|
115
|
+
str = to_s
|
|
116
|
+
if state[:processing_key]
|
|
117
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
118
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
119
|
+
end
|
|
120
|
+
else
|
|
121
|
+
if ( status = FFI_Yajl.yajl_gen_null(yajl_gen) ) != 0
|
|
122
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
class TrueClass
|
|
129
|
+
def ffi_yajl(yajl_gen, state)
|
|
130
|
+
str = to_s
|
|
131
|
+
if state[:processing_key]
|
|
132
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
133
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
134
|
+
end
|
|
135
|
+
else
|
|
136
|
+
if ( status = FFI_Yajl.yajl_gen_bool(yajl_gen, 1) ) != 0
|
|
137
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
class FalseClass
|
|
144
|
+
def ffi_yajl(yajl_gen, state)
|
|
145
|
+
str = to_s
|
|
146
|
+
if state[:processing_key]
|
|
147
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
148
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
149
|
+
end
|
|
150
|
+
else
|
|
151
|
+
if ( status = FFI_Yajl.yajl_gen_bool(yajl_gen, 0) ) != 0
|
|
152
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
class Integer
|
|
159
|
+
def ffi_yajl(yajl_gen, state)
|
|
160
|
+
str = to_s
|
|
161
|
+
if str == "NaN" || str == "Infinity" || str == "-Infinity"
|
|
162
|
+
raise ::FFI_Yajl::EncodeError, "'#{str}' is an invalid number"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
if state[:processing_key]
|
|
166
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
167
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
168
|
+
end
|
|
169
|
+
else
|
|
170
|
+
if ( status = FFI_Yajl.yajl_gen_number(yajl_gen, str, str.bytesize) ) != 0
|
|
171
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
class Float
|
|
178
|
+
def ffi_yajl(yajl_gen, state)
|
|
179
|
+
str = to_s
|
|
180
|
+
if str == "NaN" || str == "Infinity" || str == "-Infinity"
|
|
181
|
+
raise ::FFI_Yajl::EncodeError, "'#{str}' is an invalid number"
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
if state[:processing_key]
|
|
185
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
186
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
187
|
+
end
|
|
188
|
+
else
|
|
189
|
+
if ( status = FFI_Yajl.yajl_gen_number(yajl_gen, str, str.bytesize) ) != 0
|
|
190
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
class Symbol
|
|
197
|
+
def ffi_yajl(yajl_gen, state)
|
|
198
|
+
str = to_s
|
|
199
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
200
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
class String
|
|
206
|
+
def ffi_yajl(yajl_gen, state)
|
|
207
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, self, bytesize) ) != 0
|
|
208
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, self)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
class StringIO
|
|
214
|
+
def ffi_yajl(yajl_gen, state)
|
|
215
|
+
str = read
|
|
216
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
217
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
class Date
|
|
223
|
+
def ffi_yajl(yajl_gen, state)
|
|
224
|
+
str = to_s
|
|
225
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
226
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
class Time
|
|
232
|
+
def ffi_yajl(yajl_gen, state)
|
|
233
|
+
str = strftime "%Y-%m-%d %H:%M:%S %z"
|
|
234
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
235
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
class DateTime
|
|
241
|
+
def ffi_yajl(yajl_gen, state)
|
|
242
|
+
str = to_s
|
|
243
|
+
if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
|
|
244
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str)
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# I feel dirty
|
|
250
|
+
class Object
|
|
251
|
+
def ffi_yajl(yajl_gen, state)
|
|
252
|
+
if !state[:processing_key] && respond_to?(:to_json)
|
|
253
|
+
str = to_json(state[:json_opts])
|
|
254
|
+
# #yajl_gen_number outputs a string without quotes around it
|
|
255
|
+
status = FFI_Yajl.yajl_gen_number(yajl_gen, str, str.bytesize)
|
|
256
|
+
else
|
|
257
|
+
str = to_s
|
|
258
|
+
status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize)
|
|
259
|
+
end
|
|
260
|
+
FFI_Yajl::Encoder.raise_error_for_status(status, str) if ( status ) != 0
|
|
261
|
+
end
|
|
262
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Copyright (c) 2015 Lamont Granquist
|
|
2
|
+
# Copyright (c) 2015-2018, Chef Software Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
module FFI_Yajl
|
|
24
|
+
module FFI
|
|
25
|
+
module Parser
|
|
26
|
+
def set_value(val) # rubocop:disable Naming/AccessorMethodName
|
|
27
|
+
case stack.last
|
|
28
|
+
when Hash
|
|
29
|
+
raise FFI_Yajl::ParseError, "internal error: missing key in parse" if key.nil?
|
|
30
|
+
if @opts[:unique_key_checking] && stack.last.key?(key)
|
|
31
|
+
raise FFI_Yajl::ParseError, "repeated key: #{key}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
stack.last[key] = val
|
|
35
|
+
when Array
|
|
36
|
+
stack.last.push(val)
|
|
37
|
+
else
|
|
38
|
+
stack.push(val)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def stack_pop
|
|
43
|
+
set_value( stack.pop ) if stack.length > 1
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def key_push
|
|
47
|
+
key_stack.push(key)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def key_pop
|
|
51
|
+
@key = key_stack.pop
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def setup_callbacks
|
|
55
|
+
@null_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
|
|
56
|
+
set_value(nil)
|
|
57
|
+
1
|
|
58
|
+
end
|
|
59
|
+
@boolean_callback = ::FFI::Function.new(:int, %i{pointer int}) do |ctx, boolval|
|
|
60
|
+
set_value(boolval == 1 ? true : false)
|
|
61
|
+
1
|
|
62
|
+
end
|
|
63
|
+
@integer_callback = ::FFI::Function.new(:int, %i{pointer long_long}) do |ctx, intval|
|
|
64
|
+
set_value(intval)
|
|
65
|
+
1
|
|
66
|
+
end
|
|
67
|
+
@number_callback = ::FFI::Function.new(:int, %i{pointer string size_t}) do |ctx, stringval, stringlen|
|
|
68
|
+
s = stringval.slice(0, stringlen)
|
|
69
|
+
s.force_encoding("UTF-8") if defined? Encoding
|
|
70
|
+
# XXX: I can't think of a better way to do this right now. need to call to_f if and only if its a float.
|
|
71
|
+
v = ( s =~ /[\.eE]/ ) ? s.to_f : s.to_i
|
|
72
|
+
set_value(v)
|
|
73
|
+
1
|
|
74
|
+
end
|
|
75
|
+
@double_callback = ::FFI::Function.new(:int, %i{pointer double}) do |ctx, doubleval|
|
|
76
|
+
set_value(doubleval)
|
|
77
|
+
1
|
|
78
|
+
end
|
|
79
|
+
@string_callback = ::FFI::Function.new(:int, %i{pointer string size_t}) do |ctx, stringval, stringlen|
|
|
80
|
+
s = stringval.slice(0, stringlen)
|
|
81
|
+
s.force_encoding("UTF-8") if defined? Encoding
|
|
82
|
+
set_value(s)
|
|
83
|
+
1
|
|
84
|
+
end
|
|
85
|
+
@start_map_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
|
|
86
|
+
key_push # for key => { } case, save the key
|
|
87
|
+
stack.push({})
|
|
88
|
+
1
|
|
89
|
+
end
|
|
90
|
+
@map_key_callback = ::FFI::Function.new(:int, %i{pointer string size_t}) do |ctx, key, keylen|
|
|
91
|
+
s = key.slice(0, keylen)
|
|
92
|
+
s.force_encoding("UTF-8") if defined? Encoding
|
|
93
|
+
self.key = @opts[:symbolize_keys] ? s.to_sym : s
|
|
94
|
+
1
|
|
95
|
+
end
|
|
96
|
+
@end_map_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
|
|
97
|
+
key_pop
|
|
98
|
+
stack_pop
|
|
99
|
+
1
|
|
100
|
+
end
|
|
101
|
+
@start_array_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
|
|
102
|
+
key_push # for key => [ ] case, save the key
|
|
103
|
+
stack.push([])
|
|
104
|
+
1
|
|
105
|
+
end
|
|
106
|
+
@end_array_callback = ::FFI::Function.new(:int, [:pointer]) do |ctx|
|
|
107
|
+
key_pop
|
|
108
|
+
stack_pop
|
|
109
|
+
1
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def do_yajl_parse(str, yajl_opts = {})
|
|
114
|
+
setup_callbacks
|
|
115
|
+
callback_ptr = ::FFI::MemoryPointer.new(::FFI_Yajl::YajlCallbacks)
|
|
116
|
+
callbacks = ::FFI_Yajl::YajlCallbacks.new(callback_ptr)
|
|
117
|
+
callbacks[:yajl_null] = @null_callback
|
|
118
|
+
callbacks[:yajl_boolean] = @boolean_callback
|
|
119
|
+
callbacks[:yajl_integer] = @integer_callback
|
|
120
|
+
callbacks[:yajl_double] = @double_callback
|
|
121
|
+
callbacks[:yajl_number] = @number_callback
|
|
122
|
+
callbacks[:yajl_string] = @string_callback
|
|
123
|
+
callbacks[:yajl_start_map] = @start_map_callback
|
|
124
|
+
callbacks[:yajl_map_key] = @map_key_callback
|
|
125
|
+
callbacks[:yajl_end_map] = @end_map_callback
|
|
126
|
+
callbacks[:yajl_start_array] = @start_array_callback
|
|
127
|
+
callbacks[:yajl_end_array] = @end_array_callback
|
|
128
|
+
yajl_handle = ::FFI_Yajl.yajl_alloc(callback_ptr, nil, nil)
|
|
129
|
+
|
|
130
|
+
# configure the yajl parser
|
|
131
|
+
if yajl_opts[:yajl_allow_comments]
|
|
132
|
+
::FFI_Yajl.yajl_config(yajl_handle, :yajl_allow_comments, :int, 1)
|
|
133
|
+
end
|
|
134
|
+
if yajl_opts[:yajl_dont_validate_strings]
|
|
135
|
+
::FFI_Yajl.yajl_config(yajl_handle, :yajl_dont_validate_strings, :int, 1)
|
|
136
|
+
end
|
|
137
|
+
if yajl_opts[:yajl_allow_trailing_garbage]
|
|
138
|
+
::FFI_Yajl.yajl_config(yajl_handle, :yajl_allow_trailing_garbage, :int, 1)
|
|
139
|
+
end
|
|
140
|
+
if yajl_opts[:yajl_allow_multiple_values]
|
|
141
|
+
::FFI_Yajl.yajl_config(yajl_handle, :yajl_allow_multiple_values, :int, 1)
|
|
142
|
+
end
|
|
143
|
+
if yajl_opts[:yajl_allow_partial_values]
|
|
144
|
+
::FFI_Yajl.yajl_config(yajl_handle, :yajl_allow_partial_values, :int, 1)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
if ::FFI_Yajl.yajl_parse(yajl_handle, str, str.bytesize) != :yajl_status_ok
|
|
148
|
+
# FIXME: dup the error and call yajl_free_error?
|
|
149
|
+
error = ::FFI_Yajl.yajl_get_error(yajl_handle, 1, str, str.bytesize)
|
|
150
|
+
raise ::FFI_Yajl::ParseError, error
|
|
151
|
+
end
|
|
152
|
+
if ::FFI_Yajl.yajl_complete_parse(yajl_handle) != :yajl_status_ok
|
|
153
|
+
# FIXME: dup the error and call yajl_free_error?
|
|
154
|
+
error = ::FFI_Yajl.yajl_get_error(yajl_handle, 1, str, str.bytesize)
|
|
155
|
+
raise ::FFI_Yajl::ParseError, error
|
|
156
|
+
end
|
|
157
|
+
stack.pop
|
|
158
|
+
ensure
|
|
159
|
+
::FFI_Yajl.yajl_free(yajl_handle) if yajl_handle
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|