escape_utils 0.2.4 → 0.3.0
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.
- data/.gitignore +2 -1
- data/.travis.yml +13 -0
- data/CHANGELOG.md +7 -0
- data/MIT-LICENSE +1 -1
- data/Rakefile +5 -18
- data/benchmark/html_escape.rb +9 -2
- data/benchmark/xml_escape.rb +29 -0
- data/escape_utils.gemspec +2 -3
- data/ext/escape_utils/buffer.c +181 -160
- data/ext/escape_utils/buffer.h +90 -68
- data/ext/escape_utils/escape_utils.c +77 -39
- data/ext/escape_utils/extconf.rb +1 -1
- data/ext/escape_utils/houdini.h +37 -8
- data/ext/escape_utils/houdini_href_e.c +115 -0
- data/ext/escape_utils/houdini_html_e.c +90 -0
- data/ext/escape_utils/houdini_html_u.c +122 -0
- data/ext/escape_utils/{houdini_js.c → houdini_js_e.c} +17 -75
- data/ext/escape_utils/houdini_js_u.c +60 -0
- data/ext/escape_utils/{uri_escape.h → houdini_uri_e.c} +68 -2
- data/ext/escape_utils/houdini_uri_u.c +65 -0
- data/ext/escape_utils/houdini_xml_e.c +136 -0
- data/lib/escape_utils/version.rb +1 -1
- data/lib/escape_utils/xml/builder.rb +8 -0
- data/test/helper.rb +14 -0
- data/test/html/escape_test.rb +61 -0
- data/test/html/unescape_test.rb +48 -0
- data/test/html_safety_test.rb +46 -0
- data/test/javascript/escape_test.rb +42 -0
- data/test/javascript/unescape_test.rb +46 -0
- data/test/query/escape_test.rb +50 -0
- data/test/query/unescape_test.rb +52 -0
- data/test/uri/escape_test.rb +50 -0
- data/test/uri/unescape_test.rb +55 -0
- data/test/url/escape_test.rb +58 -0
- data/test/url/unescape_test.rb +60 -0
- data/test/xml/escape_test.rb +67 -0
- metadata +136 -152
- data/.rspec +0 -2
- data/ext/escape_utils/houdini_html.c +0 -214
- data/ext/escape_utils/houdini_uri.c +0 -130
- data/spec/html/escape_spec.rb +0 -42
- data/spec/html/unescape_spec.rb +0 -37
- data/spec/html_safety_spec.rb +0 -48
- data/spec/javascript/escape_spec.rb +0 -34
- data/spec/javascript/unescape_spec.rb +0 -37
- data/spec/query/escape_spec.rb +0 -44
- data/spec/query/unescape_spec.rb +0 -46
- data/spec/rcov.opts +0 -3
- data/spec/spec_helper.rb +0 -5
- data/spec/uri/escape_spec.rb +0 -43
- data/spec/uri/unescape_spec.rb +0 -57
- data/spec/url/escape_spec.rb +0 -52
- data/spec/url/unescape_spec.rb +0 -57
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.3.0 (February 26th, 2013)
|
4
|
+
* add xml escaping support
|
5
|
+
* in Ruby 1.9 - escape_utils now requires the input string be UTF-8
|
6
|
+
* update upstream houdini to pull in some speed optimizations
|
7
|
+
* a couple of other perf tweaks
|
8
|
+
* switched to minitest
|
9
|
+
|
3
10
|
## 0.2.4 (September 7th, 2011)
|
4
11
|
* swap out custom escaping routines for houdini - https://github.com/tanoku/houdini
|
5
12
|
* add RSTRING_NOT_MODIFIED define for a Rubinius speedup
|
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2010-
|
1
|
+
Copyright (c) 2010-2013 Brian Lopez - http://github.com/brianmario
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,23 +1,10 @@
|
|
1
|
-
|
2
|
-
begin
|
3
|
-
require 'rspec'
|
4
|
-
require 'rspec/core/rake_task'
|
1
|
+
require 'rake/testtask'
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
t.rcov = true
|
9
|
-
end
|
10
|
-
RSpec::Core::RakeTask.new('spec') do |t|
|
11
|
-
t.verbose = true
|
12
|
-
end
|
13
|
-
|
14
|
-
task :default => :spec
|
15
|
-
rescue LoadError
|
16
|
-
puts "rspec, or one of its dependencies, is not available. Install it with: sudo gem install rspec"
|
3
|
+
Rake::TestTask.new do |t|
|
4
|
+
t.pattern = "test/**/*_test.rb"
|
17
5
|
end
|
18
6
|
|
19
|
-
|
20
|
-
require 'rake' unless defined? Rake
|
7
|
+
task :default => :test
|
21
8
|
|
22
9
|
gem 'rake-compiler', '>= 0.7.5'
|
23
10
|
require "rake/extensiontask"
|
@@ -29,4 +16,4 @@ Rake::ExtensionTask.new('escape_utils') do |ext|
|
|
29
16
|
ext.lib_dir = File.join 'lib', 'escape_utils'
|
30
17
|
end
|
31
18
|
|
32
|
-
Rake::Task[:
|
19
|
+
Rake::Task[:test].prerequisites << :compile
|
data/benchmark/html_escape.rb
CHANGED
@@ -19,7 +19,7 @@ end
|
|
19
19
|
times = 100
|
20
20
|
url = "http://en.wikipedia.org/wiki/Line_of_succession_to_the_British_throne"
|
21
21
|
html = `curl -s #{url}`
|
22
|
-
html = html.force_encoding('
|
22
|
+
html = html.force_encoding('utf-8') if html.respond_to?(:force_encoding)
|
23
23
|
puts "Escaping #{html.bytesize} bytes of html #{times} times, from #{url}"
|
24
24
|
|
25
25
|
Benchmark.bmbm do |x|
|
@@ -47,6 +47,13 @@ Benchmark.bmbm do |x|
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
x.report "String#gsub" do
|
51
|
+
html_escape = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' }
|
52
|
+
times.times do
|
53
|
+
html.gsub(/[&"'><]/, html_escape)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
50
57
|
x.report "fast_xs_extra#fast_xs_html" do
|
51
58
|
times.times do
|
52
59
|
html.fast_xs_html
|
@@ -58,4 +65,4 @@ Benchmark.bmbm do |x|
|
|
58
65
|
EscapeUtils.escape_html(html)
|
59
66
|
end
|
60
67
|
end
|
61
|
-
end
|
68
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
|
3
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'benchmark'
|
7
|
+
|
8
|
+
require 'builder'
|
9
|
+
require 'escape_utils'
|
10
|
+
|
11
|
+
times = 100
|
12
|
+
url = "http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml"
|
13
|
+
xml = `curl -s #{url}`
|
14
|
+
xml = xml.force_encoding('binary') if xml.respond_to?(:force_encoding)
|
15
|
+
puts "Escaping #{xml.bytesize} bytes of xml #{times} times, from #{url}"
|
16
|
+
|
17
|
+
Benchmark.bmbm do |x|
|
18
|
+
x.report "Builder::String.to_xs" do
|
19
|
+
times.times do
|
20
|
+
xml.to_xs
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
x.report "EscapeUtils.escape_xml" do
|
25
|
+
times.times do
|
26
|
+
EscapeUtils.escape_xml(xml)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/escape_utils.gemspec
CHANGED
@@ -4,20 +4,19 @@ Gem::Specification.new do |s|
|
|
4
4
|
s.name = %q{escape_utils}
|
5
5
|
s.version = EscapeUtils::VERSION
|
6
6
|
s.authors = ["Brian Lopez"]
|
7
|
-
s.date = Time.now.utc.strftime("%Y-%m-%d")
|
8
7
|
s.email = %q{seniorlopez@gmail.com}
|
9
8
|
s.extensions = ["ext/escape_utils/extconf.rb"]
|
10
9
|
s.files = `git ls-files`.split("\n")
|
11
10
|
s.homepage = %q{http://github.com/brianmario/escape_utils}
|
12
11
|
s.rdoc_options = ["--charset=UTF-8"]
|
13
|
-
s.require_paths = ["lib"
|
12
|
+
s.require_paths = ["lib"]
|
14
13
|
s.rubygems_version = %q{1.4.2}
|
15
14
|
s.summary = %q{Faster string escaping routines for your web apps}
|
16
15
|
s.test_files = `git ls-files spec`.split("\n")
|
17
16
|
|
18
17
|
# tests
|
19
18
|
s.add_development_dependency 'rake-compiler', ">= 0.7.5"
|
20
|
-
s.add_development_dependency '
|
19
|
+
s.add_development_dependency 'minitest'
|
21
20
|
# benchmarks
|
22
21
|
s.add_development_dependency 'rack'
|
23
22
|
s.add_development_dependency 'haml'
|
data/ext/escape_utils/buffer.c
CHANGED
@@ -1,228 +1,249 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (
|
3
|
-
* Copyright (c) 2011, Vicent Martí
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
4
3
|
*
|
5
|
-
*
|
6
|
-
*
|
7
|
-
* copyright notice and this permission notice appear in all copies.
|
8
|
-
*
|
9
|
-
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
10
|
-
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
11
|
-
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
12
|
-
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
13
|
-
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
14
|
-
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
15
|
-
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
4
|
+
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
|
+
* a Linking Exception. For full terms see the included COPYING file.
|
16
6
|
*/
|
17
|
-
|
18
|
-
#
|
19
|
-
|
20
|
-
#include
|
21
|
-
|
7
|
+
#include <stdarg.h>
|
8
|
+
#include <ctype.h>
|
9
|
+
#include <string.h>
|
10
|
+
#include <assert.h>
|
11
|
+
#include <string.h>
|
22
12
|
#include <stdio.h>
|
23
13
|
#include <stdlib.h>
|
24
|
-
#include <
|
14
|
+
#include <sys/param.h>
|
25
15
|
|
26
|
-
|
27
|
-
#if defined(_MSC_VER)
|
28
|
-
# define _buf_vsnprintf _vsnprintf
|
29
|
-
#else
|
30
|
-
# define _buf_vsnprintf vsnprintf
|
31
|
-
#endif
|
16
|
+
#include "buffer.h"
|
32
17
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
18
|
+
/* Used as default value for gh_buf->ptr so that people can always
|
19
|
+
* assume ptr is non-NULL and zero terminated even for new gh_bufs.
|
20
|
+
*/
|
21
|
+
char gh_buf__initbuf[1];
|
22
|
+
char gh_buf__oom[1];
|
37
23
|
|
38
|
-
|
39
|
-
|
40
|
-
|
24
|
+
#define ENSURE_SIZE(b, d) \
|
25
|
+
if ((d) > buf->asize && gh_buf_grow(b, (d)) < 0)\
|
26
|
+
return -1;
|
41
27
|
|
42
|
-
|
43
|
-
|
44
|
-
|
28
|
+
void gh_buf_init(gh_buf *buf, size_t initial_size)
|
29
|
+
{
|
30
|
+
buf->asize = 0;
|
31
|
+
buf->size = 0;
|
32
|
+
buf->ptr = gh_buf__initbuf;
|
45
33
|
|
46
|
-
|
34
|
+
if (initial_size)
|
35
|
+
gh_buf_grow(buf, initial_size);
|
47
36
|
}
|
48
37
|
|
49
|
-
|
50
|
-
int
|
51
|
-
bufgrow(struct buf *buf, size_t neosz)
|
38
|
+
int gh_buf_try_grow(gh_buf *buf, size_t target_size, bool mark_oom)
|
52
39
|
{
|
53
|
-
|
54
|
-
|
55
|
-
if (!buf || !buf->unit || neosz > BUFFER_MAX_ALLOC_SIZE)
|
56
|
-
return BUF_ENOMEM;
|
40
|
+
char *new_ptr;
|
41
|
+
size_t new_size;
|
57
42
|
|
58
|
-
if (buf->
|
59
|
-
return
|
43
|
+
if (buf->ptr == gh_buf__oom)
|
44
|
+
return -1;
|
60
45
|
|
61
|
-
|
62
|
-
|
63
|
-
neoasz += buf->unit;
|
46
|
+
if (target_size <= buf->asize)
|
47
|
+
return 0;
|
64
48
|
|
65
|
-
|
66
|
-
|
67
|
-
|
49
|
+
if (buf->asize == 0) {
|
50
|
+
new_size = target_size;
|
51
|
+
new_ptr = NULL;
|
52
|
+
} else {
|
53
|
+
new_size = buf->asize;
|
54
|
+
new_ptr = buf->ptr;
|
55
|
+
}
|
68
56
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
57
|
+
/* grow the buffer size by 1.5, until it's big enough
|
58
|
+
* to fit our target size */
|
59
|
+
while (new_size < target_size)
|
60
|
+
new_size = (new_size << 1) - (new_size >> 1);
|
73
61
|
|
62
|
+
/* round allocation up to multiple of 8 */
|
63
|
+
new_size = (new_size + 7) & ~7;
|
74
64
|
|
75
|
-
|
76
|
-
struct buf *
|
77
|
-
bufnew(size_t unit)
|
78
|
-
{
|
79
|
-
struct buf *ret;
|
80
|
-
ret = malloc(sizeof (struct buf));
|
65
|
+
new_ptr = realloc(new_ptr, new_size);
|
81
66
|
|
82
|
-
if (
|
83
|
-
|
84
|
-
|
85
|
-
|
67
|
+
if (!new_ptr) {
|
68
|
+
if (mark_oom)
|
69
|
+
buf->ptr = gh_buf__oom;
|
70
|
+
return -1;
|
86
71
|
}
|
87
|
-
|
72
|
+
|
73
|
+
buf->asize = new_size;
|
74
|
+
buf->ptr = new_ptr;
|
75
|
+
|
76
|
+
/* truncate the existing buffer size if necessary */
|
77
|
+
if (buf->size >= buf->asize)
|
78
|
+
buf->size = buf->asize - 1;
|
79
|
+
buf->ptr[buf->size] = '\0';
|
80
|
+
|
81
|
+
return 0;
|
88
82
|
}
|
89
83
|
|
90
|
-
|
91
|
-
const char *
|
92
|
-
bufcstr(struct buf *buf)
|
84
|
+
void gh_buf_free(gh_buf *buf)
|
93
85
|
{
|
94
|
-
if (!buf
|
95
|
-
return NULL;
|
86
|
+
if (!buf) return;
|
96
87
|
|
97
|
-
if (buf->
|
98
|
-
|
88
|
+
if (buf->ptr != gh_buf__initbuf && buf->ptr != gh_buf__oom)
|
89
|
+
free(buf->ptr);
|
99
90
|
|
100
|
-
|
101
|
-
buf->data[buf->size] = 0;
|
102
|
-
return (char *)buf->data;
|
103
|
-
}
|
104
|
-
|
105
|
-
return NULL;
|
91
|
+
gh_buf_init(buf, 0);
|
106
92
|
}
|
107
93
|
|
108
|
-
|
109
|
-
void
|
110
|
-
bufprintf(struct buf *buf, const char *fmt, ...)
|
94
|
+
void gh_buf_clear(gh_buf *buf)
|
111
95
|
{
|
112
|
-
|
113
|
-
if (
|
114
|
-
|
96
|
+
buf->size = 0;
|
97
|
+
if (buf->asize > 0)
|
98
|
+
buf->ptr[0] = '\0';
|
99
|
+
}
|
115
100
|
|
116
|
-
|
117
|
-
|
118
|
-
|
101
|
+
int gh_buf_set(gh_buf *buf, const char *data, size_t len)
|
102
|
+
{
|
103
|
+
if (len == 0 || data == NULL) {
|
104
|
+
gh_buf_clear(buf);
|
105
|
+
} else {
|
106
|
+
if (data != buf->ptr) {
|
107
|
+
ENSURE_SIZE(buf, len + 1);
|
108
|
+
memmove(buf->ptr, data, len);
|
109
|
+
}
|
110
|
+
buf->size = len;
|
111
|
+
buf->ptr[buf->size] = '\0';
|
112
|
+
}
|
113
|
+
return 0;
|
119
114
|
}
|
120
115
|
|
121
|
-
|
122
|
-
void
|
123
|
-
bufput(struct buf *buf, const void *data, size_t len)
|
116
|
+
int gh_buf_sets(gh_buf *buf, const char *string)
|
124
117
|
{
|
125
|
-
|
126
|
-
|
118
|
+
return gh_buf_set(buf, string, string ? strlen(string) : 0);
|
119
|
+
}
|
127
120
|
|
128
|
-
|
129
|
-
|
121
|
+
int gh_buf_putc(gh_buf *buf, char c)
|
122
|
+
{
|
123
|
+
ENSURE_SIZE(buf, buf->size + 2);
|
124
|
+
buf->ptr[buf->size++] = c;
|
125
|
+
buf->ptr[buf->size] = '\0';
|
126
|
+
return 0;
|
127
|
+
}
|
130
128
|
|
131
|
-
|
129
|
+
int gh_buf_put(gh_buf *buf, const void *data, size_t len)
|
130
|
+
{
|
131
|
+
ENSURE_SIZE(buf, buf->size + len + 1);
|
132
|
+
memmove(buf->ptr + buf->size, data, len);
|
132
133
|
buf->size += len;
|
134
|
+
buf->ptr[buf->size] = '\0';
|
135
|
+
return 0;
|
133
136
|
}
|
134
137
|
|
135
|
-
|
136
|
-
void
|
137
|
-
bufputs(struct buf *buf, const char *str)
|
138
|
+
int gh_buf_puts(gh_buf *buf, const char *string)
|
138
139
|
{
|
139
|
-
|
140
|
+
assert(string);
|
141
|
+
return gh_buf_put(buf, string, strlen(string));
|
140
142
|
}
|
141
143
|
|
142
|
-
|
143
|
-
/* bufputc: appends a single uint8_t to a buffer */
|
144
|
-
void
|
145
|
-
bufputc(struct buf *buf, int c)
|
144
|
+
int gh_buf_vprintf(gh_buf *buf, const char *format, va_list ap)
|
146
145
|
{
|
147
|
-
|
148
|
-
|
146
|
+
int len;
|
147
|
+
const size_t expected_size = buf->size + (strlen(format) * 2);
|
149
148
|
|
150
|
-
|
151
|
-
return;
|
149
|
+
ENSURE_SIZE(buf, expected_size);
|
152
150
|
|
153
|
-
|
154
|
-
|
155
|
-
|
151
|
+
while (1) {
|
152
|
+
va_list args;
|
153
|
+
va_copy(args, ap);
|
156
154
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
return;
|
155
|
+
len = vsnprintf(
|
156
|
+
buf->ptr + buf->size,
|
157
|
+
buf->asize - buf->size,
|
158
|
+
format, args
|
159
|
+
);
|
163
160
|
|
164
|
-
|
165
|
-
|
166
|
-
|
161
|
+
if (len < 0) {
|
162
|
+
free(buf->ptr);
|
163
|
+
buf->ptr = gh_buf__oom;
|
164
|
+
return -1;
|
165
|
+
}
|
166
|
+
|
167
|
+
if ((size_t)len + 1 <= buf->asize - buf->size) {
|
168
|
+
buf->size += len;
|
169
|
+
break;
|
170
|
+
}
|
167
171
|
|
172
|
+
ENSURE_SIZE(buf, buf->size + len + 1);
|
173
|
+
}
|
168
174
|
|
169
|
-
|
170
|
-
|
171
|
-
|
175
|
+
return 0;
|
176
|
+
}
|
177
|
+
|
178
|
+
int gh_buf_printf(gh_buf *buf, const char *format, ...)
|
172
179
|
{
|
173
|
-
|
174
|
-
|
180
|
+
int r;
|
181
|
+
va_list ap;
|
175
182
|
|
176
|
-
|
177
|
-
|
178
|
-
|
183
|
+
va_start(ap, format);
|
184
|
+
r = gh_buf_vprintf(buf, format, ap);
|
185
|
+
va_end(ap);
|
186
|
+
|
187
|
+
return r;
|
179
188
|
}
|
180
189
|
|
181
|
-
|
182
|
-
void
|
183
|
-
bufslurp(struct buf *buf, size_t len)
|
190
|
+
void gh_buf_copy_cstr(char *data, size_t datasize, const gh_buf *buf)
|
184
191
|
{
|
185
|
-
|
186
|
-
|
192
|
+
size_t copylen;
|
193
|
+
|
194
|
+
assert(data && datasize && buf);
|
187
195
|
|
188
|
-
|
189
|
-
|
196
|
+
data[0] = '\0';
|
197
|
+
|
198
|
+
if (buf->size == 0 || buf->asize <= 0)
|
190
199
|
return;
|
191
|
-
}
|
192
200
|
|
193
|
-
buf->size
|
194
|
-
|
201
|
+
copylen = buf->size;
|
202
|
+
if (copylen > datasize - 1)
|
203
|
+
copylen = datasize - 1;
|
204
|
+
memmove(data, buf->ptr, copylen);
|
205
|
+
data[copylen] = '\0';
|
195
206
|
}
|
196
207
|
|
197
|
-
|
198
|
-
void
|
199
|
-
vbufprintf(struct buf *buf, const char *fmt, va_list ap)
|
208
|
+
void gh_buf_swap(gh_buf *buf_a, gh_buf *buf_b)
|
200
209
|
{
|
201
|
-
|
210
|
+
gh_buf t = *buf_a;
|
211
|
+
*buf_a = *buf_b;
|
212
|
+
*buf_b = t;
|
213
|
+
}
|
202
214
|
|
203
|
-
|
204
|
-
|
215
|
+
char *gh_buf_detach(gh_buf *buf)
|
216
|
+
{
|
217
|
+
char *data = buf->ptr;
|
205
218
|
|
206
|
-
|
219
|
+
if (buf->asize == 0 || buf->ptr == gh_buf__oom)
|
220
|
+
return NULL;
|
207
221
|
|
208
|
-
|
209
|
-
#ifdef _MSC_VER
|
210
|
-
n = _vscprintf(fmt, ap);
|
211
|
-
#else
|
212
|
-
return;
|
213
|
-
#endif
|
214
|
-
}
|
222
|
+
gh_buf_init(buf, 0);
|
215
223
|
|
216
|
-
|
217
|
-
|
218
|
-
return;
|
224
|
+
return data;
|
225
|
+
}
|
219
226
|
|
220
|
-
|
227
|
+
void gh_buf_attach(gh_buf *buf, char *ptr, size_t asize)
|
228
|
+
{
|
229
|
+
gh_buf_free(buf);
|
230
|
+
|
231
|
+
if (ptr) {
|
232
|
+
buf->ptr = ptr;
|
233
|
+
buf->size = strlen(ptr);
|
234
|
+
if (asize)
|
235
|
+
buf->asize = (asize < buf->size) ? buf->size + 1 : asize;
|
236
|
+
else /* pass 0 to fall back on strlen + 1 */
|
237
|
+
buf->asize = buf->size + 1;
|
238
|
+
} else {
|
239
|
+
gh_buf_grow(buf, asize);
|
221
240
|
}
|
241
|
+
}
|
222
242
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
243
|
+
int gh_buf_cmp(const gh_buf *a, const gh_buf *b)
|
244
|
+
{
|
245
|
+
int result = memcmp(a->ptr, b->ptr, MIN(a->size, b->size));
|
246
|
+
return (result != 0) ? result :
|
247
|
+
(a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0;
|
227
248
|
}
|
228
249
|
|