bson 4.2.0.rc1-java → 4.2.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/bson-ruby.jar +0 -0
- data/lib/bson/array.rb +1 -1
- data/lib/bson/binary.rb +4 -2
- data/lib/bson/code.rb +1 -1
- data/lib/bson/code_with_scope.rb +1 -1
- data/lib/bson/date.rb +1 -1
- data/lib/bson/date_time.rb +1 -1
- data/lib/bson/decimal128.rb +2 -2
- data/lib/bson/false_class.rb +1 -1
- data/lib/bson/float.rb +1 -1
- data/lib/bson/hash.rb +1 -1
- data/lib/bson/integer.rb +1 -1
- data/lib/bson/object_id.rb +1 -1
- data/lib/bson/open_struct.rb +1 -1
- data/lib/bson/regexp.rb +87 -19
- data/lib/bson/specialized.rb +1 -1
- data/lib/bson/string.rb +1 -1
- data/lib/bson/symbol.rb +1 -1
- data/lib/bson/time.rb +1 -1
- data/lib/bson/timestamp.rb +1 -1
- data/lib/bson/true_class.rb +1 -1
- data/lib/bson/version.rb +1 -1
- data/spec/bson/array_spec.rb +1 -1
- data/spec/bson/binary_spec.rb +2 -1
- data/spec/bson/corpus_spec.rb +68 -0
- data/spec/bson/decimal128_spec.rb +5 -1
- data/spec/bson/int64_spec.rb +47 -0
- data/spec/bson/raw_spec.rb +562 -0
- data/spec/bson/regexp_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -0
- data/spec/support/corpus-tests/array.json +43 -0
- data/spec/support/corpus-tests/boolean.json +27 -0
- data/spec/support/corpus-tests/code.json +67 -0
- data/spec/support/corpus-tests/code_w_scope.json +78 -0
- data/spec/support/corpus-tests/document.json +36 -0
- data/spec/support/corpus-tests/double.json +69 -0
- data/spec/support/corpus-tests/failures/binary.json +69 -0
- data/spec/support/corpus-tests/failures/datetime.json +31 -0
- data/spec/support/corpus-tests/failures/dbpointer.json +42 -0
- data/spec/support/corpus-tests/failures/int64.json +38 -0
- data/spec/support/corpus-tests/failures/symbol.json +62 -0
- data/spec/support/corpus-tests/failures/undefined.json +13 -0
- data/spec/support/corpus-tests/int32.json +38 -0
- data/spec/support/corpus-tests/maxkey.json +12 -0
- data/spec/support/corpus-tests/minkey.json +12 -0
- data/spec/support/corpus-tests/null.json +12 -0
- data/spec/support/corpus-tests/oid.json +28 -0
- data/spec/support/corpus-tests/regex.json +37 -0
- data/spec/support/corpus-tests/string.json +67 -0
- data/spec/support/corpus-tests/timestamp.json +18 -0
- data/spec/support/corpus-tests/top.json +62 -0
- data/spec/support/corpus.rb +265 -0
- data/spec/support/shared_examples.rb +1 -1
- metadata +51 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0943fd6b5a5e056e3a5ec9f82d6ff228acf678da
|
4
|
+
data.tar.gz: 40bd34efa88bfc193570ea92aa30bf8ea14a7bdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a15fb476ce3e5a594fed1960360f6fa8e1940cdde17573024d8d9fee551e1c49f1d6687d8279ff55ea505ea93f2bcb2abfba5c6741d9696f611dfb24524304e
|
7
|
+
data.tar.gz: d6d0c5456eb12da27b80c27c731e145d79668ead9170f4c2fe1a25b1090b5728aee15b17d07151b63e62bfbf9e2bcc2dc169a03029d4b63e8ad5fb9149f8767e
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/bson-ruby.jar
CHANGED
Binary file
|
data/lib/bson/array.rb
CHANGED
@@ -35,7 +35,7 @@ module BSON
|
|
35
35
|
# @note Arrays are encoded as documents, where the index of the value in
|
36
36
|
# the array is the actual key.
|
37
37
|
#
|
38
|
-
# @return [
|
38
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
39
39
|
#
|
40
40
|
# @see http://bsonspec.org/#/specification
|
41
41
|
#
|
data/lib/bson/binary.rb
CHANGED
@@ -12,6 +12,8 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
require 'base64'
|
16
|
+
|
15
17
|
module BSON
|
16
18
|
|
17
19
|
# Represents binary data.
|
@@ -89,7 +91,7 @@ module BSON
|
|
89
91
|
#
|
90
92
|
# @since 2.0.0
|
91
93
|
def as_json(*args)
|
92
|
-
{ "$binary" => data, "$type" => type }
|
94
|
+
{ "$binary" => Base64.encode64(data), "$type" => type }
|
93
95
|
end
|
94
96
|
|
95
97
|
# Instantiate the new binary object.
|
@@ -124,7 +126,7 @@ module BSON
|
|
124
126
|
# @example Encode the binary.
|
125
127
|
# binary.to_bson
|
126
128
|
#
|
127
|
-
# @return [
|
129
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
128
130
|
#
|
129
131
|
# @see http://bsonspec.org/#/specification
|
130
132
|
#
|
data/lib/bson/code.rb
CHANGED
data/lib/bson/code_with_scope.rb
CHANGED
data/lib/bson/date.rb
CHANGED
@@ -29,7 +29,7 @@ module BSON
|
|
29
29
|
# @example Get the date as encoded BSON.
|
30
30
|
# Date.new(2012, 1, 1).to_bson
|
31
31
|
#
|
32
|
-
# @return [
|
32
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
33
33
|
#
|
34
34
|
# @see http://bsonspec.org/#/specification
|
35
35
|
#
|
data/lib/bson/date_time.rb
CHANGED
@@ -29,7 +29,7 @@ module BSON
|
|
29
29
|
# @example Get the date time as encoded BSON.
|
30
30
|
# DateTime.new(2012, 1, 1, 0, 0, 0).to_bson
|
31
31
|
#
|
32
|
-
# @return [
|
32
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
33
33
|
#
|
34
34
|
# @see http://bsonspec.org/#/specification
|
35
35
|
#
|
data/lib/bson/decimal128.rb
CHANGED
@@ -109,7 +109,7 @@ module BSON
|
|
109
109
|
# @example Get the raw bson bytes in a buffer.
|
110
110
|
# decimal.to_bson
|
111
111
|
#
|
112
|
-
# @return [ BSON::ByteBuffer ] The
|
112
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
113
113
|
#
|
114
114
|
# @see http://bsonspec.org/#/specification
|
115
115
|
#
|
@@ -200,7 +200,7 @@ module BSON
|
|
200
200
|
#
|
201
201
|
# @since 4.2.0
|
202
202
|
def from_bson(buffer)
|
203
|
-
from_bits(*buffer.get_decimal128_bytes.unpack('Q
|
203
|
+
from_bits(*buffer.get_decimal128_bytes.unpack('Q<*'))
|
204
204
|
end
|
205
205
|
|
206
206
|
# Instantiate a Decimal128 from a string.
|
data/lib/bson/false_class.rb
CHANGED
data/lib/bson/float.rb
CHANGED
@@ -37,7 +37,7 @@ module BSON
|
|
37
37
|
# @example Get the floating point as encoded BSON.
|
38
38
|
# 1.221311.to_bson
|
39
39
|
#
|
40
|
-
# @return [
|
40
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
41
41
|
#
|
42
42
|
# @see http://bsonspec.org/#/specification
|
43
43
|
#
|
data/lib/bson/hash.rb
CHANGED
@@ -32,7 +32,7 @@ module BSON
|
|
32
32
|
# @example Get the hash as encoded BSON.
|
33
33
|
# { "field" => "value" }.to_bson
|
34
34
|
#
|
35
|
-
# @return [
|
35
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
36
36
|
#
|
37
37
|
# @see http://bsonspec.org/#/specification
|
38
38
|
#
|
data/lib/bson/integer.rb
CHANGED
@@ -98,7 +98,7 @@ module BSON
|
|
98
98
|
# @example Get the integer as encoded BSON.
|
99
99
|
# 1024.to_bson
|
100
100
|
#
|
101
|
-
# @return [
|
101
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
102
102
|
#
|
103
103
|
# @see http://bsonspec.org/#/specification
|
104
104
|
#
|
data/lib/bson/object_id.rb
CHANGED
@@ -164,7 +164,7 @@ module BSON
|
|
164
164
|
# where the object was instantiated in a non-standard way. (Like a
|
165
165
|
# Marshal.load)
|
166
166
|
#
|
167
|
-
# @return [
|
167
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
168
168
|
#
|
169
169
|
# @see http://bsonspec.org/#/specification
|
170
170
|
#
|
data/lib/bson/open_struct.rb
CHANGED
@@ -27,7 +27,7 @@ module BSON
|
|
27
27
|
# @example Get the OpenStruct object as encoded BSON.
|
28
28
|
# OpenStruct.new({ "field" => "value" }).to_bson
|
29
29
|
#
|
30
|
-
# @return [
|
30
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
31
31
|
#
|
32
32
|
# @see http://bsonspec.org/#/specification
|
33
33
|
#
|
data/lib/bson/regexp.rb
CHANGED
@@ -51,6 +51,8 @@ module BSON
|
|
51
51
|
# Ruby multiline constant.
|
52
52
|
#
|
53
53
|
# @since 3.2.6
|
54
|
+
#
|
55
|
+
# @deprecated Will be removed in 5.0
|
54
56
|
RUBY_MULTILINE_VALUE = 'ms'.freeze
|
55
57
|
|
56
58
|
# Get the regexp as JSON hash data.
|
@@ -79,7 +81,10 @@ module BSON
|
|
79
81
|
# 's' for dotall mode ('.' matches everything),
|
80
82
|
# and 'u' to make \w, \W, etc. match unicode.
|
81
83
|
#
|
82
|
-
# @
|
84
|
+
# @param [ BSON::ByteBuffer ] buffer The byte buffer to append to.
|
85
|
+
# @param [ true, false ] validating_keys
|
86
|
+
#
|
87
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
83
88
|
#
|
84
89
|
# @see http://bsonspec.org/#/specification
|
85
90
|
#
|
@@ -92,7 +97,8 @@ module BSON
|
|
92
97
|
private
|
93
98
|
|
94
99
|
def bson_options
|
95
|
-
|
100
|
+
# Ruby's Regexp always has BSON's equivalent of 'm' on, so always add it
|
101
|
+
bson_ignorecase + MULTILINE_VALUE + bson_dotall + bson_extended
|
96
102
|
end
|
97
103
|
|
98
104
|
def bson_extended
|
@@ -103,8 +109,9 @@ module BSON
|
|
103
109
|
(options & ::Regexp::IGNORECASE != 0) ? IGNORECASE_VALUE : NO_VALUE
|
104
110
|
end
|
105
111
|
|
106
|
-
def
|
107
|
-
|
112
|
+
def bson_dotall
|
113
|
+
# Ruby Regexp's MULTILINE is equivalent to BSON's dotall value
|
114
|
+
(options & ::Regexp::MULTILINE != 0) ? NEWLINE_VALUE : NO_VALUE
|
108
115
|
end
|
109
116
|
|
110
117
|
# Represents the raw values for the regular expression.
|
@@ -113,6 +120,7 @@ module BSON
|
|
113
120
|
#
|
114
121
|
# @since 3.0.0
|
115
122
|
class Raw
|
123
|
+
include JSON
|
116
124
|
|
117
125
|
# @return [ String ] pattern The regex pattern.
|
118
126
|
attr_reader :pattern
|
@@ -129,7 +137,7 @@ module BSON
|
|
129
137
|
#
|
130
138
|
# @since 3.0.0
|
131
139
|
def compile
|
132
|
-
@compiled ||= ::Regexp.new(pattern,
|
140
|
+
@compiled ||= ::Regexp.new(pattern, options_to_int)
|
133
141
|
end
|
134
142
|
|
135
143
|
# Initialize the new raw regular expression.
|
@@ -138,10 +146,14 @@ module BSON
|
|
138
146
|
# Raw.new(pattern, options)
|
139
147
|
#
|
140
148
|
# @param [ String ] pattern The regular expression pattern.
|
141
|
-
# @param [ Integer ] options The options.
|
149
|
+
# @param [ String, Integer ] options The options.
|
150
|
+
#
|
151
|
+
# @note The ability to specify options as an Integer is deprecated.
|
152
|
+
# Please specify options as a String. The ability to pass options as
|
153
|
+
# as Integer will be removed in version 5.0.0.
|
142
154
|
#
|
143
155
|
# @since 3.0.0
|
144
|
-
def initialize(pattern, options)
|
156
|
+
def initialize(pattern, options = '')
|
145
157
|
@pattern = pattern
|
146
158
|
@options = options
|
147
159
|
end
|
@@ -153,15 +165,81 @@ module BSON
|
|
153
165
|
#
|
154
166
|
# @since 3.1.0
|
155
167
|
def respond_to?(method, include_private = false)
|
156
|
-
compile.respond_to?(method, include_private
|
168
|
+
compile.respond_to?(method, include_private) || super
|
157
169
|
end
|
158
170
|
|
171
|
+
# Encode the Raw Regexp object to BSON.
|
172
|
+
#
|
173
|
+
# @example Get the raw regular expression as encoded BSON.
|
174
|
+
# raw_regexp.to_bson
|
175
|
+
#
|
176
|
+
# @note From the BSON spec: The first cstring is the regex pattern,
|
177
|
+
# the second is the regex options string. Options are identified
|
178
|
+
# by characters, which must be stored in alphabetical order.
|
179
|
+
# Valid options are 'i' for case insensitive matching,
|
180
|
+
# 'm' for multiline matching, 'x' for verbose mode,
|
181
|
+
# 'l' to make \w, \W, etc. locale dependent,
|
182
|
+
# 's' for dotall mode ('.' matches everything),
|
183
|
+
# and 'u' to make \w, \W, etc. match unicode.
|
184
|
+
#
|
185
|
+
# @param [ BSON::ByteBuffer ] buffer The byte buffer to append to.
|
186
|
+
# @param [ true, false ] validating_keys
|
187
|
+
#
|
188
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
189
|
+
#
|
190
|
+
# @see http://bsonspec.org/#/specification
|
191
|
+
#
|
192
|
+
# @since 4.2.0
|
193
|
+
def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
|
194
|
+
return compile.to_bson(buffer, validating_keys) if options.is_a?(Integer)
|
195
|
+
buffer.put_cstring(source)
|
196
|
+
buffer.put_cstring(options.chars.sort.join)
|
197
|
+
end
|
198
|
+
|
199
|
+
# Get the raw BSON regexp as JSON hash data.
|
200
|
+
#
|
201
|
+
# @example Get the raw regexp as a JSON hash.
|
202
|
+
# raw_regexp.as_json
|
203
|
+
#
|
204
|
+
# @return [ Hash ] The raw regexp as a JSON hash.
|
205
|
+
#
|
206
|
+
# @since 4.2.0
|
207
|
+
def as_json(*args)
|
208
|
+
{ "$regex" => source, "$options" => options }
|
209
|
+
end
|
210
|
+
|
211
|
+
# Check equality of the raw bson regexp against another.
|
212
|
+
#
|
213
|
+
# @example Check if the raw bson regexp is equal to the other.
|
214
|
+
# raw_regexp == other
|
215
|
+
#
|
216
|
+
# @param [ Object ] other The object to check against.
|
217
|
+
#
|
218
|
+
# @return [ true, false ] If the objects are equal.
|
219
|
+
#
|
220
|
+
# @since 4.2.0
|
221
|
+
def ==(other)
|
222
|
+
return false unless other.is_a?(::Regexp::Raw)
|
223
|
+
pattern == other.pattern &&
|
224
|
+
options == other.options
|
225
|
+
end
|
226
|
+
alias :eql? :==
|
227
|
+
|
159
228
|
private
|
160
229
|
|
161
230
|
def method_missing(method, *arguments)
|
162
231
|
return super unless respond_to?(method)
|
163
232
|
compile.send(method, *arguments)
|
164
233
|
end
|
234
|
+
|
235
|
+
def options_to_int
|
236
|
+
return options if options.is_a?(Integer)
|
237
|
+
opts = 0
|
238
|
+
opts |= ::Regexp::IGNORECASE if options.include?(IGNORECASE_VALUE)
|
239
|
+
opts |= ::Regexp::MULTILINE if options.include?(NEWLINE_VALUE)
|
240
|
+
opts |= ::Regexp::EXTENDED if options.include?(EXTENDED_VALUE)
|
241
|
+
opts
|
242
|
+
end
|
165
243
|
end
|
166
244
|
|
167
245
|
module ClassMethods
|
@@ -177,17 +255,7 @@ module BSON
|
|
177
255
|
# @since 2.0.0
|
178
256
|
def from_bson(buffer)
|
179
257
|
pattern = buffer.get_cstring
|
180
|
-
options =
|
181
|
-
while (option = buffer.get_byte) != NULL_BYTE
|
182
|
-
case option
|
183
|
-
when IGNORECASE_VALUE
|
184
|
-
options |= ::Regexp::IGNORECASE
|
185
|
-
when MULTILINE_VALUE, NEWLINE_VALUE
|
186
|
-
options |= ::Regexp::MULTILINE
|
187
|
-
when EXTENDED_VALUE
|
188
|
-
options |= ::Regexp::EXTENDED
|
189
|
-
end
|
190
|
-
end
|
258
|
+
options = buffer.get_cstring
|
191
259
|
Raw.new(pattern, options)
|
192
260
|
end
|
193
261
|
end
|
data/lib/bson/specialized.rb
CHANGED
@@ -42,7 +42,7 @@ module BSON
|
|
42
42
|
# @example Encode the min key value.
|
43
43
|
# min_key.to_bson
|
44
44
|
#
|
45
|
-
# @return [
|
45
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
46
46
|
#
|
47
47
|
# @since 2.0.0
|
48
48
|
def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
|
data/lib/bson/string.rb
CHANGED
data/lib/bson/symbol.rb
CHANGED
data/lib/bson/time.rb
CHANGED
@@ -32,7 +32,7 @@ module BSON
|
|
32
32
|
# @example Get the time as encoded BSON.
|
33
33
|
# Time.new(2012, 1, 1, 0, 0, 0).to_bson
|
34
34
|
#
|
35
|
-
# @return [
|
35
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
36
36
|
#
|
37
37
|
# @see http://bsonspec.org/#/specification
|
38
38
|
#
|
data/lib/bson/timestamp.rb
CHANGED
data/lib/bson/true_class.rb
CHANGED
data/lib/bson/version.rb
CHANGED
data/spec/bson/array_spec.rb
CHANGED
data/spec/bson/binary_spec.rb
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
require "spec_helper"
|
16
|
+
require "base64"
|
16
17
|
|
17
18
|
describe BSON::Binary do
|
18
19
|
let(:testing1) { described_class.new("testing") }
|
@@ -62,7 +63,7 @@ describe BSON::Binary do
|
|
62
63
|
|
63
64
|
it "returns the binary data plus type" do
|
64
65
|
expect(object.as_json).to eq(
|
65
|
-
{ "$binary" => "testing", "$type" => :user }
|
66
|
+
{ "$binary" => Base64.encode64("testing"), "$type" => :user }
|
66
67
|
)
|
67
68
|
end
|
68
69
|
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Driver BSON Corpus spec tests' do
|
4
|
+
|
5
|
+
specs = BSON_CORPUS_TESTS.map { |file| BSON::Corpus::Spec.new(file) }
|
6
|
+
|
7
|
+
specs.each do |spec|
|
8
|
+
|
9
|
+
context(spec.description) do
|
10
|
+
|
11
|
+
spec.valid_tests.each do |test|
|
12
|
+
|
13
|
+
context("VALID CASE: #{test.description}") do
|
14
|
+
|
15
|
+
it 'roundtrips the given bson correctly' do
|
16
|
+
expect(test.reencoded_bson).to eq(test.correct_bson)
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when the canonical bson is roundtripped', if: test.test_canonical_bson? do
|
20
|
+
|
21
|
+
it 'encodes the canonical bson correctly' do
|
22
|
+
expect(test.reencoded_canonical_bson).to eq(test.correct_bson)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when the document can be represented as extended json', if: test.test_extjson? do
|
27
|
+
|
28
|
+
it 'decodes from the given bson, then encodes the document as extended json correctly' do
|
29
|
+
skip 'The extended json in this test case does not match' unless (test.extjson_from_bson == test.correct_extjson)
|
30
|
+
expect(test.extjson_from_bson).to eq(test.correct_extjson)
|
31
|
+
expect(test.extjson_from_bson[test.test_key]).to eq(test.correct_extjson[test.test_key])
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'decodes from extended json, then encodes the document as extended json correctly' do
|
35
|
+
expect(test.extjson_from_encoded_extjson).to eq(test.correct_extjson)
|
36
|
+
expect(test.extjson_from_encoded_extjson[test.test_key]).to eq(test.correct_extjson[test.test_key])
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when the canonical bson can be represented as extended json', if: (test.test_canonical_bson? && test.test_extjson?) do
|
40
|
+
|
41
|
+
it 'encodes the canonical bson correctly as extended json' do
|
42
|
+
expect(test.extjson_from_canonical_bson).to eq(test.correct_extjson)
|
43
|
+
expect(test.extjson_from_canonical_bson[test.test_key]).to eq(test.correct_extjson[test.test_key])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
spec.invalid_tests.each do |test|
|
51
|
+
|
52
|
+
context("INVALID CASE: #{test.description}") do
|
53
|
+
|
54
|
+
let(:error) do
|
55
|
+
begin; test.reencoded_bson; false; rescue => e; e; end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'raises an error' do
|
59
|
+
skip 'This test case does not raise and error but should' unless error
|
60
|
+
expect {
|
61
|
+
test.reencoded_bson
|
62
|
+
}.to raise_error
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|