rubinius-melbourne 1.2.1.0 → 2.0.0.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,9 +2,12 @@
2
2
  #define MEL_VISITOR_HPP
3
3
 
4
4
  namespace MELBOURNE {
5
+ rb_parser_state *parser_alloc_state();
6
+ void *pt_allocate(rb_parser_state *st, int size);
7
+ void pt_free(rb_parser_state *st);
8
+
5
9
  void create_error(rb_parser_state *parser_state, char *msg);
6
- NODE *parser_node_newnode(rb_parser_state*, enum node_type, VALUE, VALUE, VALUE);
7
- VALUE process_parse_tree(rb_parser_state*, VALUE, NODE*, QUID*);
8
10
  };
9
11
 
10
12
  #endif
13
+
@@ -1,7 +1,27 @@
1
- require "rubinius/melbourne/version"
2
1
  require "rubinius/melbourne/melbourne"
2
+ require "rubinius/melbourne/version"
3
+
4
+ class String
5
+ def to_ast(name="(eval)", line=1)
6
+ Rubinius::ToolSet.get(:runtime)::Melbourne.parse_string self, name, line
7
+ end
8
+
9
+ def to_sexp(name="(eval)", line=1)
10
+ to_ast(name, line).to_sexp
11
+ end
12
+ end
13
+
14
+ class File
15
+ def self.to_ast(name, line=1)
16
+ Rubinius::ToolSet.get(:runtime)::Melbourne.parse_file name, line
17
+ end
18
+
19
+ def self.to_sexp(name, line=1)
20
+ to_ast(name, line).to_sexp
21
+ end
22
+ end
3
23
 
4
- module CodeTools
24
+ module Rubinius::ToolSet.current::TS
5
25
  class Melbourne
6
26
  attr_accessor :transforms
7
27
  attr_accessor :magic_handler
@@ -54,7 +74,7 @@ module CodeTools
54
74
  end
55
75
 
56
76
  def parse_file
57
- unless @name and File.exist? @name
77
+ unless @name and File.exists? @name
58
78
  raise Errno::ENOENT, @name.inspect
59
79
  end
60
80
 
@@ -1,5 +1,5 @@
1
- module CodeTools
1
+ module Rubinius::ToolSet.current::TS
2
2
  class Melbourne
3
- VERSION = "1.2.1.0"
3
+ VERSION = "2.0.0.17"
4
4
  end
5
5
  end
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ require 'rubinius/toolset'
2
3
  require './lib/rubinius/melbourne/version'
3
4
 
4
5
  Gem::Specification.new do |spec|
@@ -15,13 +16,10 @@ Gem::Specification.new do |spec|
15
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
17
  spec.name = "rubinius-melbourne"
17
18
  spec.require_paths = ["lib"]
18
- spec.version = CodeTools::Melbourne::VERSION
19
+ spec.version = Rubinius::ToolSet.current::TS::Melbourne::VERSION
19
20
 
20
- spec.add_development_dependency "rubinius-processor", "~> 1.0"
21
- spec.add_development_dependency "rubinius-compiler", "~> 1.0"
22
- spec.add_development_dependency "rubinius-ast", "~> 1.0"
23
- spec.add_development_dependency "rubinius-bridge", "~> 1.0"
24
- spec.add_development_dependency "redcard", "~> 1.0"
25
- spec.add_development_dependency "mspec", "~> 1.5"
26
- spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_runtime_dependency "rubinius-toolset"
22
+
23
+ spec.add_development_dependency "mspec", "~> 1.5"
24
+ spec.add_development_dependency "rake", "~> 10.0"
27
25
  end
metadata CHANGED
@@ -1,85 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubinius-melbourne
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1.0
4
+ version: 2.0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-13 00:00:00.000000000 Z
11
+ date: 2013-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rubinius-processor
14
+ name: rubinius-toolset
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
18
- - !ruby/object:Gem::Version
19
- version: '1.0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: '1.0'
27
- - !ruby/object:Gem::Dependency
28
- name: rubinius-compiler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ~>
17
+ - - '>='
32
18
  - !ruby/object:Gem::Version
33
- version: '1.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ~>
39
- - !ruby/object:Gem::Version
40
- version: '1.0'
41
- - !ruby/object:Gem::Dependency
42
- name: rubinius-ast
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ~>
46
- - !ruby/object:Gem::Version
47
- version: '1.0'
48
- type: :development
19
+ version: '0'
20
+ type: :runtime
49
21
  prerelease: false
50
22
  version_requirements: !ruby/object:Gem::Requirement
51
23
  requirements:
52
- - - ~>
53
- - !ruby/object:Gem::Version
54
- version: '1.0'
55
- - !ruby/object:Gem::Dependency
56
- name: rubinius-bridge
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ~>
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
- - !ruby/object:Gem::Dependency
70
- name: redcard
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ~>
74
- - !ruby/object:Gem::Version
75
- version: '1.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ~>
24
+ - - '>='
81
25
  - !ruby/object:Gem::Version
82
- version: '1.0'
26
+ version: '0'
83
27
  - !ruby/object:Gem::Dependency
84
28
  name: mspec
85
29
  requirement: !ruby/object:Gem::Requirement
@@ -121,15 +65,13 @@ files:
121
65
  - LICENSE
122
66
  - README.md
123
67
  - Rakefile
124
- - ext/rubinius/melbourne/bstring-license.txt
125
- - ext/rubinius/melbourne/bstrlib.cpp
126
- - ext/rubinius/melbourne/bstrlib.h
68
+ - ext/rubinius/melbourne/encoding_compat.cpp
69
+ - ext/rubinius/melbourne/encoding_compat.hpp
127
70
  - ext/rubinius/melbourne/extconf.rb
128
71
  - ext/rubinius/melbourne/grammar.cpp
129
72
  - ext/rubinius/melbourne/grammar.hpp
130
73
  - ext/rubinius/melbourne/grammar.y
131
- - ext/rubinius/melbourne/lex.c.tab
132
- - ext/rubinius/melbourne/local_state.hpp
74
+ - ext/rubinius/melbourne/lex.c.blt
133
75
  - ext/rubinius/melbourne/melbourne.cpp
134
76
  - ext/rubinius/melbourne/melbourne.hpp
135
77
  - ext/rubinius/melbourne/node.hpp
@@ -137,8 +79,6 @@ files:
137
79
  - ext/rubinius/melbourne/node_types.hpp
138
80
  - ext/rubinius/melbourne/node_types.rb
139
81
  - ext/rubinius/melbourne/parser_state.hpp
140
- - ext/rubinius/melbourne/quark.cpp
141
- - ext/rubinius/melbourne/quark.hpp
142
82
  - ext/rubinius/melbourne/symbols.cpp
143
83
  - ext/rubinius/melbourne/symbols.hpp
144
84
  - ext/rubinius/melbourne/var_table.cpp
@@ -168,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
108
  version: '0'
169
109
  requirements: []
170
110
  rubyforge_project:
171
- rubygems_version: 2.0.14
111
+ rubygems_version: 2.0.7
172
112
  signing_key:
173
113
  specification_version: 4
174
114
  summary: Rubinius Ruby Parser.
@@ -1,29 +0,0 @@
1
- Copyright (c) 2002-2007 Paul Hsieh
2
- All rights reserved.
3
-
4
- Redistribution and use in source and binary forms, with or without
5
- modification, are permitted provided that the following conditions are met:
6
-
7
- Redistributions of source code must retain the above copyright notice,
8
- this list of conditions and the following disclaimer.
9
-
10
- Redistributions in binary form must reproduce the above copyright notice,
11
- this list of conditions and the following disclaimer in the documentation
12
- and/or other materials provided with the distribution.
13
-
14
- Neither the name of bstrlib nor the names of its contributors may be used
15
- to endorse or promote products derived from this software without
16
- specific prior written permission.
17
-
18
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
- POSSIBILITY OF SUCH DAMAGE.
29
-
@@ -1,2687 +0,0 @@
1
- /*
2
- * This source file is part of the bstring string library. This code was
3
- * written by Paul Hsieh in 2002-2007, and is covered by the BSD open source
4
- * license. Refer to the accompanying documentation for details on usage and
5
- * license.
6
- */
7
-
8
- /*
9
- * bstrlib.c
10
- *
11
- * This file is the core module for implementing the bstring functions.
12
- */
13
-
14
- #include <stdio.h>
15
- #include <stddef.h>
16
- #include <stdarg.h>
17
- #include <stdlib.h>
18
- #include <string.h>
19
- #include <ctype.h>
20
- #include "bstrlib.h"
21
-
22
- /* Optionally include a mechanism for debugging memory */
23
-
24
- #if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG)
25
- /* TODO: temporarily disable include until dependency grapher
26
- * properly parses expressions.
27
- *
28
- * #include "memdbg.h"
29
- */
30
- #endif
31
-
32
- #ifndef bstr__alloc
33
- #define bstr__alloc(x) malloc (x)
34
- #endif
35
-
36
- #ifndef bstr__free
37
- #define bstr__free(p) free (p)
38
- #endif
39
-
40
- #ifndef bstr__realloc
41
- #define bstr__realloc(p,x) realloc ((p), (x))
42
- #endif
43
-
44
- #ifndef bstr__memcpy
45
- #define bstr__memcpy(d,s,l) memcpy ((d), (s), (l))
46
- #endif
47
-
48
- #ifndef bstr__memmove
49
- #define bstr__memmove(d,s,l) memmove ((d), (s), (l))
50
- #endif
51
-
52
- #ifndef bstr__memset
53
- #define bstr__memset(d,c,l) memset ((d), (c), (l))
54
- #endif
55
-
56
- #ifndef bstr__memcmp
57
- #define bstr__memcmp(d,c,l) memcmp ((d), (c), (l))
58
- #endif
59
-
60
- #ifndef bstr__memchr
61
- #define bstr__memchr(s,c,l) memchr ((s), (c), (l))
62
- #endif
63
-
64
- /* Just a length safe wrapper for memmove. */
65
-
66
- #define bBlockCopy(D,S,L) { if ((L) > 0) bstr__memmove ((D),(S),(L)); }
67
-
68
- /* Compute the snapped size for a given requested size. By snapping to powers
69
- of 2 like this, repeated reallocations are avoided. */
70
- static int snapUpSize (int i) {
71
- if (i < 8) {
72
- i = 8;
73
- } else {
74
- unsigned int j;
75
- j = (unsigned int) i;
76
-
77
- j |= (j >> 1);
78
- j |= (j >> 2);
79
- j |= (j >> 4);
80
- j |= (j >> 8); /* Ok, since int >= 16 bits */
81
- #if (UINT_MAX != 0xffff)
82
- j |= (j >> 16); /* For 32 bit int systems */
83
- #if (UINT_MAX > 0xffffffffUL)
84
- j |= (j >> 32); /* For 64 bit int systems */
85
- #endif
86
- #endif
87
- /* Least power of two greater than i */
88
- j++;
89
- if ((int) j >= i) i = (int) j;
90
- }
91
- return i;
92
- }
93
-
94
- /* int balloc (bstring b, int len)
95
- *
96
- * Increase the size of the memory backing the bstring b to at least len.
97
- */
98
- int balloc (bstring b, int olen) {
99
- int len;
100
- if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen <= 0 ||
101
- b->mlen < b->slen || olen <= 0) {
102
- return BSTR_ERR;
103
- }
104
-
105
- if (olen >= b->mlen) {
106
- unsigned char * x;
107
-
108
- if ((len = snapUpSize (olen)) <= b->mlen) return BSTR_OK;
109
-
110
- /* Assume probability of a non-moving realloc is 0.125 */
111
- if (7 * b->mlen < 8 * b->slen) {
112
-
113
- /* If slen is close to mlen in size then use realloc to reduce
114
- the memory defragmentation */
115
-
116
- reallocStrategy:;
117
-
118
- x = (unsigned char *) bstr__realloc (b->data, (size_t) len);
119
- if (x == NULL) {
120
-
121
- /* Since we failed, try allocating the tighest possible
122
- allocation */
123
-
124
- if (NULL == (x = (unsigned char *) bstr__realloc (b->data, (size_t) (len = olen)))) {
125
- return BSTR_ERR;
126
- }
127
- }
128
- } else {
129
-
130
- /* If slen is not close to mlen then avoid the penalty of copying
131
- the extra bytes that are allocated, but not considered part of
132
- the string */
133
-
134
- if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len))) {
135
-
136
- /* Perhaps there is no available memory for the two
137
- allocations to be in memory at once */
138
-
139
- goto reallocStrategy;
140
-
141
- } else {
142
- if (b->slen) bstr__memcpy ((char *) x, (char *) b->data, (size_t) b->slen);
143
- bstr__free (b->data);
144
- }
145
- }
146
- b->data = x;
147
- b->mlen = len;
148
- b->data[b->slen] = (unsigned char) '\0';
149
- }
150
-
151
- return BSTR_OK;
152
- }
153
-
154
- /* int ballocmin (bstring b, int len)
155
- *
156
- * Set the size of the memory backing the bstring b to len or b->slen+1,
157
- * whichever is larger. Note that repeated use of this function can degrade
158
- * performance.
159
- */
160
- int ballocmin (bstring b, int len) {
161
- unsigned char * s;
162
-
163
- if (b == NULL || b->data == NULL || (b->slen+1) < 0 || b->mlen <= 0 ||
164
- b->mlen < b->slen || len <= 0) {
165
- return BSTR_ERR;
166
- }
167
-
168
- if (len < b->slen + 1) len = b->slen + 1;
169
-
170
- if (len != b->mlen) {
171
- s = (unsigned char *) bstr__realloc (b->data, (size_t) len);
172
- if (NULL == s) return BSTR_ERR;
173
- s[b->slen] = (unsigned char) '\0';
174
- b->data = s;
175
- b->mlen = len;
176
- }
177
-
178
- return BSTR_OK;
179
- }
180
-
181
- /* bstring bfromcstr (const char * str)
182
- *
183
- * Create a bstring which contains the contents of the '\0' terminated char *
184
- * buffer str.
185
- */
186
- bstring bfromcstr (const char * str) {
187
- bstring b;
188
- int i;
189
- size_t j;
190
-
191
- if (str == NULL) return NULL;
192
- j = (strlen) (str);
193
- i = snapUpSize ((int) (j + (2 - (j != 0))));
194
- if (i <= (int) j) return NULL;
195
-
196
- b = (bstring) bstr__alloc (sizeof (struct tagbstring));
197
- if (NULL == b) return NULL;
198
- b->slen = (int) j;
199
- if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) {
200
- bstr__free (b);
201
- return NULL;
202
- }
203
-
204
- bstr__memcpy (b->data, str, j+1);
205
- return b;
206
- }
207
-
208
- /* bstring bfromcstralloc (int mlen, const char * str)
209
- *
210
- * Create a bstring which contains the contents of the '\0' terminated char *
211
- * buffer str. The memory buffer backing the string is at least len
212
- * characters in length.
213
- */
214
- bstring bfromcstralloc (int mlen, const char * str) {
215
- bstring b;
216
- int i;
217
- size_t j;
218
-
219
- if (str == NULL) return NULL;
220
- j = (strlen) (str);
221
- i = snapUpSize ((int) (j + (2 - (j != 0))));
222
- if (i <= (int) j) return NULL;
223
-
224
- b = (bstring) bstr__alloc (sizeof (struct tagbstring));
225
- if (b == NULL) return NULL;
226
- b->slen = (int) j;
227
- if (i < mlen) i = mlen;
228
-
229
- if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) {
230
- bstr__free (b);
231
- return NULL;
232
- }
233
-
234
- bstr__memcpy (b->data, str, j+1);
235
- return b;
236
- }
237
-
238
- /* bstring blk2bstr (const void * blk, int len)
239
- *
240
- * Create a bstring which contains the content of the block blk of length
241
- * len.
242
- */
243
- bstring blk2bstr (const void * blk, int len) {
244
- bstring b;
245
- int i;
246
-
247
- if (blk == NULL || len < 0) return NULL;
248
- b = (bstring) bstr__alloc (sizeof (struct tagbstring));
249
- if (b == NULL) return NULL;
250
- b->slen = len;
251
-
252
- i = len + (2 - (len != 0));
253
- i = snapUpSize (i);
254
-
255
- b->mlen = i;
256
-
257
- b->data = (unsigned char *) bstr__alloc ((size_t) b->mlen);
258
- if (b->data == NULL) {
259
- bstr__free (b);
260
- return NULL;
261
- }
262
-
263
- if (len > 0) bstr__memcpy (b->data, blk, (size_t) len);
264
- b->data[len] = (unsigned char) '\0';
265
-
266
- return b;
267
- }
268
-
269
- /* char * bstr2cstr (const_bstring s, char z)
270
- *
271
- * Create a '\0' terminated char * buffer which is equal to the contents of
272
- * the bstring s, except that any contained '\0' characters are converted
273
- * to the character in z. This returned value should be freed with a
274
- * bcstrfree () call, by the calling application.
275
- */
276
- char * bstr2cstr (const_bstring b, char z) {
277
- int i, l;
278
- char * r;
279
-
280
- if (b == NULL || b->slen < 0 || b->data == NULL) return NULL;
281
- l = b->slen;
282
- r = (char *) bstr__alloc ((size_t) (l + 1));
283
- if (r == NULL) return r;
284
-
285
- for (i=0; i < l; i ++) {
286
- r[i] = (char) ((b->data[i] == '\0') ? z : (char) (b->data[i]));
287
- }
288
-
289
- r[l] = (unsigned char) '\0';
290
-
291
- return r;
292
- }
293
-
294
- /* int bcstrfree (char * s)
295
- *
296
- * Frees a C-string generated by bstr2cstr (). This is normally unnecessary
297
- * since it just wraps a call to bstr__free (), however, if bstr__alloc ()
298
- * and bstr__free () have been redefined as a macros within the bstrlib
299
- * module (via defining them in memdbg.h after defining
300
- * BSTRLIB_MEMORY_DEBUG) with some difference in behaviour from the std
301
- * library functions, then this allows a correct way of freeing the memory
302
- * that allows higher level code to be independent from these macro
303
- * redefinitions.
304
- */
305
- int bcstrfree (char * s) {
306
- if (s) {
307
- bstr__free (s);
308
- return BSTR_OK;
309
- }
310
- return BSTR_ERR;
311
- }
312
-
313
- /* int bconcat (bstring b0, const_bstring b1)
314
- *
315
- * Concatenate the bstring b1 to the bstring b0.
316
- */
317
- int bconcat (bstring b0, const_bstring b1) {
318
- int len, d;
319
- bstring aux = (bstring) b1;
320
-
321
- if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL) return BSTR_ERR;
322
-
323
- d = b0->slen;
324
- len = b1->slen;
325
- if ((d | (b0->mlen - d) | len) < 0) return BSTR_ERR;
326
-
327
- if (b0->mlen <= d + len + 1) {
328
- ptrdiff_t pd;
329
- if (0 <= (pd = b1->data - b0->data) && pd < b0->mlen) {
330
- if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR;
331
- }
332
- if (balloc (b0, d + len + 1) != BSTR_OK) {
333
- if (aux != b1) bdestroy (aux);
334
- return BSTR_ERR;
335
- }
336
- }
337
-
338
- bBlockCopy (&b0->data[d], &aux->data[0], (size_t) len);
339
- b0->data[d + len] = (unsigned char) '\0';
340
- b0->slen += len;
341
- if (aux != b1) bdestroy (aux);
342
- return BSTR_OK;
343
- }
344
-
345
- /* int bconchar (bstring b, char c)
346
- *
347
- * Concatenate the single character c to the bstring b.
348
- */
349
- int bconchar (bstring b, char c) {
350
- int d;
351
-
352
- if (b == NULL) return BSTR_ERR;
353
- d = b->slen;
354
- if ((d | (b->mlen - d)) < 0 || balloc (b, d + 2) != BSTR_OK) return BSTR_ERR;
355
- b->data[d] = (unsigned char) c;
356
- b->data[d + 1] = (unsigned char) '\0';
357
- b->slen++;
358
- return BSTR_OK;
359
- }
360
-
361
- /* int bcatcstr (bstring b, const char * s)
362
- *
363
- * Concatenate a char * string to a bstring.
364
- */
365
- int bcatcstr (bstring b, const char * s) {
366
- char * d;
367
- int i, l;
368
-
369
- if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen
370
- || b->mlen <= 0 || s == NULL) return BSTR_ERR;
371
-
372
- /* Optimistically concatenate directly */
373
- l = b->mlen - b->slen;
374
- d = (char *) &b->data[b->slen];
375
- for (i=0; i < l; i++) {
376
- if ((*d++ = *s++) == '\0') {
377
- b->slen += i;
378
- return BSTR_OK;
379
- }
380
- }
381
- b->slen += i;
382
-
383
- /* Need to explicitely resize and concatenate tail */
384
- return bcatblk (b, (const void *) s, (int) strlen (s));
385
- }
386
-
387
- /* int bcatblk (bstring b, const void * s, int len)
388
- *
389
- * Concatenate a fixed length buffer to a bstring.
390
- */
391
- int bcatblk (bstring b, const void * s, int len) {
392
- int nl;
393
-
394
- if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen
395
- || b->mlen <= 0 || s == NULL || len < 0) return BSTR_ERR;
396
-
397
- if (0 > (nl = b->slen + len)) return BSTR_ERR; /* Overflow? */
398
- if (b->mlen <= nl && 0 > balloc (b, nl + 1)) return BSTR_ERR;
399
-
400
- bBlockCopy (&b->data[b->slen], s, (size_t) len);
401
- b->slen = nl;
402
- b->data[nl] = (unsigned char) '\0';
403
- return BSTR_OK;
404
- }
405
-
406
- /* bstring bstrcpy (const_bstring b)
407
- *
408
- * Create a copy of the bstring b.
409
- */
410
- bstring bstrcpy (const_bstring b) {
411
- bstring b0;
412
- int i,j;
413
-
414
- /* Attempted to copy an invalid string? */
415
- if (b == NULL || b->slen < 0 || b->data == NULL) return NULL;
416
-
417
- b0 = (bstring) bstr__alloc (sizeof (struct tagbstring));
418
- if (b0 == NULL) {
419
- /* Unable to allocate memory for string header */
420
- return NULL;
421
- }
422
-
423
- i = b->slen;
424
- j = snapUpSize (i + 1);
425
-
426
- b0->data = (unsigned char *) bstr__alloc (j);
427
- if (b0->data == NULL) {
428
- j = i + 1;
429
- b0->data = (unsigned char *) bstr__alloc (j);
430
- if (b0->data == NULL) {
431
- /* Unable to allocate memory for string data */
432
- bstr__free (b0);
433
- return NULL;
434
- }
435
- }
436
-
437
- b0->mlen = j;
438
- b0->slen = i;
439
-
440
- if (i) bstr__memcpy ((char *) b0->data, (char *) b->data, i);
441
- b0->data[b0->slen] = (unsigned char) '\0';
442
-
443
- return b0;
444
- }
445
-
446
- /* int bassign (bstring a, const_bstring b)
447
- *
448
- * Overwrite the string a with the contents of string b.
449
- */
450
- int bassign (bstring a, const_bstring b) {
451
- if (b == NULL || b->data == NULL || b->slen < 0)
452
- return BSTR_ERR;
453
- if (b->slen != 0) {
454
- if (balloc (a, b->slen) != BSTR_OK) return BSTR_ERR;
455
- bstr__memmove (a->data, b->data, b->slen);
456
- } else {
457
- if (a == NULL || a->data == NULL || a->mlen < a->slen ||
458
- a->slen < 0 || a->mlen == 0)
459
- return BSTR_ERR;
460
- }
461
- a->data[b->slen] = (unsigned char) '\0';
462
- a->slen = b->slen;
463
- return BSTR_OK;
464
- }
465
-
466
- /* int bassignmidstr (bstring a, const_bstring b, int left, int len)
467
- *
468
- * Overwrite the string a with the middle of contents of string b
469
- * starting from position left and running for a length len. left and
470
- * len are clamped to the ends of b as with the function bmidstr.
471
- */
472
- int bassignmidstr (bstring a, const_bstring b, int left, int len) {
473
- if (b == NULL || b->data == NULL || b->slen < 0)
474
- return BSTR_ERR;
475
-
476
- if (left < 0) {
477
- len += left;
478
- left = 0;
479
- }
480
-
481
- if (len > b->slen - left) len = b->slen - left;
482
-
483
- if (a == NULL || a->data == NULL || a->mlen < a->slen ||
484
- a->slen < 0 || a->mlen == 0)
485
- return BSTR_ERR;
486
-
487
- if (len > 0) {
488
- if (balloc (a, len) != BSTR_OK) return BSTR_ERR;
489
- bstr__memmove (a->data, b->data + left, len);
490
- a->slen = len;
491
- } else {
492
- a->slen = 0;
493
- }
494
- a->data[a->slen] = (unsigned char) '\0';
495
- return BSTR_OK;
496
- }
497
-
498
- /* int bassigncstr (bstring a, const char * str)
499
- *
500
- * Overwrite the string a with the contents of char * string str. Note that
501
- * the bstring a must be a well defined and writable bstring. If an error
502
- * occurs BSTR_ERR is returned however a may be partially overwritten.
503
- */
504
- int bassigncstr (bstring a, const char * str) {
505
- int i;
506
- size_t len;
507
- if (a == NULL || a->data == NULL || a->mlen < a->slen ||
508
- a->slen < 0 || a->mlen == 0 || NULL == str)
509
- return BSTR_ERR;
510
-
511
- for (i=0; i < a->mlen; i++) {
512
- if ('\0' == (a->data[i] = str[i])) {
513
- a->slen = i;
514
- return BSTR_OK;
515
- }
516
- }
517
-
518
- a->slen = i;
519
- len = strlen (str + i);
520
- if (len > INT_MAX || i + len + 1 > INT_MAX ||
521
- 0 > balloc (a, (int) (i + len + 1))) return BSTR_ERR;
522
- bBlockCopy (a->data + i, str + i, (size_t) len + 1);
523
- a->slen += (int) len;
524
- return BSTR_OK;
525
- }
526
-
527
- /* int bassignblk (bstring a, const void * s, int len)
528
- *
529
- * Overwrite the string a with the contents of the block (s, len). Note that
530
- * the bstring a must be a well defined and writable bstring. If an error
531
- * occurs BSTR_ERR is returned and a is not overwritten.
532
- */
533
- int bassignblk (bstring a, const void * s, int len) {
534
- if (a == NULL || a->data == NULL || a->mlen < a->slen ||
535
- a->slen < 0 || a->mlen == 0 || NULL == s || len + 1 < 1)
536
- return BSTR_ERR;
537
- if (len + 1 > a->mlen && 0 > balloc (a, len + 1)) return BSTR_ERR;
538
- bBlockCopy (a->data, s, (size_t) len);
539
- a->data[len] = (unsigned char) '\0';
540
- a->slen = len;
541
- return BSTR_OK;
542
- }
543
-
544
- /* int btrunc (bstring b, int n)
545
- *
546
- * Truncate the bstring to at most n characters.
547
- */
548
- int btrunc (bstring b, int n) {
549
- if (n < 0 || b == NULL || b->data == NULL || b->mlen < b->slen ||
550
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
551
- if (b->slen > n) {
552
- b->slen = n;
553
- b->data[n] = (unsigned char) '\0';
554
- }
555
- return BSTR_OK;
556
- }
557
-
558
- #define upcase(c) (toupper ((unsigned char) c))
559
- #define downcase(c) (tolower ((unsigned char) c))
560
- #define wspace(c) (isspace ((unsigned char) c))
561
-
562
- /* int btoupper (bstring b)
563
- *
564
- * Convert contents of bstring to upper case.
565
- */
566
- int btoupper (bstring b) {
567
- int i, len;
568
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
569
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
570
- for (i=0, len = b->slen; i < len; i++) {
571
- b->data[i] = (unsigned char) upcase (b->data[i]);
572
- }
573
- return BSTR_OK;
574
- }
575
-
576
- /* int btolower (bstring b)
577
- *
578
- * Convert contents of bstring to lower case.
579
- */
580
- int btolower (bstring b) {
581
- int i, len;
582
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
583
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
584
- for (i=0, len = b->slen; i < len; i++) {
585
- b->data[i] = (unsigned char) downcase (b->data[i]);
586
- }
587
- return BSTR_OK;
588
- }
589
-
590
- /* int bstricmp (const_bstring b0, const_bstring b1)
591
- *
592
- * Compare two strings without differentiating between case. The return
593
- * value is the difference of the values of the characters where the two
594
- * strings first differ after lower case transformation, otherwise 0 is
595
- * returned indicating that the strings are equal. If the lengths are
596
- * different, then a difference from 0 is given, but if the first extra
597
- * character is '\0', then it is taken to be the value UCHAR_MAX+1.
598
- */
599
- int bstricmp (const_bstring b0, const_bstring b1) {
600
- int i, v, n;
601
-
602
- if (bdata (b0) == NULL || b0->slen < 0 ||
603
- bdata (b1) == NULL || b1->slen < 0) return SHRT_MIN;
604
- if ((n = b0->slen) > b1->slen) n = b1->slen;
605
- else if (b0->slen == b1->slen && b0->data == b1->data) return BSTR_OK;
606
-
607
- for (i = 0; i < n; i ++) {
608
- v = (char) downcase (b0->data[i])
609
- - (char) downcase (b1->data[i]);
610
- if (0 != v) return v;
611
- }
612
-
613
- if (b0->slen > n) {
614
- v = (char) downcase (b0->data[n]);
615
- if (v) return v;
616
- return UCHAR_MAX + 1;
617
- }
618
- if (b1->slen > n) {
619
- v = - (char) downcase (b1->data[n]);
620
- if (v) return v;
621
- return - (int) (UCHAR_MAX + 1);
622
- }
623
- return BSTR_OK;
624
- }
625
-
626
- /* int bstrnicmp (const_bstring b0, const_bstring b1, int n)
627
- *
628
- * Compare two strings without differentiating between case for at most n
629
- * characters. If the position where the two strings first differ is
630
- * before the nth position, the return value is the difference of the values
631
- * of the characters, otherwise 0 is returned. If the lengths are different
632
- * and less than n characters, then a difference from 0 is given, but if the
633
- * first extra character is '\0', then it is taken to be the value
634
- * UCHAR_MAX+1.
635
- */
636
- int bstrnicmp (const_bstring b0, const_bstring b1, int n) {
637
- int i, v, m;
638
-
639
- if (bdata (b0) == NULL || b0->slen < 0 ||
640
- bdata (b1) == NULL || b1->slen < 0 || n < 0) return SHRT_MIN;
641
- m = n;
642
- if (m > b0->slen) m = b0->slen;
643
- if (m > b1->slen) m = b1->slen;
644
-
645
- if (b0->data != b1->data) {
646
- for (i = 0; i < m; i ++) {
647
- v = (char) downcase (b0->data[i]);
648
- v -= (char) downcase (b1->data[i]);
649
- if (v != 0) return b0->data[i] - b1->data[i];
650
- }
651
- }
652
-
653
- if (n == m || b0->slen == b1->slen) return BSTR_OK;
654
-
655
- if (b0->slen > m) {
656
- v = (char) downcase (b0->data[m]);
657
- if (v) return v;
658
- return UCHAR_MAX + 1;
659
- }
660
-
661
- v = - (char) downcase (b1->data[m]);
662
- if (v) return v;
663
- return - (int) (UCHAR_MAX + 1);
664
- }
665
-
666
- /* int biseqcaseless (const_bstring b0, const_bstring b1)
667
- *
668
- * Compare two strings for equality without differentiating between case.
669
- * If the strings differ other than in case, 0 is returned, if the strings
670
- * are the same, 1 is returned, if there is an error, -1 is returned. If
671
- * the length of the strings are different, this function is O(1). '\0'
672
- * termination characters are not treated in any special way.
673
- */
674
- int biseqcaseless (const_bstring b0, const_bstring b1) {
675
- int i, n;
676
-
677
- if (bdata (b0) == NULL || b0->slen < 0 ||
678
- bdata (b1) == NULL || b1->slen < 0) return BSTR_ERR;
679
- if (b0->slen != b1->slen) return BSTR_OK;
680
- if (b0->data == b1->data || b0->slen == 0) return 1;
681
- for (i=0, n=b0->slen; i < n; i++) {
682
- if (b0->data[i] != b1->data[i]) {
683
- unsigned char c = (unsigned char) downcase (b0->data[i]);
684
- if (c != (unsigned char) downcase (b1->data[i])) return 0;
685
- }
686
- }
687
- return 1;
688
- }
689
-
690
- /* int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len)
691
- *
692
- * Compare beginning of string b0 with a block of memory of length len
693
- * without differentiating between case for equality. If the beginning of b0
694
- * differs from the memory block other than in case (or if b0 is too short),
695
- * 0 is returned, if the strings are the same, 1 is returned, if there is an
696
- * error, -1 is returned. '\0' characters are not treated in any special
697
- * way.
698
- */
699
- int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) {
700
- int i;
701
-
702
- if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0)
703
- return BSTR_ERR;
704
- if (b0->slen < len) return BSTR_OK;
705
- if (b0->data == (const unsigned char *) blk || len == 0) return 1;
706
-
707
- for (i = 0; i < len; i ++) {
708
- if (b0->data[i] != ((const unsigned char *) blk)[i]) {
709
- if (downcase (b0->data[i]) !=
710
- downcase (((const unsigned char *) blk)[i])) return 0;
711
- }
712
- }
713
- return 1;
714
- }
715
-
716
- /*
717
- * int bltrimws (bstring b)
718
- *
719
- * Delete whitespace contiguous from the left end of the string.
720
- */
721
- int bltrimws (bstring b) {
722
- int i, len;
723
-
724
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
725
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
726
-
727
- for (len = b->slen, i = 0; i < len; i++) {
728
- if (!wspace (b->data[i])) {
729
- return bdelete (b, 0, i);
730
- }
731
- }
732
-
733
- b->data[0] = (unsigned char) '\0';
734
- b->slen = 0;
735
- return BSTR_OK;
736
- }
737
-
738
- /*
739
- * int brtrimws (bstring b)
740
- *
741
- * Delete whitespace contiguous from the right end of the string.
742
- */
743
- int brtrimws (bstring b) {
744
- int i;
745
-
746
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
747
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
748
-
749
- for (i = b->slen - 1; i >= 0; i--) {
750
- if (!wspace (b->data[i])) {
751
- if (b->mlen > i) b->data[i+1] = (unsigned char) '\0';
752
- b->slen = i + 1;
753
- return BSTR_OK;
754
- }
755
- }
756
-
757
- b->data[0] = (unsigned char) '\0';
758
- b->slen = 0;
759
- return BSTR_OK;
760
- }
761
-
762
- /*
763
- * int btrimws (bstring b)
764
- *
765
- * Delete whitespace contiguous from both ends of the string.
766
- */
767
- int btrimws (bstring b) {
768
- int i, j;
769
-
770
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
771
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
772
-
773
- for (i = b->slen - 1; i >= 0; i--) {
774
- if (!wspace (b->data[i])) {
775
- if (b->mlen > i) b->data[i+1] = (unsigned char) '\0';
776
- b->slen = i + 1;
777
- for (j = 0; wspace (b->data[j]); j++) {}
778
- return bdelete (b, 0, j);
779
- }
780
- }
781
-
782
- b->data[0] = (unsigned char) '\0';
783
- b->slen = 0;
784
- return BSTR_OK;
785
- }
786
-
787
- /* int biseq (const_bstring b0, const_bstring b1)
788
- *
789
- * Compare the string b0 and b1. If the strings differ, 0 is returned, if
790
- * the strings are the same, 1 is returned, if there is an error, -1 is
791
- * returned. If the length of the strings are different, this function is
792
- * O(1). '\0' termination characters are not treated in any special way.
793
- */
794
- int biseq (const_bstring b0, const_bstring b1) {
795
- if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL ||
796
- b0->slen < 0 || b1->slen < 0) return BSTR_ERR;
797
- if (b0->slen != b1->slen) return BSTR_OK;
798
- if (b0->data == b1->data || b0->slen == 0) return 1;
799
- return !bstr__memcmp (b0->data, b1->data, b0->slen);
800
- }
801
-
802
- /* int bisstemeqblk (const_bstring b0, const void * blk, int len)
803
- *
804
- * Compare beginning of string b0 with a block of memory of length len for
805
- * equality. If the beginning of b0 differs from the memory block (or if b0
806
- * is too short), 0 is returned, if the strings are the same, 1 is returned,
807
- * if there is an error, -1 is returned. '\0' characters are not treated in
808
- * any special way.
809
- */
810
- int bisstemeqblk (const_bstring b0, const void * blk, int len) {
811
- int i;
812
-
813
- if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0)
814
- return BSTR_ERR;
815
- if (b0->slen < len) return BSTR_OK;
816
- if (b0->data == (const unsigned char *) blk || len == 0) return 1;
817
-
818
- for (i = 0; i < len; i ++) {
819
- if (b0->data[i] != ((const unsigned char *) blk)[i]) return BSTR_OK;
820
- }
821
- return 1;
822
- }
823
-
824
- /* int biseqcstr (const_bstring b, const char *s)
825
- *
826
- * Compare the bstring b and char * string s. The C string s must be '\0'
827
- * terminated at exactly the length of the bstring b, and the contents
828
- * between the two must be identical with the bstring b with no '\0'
829
- * characters for the two contents to be considered equal. This is
830
- * equivalent to the condition that their current contents will be always be
831
- * equal when comparing them in the same format after converting one or the
832
- * other. If the strings are equal 1 is returned, if they are unequal 0 is
833
- * returned and if there is a detectable error BSTR_ERR is returned.
834
- */
835
- int biseqcstr (const_bstring b, const char * s) {
836
- int i;
837
- if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR;
838
- for (i=0; i < b->slen; i++) {
839
- if (s[i] == '\0' || b->data[i] != (unsigned char) s[i]) return BSTR_OK;
840
- }
841
- return s[i] == '\0';
842
- }
843
-
844
- /* int biseqcstrcaseless (const_bstring b, const char *s)
845
- *
846
- * Compare the bstring b and char * string s. The C string s must be '\0'
847
- * terminated at exactly the length of the bstring b, and the contents
848
- * between the two must be identical except for case with the bstring b with
849
- * no '\0' characters for the two contents to be considered equal. This is
850
- * equivalent to the condition that their current contents will be always be
851
- * equal ignoring case when comparing them in the same format after
852
- * converting one or the other. If the strings are equal, except for case,
853
- * 1 is returned, if they are unequal regardless of case 0 is returned and
854
- * if there is a detectable error BSTR_ERR is returned.
855
- */
856
- int biseqcstrcaseless (const_bstring b, const char * s) {
857
- int i;
858
- if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR;
859
- for (i=0; i < b->slen; i++) {
860
- if (s[i] == '\0' ||
861
- (b->data[i] != (unsigned char) s[i] &&
862
- downcase (b->data[i]) != (unsigned char) downcase (s[i])))
863
- return BSTR_OK;
864
- }
865
- return s[i] == '\0';
866
- }
867
-
868
- /* int bstrcmp (const_bstring b0, const_bstring b1)
869
- *
870
- * Compare the string b0 and b1. If there is an error, SHRT_MIN is returned,
871
- * otherwise a value less than or greater than zero, indicating that the
872
- * string pointed to by b0 is lexicographically less than or greater than
873
- * the string pointed to by b1 is returned. If the the string lengths are
874
- * unequal but the characters up until the length of the shorter are equal
875
- * then a value less than, or greater than zero, indicating that the string
876
- * pointed to by b0 is shorter or longer than the string pointed to by b1 is
877
- * returned. 0 is returned if and only if the two strings are the same. If
878
- * the length of the strings are different, this function is O(n). Like its
879
- * standard C library counter part strcmp, the comparison does not proceed
880
- * past any '\0' termination characters encountered.
881
- */
882
- int bstrcmp (const_bstring b0, const_bstring b1) {
883
- int i, v, n;
884
-
885
- if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL ||
886
- b0->slen < 0 || b1->slen < 0) return SHRT_MIN;
887
- n = b0->slen; if (n > b1->slen) n = b1->slen;
888
- if (b0->slen == b1->slen && (b0->data == b1->data || b0->slen == 0))
889
- return BSTR_OK;
890
-
891
- for (i = 0; i < n; i ++) {
892
- v = ((char) b0->data[i]) - ((char) b1->data[i]);
893
- if (v != 0) return v;
894
- if (b0->data[i] == (unsigned char) '\0') return BSTR_OK;
895
- }
896
-
897
- if (b0->slen > n) return 1;
898
- if (b1->slen > n) return -1;
899
- return BSTR_OK;
900
- }
901
-
902
- /* int bstrncmp (const_bstring b0, const_bstring b1, int n)
903
- *
904
- * Compare the string b0 and b1 for at most n characters. If there is an
905
- * error, SHRT_MIN is returned, otherwise a value is returned as if b0 and
906
- * b1 were first truncated to at most n characters then bstrcmp was called
907
- * with these new strings are paremeters. If the length of the strings are
908
- * different, this function is O(n). Like its standard C library counter
909
- * part strcmp, the comparison does not proceed past any '\0' termination
910
- * characters encountered.
911
- */
912
- int bstrncmp (const_bstring b0, const_bstring b1, int n) {
913
- int i, v, m;
914
-
915
- if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL ||
916
- b0->slen < 0 || b1->slen < 0) return SHRT_MIN;
917
- m = n;
918
- if (m > b0->slen) m = b0->slen;
919
- if (m > b1->slen) m = b1->slen;
920
-
921
- if (b0->data != b1->data) {
922
- for (i = 0; i < m; i ++) {
923
- v = ((char) b0->data[i]) - ((char) b1->data[i]);
924
- if (v != 0) return v;
925
- if (b0->data[i] == (unsigned char) '\0') return BSTR_OK;
926
- }
927
- }
928
-
929
- if (n == m || b0->slen == b1->slen) return BSTR_OK;
930
-
931
- if (b0->slen > m) return 1;
932
- return -1;
933
- }
934
-
935
- /* bstring bmidstr (const_bstring b, int left, int len)
936
- *
937
- * Create a bstring which is the substring of b starting from position left
938
- * and running for a length len (clamped by the end of the bstring b.) If
939
- * b is detectably invalid, then NULL is returned. The section described
940
- * by (left, len) is clamped to the boundaries of b.
941
- */
942
- bstring bmidstr (const_bstring b, int left, int len) {
943
-
944
- if (b == NULL || b->slen < 0 || b->data == NULL) return NULL;
945
-
946
- if (left < 0) {
947
- len += left;
948
- left = 0;
949
- }
950
-
951
- if (len > b->slen - left) len = b->slen - left;
952
-
953
- if (len <= 0) return bfromcstr ("");
954
- return blk2bstr (b->data + left, len);
955
- }
956
-
957
- /* int bdelete (bstring b, int pos, int len)
958
- *
959
- * Removes characters from pos to pos+len-1 inclusive and shifts the tail of
960
- * the bstring starting from pos+len to pos. len must be positive for this
961
- * call to have any effect. The section of the string described by (pos,
962
- * len) is clamped to boundaries of the bstring b.
963
- */
964
- int bdelete (bstring b, int pos, int len) {
965
- /* Clamp to left side of bstring */
966
- if (pos < 0) {
967
- len += pos;
968
- pos = 0;
969
- }
970
-
971
- if (len < 0 || b == NULL || b->data == NULL || b->slen < 0 ||
972
- b->mlen < b->slen || b->mlen <= 0)
973
- return BSTR_ERR;
974
- if (len > 0 && pos < b->slen) {
975
- if (pos + len >= b->slen) {
976
- b->slen = pos;
977
- } else {
978
- bBlockCopy ((char *) (b->data + pos),
979
- (char *) (b->data + pos + len),
980
- b->slen - (pos+len));
981
- b->slen -= len;
982
- }
983
- b->data[b->slen] = (unsigned char) '\0';
984
- }
985
- return BSTR_OK;
986
- }
987
-
988
- /* int bdestroy (bstring b)
989
- *
990
- * Free up the bstring. Note that if b is detectably invalid or not writable
991
- * then no action is performed and BSTR_ERR is returned. Like a freed memory
992
- * allocation, dereferences, writes or any other action on b after it has
993
- * been bdestroyed is undefined.
994
- */
995
- int bdestroy (bstring b) {
996
- if (b == NULL || b->slen < 0 || b->mlen <= 0 || b->mlen < b->slen ||
997
- b->data == NULL)
998
- return BSTR_ERR;
999
-
1000
- bstr__free (b->data);
1001
-
1002
- /* In case there is any stale usage, there is one more chance to
1003
- notice this error. */
1004
-
1005
- b->slen = -1;
1006
- b->mlen = -__LINE__;
1007
- b->data = NULL;
1008
-
1009
- bstr__free (b);
1010
- return BSTR_OK;
1011
- }
1012
-
1013
- /* int binstr (const_bstring b1, int pos, const_bstring b2)
1014
- *
1015
- * Search for the bstring b2 in b1 starting from position pos, and searching
1016
- * forward. If it is found then return with the first position where it is
1017
- * found, otherwise return BSTR_ERR. Note that this is just a brute force
1018
- * string searcher that does not attempt clever things like the Boyer-Moore
1019
- * search algorithm. Because of this there are many degenerate cases where
1020
- * this can take much longer than it needs to.
1021
- */
1022
- int binstr (const_bstring b1, int pos, const_bstring b2) {
1023
- int j, ii, ll, lf;
1024
- unsigned char * d0;
1025
- unsigned char c0;
1026
- register unsigned char * d1;
1027
- register unsigned char c1;
1028
- register int i;
1029
-
1030
- if (b1 == NULL || b1->data == NULL || b1->slen < 0 ||
1031
- b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR;
1032
- if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR;
1033
- if (b1->slen < pos || pos < 0) return BSTR_ERR;
1034
- if (b2->slen == 0) return pos;
1035
-
1036
- /* No space to find such a string? */
1037
- if ((lf = b1->slen - b2->slen + 1) <= pos) return BSTR_ERR;
1038
-
1039
- /* An obvious alias case */
1040
- if (b1->data == b2->data && pos == 0) return 0;
1041
-
1042
- i = pos;
1043
-
1044
- d0 = b2->data;
1045
- d1 = b1->data;
1046
- ll = b2->slen;
1047
-
1048
- /* Peel off the b2->slen == 1 case */
1049
- c0 = d0[0];
1050
- if (1 == ll) {
1051
- for (;i < lf; i++) if (c0 == d1[i]) return i;
1052
- return BSTR_ERR;
1053
- }
1054
-
1055
- c1 = c0;
1056
- j = 0;
1057
- lf = b1->slen - 1;
1058
-
1059
- ii = -1;
1060
- if (i < lf) do {
1061
- /* Unrolled current character test */
1062
- if (c1 != d1[i]) {
1063
- if (c1 != d1[1+i]) {
1064
- i += 2;
1065
- continue;
1066
- }
1067
- i++;
1068
- }
1069
-
1070
- /* Take note if this is the start of a potential match */
1071
- if (0 == j) ii = i;
1072
-
1073
- /* Shift the test character down by one */
1074
- j++;
1075
- i++;
1076
-
1077
- /* If this isn't past the last character continue */
1078
- if (j < ll) {
1079
- c1 = d0[j];
1080
- continue;
1081
- }
1082
-
1083
- N0:;
1084
-
1085
- /* If no characters mismatched, then we matched */
1086
- if (i == ii+j) return ii;
1087
-
1088
- /* Shift back to the beginning */
1089
- i -= j;
1090
- j = 0;
1091
- c1 = c0;
1092
- } while (i < lf);
1093
-
1094
- /* Deal with last case if unrolling caused a misalignment */
1095
- if (i == lf && ll == j+1 && c1 == d1[i]) goto N0;
1096
-
1097
- return BSTR_ERR;
1098
- }
1099
-
1100
- /* int binstrr (const_bstring b1, int pos, const_bstring b2)
1101
- *
1102
- * Search for the bstring b2 in b1 starting from position pos, and searching
1103
- * backward. If it is found then return with the first position where it is
1104
- * found, otherwise return BSTR_ERR. Note that this is just a brute force
1105
- * string searcher that does not attempt clever things like the Boyer-Moore
1106
- * search algorithm. Because of this there are many degenerate cases where
1107
- * this can take much longer than it needs to.
1108
- */
1109
- int binstrr (const_bstring b1, int pos, const_bstring b2) {
1110
- int j, i, l;
1111
- unsigned char * d0, * d1;
1112
-
1113
- if (b1 == NULL || b1->data == NULL || b1->slen < 0 ||
1114
- b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR;
1115
- if (b1->slen == pos && b2->slen == 0) return pos;
1116
- if (b1->slen < pos || pos < 0) return BSTR_ERR;
1117
- if (b2->slen == 0) return pos;
1118
-
1119
- /* Obvious alias case */
1120
- if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return 0;
1121
-
1122
- i = pos;
1123
- if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR;
1124
-
1125
- /* If no space to find such a string then snap back */
1126
- if (l + 1 <= i) i = l;
1127
- j = 0;
1128
-
1129
- d0 = b2->data;
1130
- d1 = b1->data;
1131
- l = b2->slen;
1132
-
1133
- for (;;) {
1134
- if (d0[j] == d1[i + j]) {
1135
- j ++;
1136
- if (j >= l) return i;
1137
- } else {
1138
- i --;
1139
- if (i < 0) break;
1140
- j=0;
1141
- }
1142
- }
1143
-
1144
- return BSTR_ERR;
1145
- }
1146
-
1147
- /* int binstrcaseless (const_bstring b1, int pos, const_bstring b2)
1148
- *
1149
- * Search for the bstring b2 in b1 starting from position pos, and searching
1150
- * forward but without regard to case. If it is found then return with the
1151
- * first position where it is found, otherwise return BSTR_ERR. Note that
1152
- * this is just a brute force string searcher that does not attempt clever
1153
- * things like the Boyer-Moore search algorithm. Because of this there are
1154
- * many degenerate cases where this can take much longer than it needs to.
1155
- */
1156
- int binstrcaseless (const_bstring b1, int pos, const_bstring b2) {
1157
- int j, i, l, ll;
1158
- unsigned char * d0, * d1;
1159
-
1160
- if (b1 == NULL || b1->data == NULL || b1->slen < 0 ||
1161
- b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR;
1162
- if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR;
1163
- if (b1->slen < pos || pos < 0) return BSTR_ERR;
1164
- if (b2->slen == 0) return pos;
1165
-
1166
- l = b1->slen - b2->slen + 1;
1167
-
1168
- /* No space to find such a string? */
1169
- if (l <= pos) return BSTR_ERR;
1170
-
1171
- /* An obvious alias case */
1172
- if (b1->data == b2->data && pos == 0) return BSTR_OK;
1173
-
1174
- i = pos;
1175
- j = 0;
1176
-
1177
- d0 = b2->data;
1178
- d1 = b1->data;
1179
- ll = b2->slen;
1180
-
1181
- for (;;) {
1182
- if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) {
1183
- j ++;
1184
- if (j >= ll) return i;
1185
- } else {
1186
- i ++;
1187
- if (i >= l) break;
1188
- j=0;
1189
- }
1190
- }
1191
-
1192
- return BSTR_ERR;
1193
- }
1194
-
1195
- /* int binstrrcaseless (const_bstring b1, int pos, const_bstring b2)
1196
- *
1197
- * Search for the bstring b2 in b1 starting from position pos, and searching
1198
- * backward but without regard to case. If it is found then return with the
1199
- * first position where it is found, otherwise return BSTR_ERR. Note that
1200
- * this is just a brute force string searcher that does not attempt clever
1201
- * things like the Boyer-Moore search algorithm. Because of this there are
1202
- * many degenerate cases where this can take much longer than it needs to.
1203
- */
1204
- int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) {
1205
- int j, i, l;
1206
- unsigned char * d0, * d1;
1207
-
1208
- if (b1 == NULL || b1->data == NULL || b1->slen < 0 ||
1209
- b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR;
1210
- if (b1->slen == pos && b2->slen == 0) return pos;
1211
- if (b1->slen < pos || pos < 0) return BSTR_ERR;
1212
- if (b2->slen == 0) return pos;
1213
-
1214
- /* Obvious alias case */
1215
- if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return BSTR_OK;
1216
-
1217
- i = pos;
1218
- if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR;
1219
-
1220
- /* If no space to find such a string then snap back */
1221
- if (l + 1 <= i) i = l;
1222
- j = 0;
1223
-
1224
- d0 = b2->data;
1225
- d1 = b1->data;
1226
- l = b2->slen;
1227
-
1228
- for (;;) {
1229
- if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) {
1230
- j ++;
1231
- if (j >= l) return i;
1232
- } else {
1233
- i --;
1234
- if (i < 0) break;
1235
- j=0;
1236
- }
1237
- }
1238
-
1239
- return BSTR_ERR;
1240
- }
1241
-
1242
-
1243
- /* int bstrchrp (const_bstring b, int c, int pos)
1244
- *
1245
- * Search for the character c in b forwards from the position pos
1246
- * (inclusive).
1247
- */
1248
- int bstrchrp (const_bstring b, int c, int pos) {
1249
- unsigned char * p;
1250
-
1251
- if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR;
1252
- p = (unsigned char *) bstr__memchr ((b->data + pos), (unsigned char) c, (b->slen - pos));
1253
- if (p) return (int) (p - b->data);
1254
- return BSTR_ERR;
1255
- }
1256
-
1257
- /* int bstrrchrp (const_bstring b, int c, int pos)
1258
- *
1259
- * Search for the character c in b backwards from the position pos in string
1260
- * (inclusive).
1261
- */
1262
- int bstrrchrp (const_bstring b, int c, int pos) {
1263
- int i;
1264
-
1265
- if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR;
1266
- for (i=pos; i >= 0; i--) {
1267
- if (b->data[i] == (unsigned char) c) return i;
1268
- }
1269
- return BSTR_ERR;
1270
- }
1271
-
1272
- #if !defined (BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF)
1273
- #define LONG_LOG_BITS_QTY (3)
1274
- #define LONG_BITS_QTY (1 << LONG_LOG_BITS_QTY)
1275
- #define LONG_TYPE unsigned char
1276
-
1277
- #define CFCLEN ((1 << CHAR_BIT) / LONG_BITS_QTY)
1278
- struct charField { LONG_TYPE content[CFCLEN]; };
1279
- #define testInCharField(cf,c) ((cf)->content[(c) >> LONG_LOG_BITS_QTY] & (((long)1) << ((c) & (LONG_BITS_QTY-1))))
1280
- #define setInCharField(cf,idx) { \
1281
- unsigned int c = (unsigned int) (idx); \
1282
- (cf)->content[c >> LONG_LOG_BITS_QTY] |= (LONG_TYPE) (1ul << (c & (LONG_BITS_QTY-1))); \
1283
- }
1284
-
1285
- #else
1286
-
1287
- #define CFCLEN (1 << CHAR_BIT)
1288
- struct charField { unsigned char content[CFCLEN]; };
1289
- #define testInCharField(cf,c) ((cf)->content[(unsigned char) (c)])
1290
- #define setInCharField(cf,idx) (cf)->content[(unsigned int) (idx)] = ~0
1291
-
1292
- #endif
1293
-
1294
- /* Convert a bstring to charField */
1295
- static int buildCharField (struct charField * cf, const_bstring b) {
1296
- int i;
1297
- if (b == NULL || b->data == NULL || b->slen <= 0) return BSTR_ERR;
1298
- memset ((void *) cf->content, 0, sizeof (struct charField));
1299
- for (i=0; i < b->slen; i++) {
1300
- setInCharField (cf, b->data[i]);
1301
- }
1302
- return BSTR_OK;
1303
- }
1304
-
1305
- static void invertCharField (struct charField * cf) {
1306
- int i;
1307
- for (i=0; i < CFCLEN; i++) cf->content[i] = ~cf->content[i];
1308
- }
1309
-
1310
- /* Inner engine for binchr */
1311
- static int binchrCF (const unsigned char * data, int len, int pos, const struct charField * cf) {
1312
- int i;
1313
- for (i=pos; i < len; i++) {
1314
- unsigned char c = (unsigned char) data[i];
1315
- if (testInCharField (cf, c)) return i;
1316
- }
1317
- return BSTR_ERR;
1318
- }
1319
-
1320
- /* int binchr (const_bstring b0, int pos, const_bstring b1);
1321
- *
1322
- * Search for the first position in b0 starting from pos or after, in which
1323
- * one of the characters in b1 is found and return it. If such a position
1324
- * does not exist in b0, then BSTR_ERR is returned.
1325
- */
1326
- int binchr (const_bstring b0, int pos, const_bstring b1) {
1327
- struct charField chrs;
1328
- if (pos < 0 || b0 == NULL || b0->data == NULL ||
1329
- b0->slen <= pos) return BSTR_ERR;
1330
- if (1 == b1->slen) return bstrchrp (b0, b1->data[0], pos);
1331
- if (0 > buildCharField (&chrs, b1)) return BSTR_ERR;
1332
- return binchrCF (b0->data, b0->slen, pos, &chrs);
1333
- }
1334
-
1335
- /* Inner engine for binchrr */
1336
- static int binchrrCF (const unsigned char * data, int pos, const struct charField * cf) {
1337
- int i;
1338
- for (i=pos; i >= 0; i--) {
1339
- unsigned int c = (unsigned int) data[i];
1340
- if (testInCharField (cf, c)) return i;
1341
- }
1342
- return BSTR_ERR;
1343
- }
1344
-
1345
- /* int binchrr (const_bstring b0, int pos, const_bstring b1);
1346
- *
1347
- * Search for the last position in b0 no greater than pos, in which one of
1348
- * the characters in b1 is found and return it. If such a position does not
1349
- * exist in b0, then BSTR_ERR is returned.
1350
- */
1351
- int binchrr (const_bstring b0, int pos, const_bstring b1) {
1352
- struct charField chrs;
1353
- if (pos < 0 || b0 == NULL || b0->data == NULL || b1 == NULL ||
1354
- b0->slen < pos) return BSTR_ERR;
1355
- if (pos == b0->slen) pos--;
1356
- if (1 == b1->slen) return bstrrchrp (b0, b1->data[0], pos);
1357
- if (0 > buildCharField (&chrs, b1)) return BSTR_ERR;
1358
- return binchrrCF (b0->data, pos, &chrs);
1359
- }
1360
-
1361
- /* int bninchr (const_bstring b0, int pos, const_bstring b1);
1362
- *
1363
- * Search for the first position in b0 starting from pos or after, in which
1364
- * none of the characters in b1 is found and return it. If such a position
1365
- * does not exist in b0, then BSTR_ERR is returned.
1366
- */
1367
- int bninchr (const_bstring b0, int pos, const_bstring b1) {
1368
- struct charField chrs;
1369
- if (pos < 0 || b0 == NULL || b0->data == NULL ||
1370
- b0->slen <= pos) return BSTR_ERR;
1371
- if (buildCharField (&chrs, b1) < 0) return BSTR_ERR;
1372
- invertCharField (&chrs);
1373
- return binchrCF (b0->data, b0->slen, pos, &chrs);
1374
- }
1375
-
1376
- /* int bninchrr (const_bstring b0, int pos, const_bstring b1);
1377
- *
1378
- * Search for the last position in b0 no greater than pos, in which none of
1379
- * the characters in b1 is found and return it. If such a position does not
1380
- * exist in b0, then BSTR_ERR is returned.
1381
- */
1382
- int bninchrr (const_bstring b0, int pos, const_bstring b1) {
1383
- struct charField chrs;
1384
- if (pos < 0 || b0 == NULL || b0->data == NULL ||
1385
- b0->slen < pos) return BSTR_ERR;
1386
- if (pos == b0->slen) pos--;
1387
- if (buildCharField (&chrs, b1) < 0) return BSTR_ERR;
1388
- invertCharField (&chrs);
1389
- return binchrrCF (b0->data, pos, &chrs);
1390
- }
1391
-
1392
- /* int bsetstr (bstring b0, int pos, bstring b1, unsigned char fill)
1393
- *
1394
- * Overwrite the string b0 starting at position pos with the string b1. If
1395
- * the position pos is past the end of b0, then the character "fill" is
1396
- * appended as necessary to make up the gap between the end of b0 and pos.
1397
- * If b1 is NULL, it behaves as if it were a 0-length string.
1398
- */
1399
- int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill) {
1400
- int d, newlen;
1401
- ptrdiff_t pd;
1402
- bstring aux = (bstring) b1;
1403
-
1404
- if (pos < 0 || b0 == NULL || b0->slen < 0 || NULL == b0->data ||
1405
- b0->mlen < b0->slen || b0->mlen <= 0) return BSTR_ERR;
1406
- if (b1 != NULL && (b1->slen < 0 || b1->data == NULL)) return BSTR_ERR;
1407
-
1408
- d = pos;
1409
-
1410
- /* Aliasing case */
1411
- if (NULL != aux) {
1412
- if ((pd = (ptrdiff_t) (b1->data - b0->data)) >= 0 && pd < (ptrdiff_t) b0->mlen) {
1413
- if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR;
1414
- }
1415
- d += aux->slen;
1416
- }
1417
-
1418
- /* Increase memory size if necessary */
1419
- if (balloc (b0, d + 1) != BSTR_OK) {
1420
- if (aux != b1) bdestroy (aux);
1421
- return BSTR_ERR;
1422
- }
1423
-
1424
- newlen = b0->slen;
1425
-
1426
- /* Fill in "fill" character as necessary */
1427
- if (pos > newlen) {
1428
- bstr__memset (b0->data + b0->slen, (int) fill, (size_t) (pos - b0->slen));
1429
- newlen = pos;
1430
- }
1431
-
1432
- /* Copy b1 to position pos in b0. */
1433
- if (aux != NULL) {
1434
- bBlockCopy ((char *) (b0->data + pos), (char *) aux->data, aux->slen);
1435
- if (aux != b1) bdestroy (aux);
1436
- }
1437
-
1438
- /* Indicate the potentially increased size of b0 */
1439
- if (d > newlen) newlen = d;
1440
-
1441
- b0->slen = newlen;
1442
- b0->data[newlen] = (unsigned char) '\0';
1443
-
1444
- return BSTR_OK;
1445
- }
1446
-
1447
- /* int binsert (bstring b1, int pos, bstring b2, unsigned char fill)
1448
- *
1449
- * Inserts the string b2 into b1 at position pos. If the position pos is
1450
- * past the end of b1, then the character "fill" is appended as necessary to
1451
- * make up the gap between the end of b1 and pos. Unlike bsetstr, binsert
1452
- * does not allow b2 to be NULL.
1453
- */
1454
- int binsert (bstring b1, int pos, const_bstring b2, unsigned char fill) {
1455
- int d, l;
1456
- ptrdiff_t pd;
1457
- bstring aux = (bstring) b2;
1458
-
1459
- if (pos < 0 || b1 == NULL || b2 == NULL || b1->slen < 0 ||
1460
- b2->slen < 0 || b1->mlen < b1->slen || b1->mlen <= 0) return BSTR_ERR;
1461
-
1462
- /* Aliasing case */
1463
- if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->mlen) {
1464
- if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR;
1465
- }
1466
-
1467
- /* Compute the two possible end pointers */
1468
- d = b1->slen + aux->slen;
1469
- l = pos + aux->slen;
1470
- if ((d|l) < 0) return BSTR_ERR;
1471
-
1472
- if (l > d) {
1473
- /* Inserting past the end of the string */
1474
- if (balloc (b1, l + 1) != BSTR_OK) {
1475
- if (aux != b2) bdestroy (aux);
1476
- return BSTR_ERR;
1477
- }
1478
- bstr__memset (b1->data + b1->slen, (int) fill, (size_t) (pos - b1->slen));
1479
- b1->slen = l;
1480
- } else {
1481
- /* Inserting in the middle of the string */
1482
- if (balloc (b1, d + 1) != BSTR_OK) {
1483
- if (aux != b2) bdestroy (aux);
1484
- return BSTR_ERR;
1485
- }
1486
- bBlockCopy (b1->data + l, b1->data + pos, d - l);
1487
- b1->slen = d;
1488
- }
1489
- bBlockCopy (b1->data + pos, aux->data, aux->slen);
1490
- b1->data[b1->slen] = (unsigned char) '\0';
1491
- if (aux != b2) bdestroy (aux);
1492
- return BSTR_OK;
1493
- }
1494
-
1495
- /* int breplace (bstring b1, int pos, int len, bstring b2,
1496
- * unsigned char fill)
1497
- *
1498
- * Replace a section of a string from pos for a length len with the string b2.
1499
- * fill is used is pos > b1->slen.
1500
- */
1501
- int breplace (bstring b1, int pos, int len, const_bstring b2,
1502
- unsigned char fill) {
1503
- int pl, ret;
1504
- ptrdiff_t pd;
1505
- bstring aux = (bstring) b2;
1506
-
1507
- if (pos < 0 || len < 0 || (pl = pos + len) < 0 || b1 == NULL ||
1508
- b2 == NULL || b1->data == NULL || b2->data == NULL ||
1509
- b1->slen < 0 || b2->slen < 0 || b1->mlen < b1->slen ||
1510
- b1->mlen <= 0) return BSTR_ERR;
1511
-
1512
- /* Straddles the end? */
1513
- if (pl >= b1->slen) {
1514
- if ((ret = bsetstr (b1, pos, b2, fill)) < 0) return ret;
1515
- if (pos + b2->slen < b1->slen) {
1516
- b1->slen = pos + b2->slen;
1517
- b1->data[b1->slen] = (unsigned char) '\0';
1518
- }
1519
- return ret;
1520
- }
1521
-
1522
- /* Aliasing case */
1523
- if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->slen) {
1524
- if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR;
1525
- }
1526
-
1527
- if (aux->slen > len) {
1528
- if (balloc (b1, b1->slen + aux->slen - len) != BSTR_OK) {
1529
- if (aux != b2) bdestroy (aux);
1530
- return BSTR_ERR;
1531
- }
1532
- }
1533
-
1534
- if (aux->slen != len) bstr__memmove (b1->data + pos + aux->slen, b1->data + pos + len, b1->slen - (pos + len));
1535
- bstr__memcpy (b1->data + pos, aux->data, aux->slen);
1536
- b1->slen += aux->slen - len;
1537
- b1->data[b1->slen] = (unsigned char) '\0';
1538
- if (aux != b2) bdestroy (aux);
1539
- return BSTR_OK;
1540
- }
1541
-
1542
- /* int bfindreplace (bstring b, const_bstring find, const_bstring repl,
1543
- * int pos)
1544
- *
1545
- * Replace all occurrences of a find string with a replace string after a
1546
- * given point in a bstring.
1547
- */
1548
-
1549
- typedef int (*instr_fnptr) (const_bstring s1, int pos, const_bstring s2);
1550
-
1551
- static int findreplaceengine (bstring b, const_bstring find, const_bstring repl, int pos, instr_fnptr instr) {
1552
- int i, ret, slen, mlen, delta, acc;
1553
- int * d;
1554
- int static_d[32];
1555
- ptrdiff_t pd;
1556
- bstring auxf = (bstring) find;
1557
- bstring auxr = (bstring) repl;
1558
-
1559
- if (b == NULL || b->data == NULL || find == NULL ||
1560
- find->data == NULL || repl == NULL || repl->data == NULL ||
1561
- pos < 0 || find->slen <= 0 || b->mlen < 0 || b->slen > b->mlen ||
1562
- b->mlen <= 0 || b->slen < 0 || repl->slen < 0) return BSTR_ERR;
1563
- if (pos > b->slen - find->slen) return BSTR_OK;
1564
-
1565
- /* Alias with find string */
1566
- pd = (ptrdiff_t) (find->data - b->data);
1567
- if ((ptrdiff_t) (pos - find->slen) < pd && pd < (ptrdiff_t) b->slen) {
1568
- if (NULL == (auxf = bstrcpy (find))) return BSTR_ERR;
1569
- }
1570
-
1571
- /* Alias with repl string */
1572
- pd = (ptrdiff_t) (repl->data - b->data);
1573
- if ((ptrdiff_t) (pos - repl->slen) < pd && pd < (ptrdiff_t) b->slen) {
1574
- if (NULL == (auxr = bstrcpy (repl))) {
1575
- if (auxf != find) bdestroy (auxf);
1576
- return BSTR_ERR;
1577
- }
1578
- }
1579
-
1580
- delta = auxf->slen - auxr->slen;
1581
-
1582
- /* in-place replacement since find and replace strings are of equal
1583
- length */
1584
- if (delta == 0) {
1585
- while ((pos = instr (b, pos, auxf)) >= 0) {
1586
- bstr__memcpy (b->data + pos, auxr->data, auxr->slen);
1587
- pos += auxf->slen;
1588
- }
1589
- if (auxf != find) bdestroy (auxf);
1590
- if (auxr != repl) bdestroy (auxr);
1591
- return BSTR_OK;
1592
- }
1593
-
1594
- /* shrinking replacement since auxf->slen > auxr->slen */
1595
- if (delta > 0) {
1596
- acc = 0;
1597
-
1598
- while ((i = instr (b, pos, auxf)) >= 0) {
1599
- if (acc && i > pos)
1600
- bstr__memmove (b->data + pos - acc, b->data + pos, i - pos);
1601
- if (auxr->slen)
1602
- bstr__memcpy (b->data + i - acc, auxr->data, auxr->slen);
1603
- acc += delta;
1604
- pos = i + auxf->slen;
1605
- }
1606
-
1607
- if (acc) {
1608
- i = b->slen;
1609
- if (i > pos)
1610
- bstr__memmove (b->data + pos - acc, b->data + pos, i - pos);
1611
- b->slen -= acc;
1612
- b->data[b->slen] = (unsigned char) '\0';
1613
- }
1614
-
1615
- if (auxf != find) bdestroy (auxf);
1616
- if (auxr != repl) bdestroy (auxr);
1617
- return BSTR_OK;
1618
- }
1619
-
1620
- /* expanding replacement since find->slen < repl->slen. Its a lot
1621
- more complicated. */
1622
-
1623
- mlen = 32;
1624
- d = (int *) static_d; /* Avoid malloc for trivial cases */
1625
- acc = slen = 0;
1626
-
1627
- while ((pos = instr (b, pos, auxf)) >= 0) {
1628
- if (slen + 1 >= mlen) {
1629
- int sl;
1630
- int * t;
1631
- mlen += mlen;
1632
- sl = (int)(sizeof (int *) * mlen);
1633
- if (static_d == d) d = NULL;
1634
- if (sl < mlen || NULL == (t = (int *) bstr__realloc (d, sl))) {
1635
- ret = BSTR_ERR;
1636
- goto done;
1637
- }
1638
- if (NULL == d) bstr__memcpy (t, static_d, sizeof (static_d));
1639
- d = t;
1640
- }
1641
- d[slen] = pos;
1642
- slen++;
1643
- acc -= delta;
1644
- pos += auxf->slen;
1645
- if (pos < 0 || acc < 0) {
1646
- ret = BSTR_ERR;
1647
- goto done;
1648
- }
1649
- }
1650
- d[slen] = b->slen;
1651
-
1652
- if (BSTR_OK == (ret = balloc (b, b->slen + acc + 1))) {
1653
- b->slen += acc;
1654
- for (i = slen-1; i >= 0; i--) {
1655
- int s, l;
1656
- s = d[i] + auxf->slen;
1657
- l = d[i+1] - s;
1658
- if (l) {
1659
- bstr__memmove (b->data + s + acc, b->data + s, l);
1660
- }
1661
- if (auxr->slen) {
1662
- bstr__memmove (b->data + s + acc - auxr->slen,
1663
- auxr->data, auxr->slen);
1664
- }
1665
- acc += delta;
1666
- }
1667
- b->data[b->slen] = (unsigned char) '\0';
1668
- }
1669
-
1670
- done:;
1671
- if (static_d == d) d = NULL;
1672
- bstr__free (d);
1673
- if (auxf != find) bdestroy (auxf);
1674
- if (auxr != repl) bdestroy (auxr);
1675
- return ret;
1676
- }
1677
-
1678
- /* int bfindreplace (bstring b, const_bstring find, const_bstring repl,
1679
- * int pos)
1680
- *
1681
- * Replace all occurrences of a find string with a replace string after a
1682
- * given point in a bstring.
1683
- */
1684
- int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos) {
1685
- return findreplaceengine (b, find, repl, pos, binstr);
1686
- }
1687
-
1688
- /* int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl,
1689
- * int pos)
1690
- *
1691
- * Replace all occurrences of a find string, ignoring case, with a replace
1692
- * string after a given point in a bstring.
1693
- */
1694
- int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos) {
1695
- return findreplaceengine (b, find, repl, pos, binstrcaseless);
1696
- }
1697
-
1698
- /* int binsertch (bstring b, int pos, int len, unsigned char fill)
1699
- *
1700
- * Inserts the character fill repeatedly into b at position pos for a
1701
- * length len. If the position pos is past the end of b, then the
1702
- * character "fill" is appended as necessary to make up the gap between the
1703
- * end of b and the position pos + len.
1704
- */
1705
- int binsertch (bstring b, int pos, int len, unsigned char fill) {
1706
- int d, l, i;
1707
-
1708
- if (pos < 0 || b == NULL || b->slen < 0 || b->mlen < b->slen ||
1709
- b->mlen <= 0 || len < 0) return BSTR_ERR;
1710
-
1711
- /* Compute the two possible end pointers */
1712
- d = b->slen + len;
1713
- l = pos + len;
1714
- if ((d|l) < 0) return BSTR_ERR;
1715
-
1716
- if (l > d) {
1717
- /* Inserting past the end of the string */
1718
- if (balloc (b, l + 1) != BSTR_OK) return BSTR_ERR;
1719
- pos = b->slen;
1720
- b->slen = l;
1721
- } else {
1722
- /* Inserting in the middle of the string */
1723
- if (balloc (b, d + 1) != BSTR_OK) return BSTR_ERR;
1724
- for (i = d - 1; i >= l; i--) {
1725
- b->data[i] = b->data[i - len];
1726
- }
1727
- b->slen = d;
1728
- }
1729
-
1730
- for (i=pos; i < l; i++) b->data[i] = fill;
1731
- b->data[b->slen] = (unsigned char) '\0';
1732
- return BSTR_OK;
1733
- }
1734
-
1735
- /* int bpattern (bstring b, int len)
1736
- *
1737
- * Replicate the bstring, b in place, end to end repeatedly until it
1738
- * surpasses len characters, then chop the result to exactly len characters.
1739
- * This function operates in-place. The function will return with BSTR_ERR
1740
- * if b is NULL or of length 0, otherwise BSTR_OK is returned.
1741
- */
1742
- int bpattern (bstring b, int len) {
1743
- int i, d;
1744
-
1745
- d = blength (b);
1746
- if (d <= 0 || len < 0 || balloc (b, len + 1) != BSTR_OK) return BSTR_ERR;
1747
- if (len > 0) {
1748
- if (d == 1) return bsetstr (b, len, NULL, b->data[0]);
1749
- for (i = d; i < len; i++) b->data[i] = b->data[i - d];
1750
- }
1751
- b->data[len] = (unsigned char) '\0';
1752
- b->slen = len;
1753
- return BSTR_OK;
1754
- }
1755
-
1756
- #define BS_BUFF_SZ (1024)
1757
-
1758
- /* int breada (bstring b, bNread readPtr, void * parm)
1759
- *
1760
- * Use a finite buffer fread-like function readPtr to concatenate to the
1761
- * bstring b the entire contents of file-like source data in a roughly
1762
- * efficient way.
1763
- */
1764
- int breada (bstring b, bNread readPtr, void * parm) {
1765
- int i, l, n;
1766
-
1767
- if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen ||
1768
- b->mlen <= 0 || readPtr == NULL) return BSTR_ERR;
1769
-
1770
- i = b->slen;
1771
- for (n=i+16; ; n += ((n < BS_BUFF_SZ) ? n : BS_BUFF_SZ)) {
1772
- if (BSTR_OK != balloc (b, n + 1)) return BSTR_ERR;
1773
- l = (int) readPtr ((void *) (b->data + i), 1, n - i, parm);
1774
- i += l;
1775
- b->slen = i;
1776
- if (i < n) break;
1777
- }
1778
-
1779
- b->data[i] = (unsigned char) '\0';
1780
- return BSTR_OK;
1781
- }
1782
-
1783
- /* bstring bread (bNread readPtr, void * parm)
1784
- *
1785
- * Use a finite buffer fread-like function readPtr to create a bstring
1786
- * filled with the entire contents of file-like source data in a roughly
1787
- * efficient way.
1788
- */
1789
- bstring bread (bNread readPtr, void * parm) {
1790
- int ret;
1791
- bstring buff;
1792
-
1793
- if (readPtr == NULL) return NULL;
1794
- buff = bfromcstr ("");
1795
- if (buff == NULL) return NULL;
1796
- ret = breada (buff, readPtr, parm);
1797
- if (ret < 0) {
1798
- bdestroy (buff);
1799
- return NULL;
1800
- }
1801
- return buff;
1802
- }
1803
-
1804
- /* int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator)
1805
- *
1806
- * Use an fgetc-like single character stream reading function (getcPtr) to
1807
- * obtain a sequence of characters which are concatenated to the end of the
1808
- * bstring b. The stream read is terminated by the passed in terminator
1809
- * parameter.
1810
- *
1811
- * If getcPtr returns with a negative number, or the terminator character
1812
- * (which is appended) is read, then the stream reading is halted and the
1813
- * function returns with a partial result in b. If there is an empty partial
1814
- * result, 1 is returned. If no characters are read, or there is some other
1815
- * detectable error, BSTR_ERR is returned.
1816
- */
1817
- int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) {
1818
- int c, d, e;
1819
-
1820
- if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen ||
1821
- b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR;
1822
- d = 0;
1823
- e = b->mlen - 2;
1824
-
1825
- while ((c = getcPtr (parm)) >= 0) {
1826
- if (d > e) {
1827
- b->slen = d;
1828
- if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR;
1829
- e = b->mlen - 2;
1830
- }
1831
- b->data[d] = (unsigned char) c;
1832
- d++;
1833
- if (c == terminator) break;
1834
- }
1835
-
1836
- b->data[d] = (unsigned char) '\0';
1837
- b->slen = d;
1838
-
1839
- return d == 0 && c < 0;
1840
- }
1841
-
1842
- /* int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator)
1843
- *
1844
- * Use an fgetc-like single character stream reading function (getcPtr) to
1845
- * obtain a sequence of characters which are concatenated to the end of the
1846
- * bstring b. The stream read is terminated by the passed in terminator
1847
- * parameter.
1848
- *
1849
- * If getcPtr returns with a negative number, or the terminator character
1850
- * (which is appended) is read, then the stream reading is halted and the
1851
- * function returns with a partial result concatentated to b. If there is
1852
- * an empty partial result, 1 is returned. If no characters are read, or
1853
- * there is some other detectable error, BSTR_ERR is returned.
1854
- */
1855
- int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) {
1856
- int c, d, e;
1857
-
1858
- if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen ||
1859
- b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR;
1860
- d = b->slen;
1861
- e = b->mlen - 2;
1862
-
1863
- while ((c = getcPtr (parm)) >= 0) {
1864
- if (d > e) {
1865
- b->slen = d;
1866
- if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR;
1867
- e = b->mlen - 2;
1868
- }
1869
- b->data[d] = (unsigned char) c;
1870
- d++;
1871
- if (c == terminator) break;
1872
- }
1873
-
1874
- b->data[d] = (unsigned char) '\0';
1875
- b->slen = d;
1876
-
1877
- return d == 0 && c < 0;
1878
- }
1879
-
1880
- /* bstring bgets (bNgetc getcPtr, void * parm, char terminator)
1881
- *
1882
- * Use an fgetc-like single character stream reading function (getcPtr) to
1883
- * obtain a sequence of characters which are concatenated into a bstring.
1884
- * The stream read is terminated by the passed in terminator function.
1885
- *
1886
- * If getcPtr returns with a negative number, or the terminator character
1887
- * (which is appended) is read, then the stream reading is halted and the
1888
- * result obtained thus far is returned. If no characters are read, or
1889
- * there is some other detectable error, NULL is returned.
1890
- */
1891
- bstring bgets (bNgetc getcPtr, void * parm, char terminator) {
1892
- int ret;
1893
- bstring buff;
1894
-
1895
- if (NULL == getcPtr || NULL == (buff = bfromcstr (""))) return NULL;
1896
-
1897
- ret = bgetsa (buff, getcPtr, parm, terminator);
1898
- if (ret < 0 || buff->slen <= 0) {
1899
- bdestroy (buff);
1900
- buff = NULL;
1901
- }
1902
- return buff;
1903
- }
1904
-
1905
- struct bStream {
1906
- bstring buff; /* Buffer for over-reads */
1907
- void * parm; /* The stream handle for core stream */
1908
- bNread readFnPtr; /* fread compatible fnptr for core stream */
1909
- int isEOF; /* track file's EOF state */
1910
- int maxBuffSz;
1911
- };
1912
-
1913
- /* struct bStream * bsopen (bNread readPtr, void * parm)
1914
- *
1915
- * Wrap a given open stream (described by a fread compatible function
1916
- * pointer and stream handle) into an open bStream suitable for the bstring
1917
- * library streaming functions.
1918
- */
1919
- struct bStream * bsopen (bNread readPtr, void * parm) {
1920
- struct bStream * s;
1921
-
1922
- if (readPtr == NULL) return NULL;
1923
- s = (struct bStream *) bstr__alloc (sizeof (struct bStream));
1924
- if (s == NULL) return NULL;
1925
- s->parm = parm;
1926
- s->buff = bfromcstr ("");
1927
- s->readFnPtr = readPtr;
1928
- s->maxBuffSz = BS_BUFF_SZ;
1929
- s->isEOF = 0;
1930
- return s;
1931
- }
1932
-
1933
- /* int bsbufflength (struct bStream * s, int sz)
1934
- *
1935
- * Set the length of the buffer used by the bStream. If sz is zero, the
1936
- * length is not set. This function returns with the previous length.
1937
- */
1938
- int bsbufflength (struct bStream * s, int sz) {
1939
- int oldSz;
1940
- if (s == NULL || sz < 0) return BSTR_ERR;
1941
- oldSz = s->maxBuffSz;
1942
- if (sz > 0) s->maxBuffSz = sz;
1943
- return oldSz;
1944
- }
1945
-
1946
- int bseof (const struct bStream * s) {
1947
- if (s == NULL || s->readFnPtr == NULL) return BSTR_ERR;
1948
- return s->isEOF && (s->buff->slen == 0);
1949
- }
1950
-
1951
- /* void * bsclose (struct bStream * s)
1952
- *
1953
- * Close the bStream, and return the handle to the stream that was originally
1954
- * used to open the given stream.
1955
- */
1956
- void * bsclose (struct bStream * s) {
1957
- void * parm;
1958
- if (s == NULL) return NULL;
1959
- s->readFnPtr = NULL;
1960
- if (s->buff) bdestroy (s->buff);
1961
- s->buff = NULL;
1962
- parm = s->parm;
1963
- s->parm = NULL;
1964
- s->isEOF = 1;
1965
- bstr__free (s);
1966
- return parm;
1967
- }
1968
-
1969
- /* int bsreadlna (bstring r, struct bStream * s, char terminator)
1970
- *
1971
- * Read a bstring terminated by the terminator character or the end of the
1972
- * stream from the bStream (s) and return it into the parameter r. This
1973
- * function may read additional characters from the core stream that are not
1974
- * returned, but will be retained for subsequent read operations.
1975
- */
1976
- int bsreadlna (bstring r, struct bStream * s, char terminator) {
1977
- int i, l, ret, rlo;
1978
- char * b;
1979
- struct tagbstring x;
1980
-
1981
- if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 ||
1982
- r->slen < 0 || r->mlen < r->slen) return BSTR_ERR;
1983
- l = s->buff->slen;
1984
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
1985
- b = (char *) s->buff->data;
1986
- x.data = (unsigned char *) b;
1987
-
1988
- /* First check if the current buffer holds the terminator */
1989
- b[l] = terminator; /* Set sentinel */
1990
- for (i=0; b[i] != terminator; i++) ;
1991
- if (i < l) {
1992
- x.slen = i + 1;
1993
- ret = bconcat (r, &x);
1994
- s->buff->slen = l;
1995
- if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1);
1996
- return BSTR_OK;
1997
- }
1998
-
1999
- rlo = r->slen;
2000
-
2001
- /* If not then just concatenate the entire buffer to the output */
2002
- x.slen = l;
2003
- if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR;
2004
-
2005
- /* Perform direct in-place reads into the destination to allow for
2006
- the minimum of data-copies */
2007
- for (;;) {
2008
- if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR;
2009
- b = (char *) (r->data + r->slen);
2010
- l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm);
2011
- if (l <= 0) {
2012
- r->data[r->slen] = (unsigned char) '\0';
2013
- s->buff->slen = 0;
2014
- s->isEOF = 1;
2015
- /* If nothing was read return with an error message */
2016
- return BSTR_ERR & -(r->slen == rlo);
2017
- }
2018
- b[l] = terminator; /* Set sentinel */
2019
- for (i=0; b[i] != terminator; i++) ;
2020
- if (i < l) break;
2021
- r->slen += l;
2022
- }
2023
-
2024
- /* Terminator found, push over-read back to buffer */
2025
- i++;
2026
- r->slen += i;
2027
- s->buff->slen = l - i;
2028
- bstr__memcpy (s->buff->data, b + i, l - i);
2029
- r->data[r->slen] = (unsigned char) '\0';
2030
- return BSTR_OK;
2031
- }
2032
-
2033
- /* int bsreadlnsa (bstring r, struct bStream * s, bstring term)
2034
- *
2035
- * Read a bstring terminated by any character in the term string or the end
2036
- * of the stream from the bStream (s) and return it into the parameter r.
2037
- * This function may read additional characters from the core stream that
2038
- * are not returned, but will be retained for subsequent read operations.
2039
- */
2040
- int bsreadlnsa (bstring r, struct bStream * s, const_bstring term) {
2041
- int i, l, ret, rlo;
2042
- unsigned char * b;
2043
- struct tagbstring x;
2044
- struct charField cf;
2045
-
2046
- if (s == NULL || s->buff == NULL || r == NULL || term == NULL ||
2047
- term->data == NULL || r->mlen <= 0 || r->slen < 0 ||
2048
- r->mlen < r->slen) return BSTR_ERR;
2049
- if (term->slen == 1) return bsreadlna (r, s, term->data[0]);
2050
- if (term->slen < 1 || buildCharField (&cf, term)) return BSTR_ERR;
2051
-
2052
- l = s->buff->slen;
2053
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
2054
- b = (unsigned char *) s->buff->data;
2055
- x.data = b;
2056
-
2057
- /* First check if the current buffer holds the terminator */
2058
- b[l] = term->data[0]; /* Set sentinel */
2059
- for (i=0; !testInCharField (&cf, b[i]); i++) ;
2060
- if (i < l) {
2061
- x.slen = i + 1;
2062
- ret = bconcat (r, &x);
2063
- s->buff->slen = l;
2064
- if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1);
2065
- return BSTR_OK;
2066
- }
2067
-
2068
- rlo = r->slen;
2069
-
2070
- /* If not then just concatenate the entire buffer to the output */
2071
- x.slen = l;
2072
- if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR;
2073
-
2074
- /* Perform direct in-place reads into the destination to allow for
2075
- the minimum of data-copies */
2076
- for (;;) {
2077
- if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR;
2078
- b = (unsigned char *) (r->data + r->slen);
2079
- l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm);
2080
- if (l <= 0) {
2081
- r->data[r->slen] = (unsigned char) '\0';
2082
- s->buff->slen = 0;
2083
- s->isEOF = 1;
2084
- /* If nothing was read return with an error message */
2085
- return BSTR_ERR & -(r->slen == rlo);
2086
- }
2087
-
2088
- b[l] = term->data[0]; /* Set sentinel */
2089
- for (i=0; !testInCharField (&cf, b[i]); i++) ;
2090
- if (i < l) break;
2091
- r->slen += l;
2092
- }
2093
-
2094
- /* Terminator found, push over-read back to buffer */
2095
- i++;
2096
- r->slen += i;
2097
- s->buff->slen = l - i;
2098
- bstr__memcpy (s->buff->data, b + i, l - i);
2099
- r->data[r->slen] = (unsigned char) '\0';
2100
- return BSTR_OK;
2101
- }
2102
-
2103
- /* int bsreada (bstring r, struct bStream * s, int n)
2104
- *
2105
- * Read a bstring of length n (or, if it is fewer, as many bytes as is
2106
- * remaining) from the bStream. This function may read additional
2107
- * characters from the core stream that are not returned, but will be
2108
- * retained for subsequent read operations. This function will not read
2109
- * additional characters from the core stream beyond virtual stream pointer.
2110
- */
2111
- int bsreada (bstring r, struct bStream * s, int n) {
2112
- int l, ret, orslen;
2113
- char * b;
2114
- struct tagbstring x;
2115
-
2116
- if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0
2117
- || r->slen < 0 || r->mlen < r->slen || n <= 0) return BSTR_ERR;
2118
-
2119
- n += r->slen;
2120
- if (n <= 0) return BSTR_ERR;
2121
-
2122
- l = s->buff->slen;
2123
-
2124
- orslen = r->slen;
2125
-
2126
- if (0 == l) {
2127
- if (s->isEOF) return BSTR_ERR;
2128
- if (r->mlen > n) {
2129
- l = (int) s->readFnPtr (r->data + r->slen, 1, n - r->slen, s->parm);
2130
- if (0 >= l || l > n - r->slen) {
2131
- s->isEOF = 1;
2132
- return BSTR_ERR;
2133
- }
2134
- r->slen += l;
2135
- r->data[r->slen] = (unsigned char) '\0';
2136
- return 0;
2137
- }
2138
- }
2139
-
2140
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
2141
- b = (char *) s->buff->data;
2142
- x.data = (unsigned char *) b;
2143
-
2144
- do {
2145
- if (l + r->slen >= n) {
2146
- x.slen = n - r->slen;
2147
- ret = bconcat (r, &x);
2148
- s->buff->slen = l;
2149
- if (BSTR_OK == ret) bdelete (s->buff, 0, x.slen);
2150
- return BSTR_ERR & -(r->slen == orslen);
2151
- }
2152
-
2153
- x.slen = l;
2154
- if (BSTR_OK != bconcat (r, &x)) break;
2155
-
2156
- l = n - r->slen;
2157
- if (l > s->maxBuffSz) l = s->maxBuffSz;
2158
-
2159
- l = (int) s->readFnPtr (b, 1, l, s->parm);
2160
-
2161
- } while (l > 0);
2162
- if (l < 0) l = 0;
2163
- if (l == 0) s->isEOF = 1;
2164
- s->buff->slen = l;
2165
- return BSTR_ERR & -(r->slen == orslen);
2166
- }
2167
-
2168
- /* int bsreadln (bstring r, struct bStream * s, char terminator)
2169
- *
2170
- * Read a bstring terminated by the terminator character or the end of the
2171
- * stream from the bStream (s) and return it into the parameter r. This
2172
- * function may read additional characters from the core stream that are not
2173
- * returned, but will be retained for subsequent read operations.
2174
- */
2175
- int bsreadln (bstring r, struct bStream * s, char terminator) {
2176
- if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0)
2177
- return BSTR_ERR;
2178
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
2179
- r->slen = 0;
2180
- return bsreadlna (r, s, terminator);
2181
- }
2182
-
2183
- /* int bsreadlns (bstring r, struct bStream * s, bstring term)
2184
- *
2185
- * Read a bstring terminated by any character in the term string or the end
2186
- * of the stream from the bStream (s) and return it into the parameter r.
2187
- * This function may read additional characters from the core stream that
2188
- * are not returned, but will be retained for subsequent read operations.
2189
- */
2190
- int bsreadlns (bstring r, struct bStream * s, const_bstring term) {
2191
- if (s == NULL || s->buff == NULL || r == NULL || term == NULL
2192
- || term->data == NULL || r->mlen <= 0) return BSTR_ERR;
2193
- if (term->slen == 1) return bsreadln (r, s, term->data[0]);
2194
- if (term->slen < 1) return BSTR_ERR;
2195
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
2196
- r->slen = 0;
2197
- return bsreadlnsa (r, s, term);
2198
- }
2199
-
2200
- /* int bsread (bstring r, struct bStream * s, int n)
2201
- *
2202
- * Read a bstring of length n (or, if it is fewer, as many bytes as is
2203
- * remaining) from the bStream. This function may read additional
2204
- * characters from the core stream that are not returned, but will be
2205
- * retained for subsequent read operations. This function will not read
2206
- * additional characters from the core stream beyond virtual stream pointer.
2207
- */
2208
- int bsread (bstring r, struct bStream * s, int n) {
2209
- if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0
2210
- || n <= 0) return BSTR_ERR;
2211
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
2212
- r->slen = 0;
2213
- return bsreada (r, s, n);
2214
- }
2215
-
2216
- /* int bsunread (struct bStream * s, const_bstring b)
2217
- *
2218
- * Insert a bstring into the bStream at the current position. These
2219
- * characters will be read prior to those that actually come from the core
2220
- * stream.
2221
- */
2222
- int bsunread (struct bStream * s, const_bstring b) {
2223
- if (s == NULL || s->buff == NULL) return BSTR_ERR;
2224
- return binsert (s->buff, 0, b, (unsigned char) '?');
2225
- }
2226
-
2227
- /* int bspeek (bstring r, const struct bStream * s)
2228
- *
2229
- * Return the currently buffered characters from the bStream that will be
2230
- * read prior to reads from the core stream.
2231
- */
2232
- int bspeek (bstring r, const struct bStream * s) {
2233
- if (s == NULL || s->buff == NULL) return BSTR_ERR;
2234
- return bassign (r, s->buff);
2235
- }
2236
-
2237
- /* bstring bjoin (const struct bstrList * bl, const_bstring sep);
2238
- *
2239
- * Join the entries of a bstrList into one bstring by sequentially
2240
- * concatenating them with the sep string in between. If there is an error
2241
- * NULL is returned, otherwise a bstring with the correct result is returned.
2242
- */
2243
- bstring bjoin (const struct bstrList * bl, const_bstring sep) {
2244
- bstring b;
2245
- int i, c, v;
2246
-
2247
- if (bl == NULL || bl->qty < 0) return NULL;
2248
- if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) return NULL;
2249
-
2250
- for (i = 0, c = 1; i < bl->qty; i++) {
2251
- v = bl->entry[i]->slen;
2252
- if (v < 0) return NULL; /* Invalid input */
2253
- c += v;
2254
- if (c < 0) return NULL; /* Wrap around ?? */
2255
- }
2256
-
2257
- if (sep != NULL) c += (bl->qty - 1) * sep->slen;
2258
-
2259
- b = (bstring) bstr__alloc (sizeof (struct tagbstring));
2260
- if (NULL == b) return NULL; /* Out of memory */
2261
- b->data = (unsigned char *) bstr__alloc (c);
2262
- if (b->data == NULL) {
2263
- bstr__free (b);
2264
- return NULL;
2265
- }
2266
-
2267
- b->mlen = c;
2268
- b->slen = c-1;
2269
-
2270
- for (i = 0, c = 0; i < bl->qty; i++) {
2271
- if (i > 0 && sep != NULL) {
2272
- bstr__memcpy (b->data + c, sep->data, sep->slen);
2273
- c += sep->slen;
2274
- }
2275
- v = bl->entry[i]->slen;
2276
- bstr__memcpy (b->data + c, bl->entry[i]->data, v);
2277
- c += v;
2278
- }
2279
- b->data[c] = (unsigned char) '\0';
2280
- return b;
2281
- }
2282
-
2283
- #define BSSSC_BUFF_LEN (256)
2284
-
2285
- /* int bssplitscb (struct bStream * s, const_bstring splitStr,
2286
- * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm)
2287
- *
2288
- * Iterate the set of disjoint sequential substrings read from a stream
2289
- * divided by any of the characters in splitStr. An empty splitStr causes
2290
- * the whole stream to be iterated once.
2291
- *
2292
- * Note: At the point of calling the cb function, the bStream pointer is
2293
- * pointed exactly at the position right after having read the split
2294
- * character. The cb function can act on the stream by causing the bStream
2295
- * pointer to move, and bssplitscb will continue by starting the next split
2296
- * at the position of the pointer after the return from cb.
2297
- *
2298
- * However, if the cb causes the bStream s to be destroyed then the cb must
2299
- * return with a negative value, otherwise bssplitscb will continue in an
2300
- * undefined manner.
2301
- */
2302
- int bssplitscb (struct bStream * s, const_bstring splitStr,
2303
- int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) {
2304
- struct charField chrs;
2305
- bstring buff;
2306
- int i, p, ret;
2307
-
2308
- if (cb == NULL || s == NULL || s->readFnPtr == NULL
2309
- || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR;
2310
-
2311
- if (NULL == (buff = bfromcstr (""))) return BSTR_ERR;
2312
-
2313
- if (splitStr->slen == 0) {
2314
- while (bsreada (buff, s, BSSSC_BUFF_LEN) >= 0) ;
2315
- if ((ret = cb (parm, 0, buff)) > 0)
2316
- ret = 0;
2317
- } else {
2318
- buildCharField (&chrs, splitStr);
2319
- ret = p = i = 0;
2320
- for (;;) {
2321
- if (i >= buff->slen) {
2322
- bsreada (buff, s, BSSSC_BUFF_LEN);
2323
- if (i >= buff->slen) {
2324
- if (0 < (ret = cb (parm, p, buff))) ret = 0;
2325
- break;
2326
- }
2327
- }
2328
- if (testInCharField (&chrs, buff->data[i])) {
2329
- struct tagbstring t;
2330
- unsigned char c;
2331
-
2332
- blk2tbstr (t, buff->data + i + 1, buff->slen - (i + 1));
2333
- if ((ret = bsunread (s, &t)) < 0) break;
2334
- buff->slen = i;
2335
- c = buff->data[i];
2336
- buff->data[i] = (unsigned char) '\0';
2337
- if ((ret = cb (parm, p, buff)) < 0) break;
2338
- buff->data[i] = c;
2339
- buff->slen = 0;
2340
- p += i + 1;
2341
- i = -1;
2342
- }
2343
- i++;
2344
- }
2345
- }
2346
-
2347
- bdestroy (buff);
2348
- return ret;
2349
- }
2350
-
2351
- /* int bssplitstrcb (struct bStream * s, const_bstring splitStr,
2352
- * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm)
2353
- *
2354
- * Iterate the set of disjoint sequential substrings read from a stream
2355
- * divided by the entire substring splitStr. An empty splitStr causes
2356
- * each character of the stream to be iterated.
2357
- *
2358
- * Note: At the point of calling the cb function, the bStream pointer is
2359
- * pointed exactly at the position right after having read the split
2360
- * character. The cb function can act on the stream by causing the bStream
2361
- * pointer to move, and bssplitscb will continue by starting the next split
2362
- * at the position of the pointer after the return from cb.
2363
- *
2364
- * However, if the cb causes the bStream s to be destroyed then the cb must
2365
- * return with a negative value, otherwise bssplitscb will continue in an
2366
- * undefined manner.
2367
- */
2368
- int bssplitstrcb (struct bStream * s, const_bstring splitStr,
2369
- int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) {
2370
- bstring buff;
2371
- int i, p, ret;
2372
-
2373
- if (cb == NULL || s == NULL || s->readFnPtr == NULL
2374
- || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR;
2375
-
2376
- if (splitStr->slen == 1) return bssplitscb (s, splitStr, cb, parm);
2377
-
2378
- if (NULL == (buff = bfromcstr (""))) return BSTR_ERR;
2379
-
2380
- if (splitStr->slen == 0) {
2381
- for (i=0; bsreada (buff, s, BSSSC_BUFF_LEN) >= 0; i++) {
2382
- if ((ret = cb (parm, 0, buff)) < 0) {
2383
- bdestroy (buff);
2384
- return ret;
2385
- }
2386
- buff->slen = 0;
2387
- }
2388
- return BSTR_OK;
2389
- } else {
2390
- ret = p = i = 0;
2391
- for (i=p=0;;) {
2392
- if ((ret = binstr (buff, 0, splitStr)) >= 0) {
2393
- struct tagbstring t;
2394
- blk2tbstr (t, buff->data, ret);
2395
- i = ret + splitStr->slen;
2396
- if ((ret = cb (parm, p, &t)) < 0) break;
2397
- p += i;
2398
- bdelete (buff, 0, i);
2399
- } else {
2400
- bsreada (buff, s, BSSSC_BUFF_LEN);
2401
- if (bseof (s)) {
2402
- if ((ret = cb (parm, p, buff)) > 0) ret = 0;
2403
- break;
2404
- }
2405
- }
2406
- }
2407
- }
2408
-
2409
- bdestroy (buff);
2410
- return ret;
2411
- }
2412
-
2413
- /* int bstrListCreate (void)
2414
- *
2415
- * Create a bstrList.
2416
- */
2417
- struct bstrList * bstrListCreate (void) {
2418
- struct bstrList * sl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList));
2419
- if (sl) {
2420
- sl->entry = (bstring *) bstr__alloc (1*sizeof (bstring));
2421
- if (!sl->entry) {
2422
- bstr__free (sl);
2423
- sl = NULL;
2424
- } else {
2425
- sl->qty = 0;
2426
- sl->mlen = 1;
2427
- }
2428
- }
2429
- return sl;
2430
- }
2431
-
2432
- /* int bstrListDestroy (struct bstrList * sl)
2433
- *
2434
- * Destroy a bstrList that has been created by bsplit, bsplits or bstrListCreate.
2435
- */
2436
- int bstrListDestroy (struct bstrList * sl) {
2437
- int i;
2438
- if (sl == NULL || sl->qty < 0) return BSTR_ERR;
2439
- for (i=0; i < sl->qty; i++) {
2440
- if (sl->entry[i]) {
2441
- bdestroy (sl->entry[i]);
2442
- sl->entry[i] = NULL;
2443
- }
2444
- }
2445
- sl->qty = -1;
2446
- sl->mlen = -1;
2447
- bstr__free (sl->entry);
2448
- sl->entry = NULL;
2449
- bstr__free (sl);
2450
- return BSTR_OK;
2451
- }
2452
-
2453
- /* int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
2454
- * int (* cb) (void * parm, int ofs, int len), void * parm)
2455
- *
2456
- * Iterate the set of disjoint sequential substrings over str divided by the
2457
- * character in splitChar.
2458
- *
2459
- * Note: Non-destructive modification of str from within the cb function
2460
- * while performing this split is not undefined. bsplitcb behaves in
2461
- * sequential lock step with calls to cb. I.e., after returning from a cb
2462
- * that return a non-negative integer, bsplitcb continues from the position
2463
- * 1 character after the last detected split character and it will halt
2464
- * immediately if the length of str falls below this point. However, if the
2465
- * cb function destroys str, then it *must* return with a negative value,
2466
- * otherwise bsplitcb will continue in an undefined manner.
2467
- */
2468
- int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
2469
- int (* cb) (void * parm, int ofs, int len), void * parm) {
2470
- int i, p, ret;
2471
-
2472
- if (cb == NULL || str == NULL || pos < 0 || pos > str->slen)
2473
- return BSTR_ERR;
2474
-
2475
- p = pos;
2476
- do {
2477
- for (i=p; i < str->slen; i++) {
2478
- if (str->data[i] == splitChar) break;
2479
- }
2480
- if ((ret = cb (parm, p, i - p)) < 0) return ret;
2481
- p = i + 1;
2482
- } while (p <= str->slen);
2483
- return BSTR_OK;
2484
- }
2485
-
2486
- /* int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
2487
- * int (* cb) (void * parm, int ofs, int len), void * parm)
2488
- *
2489
- * Iterate the set of disjoint sequential substrings over str divided by any
2490
- * of the characters in splitStr. An empty splitStr causes the whole str to
2491
- * be iterated once.
2492
- *
2493
- * Note: Non-destructive modification of str from within the cb function
2494
- * while performing this split is not undefined. bsplitscb behaves in
2495
- * sequential lock step with calls to cb. I.e., after returning from a cb
2496
- * that return a non-negative integer, bsplitscb continues from the position
2497
- * 1 character after the last detected split character and it will halt
2498
- * immediately if the length of str falls below this point. However, if the
2499
- * cb function destroys str, then it *must* return with a negative value,
2500
- * otherwise bsplitscb will continue in an undefined manner.
2501
- */
2502
- int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
2503
- int (* cb) (void * parm, int ofs, int len), void * parm) {
2504
- struct charField chrs;
2505
- int i, p, ret;
2506
-
2507
- if (cb == NULL || str == NULL || pos < 0 || pos > str->slen
2508
- || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR;
2509
- if (splitStr->slen == 0) {
2510
- if ((ret = cb (parm, 0, str->slen)) > 0) ret = 0;
2511
- return ret;
2512
- }
2513
-
2514
- if (splitStr->slen == 1)
2515
- return bsplitcb (str, splitStr->data[0], pos, cb, parm);
2516
-
2517
- buildCharField (&chrs, splitStr);
2518
-
2519
- p = pos;
2520
- do {
2521
- for (i=p; i < str->slen; i++) {
2522
- if (testInCharField (&chrs, str->data[i])) break;
2523
- }
2524
- if ((ret = cb (parm, p, i - p)) < 0) return ret;
2525
- p = i + 1;
2526
- } while (p <= str->slen);
2527
- return BSTR_OK;
2528
- }
2529
-
2530
- /* int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
2531
- * int (* cb) (void * parm, int ofs, int len), void * parm)
2532
- *
2533
- * Iterate the set of disjoint sequential substrings over str divided by the
2534
- * substring splitStr. An empty splitStr causes the whole str to be
2535
- * iterated once.
2536
- *
2537
- * Note: Non-destructive modification of str from within the cb function
2538
- * while performing this split is not undefined. bsplitstrcb behaves in
2539
- * sequential lock step with calls to cb. I.e., after returning from a cb
2540
- * that return a non-negative integer, bsplitscb continues from the position
2541
- * 1 character after the last detected split character and it will halt
2542
- * immediately if the length of str falls below this point. However, if the
2543
- * cb function destroys str, then it *must* return with a negative value,
2544
- * otherwise bsplitscb will continue in an undefined manner.
2545
- */
2546
- int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
2547
- int (* cb) (void * parm, int ofs, int len), void * parm) {
2548
- int i, p, ret;
2549
-
2550
- if (cb == NULL || str == NULL || pos < 0 || pos > str->slen
2551
- || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR;
2552
-
2553
- if (0 == splitStr->slen) {
2554
- for (i=pos; i < str->slen; i++) {
2555
- if ((ret = cb (parm, i, 1)) < 0) return ret;
2556
- }
2557
- return BSTR_OK;
2558
- }
2559
-
2560
- if (splitStr->slen == 1)
2561
- return bsplitcb (str, splitStr->data[0], pos, cb, parm);
2562
-
2563
- for (i=p=pos; i <= str->slen - splitStr->slen; i++) {
2564
- if (0 == bstr__memcmp (splitStr->data, str->data + i, splitStr->slen)) {
2565
- if ((ret = cb (parm, p, i - p)) < 0) return ret;
2566
- i += splitStr->slen;
2567
- p = i;
2568
- }
2569
- }
2570
- if ((ret = cb (parm, p, str->slen - p)) < 0) return ret;
2571
- return BSTR_OK;
2572
- }
2573
-
2574
- struct genBstrList {
2575
- bstring b;
2576
- struct bstrList * bl;
2577
- };
2578
-
2579
- static int bscb (void * parm, int ofs, int len) {
2580
- struct genBstrList * g = (struct genBstrList *) parm;
2581
- if (g->bl->qty >= g->bl->mlen) {
2582
- int mlen = g->bl->mlen * 2;
2583
- bstring * tbl;
2584
-
2585
- while (g->bl->qty >= mlen) {
2586
- if (mlen < g->bl->mlen) return BSTR_ERR;
2587
- mlen += mlen;
2588
- }
2589
-
2590
- tbl = (bstring *) bstr__realloc (g->bl->entry, sizeof (bstring) * mlen);
2591
- if (tbl == NULL) return BSTR_ERR;
2592
-
2593
- g->bl->entry = tbl;
2594
- g->bl->mlen = mlen;
2595
- }
2596
-
2597
- g->bl->entry[g->bl->qty] = bmidstr (g->b, ofs, len);
2598
- g->bl->qty++;
2599
- return BSTR_OK;
2600
- }
2601
-
2602
- /* struct bstrList * bsplit (const_bstring str, unsigned char splitChar)
2603
- *
2604
- * Create an array of sequential substrings from str divided by the character
2605
- * splitChar.
2606
- */
2607
- struct bstrList * bsplit (const_bstring str, unsigned char splitChar) {
2608
- struct genBstrList g;
2609
-
2610
- if (str == NULL || str->data == NULL || str->slen < 0) return NULL;
2611
-
2612
- g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList));
2613
- if (g.bl == NULL) return NULL;
2614
- g.bl->mlen = 4;
2615
- g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring));
2616
- if (NULL == g.bl->entry) {
2617
- bstr__free (g.bl);
2618
- return NULL;
2619
- }
2620
-
2621
- g.b = (bstring) str;
2622
- g.bl->qty = 0;
2623
- if (bsplitcb (str, splitChar, 0, bscb, &g) < 0) {
2624
- bstrListDestroy (g.bl);
2625
- return NULL;
2626
- }
2627
- return g.bl;
2628
- }
2629
-
2630
- /* struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr)
2631
- *
2632
- * Create an array of sequential substrings from str divided by the entire
2633
- * substring splitStr.
2634
- */
2635
- struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) {
2636
- struct genBstrList g;
2637
-
2638
- if (str == NULL || str->data == NULL || str->slen < 0) return NULL;
2639
-
2640
- g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList));
2641
- if (g.bl == NULL) return NULL;
2642
- g.bl->mlen = 4;
2643
- g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring));
2644
- if (NULL == g.bl->entry) {
2645
- bstr__free (g.bl);
2646
- return NULL;
2647
- }
2648
-
2649
- g.b = (bstring) str;
2650
- g.bl->qty = 0;
2651
- if (bsplitstrcb (str, splitStr, 0, bscb, &g) < 0) {
2652
- bstrListDestroy (g.bl);
2653
- return NULL;
2654
- }
2655
- return g.bl;
2656
- }
2657
-
2658
- /* struct bstrList * bsplits (const_bstring str, bstring splitStr)
2659
- *
2660
- * Create an array of sequential substrings from str divided by any of the
2661
- * characters in splitStr. An empty splitStr causes a single entry bstrList
2662
- * containing a copy of str to be returned.
2663
- */
2664
- struct bstrList * bsplits (const_bstring str, const_bstring splitStr) {
2665
- struct genBstrList g;
2666
-
2667
- if ( str == NULL || str->slen < 0 || str->data == NULL ||
2668
- splitStr == NULL || splitStr->slen < 0 || splitStr->data == NULL)
2669
- return NULL;
2670
-
2671
- g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList));
2672
- if (g.bl == NULL) return NULL;
2673
- g.bl->mlen = 4;
2674
- g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring));
2675
- if (NULL == g.bl->entry) {
2676
- bstr__free (g.bl);
2677
- return NULL;
2678
- }
2679
- g.b = (bstring) str;
2680
- g.bl->qty = 0;
2681
-
2682
- if (bsplitscb (str, splitStr, 0, bscb, &g) < 0) {
2683
- bstrListDestroy (g.bl);
2684
- return NULL;
2685
- }
2686
- return g.bl;
2687
- }