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