Raw File
1 /*============================================================================
2 epub2txt v2
3 string.c
4 Copyright (c)2020 Kevin Boone, GPL v3.0
5 ============================================================================*/
6
7 #define _GNU_SOURCE
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <memory.h>
11
12 #if !defined(__MACH__)
13 #include <malloc.h>
14 #endif
15
16 #include <pthread.h>
17 #include <stdint.h>
18 #include <stdarg.h>
19 #include <errno.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <ctype.h>
25 #include "custom_string.h"
26 #include "defs.h"
27 #include "log.h"
28
29 struct _String
30 {
31 char *str;
32 };
33
34
35 /*==========================================================================
36 string_create_empty
37 *==========================================================================*/
38 String *string_create_empty (void)
39 {
40 return string_create ("");
41 }
42
43
44 /*==========================================================================
45 string_create
46 *==========================================================================*/
47 String *string_create (const char *s)
48 {
49 String *self = malloc (sizeof (String));
50 self->str = strdup (s);
51 return self;
52 }
53
54
55 /*==========================================================================
56 string_destroy
57 *==========================================================================*/
58 void string_destroy (String *self)
59 {
60 if (self)
61 {
62 if (self->str) free (self->str);
63 free (self);
64 }
65 }
66
67
68 /*==========================================================================
69 string_cstr
70 *==========================================================================*/
71 const char *string_cstr (const String *self)
72 {
73 return self->str;
74 }
75
76
77 /*==========================================================================
78 string_cstr_safe
79 *==========================================================================*/
80 const char *string_cstr_safe (const String *self)
81 {
82 if (self)
83 {
84 if (self->str)
85 return self->str;
86 else
87 return "";
88 }
89 else
90 return "";
91 }
92
93
94 /*==========================================================================
95 string_append
96 *==========================================================================*/
97 void string_append (String *self, const char *s)
98 {
99 if (!s) return;
100 if (self->str == NULL) self->str = strdup ("");
101 int newlen = strlen (self->str) + strlen (s) + 2;
102 self->str = realloc (self->str, newlen);
103 strcat (self->str, s);
104 }
105
106
107 /*==========================================================================
108 string_prepend
109 *==========================================================================*/
110 void string_prepend (String *self, const char *s)
111 {
112 if (!s) return;
113 if (self->str == NULL) self->str = strdup ("");
114 int newlen = strlen (self->str) + strlen (s) + 2;
115 char *temp = strdup (self->str);
116 free (self->str);
117 self->str = malloc (newlen);
118 strcpy (self->str, s);
119 strcat (self->str, temp);
120 free (temp);
121 }
122
123
124 /*==========================================================================
125 string_append_printf
126 *==========================================================================*/
127 void string_append_printf (String *self, const char *fmt,...)
128 {
129 if (self->str == NULL) self->str = strdup ("");
130 va_list ap;
131 va_start (ap, fmt);
132 char *s;
133 vasprintf (&s, fmt, ap);
134 string_append (self, s);
135 free (s);
136 va_end (ap);
137 }
138
139
140 /*==========================================================================
141 string_length
142 *==========================================================================*/
143 int string_length (const String *self)
144 {
145 if (self == NULL) return 0;
146 if (self->str == NULL) return 0;
147 return strlen (self->str);
148 }
149
150
151 /*==========================================================================
152 string_clone
153 *==========================================================================*/
154 String *string_clone (const String *self)
155 {
156 if (!self) return NULL;
157 if (!self->str) return string_create_empty();
158 return string_create (string_cstr (self));
159 }
160
161
162 /*==========================================================================
163 string_find
164 *==========================================================================*/
165 int string_find (const String *self, const char *search)
166 {
167 if (!self) return -1;
168 if (!self->str) return -1;
169 const char *p = strstr (self->str, search);
170 if (p)
171 return p - self->str;
172 else
173 return -1;
174 }
175
176
177 /*==========================================================================
178 string_delete
179 *==========================================================================*/
180 void string_delete (String *self, const int pos, const int len)
181 {
182 char *str = self->str;
183 if (pos + len > strlen (str))
184 string_delete (self, pos, strlen(str) - len);
185 else
186 {
187 char *buff = malloc (strlen (str) - len + 2);
188 strncpy (buff, str, pos);
189 strcpy (buff + pos, str + pos + len);
190 free (self->str);
191 self->str = buff;
192 }
193 }
194
195
196 /*==========================================================================
197 string_insert
198 *==========================================================================*/
199 void string_insert (String *self, const int pos,
200 const char *replace)
201 {
202 char *buff = malloc (strlen (self->str) + strlen (replace) + 2);
203 char *str = self->str;
204 strncpy (buff, str, pos);
205 buff[pos] = 0;
206 strcat (buff, replace);
207 strcat (buff, str + pos);
208 free (self->str);
209 self->str = buff;
210 }
211
212
213
214 /*==========================================================================
215 string_substitute_all
216 *==========================================================================*/
217 String *string_substitute_all (const String *self,
218 const char *search, const char *replace)
219 {
220 String *working = string_clone (self);
221 BOOL cont = TRUE;
222 while (cont)
223 {
224 int i = string_find (working, search);
225 if (i >= 0)
226 {
227 string_delete (working, i, strlen (search));
228 string_insert (working, i, replace);
229 }
230 else
231 cont = FALSE;
232 }
233 return working;
234 }
235
236
237 /*==========================================================================
238 string_create_from_utf8_file
239 *==========================================================================*/
240 BOOL string_create_from_utf8_file (const char *filename,
241 String **result, char **error)
242 {
243 String *self = NULL;
244 BOOL ok = FALSE;
245 int f = open (filename, O_RDONLY);
246 if (f > 0)
247 {
248 self = malloc (sizeof (String));
249 struct stat sb;
250 fstat (f, &sb);
251 int64_t size = sb.st_size;
252 char *buff = malloc (size + 2);
253 self->str = buff;
254
255 // Read the first three characters, to check for a UTF-8 byte-order-mark
256 read (f, buff, 3);
257 if (buff[0] == (char)0xEF && buff[1] == (char)0xBB && buff[2] == (char)0xBF)
258 {
259 read (f, buff, size - 3);
260 self->str[size - 3] = 0;
261 }
262 else
263 {
264 read (f, buff + 3, size - 3);
265 self->str[size] = 0;
266 }
267
268 *result = self;
269 ok = TRUE;
270 }
271 else
272 {
273 asprintf (error, "Can't open file '%s' for reading: %s",
274 filename, strerror (errno));
275 ok = FALSE;
276 }
277
278 return ok;
279 }
280
281
282 /*==========================================================================
283 string_encode_url
284 *==========================================================================*/
285 static char to_hex(char code)
286 {
287 static char hex[] = "0123456789abcdef";
288 return hex[code & 15];
289 }
290
291
292 String *string_encode_url (const char *str)
293 {
294 if (!str) return string_create_empty();;
295 const char *pstr = str;
296 char *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
297 while (*pstr)
298 {
299 if (isalnum(*pstr) || *pstr == '-' || *pstr == '_'
300 || *pstr == '.' || *pstr == '~')
301 *pbuf++ = *pstr;
302 else if (*pstr == ' ')
303 *pbuf++ = '+';
304 else
305 *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4),
306 *pbuf++ = to_hex(*pstr & 15);
307 pstr++;
308 }
309 *pbuf = '\0';
310 String *result = string_create (buf);
311 free (buf);
312 return (result);
313 }
314
315
316 /*==========================================================================
317 string_append_byte
318 *==========================================================================*/
319 void string_append_byte (String *self, const BYTE byte)
320 {
321 char buff[2];
322 buff[0] = byte;
323 buff[1] = 0;
324 string_append (self, buff);
325 }
326
327
328 /*==========================================================================
329 string_append_c
330 *==========================================================================*/
331 void string_append_c (String *self, const uint32_t ch)
332 {
333 if (ch < 0x80)
334 {
335 string_append_byte (self, (BYTE)ch);
336 }
337 else if (ch < 0x0800)
338 {
339 string_append_byte (self, (BYTE)((ch >> 6) | 0xC0));
340 string_append_byte (self, (BYTE)((ch & 0x3F) | 0x80));
341 }
342 else if (ch < 0x10000)
343 {
344 string_append_byte (self, (BYTE)((ch >> 12) | 0xE0));
345 string_append_byte (self, (BYTE)((ch >> 6 & 0x3F) | 0x80));
346 string_append_byte (self, (BYTE)((ch & 0x3F) | 0x80));
347 }
348 else
349 {
350 string_append_byte (self, (BYTE)((ch >> 18) | 0xF0));
351 string_append_byte (self, (BYTE)(((ch >> 12) & 0x3F) | 0x80));
352 string_append_byte (self, (BYTE)(((ch >> 6) & 0x3F) | 0x80));
353 string_append_byte (self, (BYTE)((ch & 0x3F) | 0x80));
354 }
355 }
356
357
358
359
360
Generated by GNU Enscript 1.6.6, and GophHub 1.3.