bitstring 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/CONTRIBUTORS.txt +5 -0
  2. data/Changelog.txt +20 -0
  3. data/LICENCE.txt +202 -0
  4. data/NOTICE.txt +5 -0
  5. data/README.txt +63 -0
  6. data/doc/classes/BitString.html +2479 -0
  7. data/doc/classes/BitString.src/M000001.html +99 -0
  8. data/doc/classes/BitString.src/M000002.html +18 -0
  9. data/doc/classes/BitString.src/M000003.html +20 -0
  10. data/doc/classes/BitString.src/M000004.html +19 -0
  11. data/doc/classes/BitString.src/M000005.html +24 -0
  12. data/doc/classes/BitString.src/M000006.html +44 -0
  13. data/doc/classes/BitString.src/M000007.html +21 -0
  14. data/doc/classes/BitString.src/M000008.html +18 -0
  15. data/doc/classes/BitString.src/M000009.html +18 -0
  16. data/doc/classes/BitString.src/M000010.html +22 -0
  17. data/doc/classes/BitString.src/M000011.html +29 -0
  18. data/doc/classes/BitString.src/M000012.html +22 -0
  19. data/doc/classes/BitString.src/M000013.html +43 -0
  20. data/doc/classes/BitString.src/M000014.html +19 -0
  21. data/doc/classes/BitString.src/M000015.html +40 -0
  22. data/doc/classes/BitString.src/M000016.html +21 -0
  23. data/doc/classes/BitString.src/M000017.html +18 -0
  24. data/doc/classes/BitString.src/M000018.html +18 -0
  25. data/doc/classes/BitString.src/M000019.html +18 -0
  26. data/doc/classes/BitString.src/M000020.html +20 -0
  27. data/doc/classes/BitString.src/M000021.html +24 -0
  28. data/doc/classes/BitString.src/M000022.html +23 -0
  29. data/doc/classes/BitString.src/M000023.html +42 -0
  30. data/doc/classes/BitString.src/M000024.html +61 -0
  31. data/doc/classes/BitString.src/M000025.html +18 -0
  32. data/doc/classes/BitString.src/M000026.html +18 -0
  33. data/doc/classes/BitString.src/M000027.html +20 -0
  34. data/doc/classes/BitString.src/M000028.html +18 -0
  35. data/doc/classes/BitString.src/M000029.html +18 -0
  36. data/doc/classes/BitString.src/M000030.html +18 -0
  37. data/doc/classes/BitString.src/M000031.html +18 -0
  38. data/doc/classes/BitString.src/M000032.html +18 -0
  39. data/doc/created.rid +1 -0
  40. data/doc/files/lib/bitstring/operators_rb.html +122 -0
  41. data/doc/files/lib/bitstring_rb.html +153 -0
  42. data/doc/fr_class_index.html +27 -0
  43. data/doc/fr_file_index.html +28 -0
  44. data/doc/fr_method_index.html +60 -0
  45. data/doc/index.html +24 -0
  46. data/doc/rdoc-style.css +208 -0
  47. data/lib/bitstring.rb +1318 -0
  48. data/lib/bitstring/operators.rb +481 -0
  49. data/test/Rakefile +21 -0
  50. data/test/test_basic.rb +848 -0
  51. data/test/test_data.rb +24 -0
  52. data/test/test_enum.rb +671 -0
  53. data/test/test_helper.rb +3 -0
  54. data/test/test_operators.rb +454 -0
  55. metadata +121 -0
@@ -0,0 +1,481 @@
1
+ #
2
+ # = operators.rb - Operators for the BitString class
3
+ #
4
+ # Author:: Ken Coar
5
+ # Copyright:: Copyright © 2010 Ken Coar
6
+ # License:: Apache Licence 2.0
7
+ #
8
+ # == Description
9
+ #
10
+ # Operator methods for <i>BitString</i> class (<i>e.g.</i>, those consisting
11
+ # of special characters).
12
+ #
13
+ #--
14
+ # Copyright © 2010 Ken Coar
15
+ #
16
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
17
+ # may not use this file except in compliance with the License. You may
18
+ # obtain a copy of the License at
19
+ #
20
+ # http://www.apache.org/licenses/LICENSE-2.0
21
+ #
22
+ # Unless required by applicable law or agreed to in writing, software
23
+ # distributed under the License is distributed on an "AS IS" BASIS,
24
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
25
+ # implied. See the License for the specific language governing
26
+ # permissions and limitations under the License.
27
+ #++
28
+
29
+ #--
30
+ # Re-open the class to add the operator methods
31
+ #++
32
+
33
+ class BitString
34
+
35
+ #
36
+ # === Description
37
+ #
38
+ # Perform a bitwise AND on the entire bitstring, returning a new
39
+ # <i>BitString</i> object. The new bitstring will have the
40
+ # same boundedness as the original.
41
+ #
42
+ # call-seq:
43
+ # bitstring <i>& value</i> => <i>BitString</i>
44
+ # bitstring.&<i>(value)</i> => <i>BitString</i>
45
+ #
46
+ # === Arguments
47
+ # [<i>value</i>] <i>BitString</i>, <i>Integer</i>, or <i>String</i>. Value to AND with the bitstring.
48
+ #
49
+ # === Examples
50
+ # bs = BitString.new('111111111')
51
+ # nbs = bs & '111100011'
52
+ # nbs.to_s
53
+ # => "111100011"
54
+ #
55
+ # bs = BitString.new('10101010101', 11)
56
+ # nbs = bs & '11110001111'
57
+ # nbs.to_s
58
+ # => "10100000101"
59
+ # nbs = bs & '00001110000'
60
+ # nbs.to_s
61
+ # => "00001010000"
62
+ #
63
+ # === Exceptions
64
+ # <i>None</i>.
65
+ #
66
+ def &(val)
67
+ val = _arg2int(val)
68
+ vMask = self.mask
69
+ newval = (@value & val) & vMask
70
+ bounded? ? self.class.new(newval, @length) : self.class.new(newval)
71
+ end # def &
72
+
73
+ #
74
+ # === Description
75
+ #
76
+ # Perform a left-shift on the bitstring, returning a new <i>BitString</i>
77
+ # containing the shifted value. If the bitstring is bounded, bits
78
+ # shifted off the high end are lost.
79
+ #
80
+ # call-seq:
81
+ # bitstring <i>&lt;&lt; bitcount</i> => <i>BitString</i>
82
+ # bitstring.&lt;&lt;<i>(bitcount)</i> => <i>BitString</i>
83
+ #
84
+ # === Arguments
85
+ # [<i>bitcount</i>] <i>Integer</i>. Number of positions by which to left-shift.
86
+ #
87
+ # === Examples
88
+ # bs = BitString.new('1100111')
89
+ # nbs = bs << 2
90
+ # nbs.to_s
91
+ # => "110011100"
92
+ #
93
+ # bs = BitString.new('00010001', 8)
94
+ # nbs = bs << 2
95
+ # nbs.to_s
96
+ # => "01000100"
97
+ # nbs = bs << 4
98
+ # nbs.to_s
99
+ # => "00010000" # High bits shifted off and lost
100
+ #
101
+ # === Exceptions
102
+ # <i>None</i>.
103
+ #
104
+ def <<(bits)
105
+ value = @value * (2**bits.to_i)
106
+ if (bounded?)
107
+ self.class.new(value & self.mask, @length)
108
+ else
109
+ self.class.new(value)
110
+ end
111
+ end # def <<
112
+
113
+ #
114
+ # === Description
115
+ #
116
+ # Right-shift the bitstring (toward the low end) by the specified number
117
+ # of bits. Bits shifted off the end are lost; new bits shifted in at
118
+ # the high end are 0.
119
+ #
120
+ # call-seq:
121
+ # bitstring &gt;&gt; <i>bitcount</i> => <i>BitString</i>
122
+ # bitstring.&gt;&gt;<i>(bitcount)</i> => <i>BitString</i>
123
+ #
124
+ # === Arguments
125
+ # [<i>bitcount</i>] <i>Integer</i>. Number of positions to right-shift by.
126
+ #
127
+ # === Examples
128
+ # bs = BitString.new('1100111')
129
+ # nbs = bs >> 2
130
+ # nbs.to_s
131
+ # => "11001"
132
+ #
133
+ # bs = BitString.new('00010001', 8)
134
+ # nbs = bs >> 2
135
+ # nbs.to_s
136
+ # => "00000100"
137
+ # nbs = bs >> 4
138
+ # nbs.to_s
139
+ # => "00000001"
140
+ #
141
+ # === Exceptions
142
+ # <i>None</i>.
143
+ #
144
+ def >>(bits)
145
+ value = @value / 2**bits.to_i
146
+ if (bounded?)
147
+ self.class.new(value, @length)
148
+ else
149
+ self.class.new(value)
150
+ end
151
+ end # def >>
152
+
153
+ #
154
+ # === Description
155
+ #
156
+ # Extract a particular substring from the bitstring.
157
+ # If we're given a single index, we return an integer; if
158
+ # a range, we return a new BitString.
159
+ #
160
+ # call-seq:
161
+ # bitstring<i>[index]</i> => <i>Integer</i>
162
+ # bitstring<i>[start, length]</i> => <i>BitString</i>
163
+ # bitstring<i>[range]</i> => <i>BitString</i>
164
+ #
165
+ # === Arguments
166
+ # [<i>index</i>] <i>Integer</i>. Single bit position.
167
+ # [<i>start</i>] <i>Integer</i>. Start position of subset.
168
+ # [<i>length</i>] <i>Integer</i>. Length of subset.
169
+ # [<i>range</i>] <i>Range</i>. Subset specified as a range.
170
+ #
171
+ # === Examples
172
+ # bs = BitString.new('110010110')
173
+ # bs[0]
174
+ # => 0
175
+ # bs[1]
176
+ # => 1
177
+ # bs[0..1].to_s # Multi-bit indexing returns a bitsring
178
+ # => "10"
179
+ # bs[0,9].to_s
180
+ # => "110010110"
181
+ # bs[100..102].to_s # Can index 'way past the end for unbounded bitstrings
182
+ # => "000"
183
+ #
184
+ # bs = BitString.new('110010110', 9)
185
+ # bs[100..102].to_s #
186
+ # => exception: "IndexError: index out of range"
187
+ #
188
+ # === Exceptions
189
+ # [<tt>ArgumentError</tt>] If length specified with a range.
190
+ # [<tt>IndexError</tt>] If bitstring is bounded and the substring is illegal.
191
+ #
192
+ def [](pos_p, length_p=nil)
193
+ #
194
+ # Turn a position/length into a range.
195
+ #
196
+ if (pos_p.kind_of?(Integer) && length_p.kind_of?(Integer))
197
+ pos_p = Range.new(pos_p, pos_p + length_p - 1)
198
+ length_p = nil
199
+ end
200
+ if (pos_p.kind_of?(Range))
201
+ unless (length_p.nil?)
202
+ raise ArgumentError.new('length not allowed with range')
203
+ end
204
+ pos_a = pos_p.to_a
205
+ pos_a.reverse! if (pos_a.first < pos_a.last)
206
+ r = pos_a.collect { |pos| self[pos].to_s }
207
+ return self.class.new(r.join(''), r.length)
208
+ end
209
+ pos = pos_p.to_i
210
+ #
211
+ # Blow an error if we were given an index out of range.
212
+ #
213
+ unless ((pos >= 0) &&
214
+ ((! bounded?) || pos.between?(0, @length - 1)))
215
+ _raise(OuttasightIndex, pos)
216
+ end
217
+ (@value & (2**pos)) / (2**pos)
218
+ end # def []
219
+
220
+ #
221
+ # === Description
222
+ #
223
+ # Set a bit or range of bits with a single operation.
224
+ #
225
+ # call-seq:
226
+ # bitstring[<i>pos</i>] = <i>value</i> => <i>value</i>
227
+ # bitstring[<i>start, length</i>] = <i>value</i> => <i>value</i>
228
+ # bitstring[<i>range</i>] = <i>value</i> => <i>value</i>
229
+ #
230
+ # === Arguments
231
+ # [<i>value</i>] <i>Array</i>, <i>BitString</i>, <i>Integer</i>, or <i>String</i>. Value (treated as a stream of bits) used to set the bitstring.
232
+ # [<i>pos</i>] <i>Integer</i>. Single bit position to alter.
233
+ # [<i>start</i>] <i>Integer</i>. First bit position in substring.
234
+ # [<i>length</i>] <i>Integer</i>. Number of bits in substring.
235
+ # [<i>range</i>] <i>Range</i>. Range of bits (<i>e.g.</i>, 5..10) to affect.
236
+ #
237
+ # === Examples
238
+ # bs = BitString.new('110010110')
239
+ # bs[0] = 1
240
+ # => 1
241
+ # bs.to_s
242
+ # => "110010111"
243
+ # bs[1] = 0
244
+ # => 0
245
+ # bs.to_s
246
+ # => "110010101"
247
+ # bs[0..3] = 14 # Multi-bit indexing set a bitsring
248
+ # => "14"
249
+ # bs.to_s
250
+ # => "110011110"
251
+ # bs[12..14] = 5
252
+ # => 5
253
+ # bs.to_s
254
+ # => "101000110011110" # Can index past the end for unbounded bitstrings
255
+ #
256
+ # bs = BitString.new('110010110', 9)
257
+ # bs[1,3] = 4095 # 111111111111, but gets truncated to low 3 bits
258
+ # bs.to_s
259
+ # => "110011110"
260
+ #
261
+ # === Exceptions
262
+ # [<tt>ArgumentError</tt>] Both range and length specified, or value cannot be interpreted as an integer.
263
+ # [<tt>IndexError</tt>] Non-integer or negative index, or beyond the end of the bitstring.
264
+ #
265
+ def []=(*args_p)
266
+ low = high = width = nil
267
+ args = args_p
268
+ if (args.length == 2)
269
+ #
270
+ # [pos]= or [range]=
271
+ #
272
+ if ((r = args[0]).class.eql?(Range))
273
+ #
274
+ # Convert into a [start,length] format to reuse that stream.
275
+ #
276
+ (start, stop) = [r.first, r.last].sort
277
+ width = stop - start + 1
278
+ args = [start, width, args[1]]
279
+ else
280
+ args = [args[0], 1, args[1]]
281
+ end
282
+ elsif (args_p.length != 3)
283
+ _raise(WrongNargs, args_p.length, 3)
284
+ end
285
+ #
286
+ # Special cases of args have now been normalised to [start,length,value].
287
+ # Make sure the values are acceptable.
288
+ #
289
+ (start, nBits, value) = args
290
+ _raise(BogoIndex, start) unless (start.respond_to?(:to_i))
291
+ start = start.to_i unless (start.kind_of?(Integer))
292
+ _raise(BogoIndex, nBits) unless (nBits.respond_to?(:to_i))
293
+ nBits = length.to_i unless (nBits.kind_of?(Integer))
294
+ highpos = start + nBits - 1
295
+ _raise(OuttasightIndex, highpos) if (bounded? && (highpos > @length - 1))
296
+ _raise(BitsRInts, value) unless (value.respond_to?(:to_i))
297
+ value = _arg2int(value)
298
+ #
299
+ # All the checking is done, let's do this thing.
300
+ #
301
+ vMask = 2**nBits - 1
302
+ fvalue = (value &= vMask)
303
+ vMask *= 2**start
304
+ value *= 2**start
305
+
306
+ highpos = self.length
307
+ bValue = @value & ((2**highpos - 1) & ~vMask)
308
+ @value = bValue | value
309
+ return fvalue
310
+ end # def []=
311
+
312
+ #
313
+ # === Description
314
+ #
315
+ # Perform a bitwise exclusive OR (XOR) and return a copy of the
316
+ # result.
317
+ #
318
+ # call-seq:
319
+ # bitstring <i>^ value</i> => <i>BitString</i>
320
+ # bitstring.^<i>(value)</i> => <i>BitString</i>
321
+ #
322
+ # === Arguments
323
+ # [<i>value</i>] <i>Array</i>, <i>BitString</i>, <i>Integer</i>, or <i>String</i>. Value treated as a bitstream and exclusively ORed with the bitstring.
324
+ #
325
+ # === Examples
326
+ # bs = BitString.new('110010110', 9)
327
+ # nbs = bs ^ '001101001'
328
+ # nbs.to_s
329
+ # => "111111111"
330
+ # nbs = bs ^ bs.mask # Equivalent to 'nbs = ~ bs'
331
+ # nbs.to_s
332
+ # => "001101001"
333
+ #
334
+ # === Exceptions
335
+ # <i>None</i>.
336
+ #
337
+ def ^(value)
338
+ value = _arg2int(value)
339
+ value &= self.mask if (bounded?)
340
+ bs = dup
341
+ bs.from_i(value ^ bs.to_i)
342
+ bs
343
+ end # def ^
344
+
345
+ #
346
+ # === Description
347
+ #
348
+ # Perform a bitwise inclusive OR with the current bitstring and
349
+ # return a bitstring containing the result.
350
+ #
351
+ # call-seq:
352
+ # bitstring <i>| value</i> => <i>BitString</i>
353
+ # bitstring.|<i>(value)</i> => <i>BitString</i>
354
+ #
355
+ # === Arguments
356
+ # [<i>value</i>] <i>Array</i>, <i>BitString</i>, <i>Integer</i>, or <i>String</i>. Value treated as a bitstream and inclusively ORed with the bitstring.
357
+ #
358
+ # === Examples
359
+ # bs = BitString.new('110010110')
360
+ # nbs = bs | '11000000000000000'
361
+ # nbs.to_s # Bits cab be ORed in anywhere in an
362
+ # => "11000000110010110" # unbouded string
363
+ #
364
+ # === Exceptions
365
+ # <i>None</i>.
366
+ #
367
+ def |(value)
368
+ value = _arg2int(value)
369
+ value &= self.mask if (bounded?)
370
+ bs = dup
371
+ bs.from_i(value | bs.to_i)
372
+ bs
373
+ end # def |
374
+
375
+ #
376
+ # === Description
377
+ #
378
+ # Perform a one's complement on the current bitstring and return the
379
+ # result in a new one.
380
+ #
381
+ # call-seq:
382
+ # <i>~</i> bitstring => <i>BitString</i>
383
+ # bitstring.~<i>()</i> => <i>BitString</i>
384
+ #
385
+ # === Arguments
386
+ # <i>None</i>.
387
+ #
388
+ # === Examples
389
+ # bs = BitString.new('110010110')
390
+ # nbs = ~ bs
391
+ # nbs.to_s
392
+ # => "1101001" # Leading zeroes stripped when unbounded
393
+ #
394
+ # bs = BitString.new('110010110', 9)
395
+ # nbs = ~ bs
396
+ # nbs.to_s
397
+ # => "001101001"
398
+ #
399
+ # bs = BitString.new('111111111')
400
+ # nbs = ~ bs
401
+ # nbs.to_s
402
+ # => "0"
403
+ #
404
+ # bs = BitString.new('111111111', 9)
405
+ # nbs = ~ bs
406
+ # nbs.to_s
407
+ # => "000000000"
408
+ #
409
+ # === Exceptions
410
+ # <i>None</i>.
411
+ #
412
+ def ~()
413
+ newval = (~ @value) & self.mask
414
+ bounded? ? self.class.new(newval, @length) : self.class.new(newval)
415
+ end # def ~
416
+
417
+ #
418
+ # === Description
419
+ #
420
+ # Perform an equality check against another bitstring or representation
421
+ # of one. The value and the boundedness must both match to be considered
422
+ # equal.
423
+ #
424
+ # call-seq:
425
+ # bitstring == <i>compstring</i> => <i>Boolean</i>
426
+ # bitstring.==<i>(compstring)</i> => <i>Boolean</i>
427
+ #
428
+ # === Arguments
429
+ # [<i>compstring</i>] <i>Array</i>, <i>BitString</i>, <i>Integer</i>, or <i>String</i>. Bitstring (or something representing one) against which to compare.
430
+ #
431
+ # === Examples
432
+ # bs1 = BitString.new('111111111')
433
+ # bs2 = BitString.new('111111111', 9)
434
+ # bs1 == bs2
435
+ # => false # Boundedness doesn't match
436
+ #
437
+ # bs1 = BitString.new('111111111')
438
+ # bs2 = BitString.new('111111111')
439
+ # bs1 == bs2
440
+ # => true # Values and boundedness match
441
+ #
442
+ # bs1 = BitString.new('111111111')
443
+ # bs1 == '111111111'
444
+ # => true # When converted to an unbounded bitstring, it matches
445
+ #
446
+ # bs1 = BitString.new('111111111')
447
+ # bs1 == '0000000111111111'
448
+ # => true # When converted to an unbounded bitstring, it matches
449
+ #
450
+ # bs1 = BitString.new('111111111')
451
+ # bs1 == 511
452
+ # => true # When converted to an unbounded bitstring, it matches
453
+ #
454
+ # bs1 = BitString.new('111111111', 9)
455
+ # bs1 == '1000111111111'
456
+ # => false # When converted to a bounded bitstring (because bs1 is),
457
+ # # lengths and values don't match
458
+ #
459
+ # === Exceptions
460
+ # <i>None</i>.
461
+ #
462
+ def ==(value)
463
+ #
464
+ # Bitstring/bitstring comparison
465
+ #
466
+ unless (value.class == self.class)
467
+ value = _arg2int(value)
468
+ if (self.bounded?)
469
+ bits = [self.length, value.to_s(2).length].max
470
+ value = self.class.new(value, bits)
471
+ else
472
+ value = self.class.new(value)
473
+ end
474
+ end
475
+ ((self.class == value.class) &&
476
+ (self.bounded? == value.bounded?) &&
477
+ (self.length == value.length) &&
478
+ (@value == value.to_i))
479
+ end # def ==
480
+
481
+ end # class BitString