corefoundation 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: