geotree 1.1.4 → 1.1.5

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.txt +2 -0
  3. data/lib/geotree/tools.rb +237 -112
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e27ac7237a87748973d68e8e8ab42fa3fd3de713
4
- data.tar.gz: 2d3c2f8fe96472d903d0779b2f998af147c92b3e
3
+ metadata.gz: 85af00a89ad99ed45458d35e01dccd40130f1425
4
+ data.tar.gz: f09de405c3d93b22b4ad09433a145ca5f55178fc
5
5
  SHA512:
6
- metadata.gz: bd5d7194460709171d65219dbdf19686d24d2b8cf768c3aa5ac5fc4a010157654b4ad3cc44dea7c250ff578cab3b6484a40da57d9f7784740ef998599453ec1a
7
- data.tar.gz: 26cc87072057131efa87568e1990a8fd8aa8f2fed43b4f3424bfed117a81eb69d3b0958c7894d03b7a9bee130a0e2d826b35d4d2aeaba8e9466f6f2d8b5556ae
6
+ metadata.gz: d4391cce4097615644b4fa91925528e571ce5f0820aaefba2c7724f6d99d080fc0d400aa1e7f2f5775402a85944d206f1dae7cb1a772c2cdc1338c5e00031372
7
+ data.tar.gz: cdfff7ccafcb22a97141ae2b19addb6f3031e38d0e1f8ff110adce39c8337b3a302a1fdce2345f850b8bd9188d2afc74fe72e16a6bb8a0f5ae00cd00a1191557
@@ -15,3 +15,5 @@
15
15
  * Placed on github
16
16
  * Moved some documentation out of class headers and into README file
17
17
 
18
+ 2013-04-15
19
+ * No longer updating CHANGELOG.txt; consult git commit summaries instead.
@@ -1,13 +1,23 @@
1
1
  require 'set'
2
2
  require 'fileutils'
3
3
 
4
+ ###############################################################
5
+ #
4
6
  # Various utility and debug convenience functions.
5
7
  #
8
+ ###############################################################
9
+
10
+ # Exception class for objects in illegal states
11
+ #
12
+ class IllegalStateException < Exception
13
+ end
6
14
 
7
15
  # A string containing a single zero, with ASCII 8-bit encoding (i.e., plain old bytes)
8
16
  ZERO_CHAR = "\0".force_encoding("ASCII-8BIT")
9
17
 
10
-
18
+ # Construct a string of zeros
19
+ # @param count number of zeros
20
+ #
11
21
  def zero_bytes(count)
12
22
  ZERO_CHAR * count
13
23
  end
@@ -28,20 +38,16 @@ def req(fileListStr,subdir = nil)
28
38
  end
29
39
 
30
40
  # Shorthand for printf(...)
31
- # @param args passed to printf
32
- def pr(*args)
33
- printf(*args)
34
- end
35
-
41
+ #
42
+ alias :pr :printf
36
43
 
37
44
  # Convert an object to a human-readable string,
38
- # or <nil>
45
+ # or <nil>; should be considered a debug-only feature
39
46
  #
40
47
  def d(arg)
41
48
  arg.nil? ? "<nil>" : arg.inspect
42
49
  end
43
50
 
44
-
45
51
  # Convert an object to a human-readable string,
46
52
  # by calling a type-appropriate function: da, dh, or just d.
47
53
  # @param arg object
@@ -120,8 +126,6 @@ def df(flag, label=nil)
120
126
  s
121
127
  end
122
128
 
123
-
124
-
125
129
  # Assert that a value is true. Should be considered a
126
130
  # very temporary, debug-only option; it is slow and
127
131
  # generates a warning that it is being called.
@@ -134,6 +138,9 @@ def assert!(cond, *msg)
134
138
  raise Exception, str
135
139
  end
136
140
  end
141
+
142
+ # Abort with message about unimplemented code
143
+ #
137
144
  def unimp!(msg = nil)
138
145
  msg2 = "Unimplemented code"
139
146
  if msg
@@ -142,7 +149,27 @@ def unimp!(msg = nil)
142
149
  raise Exception, msg2
143
150
  end
144
151
 
145
-
152
+ # Extensions to the Enumerable module
153
+ #
154
+ module Enumerable
155
+ # Calculate a value for each item, and return the item with the
156
+ # highest value, its index, and the value.
157
+ # @yieldparam function to calculate value of an object, given that object as a parameter
158
+ # @return the triple [object, index, value] reflecting the maximum value, or
159
+ # nil if there were no items
160
+ def max_with_index
161
+
162
+ best = nil
163
+
164
+ each_with_index do |obj,ind|
165
+ sc = yield(obj)
166
+ if !best || best[2] < sc
167
+ best = [obj,ind,sc]
168
+ end
169
+ end
170
+ best
171
+ end
172
+ end
146
173
 
147
174
  # Get a nice, concise description of the file and line
148
175
  # of some caller within the stack.
@@ -211,6 +238,19 @@ def warn(*args)
211
238
  one_time_alert("warning",0, *args)
212
239
  end
213
240
 
241
+ # Convenience method for setting 'db' true within methods,
242
+ # and to print a one-time warning if so.
243
+ # @param val value to set db to; it is convenient to disable
244
+ # debug printing quickly by adding a zero, e.g., 'warndb 0'
245
+ #
246
+ def warndb(val = true)
247
+ if !val || val == 0
248
+ return false
249
+ end
250
+ one_time_alert("warning",1,"Debug printing enabled")
251
+ true
252
+ end
253
+
214
254
  # Print an 'unimplemented' alert, one time only
215
255
  # @param args if present, calls printf() with these
216
256
  def unimp(*args)
@@ -242,22 +282,30 @@ def block
242
282
  yield
243
283
  end
244
284
 
245
- # Exception class for objects in illegal states
285
+ # Construct hex representation of value
286
+ # @param value integer value
287
+ # @param num_digits number of hex digits
246
288
  #
247
- class IllegalStateException < Exception
248
- end
249
-
250
-
251
289
  def to_hex(value, num_digits=4)
252
290
  s = sprintf("%x", value)
253
291
  s.rjust(num_digits,'0')
254
292
  end
255
293
 
294
+ # Hex dump a string or byte array
295
+ # @param byte_array_or_string
296
+ # @param title
297
+ # @param offset offset to first value within array
298
+ # @param length number of values to dump
299
+ # @param bytes_per_row
300
+ # @param with_text if true, displays ASCII values to right of hex dump
301
+ #
256
302
  def hex_dump(byte_array_or_string, title=nil, offset=0, length= -1, bytes_per_row=16, with_text=true)
257
303
  ss = hex_dump_to_string(byte_array_or_string, title, offset, length, bytes_per_row, with_text)
258
304
  puts ss
259
305
  end
260
306
 
307
+ # Hex dump a string or byte array to a string; see hex_dump for parameter descriptions
308
+ #
261
309
  def hex_dump_to_string(byte_array_or_string, title=nil, offset=0, length= -1, bytes_per_row=16, with_text=true)
262
310
 
263
311
  byte_array = byte_array_or_string
@@ -300,10 +348,8 @@ def hex_dump_to_string(byte_array_or_string, title=nil, offset=0, length= -1, by
300
348
  else
301
349
  ss << ' '
302
350
  end
303
-
304
351
  end
305
352
 
306
-
307
353
  if with_text
308
354
  ss << ' |'
309
355
  bytes_per_row.times do |i|
@@ -327,6 +373,7 @@ $prevTime = nil
327
373
 
328
374
  # Calculate time elapsed, in seconds, from last call to this function;
329
375
  # if it's never been called, returns zero
376
+ #
330
377
  def elapsed
331
378
  curr = Time.now.to_f
332
379
  elap = 0
@@ -337,74 +384,9 @@ def elapsed
337
384
  elap
338
385
  end
339
386
 
340
- # Construct a string from an array of bytes
341
- # @param byte_array array of bytes, or string (in which case it
342
- # returns it unchanged)
343
- #
344
- def bytes_to_str(byte_array)
345
- return byte_array if byte_array.is_a? String
346
-
347
- byte_array.pack('C*')
348
- end
349
-
350
- # Construct an array of bytes from a string
351
- # @param str string, or array of bytes (in which case it
352
- # returns it unchanged)
353
- #
354
- def str_to_bytes(str)
355
- return str if str.is_a? Array
356
- str.bytes
357
- end
358
-
359
- # Get directory entries, excluding '.' and '..'
360
- #
361
- def dir_entries(path)
362
- ents = Dir.entries(path)
363
- ents.reject!{|entry| entry == '.' || entry == '..'}
364
- end
365
-
366
- # Convenience method for setting 'db' true within methods,
367
- # and to print a one-time warning if so.
368
- # @param val value to set db to; it is convenient to disable
369
- # debug printing quickly by adding a zero, e.g., 'warndb 0'
370
- #
371
- def warndb(val = true)
372
- if !val || val == 0
373
- return false
374
- end
375
- one_time_alert("warning",1, "Debug printing enabled")
376
- true
377
- end
378
-
379
-
380
- def int_to_bytes(x)
381
- [(x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff]
382
- end
383
-
384
- def short_to_bytes(x)
385
- [(x >> 8) & 0xff, x & 0xff]
386
- end
387
-
388
- # Decode a short from an array of bytes (big-endian).
389
- # @param ba array of bytes
390
- # @param offset offset of first (most significant) byte
391
- #
392
- def short_from_bytes(ba, offset=0)
393
- (ba[offset] << 8) | ba[offset + 1]
394
- end
395
-
396
- # Decode an int from an array of bytes (big-endian).
397
- # @param ba array of bytes
398
- # @param offset offset of first (most significant) byte
399
- #
400
- def int_from_bytes(ba, offset=0)
401
- (((((ba[offset] << 8) | ba[offset + 1]) << 8) | \
402
- ba[offset + 2]) << 8) | ba[offset + 3]
403
- end
404
-
405
-
406
387
  # Delete a file or directory, if it exists.
407
388
  # Caution! If directory, deletes all files and subdirectories.
389
+ #
408
390
  def remove_file_or_dir(pth)
409
391
  if File.directory?(pth)
410
392
  FileUtils.remove_dir(pth)
@@ -413,46 +395,101 @@ def remove_file_or_dir(pth)
413
395
  end
414
396
  end
415
397
 
416
- # Transform string to 8-bit ASCII (i.e., just treat each byte as-is)
398
+ require 'stringio'
399
+
400
+ $IODest = nil
401
+ $OldStdOut = nil
402
+
403
+ # Redirect standard output to an internal string
417
404
  #
418
- def to_ascii8(str)
419
- str.force_encoding("ASCII-8BIT")
405
+ def capture_begin
406
+ raise IllegalStateException if $IODest
407
+ $IODest = StringIO.new
408
+ $OldStdOut, $stdout = $stdout, $IODest
420
409
  end
421
410
 
422
- # Verify that a string is encoded as ASCII-8BIT
423
- def simple_str(s)
424
- if s.encoding.name != 'ASCII-8BIT' && s.encoding.name != 'UTF-8'
425
- pr("string [%s]\n encoding is %s,\n expected ASCII-8BIT\n",s,s.encoding.name)
426
- assert!(false)
427
- end
411
+ # Restore standard output; return captured text
412
+ # @return text that was redirected
413
+ #
414
+ def capture_end
415
+ raise IllegalStateException if !$IODest
416
+ $stdout = $OldStdOut
417
+ ret = $IODest.string
418
+ $IODest = nil
419
+ ret
428
420
  end
429
421
 
430
- # Truncate or pad string so it has a particular size
422
+ # Compare a string with disk file; abort if different. Disk filename is derived
423
+ # from caller function name; e.g., test_xxx produces filename _output_xxx
431
424
  #
432
- # @param s input string
433
- # @param size
434
- # @param pad padding character to use if string needs to grow
435
- # @return modified string
425
+ # @param str if not nil, string to compare; if nil, calls capture_end to get string
436
426
  #
437
- def str_sized(s, size, pad="\0")
438
- s[0...size].ljust(size,pad)
439
- end
427
+ def match_expected_output(str = nil)
440
428
 
441
- # Determine if running on the Windows operating system.
442
- # Note: there is some debate about the best way to do this.
443
- #
444
- def windows?
445
- if !defined? $__windows__
446
- $__windows__ = (RUBY_PLATFORM =~ /mswin/)
429
+ if !str
430
+ str = capture_end
447
431
  end
448
- $__windows__
449
- end
450
432
 
433
+ cl_method = caller[0][/`.*'/][1..-2]
434
+ if (cl_method.start_with?("test_"))
435
+ cl_method = cl_method[5..-1]
436
+ end
437
+ path = "_output_" + cl_method + ".txt"
438
+
439
+ if !File.file?(path)
440
+ printf("no such file #{path} exists, writing it...\n")
441
+ write_text_file(path,str)
442
+ else
443
+ exp_cont = read_text_file(path)
444
+ if str != exp_cont
445
+ d1 = str
446
+ d2 = exp_cont
447
+
448
+ # Find location where they differ
449
+ lines1 = d1.split("\n")
450
+ lines2 = d2.split("\n")
451
+ j = [lines1.size, lines2.size].max
452
+
453
+ s = "???"
454
+ found_diff = false
455
+ hist = []
456
+
457
+ found_count = 0
458
+ j.times do |i|
459
+ found_diff ||= (i >= lines1.size || i >= lines2.size || lines1[i] != lines2[i])
460
+ s = sprintf("%3d:",i)
461
+ if !found_diff
462
+ hist << "#{s} #{lines1[i]}\n #{lines2[i]}\n"
463
+ else
464
+ if found_count < 3
465
+ if i < lines1.size
466
+ s << " #{lines1[i]}\n"
467
+ else
468
+ s << " ---END---\n"
469
+ end
470
+ if i < lines2.size
471
+ s << " #{lines2[i]}\n"
472
+ else
473
+ s << " ---END---\n"
474
+ end
475
+ hist << s
476
+ end
477
+ found_count += 1
478
+ end
479
+ while hist.size > 6
480
+ hist.shift
481
+ end
482
+ end
483
+ dash = "-" * 95 + "\n"
484
+ raise IllegalStateException,"output did not match expected:\n#{dash}#{hist.join('')}#{dash}"
485
+ end
486
+ end
487
+ end
451
488
 
452
489
  # Convenience method to detect if a script is being run
453
490
  # e.g. as a 'main' method (for debug purposes only).
454
491
  # If so, it changes the current directory to the
455
- # directory containing the script.
492
+ # directory containing the script (if such a directory exists).
456
493
  #
457
494
  # @param file pass __FILE__ in here
458
495
  # @return true if so
@@ -469,7 +506,10 @@ def main?(file)
469
506
  end
470
507
 
471
508
  if (ret = (file == scr))
472
- Dir.chdir(File.dirname(file))
509
+ dr = File.dirname(file)
510
+ if File.directory?(dr)
511
+ Dir.chdir(dr)
512
+ end
473
513
  end
474
514
  ret
475
515
  end
@@ -577,6 +617,92 @@ if defined? Test::Unit
577
617
  end
578
618
  end
579
619
 
620
+ # Construct a string from an array of bytes
621
+ # @param byte_array array of bytes, or string (in which case it
622
+ # returns it unchanged)
623
+ #
624
+ def bytes_to_str(byte_array)
625
+ return byte_array if byte_array.is_a? String
626
+
627
+ byte_array.pack('C*')
628
+ end
629
+
630
+ # Construct an array of bytes from a string
631
+ # @param str string, or array of bytes (in which case it
632
+ # returns it unchanged)
633
+ #
634
+ def str_to_bytes(str)
635
+ return str if str.is_a? Array
636
+ str.bytes
637
+ end
638
+
639
+ # Get directory entries, excluding '.' and '..'
640
+ #
641
+ def dir_entries(path)
642
+ ents = Dir.entries(path)
643
+ ents.reject!{|entry| entry == '.' || entry == '..'}
644
+ end
645
+
646
+ def int_to_bytes(x)
647
+ [(x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff]
648
+ end
649
+
650
+ def short_to_bytes(x)
651
+ [(x >> 8) & 0xff, x & 0xff]
652
+ end
653
+
654
+ # Decode a short from an array of bytes (big-endian).
655
+ # @param ba array of bytes
656
+ # @param offset offset of first (most significant) byte
657
+ #
658
+ def short_from_bytes(ba, offset=0)
659
+ (ba[offset] << 8) | ba[offset + 1]
660
+ end
661
+
662
+ # Decode an int from an array of bytes (big-endian).
663
+ # @param ba array of bytes
664
+ # @param offset offset of first (most significant) byte
665
+ #
666
+ def int_from_bytes(ba, offset=0)
667
+ (((((ba[offset] << 8) | ba[offset + 1]) << 8) | \
668
+ ba[offset + 2]) << 8) | ba[offset + 3]
669
+ end
670
+
671
+ # Transform string to 8-bit ASCII (i.e., just treat each byte as-is)
672
+ #
673
+ def to_ascii8(str)
674
+ str.force_encoding("ASCII-8BIT")
675
+ end
676
+
677
+ # Verify that a string is encoded as ASCII-8BIT
678
+ def simple_str(s)
679
+ if s.encoding.name != 'ASCII-8BIT' && s.encoding.name != 'UTF-8'
680
+ pr("string [%s]\n encoding is %s,\n expected ASCII-8BIT\n",s,s.encoding.name)
681
+ assert!(false)
682
+ end
683
+ end
684
+
685
+ # Truncate or pad string so it has a particular size
686
+ #
687
+ # @param s input string
688
+ # @param size
689
+ # @param pad padding character to use if string needs to grow
690
+ # @return modified string
691
+ #
692
+ def str_sized(s, size, pad="\0")
693
+ s[0...size].ljust(size,pad)
694
+ end
695
+
696
+ # Determine if running on the Windows operating system.
697
+ # Note: there is some debate about the best way to do this.
698
+ #
699
+ def windows?
700
+ if !defined? $__windows__
701
+ $__windows__ = (RUBY_PLATFORM =~ /mswin/)
702
+ end
703
+ $__windows__
704
+ end
705
+
580
706
  # Mark all constants ending with '_' as private constants
581
707
  #
582
708
  # @param entity the class to examine
@@ -624,4 +750,3 @@ def privatize(entity, add_non_suffix_versions = false)
624
750
  eval(cmd2)
625
751
  end
626
752
  end
627
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geotree
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Sember
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-09 00:00:00.000000000 Z
11
+ date: 2013-04-15 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: " \nA GeoTree is a variant of a k-d tree, and stores data points that
14
14
  have a latitude and longitude, \na unique integer identifier, and an optional 'weight'