|  | #include "sam.h" | 
|  |  | 
|  | #define	MINSIZE	16		/* minimum number of chars allocated */ | 
|  | #define	MAXSIZE	256		/* maximum number of chars for an empty string */ | 
|  |  | 
|  |  | 
|  | void | 
|  | Strinit(String *p) | 
|  | { | 
|  | p->s = emalloc(MINSIZE*RUNESIZE); | 
|  | p->n = 0; | 
|  | p->size = MINSIZE; | 
|  | } | 
|  |  | 
|  | void | 
|  | Strinit0(String *p) | 
|  | { | 
|  | p->s = emalloc(MINSIZE*RUNESIZE); | 
|  | p->s[0] = 0; | 
|  | p->n = 1; | 
|  | p->size = MINSIZE; | 
|  | } | 
|  |  | 
|  | void | 
|  | Strclose(String *p) | 
|  | { | 
|  | free(p->s); | 
|  | } | 
|  |  | 
|  | void | 
|  | Strzero(String *p) | 
|  | { | 
|  | if(p->size > MAXSIZE){ | 
|  | p->s = erealloc(p->s, RUNESIZE*MAXSIZE); /* throw away the garbage */ | 
|  | p->size = MAXSIZE; | 
|  | } | 
|  | p->n = 0; | 
|  | } | 
|  |  | 
|  | int | 
|  | Strlen(Rune *r) | 
|  | { | 
|  | Rune *s; | 
|  |  | 
|  | for(s=r; *s; s++) | 
|  | ; | 
|  | return s-r; | 
|  | } | 
|  |  | 
|  | void | 
|  | Strdupl(String *p, Rune *s)	/* copies the null */ | 
|  | { | 
|  | p->n = Strlen(s)+1; | 
|  | Strinsure(p, p->n); | 
|  | memmove(p->s, s, p->n*RUNESIZE); | 
|  | } | 
|  |  | 
|  | void | 
|  | Strduplstr(String *p, String *q)	/* will copy the null if there's one there */ | 
|  | { | 
|  | Strinsure(p, q->n); | 
|  | p->n = q->n; | 
|  | memmove(p->s, q->s, q->n*RUNESIZE); | 
|  | } | 
|  |  | 
|  | void | 
|  | Straddc(String *p, int c) | 
|  | { | 
|  | Strinsure(p, p->n+1); | 
|  | p->s[p->n++] = c; | 
|  | } | 
|  |  | 
|  | void | 
|  | Strinsure(String *p, ulong n) | 
|  | { | 
|  | if(n > STRSIZE) | 
|  | error(Etoolong); | 
|  | if(p->size < n){	/* p needs to grow */ | 
|  | n += 100; | 
|  | p->s = erealloc(p->s, n*RUNESIZE); | 
|  | p->size = n; | 
|  | } | 
|  | } | 
|  |  | 
|  | void | 
|  | Strinsert(String *p, String *q, Posn p0) | 
|  | { | 
|  | Strinsure(p, p->n+q->n); | 
|  | memmove(p->s+p0+q->n, p->s+p0, (p->n-p0)*RUNESIZE); | 
|  | memmove(p->s+p0, q->s, q->n*RUNESIZE); | 
|  | p->n += q->n; | 
|  | } | 
|  |  | 
|  | void | 
|  | Strdelete(String *p, Posn p1, Posn p2) | 
|  | { | 
|  | memmove(p->s+p1, p->s+p2, (p->n-p2)*RUNESIZE); | 
|  | p->n -= p2-p1; | 
|  | } | 
|  |  | 
|  | int | 
|  | Strcmp(String *a, String *b) | 
|  | { | 
|  | int i, c; | 
|  |  | 
|  | for(i=0; i<a->n && i<b->n; i++) | 
|  | if(c = (a->s[i] - b->s[i]))	/* assign = */ | 
|  | return c; | 
|  | /* damn NULs confuse everything */ | 
|  | i = a->n - b->n; | 
|  | if(i == 1){ | 
|  | if(a->s[a->n-1] == 0) | 
|  | return 0; | 
|  | }else if(i == -1){ | 
|  | if(b->s[b->n-1] == 0) | 
|  | return 0; | 
|  | } | 
|  | return i; | 
|  | } | 
|  |  | 
|  | int | 
|  | Strispre(String *a, String *b) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | for(i=0; i<a->n && i<b->n; i++){ | 
|  | if(a->s[i] - b->s[i]){	/* assign = */ | 
|  | if(a->s[i] == 0) | 
|  | return 1; | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | return i == a->n; | 
|  | } | 
|  |  | 
|  | char* | 
|  | Strtoc(String *s) | 
|  | { | 
|  | int i; | 
|  | char *c, *d; | 
|  | Rune *r; | 
|  | c = emalloc(s->n*UTFmax + 1);  /* worst case UTFmax bytes per rune, plus NUL */ | 
|  | d = c; | 
|  | r = s->s; | 
|  | for(i=0; i<s->n; i++) | 
|  | d += runetochar(d, r++); | 
|  | if(d==c || d[-1]!=0) | 
|  | *d = 0; | 
|  | return c; | 
|  |  | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Build very temporary String from Rune* | 
|  | */ | 
|  | String* | 
|  | tmprstr(Rune *r, int n) | 
|  | { | 
|  | static String p; | 
|  |  | 
|  | p.s = r; | 
|  | p.n = n; | 
|  | p.size = n; | 
|  | return &p; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Convert null-terminated char* into String | 
|  | */ | 
|  | String* | 
|  | tmpcstr(char *s) | 
|  | { | 
|  | String *p; | 
|  | Rune *r; | 
|  | int i, n; | 
|  |  | 
|  | n = utflen(s);	/* don't include NUL */ | 
|  | p = emalloc(sizeof(String)); | 
|  | r = emalloc(n*RUNESIZE); | 
|  | p->s = r; | 
|  | for(i=0; i<n; i++,r++) | 
|  | s += chartorune(r, s); | 
|  | p->n = n; | 
|  | p->size = n; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | void | 
|  | freetmpstr(String *s) | 
|  | { | 
|  | free(s->s); | 
|  | free(s); | 
|  | } |