1 /* Copyright David Abrahams 2004. Distributed under the Boost */
2 /* Software License, Version 1.0. (See accompanying */
3 /* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
9 # define assert(...) do {} while (0)
17 # define JAM_STRING_MAGIC ((char)0xcf)
18 # define JAM_STRING_MAGIC_SIZE (4)
19 static void assertInvariants (tKString
*s
) {
22 if (s
->value
== NULL
) {
24 assert(s
->capacity
== 0);
25 assert(s
->opt
[0] == 0);
28 assert(s
->size
< s
->capacity
);
29 assert((s
->capacity
<=sizeof(s
->opt
))==(s
->value
==s
->opt
));
30 //assert(strlen(s->value) == s->size);
31 assert(s
->value
[s
->size
] == 0);
32 for (f
= 0; f
< 4; ++f
) {
33 assert(s
->magic
[f
] == JAM_STRING_MAGIC
);
34 assert(s
->value
[s
->capacity
+f
] == JAM_STRING_MAGIC
);
38 # define JAM_STRING_MAGIC_SIZE (0)
39 # define assertInvariants(x) do {} while (0)
43 static void kStringEmpty (tKString
*s
) {
46 s
->capacity
= sizeof(s
->opt
);
49 memset(s
->magic
, JAM_STRING_MAGIC
, sizeof(s
->magic
));
54 void kStringNew (tKString
*s
) {
60 void kStringFree (tKString
*s
) {
62 if (s
->value
!= s
->opt
) free(s
->value
);
67 void kStringClear (tKString
*s
) {
69 s
->value
[s
->size
=0] = 0;
73 static void kStringReserveInternal (tKString
*s
, int capacity
) {
74 if (s
->value
== s
->opt
) {
75 s
->value
= (char *)malloc(capacity
+JAM_STRING_MAGIC_SIZE
);
77 if (s
->size
> 0) memcpy(s
->value
, s
->opt
, s
->size
);
78 s
->value
[s
->size
] = 0;
80 s
->value
= (char *)realloc(s
->value
, capacity
+JAM_STRING_MAGIC_SIZE
);
84 memcpy(s
->value
+capacity
, s
->magic
, JAM_STRING_MAGIC_SIZE
);
86 s
->capacity
= capacity
;
90 void kStringReserve (tKString
*s
, int capacity
) {
92 if (capacity
<= s
->capacity
) return;
93 kStringReserveInternal(s
, capacity
);
98 // make room for at leans `chars` chars
99 // `chars` should not be less than zero
100 static void kStringExpand (tKString
*s
, int chars
) {
101 int newS
= s
->size
+chars
+1;
102 int newC
= s
->capacity
;
104 if (newS
<= newC
) return; // nothing to do
105 while (newC
< newS
) newC
<<= 1;
106 kStringReserveInternal(s
, newC
);
110 void kStringAppendBytes (tKString
*s
, char const *start
, int len
) {
111 if (len
< 0) len
= start
!=NULL
?strlen(start
):0;
112 if (len
< 1) return; // nothing to do
114 kStringExpand(s
, len
);
116 memset(s
->value
+s
->size
, 32, len
);
118 memmove(s
->value
+s
->size
, start
, len
);
120 s
->value
[s
->size
+=len
] = 0;
125 void kStringAppendCStr (tKString
*s
, char const *str
) {
126 kStringAppendBytes(s
, str
, -1);
130 void kStringAppendRange (tKString
*s
, char const *start
, char const *finish
) {
131 if (finish
> start
) kStringAppendBytes(s
, start
, finish
-start
);
135 void kStringNewCStr (tKString
*s
, char const *rhs
) {
137 kStringAppendCStr(s
, rhs
);
141 void kStringTruncate (tKString
*s
, int n
) {
143 assert(n
>= 0 && n
<= s
->size
);
144 s
->value
[s
->size
=n
] = 0;
149 char kStringPopBack (tKString
*s
) {
153 if (s
->size
< 1) return 0;
154 res
= s
->value
[--s
->size
];
155 s
->value
[s
->size
] = 0;
160 void kStringPushBack (tKString
*s
, char x
) {
161 kStringAppendBytes(s
, &x
, 1);
165 char kStringLastChar (tKString
*s
) {
167 if (s
->size
< 1) return 0;
168 return s
->value
[s
->size
-1];
172 char *kStringCStr (tKString
*s
) {
178 int kStringLen (tKString
*s
) {
184 #ifdef KSTRINGS_DEBUG
185 void kStringUnitTest (void) {
188 char buffer
[sizeof(s
->opt
)*2+2];
189 int limit
= sizeof(buffer
)>254?254:sizeof(buffer
);
192 for (f
= 0; f
< limit
; ++f
) kStringPushBack(s
, (char)(f
+1));
193 for (f
= 0; f
< limit
; ++f
) {
195 assert(s
->value
[f
] == (char)(f
+1));