geotree 1.1.4 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.txt +2 -0
- data/lib/geotree/tools.rb +237 -112
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85af00a89ad99ed45458d35e01dccd40130f1425
|
4
|
+
data.tar.gz: f09de405c3d93b22b4ad09433a145ca5f55178fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4391cce4097615644b4fa91925528e571ce5f0820aaefba2c7724f6d99d080fc0d400aa1e7f2f5775402a85944d206f1dae7cb1a772c2cdc1338c5e00031372
|
7
|
+
data.tar.gz: cdfff7ccafcb22a97141ae2b19addb6f3031e38d0e1f8ff110adce39c8337b3a302a1fdce2345f850b8bd9188d2afc74fe72e16a6bb8a0f5ae00cd00a1191557
|
data/CHANGELOG.txt
CHANGED
data/lib/geotree/tools.rb
CHANGED
@@ -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
|
-
#
|
32
|
-
|
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
|
-
#
|
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
|
-
|
398
|
+
require 'stringio'
|
399
|
+
|
400
|
+
$IODest = nil
|
401
|
+
$OldStdOut = nil
|
402
|
+
|
403
|
+
# Redirect standard output to an internal string
|
417
404
|
#
|
418
|
-
def
|
419
|
-
|
405
|
+
def capture_begin
|
406
|
+
raise IllegalStateException if $IODest
|
407
|
+
$IODest = StringIO.new
|
408
|
+
$OldStdOut, $stdout = $stdout, $IODest
|
420
409
|
end
|
421
410
|
|
422
|
-
#
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
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
|
-
#
|
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
|
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
|
438
|
-
s[0...size].ljust(size,pad)
|
439
|
-
end
|
427
|
+
def match_expected_output(str = nil)
|
440
428
|
|
441
|
-
|
442
|
-
|
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
|
-
|
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
|
+
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-
|
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'
|