mongo 0.19.1 → 0.19.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,224 @@
1
+ # --
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ++
16
+
17
+ # A byte buffer.
18
+ module BSON
19
+ class ByteBuffer
20
+
21
+ # Commonly-used integers.
22
+ INT_LOOKUP = {
23
+ 0 => [0, 0, 0, 0],
24
+ 1 => [1, 0, 0, 0],
25
+ 2 => [2, 0, 0, 0],
26
+ 3 => [3, 0, 0, 0],
27
+ 4 => [4, 0, 0, 0],
28
+ 2001 => [209, 7, 0, 0],
29
+ 2002 => [210, 7, 0, 0],
30
+ 2004 => [212, 7, 0, 0],
31
+ 2005 => [213, 7, 0, 0],
32
+ 2006 => [214, 7, 0, 0]
33
+ }
34
+
35
+ attr_reader :order
36
+
37
+ def initialize(initial_data=[])
38
+ @buf = initial_data
39
+ @cursor = @buf.length
40
+ @order = :little_endian
41
+ @int_pack_order = 'V'
42
+ @double_pack_order = 'E'
43
+ end
44
+
45
+ if RUBY_VERSION >= '1.9'
46
+ def self.to_utf8(str)
47
+ str.encode("utf-8")
48
+ end
49
+ else
50
+ def self.to_utf8(str)
51
+ begin
52
+ str.unpack("U*")
53
+ rescue => ex
54
+ raise InvalidStringEncoding, "String not valid utf-8: #{str}"
55
+ end
56
+ str
57
+ end
58
+ end
59
+
60
+ def self.serialize_cstr(buf, val)
61
+ buf.put_array(to_utf8(val.to_s).unpack("C*") + [0])
62
+ end
63
+
64
+ # +endianness+ should be :little_endian or :big_endian. Default is :little_endian
65
+ def order=(endianness)
66
+ @order = endianness
67
+ @int_pack_order = endianness == :little_endian ? 'V' : 'N'
68
+ @double_pack_order = endianness == :little_endian ? 'E' : 'G'
69
+ end
70
+
71
+ def rewind
72
+ @cursor = 0
73
+ end
74
+
75
+ def position
76
+ @cursor
77
+ end
78
+
79
+ def position=(val)
80
+ @cursor = val
81
+ end
82
+
83
+ def clear
84
+ @buf = []
85
+ rewind
86
+ end
87
+
88
+ def size
89
+ @buf.size
90
+ end
91
+ alias_method :length, :size
92
+
93
+ # Appends a second ByteBuffer object, +buffer+, to the current buffer.
94
+ def append!(buffer)
95
+ @buf = @buf + buffer.to_a
96
+ self
97
+ end
98
+
99
+ # Prepends a second ByteBuffer object, +buffer+, to the current buffer.
100
+ def prepend!(buffer)
101
+ @buf = buffer.to_a + @buf
102
+ self
103
+ end
104
+
105
+ def put(byte, offset=nil)
106
+ @cursor = offset if offset
107
+ @buf[@cursor] = byte
108
+ @cursor += 1
109
+ end
110
+
111
+ def put_array(array, offset=nil)
112
+ @cursor = offset if offset
113
+ @buf[@cursor, array.length] = array
114
+ @cursor += array.length
115
+ end
116
+
117
+ def put_int(i, offset=nil)
118
+ unless a = INT_LOOKUP[i]
119
+ a = []
120
+ [i].pack(@int_pack_order).each_byte { |b| a << b }
121
+ end
122
+ put_array(a, offset)
123
+ end
124
+
125
+ def put_long(i, offset=nil)
126
+ offset = @cursor unless offset
127
+ if @int_pack_order == 'N'
128
+ put_int(i >> 32, offset)
129
+ put_int(i & 0xffffffff, offset + 4)
130
+ else
131
+ put_int(i & 0xffffffff, offset)
132
+ put_int(i >> 32, offset + 4)
133
+ end
134
+ end
135
+
136
+ def put_double(d, offset=nil)
137
+ a = []
138
+ [d].pack(@double_pack_order).each_byte { |b| a << b }
139
+ put_array(a, offset)
140
+ end
141
+
142
+ # If +size+ == nil, returns one byte. Else returns array of bytes of length
143
+ # # +size+.
144
+ def get(len=nil)
145
+ one_byte = len.nil?
146
+ len ||= 1
147
+ check_read_length(len)
148
+ start = @cursor
149
+ @cursor += len
150
+ if one_byte
151
+ @buf[start]
152
+ else
153
+ if @buf.respond_to? "unpack"
154
+ @buf[start, len].unpack("C*")
155
+ else
156
+ @buf[start, len]
157
+ end
158
+ end
159
+ end
160
+
161
+ def get_int
162
+ check_read_length(4)
163
+ vals = ""
164
+ (@cursor..@cursor+3).each { |i| vals << @buf[i].chr }
165
+ @cursor += 4
166
+ vals.unpack(@int_pack_order)[0]
167
+ end
168
+
169
+ def get_long
170
+ i1 = get_int
171
+ i2 = get_int
172
+ if @int_pack_order == 'N'
173
+ (i1 << 32) + i2
174
+ else
175
+ (i2 << 32) + i1
176
+ end
177
+ end
178
+
179
+ def get_double
180
+ check_read_length(8)
181
+ vals = ""
182
+ (@cursor..@cursor+7).each { |i| vals << @buf[i].chr }
183
+ @cursor += 8
184
+ vals.unpack(@double_pack_order)[0]
185
+ end
186
+
187
+ def more?
188
+ @cursor < @buf.size
189
+ end
190
+
191
+ def to_a
192
+ if @buf.respond_to? "unpack"
193
+ @buf.unpack("C*")
194
+ else
195
+ @buf
196
+ end
197
+ end
198
+
199
+ def unpack(args)
200
+ to_a
201
+ end
202
+
203
+ def to_s
204
+ if @buf.respond_to? :fast_pack
205
+ @buf.fast_pack
206
+ elsif @buf.respond_to? "pack"
207
+ @buf.pack("C*")
208
+ else
209
+ @buf
210
+ end
211
+ end
212
+
213
+ def dump
214
+ @buf.each_with_index { |c, i| $stderr.puts "#{'%04d' % i}: #{'%02x' % c} #{'%03o' % c} #{'%s' % c.chr} #{'%3d' % c}" }
215
+ end
216
+
217
+ private
218
+
219
+ def check_read_length(len)
220
+ raise "attempt to read past end of buffer" if @cursor + len > @buf.length
221
+ end
222
+
223
+ end
224
+ end
@@ -0,0 +1,39 @@
1
+ # --
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ++
16
+
17
+ module BSON
18
+ # Generic Mongo Ruby Driver exception class.
19
+ class MongoRubyError < StandardError; end
20
+
21
+ # Raised when MongoDB itself has returned an error.
22
+ class MongoDBError < RuntimeError; end
23
+
24
+ # This will replace MongoDBError.
25
+ class BSONError < MongoDBError; end
26
+
27
+ # Raised when given a string is not valid utf-8 (Ruby 1.8 only).
28
+ class InvalidStringEncoding < BSONError; end
29
+
30
+ # Raised when attempting to initialize an invalid ObjectID.
31
+ class InvalidObjectID < BSONError; end
32
+
33
+ # Raised when trying to insert a document that exceeds the 4MB limit or
34
+ # when the document contains objects that can't be serialized as BSON.
35
+ class InvalidDocument < BSONError; end
36
+
37
+ # Raised when an invalid name is used.
38
+ class InvalidName < BSONError; end
39
+ end
@@ -0,0 +1,140 @@
1
+ # --
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ++
16
+
17
+ # A hash in which the order of keys are preserved.
18
+ #
19
+ # Under Ruby 1.9 and greater, this class has no added methods because Ruby's
20
+ # Hash already keeps its keys ordered by order of insertion.
21
+ class OrderedHash < Hash
22
+
23
+ def ==(other)
24
+ begin
25
+ !other.nil? &&
26
+ keys == other.keys &&
27
+ values == other.values
28
+ rescue
29
+ false
30
+ end
31
+ end
32
+
33
+ # We only need the body of this class if the RUBY_VERSION is before 1.9
34
+ if RUBY_VERSION < '1.9'
35
+ attr_accessor :ordered_keys
36
+
37
+ def self.[] *args
38
+ oh = OrderedHash.new
39
+ if Hash === args[0]
40
+ oh.merge! args[0]
41
+ elsif (args.size % 2) != 0
42
+ raise ArgumentError, "odd number of elements for Hash"
43
+ else
44
+ 0.step(args.size - 1, 2) do |key|
45
+ value = key + 1
46
+ oh[args[key]] = args[value]
47
+ end
48
+ end
49
+ oh
50
+ end
51
+
52
+ def initialize(*a, &b)
53
+ super
54
+ @ordered_keys = []
55
+ end
56
+
57
+ def keys
58
+ @ordered_keys || []
59
+ end
60
+
61
+ def []=(key, value)
62
+ @ordered_keys ||= []
63
+ @ordered_keys << key unless @ordered_keys.include?(key)
64
+ super(key, value)
65
+ end
66
+
67
+ def each
68
+ @ordered_keys ||= []
69
+ @ordered_keys.each { |k| yield k, self[k] }
70
+ self
71
+ end
72
+ alias :each_pair :each
73
+
74
+ def to_a
75
+ @ordered_keys ||= []
76
+ @ordered_keys.map { |k| [k, self[k]] }
77
+ end
78
+
79
+ def values
80
+ collect { |k, v| v }
81
+ end
82
+
83
+ def merge(other)
84
+ oh = self.dup
85
+ oh.merge!(other)
86
+ oh
87
+ end
88
+
89
+ def merge!(other)
90
+ @ordered_keys ||= []
91
+ @ordered_keys += other.keys # unordered if not an OrderedHash
92
+ @ordered_keys.uniq!
93
+ super(other)
94
+ end
95
+
96
+ alias :update :merge!
97
+
98
+ def inspect
99
+ str = '{'
100
+ str << (@ordered_keys || []).collect { |k| "\"#{k}\"=>#{self.[](k).inspect}" }.join(", ")
101
+ str << '}'
102
+ end
103
+
104
+ def delete(key, &block)
105
+ @ordered_keys.delete(key) if @ordered_keys
106
+ super
107
+ end
108
+
109
+ def delete_if(&block)
110
+ self.each { |k,v|
111
+ if yield k, v
112
+ delete(k)
113
+ end
114
+ }
115
+ end
116
+
117
+ def clear
118
+ super
119
+ @ordered_keys = []
120
+ end
121
+
122
+ def hash
123
+ code = 17
124
+ each_pair do |key, value|
125
+ code = 37 * code + key.hash
126
+ code = 37 * code + value.hash
127
+ end
128
+ code & 0x7fffffff
129
+ end
130
+
131
+ def eql?(o)
132
+ if o.instance_of? OrderedHash
133
+ self.hash == o.hash
134
+ else
135
+ false
136
+ end
137
+ end
138
+
139
+ end
140
+ end
@@ -0,0 +1,54 @@
1
+ # --
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ++
16
+
17
+ require 'bson/byte_buffer'
18
+
19
+ module BSON
20
+
21
+ # An array of binary bytes with a MongoDB subtype. See the subtype
22
+ # constants for reference.
23
+ #
24
+ # Use this class when storing binary data in documents.
25
+ class Binary < ByteBuffer
26
+
27
+ SUBTYPE_BYTES = 0x02
28
+ SUBTYPE_UUID = 0x03
29
+ SUBTYPE_MD5 = 0x05
30
+ SUBTYPE_USER_DEFINED = 0x80
31
+
32
+ # One of the SUBTYPE_* constants. Default is SUBTYPE_BYTES.
33
+ attr_accessor :subtype
34
+
35
+ # Create a buffer for storing binary data in MongoDB.
36
+ #
37
+ # @param [Array, String] data to story as BSON binary. If a string is given, the value will be
38
+ # concerted to an array of bytes using String#unpack("c*").
39
+ # @param [Fixnum] one of four values specifying a BSON binary subtype. Possible values are
40
+ # SUBTYPE_BYTES, SUBTYPE_UUID, SUBTYPE_MD5, and SUBTYPE_USER_DEFINED.
41
+ #
42
+ # @see http://www.mongodb.org/display/DOCS/BSON#BSON-noteondatabinary BSON binary subtypes.
43
+ def initialize(data=[], subtype=SUBTYPE_BYTES)
44
+ data = data.unpack("c*") if data.is_a?(String)
45
+ super(data)
46
+ @subtype = subtype
47
+ end
48
+
49
+ def inspect
50
+ "<BSON::Binary:#{object_id}>"
51
+ end
52
+
53
+ end
54
+ end