og-corefoundation 0.2.1
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.
- checksums.yaml +7 -0
- data/CHANGELOG +14 -0
- data/LICENSE +8 -0
- data/README.md +41 -0
- data/lib/corefoundation/array.rb +123 -0
- data/lib/corefoundation/base.rb +197 -0
- data/lib/corefoundation/boolean.rb +25 -0
- data/lib/corefoundation/data.rb +42 -0
- data/lib/corefoundation/date.rb +32 -0
- data/lib/corefoundation/dictionary.rb +114 -0
- data/lib/corefoundation/extensions.rb +158 -0
- data/lib/corefoundation/null.rb +11 -0
- data/lib/corefoundation/number.rb +98 -0
- data/lib/corefoundation/string.rb +91 -0
- data/lib/corefoundation/version.rb +4 -0
- data/lib/corefoundation.rb +13 -0
- data/spec/array_spec.rb +92 -0
- data/spec/boolean_spec.rb +24 -0
- data/spec/data_spec.rb +30 -0
- data/spec/date_spec.rb +25 -0
- data/spec/dictionary_spec.rb +81 -0
- data/spec/extensions_spec.rb +127 -0
- data/spec/null_spec.rb +7 -0
- data/spec/number_spec.rb +52 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/string_spec.rb +48 -0
- metadata +137 -0
@@ -0,0 +1,158 @@
|
|
1
|
+
# Rubyinteger
|
2
|
+
class Integer
|
3
|
+
# Converts the Integer to a {CF::Number} using {CF::Number.from_i}
|
4
|
+
# @return [CF::Number]
|
5
|
+
def to_cf
|
6
|
+
CF::Number.from_i(self)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Ruby float class
|
11
|
+
class Float
|
12
|
+
# Converts the Float to a {CF::Number} using {CF::Number.from_f}
|
13
|
+
# @return [CF::Number]
|
14
|
+
def to_cf
|
15
|
+
CF::Number.from_f(self)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Ruby array class
|
20
|
+
class Array
|
21
|
+
# Converts the Array to an immutable {CF::Array} by calling `to_cf` on each element it contains
|
22
|
+
# @return [CF::Number]
|
23
|
+
def to_cf
|
24
|
+
CF::Array.immutable(collect(&:to_cf))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Ruby true class
|
29
|
+
class TrueClass
|
30
|
+
# Returns a CF::Boolean object representing true
|
31
|
+
# @return [CF::Boolean]
|
32
|
+
def to_cf
|
33
|
+
CF::Boolean::TRUE
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Ruby false class
|
38
|
+
class FalseClass
|
39
|
+
# Returns a CF::Boolean object representing false
|
40
|
+
# @return [CF::Boolean]
|
41
|
+
def to_cf
|
42
|
+
CF::Boolean::FALSE
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Ruby String class
|
47
|
+
class String
|
48
|
+
# Returns a {CF::String} or {CF::Data} representing the string.
|
49
|
+
# If {#binary?} returns true a {CF::Data} is returned, if not a {CF::String} is returned
|
50
|
+
#
|
51
|
+
# If you want a {CF::Data} with the contents of a non binary string, use {#to_cf_data}
|
52
|
+
#
|
53
|
+
# @return [CF::String, CF::Data]
|
54
|
+
def to_cf
|
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
|
121
|
+
end
|
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
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
# Ruby Time class
|
139
|
+
class Time
|
140
|
+
# Returns a {CF::Date} representing the time.
|
141
|
+
# @return [CF::Date]
|
142
|
+
def to_cf
|
143
|
+
CF::Date.from_time(self)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Ruby Hash class
|
148
|
+
class Hash
|
149
|
+
# Converts the Hash to an mutable {CF::Dictionary} by calling `to_cf` on each key and value it contains
|
150
|
+
# @return [CF::Dictionary]
|
151
|
+
def to_cf
|
152
|
+
CF::Dictionary.mutable.tap do |r|
|
153
|
+
each do |k,v|
|
154
|
+
r[k.to_cf] = v.to_cf
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module CF
|
2
|
+
typedef :pointer, :cfnumberref
|
3
|
+
enum :cf_number_type, [
|
4
|
+
:kCFNumberSInt8Type,1,
|
5
|
+
:kCFNumberSInt16Type,2,
|
6
|
+
:kCFNumberSInt32Type,3,
|
7
|
+
:kCFNumberSInt64Type,4,
|
8
|
+
:kCFNumberFloat32Type,5,
|
9
|
+
:kCFNumberFloat64Type,6,
|
10
|
+
:kCFNumberCharType,7,
|
11
|
+
:kCFNumberShortType,8,
|
12
|
+
:kCFNumberIntType,9,
|
13
|
+
:kCFNumberLongType,10,
|
14
|
+
:kCFNumberLongLongType,11,
|
15
|
+
:kCFNumberFloatType,12,
|
16
|
+
:kCFNumberDoubleType,13,
|
17
|
+
:kCFNumberCFIndexType,14,
|
18
|
+
:kCFNumberNSIntegerType,15,
|
19
|
+
:kCFNumberCGFloatType,16,
|
20
|
+
:kCFNumberMaxType,16
|
21
|
+
]
|
22
|
+
|
23
|
+
attach_function 'CFNumberGetValue', [:cfnumberref, :cf_number_type, :pointer], :uchar
|
24
|
+
attach_function 'CFNumberCreate', [:pointer, :cf_number_type, :pointer], :cfnumberref
|
25
|
+
attach_function 'CFNumberIsFloatType', [:pointer], :uchar
|
26
|
+
attach_function 'CFNumberCompare', [:cfnumberref, :cfnumberref, :pointer], :cfcomparisonresult
|
27
|
+
|
28
|
+
# Wrapper for CFNumberRef
|
29
|
+
#
|
30
|
+
#
|
31
|
+
class Number < Base
|
32
|
+
register_type 'CFNumber'
|
33
|
+
include Comparable
|
34
|
+
|
35
|
+
|
36
|
+
# Constructs a CF::Number from a float
|
37
|
+
# @param [Float] float
|
38
|
+
# @return [CF::Number]
|
39
|
+
def self.from_f(float)
|
40
|
+
p = FFI::MemoryPointer.new(:double)
|
41
|
+
p.write_double(float.to_f)
|
42
|
+
new(CF.CFNumberCreate(nil, :kCFNumberDoubleType, p)).release_on_gc
|
43
|
+
end
|
44
|
+
|
45
|
+
# Constructs a CF::Number from an integer
|
46
|
+
# @param [Integer] int
|
47
|
+
# @return [CF::Number]
|
48
|
+
def self.from_i(int)
|
49
|
+
p = FFI::MemoryPointer.new(:int64)
|
50
|
+
p.put_int64(0,int.to_i)
|
51
|
+
new(CF.CFNumberCreate(nil, :kCFNumberSInt64Type, p)).release_on_gc
|
52
|
+
end
|
53
|
+
|
54
|
+
# Compares the receiver with the argument
|
55
|
+
# @param [CF::Number] other
|
56
|
+
# @return [Integer]
|
57
|
+
def <=>(other)
|
58
|
+
raise TypeError, "argument should be CF::Number" unless other.is_a?(CF::Number)
|
59
|
+
CF.CFNumberCompare(self,other,nil)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# Converts the CF::Number to either an Integer or a Float, depending on the result of CFNumberIsFloatType
|
64
|
+
#
|
65
|
+
# @return [Integer, Float]
|
66
|
+
def to_ruby
|
67
|
+
if CF.CFNumberIsFloatType(self) == 0
|
68
|
+
to_i
|
69
|
+
else
|
70
|
+
to_f
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Converts the CF::Number to an integer
|
75
|
+
# May raise if the conversion cannot be done without loss of precision
|
76
|
+
# @return [Integer]
|
77
|
+
def to_i
|
78
|
+
p = FFI::MemoryPointer.new(:int64)
|
79
|
+
if CF.CFNumberGetValue(self, :kCFNumberSInt64Type, p) != 0
|
80
|
+
p.get_int64 0
|
81
|
+
else
|
82
|
+
raise "CF.CFNumberGetValue failed to convert #{self.inspect} to kCFNumberSInt64Type"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Converts the CF::Number to a float
|
87
|
+
# May raise if the conversion cannot be done without loss of precision
|
88
|
+
# @return [Float]
|
89
|
+
def to_f
|
90
|
+
p = FFI::MemoryPointer.new(:double)
|
91
|
+
if CF.CFNumberGetValue(self, :kCFNumberDoubleType, p) != 0
|
92
|
+
p.read_double
|
93
|
+
else
|
94
|
+
raise "CF.CFNumberGetValue failed to convert #{self.inspect} to kCFNumberDoubleType"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module CF
|
2
|
+
typedef :pointer, :cfstringref
|
3
|
+
|
4
|
+
attach_function 'CFStringCreateWithBytes', [:pointer, :buffer_in, :cfindex, :uint, :char], :cfstringref
|
5
|
+
attach_function 'CFStringGetBytes', [:cfstringref, :uint], :pointer
|
6
|
+
attach_function 'CFStringGetMaximumSizeForEncoding', [:cfindex, :uint], :cfindex
|
7
|
+
attach_function 'CFStringGetLength', [:cfstringref], :cfindex
|
8
|
+
|
9
|
+
attach_function 'CFStringGetBytes', [:cfstringref, CF::Range.by_value, :uint, :uchar, :char, :buffer_out, :cfindex, :buffer_out], :cfindex
|
10
|
+
|
11
|
+
attach_function 'CFStringCompare', [:cfstringref, :cfstringref, :cfoptionflags], :cfcomparisonresult
|
12
|
+
|
13
|
+
# Wrapper class for CFString
|
14
|
+
#
|
15
|
+
# Unlike ruby, CFString is not an arbitrary bag of bytes - the data will be converted to a collection of unicode characters
|
16
|
+
class String < Base
|
17
|
+
include Comparable
|
18
|
+
register_type("CFString")
|
19
|
+
|
20
|
+
# The cfstring encoding for UTF8
|
21
|
+
UTF8 = 0x08000100 #From cfstring.h
|
22
|
+
|
23
|
+
# workaround for ruby 1.8.7 compat
|
24
|
+
HAS_ENCODING = "foo".respond_to? "encode"
|
25
|
+
|
26
|
+
# Creates a string from a ruby string
|
27
|
+
# The string must be convertable to UTF-8
|
28
|
+
#
|
29
|
+
# @param [String] s
|
30
|
+
# @return [CF::String]
|
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
|
41
|
+
raw = CF.CFStringCreateWithBytes(nil, s_utf, s_utf.bytesize, UTF8, 0)
|
42
|
+
raw.null? ? nil : new(raw).release_on_gc
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the length, in unicode characters of the string
|
46
|
+
# @return [Integer]
|
47
|
+
def length
|
48
|
+
CF.CFStringGetLength(self)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Compares the receiver with the argument
|
52
|
+
# @param [CF::String] other
|
53
|
+
# @return [Integer]
|
54
|
+
def <=>(other)
|
55
|
+
Base.check_cftype(other)
|
56
|
+
CF.CFStringCompare(self,other,0)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Converts the CF::String to a UTF-8 ruby string
|
60
|
+
#
|
61
|
+
# @return [String]
|
62
|
+
def to_s
|
63
|
+
max_size = CF.CFStringGetMaximumSizeForEncoding(length, UTF8)
|
64
|
+
range = CF::Range.new
|
65
|
+
range[:location] = 0
|
66
|
+
range[:length] = length
|
67
|
+
buffer = FFI::MemoryPointer.new(:char, max_size)
|
68
|
+
|
69
|
+
cfindex = CF.find_type(:cfindex)
|
70
|
+
bytes_used_buffer = FFI::MemoryPointer.new(cfindex)
|
71
|
+
|
72
|
+
CF.CFStringGetBytes(self, range, UTF8, 0, 0, buffer, max_size, bytes_used_buffer)
|
73
|
+
|
74
|
+
bytes_used = if cfindex == CF.find_type(:long_long)
|
75
|
+
bytes_used_buffer.read_long_long
|
76
|
+
else
|
77
|
+
bytes_used_buffer.read_long
|
78
|
+
end
|
79
|
+
|
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
|
85
|
+
end
|
86
|
+
|
87
|
+
alias_method :to_ruby, :to_s
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'iconv' if RUBY_VERSION < "1.9"
|
3
|
+
|
4
|
+
require 'corefoundation/base'
|
5
|
+
require 'corefoundation/null'
|
6
|
+
require 'corefoundation/string'
|
7
|
+
require 'corefoundation/array'
|
8
|
+
require 'corefoundation/boolean'
|
9
|
+
require 'corefoundation/data'
|
10
|
+
require 'corefoundation/dictionary'
|
11
|
+
require 'corefoundation/number'
|
12
|
+
require 'corefoundation/date'
|
13
|
+
require 'corefoundation/extensions'
|
data/spec/array_spec.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CF::Array do
|
4
|
+
describe 'mutable' do
|
5
|
+
subject { CF::Array.mutable}
|
6
|
+
|
7
|
+
it { should be_a(CF::Array)}
|
8
|
+
it { should be_mutable}
|
9
|
+
|
10
|
+
describe '[]=' do
|
11
|
+
it 'should raise when trying to store a non cf value' do
|
12
|
+
expect {subject[0] = 123}.to raise_error(TypeError)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '<<' do
|
17
|
+
it 'should raise when trying to store a non cf value' do
|
18
|
+
expect {subject << 123}.to raise_error(TypeError)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'immutable' do
|
25
|
+
it 'should raise if all of the array elements are not cf values' do
|
26
|
+
expect {CF::Array.immutable([CF::Boolean::TRUE, 1])}.to raise_error(TypeError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should return an immutable cfarray' do
|
30
|
+
CF::Array.immutable([CF::Boolean::TRUE]).should be_a(CF::Array)
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'with an immutable array' do
|
34
|
+
subject { CF::Array.immutable([CF::Boolean::TRUE, CF::String.from_string('123')])}
|
35
|
+
|
36
|
+
describe '[]=' do
|
37
|
+
it 'should raise TypeError' do
|
38
|
+
expect {subject[0] = CF::Boolean::TRUE}.to raise_error(TypeError)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '<<' do
|
43
|
+
it 'should raise TypeError' do
|
44
|
+
expect {subject << CF::Boolean::TRUE}.to raise_error(TypeError)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with an array" do
|
51
|
+
subject { CF::Array.immutable([CF::Boolean::TRUE, CF::String.from_string('123')])}
|
52
|
+
|
53
|
+
describe '[]' do
|
54
|
+
it 'should return the typecast value at the index' do
|
55
|
+
subject[1].should be_a(CF::String)
|
56
|
+
subject[1].should == CF::String.from_string('123')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
describe 'length' do
|
62
|
+
it 'should return the count of items in the dictionary' do
|
63
|
+
subject.length.should == 2
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'to_ruby' do
|
68
|
+
it 'should return the result of calling to ruby on its contents' do
|
69
|
+
subject.to_ruby.should == [true, '123']
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'each' do
|
74
|
+
it 'should iterate over each value' do
|
75
|
+
values = []
|
76
|
+
subject.each do |v|
|
77
|
+
values << v
|
78
|
+
end
|
79
|
+
values[0].should == CF::Boolean::TRUE
|
80
|
+
values[1].should == CF::String.from_string('123')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should be enumerable' do
|
85
|
+
values = {}
|
86
|
+
subject.each_with_index do |value, index|
|
87
|
+
values[index] = value
|
88
|
+
end
|
89
|
+
values.should == {0 => CF::Boolean::TRUE, 1 => CF::String.from_string('123')}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CF do
|
4
|
+
|
5
|
+
|
6
|
+
describe CF::Boolean do
|
7
|
+
describe 'value' do
|
8
|
+
it 'should return true for CF::Boolean::TRUE' do
|
9
|
+
CF::Boolean::TRUE.value.should == true
|
10
|
+
end
|
11
|
+
it 'should return false for CF::Boolean::FALSE' do
|
12
|
+
CF::Boolean::FALSE.value.should == false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'to_ruby' do
|
17
|
+
it 'should behave like value' do
|
18
|
+
CF::Boolean::FALSE.to_ruby.should == false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/spec/data_spec.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe CF::Data do
|
5
|
+
subject {CF::Data.from_string('A CF string')}
|
6
|
+
describe '#to_s' do
|
7
|
+
it 'should return a binary ruby string' do
|
8
|
+
ruby_string = subject.to_s
|
9
|
+
ruby_string.should == 'A CF string'
|
10
|
+
if CF::String::HAS_ENCODING
|
11
|
+
ruby_string.encoding.should == Encoding::ASCII_8BIT
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#size' do
|
17
|
+
it 'should return the size in bytes of the cfdata' do
|
18
|
+
subject.size.should == 11
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'to_ruby' do
|
23
|
+
it 'should behave like to_s' do
|
24
|
+
subject.to_ruby.should == 'A CF string'
|
25
|
+
if 'A CF string'.respond_to? "encoding"
|
26
|
+
subject.to_ruby.encoding.should == Encoding::ASCII_8BIT
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/spec/date_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CF::Date do
|
4
|
+
describe('from_time') do
|
5
|
+
it 'should create a cf date from a time' do
|
6
|
+
CF::Date.from_time(Time.now).should be_a(CF::Date)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe('to_time') do
|
11
|
+
it 'should return a time' do
|
12
|
+
t = CF::Date.from_time(Time.now).to_time
|
13
|
+
t.should be_a(Time)
|
14
|
+
t.should be_within(0.01).of(Time.now)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'to_ruby' do
|
19
|
+
it 'should behave like to_time' do
|
20
|
+
t = CF::Date.from_time(Time.now).to_ruby
|
21
|
+
t.should be_a(Time)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe CF::Dictionary do
|
5
|
+
describe 'mutable' do
|
6
|
+
it 'should return a cf dictionary' do
|
7
|
+
CF::Dictionary.mutable.should be_a(CF::Dictionary)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'hash access' do
|
12
|
+
subject {CF::Dictionary.mutable}
|
13
|
+
|
14
|
+
it 'should return nil when the key does not exist' do
|
15
|
+
subject['doesnotexist'].should be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should raise when trying to store a non cf value' do
|
19
|
+
expect {subject[CF::String.from_string('key')]=1}.to raise_error(TypeError)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should raise when trying to store a non cf key' do
|
23
|
+
expect {subject[1]=CF::String.from_string('value')}.to raise_error(TypeError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should allow storing and retrieving a cf key pair' do
|
27
|
+
subject[CF::String.from_string('key')] = CF::String.from_string('value')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should instantiate the correct type on retrieval' do
|
31
|
+
subject[CF::String.from_string('key')] = CF::String.from_string('value')
|
32
|
+
subject[CF::String.from_string('key')].should be_a(CF::String)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should coerce string keys' do
|
36
|
+
subject['key'] = CF::String.from_string('value')
|
37
|
+
subject['key'].to_s.should == 'value'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'merge!' do
|
42
|
+
subject { CF::Dictionary.mutable.tap {|dict| dict['1'] = CF::Boolean::TRUE; dict['2'] = CF::Boolean::FALSE}}
|
43
|
+
it 'should merge the argument into the receiver' do
|
44
|
+
argument = {'1' => false, 'foo' => 'bar'}.to_cf
|
45
|
+
subject.merge! argument
|
46
|
+
subject.to_ruby.should == {'1' => false, '2' => false, 'foo' => 'bar'}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'length' do
|
51
|
+
it 'should return the count of items in the dictionary' do
|
52
|
+
dict = CF::Dictionary.mutable
|
53
|
+
dict['one'] = CF::Boolean::TRUE
|
54
|
+
dict['two'] = CF::Boolean::TRUE
|
55
|
+
|
56
|
+
dict.length.should == 2
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'enumeration' do
|
61
|
+
subject { CF::Dictionary.mutable.tap {|dict| dict['1'] = CF::Boolean::TRUE; dict['2'] = CF::Boolean::FALSE}}
|
62
|
+
|
63
|
+
it 'should yield each key value pair in the dictionary' do
|
64
|
+
hash = {}
|
65
|
+
subject.each do |k,v|
|
66
|
+
hash[k] = v
|
67
|
+
end
|
68
|
+
hash.should == {CF::String.from_string('1') => CF::Boolean::TRUE,
|
69
|
+
CF::String.from_string('2') => CF::Boolean::FALSE}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'to_ruby' do
|
74
|
+
subject { CF::Dictionary.mutable.tap {|dict| dict['1'] = CF::Boolean::TRUE; dict['2'] = CF::Array.immutable([CF::Boolean::FALSE])}}
|
75
|
+
|
76
|
+
it 'should return a ruby hash where keys and values have been converted to ruby types' do
|
77
|
+
subject.to_ruby.should == {'1' => true, '2' => [false]}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|