]>
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
)
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
)
49 s
->max
= NMH_MAX_CHARWIDTH
* (max
? max
: CHARSTRING_DEFAULT_SIZE
);
50 s
->cur
= s
->buffer
= mh_xmalloc (s
->max
);
57 charstring_copy (const charstring_t src
)
59 const size_t num
= src
->cur
- src
->buffer
;
64 s
->buffer
= mh_xmalloc (s
->max
);
65 memcpy (s
->buffer
, src
->buffer
, num
);
66 s
->cur
= s
->buffer
+ num
;
67 s
->chars
= src
->chars
;
73 * OK to call charstring_free with a NULL argument.
76 charstring_free (charstring_t s
)
85 charstring_push_back (charstring_t s
, const char c
)
87 charstring_reserve (s
, s
->cur
- s
->buffer
+ 1);
93 * num is the number of bytes in c, width is the display width
94 * occupied by the character(s).
97 charstring_push_back_chars (charstring_t s
, const char c
[], size_t num
,
102 charstring_reserve (s
, s
->cur
- s
->buffer
+ num
);
103 for (i
= 0; i
< num
; ++i
) { *s
->cur
++ = *c
++; }
108 charstring_append (charstring_t dest
, const charstring_t src
)
110 const size_t num
= src
->cur
- src
->buffer
;
113 charstring_reserve (dest
, dest
->cur
- dest
->buffer
+ num
);
114 memcpy (dest
->cur
, src
->buffer
, num
);
116 dest
->chars
+= src
->chars
;
121 charstring_append_cstring (charstring_t dest
, const char src
[])
123 const size_t num
= strlen (src
);
126 charstring_reserve (dest
, dest
->cur
- dest
->buffer
+ num
);
127 memcpy (dest
->cur
, src
, num
); /* Exclude src's trailing newline. */
134 charstring_clear (charstring_t s
)
141 * Don't store return value of charstring_buffer() and use later after
142 * intervening push_back's; use charstring_buffer_copy() instead.
145 charstring_buffer (const charstring_t s
)
147 charstring_reserve (s
, s
->cur
- s
->buffer
+ 1);
149 /* This is the only place that we null-terminate the buffer. */
151 /* Don't increment cur so that more can be appended later, and so
152 that charstring_bytes() behaves as strlen() by not counting the
159 charstring_buffer_copy (const charstring_t s
)
161 char *copy
= mh_xmalloc (s
->cur
- s
->buffer
+ 1);
163 /* Use charstring_buffer() to null terminate the buffer. */
164 memcpy (copy
, charstring_buffer (s
), s
->cur
- s
->buffer
+ 1);
170 charstring_bytes (const charstring_t s
)
172 return s
->cur
- s
->buffer
;
176 charstring_chars (const charstring_t s
)
182 charstring_last_char_len (const charstring_t s
)
185 #ifdef MULTIBYTE_SUPPORT
186 const char *sp
= charstring_buffer (s
);
187 size_t remaining
= charstring_bytes (s
);
189 if (mbtowc (NULL
, NULL
, 0)) {} /* reset shift state */
191 while (*sp
&& remaining
> 0) {
194 len
= mbtowc (&wide_char
, sp
, (size_t) MB_CUR_MAX
< remaining
195 ? (size_t) MB_CUR_MAX
198 remaining
-= max(len
, 1);
200 #else /* ! MULTIBYTE_SUPPORT */
201 if (charstring_bytes (s
) > 0) { len
= 1; }
202 #endif /* ! MULTIBYTE_SUPPORT */