2 Copyright (C) 2023-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation, either version 3 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2023. */
23 #define GL_STRING_DESC_INLINE _GL_EXTERN_INLINE
25 /* Specification and inline definitions. */
26 #include "string-desc.h"
33 #include "full-write.h"
36 /* ==== Side-effect-free operations on string descriptors ==== */
38 /* Return true if A and B are equal. */
40 string_desc_equals (string_desc_t a
, string_desc_t b
)
42 return (a
._nbytes
== b
._nbytes
43 && (a
._nbytes
== 0 || memcmp (a
._data
, b
._data
, a
._nbytes
) == 0));
47 string_desc_startswith (string_desc_t s
, string_desc_t prefix
)
49 return (s
._nbytes
>= prefix
._nbytes
50 && (prefix
._nbytes
== 0
51 || memcmp (s
._data
, prefix
._data
, prefix
._nbytes
) == 0));
55 string_desc_endswith (string_desc_t s
, string_desc_t suffix
)
57 return (s
._nbytes
>= suffix
._nbytes
58 && (suffix
._nbytes
== 0
59 || memcmp (s
._data
+ (s
._nbytes
- suffix
._nbytes
), suffix
._data
,
60 suffix
._nbytes
) == 0));
64 string_desc_cmp (string_desc_t a
, string_desc_t b
)
66 if (a
._nbytes
> b
._nbytes
)
70 return (memcmp (a
._data
, b
._data
, b
._nbytes
) < 0 ? -1 : 1);
72 else if (a
._nbytes
< b
._nbytes
)
76 return (memcmp (a
._data
, b
._data
, a
._nbytes
) > 0 ? 1 : -1);
78 else /* a._nbytes == b._nbytes */
82 return memcmp (a
._data
, b
._data
, a
._nbytes
);
87 string_desc_index (string_desc_t s
, char c
)
91 void *found
= memchr (s
._data
, (unsigned char) c
, s
._nbytes
);
93 return (char *) found
- s
._data
;
99 string_desc_last_index (string_desc_t s
, char c
)
103 void *found
= memrchr (s
._data
, (unsigned char) c
, s
._nbytes
);
105 return (char *) found
- s
._data
;
111 string_desc_new_empty (void)
113 string_desc_t result
;
123 string_desc_from_c (const char *s
)
125 string_desc_t result
;
127 result
._nbytes
= strlen (s
);
128 result
._data
= (char *) s
;
134 string_desc_substring (string_desc_t s
, idx_t start
, idx_t end
)
136 string_desc_t result
;
138 if (!(start
>= 0 && start
<= end
))
139 /* Invalid arguments. */
142 result
._nbytes
= end
- start
;
143 result
._data
= s
._data
+ start
;
149 string_desc_write (int fd
, string_desc_t s
)
152 if (full_write (fd
, s
._data
, s
._nbytes
) != s
._nbytes
)
153 /* errno is set here. */
159 string_desc_fwrite (FILE *fp
, string_desc_t s
)
162 if (fwrite (s
._data
, 1, s
._nbytes
, fp
) != s
._nbytes
)
168 /* ==== Memory-allocating operations on string descriptors ==== */
171 string_desc_new (string_desc_t
*resultp
, idx_t n
)
173 string_desc_t result
;
176 /* Invalid argument. */
184 result
._data
= (char *) imalloc (n
);
185 if (result
._data
== NULL
)
186 /* errno is set here. */
195 string_desc_new_addr (idx_t n
, char *addr
)
197 string_desc_t result
;
209 string_desc_new_filled (string_desc_t
*resultp
, idx_t n
, char c
)
211 string_desc_t result
;
218 result
._data
= (char *) imalloc (n
);
219 if (result
._data
== NULL
)
220 /* errno is set here. */
222 memset (result
._data
, (unsigned char) c
, n
);
230 string_desc_copy (string_desc_t
*resultp
, string_desc_t s
)
232 string_desc_t result
;
240 result
._data
= (char *) imalloc (n
);
241 if (result
._data
== NULL
)
242 /* errno is set here. */
244 memcpy (result
._data
, s
._data
, n
);
252 string_desc_concat (string_desc_t
*resultp
, idx_t n
, string_desc_t string1
, ...)
255 /* Invalid argument. */
259 total
+= string1
._nbytes
;
262 va_list other_strings
;
265 va_start (other_strings
, string1
);
266 for (i
= n
- 1; i
> 0; i
--)
268 string_desc_t arg
= va_arg (other_strings
, string_desc_t
);
269 total
+= arg
._nbytes
;
271 va_end (other_strings
);
274 char *combined
= (char *) imalloc (total
);
275 if (combined
== NULL
)
276 /* errno is set here. */
279 memcpy (combined
, string1
._data
, string1
._nbytes
);
280 pos
+= string1
._nbytes
;
283 va_list other_strings
;
286 va_start (other_strings
, string1
);
287 for (i
= n
- 1; i
> 0; i
--)
289 string_desc_t arg
= va_arg (other_strings
, string_desc_t
);
291 memcpy (combined
+ pos
, arg
._data
, arg
._nbytes
);
294 va_end (other_strings
);
297 string_desc_t result
;
298 result
._nbytes
= total
;
299 result
._data
= combined
;
306 string_desc_c (string_desc_t s
)
309 char *result
= (char *) imalloc (n
+ 1);
311 /* errno is set here. */
314 memcpy (result
, s
._data
, n
);
321 /* ==== Operations with side effects on string descriptors ==== */
324 string_desc_set_char_at (string_desc_t s
, idx_t i
, char c
)
326 if (!(i
>= 0 && i
< s
._nbytes
))
327 /* Invalid argument. */
333 string_desc_fill (string_desc_t s
, idx_t start
, idx_t end
, char c
)
335 if (!(start
>= 0 && start
<= end
))
336 /* Invalid arguments. */
340 memset (s
._data
+ start
, (unsigned char) c
, end
- start
);
344 string_desc_overwrite (string_desc_t s
, idx_t start
, string_desc_t t
)
346 if (!(start
>= 0 && start
+ t
._nbytes
<= s
._nbytes
))
347 /* Invalid arguments. */
351 memcpy (s
._data
+ start
, t
._data
, t
._nbytes
);
355 string_desc_free (string_desc_t s
)