epitools 0.5.36 → 0.5.37
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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/epitools/core_ext.rb +1 -0
- data/lib/epitools/core_ext/file.rb +102 -0
- data/lib/epitools/core_ext/misc.rb +9 -0
- data/lib/epitools/core_ext/string.rb +4 -2
- data/spec/core_ext_spec.rb +12 -0
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74b5a665bc66555050576a5aa863b79017d10e90
|
4
|
+
data.tar.gz: a860badfc15c9f1f44f7d8db7aa4f47d2ef32bd4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d19c2fd984f89485d8a00f7c2f8c5fb0cdeff916b1bf7fa8ea4a5922c447258a56ea21b610ae20e6c5e0b27d5e4679a4d9617b7263d9dbe1b36eaefff4a8f8e
|
7
|
+
data.tar.gz: db684ad10202d61c32167346cf6e3032316041308a0914bd3be5ac5b3ef535a687362966be703778f573686180c526ea3d4525957b9042669bb1cbd9d497e888
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.37
|
data/lib/epitools/core_ext.rb
CHANGED
@@ -5,6 +5,7 @@ require 'epitools'
|
|
5
5
|
require 'epitools/core_ext/object'
|
6
6
|
require 'epitools/core_ext/string'
|
7
7
|
require 'epitools/core_ext/array'
|
8
|
+
require 'epitools/core_ext/file'
|
8
9
|
require 'epitools/core_ext/enumerable'
|
9
10
|
require 'epitools/core_ext/hash'
|
10
11
|
require 'epitools/core_ext/numbers'
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'epitools/minimal'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Beginning of File reached! (Raised when reading a file backwards.)
|
5
|
+
#
|
6
|
+
class BOFError < Exception; end
|
7
|
+
|
8
|
+
class File
|
9
|
+
|
10
|
+
#
|
11
|
+
# A much faster `reverse_each` implementation.
|
12
|
+
#
|
13
|
+
def reverse_each(&block)
|
14
|
+
return to_enum(:reverse_each) unless block_given?
|
15
|
+
|
16
|
+
seek_end
|
17
|
+
reverse_each_from_current_pos(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Read the previous +length+ bytes. After the read, +pos+ will be at the beginning of the region that you just read.
|
22
|
+
#
|
23
|
+
def read_backwards(length)
|
24
|
+
old_pos = pos
|
25
|
+
|
26
|
+
if length > pos
|
27
|
+
seek(0)
|
28
|
+
else
|
29
|
+
seek(-length, IO::SEEK_CUR)
|
30
|
+
end
|
31
|
+
|
32
|
+
new_pos = pos
|
33
|
+
data = read(old_pos - new_pos)
|
34
|
+
seek(new_pos)
|
35
|
+
|
36
|
+
data
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Read each line of file backwards (from the current position.)
|
41
|
+
#
|
42
|
+
def reverse_each_from_current_pos
|
43
|
+
return to_enum(:reverse_each_from_current_pos) unless block_given?
|
44
|
+
|
45
|
+
fragment = readline rescue ""
|
46
|
+
|
47
|
+
loop do
|
48
|
+
data = read_backwards(4096) + fragment
|
49
|
+
loc = data.size-1
|
50
|
+
|
51
|
+
# NOTE: `rindex(str, loc)` includes the character at `loc`
|
52
|
+
while index = data.rindex("\n", loc-1)
|
53
|
+
line = data[index+1..loc]
|
54
|
+
yield line
|
55
|
+
loc = index
|
56
|
+
end
|
57
|
+
|
58
|
+
fragment = data[0..loc]
|
59
|
+
|
60
|
+
break if pos == 0 # we're done reading!
|
61
|
+
end
|
62
|
+
|
63
|
+
yield fragment
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Seek to `EOF`
|
68
|
+
#
|
69
|
+
def seek_end
|
70
|
+
seek(0, IO::SEEK_END)
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Read the previous line (leaving `pos` at the beginning of the string that was read.)
|
75
|
+
#
|
76
|
+
def reverse_readline
|
77
|
+
raise BOFError.new("beginning of file reached") if pos == 0
|
78
|
+
|
79
|
+
seek_backwards_to("\n", 512, -2)
|
80
|
+
new_pos = pos
|
81
|
+
data = readline
|
82
|
+
seek(new_pos)
|
83
|
+
data
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Scan backwards in the file until `string` is found, and set the IO's +pos+ to the first character after the matched string.
|
88
|
+
#
|
89
|
+
def seek_backwards_to(string, blocksize=512, rindex_end=-1)
|
90
|
+
loop do
|
91
|
+
data = read_backwards(blocksize)
|
92
|
+
|
93
|
+
if index = data.rindex(string, rindex_end)
|
94
|
+
seek(index+string.size, IO::SEEK_CUR)
|
95
|
+
break
|
96
|
+
elsif pos == 0
|
97
|
+
break
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -268,16 +268,18 @@ class String
|
|
268
268
|
|
269
269
|
# `true` if this string starts with the substring
|
270
270
|
#
|
271
|
-
def startswith(substring)
|
271
|
+
def startswith?(substring)
|
272
272
|
self[0...substring.size] == substring
|
273
273
|
end
|
274
|
+
alias_method :startswith, :startswith?
|
274
275
|
|
275
276
|
#
|
276
277
|
# `true` if this string ends with the substring
|
277
278
|
#
|
278
|
-
def endswith(substring)
|
279
|
+
def endswith?(substring)
|
279
280
|
self[-substring.size..-1] == substring
|
280
281
|
end
|
282
|
+
alias_method :endswith, :endswith?
|
281
283
|
|
282
284
|
#
|
283
285
|
# Parse this string as JSON
|
data/spec/core_ext_spec.rb
CHANGED
@@ -754,4 +754,16 @@ describe "to_hms and from_hms" do
|
|
754
754
|
60.to_hms.from_hms.should == 60
|
755
755
|
"1:20:33".from_hms.to_hms.should == "01:20:33"
|
756
756
|
"5:01:20:33".from_hms.to_hms.should == "05:01:20:33"
|
757
|
+
end
|
758
|
+
|
759
|
+
|
760
|
+
describe File do
|
761
|
+
|
762
|
+
it "reverse_eaches" do
|
763
|
+
tmp = Path.tmp
|
764
|
+
tmp << "hi\nthere\neveryone!\n"
|
765
|
+
f = open(tmp)
|
766
|
+
f.reverse_each.to_a.should == ["everyone!\n", "there\n", "hi\n"]
|
767
|
+
end
|
768
|
+
|
757
769
|
end
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: epitools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.37
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- epitron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
description: Miscellaneous utility libraries to make my life easier.
|
@@ -33,9 +33,9 @@ extra_rdoc_files:
|
|
33
33
|
- README.rdoc
|
34
34
|
- TODO
|
35
35
|
files:
|
36
|
-
-
|
37
|
-
-
|
38
|
-
-
|
36
|
+
- .document
|
37
|
+
- .gemspec
|
38
|
+
- .gitignore
|
39
39
|
- Guardfile
|
40
40
|
- LICENSE
|
41
41
|
- README.rdoc
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- lib/epitools/core_ext.rb
|
53
53
|
- lib/epitools/core_ext/array.rb
|
54
54
|
- lib/epitools/core_ext/enumerable.rb
|
55
|
+
- lib/epitools/core_ext/file.rb
|
55
56
|
- lib/epitools/core_ext/hash.rb
|
56
57
|
- lib/epitools/core_ext/matrix.rb
|
57
58
|
- lib/epitools/core_ext/misc.rb
|
@@ -113,17 +114,17 @@ require_paths:
|
|
113
114
|
- lib
|
114
115
|
required_ruby_version: !ruby/object:Gem::Requirement
|
115
116
|
requirements:
|
116
|
-
- -
|
117
|
+
- - '>='
|
117
118
|
- !ruby/object:Gem::Version
|
118
119
|
version: '0'
|
119
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
121
|
requirements:
|
121
|
-
- -
|
122
|
+
- - '>='
|
122
123
|
- !ruby/object:Gem::Version
|
123
124
|
version: '0'
|
124
125
|
requirements: []
|
125
126
|
rubyforge_project:
|
126
|
-
rubygems_version: 2.
|
127
|
+
rubygems_version: 2.1.11
|
127
128
|
signing_key:
|
128
129
|
specification_version: 3
|
129
130
|
summary: Not utils... METILS!
|