1 #include "sam.h"
2 
3 #define	MINSIZE	16		/* minimum number of chars allocated */
4 #define	MAXSIZE	256		/* maximum number of chars for an empty string */
5 
6 
7 void
Strinit(String * p)8 Strinit(String *p)
9 {
10 	p->s = emalloc(MINSIZE*RUNESIZE);
11 	p->n = 0;
12 	p->size = MINSIZE;
13 }
14 
15 void
Strinit0(String * p)16 Strinit0(String *p)
17 {
18 	p->s = emalloc(MINSIZE*RUNESIZE);
19 	p->s[0] = 0;
20 	p->n = 1;
21 	p->size = MINSIZE;
22 }
23 
24 void
Strclose(String * p)25 Strclose(String *p)
26 {
27 	free(p->s);
28 }
29 
30 void
Strzero(String * p)31 Strzero(String *p)
32 {
33 	if(p->size > MAXSIZE){
34 		p->s = erealloc(p->s, RUNESIZE*MAXSIZE); /* throw away the garbage */
35 		p->size = MAXSIZE;
36 	}
37 	p->n = 0;
38 }
39 
40 int
Strlen(Rune * r)41 Strlen(Rune *r)
42 {
43 	Rune *s;
44 
45 	for(s=r; *s; s++)
46 		;
47 	return s-r;
48 }
49 
50 void
Strdupl(String * p,Rune * s)51 Strdupl(String *p, Rune *s)	/* copies the null */
52 {
53 	p->n = Strlen(s)+1;
54 	Strinsure(p, p->n);
55 	memmove(p->s, s, p->n*RUNESIZE);
56 }
57 
58 void
Strduplstr(String * p,String * q)59 Strduplstr(String *p, String *q)	/* will copy the null if there's one there */
60 {
61 	Strinsure(p, q->n);
62 	p->n = q->n;
63 	memmove(p->s, q->s, q->n*RUNESIZE);
64 }
65 
66 void
Straddc(String * p,int c)67 Straddc(String *p, int c)
68 {
69 	Strinsure(p, p->n+1);
70 	p->s[p->n++] = c;
71 }
72 
73 void
Strinsure(String * p,ulong n)74 Strinsure(String *p, ulong n)
75 {
76 	if(n > STRSIZE)
77 		error(Etoolong);
78 	if(p->size < n){	/* p needs to grow */
79 		n += 100;
80 		p->s = erealloc(p->s, n*RUNESIZE);
81 		p->size = n;
82 	}
83 }
84 
85 void
Strinsert(String * p,String * q,Posn p0)86 Strinsert(String *p, String *q, Posn p0)
87 {
88 	Strinsure(p, p->n+q->n);
89 	memmove(p->s+p0+q->n, p->s+p0, (p->n-p0)*RUNESIZE);
90 	memmove(p->s+p0, q->s, q->n*RUNESIZE);
91 	p->n += q->n;
92 }
93 
94 void
Strdelete(String * p,Posn p1,Posn p2)95 Strdelete(String *p, Posn p1, Posn p2)
96 {
97 	memmove(p->s+p1, p->s+p2, (p->n-p2)*RUNESIZE);
98 	p->n -= p2-p1;
99 }
100 
101 int
Strcmp(String * a,String * b)102 Strcmp(String *a, String *b)
103 {
104 	int i, c;
105 
106 	for(i=0; i<a->n && i<b->n; i++)
107 		if(c = (a->s[i] - b->s[i]))	/* assign = */
108 			return c;
109 	/* damn NULs confuse everything */
110 	i = a->n - b->n;
111 	if(i == 1){
112 		if(a->s[a->n-1] == 0)
113 			return 0;
114 	}else if(i == -1){
115 		if(b->s[b->n-1] == 0)
116 			return 0;
117 	}
118 	return i;
119 }
120 
121 int
Strispre(String * a,String * b)122 Strispre(String *a, String *b)
123 {
124 	int i;
125 
126 	for(i=0; i<a->n && i<b->n; i++){
127 		if(a->s[i] - b->s[i]){	/* assign = */
128 			if(a->s[i] == 0)
129 				return 1;
130 			return 0;
131 		}
132 	}
133 	return i == a->n;
134 }
135 
136 char*
Strtoc(String * s)137 Strtoc(String *s)
138 {
139 	int i;
140 	char *c, *d;
141 	Rune *r;
142 	c = emalloc(s->n*UTFmax + 1);  /* worst case UTFmax bytes per rune, plus NUL */
143 	d = c;
144 	r = s->s;
145 	for(i=0; i<s->n; i++)
146 		d += runetochar(d, r++);
147 	if(d==c || d[-1]!=0)
148 		*d = 0;
149 	return c;
150 
151 }
152 
153 /*
154  * Build very temporary String from Rune*
155  */
156 String*
tmprstr(Rune * r,int n)157 tmprstr(Rune *r, int n)
158 {
159 	static String p;
160 
161 	p.s = r;
162 	p.n = n;
163 	p.size = n;
164 	return &p;
165 }
166 
167 /*
168  * Convert null-terminated char* into String
169  */
170 String*
tmpcstr(char * s)171 tmpcstr(char *s)
172 {
173 	String *p;
174 	Rune *r;
175 	int i, n;
176 
177 	n = utflen(s);	/* don't include NUL */
178 	p = emalloc(sizeof(String));
179 	r = emalloc(n*RUNESIZE);
180 	p->s = r;
181 	for(i=0; i<n; i++,r++)
182 		s += chartorune(r, s);
183 	p->n = n;
184 	p->size = n;
185 	return p;
186 }
187 
188 void
freetmpstr(String * s)189 freetmpstr(String *s)
190 {
191 	free(s->s);
192 	free(s);
193 }
194