rmultimarkdown 6.2.2.1 → 6.4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/Makefile +2 -2
- data/ext/mmd/aho-corasick.c +12 -8
- data/ext/mmd/beamer.c +29 -0
- data/ext/mmd/critic_markup.c +100 -4
- data/ext/mmd/critic_markup.h +7 -0
- data/ext/mmd/d_string.c +502 -119
- data/ext/mmd/epub.c +2 -4
- data/ext/mmd/file.c +436 -0
- data/ext/mmd/file.h +153 -0
- data/ext/mmd/html.c +130 -37
- data/ext/mmd/include/d_string.h +20 -19
- data/ext/mmd/include/libMultiMarkdown.h +42 -27
- data/ext/mmd/include/token.h +15 -15
- data/ext/mmd/latex.c +107 -30
- data/ext/mmd/lexer.c +19 -7
- data/ext/mmd/lexer.h +2 -2
- data/ext/mmd/memoir.c +29 -0
- data/ext/mmd/mmd.c +65 -39
- data/ext/mmd/object_pool.h +4 -4
- data/ext/mmd/opendocument-content.c +95 -13
- data/ext/mmd/opendocument.c +315 -313
- data/ext/mmd/opml-lexer.c +2183 -0
- data/ext/mmd/opml-lexer.h +157 -0
- data/ext/mmd/opml-parser.c +1193 -0
- data/ext/mmd/opml-parser.h +15 -0
- data/ext/mmd/opml-reader.c +435 -0
- data/ext/mmd/opml-reader.h +111 -0
- data/ext/mmd/opml.c +511 -0
- data/ext/mmd/opml.h +115 -0
- data/ext/mmd/parser.c +2 -0
- data/ext/mmd/rng.c +1 -1
- data/ext/mmd/scanners.c +51663 -24824
- data/ext/mmd/stack.c +4 -2
- data/ext/mmd/stack.h +8 -8
- data/ext/mmd/textbundle.c +2 -4
- data/ext/mmd/token.c +24 -12
- data/ext/mmd/token_pairs.c +2 -2
- data/ext/mmd/token_pairs.h +10 -10
- data/ext/mmd/transclude.c +1 -226
- data/ext/mmd/transclude.h +0 -8
- data/ext/mmd/uuid.c +3 -3
- data/ext/mmd/version.h +3 -3
- data/ext/mmd/writer.c +99 -30
- data/ext/mmd/writer.h +11 -0
- data/lib/multi_markdown.bundle +0 -0
- data/lib/multi_markdown/version.rb +1 -1
- metadata +13 -5
- data/ext/mmd/fodt.c +0 -2288
- data/ext/mmd/fodt.h +0 -81
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1014dc60ab5f2b6f2a75676afb5277d454d85375
|
4
|
+
data.tar.gz: 95e5652fde10146a1b110674ae68065bd4967420
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 180941d10b28d4062792e8b1b448c2c3948969859f9e7f8aeab2f23f55e5d3c27eb3f7537c240fad3cc6f103431f14f6e1446ba63b7af1ed38e9d9eeff08d077
|
7
|
+
data.tar.gz: ffb6e4b40683fa51fc47673d2df9ab4716a9dc1d37f43a6670bb260abec10b9559ba56b2f3dbf5fcf08a29fcf92b0dfcc497af6098058d86fe51137b12102b2b
|
data/ext/Makefile
CHANGED
@@ -136,8 +136,8 @@ target_prefix =
|
|
136
136
|
LOCAL_LIBS =
|
137
137
|
LIBS = -lpthread -lgmp -ldl -lobjc
|
138
138
|
ORIG_SRCS = ruby_multi_markdown.c
|
139
|
-
SRCS = $(ORIG_SRCS)
|
140
|
-
OBJS = mmd/
|
139
|
+
SRCS = $(ORIG_SRCS) memoir.c object_pool.c char_lookup.c textbundle.c miniz.c char.c writer.c beamer.c latex.c stack.c zip.c opendocument.c d_string.c lexer.c token.c transclude.c aho-corasick.c mmd.c uuid.c opml-reader.c html.c epub.c file.c critic_markup.c scanners.c opml-lexer.c parser.c opendocument-content.c opml-parser.c opml.c token_pairs.c rng.c ruby_multi_markdown.c
|
140
|
+
OBJS = mmd/memoir.o mmd/object_pool.o mmd/char_lookup.o mmd/textbundle.o mmd/miniz.o mmd/char.o mmd/writer.o mmd/beamer.o mmd/latex.o mmd/stack.o mmd/zip.o mmd/opendocument.o mmd/d_string.o mmd/lexer.o mmd/token.o mmd/transclude.o mmd/aho-corasick.o mmd/mmd.o mmd/uuid.o mmd/opml-reader.o mmd/html.o mmd/epub.o mmd/file.o mmd/critic_markup.o mmd/scanners.o mmd/opml-lexer.o mmd/parser.o mmd/opendocument-content.o mmd/opml-parser.o mmd/opml.o mmd/token_pairs.o mmd/rng.o ruby_multi_markdown.o
|
141
141
|
HDRS = $(srcdir)/extconf.h
|
142
142
|
TARGET = multi_markdown
|
143
143
|
TARGET_NAME = multi_markdown
|
data/ext/mmd/aho-corasick.c
CHANGED
@@ -285,7 +285,7 @@ void ac_trie_node_prepare(trie * a, size_t s, char * buffer, unsigned short dept
|
|
285
285
|
// Prepare children
|
286
286
|
for (int i = 0; i < 256; ++i) {
|
287
287
|
if ((n->child[i] != 0) &&
|
288
|
-
|
288
|
+
(n->child[i] != s)) {
|
289
289
|
buffer[depth] = i;
|
290
290
|
|
291
291
|
ac_trie_node_prepare(a, n->child[i], buffer, depth + 1, last_match_state);
|
@@ -403,7 +403,7 @@ match * ac_trie_search(trie * a, const char * source, size_t start, size_t len)
|
|
403
403
|
}
|
404
404
|
|
405
405
|
m = match_add(m, counter - a->node[temp_state].len,
|
406
|
-
|
406
|
+
a->node[temp_state].len, a->node[temp_state].match_type);
|
407
407
|
}
|
408
408
|
|
409
409
|
// Iterate to find shorter matches
|
@@ -445,7 +445,7 @@ int match_count(match * m) {
|
|
445
445
|
|
446
446
|
void match_describe(match * m, const char * source) {
|
447
447
|
fprintf(stderr, "'%.*s'(%d) at %lu:%lu\n", (int)m->len, &source[m->start],
|
448
|
-
|
448
|
+
m->match_type, m->start, m->start + m->len);
|
449
449
|
}
|
450
450
|
|
451
451
|
|
@@ -475,14 +475,16 @@ void match_set_filter_leftmost_longest(match * header) {
|
|
475
475
|
}
|
476
476
|
|
477
477
|
while (m->next &&
|
478
|
-
|
479
|
-
|
478
|
+
m->next->start > m->start &&
|
479
|
+
m->next->start < m->start + m->len) {
|
480
480
|
// This match is "lefter" than next
|
481
|
+
#ifndef __clang_analyzer__
|
481
482
|
match_excise(m->next);
|
483
|
+
#endif
|
482
484
|
}
|
483
485
|
|
484
486
|
while (m->next &&
|
485
|
-
|
487
|
+
m->next->start < m->start) {
|
486
488
|
// Next match is "lefter" than us
|
487
489
|
n = m;
|
488
490
|
m = m->prev;
|
@@ -491,11 +493,13 @@ void match_set_filter_leftmost_longest(match * header) {
|
|
491
493
|
}
|
492
494
|
|
493
495
|
while (m->prev &&
|
494
|
-
|
495
|
-
|
496
|
+
m->prev->len &&
|
497
|
+
m->prev->start >= m->start) {
|
496
498
|
// We are "lefter" than previous
|
497
499
|
n = m->prev;
|
500
|
+
#ifndef __clang_analyzer__
|
498
501
|
match_excise(n);
|
502
|
+
#endif
|
499
503
|
}
|
500
504
|
|
501
505
|
m = m->next;
|
data/ext/mmd/beamer.c
CHANGED
@@ -55,6 +55,7 @@
|
|
55
55
|
|
56
56
|
#include "latex.h"
|
57
57
|
#include "beamer.h"
|
58
|
+
#include "parser.h"
|
58
59
|
|
59
60
|
#define print(x) d_string_append(out, x)
|
60
61
|
#define print_const(x) d_string_append_c_array(out, x, sizeof(x) - 1)
|
@@ -173,6 +174,33 @@ void mmd_export_token_beamer(DString * out, const char * source, token * t, scra
|
|
173
174
|
temp_char = get_fence_language_specifier(t->child->child, source);
|
174
175
|
|
175
176
|
if (temp_char) {
|
177
|
+
if (strncmp("{=", temp_char, 2) == 0) {
|
178
|
+
// Raw source
|
179
|
+
if (raw_filter_text_matches(temp_char, FORMAT_BEAMER)) {
|
180
|
+
switch (t->child->tail->type) {
|
181
|
+
case LINE_FENCE_BACKTICK_3:
|
182
|
+
case LINE_FENCE_BACKTICK_4:
|
183
|
+
case LINE_FENCE_BACKTICK_5:
|
184
|
+
temp_token = t->child->tail;
|
185
|
+
break;
|
186
|
+
|
187
|
+
default:
|
188
|
+
temp_token = NULL;
|
189
|
+
}
|
190
|
+
|
191
|
+
if (temp_token) {
|
192
|
+
d_string_append_c_array(out, &source[t->child->next->start], temp_token->start - t->child->next->start);
|
193
|
+
scratch->padded = 1;
|
194
|
+
} else {
|
195
|
+
d_string_append_c_array(out, &source[t->child->start + t->child->len], t->start + t->len - t->child->next->start);
|
196
|
+
scratch->padded = 0;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
free(temp_char);
|
201
|
+
break;
|
202
|
+
}
|
203
|
+
|
176
204
|
printf("\\begin{lstlisting}[language=%s]\n", temp_char);
|
177
205
|
} else {
|
178
206
|
print_const("\\begin{verbatim}\n");
|
@@ -242,6 +270,7 @@ void mmd_export_token_beamer(DString * out, const char * source, token * t, scra
|
|
242
270
|
}
|
243
271
|
|
244
272
|
mmd_export_token_tree_beamer(out, source, t->child, scratch);
|
273
|
+
trim_trailing_whitespace_d_string(out);
|
245
274
|
|
246
275
|
if (scratch->extensions & EXT_NO_LABELS) {
|
247
276
|
print_const("}");
|
data/ext/mmd/critic_markup.c
CHANGED
@@ -191,6 +191,8 @@ void accept_token(DString * d, token * t) {
|
|
191
191
|
case CM_SUB_OPEN:
|
192
192
|
case CM_ADD_OPEN:
|
193
193
|
case CM_ADD_CLOSE:
|
194
|
+
case CM_HI_OPEN:
|
195
|
+
case CM_HI_CLOSE:
|
194
196
|
if (!t->mate) {
|
195
197
|
break;
|
196
198
|
}
|
@@ -233,8 +235,9 @@ void accept_token_tree(DString * d, token * t) {
|
|
233
235
|
}
|
234
236
|
}
|
235
237
|
|
236
|
-
|
237
|
-
|
238
|
+
|
239
|
+
void mmd_critic_markup_accept_range(DString * d, size_t start, size_t len) {
|
240
|
+
token * t = critic_parse_substring(d->str, start, len);
|
238
241
|
|
239
242
|
if (t && t->child) {
|
240
243
|
accept_token_tree(d, t->child->tail);
|
@@ -244,6 +247,11 @@ void mmd_critic_markup_accept(DString * d) {
|
|
244
247
|
}
|
245
248
|
|
246
249
|
|
250
|
+
void mmd_critic_markup_accept(DString * d) {
|
251
|
+
mmd_critic_markup_accept_range(d, 0, d->currentStringLength);
|
252
|
+
}
|
253
|
+
|
254
|
+
|
247
255
|
void reject_token_tree(DString * d, token * t);
|
248
256
|
void reject_token(DString * d, token * t);
|
249
257
|
|
@@ -275,6 +283,8 @@ void reject_token(DString * d, token * t) {
|
|
275
283
|
case CM_SUB_OPEN:
|
276
284
|
case CM_DEL_OPEN:
|
277
285
|
case CM_DEL_CLOSE:
|
286
|
+
case CM_HI_OPEN:
|
287
|
+
case CM_HI_CLOSE:
|
278
288
|
if (!t->mate) {
|
279
289
|
break;
|
280
290
|
}
|
@@ -317,8 +327,9 @@ void reject_token_tree(DString * d, token * t) {
|
|
317
327
|
}
|
318
328
|
}
|
319
329
|
|
320
|
-
|
321
|
-
|
330
|
+
|
331
|
+
void mmd_critic_markup_reject_range(DString * d, size_t start, size_t len) {
|
332
|
+
token * t = critic_parse_substring(d->str, start, len);
|
322
333
|
|
323
334
|
if (t && t->child) {
|
324
335
|
reject_token_tree(d, t->child->tail);
|
@@ -328,3 +339,88 @@ void mmd_critic_markup_reject(DString * d) {
|
|
328
339
|
|
329
340
|
}
|
330
341
|
|
342
|
+
|
343
|
+
void mmd_critic_markup_reject(DString * d) {
|
344
|
+
mmd_critic_markup_reject_range(d, 0, d->currentStringLength);
|
345
|
+
}
|
346
|
+
|
347
|
+
|
348
|
+
#ifdef TEST
|
349
|
+
void Test_critic(CuTest* tc) {
|
350
|
+
#ifdef kUseObjectPool
|
351
|
+
token_pool_init();
|
352
|
+
#endif
|
353
|
+
|
354
|
+
DString * test = d_string_new("{--foo bar--}");
|
355
|
+
mmd_critic_markup_reject(test);
|
356
|
+
CuAssertStrEquals(tc, "foo bar", test->str);
|
357
|
+
|
358
|
+
d_string_erase(test, 0, -1);
|
359
|
+
d_string_append(test, "{++foo bar++}");
|
360
|
+
mmd_critic_markup_reject(test);
|
361
|
+
CuAssertStrEquals(tc, "", test->str);
|
362
|
+
|
363
|
+
|
364
|
+
d_string_erase(test, 0, -1);
|
365
|
+
d_string_append(test, "{--foo bar--}");
|
366
|
+
mmd_critic_markup_accept(test);
|
367
|
+
CuAssertStrEquals(tc, "", test->str);
|
368
|
+
|
369
|
+
d_string_erase(test, 0, -1);
|
370
|
+
d_string_append(test, "{++foo bar++}");
|
371
|
+
mmd_critic_markup_accept(test);
|
372
|
+
CuAssertStrEquals(tc, "foo bar", test->str);
|
373
|
+
|
374
|
+
d_string_erase(test, 0, -1);
|
375
|
+
d_string_append(test, "{++foo{--bat--}bar++}");
|
376
|
+
mmd_critic_markup_accept(test);
|
377
|
+
CuAssertStrEquals(tc, "foobar", test->str);
|
378
|
+
|
379
|
+
d_string_erase(test, 0, -1);
|
380
|
+
d_string_append(test, "{--foo{-- bat --}bar--}");
|
381
|
+
mmd_critic_markup_reject(test);
|
382
|
+
CuAssertStrEquals(tc, "foo bat bar", test->str);
|
383
|
+
|
384
|
+
d_string_erase(test, 0, -1);
|
385
|
+
d_string_append(test, "{--foo{++ bat ++}bar--}");
|
386
|
+
mmd_critic_markup_reject(test);
|
387
|
+
CuAssertStrEquals(tc, "foobar", test->str);
|
388
|
+
|
389
|
+
d_string_erase(test, 0, -1);
|
390
|
+
d_string_append(test, "{==foo bar==}");
|
391
|
+
mmd_critic_markup_reject(test);
|
392
|
+
CuAssertStrEquals(tc, "foo bar", test->str);
|
393
|
+
|
394
|
+
d_string_erase(test, 0, -1);
|
395
|
+
d_string_append(test, "{==foo bar==}");
|
396
|
+
mmd_critic_markup_accept(test);
|
397
|
+
CuAssertStrEquals(tc, "foo bar", test->str);
|
398
|
+
|
399
|
+
d_string_erase(test, 0, -1);
|
400
|
+
d_string_append(test, "{>>foo bar<<}");
|
401
|
+
mmd_critic_markup_reject(test);
|
402
|
+
CuAssertStrEquals(tc, "", test->str);
|
403
|
+
|
404
|
+
d_string_erase(test, 0, -1);
|
405
|
+
d_string_append(test, "{>>foo bar<<}");
|
406
|
+
mmd_critic_markup_accept(test);
|
407
|
+
CuAssertStrEquals(tc, "", test->str);
|
408
|
+
|
409
|
+
d_string_erase(test, 0, -1);
|
410
|
+
d_string_append(test, "{++foo++}{>>bar<<}");
|
411
|
+
mmd_critic_markup_accept(test);
|
412
|
+
CuAssertStrEquals(tc, "foo", test->str);
|
413
|
+
|
414
|
+
d_string_erase(test, 0, -1);
|
415
|
+
d_string_append(test, "{++foo++}{>>bar<<}");
|
416
|
+
mmd_critic_markup_reject(test);
|
417
|
+
CuAssertStrEquals(tc, "", test->str);
|
418
|
+
|
419
|
+
#ifdef kUseObjectPool
|
420
|
+
// Decrement counter and clean up token pool
|
421
|
+
token_pool_drain();
|
422
|
+
|
423
|
+
token_pool_free();
|
424
|
+
#endif
|
425
|
+
}
|
426
|
+
#endif
|
data/ext/mmd/critic_markup.h
CHANGED
@@ -60,6 +60,11 @@
|
|
60
60
|
|
61
61
|
#include "d_string.h"
|
62
62
|
|
63
|
+
#ifdef TEST
|
64
|
+
#include "CuTest.h"
|
65
|
+
#endif
|
66
|
+
|
67
|
+
|
63
68
|
enum cm_types {
|
64
69
|
CM_ADD_OPEN = 1, // Can't use type 0
|
65
70
|
CM_ADD_CLOSE,
|
@@ -88,7 +93,9 @@ enum cm_types {
|
|
88
93
|
|
89
94
|
|
90
95
|
void mmd_critic_markup_accept(DString * d);
|
96
|
+
void mmd_critic_markup_accept_range(DString * d, size_t start, size_t len);
|
91
97
|
|
92
98
|
void mmd_critic_markup_reject(DString * d);
|
99
|
+
void mmd_critic_markup_reject_range(DString * d, size_t start, size_t len);
|
93
100
|
|
94
101
|
#endif
|
data/ext/mmd/d_string.c
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
/*
|
18
18
|
|
19
19
|
Copyright © 2011 Daniel Jalkut.
|
20
|
-
Modifications by Fletcher T. Penney, Copyright © 2011-
|
20
|
+
Modifications by Fletcher T. Penney, Copyright © 2011-2018 Fletcher T. Penney.
|
21
21
|
Modifications by Dan Lowe, Copyright © 2011 Dan Lowe.
|
22
22
|
|
23
23
|
|
@@ -64,6 +64,10 @@
|
|
64
64
|
|
65
65
|
#include "d_string.h"
|
66
66
|
|
67
|
+
#ifdef TEST
|
68
|
+
#include "CuTest.h"
|
69
|
+
#endif
|
70
|
+
|
67
71
|
|
68
72
|
/*
|
69
73
|
* The following section came from:
|
@@ -145,6 +149,31 @@ DString* d_string_new(const char * startingString) {
|
|
145
149
|
}
|
146
150
|
|
147
151
|
|
152
|
+
#ifdef TEST
|
153
|
+
void Test_d_string_new(CuTest* tc) {
|
154
|
+
char * test = "foo";
|
155
|
+
|
156
|
+
DString * result = d_string_new(test);
|
157
|
+
|
158
|
+
CuAssertIntEquals(tc, 3, result->currentStringLength);
|
159
|
+
CuAssertIntEquals(tc, kStringBufferStartingSize, result->currentStringBufferSize);
|
160
|
+
CuAssertStrEquals(tc, test, result->str);
|
161
|
+
CuAssertIntEquals(tc, '\0', result->str[strlen(test)]);
|
162
|
+
|
163
|
+
d_string_free(result, true);
|
164
|
+
|
165
|
+
result = d_string_new(NULL);
|
166
|
+
|
167
|
+
CuAssertIntEquals(tc, 0, result->currentStringLength);
|
168
|
+
CuAssertIntEquals(tc, kStringBufferStartingSize, result->currentStringBufferSize);
|
169
|
+
CuAssertStrEquals(tc, "", result->str);
|
170
|
+
CuAssertIntEquals(tc, '\0', 0);
|
171
|
+
|
172
|
+
d_string_free(result, true);
|
173
|
+
}
|
174
|
+
#endif
|
175
|
+
|
176
|
+
|
148
177
|
/// Free dynamic string
|
149
178
|
char* d_string_free(DString * ripString, bool freeCharacterData) {
|
150
179
|
if (ripString == NULL) {
|
@@ -169,234 +198,588 @@ char* d_string_free(DString * ripString, bool freeCharacterData) {
|
|
169
198
|
|
170
199
|
/// Ensure that dynamic string has specified capacity
|
171
200
|
static void ensureStringBufferCanHold(DString * baseString, size_t newStringSize) {
|
172
|
-
|
201
|
+
if (baseString) {
|
202
|
+
size_t newBufferSizeNeeded = newStringSize + 1;
|
203
|
+
|
204
|
+
if (newBufferSizeNeeded > baseString->currentStringBufferSize) {
|
205
|
+
size_t newBufferSize = baseString->currentStringBufferSize;
|
206
|
+
|
207
|
+
while (newBufferSizeNeeded > newBufferSize) {
|
208
|
+
if (newBufferSize > kStringBufferMaxIncrement) {
|
209
|
+
newBufferSize += kStringBufferMaxIncrement;
|
210
|
+
} else {
|
211
|
+
newBufferSize *= kStringBufferGrowthMultiplier;
|
212
|
+
}
|
213
|
+
}
|
173
214
|
|
174
|
-
|
175
|
-
|
215
|
+
char *temp;
|
216
|
+
temp = realloc(baseString->str, newBufferSize);
|
176
217
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
218
|
+
if (temp == NULL) {
|
219
|
+
/* realloc failed */
|
220
|
+
fprintf(stderr, "Error reallocating memory for d_string. Current buffer size %lu.\n", baseString->currentStringBufferSize);
|
221
|
+
|
222
|
+
exit(1);
|
182
223
|
}
|
224
|
+
|
225
|
+
baseString->str = temp;
|
226
|
+
baseString->currentStringBufferSize = newBufferSize;
|
183
227
|
}
|
228
|
+
}
|
229
|
+
}
|
184
230
|
|
185
|
-
char *temp;
|
186
|
-
temp = realloc(baseString->str, newBufferSize);
|
187
231
|
|
188
|
-
|
189
|
-
|
190
|
-
|
232
|
+
#ifdef TEST
|
233
|
+
void Test_ensureStringBufferCanHold(CuTest* tc) {
|
234
|
+
char * test = "foo";
|
191
235
|
|
192
|
-
|
193
|
-
}
|
236
|
+
DString * result = d_string_new(test);
|
194
237
|
|
195
|
-
|
196
|
-
|
197
|
-
|
238
|
+
ensureStringBufferCanHold(result, 1024);
|
239
|
+
CuAssertIntEquals(tc, 2048, result->currentStringBufferSize);
|
240
|
+
|
241
|
+
ensureStringBufferCanHold(result, 1024);
|
242
|
+
CuAssertIntEquals(tc, 2048, result->currentStringBufferSize);
|
243
|
+
|
244
|
+
/* This becomes 0 after we add 1 for the '\0' */
|
245
|
+
ensureStringBufferCanHold(result, -1);
|
246
|
+
CuAssertIntEquals(tc, 2048, result->currentStringBufferSize);
|
247
|
+
|
248
|
+
ensureStringBufferCanHold(result, 1024 * 1024 - 1);
|
249
|
+
CuAssertIntEquals(tc, 1024 * 1024, result->currentStringBufferSize);
|
250
|
+
|
251
|
+
ensureStringBufferCanHold(result, 1024 * 1024 - 1);
|
252
|
+
CuAssertIntEquals(tc, 1024 * 1024, result->currentStringBufferSize);
|
253
|
+
|
254
|
+
ensureStringBufferCanHold(NULL, 1024);
|
255
|
+
|
256
|
+
d_string_free(result, true);
|
198
257
|
}
|
258
|
+
#endif
|
199
259
|
|
200
260
|
|
201
261
|
/// Append null-terminated string to end of dynamic string
|
202
262
|
void d_string_append(DString * baseString, const char * appendedString) {
|
203
|
-
|
263
|
+
if (baseString && appendedString) {
|
264
|
+
size_t appendedStringLength = strlen(appendedString);
|
204
265
|
|
205
|
-
|
206
|
-
|
207
|
-
|
266
|
+
if (appendedStringLength > 0) {
|
267
|
+
size_t newStringLength = baseString->currentStringLength + appendedStringLength;
|
268
|
+
ensureStringBufferCanHold(baseString, newStringLength);
|
208
269
|
|
209
|
-
|
210
|
-
|
211
|
-
|
270
|
+
/* We already know where the current string ends, so pass that as the starting address for strncat */
|
271
|
+
strncat(baseString->str + baseString->currentStringLength, appendedString, appendedStringLength);
|
272
|
+
baseString->currentStringLength = newStringLength;
|
273
|
+
}
|
212
274
|
}
|
213
275
|
}
|
214
276
|
|
215
277
|
|
278
|
+
#ifdef TEST
|
279
|
+
void Test_d_string_append(CuTest* tc) {
|
280
|
+
char * test = "foo";
|
281
|
+
|
282
|
+
DString * result = d_string_new(test);
|
283
|
+
|
284
|
+
d_string_append(result, "bar");
|
285
|
+
CuAssertStrEquals(tc, "foobar", result->str);
|
286
|
+
|
287
|
+
d_string_append(result, "");
|
288
|
+
CuAssertStrEquals(tc, "foobar", result->str);
|
289
|
+
|
290
|
+
d_string_append(result, NULL);
|
291
|
+
CuAssertStrEquals(tc, "foobar", result->str);
|
292
|
+
|
293
|
+
d_string_append(NULL, "foo");
|
294
|
+
|
295
|
+
d_string_free(result, true);
|
296
|
+
}
|
297
|
+
#endif
|
298
|
+
|
299
|
+
|
216
300
|
/// Append single character to end of dynamic string
|
217
301
|
void d_string_append_c(DString * baseString, char appendedCharacter) {
|
218
|
-
|
219
|
-
|
302
|
+
if (baseString && appendedCharacter) {
|
303
|
+
size_t newSizeNeeded = baseString->currentStringLength + 1;
|
304
|
+
ensureStringBufferCanHold(baseString, newSizeNeeded);
|
220
305
|
|
221
|
-
|
222
|
-
|
223
|
-
|
306
|
+
baseString->str[baseString->currentStringLength] = appendedCharacter;
|
307
|
+
baseString->currentStringLength++;
|
308
|
+
baseString->str[baseString->currentStringLength] = '\0';
|
309
|
+
}
|
224
310
|
}
|
225
311
|
|
226
312
|
|
313
|
+
#ifdef TEST
|
314
|
+
void Test_d_string_append_c(CuTest* tc) {
|
315
|
+
char * test = "foo";
|
316
|
+
|
317
|
+
DString * result = d_string_new(test);
|
318
|
+
|
319
|
+
d_string_append_c(result, 'z');
|
320
|
+
CuAssertStrEquals(tc, "fooz", result->str);
|
321
|
+
CuAssertIntEquals(tc, 4, result->currentStringLength);
|
322
|
+
|
323
|
+
d_string_append_c(result, 0);
|
324
|
+
CuAssertStrEquals(tc, "fooz", result->str);
|
325
|
+
CuAssertIntEquals(tc, 4, result->currentStringLength);
|
326
|
+
|
327
|
+
d_string_append_c(NULL, 'f');
|
328
|
+
|
329
|
+
d_string_free(result, true);
|
330
|
+
}
|
331
|
+
#endif
|
332
|
+
|
333
|
+
|
227
334
|
/// Append array of characters to end of dynamic string
|
228
335
|
void d_string_append_c_array(DString * baseString, const char * appendedChars, size_t bytes) {
|
229
|
-
|
230
|
-
|
336
|
+
if (baseString && appendedChars) {
|
337
|
+
if (bytes == -1) {
|
338
|
+
// This is the same as regular append
|
339
|
+
d_string_append(baseString, appendedChars);
|
340
|
+
} else {
|
341
|
+
if (appendedChars) {
|
342
|
+
size_t newSizeNeeded = baseString->currentStringLength + bytes;
|
343
|
+
ensureStringBufferCanHold(baseString, newSizeNeeded);
|
344
|
+
|
345
|
+
memcpy(baseString->str + baseString->currentStringLength, appendedChars, bytes);
|
346
|
+
|
347
|
+
baseString->currentStringLength = newSizeNeeded;
|
348
|
+
baseString->str[baseString->currentStringLength] = '\0';
|
349
|
+
}
|
350
|
+
}
|
351
|
+
}
|
352
|
+
}
|
353
|
+
|
354
|
+
|
355
|
+
#ifdef TEST
|
356
|
+
void Test_d_string_append_c_array(CuTest* tc) {
|
357
|
+
char * test = "foo";
|
358
|
+
|
359
|
+
DString * result = d_string_new(test);
|
231
360
|
|
232
|
-
|
361
|
+
d_string_append_c_array(result, "bar", 3);
|
362
|
+
CuAssertStrEquals(tc, "foobar", result->str);
|
363
|
+
CuAssertIntEquals(tc, 6, result->currentStringLength);
|
233
364
|
|
234
|
-
|
235
|
-
|
365
|
+
d_string_append_c_array(result, "baz", -1);
|
366
|
+
CuAssertStrEquals(tc, "foobarbaz", result->str);
|
367
|
+
CuAssertIntEquals(tc, 9, result->currentStringLength);
|
368
|
+
|
369
|
+
d_string_append_c_array(result, NULL, 0);
|
370
|
+
CuAssertStrEquals(tc, "foobarbaz", result->str);
|
371
|
+
CuAssertIntEquals(tc, 9, result->currentStringLength);
|
372
|
+
|
373
|
+
d_string_append_c_array(result, NULL, -1);
|
374
|
+
CuAssertStrEquals(tc, "foobarbaz", result->str);
|
375
|
+
CuAssertIntEquals(tc, 9, result->currentStringLength);
|
376
|
+
|
377
|
+
d_string_append_c_array(NULL, "foo", -1);
|
378
|
+
|
379
|
+
d_string_free(result, true);
|
236
380
|
}
|
381
|
+
#endif
|
237
382
|
|
238
383
|
|
239
384
|
/// Append to end of dynamic string using format specifier
|
240
385
|
void d_string_append_printf(DString * baseString, const char * format, ...) {
|
241
|
-
|
242
|
-
|
386
|
+
if (baseString && format) {
|
387
|
+
va_list args;
|
388
|
+
va_start(args, format);
|
389
|
+
|
390
|
+
char* formattedString = NULL;
|
391
|
+
vasprintf(&formattedString, format, args);
|
243
392
|
|
244
|
-
|
245
|
-
|
393
|
+
if (formattedString != NULL) {
|
394
|
+
d_string_append(baseString, formattedString);
|
395
|
+
free(formattedString);
|
396
|
+
}
|
246
397
|
|
247
|
-
|
248
|
-
d_string_append(baseString, formattedString);
|
249
|
-
free(formattedString);
|
398
|
+
va_end(args);
|
250
399
|
}
|
400
|
+
}
|
401
|
+
|
402
|
+
|
403
|
+
#ifdef TEST
|
404
|
+
void Test_d_string_append_printf(CuTest* tc) {
|
405
|
+
char * test = "foo";
|
406
|
+
|
407
|
+
DString * result = d_string_new(test);
|
251
408
|
|
252
|
-
|
409
|
+
d_string_append_printf(result, "%dbar%d", 5, 7);
|
410
|
+
CuAssertStrEquals(tc, "foo5bar7", result->str);
|
411
|
+
CuAssertIntEquals(tc, 8, result->currentStringLength);
|
412
|
+
|
413
|
+
d_string_append_printf(result, NULL);
|
414
|
+
CuAssertStrEquals(tc, "foo5bar7", result->str);
|
415
|
+
CuAssertIntEquals(tc, 8, result->currentStringLength);
|
416
|
+
|
417
|
+
d_string_append_printf(result, NULL, 5, 7);
|
418
|
+
CuAssertStrEquals(tc, "foo5bar7", result->str);
|
419
|
+
CuAssertIntEquals(tc, 8, result->currentStringLength);
|
420
|
+
|
421
|
+
d_string_append_printf(NULL, "foo");
|
422
|
+
|
423
|
+
d_string_free(result, true);
|
253
424
|
}
|
425
|
+
#endif
|
254
426
|
|
255
427
|
|
256
428
|
/// Prepend null-terminated string to end of dynamic string
|
257
429
|
void d_string_prepend(DString * baseString, const char * prependedString) {
|
258
|
-
|
430
|
+
if (baseString && prependedString) {
|
431
|
+
size_t prependedStringLength = strlen(prependedString);
|
259
432
|
|
260
|
-
|
261
|
-
|
262
|
-
|
433
|
+
if (prependedStringLength > 0) {
|
434
|
+
size_t newStringLength = baseString->currentStringLength + prependedStringLength;
|
435
|
+
ensureStringBufferCanHold(baseString, newStringLength);
|
263
436
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
437
|
+
memmove(baseString->str + prependedStringLength, baseString->str, baseString->currentStringLength);
|
438
|
+
strncpy(baseString->str, prependedString, prependedStringLength);
|
439
|
+
baseString->currentStringLength = newStringLength;
|
440
|
+
baseString->str[baseString->currentStringLength] = '\0';
|
441
|
+
}
|
268
442
|
}
|
269
443
|
}
|
270
444
|
|
271
445
|
|
446
|
+
#ifdef TEST
|
447
|
+
void Test_d_string_prepend(CuTest* tc) {
|
448
|
+
char * test = "foo";
|
449
|
+
|
450
|
+
DString * result = d_string_new(test);
|
451
|
+
|
452
|
+
d_string_prepend(result, "bar");
|
453
|
+
CuAssertStrEquals(tc, "barfoo", result->str);
|
454
|
+
CuAssertIntEquals(tc, 6, result->currentStringLength);
|
455
|
+
|
456
|
+
d_string_prepend(result, NULL);
|
457
|
+
CuAssertStrEquals(tc, "barfoo", result->str);
|
458
|
+
CuAssertIntEquals(tc, 6, result->currentStringLength);
|
459
|
+
|
460
|
+
d_string_prepend(NULL, "bar");
|
461
|
+
|
462
|
+
d_string_free(result, true);
|
463
|
+
}
|
464
|
+
#endif
|
465
|
+
|
466
|
+
|
272
467
|
/// Insert null-terminated string inside dynamic string
|
273
468
|
void d_string_insert(DString * baseString, size_t pos, const char * insertedString) {
|
274
|
-
|
469
|
+
if (baseString && insertedString) {
|
470
|
+
size_t insertedStringLength = strlen(insertedString);
|
471
|
+
|
472
|
+
if (insertedStringLength > 0) {
|
473
|
+
if (pos > baseString->currentStringLength) {
|
474
|
+
pos = baseString->currentStringLength;
|
475
|
+
}
|
476
|
+
|
477
|
+
size_t newStringLength = baseString->currentStringLength + insertedStringLength;
|
478
|
+
ensureStringBufferCanHold(baseString, newStringLength);
|
275
479
|
|
276
|
-
|
480
|
+
/* Shift following string to 'right' */
|
481
|
+
memmove(baseString->str + pos + insertedStringLength, baseString->str + pos, baseString->currentStringLength - pos);
|
482
|
+
strncpy(baseString->str + pos, insertedString, insertedStringLength);
|
483
|
+
baseString->currentStringLength = newStringLength;
|
484
|
+
baseString->str[baseString->currentStringLength] = '\0';
|
485
|
+
}
|
486
|
+
}
|
487
|
+
}
|
488
|
+
|
489
|
+
|
490
|
+
#ifdef TEST
|
491
|
+
void Test_d_string_insert(CuTest* tc) {
|
492
|
+
char * test = "foo";
|
493
|
+
|
494
|
+
DString * result = d_string_new(test);
|
495
|
+
|
496
|
+
d_string_insert(result, 2, "bar");
|
497
|
+
CuAssertStrEquals(tc, "fobaro", result->str);
|
498
|
+
CuAssertIntEquals(tc, 6, result->currentStringLength);
|
499
|
+
|
500
|
+
d_string_insert(result, -1, "bar");
|
501
|
+
CuAssertStrEquals(tc, "fobarobar", result->str);
|
502
|
+
CuAssertIntEquals(tc, 9, result->currentStringLength);
|
503
|
+
|
504
|
+
d_string_insert(result, -1, NULL);
|
505
|
+
CuAssertStrEquals(tc, "fobarobar", result->str);
|
506
|
+
CuAssertIntEquals(tc, 9, result->currentStringLength);
|
507
|
+
|
508
|
+
d_string_insert(NULL, 0, NULL);
|
509
|
+
|
510
|
+
d_string_free(result, true);
|
511
|
+
}
|
512
|
+
#endif
|
513
|
+
|
514
|
+
|
515
|
+
/// Insert single character inside dynamic string
|
516
|
+
void d_string_insert_c(DString * baseString, size_t pos, char insertedCharacter) {
|
517
|
+
if (baseString && insertedCharacter) {
|
277
518
|
if (pos > baseString->currentStringLength) {
|
278
519
|
pos = baseString->currentStringLength;
|
279
520
|
}
|
280
521
|
|
281
|
-
size_t
|
282
|
-
ensureStringBufferCanHold(baseString,
|
522
|
+
size_t newSizeNeeded = baseString->currentStringLength + 1;
|
523
|
+
ensureStringBufferCanHold(baseString, newSizeNeeded);
|
283
524
|
|
284
525
|
/* Shift following string to 'right' */
|
285
|
-
memmove(baseString->str + pos +
|
286
|
-
|
287
|
-
baseString->
|
526
|
+
memmove(baseString->str + pos + 1, baseString->str + pos, baseString->currentStringLength - pos);
|
527
|
+
|
528
|
+
baseString->str[pos] = insertedCharacter;
|
529
|
+
baseString->currentStringLength++;
|
288
530
|
baseString->str[baseString->currentStringLength] = '\0';
|
289
531
|
}
|
290
532
|
}
|
291
533
|
|
292
534
|
|
293
|
-
|
294
|
-
void
|
295
|
-
|
296
|
-
|
297
|
-
|
535
|
+
#ifdef TEST
|
536
|
+
void Test_d_string_insert_c(CuTest* tc) {
|
537
|
+
char * test = "foo";
|
538
|
+
|
539
|
+
DString * result = d_string_new(test);
|
540
|
+
|
541
|
+
d_string_insert_c(result, 2, 'b');
|
542
|
+
CuAssertStrEquals(tc, "fobo", result->str);
|
543
|
+
CuAssertIntEquals(tc, 4, result->currentStringLength);
|
544
|
+
|
545
|
+
d_string_insert_c(result, -1, 'z');
|
546
|
+
CuAssertStrEquals(tc, "foboz", result->str);
|
547
|
+
CuAssertIntEquals(tc, 5, result->currentStringLength);
|
298
548
|
|
299
|
-
|
300
|
-
|
549
|
+
d_string_insert_c(result, 3, 0);
|
550
|
+
CuAssertStrEquals(tc, "foboz", result->str);
|
551
|
+
CuAssertIntEquals(tc, 5, result->currentStringLength);
|
301
552
|
|
302
|
-
|
303
|
-
memmove(baseString->str + pos + 1, baseString->str + pos, baseString->currentStringLength - pos);
|
553
|
+
d_string_insert_c(NULL, 0, 0);
|
304
554
|
|
305
|
-
|
306
|
-
baseString->currentStringLength++;
|
307
|
-
baseString->str[baseString->currentStringLength] = '\0';
|
555
|
+
d_string_free(result, true);
|
308
556
|
}
|
557
|
+
#endif
|
309
558
|
|
310
559
|
|
311
560
|
/// Insert inside dynamic string using format specifier
|
312
561
|
void d_string_insert_printf(DString * baseString, size_t pos, const char * format, ...) {
|
313
|
-
|
314
|
-
|
562
|
+
if (baseString && format) {
|
563
|
+
va_list args;
|
564
|
+
va_start(args, format);
|
315
565
|
|
316
|
-
|
317
|
-
|
566
|
+
char* formattedString = NULL;
|
567
|
+
vasprintf(&formattedString, format, args);
|
318
568
|
|
319
|
-
|
320
|
-
|
321
|
-
|
569
|
+
if (formattedString != NULL) {
|
570
|
+
d_string_insert(baseString, pos, formattedString);
|
571
|
+
free(formattedString);
|
572
|
+
}
|
573
|
+
|
574
|
+
va_end(args);
|
322
575
|
}
|
576
|
+
}
|
577
|
+
|
578
|
+
|
579
|
+
#ifdef TEST
|
580
|
+
void Test_d_string_insert_printf(CuTest* tc) {
|
581
|
+
char * test = "foo";
|
323
582
|
|
324
|
-
|
583
|
+
DString * result = d_string_new(test);
|
584
|
+
|
585
|
+
d_string_insert_printf(result, 2, "%dbar%d", 5, 7);
|
586
|
+
CuAssertStrEquals(tc, "fo5bar7o", result->str);
|
587
|
+
CuAssertIntEquals(tc, 8, result->currentStringLength);
|
588
|
+
|
589
|
+
d_string_insert_printf(result, -1, "z", 5, 7);
|
590
|
+
CuAssertStrEquals(tc, "fo5bar7oz", result->str);
|
591
|
+
CuAssertIntEquals(tc, 9, result->currentStringLength);
|
592
|
+
|
593
|
+
d_string_insert_printf(NULL, 0, NULL);
|
594
|
+
|
595
|
+
d_string_free(result, true);
|
325
596
|
}
|
597
|
+
#endif
|
326
598
|
|
327
599
|
|
328
600
|
/// Erase portion of dynamic string
|
329
601
|
void d_string_erase(DString * baseString, size_t pos, size_t len) {
|
330
|
-
if (
|
331
|
-
|
332
|
-
|
602
|
+
if (baseString) {
|
603
|
+
if ((pos > baseString->currentStringLength) || (len <= 0)) {
|
604
|
+
return;
|
605
|
+
}
|
333
606
|
|
334
|
-
|
335
|
-
|
336
|
-
|
607
|
+
if ((pos + len) >= baseString->currentStringLength) {
|
608
|
+
len = -1;
|
609
|
+
}
|
337
610
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
611
|
+
if (len == -1) {
|
612
|
+
baseString->currentStringLength = pos;
|
613
|
+
} else {
|
614
|
+
memmove(baseString->str + pos, baseString->str + pos + len, baseString->currentStringLength - pos - len);
|
615
|
+
baseString->currentStringLength -= len;
|
616
|
+
}
|
617
|
+
|
618
|
+
baseString->str[baseString->currentStringLength] = '\0';
|
343
619
|
}
|
620
|
+
}
|
621
|
+
|
622
|
+
|
623
|
+
#ifdef TEST
|
624
|
+
void Test_d_string_erase(CuTest* tc) {
|
625
|
+
char * test = "foobar";
|
344
626
|
|
345
|
-
|
627
|
+
DString * result = d_string_new(test);
|
628
|
+
|
629
|
+
d_string_erase(result, 2, 1);
|
630
|
+
CuAssertStrEquals(tc, "fobar", result->str);
|
631
|
+
CuAssertIntEquals(tc, 5, result->currentStringLength);
|
632
|
+
|
633
|
+
d_string_erase(result, -1, -1);
|
634
|
+
CuAssertStrEquals(tc, "fobar", result->str);
|
635
|
+
CuAssertIntEquals(tc, 5, result->currentStringLength);
|
636
|
+
|
637
|
+
d_string_erase(result, 2, -1);
|
638
|
+
CuAssertStrEquals(tc, "fo", result->str);
|
639
|
+
CuAssertIntEquals(tc, 2, result->currentStringLength);
|
640
|
+
|
641
|
+
d_string_erase(NULL, 0, 0);
|
642
|
+
|
643
|
+
d_string_free(result, true);
|
346
644
|
}
|
645
|
+
#endif
|
646
|
+
|
347
647
|
|
348
648
|
/// Copy a portion of dynamic string
|
349
649
|
char * d_string_copy_substring(DString * d, size_t start, size_t len) {
|
350
|
-
|
650
|
+
if (d) {
|
651
|
+
char * result;
|
652
|
+
|
653
|
+
if (len == -1) {
|
654
|
+
if (start <= d->currentStringLength) {
|
655
|
+
len = d->currentStringLength - start;
|
656
|
+
} else {
|
657
|
+
len = 0;
|
658
|
+
}
|
659
|
+
}
|
351
660
|
|
352
|
-
if (len == -1) {
|
353
|
-
len = d->currentStringLength - start;
|
354
|
-
} else {
|
355
661
|
if (start + len > d->currentStringLength) {
|
356
662
|
fprintf(stderr, "d_string: Asked to copy invalid substring range.\n");
|
357
663
|
fprintf(stderr, "start: %lu len: %lu string: %lu\n", start, len,
|
358
|
-
|
664
|
+
d->currentStringLength);
|
359
665
|
return NULL;
|
360
666
|
}
|
667
|
+
|
668
|
+
result = malloc(len + 1);
|
669
|
+
strncpy(result, &d->str[start], len);
|
670
|
+
result[len] = '\0';
|
671
|
+
|
672
|
+
return result;
|
673
|
+
} else {
|
674
|
+
return NULL;
|
361
675
|
}
|
676
|
+
}
|
677
|
+
|
678
|
+
|
679
|
+
#ifdef TEST
|
680
|
+
void Test_d_string_copy_substring(CuTest* tc) {
|
681
|
+
char * test = "foobar";
|
682
|
+
|
683
|
+
DString * result = d_string_new(test);
|
684
|
+
|
685
|
+
test = d_string_copy_substring(result, 0, -1);
|
686
|
+
CuAssertStrEquals(tc, "foobar", test);
|
687
|
+
free(test);
|
362
688
|
|
363
|
-
|
364
|
-
|
365
|
-
|
689
|
+
test = d_string_copy_substring(result, 2, 3);
|
690
|
+
CuAssertStrEquals(tc, "oba", test);
|
691
|
+
free(test);
|
366
692
|
|
367
|
-
|
693
|
+
test = d_string_copy_substring(result, 8, 2);
|
694
|
+
CuAssertStrEquals(tc, NULL, test);
|
695
|
+
free(test);
|
696
|
+
|
697
|
+
test = d_string_copy_substring(result, -1, -1);
|
698
|
+
CuAssertStrEquals(tc, NULL, test);
|
699
|
+
free(test);
|
700
|
+
|
701
|
+
test = d_string_copy_substring(NULL, -1, -1);
|
702
|
+
CuAssertStrEquals(tc, NULL, test);
|
703
|
+
|
704
|
+
d_string_free(result, true);
|
368
705
|
}
|
706
|
+
#endif
|
369
707
|
|
370
708
|
|
371
709
|
/// Replace occurences of "original" with "replace" inside the specified range
|
372
710
|
/// Returns the change in overall length
|
373
711
|
long d_string_replace_text_in_range(DString * d, size_t pos, size_t len, const char * original, const char * replace) {
|
374
|
-
|
712
|
+
if (d && original && replace) {
|
713
|
+
long delta = 0; // Overall change in length
|
714
|
+
|
715
|
+
long len_o = strlen(original);
|
716
|
+
long len_r = strlen(replace);
|
717
|
+
long change = len_r - len_o; // Change in length for each replacement
|
718
|
+
|
719
|
+
size_t stop;
|
720
|
+
|
721
|
+
if (len == -1) {
|
722
|
+
stop = d->currentStringLength;
|
723
|
+
} else {
|
724
|
+
stop = pos + len;
|
725
|
+
|
726
|
+
if (stop > d->currentStringLength) {
|
727
|
+
stop = d->currentStringLength;
|
728
|
+
}
|
729
|
+
}
|
730
|
+
|
731
|
+
char * match = strstr(&(d->str[pos]), original);
|
375
732
|
|
376
|
-
|
377
|
-
|
378
|
-
|
733
|
+
while (match && (match - d->str < stop)) {
|
734
|
+
pos = match - d->str;
|
735
|
+
d_string_erase(d, match - d->str, len_o);
|
736
|
+
d_string_insert(d, match - d->str, replace);
|
379
737
|
|
380
|
-
|
738
|
+
delta += change;
|
739
|
+
stop += change;
|
740
|
+
match = strstr(d->str + pos + len_r, original);
|
741
|
+
}
|
381
742
|
|
382
|
-
|
383
|
-
stop = d->currentStringLength;
|
743
|
+
return delta;
|
384
744
|
} else {
|
385
|
-
|
745
|
+
return 0;
|
386
746
|
}
|
747
|
+
}
|
387
748
|
|
388
|
-
char * match = strstr(&(d->str[pos]), original);
|
389
749
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
750
|
+
#ifdef TEST
|
751
|
+
void Test_d_string_replace_text_in_range(CuTest* tc) {
|
752
|
+
char * test = "foobarfoobarfoo";
|
753
|
+
long delta = 0;
|
394
754
|
|
395
|
-
|
396
|
-
stop += change;
|
397
|
-
match = strstr(d->str + pos + len_r, original);
|
398
|
-
}
|
755
|
+
DString * result = d_string_new(test);
|
399
756
|
|
400
|
-
|
401
|
-
|
757
|
+
delta = d_string_replace_text_in_range(result, 100, 3, "foo", "zapz");
|
758
|
+
CuAssertIntEquals(tc, 15, result->currentStringLength);
|
759
|
+
CuAssertStrEquals(tc, "foobarfoobarfoo", result->str);
|
760
|
+
CuAssertIntEquals(tc, delta, 0);
|
761
|
+
|
762
|
+
delta = d_string_replace_text_in_range(result, 0, 3, "foo", "zapz");
|
763
|
+
CuAssertIntEquals(tc, 16, result->currentStringLength);
|
764
|
+
CuAssertStrEquals(tc, "zapzbarfoobarfoo", result->str);
|
765
|
+
CuAssertIntEquals(tc, delta, 1);
|
402
766
|
|
767
|
+
delta = d_string_replace_text_in_range(result, 0, 100, "foo", "zapz");
|
768
|
+
CuAssertIntEquals(tc, 18, result->currentStringLength);
|
769
|
+
CuAssertStrEquals(tc, "zapzbarzapzbarzapz", result->str);
|
770
|
+
CuAssertIntEquals(tc, delta, 2);
|
771
|
+
|
772
|
+
delta = d_string_replace_text_in_range(result, 0, -1, NULL, "zap");
|
773
|
+
CuAssertIntEquals(tc, 18, result->currentStringLength);
|
774
|
+
CuAssertStrEquals(tc, "zapzbarzapzbarzapz", result->str);
|
775
|
+
CuAssertIntEquals(tc, delta, 0);
|
776
|
+
|
777
|
+
d_string_replace_text_in_range(result, 0, -1, "foo", NULL);
|
778
|
+
CuAssertIntEquals(tc, 18, result->currentStringLength);
|
779
|
+
CuAssertStrEquals(tc, "zapzbarzapzbarzapz", result->str);
|
780
|
+
|
781
|
+
d_string_replace_text_in_range(NULL, 0, -1, "foo", NULL);
|
782
|
+
|
783
|
+
d_string_free(result, true);
|
784
|
+
}
|
785
|
+
#endif
|