burke-monkeysupport 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ *.bundle
7
+ *.so
8
+ *.dll
9
+ *.o
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Burke Libbey
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.
data/README.rdoc ADDED
@@ -0,0 +1,18 @@
1
+ = monkeysupport
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2009 Burke Libbey. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "monkeysupport"
8
+ gem.summary = %Q{Monkeypatching Rails with C since 2009}
9
+ gem.description = %Q{MonkeySupport provides C implementations for some of the more intensive string manipulation methods in activesupport. ActionView is up next.}
10
+ gem.email = "burke@burkelibbey.org"
11
+ gem.homepage = "http://github.com/burke/monkeysupport"
12
+ gem.authors = ["Burke Libbey"]
13
+ gem.files.include '{test,lib,ext}/**/*'
14
+ gem.extensions = ["ext/extconf.rb"]
15
+ gem.add_development_dependency "thoughtbot-shoulda"
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/*_test.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/*_test.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ if File.exist?('VERSION')
49
+ version = File.read('VERSION')
50
+ else
51
+ version = ""
52
+ end
53
+
54
+ rdoc.rdoc_dir = 'rdoc'
55
+ rdoc.title = "monkeysupport #{version}"
56
+ rdoc.rdoc_files.include('README*')
57
+ rdoc.rdoc_files.include('lib/**/*.rb')
58
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.3
data/ext/Makefile ADDED
@@ -0,0 +1,157 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ exec_prefix = $(prefix)
11
+ prefix = $(DESTDIR)/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr
12
+ sharedstatedir = $(prefix)/com
13
+ mandir = $(DESTDIR)/usr/share/man
14
+ psdir = $(docdir)
15
+ oldincludedir = $(DESTDIR)/usr/include
16
+ localedir = $(datarootdir)/locale
17
+ bindir = $(exec_prefix)/bin
18
+ libexecdir = $(exec_prefix)/libexec
19
+ sitedir = $(DESTDIR)/Library/Ruby/Site
20
+ htmldir = $(docdir)
21
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
22
+ includedir = $(prefix)/include
23
+ infodir = $(DESTDIR)/usr/share/info
24
+ vendorlibdir = $(vendordir)/$(ruby_version)
25
+ sysconfdir = $(prefix)/etc
26
+ libdir = $(exec_prefix)/lib
27
+ sbindir = $(exec_prefix)/sbin
28
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
29
+ docdir = $(datarootdir)/doc/$(PACKAGE)
30
+ dvidir = $(docdir)
31
+ vendordir = $(libdir)/ruby/vendor_ruby
32
+ datarootdir = $(prefix)/share
33
+ pdfdir = $(docdir)
34
+ archdir = $(rubylibdir)/$(arch)
35
+ sitearchdir = $(sitelibdir)/$(sitearch)
36
+ datadir = $(datarootdir)
37
+ localstatedir = $(prefix)/var
38
+ sitelibdir = $(sitedir)/$(ruby_version)
39
+
40
+ CC = gcc
41
+ LIBRUBY = $(LIBRUBY_SO)
42
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
43
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
44
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)
45
+
46
+ RUBY_EXTCONF_H =
47
+ CFLAGS = -fno-common -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common $(cflags)
48
+ INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
49
+ DEFS =
50
+ CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
51
+ CXXFLAGS = $(CFLAGS)
52
+ ldflags = -L. -arch i386 -arch x86_64
53
+ dldflags =
54
+ archflag =
55
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
56
+ LDSHARED = cc -arch i386 -arch x86_64 -pipe -bundle -undefined dynamic_lookup
57
+ AR = ar
58
+ EXEEXT =
59
+
60
+ RUBY_INSTALL_NAME = ruby
61
+ RUBY_SO_NAME = ruby
62
+ arch = universal-darwin10.0
63
+ sitearch = universal-darwin10.0
64
+ ruby_version = 1.8
65
+ ruby = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
66
+ RUBY = $(ruby)
67
+ RM = rm -f
68
+ MAKEDIRS = mkdir -p
69
+ INSTALL = /usr/bin/install -c
70
+ INSTALL_PROG = $(INSTALL) -m 0755
71
+ INSTALL_DATA = $(INSTALL) -m 644
72
+ COPY = cp
73
+
74
+ #### End of system configuration section. ####
75
+
76
+ preload =
77
+
78
+ libpath = . $(libdir)
79
+ LIBPATH = -L. -L$(libdir)
80
+ DEFFILE =
81
+
82
+ CLEANFILES = mkmf.log
83
+ DISTCLEANFILES =
84
+
85
+ extout =
86
+ extout_prefix =
87
+ target_prefix =
88
+ LOCAL_LIBS =
89
+ LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl
90
+ SRCS = active_support_c.c inflector.c
91
+ OBJS = active_support_c.o inflector.o
92
+ TARGET = active_support_c
93
+ DLLIB = $(TARGET).bundle
94
+ EXTSTATIC =
95
+ STATIC_LIB =
96
+
97
+ BINDIR = $(bindir)
98
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
99
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
100
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
101
+
102
+ TARGET_SO = $(DLLIB)
103
+ CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
104
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
105
+
106
+ all: $(DLLIB)
107
+ static: $(STATIC_LIB)
108
+
109
+ clean:
110
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
111
+
112
+ distclean: clean
113
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
114
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
115
+
116
+ realclean: distclean
117
+ install: install-so install-rb
118
+
119
+ install-so: $(RUBYARCHDIR)
120
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
121
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
122
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
123
+ install-rb: pre-install-rb install-rb-default
124
+ install-rb-default: pre-install-rb-default
125
+ pre-install-rb: Makefile
126
+ pre-install-rb-default: Makefile
127
+ $(RUBYARCHDIR):
128
+ $(MAKEDIRS) $@
129
+
130
+ site-install: site-install-so site-install-rb
131
+ site-install-so: install-so
132
+ site-install-rb: install-rb
133
+
134
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
135
+
136
+ .cc.o:
137
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
138
+
139
+ .cxx.o:
140
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
141
+
142
+ .cpp.o:
143
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
144
+
145
+ .C.o:
146
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
147
+
148
+ .c.o:
149
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
150
+
151
+ $(DLLIB): $(OBJS)
152
+ @-$(RM) $@
153
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
154
+
155
+
156
+
157
+ $(OBJS): ruby.h defines.h
@@ -0,0 +1,27 @@
1
+ #include "inflector.h"
2
+ #include "core_ext/string/starts_ends_with.h"
3
+ #include "core_ext/string/access.h"
4
+ #include "core_ext/string/filters.h"
5
+
6
+ #include "ruby.h"
7
+
8
+ void
9
+ Init_active_support_c()
10
+ {
11
+ VALUE mActiveSupport = rb_define_module("ActiveSupport");
12
+ VALUE cASC = rb_define_class_under(mActiveSupport, "ASC", rb_cObject);
13
+
14
+ /* ActiveSupport::ASC.camelize("my_string") */
15
+ rb_define_singleton_method(cASC, "inflector_camelize", inflector_camelize, 2);
16
+ rb_define_singleton_method(cASC, "inflector_demodulize", inflector_demodulize, 1);
17
+ rb_define_singleton_method(cASC, "inflector_dasherize", inflector_dasherize, 1);
18
+ rb_define_singleton_method(cASC, "inflector_foreign_key", inflector_foreign_key, 2);
19
+ rb_define_singleton_method(cASC, "inflector_ordinalize", inflector_ordinalize, 1);
20
+ rb_define_singleton_method(cASC, "inflector_parameterize", inflector_parameterize, 2);
21
+ rb_define_singleton_method(cASC, "inflector_underscore", inflector_underscore, 1);
22
+
23
+ /* rb_define_singleton_method(cASC, "core_ext_string_at", core_ext_string_at, 1); */
24
+ /* rb_define_singleton_method(cASC, "core_ext_string_to", core_ext_string_to, 1); */
25
+ /* rb_define_singleton_method(cASC, "core_ext_string_from", core_ext_string_from, 1); */
26
+ /* rb_define_singleton_method(cASC, "core_ext_string_first", core_ext_string_first, 1); */
27
+ }
@@ -0,0 +1,157 @@
1
+ #include <assert.h>
2
+ #include <string.h>
3
+ #include <stdlib.h>
4
+
5
+ #include "access.h"
6
+ #include "ruby.h"
7
+
8
+ VALUE
9
+ core_ext_string_at(VALUE rstr, VALUE rposition)
10
+ {
11
+ Check_Type(rstr, T_STRING);
12
+ Check_Type(rposition, T_FIXNUM);
13
+
14
+ int position = FIX2INT(rposition);
15
+ int len = RString(rstr)->len;
16
+ struct RString *ret;
17
+
18
+ if (position < 0) { // Allow for negative indices
19
+ position += len;
20
+ }
21
+
22
+ if ((position < 0) || (position > len)) { // still out of bounds
23
+ ret->ptr = calloc(1, sizeof(char));
24
+ ret->len = 0;
25
+ } else {
26
+ len -= position;
27
+ ret->len = len;
28
+ ret->ptr = malloc((len+1)*sizeof(char));
29
+ memcpy(ret->ptr, RString(rstr)->ptr + position, len);
30
+ }
31
+
32
+ return ret;
33
+ }
34
+
35
+ void
36
+ test_core_ext_string_at()
37
+ {
38
+ char *test = "0123456789";
39
+ assert(!strcmp(core_ext_string_at(test, 0), "0"));
40
+ assert(!strcmp(core_ext_string_at(test, 1), "1"));
41
+ assert(!strcmp(core_ext_string_at(test, 9), "9"));
42
+ assert(!strcmp(core_ext_string_at(test, 10), ""));
43
+ assert(!strcmp(core_ext_string_at(test, 15), ""));
44
+ assert(!strcmp(core_ext_string_at(test, -1), "9"));
45
+ assert(!strcmp(core_ext_string_at(test, -2), "8"));
46
+ assert(!strcmp(core_ext_string_at(test, -10), "0"));
47
+ assert(!strcmp(core_ext_string_at(test, -11), ""));
48
+ assert(!strcmp(core_ext_string_at(test, -15), ""));
49
+ }
50
+
51
+ VALUE
52
+ core_ext_string_first(VALUE rstr, VALUE rposition)
53
+ {
54
+ Check_Type(rstr, T_STRING);
55
+ Check_Type(rposition, T_FIXNUM);
56
+
57
+ //int len = strlen(str);
58
+ return Qnil;
59
+ }
60
+
61
+ void
62
+ test_core_ext_string_first()
63
+ {
64
+ char *test = "0123456789";
65
+ assert(!strcmp(core_ext_string_first(test, 0), "0123456789"));
66
+ assert(!strcmp(core_ext_string_first(test, 1), "0"));
67
+ assert(!strcmp(core_ext_string_first(test, 2), "01"));
68
+ assert(!strcmp(core_ext_string_first(test, 9), "012345678"));
69
+ assert(!strcmp(core_ext_string_first(test, 10), "0123456789"));
70
+ assert(!strcmp(core_ext_string_first(test, 15), "0123456789"));
71
+ assert(!strcmp(core_ext_string_first(test, -1), "012345678"));
72
+ assert(!strcmp(core_ext_string_first(test, -2), "01234567"));
73
+ assert(!strcmp(core_ext_string_first(test, -10), ""));
74
+ assert(!strcmp(core_ext_string_first(test, -11), ""));
75
+ assert(!strcmp(core_ext_string_first(test, -15), ""));
76
+ }
77
+
78
+ VALUE
79
+ core_ext_string_from(VALUE rstr, VALUE rposition)
80
+ {
81
+ Check_Type(rstr, T_STRING);
82
+ Check_Type(rposition, T_FIXNUM);
83
+
84
+ int len = RCORE_EXT_STRING_LEN(rstr)
85
+
86
+ if (position < 0) {
87
+ position += len; // -10 + 10 = 0
88
+ }
89
+
90
+ if (position > len || position < 0) {
91
+ position = len;
92
+ }
93
+
94
+ return str + position;
95
+ }
96
+
97
+ void
98
+ test_core_ext_string_from()
99
+ {
100
+ char *test = "0123456789";
101
+ assert(!strcmp(core_ext_string_from(test, 0), "0123456789"));
102
+ assert(!strcmp(core_ext_string_from(test, 1), "123456789"));
103
+ assert(!strcmp(core_ext_string_from(test, 9), "9"));
104
+ assert(!strcmp(core_ext_string_from(test, 10), ""));
105
+ assert(!strcmp(core_ext_string_from(test, 15), ""));
106
+ assert(!strcmp(core_ext_string_from(test, -1), "9"));
107
+ assert(!strcmp(core_ext_string_from(test, -2), "89"));
108
+ assert(!strcmp(core_ext_string_from(test, -10), "0123456789"));
109
+ assert(!strcmp(core_ext_string_from(test, -11), ""));
110
+ assert(!strcmp(core_ext_string_from(test, -15), ""));
111
+ }
112
+
113
+ VALUE
114
+ core_ext_string_to(VALUE rstr, VALUE rposition)
115
+ {
116
+ int position = FIX2INT(rposition);
117
+
118
+ int len = RString(rstr)->len;
119
+ struct RString ret;
120
+
121
+ if (position < 0) { // allow for negative indices
122
+ position += len;
123
+ }
124
+
125
+ if (position > len) { // past top bound
126
+ ret->len = len;
127
+ ret->ptr = malloc((len+1)*sizeof(char));
128
+ memcpy(ret->ptr, RString(rstr)->ptr, len);
129
+ } else if (position < 0) { // under bottom bound
130
+ ret->ptr = calloc(1, sizeof(char));
131
+ ret->len = 0;
132
+ } else {
133
+ ret->len = position + 1;
134
+ ret->ptr = malloc((position + 2) * sizeof(char));
135
+
136
+ memcpy(ret->ptr, RString(rstr)->ptr, position+1);
137
+ *(ret->ptr + position + 1) = '\0';
138
+ }
139
+
140
+ return ret;
141
+ }
142
+
143
+ void
144
+ test_core_ext_string_to()
145
+ {
146
+ char *test = "0123456789";
147
+ assert(!strcmp(core_ext_string_to(test, 0), "0"));
148
+ assert(!strcmp(core_ext_string_to(test, 1), "01"));
149
+ assert(!strcmp(core_ext_string_to(test, 9), "0123456789"));
150
+ assert(!strcmp(core_ext_string_to(test, 10), "0123456789"));
151
+ assert(!strcmp(core_ext_string_to(test, 15), "0123456789"));
152
+ assert(!strcmp(core_ext_string_to(test, -1), "0123456789"));
153
+ assert(!strcmp(core_ext_string_to(test, -2), "012345678"));
154
+ assert(!strcmp(core_ext_string_to(test, -10), "0"));
155
+ assert(!strcmp(core_ext_string_to(test, -11), ""));
156
+ assert(!strcmp(core_ext_string_to(test, -15), ""));
157
+ }
@@ -0,0 +1,6 @@
1
+ #pragma once
2
+
3
+ #include "ruby.h"
4
+
5
+ VALUE core_ext_string_from(VALUE str, VALUE position);
6
+ VALUE core_ext_string_to(VALUE str, VALUE position);
@@ -0,0 +1,52 @@
1
+ #include <stdbool.h>
2
+ #include <string.h>
3
+ #include <stdlib.h>
4
+
5
+ #include "filters.h"
6
+
7
+ static bool /* Ugly, but fast! */
8
+ _is_space(char chr)
9
+ {
10
+ if (chr > 13) {
11
+ return (chr == 32);
12
+ } else {
13
+ return (chr == 9 || chr == 10 || chr == 12 || chr == 13);
14
+ }
15
+ }
16
+
17
+ VALUE
18
+ string_squish(VALUE rstr)
19
+ {
20
+ int ilen = RString(rstr)->len;
21
+ int olen = ilen;
22
+ char *ip = RString(rstr)->ptr;
23
+ bool in_space = true;
24
+ int i;
25
+ struct RString ret;
26
+ ret->ptr = (char *)malloc(len+1)*(sizeof (char));
27
+ char *op = ret->ptr;
28
+
29
+
30
+ for (i = 0; i < ilen; i++, ip++) {
31
+ if (_is_space(*ip)) {
32
+ if (in_space) {
33
+ olen--;
34
+ } else {
35
+ in_space = true;
36
+ *op++ = ' ';
37
+ }
38
+ } else {
39
+ in_space = false;
40
+ *op++ = *ip;
41
+ }
42
+ }
43
+
44
+ if (*(op-1) == ' ') {
45
+ *(op-1) = '\0';
46
+ olen--;
47
+ }
48
+
49
+ ret->len = olen;
50
+ return ret;
51
+ }
52
+
@@ -0,0 +1,5 @@
1
+ #pragma once
2
+
3
+ #include "ruby.h"
4
+
5
+ VALUE string_squish(VALUE rstr);
@@ -0,0 +1,68 @@
1
+ #include <assert.h>
2
+ #include <stdbool.h>
3
+ #include <string.h>
4
+ #include <ctype.h>
5
+
6
+ #include "starts_ends_with.h"
7
+ #include "ruby.h"
8
+
9
+ VALUE
10
+ string_starts_with(VALUE str, VALUE substr)
11
+ {
12
+ int sublen = RString(substr)->len;
13
+ char *p1 = RString(str)->ptr;
14
+ char *p2 = RString(substr)->ptr;
15
+
16
+ while (sublen--) {
17
+ if (*p1++ != *p2++) {
18
+ return Qfalse;
19
+ }
20
+ }
21
+
22
+ return Qtrue;
23
+ }
24
+
25
+ void
26
+ test_starts_with()
27
+ {
28
+ assert(string_starts_with("asdf", "") == true);
29
+ assert(string_starts_with("asdf", "asdfasdf") == false);
30
+ assert(string_starts_with("", "asdfasdf") == false);
31
+ assert(string_starts_with("", "") == true);
32
+ }
33
+
34
+ VALUE
35
+ string_ends_with(VALUE str, VALUE substr)
36
+ {
37
+ int l_str, l_substr;
38
+ char *p_str, *p_substr;
39
+
40
+ l_str = RString(str)->len;
41
+ l_substr = RString(substr)->len;
42
+
43
+ if (l_substr > l_str) {
44
+ return Qfalse;
45
+ }
46
+
47
+ p_str = RString(str)->ptr + l_str;
48
+ p_substr = RString(substr)->ptr + l_substr;
49
+
50
+
51
+ while (p_substr >= RString(substr)->ptr) {
52
+ if (*p_substr-- != *p_str--) {
53
+ return Qfale;
54
+ }
55
+ }
56
+
57
+ return Qtrue;
58
+ }
59
+
60
+ void
61
+ test_ends_with()
62
+ {
63
+ assert(string_ends_with("asdf", "") == true);
64
+ assert(string_ends_with("asdf", "asdfasdf") == false);
65
+ assert(string_ends_with("", "asdfasdf") == false);
66
+ assert(string_ends_with("", "") == true);
67
+ }
68
+
@@ -0,0 +1,6 @@
1
+ #pragma once
2
+
3
+ #include "ruby.h"
4
+
5
+ VALUE string_starts_with(VALUE str, VALUE substr);
6
+ VALUE string_ends_with(VALUE str, VALUE substr);
data/ext/extconf.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = 'active_support_c'
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
data/ext/inflector.c ADDED
@@ -0,0 +1,224 @@
1
+ #include <assert.h>
2
+ #include <ctype.h>
3
+ #include <stdbool.h>
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+
7
+ #include "inflector.h"
8
+ #include "ruby.h"
9
+
10
+ VALUE inflector_underscore(VALUE self, VALUE rstr)
11
+ {
12
+ Check_Type(rstr, T_STRING);
13
+
14
+ VALUE ret = rb_str_new("", 0);
15
+ char * ip = StringValuePtr(rstr);
16
+ int ilen = RSTRING_LEN(rstr);
17
+ char prev = '\0';
18
+ char temp;
19
+ int i;
20
+
21
+ for (i = 0; i < ilen; i++, prev=*ip++) {
22
+
23
+ // replace :: with /
24
+ if (*ip == ':' && *(ip+1) == ':') {
25
+ rb_str_cat(ret, "/", 1);
26
+ ip++;
27
+ i++; // fastforward one char.
28
+ } else {
29
+ if ((isupper(prev) && isupper(*ip) && islower(*(ip+1)))
30
+ || ((islower(prev)||isdigit(prev)) && isupper(*ip))) {
31
+ rb_str_cat(ret, "_", 1);
32
+ }
33
+ if (*ip == '-') {
34
+ rb_str_cat(ret, "_", 1);
35
+ } else {
36
+ temp = tolower(*ip);
37
+ rb_str_cat(ret, &temp, 1);
38
+ }
39
+ }
40
+ }
41
+ return ret;
42
+ }
43
+
44
+ VALUE inflector_parameterize(VALUE self, VALUE str, VALUE sep)
45
+ {
46
+ Check_Type(str, T_STRING);
47
+ Check_Type(sep, T_STRING);
48
+
49
+ VALUE ret = rb_str_new("", 0);
50
+ int sep_len = RSTRING_LEN(sep);
51
+ int ilen = RSTRING_LEN(str);
52
+ char * ip = RSTRING_PTR(str);
53
+ bool separated = true;
54
+ int i;
55
+ char tmp;
56
+
57
+ for (i = 0; i < ilen; i++, ip++) {
58
+ if (isalnum(*ip) || *ip == '-' || *ip == '_' || *ip == '+') { // normal char
59
+ separated = false;
60
+ tmp = tolower(*ip);
61
+ rb_str_cat(ret, &tmp, 1);
62
+ } else { // replace with separator
63
+ if (!separated) {
64
+ separated = true;
65
+ rb_str_cat(ret, RSTRING_PTR(sep), sep_len);
66
+ }
67
+ }
68
+ }
69
+
70
+ // cp points to the end of the return string.
71
+ // Get rid of trailing separators, if any.
72
+ if (RSTRING_LEN(ret) && !memcmp(RSTRING_PTR(sep),
73
+ RSTRING_PTR(ret) + RSTRING_LEN(ret) - sep_len,
74
+ sep_len * sizeof (char)))
75
+ {
76
+ ret = rb_str_new(RSTRING_PTR(ret), RSTRING_LEN(ret) - sep_len);
77
+ }
78
+
79
+ return ret;
80
+ }
81
+
82
+ VALUE inflector_dasherize(VALUE self, VALUE str)
83
+ {
84
+ Check_Type(str, T_STRING);
85
+
86
+ char * out = ALLOC_N(char, RSTRING_LEN(str) + 1);
87
+ char * ip = RSTRING_PTR(str);
88
+ char * op = out;
89
+ int len = RSTRING_LEN(str);
90
+ int i;
91
+
92
+ for (i = 0; i < len; i++, ip++) {
93
+ if (*ip == '_') {
94
+ *op++ = '-';
95
+ } else {
96
+ *op++ = *ip;
97
+ }
98
+ }
99
+
100
+ return rb_str_new(out, len);
101
+ }
102
+
103
+ VALUE inflector_demodulize(VALUE self, VALUE rstr)
104
+ {
105
+ Check_Type(rstr, T_STRING);
106
+
107
+ char * str = RSTRING_PTR(rstr);
108
+ char * ip = str;
109
+ char * last_part = str;
110
+ int len = RSTRING_LEN(rstr);
111
+ int olen = len;
112
+ int i;
113
+
114
+ for (i = 0; i < len; i++, ip++) {
115
+ if (*ip == ':' && *(ip+1) == ':') {
116
+ olen = len - i - 2;
117
+ last_part = ip + 2;
118
+ }
119
+ }
120
+
121
+ VALUE ret = rb_str_new("", 0);
122
+ rb_str_cat(ret, last_part, olen);
123
+ return ret;
124
+ }
125
+
126
+ VALUE inflector_camelize(VALUE self, VALUE str, VALUE first_letter_uppercase)
127
+ {
128
+ Check_Type(str, T_STRING);
129
+
130
+ VALUE ret = rb_str_new("", 0);
131
+ bool cap_next = RTEST(first_letter_uppercase);
132
+ int ilen = RSTRING_LEN(str);
133
+ char * ip = RSTRING_PTR(str);
134
+ int i;
135
+ char tmp;
136
+
137
+ for (i = 0; i < ilen; i++, ip++) {
138
+ if (*ip == '/') {
139
+ cap_next = true;
140
+ rb_str_cat(ret, "::", 2);
141
+ } else if (*ip == '_') {
142
+ cap_next = true;
143
+ // Skip over -- don't print anything.
144
+ } else {
145
+ if (cap_next) {
146
+ tmp = toupper(*ip);
147
+ cap_next = false;
148
+ } else {
149
+ tmp = tolower(*ip);
150
+ }
151
+ rb_str_cat(ret, &tmp, 1);
152
+ }
153
+ }
154
+ return ret;
155
+ }
156
+
157
+ VALUE inflector_foreign_key(VALUE self, VALUE str, VALUE use_underscore)
158
+ {
159
+ Check_Type(str, T_STRING);
160
+
161
+ VALUE ret = inflector_underscore(self, inflector_demodulize(self, str));
162
+
163
+ if (RTEST(use_underscore)) {
164
+ rb_str_cat(ret, "_id", 3);
165
+ } else {
166
+ rb_str_cat(ret, "id", 2);
167
+ }
168
+
169
+ return ret;
170
+ }
171
+
172
+
173
+ static char * itoa(int n)
174
+ {
175
+ char c_tmp;
176
+ int i_tmp;
177
+ char * ret = ALLOC_N(char, 32);
178
+ char * ptr = ret;
179
+ char * ptr1 = ret;
180
+
181
+ do {
182
+ i_tmp = n;
183
+ n /= 10;
184
+ *ptr++ = "9876543210123456789" [9 + (i_tmp - n * 10)];
185
+ } while (n);
186
+
187
+ if (i_tmp < 0) *ptr++ = '-';
188
+ *ptr-- = '\0';
189
+ while (ptr1 < ptr) {
190
+ c_tmp = *ptr;
191
+ *ptr-- = *ptr1;
192
+ *ptr1++ = c_tmp;
193
+ }
194
+
195
+ return ret;
196
+ }
197
+
198
+ VALUE inflector_ordinalize(VALUE self, VALUE rn)
199
+ {
200
+ Check_Type(rn, T_FIXNUM);
201
+
202
+ int n = FIX2INT(rn);
203
+ VALUE ret = rb_str_new2(itoa(n));
204
+ int x = n % 100;
205
+
206
+ if ((x > 10) && (x < 14)) {
207
+ rb_str_cat(ret, "th", 2);
208
+ } else {
209
+ switch(n % 10) {
210
+ case 1:
211
+ rb_str_cat(ret, "st", 2);
212
+ break;
213
+ case 2:
214
+ rb_str_cat(ret, "nd", 2);
215
+ break;
216
+ case 3:
217
+ rb_str_cat(ret, "rd", 2);
218
+ break;
219
+ default:
220
+ rb_str_cat(ret, "th", 2);
221
+ }
222
+ }
223
+ return ret;
224
+ }
data/ext/inflector.h ADDED
@@ -0,0 +1,10 @@
1
+ #pragma once
2
+ #include "ruby.h"
3
+
4
+ VALUE inflector_underscore(VALUE self, VALUE str);
5
+ VALUE inflector_parameterize(VALUE self, VALUE str, VALUE sep);
6
+ VALUE inflector_dasherize(VALUE self, VALUE str);
7
+ VALUE inflector_demodulize(VALUE self, VALUE str);
8
+ VALUE inflector_camelize(VALUE self, VALUE str, VALUE first_letter_uppercase);
9
+ VALUE inflector_foreign_key(VALUE self, VALUE str, VALUE use_underscore);
10
+ VALUE inflector_ordinalize(VALUE self, VALUE n);
@@ -0,0 +1,116 @@
1
+ module ActiveSupport
2
+ module Inflector
3
+
4
+
5
+ def check_fixnum(obj)
6
+ return (obj.class == Fixnum)
7
+ end
8
+
9
+ if '1.9'.respond_to?(:force_encoding)
10
+ ASCII_ENCODING = Encoding.find("ASCII-8BIT")
11
+ if Encoding.default_external == ASCII_ENCODING
12
+ def check_ascii_string(obj)
13
+ (obj.class == String) && obj.encoding == ASCII_ENCODING
14
+ end
15
+ else
16
+ def check_ascii_string(obj)
17
+ #TODO: Check ascii_only? and force_encoding here.
18
+ (obj.class == String) && obj.encoding == ASCII_ENCODING
19
+ end
20
+ end
21
+ else # <1.9
22
+ def check_ascii_string(obj)
23
+ obj.class == String
24
+ end
25
+ end
26
+
27
+ @_pluralize = {}
28
+ alias_method :__pluralize, :pluralize
29
+ def pluralize(word)
30
+ @_pluralize[word] ||= __pluralize(word)
31
+ end
32
+
33
+ @_singularize = {}
34
+ alias_method :__singularize, :singularize
35
+ def singularize(word)
36
+ @_singularize[word] ||= __singularize(word)
37
+ end
38
+
39
+ @_humanize = {}
40
+ alias_method :__humanize, :humanize
41
+ def humanize(word)
42
+ @_humanize[word] ||= __humanize(word)
43
+ end
44
+
45
+ alias_method :__camelize, :camelize
46
+ def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
47
+ if check_ascii_string(lower_case_and_underscored_word)
48
+ ActiveSupport::ASC.inflector_camelize(lower_case_and_underscored_word.to_s, first_letter_in_uppercase)
49
+ else
50
+ __camelize(lower_case_and_underscored_word, first_letter_in_uppercase)
51
+ end
52
+ end
53
+
54
+ alias_method :__underscore, :underscore
55
+ def underscore(camel_cased_word)
56
+ if check_ascii_string(camel_cased_word)
57
+ ActiveSupport::ASC.inflector_underscore(camel_cased_word)
58
+ else
59
+ __underscore(camel_cased_word)
60
+ end
61
+ end
62
+
63
+
64
+ alias_method :__dasherize, :dasherize
65
+ def dasherize(underscored_word)
66
+ if check_ascii_string(underscored_word)
67
+ ActiveSupport::ASC.inflector_dasherize(underscored_word)
68
+ else
69
+ __dasherize(underscored_word)
70
+ end
71
+ end
72
+
73
+ alias_method :__demodulize, :demodulize
74
+ def demodulize(class_name_in_module)
75
+ if check_ascii_string(class_name_in_module)
76
+ ActiveSupport::ASC.inflector_demodulize(class_name_in_module)
77
+ else
78
+ __demodulize(class_name_in_module)
79
+ end
80
+ end
81
+
82
+
83
+ alias_method :__parameterize, :parameterize
84
+ def parameterize(string, sep = '-')
85
+ parameterized_string = transliterate(string)
86
+ if check_ascii_string(parameterized_string) && check_ascii_string(sep)
87
+ ActiveSupport::ASC.inflector_parameterize(parameterized_string.to_s, sep)
88
+ else
89
+ __parameterize(string, sep)
90
+ end
91
+ end
92
+
93
+
94
+ alias_method :__foreign_key, :foreign_key
95
+ def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
96
+ if check_ascii_string(class_name)
97
+ ActiveSupport::ASC.inflector_foreign_key(class_name, separate_class_name_and_id_with_underscore)
98
+ else
99
+ __foreign_key(class_name, separate_class_name_and_id_with_underscore)
100
+ end
101
+ end
102
+
103
+
104
+ alias_method :__ordinalize, :ordinalize
105
+ def ordinalize(number)
106
+ x = number.to_i
107
+ if check_fixnum(x)
108
+ ActiveSupport::ASC.inflector_ordinalize(number.to_i)
109
+ else
110
+ __ordinalize(number)
111
+ end
112
+ end
113
+
114
+ end
115
+ end
116
+
@@ -0,0 +1,2 @@
1
+ require 'active_support_c'
2
+ require 'monkeysupport/inflector'
@@ -0,0 +1,81 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{monkeysupport}
8
+ s.version = "0.0.3"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Burke Libbey"]
12
+ s.date = %q{2009-09-04}
13
+ s.description = %q{MonkeySupport provides C implementations for some of the more intensive string manipulation methods in activesupport. ActionView is up next.}
14
+ s.email = %q{burke@burkelibbey.org}
15
+ s.extensions = ["ext/extconf.rb"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".gitignore",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "ext/Makefile",
28
+ "ext/Makefile",
29
+ "ext/active_support_c.c",
30
+ "ext/active_support_c.c",
31
+ "ext/core_ext/string/access.c",
32
+ "ext/core_ext/string/access.c",
33
+ "ext/core_ext/string/access.h",
34
+ "ext/core_ext/string/access.h",
35
+ "ext/core_ext/string/filters.c",
36
+ "ext/core_ext/string/filters.c",
37
+ "ext/core_ext/string/filters.h",
38
+ "ext/core_ext/string/filters.h",
39
+ "ext/core_ext/string/starts_ends_with.c",
40
+ "ext/core_ext/string/starts_ends_with.c",
41
+ "ext/core_ext/string/starts_ends_with.h",
42
+ "ext/core_ext/string/starts_ends_with.h",
43
+ "ext/extconf.rb",
44
+ "ext/extconf.rb",
45
+ "ext/inflector.c",
46
+ "ext/inflector.c",
47
+ "ext/inflector.h",
48
+ "ext/inflector.h",
49
+ "lib/monkeysupport.rb",
50
+ "lib/monkeysupport.rb",
51
+ "lib/monkeysupport/inflector.rb",
52
+ "lib/monkeysupport/inflector.rb",
53
+ "monkeysupport.gemspec",
54
+ "test/monkeysupport_test.rb",
55
+ "test/monkeysupport_test.rb",
56
+ "test/test_helper.rb",
57
+ "test/test_helper.rb"
58
+ ]
59
+ s.homepage = %q{http://github.com/burke/monkeysupport}
60
+ s.rdoc_options = ["--charset=UTF-8"]
61
+ s.require_paths = ["lib"]
62
+ s.rubygems_version = %q{1.3.4}
63
+ s.summary = %q{Monkeypatching Rails with C since 2009}
64
+ s.test_files = [
65
+ "test/monkeysupport_test.rb",
66
+ "test/test_helper.rb"
67
+ ]
68
+
69
+ if s.respond_to? :specification_version then
70
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
71
+ s.specification_version = 3
72
+
73
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
74
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
75
+ else
76
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
77
+ end
78
+ else
79
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
80
+ end
81
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class MonkeysupportTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'monkeysupport'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: burke-monkeysupport
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Burke Libbey
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-04 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: MonkeySupport provides C implementations for some of the more intensive string manipulation methods in activesupport. ActionView is up next.
26
+ email: burke@burkelibbey.org
27
+ executables: []
28
+
29
+ extensions:
30
+ - ext/extconf.rb
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Rakefile
40
+ - VERSION
41
+ - ext/Makefile
42
+ - ext/active_support_c.c
43
+ - ext/core_ext/string/access.c
44
+ - ext/core_ext/string/access.h
45
+ - ext/core_ext/string/filters.c
46
+ - ext/core_ext/string/filters.h
47
+ - ext/core_ext/string/starts_ends_with.c
48
+ - ext/core_ext/string/starts_ends_with.h
49
+ - ext/extconf.rb
50
+ - ext/inflector.c
51
+ - ext/inflector.h
52
+ - lib/monkeysupport.rb
53
+ - lib/monkeysupport/inflector.rb
54
+ - monkeysupport.gemspec
55
+ - test/monkeysupport_test.rb
56
+ - test/test_helper.rb
57
+ has_rdoc: false
58
+ homepage: http://github.com/burke/monkeysupport
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --charset=UTF-8
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.2.0
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Monkeypatching Rails with C since 2009
83
+ test_files:
84
+ - test/monkeysupport_test.rb
85
+ - test/test_helper.rb