xcodeproj 1.3.3 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/xcodeproj/gem_version.rb +1 -1
- data/lib/xcodeproj/plist.rb +25 -27
- data/lib/xcodeproj/project.rb +19 -1
- data/lib/xcodeproj/project/object.rb +25 -3
- data/lib/xcodeproj/project/object/build_configuration.rb +52 -0
- data/lib/xcodeproj/project/object/build_file.rb +4 -0
- data/lib/xcodeproj/project/object/build_phase.rb +8 -0
- data/lib/xcodeproj/project/object/build_rule.rb +4 -0
- data/lib/xcodeproj/project/object/configuration_list.rb +9 -0
- data/lib/xcodeproj/project/object/container_item_proxy.rb +26 -3
- data/lib/xcodeproj/project/object/file_reference.rb +7 -1
- data/lib/xcodeproj/project/object/group.rb +4 -0
- data/lib/xcodeproj/project/object/reference_proxy.rb +4 -0
- data/lib/xcodeproj/project/object/root_object.rb +14 -0
- data/lib/xcodeproj/project/object/target_dependency.rb +4 -0
- data/lib/xcodeproj/project/object_dictionary.rb +5 -1
- metadata +34 -11
- data/lib/xcodeproj/plist/ffi.rb +0 -153
- data/lib/xcodeproj/plist/ffi/chdir_override.rb +0 -27
- data/lib/xcodeproj/plist/ffi/core_foundation.rb +0 -441
- data/lib/xcodeproj/plist/ffi/dev_tools_core.rb +0 -194
- data/lib/xcodeproj/plist/plist_gem.rb +0 -27
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.
|
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-
|
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:
|
28
|
+
name: CFPropertyList
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
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:
|
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.
|
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.
|
data/lib/xcodeproj/plist/ffi.rb
DELETED
@@ -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
|