]>
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
) {
45 charstring_t s
= mh_xmalloc (sizeof *s
);
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
;
57 charstring_t s
= mh_xmalloc (sizeof *s
);
60 s
->buffer
= mh_xmalloc (s
->max
);
61 memcpy (s
->buffer
, src
->buffer
, num
);
62 s
->cur
= s
->buffer
+ num
;
63 s
->chars
= src
->chars
;
69 * OK to call charstring_free with a NULL argument.
72 charstring_free (charstring_t s
) {
80 charstring_push_back (charstring_t s
, const char c
) {
81 charstring_reserve (s
, s
->cur
- s
->buffer
+ 1);
87 * num is the number of bytes in c, width is the display width
88 * occupied by the character(s).
91 charstring_push_back_chars (charstring_t s
, const char c
[], size_t num
,
95 charstring_reserve (s
, s
->cur
- s
->buffer
+ num
);
96 for (i
= 0; i
< num
; ++i
) { *s
->cur
++ = *c
++; }
101 charstring_append (charstring_t dest
, const charstring_t src
) {
102 const size_t num
= src
->cur
- src
->buffer
;
105 charstring_reserve (dest
, num
+ (dest
->cur
- dest
->buffer
));
106 memcpy (dest
->cur
, src
->buffer
, num
);
108 dest
->chars
+= src
->chars
;
113 charstring_clear (charstring_t s
) {
119 * Don't store return value of charstring_buffer() and use later after
120 * intervening push_back's; use charstring_buffer_copy() instead.
123 charstring_buffer (const charstring_t s
) {
124 charstring_reserve (s
, s
->cur
- s
->buffer
+ 1);
126 /* This is the only place that we null-terminate the buffer. */
128 /* Don't increment cur so that more can be appended later, and so
129 that charstring_bytes() behaves as strlen() by not counting the
136 charstring_buffer_copy (const charstring_t s
) {
137 char *copy
= strdup (charstring_buffer (s
));
142 advise ("strdup", "unable to copy charstring buffer");
148 charstring_bytes (const charstring_t s
) {
149 return s
->cur
- s
->buffer
;
153 charstring_chars (const charstring_t s
) {
158 charstring_last_char_len (const charstring_t s
) {
160 #ifdef MULTIBYTE_SUPPORT
161 const char *sp
= charstring_buffer (s
);
162 size_t remaining
= charstring_bytes (s
);
164 (void) mbtowc (NULL
, NULL
, 0); /* reset shift state */
166 while (*sp
&& remaining
> 0) {
169 len
= mbtowc (&wide_char
, sp
, (size_t) MB_CUR_MAX
< remaining
170 ? (size_t) MB_CUR_MAX
172 sp
+= len
> 0 ? len
: 1;
173 remaining
-= len
> 0 ? len
: 1;
175 #else /* ! MULTIBYTE_SUPPORT */
176 if (charstring_bytes (s
) > 0) { len
= 1; }
177 #endif /* ! MULTIBYTE_SUPPORT */