corefoundation 0.1.4 → 0.2.0

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.
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+
4
+
5
+
6
+ ## 0.2.0 - 2012-12-06
7
+ Add support for ruby 1.8.7 [tmaher]
8
+
9
+
10
+ ## 0.1.4 - 2012-10-16
11
+
12
+ Initial version
data/README.md CHANGED
@@ -31,7 +31,8 @@ If you use the raw api (eg `CF.CFArrayCreate`) then you're on your own.
31
31
 
32
32
  Compatibility
33
33
  =============
34
- Requires ruby 1.9 due to use of encoding related methods. Should work in MRI and jruby. Not compatible with rubinius due to rubinius' ffi implemenation not supporting certain features.
34
+
35
+ Should work in MRI 1.8.7 and above and jruby. Not compatible with rubinius due to rubinius' ffi implementation not supporting certain features. On 1.8.7 the `binary?` and `binary!` methods tag a string's binary-ness with a flag, on 1.9 these methods are just shortcuts for testing whether the encoding is Encoding::ASCII_8BIT
35
36
 
36
37
  License
37
38
  =======
@@ -1,4 +1,6 @@
1
1
  require 'ffi'
2
+ require 'iconv' if RUBY_VERSION < "1.9"
3
+
2
4
  require 'corefoundation/base'
3
5
  require 'corefoundation/null'
4
6
  require 'corefoundation/string'
@@ -8,4 +10,4 @@ require 'corefoundation/data'
8
10
  require 'corefoundation/dictionary'
9
11
  require 'corefoundation/number'
10
12
  require 'corefoundation/date'
11
- require 'corefoundation/extensions'
13
+ require 'corefoundation/extensions'
@@ -23,7 +23,11 @@ module CF
23
23
  # @return [String]
24
24
  def to_s
25
25
  ptr = CF.CFDataGetBytePtr(self)
26
- ptr.read_string(CF.CFDataGetLength(self)).force_encoding(Encoding::ASCII_8BIT)
26
+ if CF::String::HAS_ENCODING
27
+ ptr.read_string(CF.CFDataGetLength(self)).force_encoding(Encoding::ASCII_8BIT)
28
+ else
29
+ ptr.read_string(CF.CFDataGetLength(self))
30
+ end
27
31
  end
28
32
 
29
33
  # The size in bytes of the CFData
@@ -46,16 +46,93 @@ end
46
46
  # Ruby String class
47
47
  class String
48
48
  # Returns a {CF::String} or {CF::Data} representing the string.
49
- # If the string has the encoding ASCII_8BIt a {CF::Data} is returned, if not a {CF::String} is returned
49
+ # If {#binary?} returns true a {CF::Data} is returned, if not a {CF::String} is returned
50
50
  #
51
+ # If you want a {CF::Data} with the contents of a non binary string, use {#to_cf_data}
52
+ #
51
53
  # @return [CF::String, CF::Data]
52
54
  def to_cf
53
- if encoding == Encoding::ASCII_8BIT
54
- CF::Data.from_string self
55
- else
56
- CF::String.from_string self
55
+ self.binary? ? self.to_cf_data : self.to_cf_string
56
+ end
57
+
58
+ # @!method binary?
59
+ #
60
+ # used to determine whether {#to_cf} should return a {CF::String} or a {CF::Data}. On ruby 1.9 and above this simply
61
+ # checks whether the encoding is ascii-8bit or not.
62
+ #
63
+ # On ruby 1.8.7
64
+ #
65
+ # - A string is binary if you call {#binary!} with the default argument of true
66
+ # - A string is not binary if you call {#binary!} with the argument false
67
+ #
68
+ # If you have never called {#binary!} then a string is binary if Iconv does not think it is valid utf-8
69
+ # @return whether the string is handled as binary data or not
70
+ #
71
+ if '<3'.respond_to? :encoding
72
+ def binary?
73
+ encoding == Encoding::ASCII_8BIT
74
+ end
75
+ else
76
+ def binary?
77
+ unless defined? @cf_is_binary
78
+ begin
79
+ ::Iconv.conv('UTF-8', 'UTF-8', self)
80
+ return false if self.frozen?
81
+ @cf_is_binary = false
82
+ rescue Iconv::IllegalSequence
83
+ return true if self.frozen?
84
+ @cf_is_binary = true
85
+ end
86
+ end
87
+ @cf_is_binary
88
+ end
89
+ end
90
+
91
+ if '<3'.respond_to? :encoding
92
+ # On ruby 1.8.7 sets or clears the flag used by {#binary?}. On ruby 1.9 the string's encoding is forced.
93
+ # @see #binary?
94
+ #
95
+ # @note There is no advantage to using this over the standard encoding methods unless you wish to retain 1.8.7 compatibility
96
+ #
97
+ # @param [optional, Boolean, Encoding] bin On ruby 1.8.7 only boolean values are admissible. On ruby 1.9 you can pass a specific encoding to force.
98
+ # If you pass `true` then `Encoding::ASCII_BIT` is used, if you pass `false` then `Encoding::UTF_8`
99
+ #
100
+ def binary!(bin=true)
101
+ if bin == true
102
+ self.force_encoding Encoding::ASCII_8BIT
103
+ else
104
+ # default to utf-8
105
+ self.force_encoding( (bin == false) ? "UTF-8" : bin)
106
+ end
107
+ self
108
+ end
109
+ else
110
+ # On ruby 1.8.7 sets or clears the flag used by {#binary?}. On ruby 1.9 the string's encoding is forced.
111
+ # @see #binary?
112
+ #
113
+ # @note There is no advantage to using this over the standard encoding methods unless you wish to retain 1.8.7 compatibility
114
+ #
115
+ # @param [optional, Boolean, Encoding] bin On ruby 1.8.7 only boolean values are admissible. On ruby 1.9 you can pass a specific encoding to force.
116
+ # If you pass `true` then `Encoding::ASCII_BIT` is used, if you pass `false` then `Encoding::UTF_8`
117
+ #
118
+ def binary!(bin=true)
119
+ @cf_is_binary = !! bin
120
+ self
57
121
  end
58
122
  end
123
+
124
+ # Returns a {CF::String} representing the string
125
+ # @return [CF::String]
126
+ def to_cf_string
127
+ CF::String.from_string self
128
+ end
129
+
130
+ # Returns a {CF::Data} representing the string
131
+ # @return [CF::Data]
132
+ def to_cf_data
133
+ CF::Data.from_string self
134
+ end
135
+
59
136
  end
60
137
 
61
138
  # Ruby Time class
@@ -78,4 +155,4 @@ class Hash
78
155
  end
79
156
  end
80
157
  end
81
- end
158
+ end
@@ -20,14 +20,24 @@ module CF
20
20
  # The cfstring encoding for UTF8
21
21
  UTF8 = 0x08000100 #From cfstring.h
22
22
 
23
+ # workaround for ruby 1.8.7 compat
24
+ HAS_ENCODING = "foo".respond_to? "encode"
23
25
 
24
26
  # Creates a string from a ruby string
25
27
  # The string must be convertable to UTF-8
26
28
  #
27
29
  # @param [String] s
28
30
  # @return [CF::String]
29
- def self.from_string(s)
30
- s_utf = s.encode('UTF-8')
31
+ def self.from_string(s, src_encoding='UTF-8')
32
+ if HAS_ENCODING
33
+ s_utf = s.encode('UTF-8')
34
+ else
35
+ begin
36
+ s_utf = Iconv.conv('UTF-8', src_encoding, s.to_s)
37
+ rescue Iconv::IllegalSequence => e
38
+ return nil
39
+ end
40
+ end
31
41
  raw = CF.CFStringCreateWithBytes(nil, s_utf, s_utf.bytesize, UTF8, 0)
32
42
  raw.null? ? nil : new(raw).release_on_gc
33
43
  end
@@ -67,11 +77,15 @@ module CF
67
77
  bytes_used_buffer.read_long
68
78
  end
69
79
 
70
- buffer.read_string(bytes_used).force_encoding(Encoding::UTF_8)
80
+ if HAS_ENCODING
81
+ buffer.read_string(bytes_used).force_encoding(Encoding::UTF_8)
82
+ else
83
+ buffer.read_string(bytes_used)
84
+ end
71
85
  end
72
86
 
73
87
  alias_method :to_ruby, :to_s
74
88
 
75
89
  end
76
90
 
77
- end
91
+ end
@@ -1,4 +1,4 @@
1
1
  module CF
2
2
  # The current version string
3
- VERSION = "0.1.4"
3
+ VERSION = "0.2.0"
4
4
  end
@@ -7,7 +7,9 @@ describe CF::Data do
7
7
  it 'should return a binary ruby string' do
8
8
  ruby_string = subject.to_s
9
9
  ruby_string.should == 'A CF string'
10
- ruby_string.encoding.should == Encoding::ASCII_8BIT
10
+ if CF::String::HAS_ENCODING
11
+ ruby_string.encoding.should == Encoding::ASCII_8BIT
12
+ end
11
13
  end
12
14
  end
13
15
 
@@ -20,7 +22,9 @@ describe CF::Data do
20
22
  describe 'to_ruby' do
21
23
  it 'should behave like to_s' do
22
24
  subject.to_ruby.should == 'A CF string'
23
- subject.to_ruby.encoding.should == Encoding::ASCII_8BIT
25
+ if 'A CF string'.respond_to? "encoding"
26
+ subject.to_ruby.encoding.should == Encoding::ASCII_8BIT
27
+ end
24
28
  end
25
29
  end
26
30
  end
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require 'spec_helper'
2
3
 
3
4
  describe 'extensions' do
@@ -13,16 +14,79 @@ describe 'extensions' do
13
14
  end
14
15
  end
15
16
 
16
- context 'with a 8bit string' do
17
- it 'should return a cf data' do
18
- '123'.encode(Encoding::ASCII_8BIT).to_cf.should be_a(CF::Data)
17
+ describe String do
18
+ uber = [195, 188, 98, 101, 114]
19
+
20
+ describe 'to_cf' do
21
+
22
+ unless defined? RUBY_ENGINE and RUBY_ENGINE == 'jruby'
23
+ context 'with data incorrectly marked as non binary' do
24
+ it 'returns nil' do
25
+ [0xff, 0xff, 0xff].pack("C*").binary!(false).to_cf.should be_nil
26
+ end
27
+ end
28
+ end
29
+
30
+ context 'with a non binary string' do
31
+ it 'should return a cf string' do
32
+ '123'.to_cf.should be_a(CF::String)
33
+ end
34
+ end
35
+
36
+ context 'with a string marked as binary' do
37
+ it 'should return a cf data' do
38
+ '123'.binary!.to_cf.should be_a(CF::Data)
39
+ end
40
+ end
41
+
42
+ context 'with a binary string' do
43
+ it 'should return a cf data' do
44
+ [0xff, 0xff, 0xff].pack("C*").to_cf.should be_a(CF::Data)
45
+ end
46
+ end
47
+
48
+ context 'with a utf-8 string' do
49
+ it 'should return a cfstring' do
50
+ uber.pack("C*").should_not be_a(CF::String)
51
+ end
52
+ end
19
53
  end
20
- end
21
54
 
22
- context 'with an asciistring' do
23
- it 'should return a cf string' do
24
- '123'.to_cf.should be_a(CF::String)
55
+ describe 'binary?' do
56
+
57
+ it 'should return false on a plain ascii string' do
58
+ '123'.should_not be_binary
59
+ end
60
+
61
+ if CF::String::HAS_ENCODING
62
+ it 'should return false on valid utf data' do
63
+ "\xc3\xc9".should_not be_binary
64
+ end
65
+ else
66
+ it 'should return false on valid utf data' do
67
+ uber.pack("C*").should_not be_binary
68
+ end
69
+ end
70
+
71
+ it 'should return false on string forced to non binary' do
72
+ "\xc3\xc9".binary!(false).should_not be_binary
73
+ end
74
+
75
+ it 'should return true if binary! has been called' do
76
+ '123'.binary!.should be_binary
77
+ end
78
+
79
+ if CF::String::HAS_ENCODING
80
+ it 'should return true for ascii 8bit strings' do
81
+ '123'.encode(Encoding::ASCII_8BIT).should be_binary
82
+ end
83
+ else
84
+ it 'should return true for data that cannot be converted to utf8' do
85
+ "\xff\xff\xff".should be_binary
86
+ end
87
+ end
25
88
  end
89
+
26
90
  end
27
91
 
28
92
  context 'with true' do
@@ -60,4 +124,4 @@ describe 'extensions' do
60
124
  cf_hash['key_2'].should == CF::Boolean::FALSE
61
125
  end
62
126
  end
63
- end
127
+ end
@@ -9,10 +9,14 @@ describe CF::String do
9
9
 
10
10
  # The intent is to force feed CF::String with an invalid utf-8 string
11
11
  # but jruby doesn't seem to allow this to be constructed
12
- unless RUBY_ENGINE == 'jruby'
12
+ unless defined? RUBY_ENGINE and RUBY_ENGINE == 'jruby'
13
13
  context 'with invalid data' do
14
14
  it 'returns nil' do
15
- CF::String.from_string("\xff\xff\xff".force_encoding('UTF-8')).should be_nil
15
+ if CF::String::HAS_ENCODING
16
+ CF::String.from_string("\xff\xff\xff".force_encoding('UTF-8')).should be_nil
17
+ else
18
+ CF::String.from_string("\xff\xff\xff").should be_nil
19
+ end
16
20
  end
17
21
  end
18
22
  end
@@ -22,14 +26,19 @@ describe CF::String do
22
26
  it 'should return a utf ruby string' do
23
27
  ruby_string = CF::String.from_string('A CF string').to_s
24
28
  ruby_string.should == 'A CF string'
25
- ruby_string.encoding.should == Encoding::UTF_8
29
+ if CF::String::HAS_ENCODING
30
+ ruby_string.encoding.should == Encoding::UTF_8
31
+ else
32
+ end
26
33
  end
27
34
  end
28
35
 
29
36
  describe 'to_ruby' do
30
37
  it 'should behave like to_s' do
31
38
  CF::String.from_string('A CF string').to_ruby.should == 'A CF string'
32
- CF::String.from_string('A CF string').to_ruby.encoding.should == Encoding::UTF_8
39
+ if CF::String::HAS_ENCODING
40
+ CF::String.from_string('A CF string').to_ruby.encoding.should == Encoding::UTF_8
41
+ end
33
42
  end
34
43
  end
35
44
 
metadata CHANGED
@@ -1,150 +1,182 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: corefoundation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
5
- prerelease:
4
+ version: 0.2.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Frederick Cheung
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-16 00:00:00.000000000 Z
12
+ date: 2012-12-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
16
+ version_requirements: !ruby/object:Gem::Requirement
18
17
  requirements:
19
18
  - - ! '>='
20
19
  - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
20
+ version: !binary |-
21
+ MA==
25
22
  none: false
23
+ requirement: !ruby/object:Gem::Requirement
26
24
  requirements:
27
25
  - - ! '>='
28
26
  - !ruby/object:Gem::Version
29
- version: '0'
27
+ version: !binary |-
28
+ MA==
29
+ none: false
30
+ prerelease: false
31
+ type: :runtime
30
32
  - !ruby/object:Gem::Dependency
31
33
  name: rspec
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
+ version_requirements: !ruby/object:Gem::Requirement
34
35
  requirements:
35
36
  - - ~>
36
37
  - !ruby/object:Gem::Version
37
38
  version: '2.10'
38
- type: :development
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
39
  none: false
40
+ requirement: !ruby/object:Gem::Requirement
42
41
  requirements:
43
42
  - - ~>
44
43
  - !ruby/object:Gem::Version
45
44
  version: '2.10'
45
+ none: false
46
+ prerelease: false
47
+ type: :development
46
48
  - !ruby/object:Gem::Dependency
47
49
  name: rake
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
+ version_requirements: !ruby/object:Gem::Requirement
50
51
  requirements:
51
52
  - - ! '>='
52
53
  - !ruby/object:Gem::Version
53
- version: '0'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
54
+ version: !binary |-
55
+ MA==
57
56
  none: false
57
+ requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: !binary |-
62
+ MA==
63
+ none: false
64
+ prerelease: false
65
+ type: :development
62
66
  - !ruby/object:Gem::Dependency
63
67
  name: yard
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
68
+ version_requirements: !ruby/object:Gem::Requirement
66
69
  requirements:
67
70
  - - ! '>='
68
71
  - !ruby/object:Gem::Version
69
- version: '0'
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
72
+ version: !binary |-
73
+ MA==
73
74
  none: false
75
+ requirement: !ruby/object:Gem::Requirement
74
76
  requirements:
75
77
  - - ! '>='
76
78
  - !ruby/object:Gem::Version
77
- version: '0'
79
+ version: !binary |-
80
+ MA==
81
+ none: false
82
+ prerelease: false
83
+ type: :development
78
84
  - !ruby/object:Gem::Dependency
79
85
  name: redcarpet
80
- requirement: !ruby/object:Gem::Requirement
81
- none: false
86
+ version_requirements: !ruby/object:Gem::Requirement
82
87
  requirements:
83
88
  - - ! '>='
84
89
  - !ruby/object:Gem::Version
85
- version: '0'
86
- type: :development
87
- prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
90
+ version: !binary |-
91
+ MA==
89
92
  none: false
93
+ requirement: !ruby/object:Gem::Requirement
90
94
  requirements:
91
95
  - - ! '>='
92
96
  - !ruby/object:Gem::Version
93
- version: '0'
97
+ version: !binary |-
98
+ MA==
99
+ none: false
100
+ prerelease: false
101
+ type: :development
94
102
  description: ! 'FFI based Ruby wrappers for Core Foundation '
95
103
  email: frederick.cheung@gmail.com
96
104
  executables: []
97
105
  extensions: []
98
106
  extra_rdoc_files: []
99
107
  files:
100
- - lib/corefoundation/array.rb
101
- - lib/corefoundation/base.rb
102
- - lib/corefoundation/boolean.rb
103
- - lib/corefoundation/data.rb
104
- - lib/corefoundation/date.rb
105
- - lib/corefoundation/dictionary.rb
106
- - lib/corefoundation/extensions.rb
107
- - lib/corefoundation/null.rb
108
- - lib/corefoundation/number.rb
109
- - lib/corefoundation/string.rb
110
- - lib/corefoundation/version.rb
111
- - lib/corefoundation.rb
112
- - spec/array_spec.rb
113
- - spec/boolean_spec.rb
114
- - spec/data_spec.rb
115
- - spec/date_spec.rb
116
- - spec/dictionary_spec.rb
117
- - spec/extensions_spec.rb
118
- - spec/null_spec.rb
119
- - spec/number_spec.rb
120
- - spec/spec_helper.rb
121
- - spec/string_spec.rb
108
+ - !binary |-
109
+ bGliL2NvcmVmb3VuZGF0aW9uLnJi
110
+ - !binary |-
111
+ bGliL2NvcmVmb3VuZGF0aW9uL2FycmF5LnJi
112
+ - !binary |-
113
+ bGliL2NvcmVmb3VuZGF0aW9uL2Jhc2UucmI=
114
+ - !binary |-
115
+ bGliL2NvcmVmb3VuZGF0aW9uL2Jvb2xlYW4ucmI=
116
+ - !binary |-
117
+ bGliL2NvcmVmb3VuZGF0aW9uL2RhdGEucmI=
118
+ - !binary |-
119
+ bGliL2NvcmVmb3VuZGF0aW9uL2RhdGUucmI=
120
+ - !binary |-
121
+ bGliL2NvcmVmb3VuZGF0aW9uL2RpY3Rpb25hcnkucmI=
122
+ - !binary |-
123
+ bGliL2NvcmVmb3VuZGF0aW9uL2V4dGVuc2lvbnMucmI=
124
+ - !binary |-
125
+ bGliL2NvcmVmb3VuZGF0aW9uL251bGwucmI=
126
+ - !binary |-
127
+ bGliL2NvcmVmb3VuZGF0aW9uL251bWJlci5yYg==
128
+ - !binary |-
129
+ bGliL2NvcmVmb3VuZGF0aW9uL3N0cmluZy5yYg==
130
+ - !binary |-
131
+ bGliL2NvcmVmb3VuZGF0aW9uL3ZlcnNpb24ucmI=
132
+ - !binary |-
133
+ c3BlYy9hcnJheV9zcGVjLnJi
134
+ - !binary |-
135
+ c3BlYy9ib29sZWFuX3NwZWMucmI=
136
+ - !binary |-
137
+ c3BlYy9kYXRhX3NwZWMucmI=
138
+ - !binary |-
139
+ c3BlYy9kYXRlX3NwZWMucmI=
140
+ - !binary |-
141
+ c3BlYy9kaWN0aW9uYXJ5X3NwZWMucmI=
142
+ - !binary |-
143
+ c3BlYy9leHRlbnNpb25zX3NwZWMucmI=
144
+ - !binary |-
145
+ c3BlYy9udWxsX3NwZWMucmI=
146
+ - !binary |-
147
+ c3BlYy9udW1iZXJfc3BlYy5yYg==
148
+ - !binary |-
149
+ c3BlYy9zcGVjX2hlbHBlci5yYg==
150
+ - !binary |-
151
+ c3BlYy9zdHJpbmdfc3BlYy5yYg==
122
152
  - README.md
123
153
  - LICENSE
154
+ - CHANGELOG
124
155
  homepage: http://github.com/fcheung/corefoundation
125
156
  licenses:
126
157
  - MIT
127
- post_install_message:
158
+ post_install_message:
128
159
  rdoc_options: []
129
160
  require_paths:
130
161
  - lib
131
162
  required_ruby_version: !ruby/object:Gem::Requirement
132
- none: false
133
163
  requirements:
134
164
  - - ! '>='
135
165
  - !ruby/object:Gem::Version
136
- version: 1.9.2
137
- required_rubygems_version: !ruby/object:Gem::Requirement
166
+ version: 1.8.7
138
167
  none: false
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
169
  requirements:
140
170
  - - ! '>='
141
171
  - !ruby/object:Gem::Version
142
- version: '0'
172
+ version: !binary |-
173
+ MA==
174
+ none: false
143
175
  requirements: []
144
- rubyforge_project:
176
+ rubyforge_project:
145
177
  rubygems_version: 1.8.24
146
- signing_key:
178
+ signing_key:
147
179
  specification_version: 3
148
- summary: Ruby wrapper for OS X's corefoundation
180
+ summary: Ruby wrapper for OS X corefoundation
149
181
  test_files: []
150
- has_rdoc:
182
+ has_rdoc: