geotree 1.1.4 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
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'