ffi-yajl 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b3576aa3b630817425565c2e7f18e03a6bf3144
4
- data.tar.gz: 0ba4867aafcbd1b5ed11e5aac09fb949d7fc28e2
3
+ metadata.gz: c235f85b05fe53002a80aabdbb3fcb9eaef46055
4
+ data.tar.gz: b4c886b8c0bdf41a77f1c38b5a7387031b063f2f
5
5
  SHA512:
6
- metadata.gz: 0437fb83e17971e61d8b07cc539de3184a7a5718471deeb91ffa57eac960519ab4429de20b944b9cb087ffee6138346c7e1cb2652ed62d8c794d7ca01f5e688f
7
- data.tar.gz: ddf01b4b3eeac328bdd8226acbc40648615f09ad6ab8662192e3774ee02c97203b65a61e78f69e8356e9c619fc5f6cac7191ed8b2ac5bd946618e3a10696cabb
6
+ metadata.gz: 3bbddb072b8f2da7e76eac038af416adfadbb765d077bdd54a794246d71bd8051726a5ebb3f4e4178e260ee7cde3f299d16bde585b276432bcdb98cca1a570ea
7
+ data.tar.gz: de43d07a727f67bb6c4d1816b813fc2c79531fb65e97e778b0ba41f424feaa3e25fcf7d3b99104c60f672b3e0da91c11a246af2ec1c6059a33bd5e4048b6821b
@@ -2,6 +2,7 @@
2
2
  #include <yajl/yajl_gen.h>
3
3
 
4
4
  static VALUE mFFI_Yajl, mExt, mEncoder, mEncoder2, cEncodeError;
5
+ static VALUE cDate, cTime, cDateTime;
5
6
  static VALUE cYajl_Gen;
6
7
 
7
8
  /* FIXME: the json gem does a whole bunch of indirection around monkeypatching... not sure if we need to as well... */
@@ -62,7 +63,6 @@ int rb_cHash_ffi_yajl_callback(VALUE key, VALUE val, VALUE extra) {
62
63
  VALUE state = rb_hash_aref(extra, rb_str_new2("state"));
63
64
  VALUE rb_yajl_gen = rb_hash_aref(extra, rb_str_new2("yajl_gen"));
64
65
 
65
-
66
66
  rb_hash_aset(state, rb_str_new2("processing_key"), Qtrue);
67
67
  rb_funcall(key, sym_ffi_yajl, 2, rb_yajl_gen, state);
68
68
  rb_hash_aset(state, rb_str_new2("processing_key"), Qfalse);
@@ -227,7 +227,8 @@ static VALUE rb_cString_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
227
227
  return Qnil;
228
228
  }
229
229
 
230
- static VALUE rb_cSymbol_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
230
+ /* calls #to_s on an object to encode it */
231
+ static VALUE object_to_s_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
231
232
  yajl_gen_status status;
232
233
  ID sym_to_s = rb_intern("to_s");
233
234
  VALUE str = rb_funcall(self, sym_to_s, 0);
@@ -241,6 +242,32 @@ static VALUE rb_cSymbol_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
241
242
  return Qnil;
242
243
  }
243
244
 
245
+ static VALUE rb_cSymbol_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
246
+ return object_to_s_ffi_yajl(self, rb_yajl_gen, state);
247
+ }
248
+
249
+ static VALUE rb_cDate_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
250
+ return object_to_s_ffi_yajl(self, rb_yajl_gen, state);
251
+ }
252
+
253
+ static VALUE rb_cTime_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
254
+ yajl_gen_status status;
255
+ ID sym_strftime = rb_intern("strftime");
256
+ VALUE str = rb_funcall(self, sym_strftime, 1, rb_str_new2("%Y-%m-%d %H:%M:%S %z"));
257
+ char *cptr = RSTRING_PTR(str);
258
+ int len = RSTRING_LEN(str);
259
+ struct yajl_gen_t *yajl_gen;
260
+ Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen);
261
+ CHECK_STATUS(
262
+ yajl_gen_string(yajl_gen, (unsigned char *)cptr, len)
263
+ );
264
+ return Qnil;
265
+ }
266
+
267
+ static VALUE rb_cDateTime_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
268
+ return object_to_s_ffi_yajl(self, rb_yajl_gen, state);
269
+ }
270
+
244
271
  static VALUE rb_cObject_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
245
272
  yajl_gen_status status;
246
273
  ID sym_to_json = rb_intern("to_json");
@@ -265,6 +292,10 @@ void Init_encoder() {
265
292
  cYajl_Gen = rb_define_class_under(mEncoder, "YajlGen", rb_cObject);
266
293
  rb_define_method(mEncoder, "do_yajl_encode", mEncoder_do_yajl_encode, 3);
267
294
 
295
+ cDate = rb_define_class("Date", rb_cObject);
296
+ cTime = rb_define_class("Time", rb_cObject);
297
+ cDateTime = rb_define_class("DateTime", cDate);
298
+
268
299
  rb_define_method(rb_cHash, "ffi_yajl", rb_cHash_ffi_yajl, 2);
269
300
  rb_define_method(rb_cArray, "ffi_yajl", rb_cArray_ffi_yajl, 2);
270
301
  rb_define_method(rb_cNilClass, "ffi_yajl", rb_cNilClass_ffi_yajl, 2);
@@ -275,6 +306,8 @@ void Init_encoder() {
275
306
  rb_define_method(rb_cFloat, "ffi_yajl", rb_cFloat_ffi_yajl, 2);
276
307
  rb_define_method(rb_cString, "ffi_yajl", rb_cString_ffi_yajl, 2);
277
308
  rb_define_method(rb_cSymbol, "ffi_yajl", rb_cSymbol_ffi_yajl, 2);
309
+ rb_define_method(cDate, "ffi_yajl", rb_cDate_ffi_yajl, 2);
310
+ rb_define_method(cTime, "ffi_yajl", rb_cTime_ffi_yajl, 2);
311
+ rb_define_method(cDateTime, "ffi_yajl", rb_cDateTime_ffi_yajl, 2);
278
312
  rb_define_method(rb_cObject, "ffi_yajl", rb_cObject_ffi_yajl, 2);
279
313
  }
280
-
@@ -8,6 +8,9 @@ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
8
8
  $CFLAGS = " -I#{Libyajl2.include_path} #{$CFLAGS}"
9
9
  $LDFLAGS = " -L#{Libyajl2.opt_path} #{$LDFLAGS}"
10
10
 
11
+ # remove "-Wl,--no-undefined" flag if existent to allow for loading with dlopen
12
+ $LDFLAGS.slice!("-Wl,--no-undefined")
13
+
11
14
  puts $CFLAGS
12
15
  puts $LDFLAGS
13
16
 
@@ -8,6 +8,9 @@ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
8
8
  $CFLAGS = "-I#{Libyajl2.include_path} #{$CFLAGS}"
9
9
  $LDFLAGS = "-L#{Libyajl2.opt_path} #{$LDFLAGS}"
10
10
 
11
+ # remove "-Wl,--no-undefined" flag if existent to allow for loading with dlopen
12
+ $LDFLAGS.slice!("-Wl,--no-undefined")
13
+
11
14
  puts $CFLAGS
12
15
  puts $LDFLAGS
13
16
 
data/lib/ffi_yajl/ext.rb CHANGED
@@ -4,28 +4,62 @@ require 'ffi_yajl/encoder'
4
4
  require 'ffi_yajl/parser'
5
5
  require 'ffi'
6
6
  require 'libyajl2'
7
- begin
8
- require 'fiddle'
9
- rescue LoadError
10
- end
11
7
 
12
8
  module FFI_Yajl
13
9
  # FIXME: DRY with ffi_yajl/ffi.rb
10
+ # FIXME: extract map_library_name from FFI and stop requiring it at the top level
11
+ # so that the C-library can be installed without FFI
14
12
  libname = ::FFI.map_library_name("yajl")
15
13
  libpath = File.expand_path(File.join(Libyajl2.opt_path, libname))
16
14
  libpath.gsub!(/dylib/, 'bundle')
17
15
  libpath = ::FFI.map_library_name("yajl") unless File.exist?(libpath)
18
- if defined?(Fiddle) && Fiddle.respond_to?(:dlopen)
19
- ::Fiddle.dlopen(libpath)
20
- else
21
- # deliberately convoluted delayed require here to avoid deprecation
22
- # warning from requiring dl
16
+
17
+ #
18
+ # FFS, what exactly was so wrong with DL.dlopen that ruby had to get rid of it???
19
+ #
20
+
21
+ def self.try_fiddle_dlopen(libpath)
22
+ require 'fiddle'
23
+ if defined?(Fiddle) && Fiddle.respond_to?(:dlopen)
24
+ ::Fiddle.dlopen(libpath)
25
+ true
26
+ else
27
+ false
28
+ end
29
+ rescue LoadError
30
+ return false
31
+ end
32
+
33
+ def self.try_dl_dlopen(libpath)
23
34
  require 'dl'
24
35
  if defined?(DL) && DL.respond_to?(:dlopen)
25
36
  ::DL.dlopen(libpath)
37
+ true
26
38
  else
27
- raise "cannot find dlopen in either DL or Fiddle, cannot proceed"
39
+ false
28
40
  end
41
+ rescue LoadError
42
+ return false
43
+ end
44
+
45
+ def self.try_ffi_dlopen(libpath)
46
+ require 'ffi'
47
+ require 'rbconfig'
48
+ extend ::FFI::Library
49
+ ffi_lib 'dl'
50
+ attach_function 'dlopen', :dlopen, [:string, :int], :void
51
+ if Config::CONFIG['host_os'] =~ /linux/i
52
+ dlopen libpath, 0x102 # linux: RTLD_GLOBAL | RTLD_NOW
53
+ else
54
+ dlopen libpath, 0
55
+ end
56
+ true
57
+ rescue LoadError
58
+ return false
59
+ end
60
+
61
+ unless try_fiddle_dlopen(libpath) || try_dl_dlopen(libpath) || try_ffi_dlopen(libpath)
62
+ raise "cannot find dlopen vi Fiddle, DL or FFI, what am I supposed to do?"
29
63
  end
30
64
 
31
65
  class Parser
@@ -38,4 +72,3 @@ module FFI_Yajl
38
72
  include FFI_Yajl::Ext::Encoder
39
73
  end
40
74
  end
41
-
@@ -171,6 +171,33 @@ class String
171
171
  end
172
172
  end
173
173
 
174
+ class Date
175
+ def ffi_yajl(yajl_gen, state)
176
+ str = self.to_s
177
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
178
+ FFI_Yajl::Encoder.raise_error_for_status(status)
179
+ end
180
+ end
181
+ end
182
+
183
+ class Time
184
+ def ffi_yajl(yajl_gen, state)
185
+ str = self.strftime "%Y-%m-%d %H:%M:%S %z"
186
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
187
+ FFI_Yajl::Encoder.raise_error_for_status(status)
188
+ end
189
+ end
190
+ end
191
+
192
+ class DateTime
193
+ def ffi_yajl(yajl_gen, state)
194
+ str = self.to_s
195
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
196
+ FFI_Yajl::Encoder.raise_error_for_status(status)
197
+ end
198
+ end
199
+ end
200
+
174
201
  # I feel dirty
175
202
  class Object
176
203
  def ffi_yajl(yajl_gen, state)
@@ -180,4 +207,3 @@ class Object
180
207
  end
181
208
  end
182
209
  end
183
-
@@ -101,6 +101,24 @@ class NilClass
101
101
  end
102
102
  end
103
103
 
104
+ class Date
105
+ def to_json(*opts, &block)
106
+ FFI_Yajl::Encoder.encode(self, *opts)
107
+ end
108
+ end
109
+
110
+ class Time
111
+ def to_json(*opts, &block)
112
+ FFI_Yajl::Encoder.encode(self, *opts)
113
+ end
114
+ end
115
+
116
+ class DateTime
117
+ def to_json(*opts, &block)
118
+ FFI_Yajl::Encoder.encode(self, *opts)
119
+ end
120
+ end
121
+
104
122
  module ::Kernel
105
123
  def JSON(object, opts = {})
106
124
  if object.respond_to? :to_s
@@ -118,4 +136,3 @@ class Object
118
136
  end
119
137
  end
120
138
  end
121
-
@@ -1,3 +1,3 @@
1
1
  module FFI_Yajl
2
- VERSION = "1.0.2"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,6 +1,7 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  require 'spec_helper'
4
+ require 'date'
4
5
 
5
6
  describe "FFI_Yajl::Encoder" do
6
7
 
@@ -60,4 +61,30 @@ describe "FFI_Yajl::Encoder" do
60
61
  end
61
62
  end
62
63
 
64
+ it "can encode Date objects" do
65
+ ruby = Date.parse('2001-02-03')
66
+ expect(encoder.encode(ruby)).to eq( %q{"2001-02-03"} )
67
+ end
68
+
69
+ context "when encoding Time objects in UTC timezone" do
70
+ before do
71
+ @saved_tz = ENV['TZ']
72
+ ENV['TZ'] = 'UTC'
73
+ end
74
+
75
+ after do
76
+ ENV['TZ'] = @saved_tz
77
+ end
78
+
79
+ it "encodes them correctly" do
80
+ ruby = Time.local(2001, 02, 02, 21, 05, 06)
81
+ expect(encoder.encode(ruby)).to eq( %q{"2001-02-02 21:05:06 +0000"} )
82
+ end
83
+ end
84
+
85
+ it "can encode DateTime objects" do
86
+ ruby = DateTime.parse('2001-02-03T04:05:06.1+07:00')
87
+ expect(encoder.encode(ruby)).to eq( %q{"2001-02-03T04:05:06+07:00"} )
88
+ end
89
+
63
90
  end
@@ -4,6 +4,7 @@
4
4
  # Kinda looks like they stole it from the JSON gem. I updated the syntax a lot.
5
5
 
6
6
  require 'spec_helper'
7
+ require 'date'
7
8
 
8
9
  class Dummy; end
9
10
 
@@ -148,19 +149,30 @@ describe "JSON Gem Compat API" do
148
149
  expect(d.to_json).to eq( %Q{"#{d.to_s}"} )
149
150
  end
150
151
 
151
- it "encodes Time values correctly" do
152
- t = Time.new
153
- expect(t.to_json).to eq( %Q{"#{t.to_s}"} )
152
+ context "when encoding Time objects in UTC timezone" do
153
+ before do
154
+ @saved_tz = ENV['TZ']
155
+ ENV['TZ'] = 'UTC'
156
+ end
157
+
158
+ after do
159
+ ENV['TZ'] = @saved_tz
160
+ end
161
+
162
+ it "encodes Time values correctly" do
163
+ t = Time.local(2001, 02, 02, 21, 05, 06)
164
+ expect(t.to_json).to eq( %Q{"2001-02-02 21:05:06 +0000"} )
165
+ end
154
166
  end
155
167
 
156
168
  it "encodes Date values correctly" do
157
- da = Date.new
158
- expect(da.to_json).to eq( %Q{"#{da.to_s}"} )
169
+ da = Date.parse('2001-02-03')
170
+ expect(da.to_json).to eq( %Q{"2001-02-03"} )
159
171
  end
160
172
 
161
173
  it "encodes DateTime values correctly" do
162
- dt = DateTime.new
163
- expect(dt.to_json).to eq( %Q{"#{dt.to_s}"} )
174
+ dt = DateTime.parse('2001-02-03T04:05:06.1+07:00')
175
+ expect(dt.to_json).to eq( %Q{"2001-02-03T04:05:06+07:00"} )
164
176
  end
165
177
  end
166
178
 
@@ -230,7 +242,6 @@ describe "JSON Gem Compat API" do
230
242
  it_behaves_like "handles encoding and parsing correctly"
231
243
  end
232
244
 
233
-
234
245
  context "when dealing with common UTF-8 symbols" do
235
246
  let(:ruby) { [ "© ≠ €! \01" ] }
236
247
  let(:json) { "[\"© ≠ €! \\u0001\"]" }
@@ -277,7 +288,6 @@ describe "JSON Gem Compat API" do
277
288
  end
278
289
  end
279
290
 
280
-
281
291
  context "when encoding basic types with #to_json" do
282
292
  it "Array#to_json should work" do
283
293
  expect([ "a", "b", "c" ].to_json).to eq(%Q{["a","b","c"]})
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-yajl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lamont Granquist
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-10 00:00:00.000000000 Z
11
+ date: 2014-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake