/* Copyright (c) 1993 Stephen F. White */ #include "cool.h" #include "proto.h" #include "servers.h" String *string_new (int len) { String *new; int newlen = MAX (len, STRING_INIT_SIZE); new = (String *) cool_malloc (sizeof (String) + newlen + 1); new->mem = newlen; new->len = 0; new->ref = 1; new->str = (char *) new + sizeof (String); new->str[0] = '\0'; return new; } #ifndef INLINE String *string_dup (String * s) { s->ref++; return s; } void string_free (String * s) { s->ref--; if (s->ref == 0) { FREE (s); } } #endif /* * string_cpy() - copy a char * into a String struct */ String *string_cpy (const char *s) { String *new; new = string_new (strlen (s)); new = string_cat (new, s); return new; } String *string_ncpy (const char *s, int len) { String *new; new = string_new (len + 1); strncpy (new->str, s, len); new->len = len; new->str[len] = '\0'; return new; } static String *string_extend_to (String * str, int mem) { String *new; if (!str) return 0; if (mem <= str->mem) { return str; } #ifdef STRING_DOUBLING while (mem > str->mem) { str->mem = (str->mem + sizeof (String)) * 2 - sizeof (String); } #else str->mem = (mem / STRING_GROW_BY + 1) * STRING_GROW_BY; #endif new = string_new (str->mem); strcpy (new->str, str->str); new->len = strlen (new->str); FREE (str); return new; } String *string_catc (String * str, char c) { if (!str) return 0; if (str->len + 2 > str->mem) { str = string_extend_to (str, str->len + 2); } str->str[str->len++] = c; str->str[str->len] = '\0'; return str; } String *string_cat (String * str, const char *s) { int len; if (!str) return 0; len = str->len + strlen (s); if (len + 1 > str->mem) { str = string_extend_to (str, len + 1); } strcat (str->str + str->len, s); str->len = len; return str; } String *string_catnum (String * str, int num) { int len; if (!str) return 0; len = str->len + INT_SIZE; if (len + 1 > str->mem) { str = string_extend_to (str, len + 1); } sprintf (str->str + str->len, "%d", num); str->len = strlen (str->str); return str; } String *string_catobj (String * str, Objid obj, int full) { const char *servername = 0; int len; if (!str) return 0; len = str->len + INT_SIZE + 2 + (full ? strlen (servername = serv_id2name (obj.server)) : 0); if (len + 1 > str->mem) { str = string_extend_to (str, len + 1); } if (full) { sprintf (str->str + str->len, "#%d@%s", obj.id, servername); } else { sprintf (str->str + str->len, "#%d", obj.id); } str->len = strlen (str->str); return str; } String *string_indent_cat (String * str, int indent, const char *s) { int len; char *c; if (!str) return 0; len = str->len + indent + strlen (s); if (len + 1 > str->mem) { str = string_extend_to (str, len + 1); } c = str->str + str->len; for (; indent; indent--) { *c++ = ' '; } strcpy (c, s); str->len = len; return str; } String *string_backslash (String * str, const char *s) { int len; const char *t; char *r; if (!str) return 0; /* * calculate required length, including backslashes * NOTE: CR-LF turns into \n, both of which are two chars, so no * length adjustment is needed */ len = str->len; for (t = s; *t; t++, len++) { if (*t == '\\' || *t == '"' || *t == '\t') { len++; } } /* * extend string, if we have to */ if (len + 1 > str->mem) { str = string_extend_to (str, len + 1); } r = str->str + str->len; /* skip to end of string */ do { switch (*s) { case '\r': s++; /* ignore \r; handle \n instead */ case '\n': *r++ = '\\'; *r++ = 'n'; break; case '\t': *r++ = '\\'; *r++ = 't'; break; case '"': case '\\': *r++ = '\\'; default: *r++ = *s; break; } } while (*s++); str->len = len; return str; } String *string_pad (String * str, int padlen, char tok) { int len; char *s; if (!str) return 0; len = str->len + padlen; if (len + 1 > str->mem) { str = string_extend_to (str, len + 1); } s = str->str + str->len; while (padlen--) { *s++ = tok; } *s = '\0'; str->len = len; return str; } String *string_prepad (String * str, int padlen, char tok) { int len; char *s, *d; if (!str) return 0; len = str->len + padlen; if (len + 1 > str->mem) { str = string_extend_to (str, len + 1); } for (s = str->str + str->len, d = s + padlen; s >= str->str;) { *d-- = *s--; } s = str->str; while (padlen--) { *s++ = tok; } str->len = len; return str; } String *string_strip_cr (String * str) { char *s1, *s2; if (!str) return 0; for (s1 = s2 = str->str; *s1; s1++) { if (*s1 != '\r') { *s2++ = *s1; } } *s2 = '\0'; /* terminate it */ str->len = s2 - str->str; return str; } /* string_strip_cr() */