home *** CD-ROM | disk | FTP | other *** search
- /*
- * ugly/expstr.c
- *
- * ugly expandable-string functions
- *
- * Copyright (C) 1995,96 Thomas Aglassinger
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * updated: 30-Jun-1996
- * created: 12-Sep-1995
- *
- */
-
- #include <ctype.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include "utypes.h"
- #include "ustring.h"
- #include "umemory.h"
-
- #define NOEXTERN_UGLY_STRING_H
- #include "expstr.h"
-
- #if DEBUG_UGLY_EXPSTR
- #define D(x) x
- #define DEXP "*expstr* "
- #else
- #define D(x) /* nufin */
- #endif
-
- static void es_null(STRPTR func, STRPTR file, ULONG line)
- {
- fprintf(stderr, "\n##\n## panic: es=NULL in %s()\n## called from %s (%lu)\n##\n",
- func, file, line);
- }
-
- static void s_null(STRPTR func, STRPTR file, ULONG line)
- {
- fprintf(stderr, "\n##\n## panic: string=NULL in %s()\n## called from %s (%lu)\n##\n",
- func, file, line);
- }
-
- /*
- *-------------------------------------
- * set/clear expstr
- *-------------------------------------
- */
-
- /*
- * set_estr_mem
- *
- * set new mem for es_data
- *
- * params: es........expstr where to assign the new mem to
- * new_size..new size for data part
- * result: TRUE if all ok, new mem in es->es_data;
- * errors: return FALSE, leave es->es_data untouched
- *
- */
- static BOOL do_set_estr_mem(EXPSTR * es, STRPTR new_data, size_t new_size)
- {
- BOOL ok = TRUE;
-
- if (new_data) {
-
- #if DEBUG_UGLY_EXPSTR == 2
- D(fprintf(stderr, DEXP "set to %lu (%p->%p)\n",
- new_size, es->es_data, new_data));
- #endif
- es->es_size = new_size;
- es->es_data = new_data;
-
- } else
- ok = FALSE;
-
- return (ok);
- }
-
- BOOL ugly_set_estr_mem(EXPSTR * es, size_t new_size)
- {
- return (do_set_estr_mem(es, umalloc(new_size), new_size));
- }
-
- BOOL ugly_dbg_set_estr_mem(EXPSTR * es, size_t new_size, STRPTR file, ULONG line)
- {
- BOOL ok = FALSE;
-
- if (!es)
- es_null("set_estr_mem", file, line);
- else {
- ok = do_set_estr_mem(es,
- ugly_malloc_tracking(new_size, file, line),
- new_size);
- }
-
- return (ok);
- }
-
- /*
- * set_estr
- *
- * set es_data with chars copied from a string
- */
- BOOL ugly_set_estr(EXPSTR * es, CONSTRPTR s)
- {
- BOOL ok = FALSE;
- size_t new_len = strlen(s) + 1;
- STRPTR old_data = es->es_data;
-
- if ((es->es_size == es->es_step)
- && (es->es_size > new_len)) {
- strcpy(es->es_data, s); /* copy new data */
- es->es_len = new_len; /* set new len */
- ok = TRUE;
- } else if (set_estr_mem(es, modadj(new_len, es->es_step))) {
-
- strcpy(es->es_data, s); /* copy new & release old data */
- ufreestr(old_data);
-
- es->es_len = new_len; /* set new len */
- ok = TRUE;
- }
- return (ok);
- }
-
- BOOL ugly_dbg_set_estr(EXPSTR * es, CONSTRPTR s, STRPTR file, ULONG line)
- {
- BOOL ok = FALSE;
-
- if (!es)
- es_null("set_estr_mem", file, line);
- else if (!s)
- s_null("set_estr_mem", file, line);
- else {
- size_t new_len = strlen(s) + 1;
- STRPTR old_data = es->es_data;
-
- #if DEBUG_UGLY_EXPSTR == 2
- uglymem_wallcheck("setestr()", file, line);
- #endif
-
- if ((es->es_size == es->es_step)
- && (es->es_size > new_len)) {
-
- strcpy(es->es_data, s); /* copy new data */
- es->es_len = new_len; /* set new len */
- ok = TRUE;
-
- } else if (ugly_dbg_set_estr_mem(es, modadj(new_len, es->es_step), file, line)) {
-
- strcpy(es->es_data, s); /* copy new & release old data */
- ufree(old_data);
-
- es->es_len = new_len; /* set new len */
- ok = TRUE;
- }
- #if DEBUG_UGLY_EXPSTR == 2
- uglymem_wallcheck("setestr()", file, line);
- #endif
-
- }
-
- return (ok);
- }
-
- /*
- * clr_estr
- *
- * clear expstr (set es_data to "")
- */
- BOOL ugly_clr_estr(EXPSTR * es)
- {
- return (set_estr(es, ""));
- }
-
- BOOL ugly_dbg_clr_estr(EXPSTR * es, STRPTR file, ULONG line)
- {
- #if DEBUG_UGLY_EXPSTR == 2
- STRPTR s = es->es_data;
- if (!s)
- s = "<null>";
- fprintf(stderr, DEXP "clr_estr(%p,`%s')\n", es, s);
- uglymem_wallcheck("clr_estr()", file, line);
- #endif
- return (ugly_dbg_set_estr(es, "", file, line));
- }
-
- /*
- * set_estrn
- *
- * set expstr with first n chars of string
- */
- BOOL set_estrn(EXPSTR * es, CONSTRPTR s, size_t n)
- {
- BOOL ok = FALSE;
- STRPTR s1 = NULL;
- size_t len = strlen(s);
-
- if (n > len)
- n = len;
-
- s1 = (STRPTR) umalloc(n + 1);
- if (s1) {
-
- memcpy(s1, s, n);
- s1[n] = 0;
- ok = set_estr(es, s1);
- ufree(s1);
-
- }
- return (ok);
- }
-
- /*
- *-------------------------------------
- * constructor / destructor
- *-------------------------------------
- */
-
- EXPSTR *ugly_dbg_init_estr(size_t step_size, STRPTR file, ULONG line)
- {
- EXPSTR *es = ugly_malloc_tracking(sizeof(EXPSTR), file, line);
-
- if (es) {
-
- if (step_size < ES_MIN_MEMSTEP)
- step_size = ES_MIN_MEMSTEP;
- es->es_data = NULL;
- es->es_size = 0;
- es->es_step = step_size;
- if (!clr_estr(es)) {
-
- ufree(es);
- es = NULL;
-
- }
- }
- return (es);
-
- }
-
- EXPSTR *ugly_init_estr(size_t step_size)
- {
- EXPSTR *es = umalloc(sizeof(EXPSTR));
-
- if (es) {
-
- if (step_size < ES_MIN_MEMSTEP)
- step_size = ES_MIN_MEMSTEP;
- es->es_data = NULL;
- es->es_size = 0;
- es->es_step = step_size;
- if (!clr_estr(es)) {
-
- ufree(es);
- es = NULL;
-
- }
- }
- return (es);
-
- }
-
- VOID del_estr(EXPSTR * es)
- {
- #if DEBUG_UGLY_EXPSTR
- if (es) {
- if (es->es_data) {
- #if DEBUG_UGLY_EXPSTR == 2
- STRARR s[17];
- strncpy(s, es->es_data, 17);
- s[16] = 0;
- D(fprintf(stderr, DEXP "del_estr(%p,`%s')\n", es, s));
- umem_wallcheck("del_estr()");
- #endif
- } else {
- D(fprintf(stderr, DEXP "attempt to free null-data-estr\n"));
- }
- } else {
- #if DEBUG_UGLY_EXPSTR == 2
- D(fprintf(stderr, DEXP "attempt to free null-estr\n"));
- #endif
- }
- #endif
-
- if (es) {
-
- ufree(es->es_data);
- es->es_len = 0;
- es->es_size = 0;
- es->es_step = 0;
- ufree(es);
-
- }
- }
-
- /*
- *-------------------------------------
- * append char/string to expstr
- *-------------------------------------
- */
- BOOL ugly_app_estrch(EXPSTR * es, int ch)
- {
- BOOL ok = TRUE;
-
- if (es->es_len >= es->es_size) { /* enough mem left? */
-
- STRPTR old_data = es->es_data; /* N->remeber old data ptr */
-
- if (set_estr_mem(es,
- es->es_size + es->es_step)) { /* set new mem sucessful? */
-
- strcpy(es->es_data, /* Y->copy old data */
- old_data);
- ufree(old_data); /* release old data */
-
- } else {
- /* N->return error */
- ok = FALSE;
- }
- }
- if (ok) {
-
- STRPTR s;
- s = es->es_data;
- s[es->es_len - 1] = ch; /* append new char to expstr */
- s[es->es_len] = 0;
- es->es_len++; /* incr. expstr length */
-
- }
- return (ok);
- }
-
- BOOL ugly_dbg_app_estrch(EXPSTR * es, int ch, STRPTR file, ULONG line)
- {
- BOOL ok = TRUE;
-
- if (!es) {
- es_null("app_estrch", file, line);
- ok = FALSE;
- } else if (es->es_len >= es->es_size) { /* enough mem left? */
-
- STRPTR old_data = es->es_data; /* N->remeber old data ptr */
-
- if (ugly_dbg_set_estr_mem(es,
- es->es_size + es->es_step, file, line)) {
- /* set new mem sucessfully? */
-
- strcpy(es->es_data, /* Y->copy old data */
- old_data);
- ufree(old_data); /* release old data */
- } else { /* N->return error */
- ok = FALSE;
- }
- }
- if (ok) {
-
- STRPTR s;
- s = es->es_data;
- s[es->es_len - 1] = ch; /* append new char to expstr */
- s[es->es_len] = 0;
- es->es_len++; /* incr. expstr length */
-
- }
- return (ok);
- }
-
- BOOL ugly_app_estr(EXPSTR * es, CONSTRPTR s)
- {
- BOOL ok = TRUE;
-
- #if 0
- size_t i;
- for (i = 0; ((s[i]) && ok); i++)
- ok &= ugly_app_estrch(es, s[i]);
- #else
- /* faster, but maybe buggy */
- size_t slen = strlen(s);
-
- ok = TRUE;
- if ((es->es_len + slen - 1) >= es->es_size) { /* enough mem left? */
-
- STRPTR old_data = es->es_data; /* N->remeber old data ptr */
-
- if (ugly_set_estr_mem(es,
- modadj(es->es_len + slen + 1, es->es_step))) {
- /* set new mem sucessful? */
-
- strcpy(es->es_data, /* Y->copy old data */
- old_data);
- ufree(old_data); /* release old data */
- } else { /* N->return error */
- ok = FALSE;
- }
- }
- if (ok) {
-
- STRPTR ds;
- ds = es->es_data + (es->es_len - 1);
- strcat(ds, s);
- /* append new char to expstr */
- es->es_len += slen; /* incr. expstr length */
- es->es_data[es->es_len - 1] = 0;
-
- }
- #endif
- return (ok);
- }
-
- #if 0
- BOOL ugly_dbg_app_estrch(EXPSTR * es, int ch, STRPTR file, ULONG line)
- {
- BOOL ok = FALSE;
-
- ok = ugly_app_estrch(es, ch);
-
- return (ok);
- }
- #endif
-
- BOOL ugly_dbg_app_estr(EXPSTR * es, CONSTRPTR s, STRPTR file, ULONG line)
- {
- BOOL ok = FALSE;
-
- if (!es)
- es_null("app_estr", file, line);
- else if (!s)
- s_null("app_estr", file, line);
- else {
- #if 0
- /* oldy, but goldy - slow, but it works */
- size_t i;
- ok = TRUE;
- for (i = 0; ((s[i]) && ok); i++)
- ok &= ugly_dbg_app_estrch(es, s[i], file, line);
- #else
- /* faster, but maybe buggy */
- size_t slen = strlen(s);
-
- ok = TRUE;
- if ((es->es_len + slen - 1) >= es->es_size) { /* enough mem left? */
-
- STRPTR old_data = es->es_data; /* N->remeber old data ptr */
-
- if (ugly_dbg_set_estr_mem(es,
- modadj(es->es_len + slen + 1, es->es_step), file, line)) { /* set new mem sucessful? */
-
- strcpy(es->es_data, /* Y->copy old data */
- old_data);
- ufree(old_data); /* release old data */
- } else { /* N->return error */
- ok = FALSE;
- }
- }
- if (ok) {
-
- STRPTR ds;
- ds = es->es_data + (es->es_len - 1);
- strcat(ds, s);
- /* append new char to expstr */
- es->es_len += slen; /* incr. expstr length */
- es->es_data[es->es_len - 1] = 0;
-
- }
- #endif
- }
-
- return (ok);
- }
-
- /*
- *-------------------------------------
- * get part of expstr
- *-------------------------------------
- */
-
- /*
- * todo: handle special cases like
- * get_right_estr( .., "hugo", 99 );
- */
-
- /*
- * get_mid_estr
- *
- * get a part from a expstr; compare BASIC's "MID$()"
- *
- * params: dest...destination expstr where to store result part
- * src....source expstr where to get part from
- * from...position of char where to begin part (0=first char)
- * num....number of chars to get
- * result: TRUE and result in dest if ok; else FALSE is returned an
- * dest is left untouched
- *
- * NOTE: it is possible to use the source-exstr as destination-expstr,
- * because the result is copied to a temp. expstr before
- * ( example: get_mid_estr( hugo, hugo, 3, 4 ); )
- */
- BOOL get_mid_estr(EXPSTR * dest, EXPSTR * src, size_t from, size_t num)
- {
- BOOL ok = FALSE;
- EXPSTR *tmp = init_estr(dest->es_step);
-
- if (tmp) {
-
- STRPTR old_data = tmp->es_data;
-
- /* check size */
- if (from >= src->es_len)
- from = src->es_len - 1;
- if (from + num >= src->es_len)
- num = src->es_len - from - 1;
-
- /* set new mem for tmp */
- ok = set_estr_mem(tmp, modadj(num + 1, tmp->es_step));
-
- if (ok) {
-
- /* copy data */
- strncpy(estr2str(tmp), estr2str(src) + from, num);
- tmp->es_data[num] = 0;
- tmp->es_len = num + 1;
- ufree(old_data);
-
- ok = estrcpy(dest, tmp);
-
- }
- del_estr(tmp);
-
- }
- return (ok);
- }
-
- /*
- * get_right_estr
- *
- * get right part from a expstr; compare BASIC's "RIGHT$()"
- */
- BOOL get_right_estr(EXPSTR * dest, EXPSTR * src, size_t num)
- {
- if (num >= src->es_len)
- num = src->es_len - 1;
-
- return (get_mid_estr(dest, src, (src->es_len - num - 1), num));
- }
-
- /*
- * get_left_estr
- *
- * get left part from a expstr; compare BASIC's "LEFT$()"
- */
- BOOL get_left_estr(EXPSTR * dest, EXPSTR * src, size_t num)
- {
- return (get_mid_estr(dest, src, 0, num));
- }
-
- /*
- *-------------------------------------
- * misc. functions
- *-------------------------------------
- */
-
- /*
- * ugly_estr2str: convert EXPSTR to conventional string
- *
- * NOTE: this function is replaced by a macro with DEBUG undefined
- */
- STRPTR ugly_estr2str(EXPSTR * es)
- {
- return (es->es_data);
- }
-
- /*
- * ugly_estrstrlen: return length of an EXPSTR
- *
- * NOTE: this function is replaced by a macro with DEBUG undefined
- */
- size_t ugly_estrlen(EXPSTR * es)
- {
- return (es->es_len - 1);
- }
-
- /* estrcpy: clone EXPSTR */
- BOOL estrcpy(EXPSTR * dest, EXPSTR * src)
- {
- return (set_estr(dest, estr2str(src)));
- }
-
- /* estrcat: concat two EXPSTRs */
- BOOL estrcat(EXPSTR * dest, EXPSTR * src)
- {
- return (app_estr(dest, estr2str(src)));
- }
-
-