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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 62218ee364081707cdf868454642a359f73863c2
4
- data.tar.gz: 61fdb3c5bd004f72a9d1c8a3f769d8d325226867
3
+ metadata.gz: 74b5a665bc66555050576a5aa863b79017d10e90
4
+ data.tar.gz: a860badfc15c9f1f44f7d8db7aa4f47d2ef32bd4
5
5
  SHA512:
6
- metadata.gz: e7941b58505310ee7212e344ff45a890455b07354a2a934b589863e4b079b8b66d6369883d11d44978268e84bdb5032d4cfdc20e4161155e45dffcedc4c0aac1
7
- data.tar.gz: 9dcea6e9c715edf1c33d22a0f5afa84a3dde31a07bc9b5bbee7023ad6c97009c9ec77f27f6bb7d82169fbafd452c95363f173d5d237af507977f7dddcb21e652
6
+ metadata.gz: 1d19c2fd984f89485d8a00f7c2f8c5fb0cdeff916b1bf7fa8ea4a5922c447258a56ea21b610ae20e6c5e0b27d5e4679a4d9617b7263d9dbe1b36eaefff4a8f8e
7
+ data.tar.gz: db684ad10202d61c32167346cf6e3032316041308a0914bd3be5ac5b3ef535a687362966be703778f573686180c526ea3d4525957b9042669bb1cbd9d497e888
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.36
1
+ 0.5.37
@@ -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
@@ -178,6 +178,15 @@ class Range
178
178
  Kernel.rand(self)
179
179
  end
180
180
 
181
+ #
182
+ # The middle element of this range.
183
+ #
184
+ def middle
185
+ (min + max) / 2
186
+ end
187
+
188
+
189
+
181
190
  end
182
191
 
183
192
 
@@ -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
@@ -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.36
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-10-13 00:00:00.000000000 Z
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
- - ".document"
37
- - ".gemspec"
38
- - ".gitignore"
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.0.3
127
+ rubygems_version: 2.1.11
127
128
  signing_key:
128
129
  specification_version: 3
129
130
  summary: Not utils... METILS!