xcodeproj 1.3.3 → 1.4.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.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xcodeproj
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.3
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eloy Duran
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-20 00:00:00.000000000 Z
11
+ date: 2016-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3'
27
27
  - !ruby/object:Gem::Dependency
28
- name: colored
28
+ name: CFPropertyList
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.2'
33
+ version: 2.3.3
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.2'
40
+ version: 2.3.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: claide
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,6 +58,34 @@ dependencies:
58
58
  - - "<"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '2.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: colored
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.2'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.2'
75
+ - !ruby/object:Gem::Dependency
76
+ name: nanaimo
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 0.1.0
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 0.1.0
61
89
  description: Xcodeproj lets you create and modify Xcode projects from Ruby. Script
62
90
  boring management tasks or build Xcode-friendly libraries. Also includes support
63
91
  for Xcode workspaces (.xcworkspace) and configuration files (.xcconfig).
@@ -84,11 +112,6 @@ files:
84
112
  - lib/xcodeproj/gem_version.rb
85
113
  - lib/xcodeproj/helper.rb
86
114
  - lib/xcodeproj/plist.rb
87
- - lib/xcodeproj/plist/ffi.rb
88
- - lib/xcodeproj/plist/ffi/chdir_override.rb
89
- - lib/xcodeproj/plist/ffi/core_foundation.rb
90
- - lib/xcodeproj/plist/ffi/dev_tools_core.rb
91
- - lib/xcodeproj/plist/plist_gem.rb
92
115
  - lib/xcodeproj/project.rb
93
116
  - lib/xcodeproj/project/case_converter.rb
94
117
  - lib/xcodeproj/project/object.rb
@@ -150,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
173
  version: '0'
151
174
  requirements: []
152
175
  rubyforge_project:
153
- rubygems_version: 2.4.5.1
176
+ rubygems_version: 2.6.7
154
177
  signing_key:
155
178
  specification_version: 3
156
179
  summary: Create and modify Xcode projects from Ruby.
@@ -1,153 +0,0 @@
1
-
2
- module Xcodeproj
3
- module Plist
4
- # Provides support for loading and serializing property list files via
5
- # Fiddle and CoreFoundation / Xcode.
6
- #
7
- module FFI
8
- autoload :CoreFoundation, 'xcodeproj/plist/ffi/core_foundation'
9
- autoload :DevToolsCore, 'xcodeproj/plist/ffi/dev_tools_core'
10
-
11
- class << self
12
- # Attempts to load the `fiddle` and Xcode based plist serializer.
13
- #
14
- # @return [String,Nil] The loading error message, or `nil` if loading
15
- # was successful.
16
- #
17
- def attempt_to_load!
18
- return @attempt_to_load if defined?(@attempt_to_load)
19
- @attempt_to_load = begin
20
- require 'fiddle'
21
- nil
22
- rescue LoadError
23
- 'Xcodeproj relies on a library called `fiddle` to read and write ' \
24
- 'Xcode project files. Ensure your Ruby installation includes ' \
25
- '`fiddle` and try again.'
26
- end
27
- end
28
-
29
- # Serializes a hash as an XML property list file.
30
- #
31
- # @param [#to_hash] hash
32
- # The hash to store.
33
- #
34
- # @param [#to_s] path
35
- # The path of the file.
36
- #
37
- def write_to_path(hash, path)
38
- raise ThreadError, 'Can only write plists from the main thread.' unless Thread.current == Thread.main
39
-
40
- path = File.expand_path(path)
41
-
42
- should_fork = ENV['FORK_XCODE_WRITING']
43
- success = ruby_hash_write_xcode(hash, path, should_fork)
44
-
45
- unless success
46
- CoreFoundation.RubyHashPropertyListWrite(hash, path)
47
- fix_encoding(path)
48
- end
49
- end
50
-
51
- # @return [Hash] Returns the native objects loaded from a property list
52
- # file.
53
- #
54
- # @param [#to_s] path
55
- # The path of the file.
56
- #
57
- def read_from_path(path)
58
- CoreFoundation.RubyHashPropertyListRead(path)
59
- end
60
-
61
- private
62
-
63
- # Simple workaround to escape characters which are outside of ASCII
64
- # character-encoding. Relies on the fact that there are no XML characters
65
- # which would need to be escaped.
66
- #
67
- # @note This is necessary because Xcode (4.6 currently) uses the MacRoman
68
- # encoding unless the `// !$*UTF8*$!` magic comment is present. It
69
- # is not possible to serialize a plist using the NeXTSTEP format
70
- # without access to the private classes of Xcode and that comment
71
- # is not compatible with the XML format. For the complete
72
- # discussion see CocoaPods/CocoaPods#926.
73
- #
74
- #
75
- # @note Sadly this hack is not sufficient for supporting Emoji.
76
- #
77
- # @param [String, Pathname] The path of the file which needs to be fixed.
78
- #
79
- # @return [void]
80
- #
81
- def fix_encoding(filename)
82
- output = ''
83
- input = File.open(filename, 'rb', &:read)
84
- input.unpack('U*').each do |codepoint|
85
- if codepoint > 127 # ASCII is 7-bit, so 0-127 are valid characters
86
- output << "&##{codepoint};"
87
- else
88
- output << codepoint.chr
89
- end
90
- end
91
- File.open(filename, 'wb') { |file| file.write(output) }
92
- end
93
-
94
- # Serializes a hash as an ASCII plist, using Xcode.
95
- #
96
- # @param [Hash] hash
97
- # The hash to store.
98
- #
99
- # @param [String] path
100
- # The path of the file.
101
- #
102
- def ruby_hash_write_xcode(hash, path, should_fork)
103
- return false unless path.end_with?('pbxproj')
104
- if should_fork
105
- require 'open3'
106
- _output, status = Open3.capture2e(Gem.ruby, '-e', <<-RUBY, path, :stdin_data => Marshal.dump(hash))
107
- $LOAD_PATH.replace #{$LOAD_PATH}
108
- path = ARGV.first
109
- hash = Marshal.load(STDIN)
110
- require "xcodeproj"
111
- require "xcodeproj/plist/ffi"
112
- ffi = Xcodeproj::Plist::FFI
113
- success = ffi::DevToolsCore.load_xcode_frameworks && ffi.send(:ruby_hash_write_devtoolscore, hash, path)
114
- exit(success ? 0 : 1)
115
- RUBY
116
-
117
- status.success?
118
- else
119
- monkey_patch_chdir
120
- success = DevToolsCore.load_xcode_frameworks && ruby_hash_write_devtoolscore(hash, path)
121
-
122
- success
123
- end
124
- end
125
-
126
- def ruby_hash_write_devtoolscore(hash, path)
127
- success = true
128
-
129
- begin
130
- plist = DevToolsCore::CFDictionary.new(CoreFoundation.RubyHashToCFDictionary(hash))
131
- data = DevToolsCore::NSData.new(plist.plistDescriptionUTF8Data)
132
- success &= data.writeToFileAtomically(path)
133
-
134
- project = DevToolsCore::PBXProject.new(path)
135
- success &= project.writeToFileSystemProjectFile
136
- project.close
137
- rescue Fiddle::DLError
138
- success = false
139
- end
140
-
141
- success
142
- end
143
-
144
- def monkey_patch_chdir
145
- require 'xcodeproj/plist/ffi/chdir_override'
146
- class << Dir
147
- alias_method :chdir, :cp_chdir
148
- end
149
- end
150
- end
151
- end
152
- end
153
- end
@@ -1,27 +0,0 @@
1
- # Since Xcode 8 beta 4, calling `PBXProject.projectWithFile` breaks subsequent calls to
2
- # `chdir`. While sounding ridiculous, this is unfortunately true and debugging it from the
3
- # userland side showed no difference at all to successful calls to `chdir`, but the working
4
- # directory is simply not changed in the end. This workaround is even more absurd, monkey
5
- # patching all calls to `chdir` to use `__pthread_chdir` which appears to work.
6
- class Dir
7
- def self.cp_chdir(path)
8
- old_dir = Dir.getwd
9
- res = cp_actually_chdir(path)
10
-
11
- if block_given?
12
- begin
13
- return yield
14
- ensure
15
- cp_actually_chdir(old_dir)
16
- end
17
- end
18
-
19
- res
20
- end
21
-
22
- def self.cp_actually_chdir(path)
23
- libc = Fiddle.dlopen '/usr/lib/libc.dylib'
24
- f = Fiddle::Function.new(libc['__pthread_chdir'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
25
- f.call(path.to_s)
26
- end
27
- end
@@ -1,441 +0,0 @@
1
- require 'fiddle'
2
-
3
- module Xcodeproj
4
- module Plist
5
- module FFI
6
- # This module provides an interface to the CoreFoundation OS X framework.
7
- # Specifically it bridges the functions required to be able to read and write
8
- # property lists.
9
- #
10
- # Everything in here should be considered an implementation detail and thus is
11
- # not further documented.
12
- #
13
- # @todo Move this out into its own gem.
14
- #
15
- # @!visibility private
16
- #
17
- module CoreFoundation
18
- PATH = '/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation'
19
-
20
- # rubocop:disable Style/MethodName
21
- # rubocop:disable Style/VariableName
22
-
23
- # @!group Ruby hash as property list (de)serialization
24
- #---------------------------------------------------------------------------#
25
-
26
- def self.RubyHashPropertyListWrite(hash, path)
27
- url = CFURLCreateFromFileSystemRepresentation(NULL,
28
- path,
29
- path.bytesize,
30
- FALSE)
31
- stream = CFWriteStreamCreateWithFile(NULL, url)
32
- unless CFWriteStreamOpen(stream) == TRUE
33
- raise IOError, 'Unable to open stream.'
34
- end
35
-
36
- plist = RubyHashToCFDictionary(hash)
37
-
38
- error_ptr = CFTypeRefPointer()
39
- result = CFPropertyListWrite(plist,
40
- stream,
41
- KCFPropertyListXMLFormat_v1_0,
42
- 0,
43
- error_ptr)
44
- CFWriteStreamClose(stream)
45
-
46
- if result == 0
47
- description = CFCopyDescription(error_ptr.ptr)
48
- raise IOError, "Unable to write plist data: #{description}"
49
- end
50
- result
51
- end
52
-
53
- def self.RubyHashPropertyListRead(path)
54
- url = CFURLCreateFromFileSystemRepresentation(NULL,
55
- path,
56
- path.bytesize,
57
- FALSE)
58
- stream = CFReadStreamCreateWithFile(NULL, url)
59
- unless CFReadStreamOpen(stream) == TRUE
60
- raise IOError, 'Unable to open stream.'
61
- end
62
-
63
- error_ptr = CFTypeRefPointer()
64
- plist = CFPropertyListCreateWithStream(NULL,
65
- stream,
66
- 0,
67
- KCFPropertyListImmutable,
68
- NULL,
69
- error_ptr)
70
- CFReadStreamClose(stream)
71
-
72
- if plist.null?
73
- description = CFCopyDescription(error_ptr.ptr)
74
- raise IOError, "Unable to read plist data: #{description}"
75
- elsif CFGetTypeID(plist) != CFDictionaryGetTypeID()
76
- raise TypeError, 'Expected a plist with a dictionary root object.'
77
- end
78
-
79
- CFDictionaryToRubyHash(plist)
80
- end
81
-
82
- # @!group Types
83
- #---------------------------------------------------------------------------#
84
-
85
- # rubocop:disable Style/ConstantName
86
-
87
- NULL = Fiddle::NULL
88
-
89
- Void = Fiddle::TYPE_VOID
90
- VoidPointer = Fiddle::TYPE_VOIDP
91
- FunctionPointer = VoidPointer
92
-
93
- UInt32 = -Fiddle::TYPE_INT
94
- UInt8 = -Fiddle::TYPE_CHAR
95
-
96
- SInt32Pointer = VoidPointer
97
- UInt8Pointer = VoidPointer
98
- CharPointer = VoidPointer
99
-
100
- Boolean = Fiddle::TYPE_CHAR
101
- TRUE = 1
102
- FALSE = 0
103
-
104
- SINT64_MAX = 2**63 - 1
105
- SINT64_MIN = -SINT64_MAX - 1
106
-
107
- SIZEOF_SINT64 = 8
108
- SIZEOF_FLOAT64 = 8
109
-
110
- SINT64_PACK_TEMPLATE = 'q'
111
- FLOAT64_PACK_TEMPLATE = 'd'
112
-
113
- CFTypeRef = VoidPointer
114
- CFTypeRefPointer = VoidPointer
115
- CFIndex = Fiddle::TYPE_LONG
116
- CFTypeID = -Fiddle::TYPE_LONG
117
- CFOptionFlags = UInt32
118
-
119
- CFPropertyListMutabilityOptions = Fiddle::TYPE_INT
120
- KCFPropertyListImmutable = 0
121
-
122
- CFPropertyListFormat = Fiddle::TYPE_INT
123
- KCFPropertyListXMLFormat_v1_0 = 100
124
- CFPropertyListFormatPointer = VoidPointer
125
-
126
- CFStringEncoding = UInt32
127
- KCFStringEncodingUTF8 = 0x08000100
128
-
129
- CFNumberType = Fiddle::TYPE_INT
130
- KCFNumberSInt64Type = 4
131
- KCFNumberFloat64Type = 6
132
-
133
- # rubocop:enable Style/ConstantName
134
-
135
- private
136
-
137
- # @!group Helpers
138
- #---------------------------------------------------------------------------#
139
-
140
- def self.image
141
- @image ||= Fiddle.dlopen(PATH)
142
- end
143
-
144
- def self.free_function
145
- @free_function ||= Fiddle::Function.new(Fiddle::Handle.new['free'], [VoidPointer], Void)
146
- end
147
-
148
- def self.CFRelease_function
149
- @CFRelease ||= Fiddle::Function.new(image['CFRelease'], [CFTypeRef], Void)
150
- end
151
-
152
- def self.extern_image(image, symbol, parameter_types, return_type)
153
- symbol = symbol.to_s
154
- create_function = symbol.include?('Create')
155
- function_cache_key = "@__#{symbol}__"
156
-
157
- # Define a singleton method on the CoreFoundation module.
158
- define_singleton_method(symbol) do |*args|
159
- unless args.size == parameter_types.size
160
- raise ArgumentError, "wrong number of arguments (#{args.size} for " \
161
- "#{parameter_types.size})"
162
- end
163
-
164
- unless function = instance_variable_get(function_cache_key)
165
- function = Fiddle::Function.new(image[symbol],
166
- parameter_types,
167
- return_type)
168
- instance_variable_set(function_cache_key, function)
169
- end
170
-
171
- result = function.call(*args)
172
- create_function ? CFAutoRelease(result) : result
173
- end
174
- end
175
-
176
- def self.extern(symbol, parameter_types, return_type)
177
- extern_image(image, symbol, parameter_types, return_type)
178
- end
179
-
180
- public
181
-
182
- # @!group CoreFoundation function definitions
183
- #---------------------------------------------------------------------------#
184
-
185
- # CFTypeRef description
186
- extern :CFShow, [CFTypeRef], Void
187
- extern :CFCopyDescription, [CFTypeRef], CFTypeRef
188
-
189
- # CFType reflection
190
- extern :CFGetTypeID, [CFTypeRef], CFTypeID
191
- extern :CFDictionaryGetTypeID, [], CFTypeID
192
- extern :CFStringGetTypeID, [], CFTypeID
193
- extern :CFArrayGetTypeID, [], CFTypeID
194
- extern :CFBooleanGetTypeID, [], CFTypeID
195
- extern :CFNumberGetTypeID, [], CFTypeID
196
-
197
- # CFStream
198
- extern :CFWriteStreamCreateWithFile, [CFTypeRef, CFTypeRef], CFTypeRef
199
- extern :CFWriteStreamOpen, [CFTypeRef], Boolean
200
- extern :CFWriteStreamClose, [CFTypeRef], Void
201
- extern :CFReadStreamCreateWithFile, [CFTypeRef, CFTypeRef], CFTypeRef
202
- extern :CFReadStreamOpen, [CFTypeRef], Boolean
203
- extern :CFReadStreamClose, [CFTypeRef], Void
204
-
205
- # CFURL
206
- extern :CFURLCreateFromFileSystemRepresentation, [CFTypeRef, UInt8Pointer, CFIndex, Boolean], CFTypeRef
207
-
208
- # CFPropertyList
209
- extern :CFPropertyListWrite, [CFTypeRef, CFTypeRef, CFPropertyListFormat, CFOptionFlags, CFTypeRefPointer], CFIndex
210
- extern :CFPropertyListCreateWithStream, [CFTypeRef, CFTypeRef, CFIndex, CFOptionFlags, CFPropertyListFormatPointer, CFTypeRefPointer], CFTypeRef
211
-
212
- # CFString
213
- extern :CFStringCreateExternalRepresentation, [CFTypeRef, CFTypeRef, CFStringEncoding, UInt8], CFTypeRef
214
- extern :CFStringCreateWithCString, [CFTypeRef, CharPointer, CFStringEncoding], CFTypeRef
215
-
216
- # CFData
217
- extern :CFDataGetLength, [CFTypeRef], CFIndex
218
- extern :CFDataGetBytePtr, [CFTypeRef], VoidPointer
219
-
220
- # CFDictionary
221
- extern :CFDictionaryCreateMutable, [CFTypeRef, CFIndex, VoidPointer, VoidPointer], CFTypeRef
222
- extern :CFDictionaryAddValue, [CFTypeRef, CFTypeRef, CFTypeRef], VoidPointer
223
- extern :CFDictionaryApplyFunction, [CFTypeRef, FunctionPointer, VoidPointer], Void
224
-
225
- # CFArray
226
- extern :CFArrayCreateMutable, [CFTypeRef, CFIndex, VoidPointer], CFTypeRef
227
- extern :CFArrayAppendValue, [CFTypeRef, CFTypeRef], VoidPointer
228
- extern :CFArrayGetCount, [CFTypeRef], CFIndex
229
- extern :CFArrayGetValueAtIndex, [CFTypeRef, CFIndex], CFTypeRef
230
-
231
- # CFBoolean
232
- extern :CFBooleanGetValue, [CFTypeRef], Boolean
233
-
234
- # CFNumber
235
- extern :CFNumberIsFloatType, [CFTypeRef], Boolean
236
- extern :CFNumberGetValue, [CFTypeRef, CFNumberType, VoidPointer], Boolean
237
- extern :CFNumberCreate, [CFTypeRef, CFNumberType, VoidPointer], CFTypeRef
238
-
239
- # @!group Custom convenience functions
240
- #---------------------------------------------------------------------------#
241
-
242
- def self.CFBooleanTrue
243
- @CFBooleanTrue ||= Fiddle::Pointer.new(image['kCFBooleanTrue']).ptr
244
- end
245
-
246
- def self.CFBooleanFalse
247
- @CFBooleanFalse ||= Fiddle::Pointer.new(image['kCFBooleanFalse']).ptr
248
- end
249
-
250
- def self.CFTypeArrayCallBacks
251
- @CFTypeArrayCallBacks ||= image['kCFTypeArrayCallBacks']
252
- end
253
-
254
- def self.CFTypeDictionaryKeyCallBacks
255
- @CFTypeDictionaryKeyCallBacks ||= image['kCFTypeDictionaryKeyCallBacks']
256
- end
257
-
258
- def self.CFTypeDictionaryValueCallBacks
259
- @CFTypeDictionaryValueCallBacks ||= image['kCFTypeDictionaryValueCallBacks']
260
- end
261
-
262
- # This pointer will assign `CFRelease` as the free function when
263
- # dereferencing the pointer.
264
- #
265
- # @note This means that the object will *not* be released if it's not
266
- # dereferenced, but that would be a leak anyways, so be sure to do so.
267
- #
268
- def self.CFTypeRefPointer
269
- pointer = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INTPTR_T, free_function)
270
- def pointer.ptr
271
- ::CoreFoundation.CFAutoRelease(super)
272
- end
273
- pointer
274
- end
275
-
276
- def self.CFAutoRelease(cf_type_reference)
277
- cf_type_reference.free = CFRelease_function() unless cf_type_reference.null?
278
- cf_type_reference
279
- end
280
-
281
- def self.CFDictionaryApplyBlock(dictionary, &applier)
282
- param_types = [CFTypeRef, CFTypeRef, VoidPointer]
283
- closure = Fiddle::Closure::BlockCaller.new(Void, param_types, &applier)
284
- closure_function = Fiddle::Function.new(closure, param_types, Void)
285
- CFDictionaryApplyFunction(dictionary, closure_function, NULL)
286
- end
287
-
288
- def self.CFArrayApplyBlock(array)
289
- CFArrayGetCount(array).times do |index|
290
- yield CFArrayGetValueAtIndex(array, index)
291
- end
292
- end
293
-
294
- # @!group CFTypeRef to Ruby value conversion
295
- #---------------------------------------------------------------------------#
296
-
297
- def self.CFTypeRefToRubyValue(cf_type_reference)
298
- case CFGetTypeID(cf_type_reference)
299
- when CFStringGetTypeID()
300
- CFStringToRubyString(cf_type_reference)
301
- when CFDictionaryGetTypeID()
302
- CFDictionaryToRubyHash(cf_type_reference)
303
- when CFArrayGetTypeID()
304
- CFArrayToRubyArray(cf_type_reference)
305
- when CFBooleanGetTypeID()
306
- CFBooleanToRubyBoolean(cf_type_reference)
307
- when CFNumberGetTypeID()
308
- CFNumberToRubyNumber(cf_type_reference)
309
- else
310
- description = CFStringToRubyString(CFCopyDescription(cf_type_reference))
311
- raise TypeError, "Unknown type: #{description}"
312
- end
313
- end
314
-
315
- def self.CFStringToRubyString(string)
316
- data = CFStringCreateExternalRepresentation(NULL,
317
- string,
318
- KCFStringEncodingUTF8,
319
- 0)
320
- if data.null?
321
- raise TypeError, 'Unable to convert CFStringRef.'
322
- end
323
- bytes_ptr = CFDataGetBytePtr(data)
324
- result = bytes_ptr.to_str(CFDataGetLength(data))
325
- result.force_encoding(Encoding::UTF_8)
326
- result
327
- end
328
-
329
- def self.CFDictionaryToRubyHash(dictionary)
330
- result = {}
331
- CFDictionaryApplyBlock(dictionary) do |key, value|
332
- result[CFStringToRubyString(key)] = CFTypeRefToRubyValue(value)
333
- end
334
- result
335
- end
336
-
337
- def self.CFArrayToRubyArray(array)
338
- result = []
339
- CFArrayApplyBlock(array) do |element|
340
- result << CFTypeRefToRubyValue(element)
341
- end
342
- result
343
- end
344
-
345
- def self.CFBooleanToRubyBoolean(boolean)
346
- CFBooleanGetValue(boolean) == TRUE
347
- end
348
-
349
- def self.CFNumberToRubyNumber(number)
350
- if CFNumberIsFloatType(number) == FALSE
351
- value_type = KCFNumberSInt64Type
352
- pack_template = SINT64_PACK_TEMPLATE
353
- size = SIZEOF_SINT64
354
- else
355
- value_type = KCFNumberFloat64Type
356
- pack_template = FLOAT64_PACK_TEMPLATE
357
- size = SIZEOF_FLOAT64
358
- end
359
- ptr = Fiddle::Pointer.malloc(size)
360
- CFNumberGetValue(number, value_type, ptr)
361
- ptr.to_str.unpack(pack_template).first
362
- end
363
-
364
- # @!group Ruby value to CFTypeRef conversion
365
- #---------------------------------------------------------------------------#
366
-
367
- def self.RubyValueToCFTypeRef(value)
368
- result = case value
369
- when String
370
- RubyStringToCFString(value)
371
- when Hash
372
- RubyHashToCFDictionary(value)
373
- when Array
374
- RubyArrayToCFArray(value)
375
- when true, false
376
- RubyBooleanToCFBoolean(value)
377
- when Numeric
378
- RubyNumberToCFNumber(value)
379
- else
380
- RubyStringToCFString(value.to_s)
381
- end
382
- if result.null?
383
- raise TypeError, "Unable to convert Ruby value `#{value.inspect}' " \
384
- 'into a CFTypeRef.'
385
- end
386
- result
387
- end
388
-
389
- def self.RubyStringToCFString(string)
390
- CFStringCreateWithCString(NULL,
391
- Fiddle::Pointer[string.encode('UTF-8')],
392
- KCFStringEncodingUTF8)
393
- end
394
-
395
- def self.RubyHashToCFDictionary(hash)
396
- result = CFDictionaryCreateMutable(NULL,
397
- 0,
398
- CFTypeDictionaryKeyCallBacks(),
399
- CFTypeDictionaryValueCallBacks())
400
- hash.each do |key, value|
401
- key = RubyStringToCFString(key.to_s)
402
- value = RubyValueToCFTypeRef(value)
403
- CFDictionaryAddValue(result, key, value)
404
- end
405
- result
406
- end
407
-
408
- def self.RubyArrayToCFArray(array)
409
- result = CFArrayCreateMutable(NULL, 0, CFTypeArrayCallBacks())
410
- array.each do |element|
411
- element = RubyValueToCFTypeRef(element)
412
- CFArrayAppendValue(result, element)
413
- end
414
- result
415
- end
416
-
417
- def self.RubyNumberToCFNumber(value)
418
- case value
419
- when Float
420
- value_type = KCFNumberFloat64Type
421
- pack_template = FLOAT64_PACK_TEMPLATE
422
- when SINT64_MIN..SINT64_MAX
423
- value_type = KCFNumberSInt64Type
424
- pack_template = SINT64_PACK_TEMPLATE
425
- else # the value is too big to be stored in a CFNumber so store it as a CFString
426
- return RubyStringToCFString(value.to_s)
427
- end
428
- ptr = Fiddle::Pointer.to_ptr([value].pack(pack_template))
429
- CFNumberCreate(NULL, value_type, ptr)
430
- end
431
-
432
- def self.RubyBooleanToCFBoolean(value)
433
- value ? CFBooleanTrue() : CFBooleanFalse()
434
- end
435
-
436
- # rubocop:enable Style/MethodName
437
- # rubocop:enable Style/VariableName
438
- end
439
- end
440
- end
441
- end