xcodeproj 1.3.3 → 1.4.0

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