fast_blank 0.0.1
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 +7 -0
- data/MIT-LICENSE +21 -0
- data/README.md +57 -0
- data/benchmark +40 -0
- data/ext/fast_blank/extconf.rb +2 -0
- data/ext/fast_blank/fast_blank.c +83 -0
- data/lib/.gemkeep +0 -0
- data/spec/fast_blank_spec.rb +51 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 23b988d318c1c1da6a788a6d0c3b1f7f0f65e6ca
|
4
|
+
data.tar.gz: ba4ef389e4cebb24ba9ac8e1fc8c5d263b817d94
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 88222e2184cf6394fd34fb5840e8ca30013e68cac6ea2f0a5408252eafe97a121db72baa42ec10bee14d7ae1ccced2f66974fcfa76c3d999f989050fe183b118
|
7
|
+
data.tar.gz: 74e3a6270528702e72428564215614a81564e2a475dfe797db27ebb5780d9cb8e452f7fc458767cbfea9a127de0ab6607879733bbee6e8916c8ac72231c55693
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2006-2009 Steve Sloan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
### String blank? Ruby Extension
|
2
|
+
|
3
|
+
`fast_blank` is a simple extension which provides a fast implementation of active support's string#blank? function
|
4
|
+
|
5
|
+
### How do you use it?
|
6
|
+
|
7
|
+
require 'fast_blank'
|
8
|
+
|
9
|
+
### How fast is "Fast"?
|
10
|
+
|
11
|
+
|
12
|
+
About 5-9x faster than current active support, on my machine (your mileage my vary):
|
13
|
+
|
14
|
+
$ ./benchmark
|
15
|
+
|
16
|
+
```
|
17
|
+
user system total real
|
18
|
+
user system total real
|
19
|
+
Fast Blank 0 : 0.070000 0.000000 0.070000 ( 0.075247)
|
20
|
+
Fast Blank (Active Support) 0 : 0.080000 0.000000 0.080000 ( 0.075029)
|
21
|
+
Slow Blank 0 : 0.500000 0.000000 0.500000 ( 0.503026)
|
22
|
+
Fast Blank 6 : 0.200000 0.000000 0.200000 ( 0.191480)
|
23
|
+
Fast Blank (Active Support) 6 : 0.180000 0.000000 0.180000 ( 0.179891)
|
24
|
+
Slow Blank 6 : 0.660000 0.000000 0.660000 ( 0.658604)
|
25
|
+
Fast Blank 14 : 0.080000 0.010000 0.090000 ( 0.086371)
|
26
|
+
Fast Blank (Active Support) 14 : 0.130000 0.000000 0.130000 ( 0.129258)
|
27
|
+
Slow Blank 14 : 0.890000 0.000000 0.890000 ( 0.886140)
|
28
|
+
Fast Blank 24 : 0.150000 0.000000 0.150000 ( 0.158151)
|
29
|
+
Fast Blank (Active Support) 24 : 0.140000 0.000000 0.140000 ( 0.149284)
|
30
|
+
Slow Blank 24 : 0.900000 0.000000 0.900000 ( 0.899663)
|
31
|
+
Fast Blank 136 : 0.130000 0.000000 0.130000 ( 0.125831)
|
32
|
+
Fast Blank (Active Support) 136 : 0.150000 0.000000 0.150000 ( 0.148948)
|
33
|
+
Slow Blank 136 : 0.900000 0.000000 0.900000 ( 0.899885)
|
34
|
+
|
35
|
+
|
36
|
+
```
|
37
|
+
|
38
|
+
|
39
|
+
Additionally, this gem allocates no strings during the test, making it less of a GC burden.
|
40
|
+
|
41
|
+
|
42
|
+
###Compatability note:
|
43
|
+
|
44
|
+
fast_blank implements string.blank? as MRI would have it implemented, meaning it has 100% parity with `String#strip.length == 0`.
|
45
|
+
|
46
|
+
|
47
|
+
Active Supports version looks also at unicode spaces
|
48
|
+
for example: `"\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000".blank?` is true in Active Support even though fast_blank would treat it as not blank.
|
49
|
+
|
50
|
+
fast_blank also provides blank_as? which is a 100% compatible blank? replacement.
|
51
|
+
|
52
|
+
Author: Sam Saffron sam.saffron@gmail.com
|
53
|
+
http://github.com/SamSaffron/fast_blank
|
54
|
+
License: MIT
|
55
|
+
|
56
|
+
|
57
|
+
(gem template based on https://github.com/CodeMonkeySteve/fast_xor )
|
data/benchmark
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.dirname(__FILE__)+'/lib'
|
3
|
+
require 'benchmark'
|
4
|
+
require 'fast_blank'
|
5
|
+
|
6
|
+
class String
|
7
|
+
# active support implementation
|
8
|
+
def slow_blank?
|
9
|
+
self !~ /[^[:space:]]/
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
n = 1000000
|
15
|
+
|
16
|
+
|
17
|
+
strings = [
|
18
|
+
"",
|
19
|
+
"\r\n\r\n ",
|
20
|
+
"this is a test",
|
21
|
+
" this is a longer test",
|
22
|
+
" this is a longer test
|
23
|
+
this is a longer test
|
24
|
+
this is a longer test
|
25
|
+
this is a longer test
|
26
|
+
this is a longer test"
|
27
|
+
]
|
28
|
+
|
29
|
+
strings.each do |s|
|
30
|
+
raise "failed on #{s.inspect}" if s.blank? != s.slow_blank?
|
31
|
+
end
|
32
|
+
|
33
|
+
Benchmark.bmbm do |x|
|
34
|
+
strings.each do |s|
|
35
|
+
x.report("Fast Blank #{s.length} :") do n.times { s.blank? } end
|
36
|
+
x.report("Fast Blank (Active Support) #{s.length} :") do n.times { s.blank_as? } end
|
37
|
+
x.report("Slow Blank #{s.length} :") do n.times { s.slow_blank? } end
|
38
|
+
#x.report("Empty #{s.length} :") do n.times { s.empty? } end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <ruby.h>
|
3
|
+
#include <ruby/encoding.h>
|
4
|
+
#include <ruby/re.h>
|
5
|
+
|
6
|
+
#define STR_ENC_GET(str) rb_enc_from_index(ENCODING_GET(str))
|
7
|
+
|
8
|
+
/* Backward compatibility with Ruby 1.8 */
|
9
|
+
#ifndef RSTRING_PTR
|
10
|
+
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
11
|
+
#endif
|
12
|
+
#ifndef RSTRING_LEN
|
13
|
+
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
14
|
+
#endif
|
15
|
+
|
16
|
+
const unsigned int as_blank[26] = {9, 0xa, 0xb, 0xc, 0xd,
|
17
|
+
0x20, 0x85, 0xa0, 0x1680, 0x180e, 0x2000, 0x2001,
|
18
|
+
0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
|
19
|
+
0x2009, 0x200a, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000
|
20
|
+
};
|
21
|
+
|
22
|
+
static VALUE
|
23
|
+
rb_str_blank_as(VALUE str)
|
24
|
+
{
|
25
|
+
rb_encoding *enc;
|
26
|
+
char *s, *e;
|
27
|
+
int i;
|
28
|
+
int found;
|
29
|
+
|
30
|
+
enc = STR_ENC_GET(str);
|
31
|
+
s = RSTRING_PTR(str);
|
32
|
+
if (!s || RSTRING_LEN(str) == 0) return Qtrue;
|
33
|
+
|
34
|
+
e = RSTRING_END(str);
|
35
|
+
while (s < e) {
|
36
|
+
int n;
|
37
|
+
unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
|
38
|
+
|
39
|
+
found = 0;
|
40
|
+
for(i=0;i<26;i++){
|
41
|
+
unsigned int current = as_blank[i];
|
42
|
+
if(current == cc) {
|
43
|
+
found = 1;
|
44
|
+
break;
|
45
|
+
}
|
46
|
+
if(cc < current){
|
47
|
+
break;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
if (!found) return Qfalse;
|
52
|
+
s += n;
|
53
|
+
}
|
54
|
+
return Qtrue;
|
55
|
+
}
|
56
|
+
|
57
|
+
static VALUE
|
58
|
+
rb_str_blank(VALUE str)
|
59
|
+
{
|
60
|
+
rb_encoding *enc;
|
61
|
+
char *s, *e;
|
62
|
+
|
63
|
+
enc = STR_ENC_GET(str);
|
64
|
+
s = RSTRING_PTR(str);
|
65
|
+
if (!s || RSTRING_LEN(str) == 0) return Qtrue;
|
66
|
+
|
67
|
+
e = RSTRING_END(str);
|
68
|
+
while (s < e) {
|
69
|
+
int n;
|
70
|
+
unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
|
71
|
+
|
72
|
+
if (!rb_isspace(cc) && cc != 0) return Qfalse;
|
73
|
+
s += n;
|
74
|
+
}
|
75
|
+
return Qtrue;
|
76
|
+
}
|
77
|
+
|
78
|
+
|
79
|
+
void Init_fast_blank( void )
|
80
|
+
{
|
81
|
+
rb_define_method(rb_cString, "blank?", rb_str_blank, 0);
|
82
|
+
rb_define_method(rb_cString, "blank_as?", rb_str_blank_as, 0);
|
83
|
+
}
|
data/lib/.gemkeep
ADDED
File without changes
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'fast_blank'
|
2
|
+
|
3
|
+
class ::String
|
4
|
+
def blank2?
|
5
|
+
self !~ /[^[:space:]]/
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe String do
|
10
|
+
it "works" do
|
11
|
+
"".blank?.should == true
|
12
|
+
" ".blank?.should == true
|
13
|
+
"\r\n".blank?.should == true
|
14
|
+
"\r\n\v\f\r\s\u0085".blank? == true
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
it "provides a parity with active support function" do
|
19
|
+
(16*16*16*16).times do |i|
|
20
|
+
c = i.chr('UTF-8') rescue nil
|
21
|
+
unless c.nil?
|
22
|
+
"#{i.to_s(16)} #{c.blank_as?}".should == "#{i.to_s(16)} #{c.blank2?}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
(256).times do |i|
|
28
|
+
c = i.chr('ASCII') rescue nil
|
29
|
+
unless c.nil?
|
30
|
+
"#{i.to_s(16)} #{c.blank_as?}".should == "#{i.to_s(16)} #{c.blank2?}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "has parity with strip.length" do
|
36
|
+
(256).times do |i|
|
37
|
+
c = i.chr('ASCII') rescue nil
|
38
|
+
unless c.nil?
|
39
|
+
"#{i.to_s(16)} #{c.strip.length == 0}".should == "#{i.to_s(16)} #{c.blank?}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "treats \u0000 correctly" do
|
45
|
+
# odd I know
|
46
|
+
"\u0000".strip.length.should == 0
|
47
|
+
"\u0000".blank_as?.should be_false
|
48
|
+
"\u0000".blank?.should be_true
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fast_blank
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sam Saffron
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-03-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake-compiler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Provides a C-optimized method for determining if a string is blank
|
56
|
+
email: sam.saffron@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions:
|
59
|
+
- ext/fast_blank/extconf.rb
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- README.md
|
64
|
+
- benchmark
|
65
|
+
- lib/.gemkeep
|
66
|
+
- ext/fast_blank/fast_blank.c
|
67
|
+
- ext/fast_blank/extconf.rb
|
68
|
+
- spec/fast_blank_spec.rb
|
69
|
+
homepage: ''
|
70
|
+
licenses: []
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.0.2
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Fast String blank? implementation
|
92
|
+
test_files:
|
93
|
+
- spec/fast_blank_spec.rb
|