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