/* $Id: str.c,v 1.10 2003/07/31 21:17:19 mastermind Exp $ */ /* * Copyright (c) 1998-2003, Alexander Marx * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * */ #define __easy_eSTR_C #include "str.h" /* --- Public Functions --------------------------------------------------- */ eSTR *va_newSTR(const char *s, ...) { va_list strs; eSTR *str=NULL; const char *t; long len=0; va_start(strs, s); while(t=va_arg(strs, const char *)) { len+=strlen(t); } va_end(strs); if(str=malloc(sizeof(*str))) { init(str); if(str->str=malloc(strlen(s)+len+1)) { strcpy(str->str, s); va_start(strs, s); while(t=va_arg(strs, const char *)) strcat(str->str, t); va_end(strs); str->len=strlen(s)+len; } else { free(str); str=NULL; } } return str; } eSTR *newSTR(const char *s) { eSTR *str=NULL; if(str=malloc(sizeof(*str))) { init(str); if(s) { if(str->str=malloc(strlen(s)+1)) { strcpy(str->str, s); str->len=strlen(s); } else { free(str); str=NULL; } } } return str; } eSTR *clrSTR(eSTR *str) { if(str) destroy(str); return str; } eSTR *cpySTR(eSTR *dest_str, const eSTR *src_str) { eSTR tmp_str; if(dest_str && src_str && (dest_str!=src_str)) { if(copy(&tmp_str, src_str)) { destroy(dest_str); *dest_str=tmp_str; return dest_str; } } return NULL; } eSTR *dupSTR(const eSTR *src_str) { eSTR *str=NULL; if(src_str) { if(str=malloc(sizeof(*str))) { if(!copy(str, src_str)) { free(str); str=NULL; } } } return str; } eSTR *setSTR(eSTR *str, const char *s) { char *t; if(str) { if(s) { if(t=malloc(strlen(s)+1)) { strcpy(t, s); destroy(str); str->str=t; str->len=strlen(s); } else return NULL; } else destroy(str); } return str; } eSTR *spcSTR(unsigned long len) { eSTR *str=NULL; if(len) { if(str=malloc(sizeof(*str))) { init(str); if(str->str=malloc(len+1)) { memset(str->str, ' ', len); str->str[len]='\0'; str->len=len; } else { free(str); str=NULL; } } } return str; } void freeSTR(eSTR *str) { if(str) { destroy(str); free(str); } } char *strSTR(const eSTR *str) { return str ? str->str : NULL; } long lenSTR(const eSTR *str) { return str ? str->len : 0; } int putSTR(const eSTR *str, FILE *fh) { int rc=0; if(fh && str && str->str) rc=fprintf(fh, "%s", str->str); return rc; } int putsSTR(const eSTR *str, FILE *fh) { int rc=0; if(fh) { if(str && str->str) rc=fprintf(fh, "%s", str->str); rc+=fprintf(fh, "\n"); } return rc; } eSTR *getSTR(FILE *fh) { int c; char *buffer=NULL; eSTR *str=NULL; long len=-1; if(fh) { if(feof(fh)) return NULL; if(str=newSTR(NULL)) { if(buffer=malloc(eSTR_BLOCK_SIZE)) { buffer[eSTR_BLOCK_SIZE-1]='\0'; for(;;) { c=fgetc(fh); len++; buffer[len]=(char)c; if(c=='\0' || c==EOF) { buffer[len]='\0'; if(catSTR(str, buffer)) break; else { freeSTR(str); str=NULL; break; } } if(len==(eSTR_BLOCK_SIZE-2)) { if(!catSTR(str, buffer)) { freeSTR(str); str=NULL; break; } else { len=-1; } } } free(buffer); } else { freeSTR(str); str=NULL; } } } return str; } eSTR *getlineSTR(FILE *fh) { int c; char *buffer=NULL; eSTR *str=NULL; long len=-1; if(fh) { if(feof(fh)) return NULL; if(str=newSTR(NULL)) { if(buffer=malloc(eSTR_BLOCK_SIZE)) { buffer[eSTR_BLOCK_SIZE-1]='\0'; for(;;) { c=fgetc(fh); len++; buffer[len]=(char)c; if(c=='\n' || c=='\r' || c=='\0' || c==EOF) { if(c=='\r') { if((c=fgetc(fh))!='\n') ungetc(c, fh); } buffer[len]='\0'; if(catSTR(str, buffer)) break; else { freeSTR(str); str=NULL; break; } } if(len==(eSTR_BLOCK_SIZE-2)) { if(!catSTR(str, buffer)) { freeSTR(str); str=NULL; break; } else { len=-1; } } } free(buffer); } else { freeSTR(str); str=NULL; } } } return str; } char traverseSTR(eSTR *str, int move_to) { if(str) { switch(move_to) { case eSTR_HEAD: str->idx=0; break; case eSTR_TAIL: str->idx=str->len; break; case eSTR_FWD: str->idx++; break; case eSTR_BWD: str->idx--; break; } } return chrSTR(str); } char *adrSTR(const eSTR *str) { return str ? str->str ? str->str+str->idx : NULL : NULL; } long idxSTR(const eSTR *str) { return str ? str->idx : 0; } char chrSTR(eSTR *str) { char c='\0'; if(str) { if(str->str) { if(str->idx<0) { c='\0'; str->idx=0; } else if(str->idx>str->len) { c='\0'; str->idx=str->len; } else { c=str->str[str->idx]; } } } return c; } eSTR *upperSTR(eSTR *str) { char *t; if(str && (t=str->str)) { while(*t) { if(islower((int)*t)) *t=toupper(*t); t++; } } return str; } eSTR *lowerSTR(eSTR *str) { char *t; if(str && (t=str->str)) { while(*t) { if(isupper((int)*t)) *t=tolower(*t); t++; } } return str; } eSTR *reverseSTR(eSTR *str) { long n, m; char c; if(str && str->str) { for(n=0, m=str->len-1; n<(str->len)/2; n++, m--) { c=str->str[n]; str->str[n]=str->str[m]; str->str[m]=c; } } return str; } eSTR *stripSTR(eSTR *str, int where, const char *s) { long m, n, i; if(str && str->str && s) { if(BTST(where, eSTR_LEAD) && str->len) { for(i=0; strchr(s, str->str[i]); i++); str->len-=i; if(str->len<0) str->len=0; else memmove(str->str, str->str+i, (unsigned int)str->len); } if(BTST(where, eSTR_TRAIL) && str->len) { i=str->len-1; if(i>=0) { while(strchr(s, str->str[i])) i--; str->str[++i]='\0'; str->len=i; } } if(BTST(where, eSTR_BODY) && str->len) { if(str->len>0) { for(i=0; strchr(s, str->str[i]); i++); for(n=str->len-1; strchr(s, str->str[n]); n--); for(m=i; str->str[i]; i++) if((strchr(s, str->str[i])==NULL) || (i>n)) { str->str[m]=str->str[i]; m++; } str->str[m]='\0'; str->len=m; } } } return str; } eSTR *catSTR(eSTR *dest_str, const char *s) { long len; char *t; if(dest_str) { if(s) { if(t=malloc(dest_str->len+strlen(s)+1)) { if(dest_str->str) strcpy(t, dest_str->str); else *t='\0'; strcat(t, s); len=dest_str->len+strlen(s); destroy(dest_str); dest_str->str=t; dest_str->len=len; return dest_str; } } else return dest_str; } return NULL; } eSTR *va_catSTR(eSTR *dest_str, ...) { va_list strs; const char *s; char *t; size_t len=0; if(!dest_str) return NULL; va_start(strs, dest_str); while(s=va_arg(strs, const char *)) { len+=strlen(s); } va_end(strs); va_start(strs, dest_str); if(t=malloc(dest_str->len+len+1)) { if(dest_str->str) strcpy(t, dest_str->str); else *t='\0'; while(s=va_arg(strs, const char *)) strcat(t, s); len=dest_str->len+len; destroy(dest_str); dest_str->str=t; dest_str->len=len; return dest_str; } va_end(strs); return NULL; } char *tokSTR(eSTR *str, const char *s) { if(str) return strtok(str->str, s); else return strtok(NULL, s); } eSTR *catSTRs(eSTR *dest_str, const eSTR *src_str) { if(dest_str && src_str && catSTR(dest_str, src_str->str)) return dest_str; else return NULL; } eSTR *leftSTR(const eSTR *str, long idx) { eSTR *left=NULL; if(str) { if(idx>=str->len) left=dupSTR(str); else if(idx<=0) left=newSTR(NULL); else { if(left=spcSTR((unsigned long)idx)) memcpy(left->str, str->str, (size_t) idx); } } return left; } eSTR *rightSTR(const eSTR *str, long idx) { eSTR *right=NULL; if(str) { if(idx>=str->len) right=newSTR(NULL); else if(idx<0) right=dupSTR(str); else { if(right=spcSTR((unsigned long)str->len-idx-1)) memcpy(right->str, str->str+idx+1, (size_t) str->len-idx-1); } } return right; } eSTR *midSTR(const eSTR *str, long idx, long len) { eSTR *mid=NULL; long start, end; if(str) { if(len<0) mid=rightSTR(str, idx); else { end=idx+len+1; if(end>str->len) end=str->len; start=idx; if(start<0) start=-1; if(idx>=str->len) mid=newSTR(NULL); else if(mid=spcSTR((unsigned long)end-start-1)) { memcpy(mid->str, str->str+start+1, (size_t) end-start-1); } } } return mid; } long subsSTR(const eSTR *haystack, const char *needle) { char *s; long idx=-1; if(haystack && needle && haystack->str) { if(s=strstr(haystack->str, needle)) { idx=s-haystack->str; } } return idx; } long subcSTR(const eSTR *haystack, char needle) { char *s; long idx=-1; if(haystack && needle && haystack->str) { if(s=strchr(haystack->str, needle)) { idx=s-haystack->str; } } return idx; } int cmpSTR(const eSTR *str, const char *s) { if(str && str->str) { if(s) return strcmp(str->str, s); else return 1; } else if(s) return -1; else return 0; } int cmpSTRs(const eSTR *s1, const eSTR *s2) { if(s1 && s1->str) { if(s2 && s2->str) return strcmp(s1->str, s2->str); else return 1; } else if(s2 && s2->str) return -1; else return 0; } BOOL verifySTR(const eSTR *str, const char *s) { BOOL rc=FALSE; char *t; if(str && str->str && s) { t=str->str; rc=TRUE; while(*t && rc) { if(strchr(s, *t)==NULL) rc=FALSE; t++; } } return rc; } eSTR *infileSTR(const char *file) { eSTR *str=NULL; long size; FILE *fh; if(fh=fopen(file, "r")) { if(str=newSTR(NULL)) { fseek(fh, 0, SEEK_END); size=ftell(fh); rewind(fh); if(str->str=malloc((unsigned long)size+1)) { fread(str->str, (size_t) size, 1, fh); str->str[size]='\0'; str->len=size; } else { freeSTR(str); str=NULL; } } fclose(fh); } return str; } int outfileSTR(const eSTR *str, const char *file) { int rc=0; FILE *fh; if(str && file) { if(fh=fopen(file, "w")) { rc=fwrite(str->str, (size_t)str->len, 1, fh); fclose(fh); } } return rc; } int tounixSTR(eSTR *str) { char *s; int i=0; if(str) { char *ss; for(i=0, s=str->str; *s; ss=++s, *(ss-i)=*s) { if(*s=='\r') i++; } str->len=str->len-i; *(str->str+str->len)='\0'; } return i; } /* --- Private Functions -------------------------------------------------- */ static int copy(eSTR *dest_str, const eSTR *src_str) { int rc=FALSE; if(dest_str->str=malloc((unsigned long) src_str->len+1)) { memcpy(dest_str->str, src_str->str, (size_t) src_str->len+1); dest_str->len=src_str->len; dest_str->idx=src_str->idx; rc=TRUE; } return rc; } static void destroy(eSTR *str) { if(str) { if(str->str) free(str->str); init(str); } } static void init(eSTR *str) { if(str) { str->str=NULL; str->len=str->idx=0; } }