/*
* $Id: strings.c,v 1.3 2025/03/09 19:50:47 snw Exp $
* freem string library
*
*
* Author: Serena Willis <snw@coherent-logic.com>
* Copyright (C) 1998 MUG Deutschland
* Copyright (C) 2020, 2025 Coherent Logic Development LLC
*
*
* This file is part of FreeM.
*
* FreeM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero Public License for more details.
*
* You should have received a copy of the GNU Affero Public License
* along with FreeM. If not, see <https://www.gnu.org/licenses/>.
*
* $Log: strings.c,v $
* Revision 1.3 2025/03/09 19:50:47 snw
* Second phase of REUSE compliance and header reformat
*
*
* SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
* SPDX-License-Identifier: AGPL-3.0-or-later
**/
#include "mpsdef.h"
#include <ctype.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
/* length of 'source' string in bytes */
long int stlen (const char *source)
{
register int length = 0;
while (*source++ != EOL) length++;
return length;
}
long int stnlen (const char *source, size_t siz)
{
register int length = 0;
while ((*source++ != EOL) && (length < siz)) length++;
return length;
}
/* copy string from 'source' to 'dest' */
long int stcpy (char *dest, const char *source)
{
register int count = 0;
while ((*dest++ = *source++) != EOL) count++;
return count;
}
long int stncpy (char *dest, const char *source, size_t siz)
{
register int count = 0;
while (((*dest++ = *source++) != EOL) && (count < siz)) count++;
return count;
}
/* copy exactly 'length' characters from source to dest */
void stcpy0 (char *dest, const char *source, long length)
{
while (length-- > 0) *dest++ = *source++;
return;
}
/* copy exactly 'length' characters from source to dest*/
void stcpy1 (char *dest, const char *source, long length)
{
while (length-- > 0) *dest-- = *source--;
return;
}
/* concatenate string from 'source' to the end of 'dest' */
short int stcat (char *dest, const char *source)
{
register int i = 0;
while (dest[i++] != EOL);
i--;
while ((dest[i] = *source++) != EOL) {
if (i++ >= STRLEN) {
//printf("i = %d\r\n", i);
dest[--i] = EOL;
return FALSE;
}
}
return TRUE;
}
long int stncat (char *dest, const char *source, size_t siz)
{
long int srclen;
long int dstlen;
srclen = stnlen (source, siz);
dstlen = stnlen (dest, siz);
return 0;
}
/* compare str1 and str2 */
short int stcmp (char *str1, char *str2)
{
while (*str1 == *str2) {
if (*str1 == EOL) return 0;
str1++;
str2++;
}
return *str1 - *str2;
}
/* trim whitespace from string 's' */
char *trim (char *s)
{
char *t = strdup (s);
char *end;
char *result;
int final_len;
if (t == NULL) return NULL;
while (isspace ((unsigned char) *t)) t++;
if (*t == 0) return t;
end = t + strlen (t) - 1;
while (end > t && isspace ((unsigned char) *end)) end--;
end[1] = '\0';
/* recover waste ('t' still occupies the same heap
* as it did before the whitespace was stripped)
*/
final_len = strlen (t);
result = (char *) malloc ((final_len + 1) * sizeof (char));
if (result == NULL) return NULL;
strcpy (result, t);
free (t);
return result;
}
/* convert EOL-terminated string 'mstr' to NUL-terminated string in-place */
void stcnv_m2c(char *mstr)
{
mstr[stlen(mstr)] = NUL;
}
void stncnv_m2c(char *mstr, size_t siz)
{
mstr[stnlen (mstr, siz)] = NUL;
}
/* convert NUL-terminated string 'cstr' to EOL-terminated string in-place */
void stcnv_c2m(char *cstr)
{
register int i;
for(i = 0; i < 256; i++) {
if(cstr[i] == '\0') {
cstr[i] = '\201';
return;
}
}
}
void stncnv_c2m(char *cstr, size_t siz)
{
register int i;
for (i = 0; i < siz; i++) {
if (cstr[i] == NUL) {
cstr[i] = EOL;
return;
}
}
return;
}
/* convert at most 'count' characters of *key into human-readable format in *buf */
size_t key_to_name(char *buf, const char *key, size_t count)
{
size_t i;
int j = 0;
int first = 1;
int has_subs = 0;
int in_strlit = 0;
char c;
char next;
if (key[0] == NUL) {
buf[0] = NUL;
return 0;
}
buf[0] = '^';
for (i = 0; i < count; i++) {
c = key[i];
next = key[i + 1];
switch (key[i]) {
case EOL:
if (first == 0) {
if (has_subs == 1) {
if (!in_strlit) {
buf[j++] = ')';
buf[j] = NUL;
}
else {
buf[j++] = '\"';
buf[j++] = ')';
buf[j] = NUL;
}
}
else {
buf[j] = NUL;
}
}
else {
buf[j] = NUL;
}
return i;
case DELIM:
if (first == 1) {
buf[j] = '(';
first = 0;
has_subs = 1;
}
else {
if (!in_strlit) {
buf[j] = ',';
}
else {
buf[j++] = '\"';
buf[j] = ',';
in_strlit = 0;
}
}
if (isalpha(next) && !in_strlit) {
in_strlit = 1;
buf[++j] = '\"';
}
else if (in_strlit) {
in_strlit = 0;
buf[++j] = '\"';
}
break;
default:
buf[j] = key[i];
break;
}
j++;
}
return count;
}
size_t name_to_key(char *buf, const char *name, size_t count)
{
size_t i;
size_t j = 0;
short insubs = FALSE;
short instr = FALSE;
char ch;
for (i = 0; i < count; i++) buf[i] = NUL;
for (i = 0; i < count; i++) {
ch = name[i];
switch (ch) {
case EOL:
buf[j] = ch;
goto n_to_k_done;
case '(':
if (insubs == FALSE && instr == FALSE) {
insubs = TRUE;
buf[j++] = DELIM;
}
else {
if (instr == TRUE) {
buf[j++] = ch;
}
}
break;
case ')':
if (insubs == TRUE && instr == FALSE) {
buf[j] = EOL;
goto n_to_k_done;
}
else {
if (insubs == TRUE && instr == TRUE) {
buf[j++] = ch;
}
}
break;
case ',':
if (insubs == TRUE && instr == FALSE) {
if (buf[j - 1] != DELIM) {
buf[j++] = DELIM;
}
}
else if (insubs == TRUE && instr == TRUE) {
buf[j++] = ch;
}
break;
case '"':
if (insubs == TRUE && instr == FALSE) {
instr = TRUE;
if (buf[j - 1] != DELIM) {
buf[j++] = DELIM;
}
break;
}
if (instr == TRUE) {
instr = FALSE;
buf[j++] = DELIM;
}
break;
default:
buf[j++] = ch;
break;
}
}
n_to_k_done:
return j;
}
void create_var_key (char *buf, int subct, char *nam, ...)
{
int i;
va_list args;
strcat (buf, nam);
strcat (buf, "\202");
va_start (args, nam);
for (i = 0; i < subct; i++) {
strcat (buf, va_arg (args, char *));
if (i < (subct - 1)) strcat (buf, "\202");
}
va_end (args);
strcat (buf, "\201");
}
void trim_decimal (char *s)
{
register int i;
for (i = stlen (s) - 1; s[i] == '0'; i--) s[i] = EOL;
if (s[i] == '.') s[i] = EOL;
}
void uuid_v4 (char *buf)
{
char *chars = "0123456789abcdef";
int seg3num;
int seg4num;
int i;
char seg1[9];
char seg2[5];
char seg3[5];
char seg4[5];
char seg5[13];
seg3num = (rand () % 4095) + 16384;
seg4num = (rand () % 16383) + 32768;
for (i = 0; i < 9; i++) {
seg1[i] = chars[rand () % 16];
}
seg1[8] = '\0';
for (i = 0; i < 4; i++) {
seg2[i] = chars[rand () % 16];
}
seg2[4] = '\0';
snprintf (seg3, 5, "%04x", seg3num);
snprintf (seg4, 5, "%04x", seg4num);
for (i = 0; i < 12; i++) {
seg5[i] = chars[rand () % 16];
}
seg5[12] = '\0';
sprintf (buf, "%s-%s-%s-%s-%s", seg1, seg2, seg3, seg4, seg5);
return;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>