]>
diplodocus.org Git - nmh/blob - sbr/charstring.c
2 * charstring -- dynamically-sized char array that can report size
3 * in both characters and bytes
5 * This code is Copyright (c) 2014, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
13 #ifdef MULTIBYTE_SUPPORT
14 # define NMH_MAX_CHARWIDTH MB_CUR_MAX
16 # define NMH_MAX_CHARWIDTH 1
19 #define CHARSTRING_DEFAULT_SIZE 64
22 char *buffer
; /* the char array, not always null-terminated */
23 size_t max
; /* current size of the char array, in bytes */
24 char *cur
; /* size in bytes = cur - buffer, without trailing null */
25 size_t chars
; /* size in characters */
30 charstring_reserve (charstring_t s
, size_t need
) {
31 const size_t cur
= s
->cur
- s
->buffer
;
33 while (need
>= s
->max
- cur
) {
34 /* Insufficient capacity, so double it. */
35 s
->buffer
= mh_xrealloc (s
->buffer
, s
->max
*= 2);
36 s
->cur
= s
->buffer
+ cur
;
41 * max is in characters
44 charstring_create (size_t max
) {
48 s
->max
= NMH_MAX_CHARWIDTH
* (max
? max
: CHARSTRING_DEFAULT_SIZE
);
49 s
->cur
= s
->buffer
= mh_xmalloc (s
->max
);
56 charstring_copy (const charstring_t src
) {
57 const size_t num
= src
->cur
- src
->buffer
;
62 s
->buffer
= mh_xmalloc (s
->max
);
63 memcpy (s
->buffer
, src
->buffer
, num
);
64 s
->cur
= s
->buffer
+ num
;
65 s
->chars
= src
->chars
;
71 * OK to call charstring_free with a NULL argument.
74 charstring_free (charstring_t s
) {
82 charstring_push_back (charstring_t s
, const char c
) {
83 charstring_reserve (s
, s
->cur
- s
->buffer
+ 1);
89 * num is the number of bytes in c, width is the display width
90 * occupied by the character(s).
93 charstring_push_back_chars (charstring_t s
, const char c
[], size_t num
,
97 charstring_reserve (s
, s
->cur
- s
->buffer
+ num
);
98 for (i
= 0; i
< num
; ++i
) { *s
->cur
++ = *c
++; }
103 charstring_append (charstring_t dest
, const charstring_t src
) {
104 const size_t num
= src
->cur
- src
->buffer
;
107 charstring_reserve (dest
, dest
->cur
- dest
->buffer
+ num
);
108 memcpy (dest
->cur
, src
->buffer
, num
);
110 dest
->chars
+= src
->chars
;
115 charstring_append_cstring (charstring_t dest
, const char src
[]) {
116 const size_t num
= strlen (src
);
119 charstring_reserve (dest
, dest
->cur
- dest
->buffer
+ num
);
120 memcpy (dest
->cur
, src
, num
); /* Exclude src's trailing newline. */
127 charstring_clear (charstring_t s
) {
133 * Don't store return value of charstring_buffer() and use later after
134 * intervening push_back's; use charstring_buffer_copy() instead.
137 charstring_buffer (const charstring_t s
) {
138 charstring_reserve (s
, s
->cur
- s
->buffer
+ 1);
140 /* This is the only place that we null-terminate the buffer. */
142 /* Don't increment cur so that more can be appended later, and so
143 that charstring_bytes() behaves as strlen() by not counting the
150 charstring_buffer_copy (const charstring_t s
) {
151 char *copy
= mh_xmalloc (s
->cur
- s
->buffer
+ 1);
153 /* Use charstring_buffer() to null terminate the buffer. */
154 memcpy (copy
, charstring_buffer (s
), s
->cur
- s
->buffer
+ 1);
160 charstring_bytes (const charstring_t s
) {
161 return s
->cur
- s
->buffer
;
165 charstring_chars (const charstring_t s
) {
170 charstring_last_char_len (const charstring_t s
) {
172 #ifdef MULTIBYTE_SUPPORT
173 const char *sp
= charstring_buffer (s
);
174 size_t remaining
= charstring_bytes (s
);
176 if (mbtowc (NULL
, NULL
, 0)) {} /* reset shift state */
178 while (*sp
&& remaining
> 0) {
181 len
= mbtowc (&wide_char
, sp
, (size_t) MB_CUR_MAX
< remaining
182 ? (size_t) MB_CUR_MAX
184 sp
+= len
> 0 ? len
: 1;
185 remaining
-= len
> 0 ? len
: 1;
187 #else /* ! MULTIBYTE_SUPPORT */
188 if (charstring_bytes (s
) > 0) { len
= 1; }
189 #endif /* ! MULTIBYTE_SUPPORT */