Annotation of freem/src/strings.c, revision 1.5
1.1 snw 1: /*
1.5 ! snw 2: * $Id: strings.c,v 1.4 2025/04/09 19:52:02 snw Exp $
1.1 snw 3: * freem string library
4: *
5: *
1.2 snw 6: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 7: * Copyright (C) 1998 MUG Deutschland
1.3 snw 8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
1.1 snw 9: *
10: *
11: * This file is part of FreeM.
12: *
13: * FreeM is free software: you can redistribute it and/or modify
14: * it under the terms of the GNU Affero Public License as published by
15: * the Free Software Foundation, either version 3 of the License, or
16: * (at your option) any later version.
17: *
18: * FreeM is distributed in the hope that it will be useful,
19: * but WITHOUT ANY WARRANTY; without even the implied warranty of
20: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: * GNU Affero Public License for more details.
22: *
23: * You should have received a copy of the GNU Affero Public License
24: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
25: *
1.4 snw 26: * $Log: strings.c,v $
1.5 ! snw 27: * Revision 1.4 2025/04/09 19:52:02 snw
! 28: * Eliminate as many warnings as possible while building with -Wall
! 29: *
1.4 snw 30: * Revision 1.3 2025/03/09 19:50:47 snw
31: * Second phase of REUSE compliance and header reformat
32: *
1.3 snw 33: *
34: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
35: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 36: **/
37:
38: #include "mpsdef.h"
39: #include <ctype.h>
40: #include <stdarg.h>
41: #include <string.h>
42: #include <stdlib.h>
43:
44: /* length of 'source' string in bytes */
45: long int stlen (const char *source)
46: {
47: register int length = 0;
48:
49: while (*source++ != EOL) length++;
50:
51: return length;
52: }
53:
54: long int stnlen (const char *source, size_t siz)
55: {
56: register int length = 0;
57:
58: while ((*source++ != EOL) && (length < siz)) length++;
59:
60: return length;
61: }
62:
63: /* copy string from 'source' to 'dest' */
64: long int stcpy (char *dest, const char *source)
65: {
66: register int count = 0;
67:
68: while ((*dest++ = *source++) != EOL) count++;
69:
70: return count;
71: }
72:
73: long int stncpy (char *dest, const char *source, size_t siz)
74: {
75: register int count = 0;
76:
77: while (((*dest++ = *source++) != EOL) && (count < siz)) count++;
78:
79: return count;
80: }
81:
82:
83: /* copy exactly 'length' characters from source to dest */
84: void stcpy0 (char *dest, const char *source, long length)
85: {
86: while (length-- > 0) *dest++ = *source++;
87:
88: return;
89: }
90:
91:
92: /* copy exactly 'length' characters from source to dest*/
93: void stcpy1 (char *dest, const char *source, long length)
94: {
95: while (length-- > 0) *dest-- = *source--;
96:
97: return;
98: }
99:
100:
101: /* concatenate string from 'source' to the end of 'dest' */
102: short int stcat (char *dest, const char *source)
103: {
104: register int i = 0;
105:
106: while (dest[i++] != EOL);
107:
108: i--;
109:
110: while ((dest[i] = *source++) != EOL) {
111:
112: if (i++ >= STRLEN) {
113: dest[--i] = EOL;
114: return FALSE;
115: }
116:
117: }
118:
119: return TRUE;
120: }
121:
122: /* compare str1 and str2 */
123: short int stcmp (char *str1, char *str2)
124: {
125: while (*str1 == *str2) {
126:
127: if (*str1 == EOL) return 0;
128:
129: str1++;
130: str2++;
131:
132: }
133:
134: return *str1 - *str2;
135: }
136:
137: /* trim whitespace from string 's' */
138: char *trim (char *s)
139: {
140:
141: char *t = strdup (s);
142: char *end;
143: char *result;
144: int final_len;
145:
146: if (t == NULL) return NULL;
147:
148: while (isspace ((unsigned char) *t)) t++;
149:
150: if (*t == 0) return t;
151:
152: end = t + strlen (t) - 1;
153:
154: while (end > t && isspace ((unsigned char) *end)) end--;
155:
156: end[1] = '\0';
157:
158: /* recover waste ('t' still occupies the same heap
159: * as it did before the whitespace was stripped)
160: */
161:
162: final_len = strlen (t);
163: result = (char *) malloc ((final_len + 1) * sizeof (char));
164:
165: if (result == NULL) return NULL;
166:
167: strcpy (result, t);
168: free (t);
169:
170: return result;
171:
172: }
173:
174:
175: /* convert EOL-terminated string 'mstr' to NUL-terminated string in-place */
176: void stcnv_m2c(char *mstr)
177: {
178: mstr[stlen(mstr)] = NUL;
179: }
180:
181: void stncnv_m2c(char *mstr, size_t siz)
182: {
183: mstr[stnlen (mstr, siz)] = NUL;
184: }
185:
186: /* convert NUL-terminated string 'cstr' to EOL-terminated string in-place */
187: void stcnv_c2m(char *cstr)
188: {
189: register int i;
190:
191: for(i = 0; i < 256; i++) {
192:
193: if(cstr[i] == '\0') {
194: cstr[i] = '\201';
195:
196: return;
197: }
198:
199: }
200: }
201:
202: void stncnv_c2m(char *cstr, size_t siz)
203: {
204: register int i;
205:
206: for (i = 0; i < siz; i++) {
207:
208: if (cstr[i] == NUL) {
209: cstr[i] = EOL;
210: return;
211: }
212:
213: }
214:
215: return;
216: }
1.4 snw 217:
1.1 snw 218: /* convert at most 'count' characters of *key into human-readable format in *buf */
219: size_t key_to_name(char *buf, const char *key, size_t count)
220: {
221: size_t i;
222: int j = 0;
223: int first = 1;
224: int has_subs = 0;
225: int in_strlit = 0;
226: char c;
227: char next;
228:
229: if (key[0] == NUL) {
230: buf[0] = NUL;
231:
232: return 0;
233: }
234:
235: buf[0] = '^';
236:
237: for (i = 0; i < count; i++) {
238:
239: c = key[i];
240: next = key[i + 1];
241:
1.4 snw 242: switch (c) {
1.1 snw 243:
244: case EOL:
245:
246: if (first == 0) {
247:
248: if (has_subs == 1) {
249:
250: if (!in_strlit) {
251: buf[j++] = ')';
252: buf[j] = NUL;
253: }
254: else {
255: buf[j++] = '\"';
256: buf[j++] = ')';
257: buf[j] = NUL;
258: }
259:
260: }
261: else {
262: buf[j] = NUL;
263: }
264:
265: }
266: else {
267: buf[j] = NUL;
268: }
269:
270: return i;
271:
272:
273: case DELIM:
274:
275: if (first == 1) {
276:
277: buf[j] = '(';
278: first = 0;
279: has_subs = 1;
280:
281: }
282: else {
283:
284: if (!in_strlit) {
285: buf[j] = ',';
286: }
287: else {
288:
289: buf[j++] = '\"';
290: buf[j] = ',';
291:
292: in_strlit = 0;
293:
294: }
295:
296: }
297:
298: if (isalpha(next) && !in_strlit) {
299: in_strlit = 1;
300: buf[++j] = '\"';
301: }
302: else if (in_strlit) {
303: in_strlit = 0;
304: buf[++j] = '\"';
305: }
306:
307: break;
308:
309:
310: default:
311: buf[j] = key[i];
312: break;
313: }
314:
315: j++;
316: }
317:
318: return count;
319:
320: }
321:
322: size_t name_to_key(char *buf, const char *name, size_t count)
323: {
324: size_t i;
325: size_t j = 0;
326:
327: short insubs = FALSE;
328: short instr = FALSE;
329:
330: char ch;
331:
332: for (i = 0; i < count; i++) buf[i] = NUL;
333:
334: for (i = 0; i < count; i++) {
335:
336: ch = name[i];
337:
338: switch (ch) {
339:
340: case EOL:
341: buf[j] = ch;
342: goto n_to_k_done;
343:
344: case '(':
345: if (insubs == FALSE && instr == FALSE) {
346: insubs = TRUE;
347: buf[j++] = DELIM;
348: }
349: else {
350: if (instr == TRUE) {
351: buf[j++] = ch;
352: }
353: }
354: break;
355:
356:
357: case ')':
358: if (insubs == TRUE && instr == FALSE) {
359: buf[j] = EOL;
360:
361: goto n_to_k_done;
362: }
363: else {
364: if (insubs == TRUE && instr == TRUE) {
365: buf[j++] = ch;
366: }
367: }
368: break;
369:
370:
371: case ',':
372: if (insubs == TRUE && instr == FALSE) {
373: if (buf[j - 1] != DELIM) {
374: buf[j++] = DELIM;
375: }
376: }
377: else if (insubs == TRUE && instr == TRUE) {
378: buf[j++] = ch;
379: }
380:
381: break;
382:
383:
384: case '"':
385:
386: if (insubs == TRUE && instr == FALSE) {
387: instr = TRUE;
388:
389: if (buf[j - 1] != DELIM) {
390: buf[j++] = DELIM;
391: }
392:
393: break;
394: }
395:
396: if (instr == TRUE) {
397: instr = FALSE;
398: buf[j++] = DELIM;
399: }
400:
401: break;
402:
403:
404: default:
405: buf[j++] = ch;
406: break;
407: }
408:
409: }
410:
411: n_to_k_done:
412:
413: return j;
414:
415: }
416:
417: void create_var_key (char *buf, int subct, char *nam, ...)
418: {
419: int i;
420: va_list args;
421:
422: strcat (buf, nam);
423: strcat (buf, "\202");
424:
425: va_start (args, nam);
426:
427: for (i = 0; i < subct; i++) {
428:
429: strcat (buf, va_arg (args, char *));
430:
431: if (i < (subct - 1)) strcat (buf, "\202");
432:
433: }
434:
435: va_end (args);
436:
437: strcat (buf, "\201");
438: }
439:
440: void trim_decimal (char *s)
441: {
442: register int i;
443:
444: for (i = stlen (s) - 1; s[i] == '0'; i--) s[i] = EOL;
445:
446: if (s[i] == '.') s[i] = EOL;
447: }
448:
449: void uuid_v4 (char *buf)
450: {
451:
452: char *chars = "0123456789abcdef";
453: int seg3num;
454: int seg4num;
455: int i;
456:
457: char seg1[9];
458: char seg2[5];
459: char seg3[5];
460: char seg4[5];
461: char seg5[13];
462:
463: seg3num = (rand () % 4095) + 16384;
464: seg4num = (rand () % 16383) + 32768;
465:
466: for (i = 0; i < 9; i++) {
467: seg1[i] = chars[rand () % 16];
468: }
469:
470: seg1[8] = '\0';
471:
472: for (i = 0; i < 4; i++) {
473: seg2[i] = chars[rand () % 16];
474: }
475:
476: seg2[4] = '\0';
477:
478: snprintf (seg3, 5, "%04x", seg3num);
479: snprintf (seg4, 5, "%04x", seg4num);
480:
481: for (i = 0; i < 12; i++) {
482: seg5[i] = chars[rand () % 16];
483: }
484:
485: seg5[12] = '\0';
486:
487: sprintf (buf, "%s-%s-%s-%s-%s", seg1, seg2, seg3, seg4, seg5);
488:
489: return;
490:
491: }
492:
493:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>