fixed pkg-config rule
[k8jam.git] / src / kstrings.c
blobe214256f8a07c7424d7a20002ebe7241853980f9
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) */
4 #include "kstrings.h"
6 #ifdef KSTRINGS_DEBUG
7 # include <assert.h>
8 #else
9 # define assert(...) do {} while (0)
10 #endif
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
16 #ifdef KSTRINGS_DEBUG
17 # define JAM_STRING_MAGIC ((char)0xcf)
18 # define JAM_STRING_MAGIC_SIZE (4)
19 static void assertInvariants (tKString *s) {
20 int f;
22 if (s->value == NULL) {
23 assert(s->size == 0);
24 assert(s->capacity == 0);
25 assert(s->opt[0] == 0);
26 return;
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);
37 #else
38 # define JAM_STRING_MAGIC_SIZE (0)
39 # define assertInvariants(x) do {} while (0)
40 #endif
43 static void kStringEmpty (tKString *s) {
44 s->value = s->opt;
45 s->size = 0;
46 s->capacity = sizeof(s->opt);
47 s->opt[0] = 0;
48 #ifdef KSTRINGS_DEBUG
49 memset(s->magic, JAM_STRING_MAGIC, sizeof(s->magic));
50 #endif
54 void kStringNew (tKString *s) {
55 kStringEmpty(s);
56 assertInvariants(s);
60 void kStringFree (tKString *s) {
61 assertInvariants(s);
62 if (s->value != s->opt) free(s->value);
63 kStringEmpty(s);
67 void kStringClear (tKString *s) {
68 assertInvariants(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);
76 assert(s->value);
77 if (s->size > 0) memcpy(s->value, s->opt, s->size);
78 s->value[s->size] = 0;
79 } else {
80 s->value = (char *)realloc(s->value, capacity+JAM_STRING_MAGIC_SIZE);
81 assert(s->value);
83 #ifdef KSTRINGS_DEBUG
84 memcpy(s->value+capacity, s->magic, JAM_STRING_MAGIC_SIZE);
85 #endif
86 s->capacity = capacity;
90 void kStringReserve (tKString *s, int capacity) {
91 assertInvariants(s);
92 if (capacity <= s->capacity) return;
93 kStringReserveInternal(s, capacity);
94 assertInvariants(s);
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
113 assertInvariants(s);
114 kStringExpand(s, len);
115 if (start == NULL) {
116 memset(s->value+s->size, 32, len);
117 } else {
118 memmove(s->value+s->size, start, len);
120 s->value[s->size+=len] = 0;
121 assertInvariants(s);
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) {
136 kStringNew(s);
137 kStringAppendCStr(s, rhs);
141 void kStringTruncate (tKString *s, int n) {
142 assertInvariants(s);
143 assert(n >= 0 && n <= s->size);
144 s->value[s->size=n] = 0;
145 assertInvariants(s);
149 char kStringPopBack (tKString *s) {
150 char res;
152 assertInvariants(s);
153 if (s->size < 1) return 0;
154 res = s->value[--s->size];
155 s->value[s->size] = 0;
156 return res;
160 void kStringPushBack (tKString *s, char x) {
161 kStringAppendBytes(s, &x, 1);
165 char kStringLastChar (tKString *s) {
166 assertInvariants(s);
167 if (s->size < 1) return 0;
168 return s->value[s->size-1];
172 char *kStringCStr (tKString *s) {
173 assertInvariants(s);
174 return s->value;
178 int kStringLen (tKString *s) {
179 assertInvariants(s);
180 return s->size;
184 #ifdef KSTRINGS_DEBUG
185 void kStringUnitTest (void) {
186 tKString s[1];
187 int f;
188 char buffer[sizeof(s->opt)*2+2];
189 int limit = sizeof(buffer)>254?254:sizeof(buffer);
191 kStringNew(s);
192 for (f = 0; f < limit; ++f) kStringPushBack(s, (char)(f+1));
193 for (f = 0; f < limit; ++f) {
194 assert(f < s->size);
195 assert(s->value[f] == (char)(f+1));
197 kStringFree(s);
199 #endif