]>
diplodocus.org Git - nmh/blob - sbr/charstring.c
1 /* charstring.c -- dynamically-sized char array that can report size
2 * in both characters and bytes
4 * This code is Copyright (c) 2014, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
12 #ifdef MULTIBYTE_SUPPORT
13 # define NMH_MAX_CHARWIDTH MB_CUR_MAX
15 # define NMH_MAX_CHARWIDTH 1
18 #define CHARSTRING_DEFAULT_SIZE 64
21 char *buffer
; /* the char array, not always null-terminated */
22 size_t max
; /* current size of the char array, in bytes */
23 char *cur
; /* size in bytes = cur - buffer, without trailing null */
24 size_t chars
; /* size in characters */
29 charstring_reserve (charstring_t s
, size_t need
) {
30 const size_t cur
= s
->cur
- s
->buffer
;
32 while (need
>= s
->max
- cur
) {
33 /* Insufficient capacity, so double it. */
34 s
->buffer
= mh_xrealloc (s
->buffer
, s
->max
*= 2);
35 s
->cur
= s
->buffer
+ cur
;
40 * max is in characters
43 charstring_create (size_t max
) {
47 s
->max
= NMH_MAX_CHARWIDTH
* (max
? max
: CHARSTRING_DEFAULT_SIZE
);
48 s
->cur
= s
->buffer
= mh_xmalloc (s
->max
);
55 charstring_copy (const charstring_t src
) {
56 const size_t num
= src
->cur
- src
->buffer
;
61 s
->buffer
= mh_xmalloc (s
->max
);
62 memcpy (s
->buffer
, src
->buffer
, num
);
63 s
->cur
= s
->buffer
+ num
;
64 s
->chars
= src
->chars
;
70 * OK to call charstring_free with a NULL argument.
73 charstring_free (charstring_t s
) {
81 charstring_push_back (charstring_t s
, const char c
) {
82 charstring_reserve (s
, s
->cur
- s
->buffer
+ 1);
88 * num is the number of bytes in c, width is the display width
89 * occupied by the character(s).
92 charstring_push_back_chars (charstring_t s
, const char c
[], size_t num
,
96 charstring_reserve (s
, s
->cur
- s
->buffer
+ num
);
97 for (i
= 0; i
< num
; ++i
) { *s
->cur
++ = *c
++; }
102 charstring_append (charstring_t dest
, const charstring_t src
) {
103 const size_t num
= src
->cur
- src
->buffer
;
106 charstring_reserve (dest
, dest
->cur
- dest
->buffer
+ num
);
107 memcpy (dest
->cur
, src
->buffer
, num
);
109 dest
->chars
+= src
->chars
;
114 charstring_append_cstring (charstring_t dest
, const char src
[]) {
115 const size_t num
= strlen (src
);
118 charstring_reserve (dest
, dest
->cur
- dest
->buffer
+ num
);
119 memcpy (dest
->cur
, src
, num
); /* Exclude src's trailing newline. */
126 charstring_clear (charstring_t s
) {
132 * Don't store return value of charstring_buffer() and use later after
133 * intervening push_back's; use charstring_buffer_copy() instead.
136 charstring_buffer (const charstring_t s
) {
137 charstring_reserve (s
, s
->cur
- s
->buffer
+ 1);
139 /* This is the only place that we null-terminate the buffer. */
141 /* Don't increment cur so that more can be appended later, and so
142 that charstring_bytes() behaves as strlen() by not counting the
149 charstring_buffer_copy (const charstring_t s
) {
150 char *copy
= mh_xmalloc (s
->cur
- s
->buffer
+ 1);
152 /* Use charstring_buffer() to null terminate the buffer. */
153 memcpy (copy
, charstring_buffer (s
), s
->cur
- s
->buffer
+ 1);
159 charstring_bytes (const charstring_t s
) {
160 return s
->cur
- s
->buffer
;
164 charstring_chars (const charstring_t s
) {
169 charstring_last_char_len (const charstring_t s
) {
171 #ifdef MULTIBYTE_SUPPORT
172 const char *sp
= charstring_buffer (s
);
173 size_t remaining
= charstring_bytes (s
);
175 if (mbtowc (NULL
, NULL
, 0)) {} /* reset shift state */
177 while (*sp
&& remaining
> 0) {
180 len
= mbtowc (&wide_char
, sp
, (size_t) MB_CUR_MAX
< remaining
181 ? (size_t) MB_CUR_MAX
184 remaining
-= max(len
, 1);
186 #else /* ! MULTIBYTE_SUPPORT */
187 if (charstring_bytes (s
) > 0) { len
= 1; }
188 #endif /* ! MULTIBYTE_SUPPORT */