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