summaryrefslogtreecommitdiff
path: root/lib/string-desc.h
blob: e5204d4ea69bc1fdb1437386632f1233e4e80968 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/* String descriptors.
   Copyright (C) 2023 Free Software Foundation, Inc.

   This file is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as
   published by the Free Software Foundation, either version 3 of the
   License, or (at your option) any later version.

   This file is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

/* Written by Bruno Haible <bruno@clisp.org>, 2023.  */

#ifndef _STRING_DESC_H
#define _STRING_DESC_H 1

/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE,
   _GL_ATTRIBUTE_NODISCARD.  */
#if !_GL_CONFIG_H_INCLUDED
 #error "Please include config.h first."
#endif

/* Get ptrdiff_t.  */
#include <stddef.h>

/* Get FILE.  */
#include <stdio.h>

/* Get abort(), free().  */
#include <stdlib.h>

/* Get idx_t.  */
#include "idx.h"


_GL_INLINE_HEADER_BEGIN
#ifndef GL_STRING_DESC_INLINE
# define GL_STRING_DESC_INLINE _GL_INLINE
#endif

#ifdef __cplusplus
extern "C" {
#endif


/* Type describing a string that may contain NUL bytes.
   It's merely a descriptor of an array of bytes.  */
typedef struct string_desc_t string_desc_t;
struct string_desc_t
{
  /* The fields of this struct should be considered private.  */
  idx_t _nbytes;
  char *_data;
};

/* String descriptors can be passed and returned by value.

   String descriptors and NUL-terminated 'const char *'/'char *' C strings
   cannot be used interchangeably.  You will get compilation errors if you
   attempt to assign a string descriptor to a C string or vice versa.  */


/* ==== Side-effect-free operations on string descriptors ==== */

/* Return the length of the string S.  */
#if 0 /* Defined inline below.  */
extern idx_t string_desc_length (string_desc_t s);
#endif

/* Return the byte at index I of string S.
   I must be < length(S).  */
#if 0 /* Defined inline below.  */
extern char string_desc_char_at (string_desc_t s, idx_t i);
#endif

/* Return a read-only view of the bytes of S.  */
#if 0 /* Defined inline below.  */
extern const char * string_desc_data (string_desc_t s);
#endif

/* Return true if S is the empty string.  */
#if 0 /* Defined inline below.  */
extern bool string_desc_is_empty (string_desc_t s);
#endif

/* Return true if A and B are equal.  */
extern bool string_desc_equals (string_desc_t a, string_desc_t b);

/* Return true if S starts with PREFIX.  */
extern bool string_desc_startswith (string_desc_t s, string_desc_t prefix);

/* Return true if S ends with SUFFIX.  */
extern bool string_desc_endswith (string_desc_t s, string_desc_t suffix);

/* Return > 0, == 0, or < 0 if A > B, A == B, A < B.
   This uses a lexicographic ordering, where the bytes are compared as
   'unsigned char'.  */
extern int string_desc_cmp (string_desc_t a, string_desc_t b);

/* Return the index of the first occurrence of C in S,
   or -1 if there is none.  */
extern ptrdiff_t string_desc_index (string_desc_t s, char c);

/* Return the index of the last occurrence of C in S,
   or -1 if there is none.  */
extern ptrdiff_t string_desc_last_index (string_desc_t s, char c);

/* Return the index of the first occurrence of NEEDLE in HAYSTACK,
   or -1 if there is none.  */
extern ptrdiff_t string_desc_contains (string_desc_t haystack, string_desc_t needle);

/* Return an empty string.  */
extern string_desc_t string_desc_new_empty (void);

/* Return a string that represents the C string S, of length strlen (S).  */
extern string_desc_t string_desc_from_c (const char *s);

/* Return the substring of S, starting at offset START and ending at offset END.
   START must be <= END.
   The result is of length END - START.
   The result must not be freed (since its storage is part of the storage
   of S).  */
extern string_desc_t string_desc_substring (string_desc_t s, idx_t start, idx_t end);

/* Output S to the file descriptor FD.
   Return 0 if successful.
   Upon error, return -1 with errno set.  */
extern int string_desc_write (int fd, string_desc_t s);

/* Output S to the FILE stream FP.
   Return 0 if successful.
   Upon error, return -1.  */
extern int string_desc_fwrite (FILE *fp, string_desc_t s);


/* ==== Memory-allocating operations on string descriptors ==== */

/* Construct a string of length N, with uninitialized contents.
   Return 0 if successful.
   Upon error, return -1 with errno set.  */
_GL_ATTRIBUTE_NODISCARD
extern int string_desc_new (string_desc_t *resultp, idx_t n);

/* Construct and return a string of length N, at the given memory address.  */
extern string_desc_t string_desc_new_addr (idx_t n, char *addr);

/* Construct a string of length N, filled with C.
   Return 0 if successful.
   Upon error, return -1 with errno set.  */
_GL_ATTRIBUTE_NODISCARD
extern int string_desc_new_filled (string_desc_t *resultp, idx_t n, char c);

/* Construct a copy of string S.
   Return 0 if successful.
   Upon error, return -1 with errno set.  */
_GL_ATTRIBUTE_NODISCARD
extern int string_desc_copy (string_desc_t *resultp, string_desc_t s);

/* Construct the concatenation of N strings.  N must be > 0.
   Return 0 if successful.
   Upon error, return -1 with errno set.  */
_GL_ATTRIBUTE_NODISCARD
extern int string_desc_concat (string_desc_t *resultp, idx_t n, string_desc_t string1, ...);

/* Construct a copy of string S, as a NUL-terminated C string.
   Return it is successful.
   Upon error, return NULL with errno set.  */
extern char * string_desc_c (string_desc_t s) _GL_ATTRIBUTE_DEALLOC_FREE;


/* ==== Operations with side effects on string descriptors ==== */

/* Overwrite the byte at index I of string S with C.
   I must be < length(S).  */
extern void string_desc_set_char_at (string_desc_t s, idx_t i, char c);

/* Fill part of S, starting at offset START and ending at offset END,
   with copies of C.
   START must be <= END.  */
extern void string_desc_fill (string_desc_t s, idx_t start, idx_t end, char c);

/* Overwrite part of S with T, starting at offset START.
   START + length(T) must be <= length (S).  */
extern void string_desc_overwrite (string_desc_t s, idx_t start, string_desc_t t);

/* Free S.  */
extern void string_desc_free (string_desc_t s);


/* ==== Inline function definitions ==== */

GL_STRING_DESC_INLINE idx_t
string_desc_length (string_desc_t s)
{
  return s._nbytes;
}

GL_STRING_DESC_INLINE char
string_desc_char_at (string_desc_t s, idx_t i)
{
  if (!(i >= 0 && i < s._nbytes))
    /* Invalid argument.  */
    abort ();
  return s._data[i];
}

GL_STRING_DESC_INLINE const char *
string_desc_data (string_desc_t s)
{
  return s._data;
}

GL_STRING_DESC_INLINE bool
string_desc_is_empty (string_desc_t s)
{
  return s._nbytes == 0;
}


#ifdef __cplusplus
}
#endif

_GL_INLINE_HEADER_END


#endif /* _STRING_DESC_H */