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