epitools 0.5.36 → 0.5.37
Sign up to get free protection for your applications and to get access to all the features.
- 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!
|