/* Copyright (c) 1993 Stephen F. White */ #include <stdio.h> #ifdef SYSV #include <string.h> #else #include <strings.h> #endif #include <ctype.h> #include "config.h" #include "cool.h" #include "proto.h" #include "sys_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; 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() */