History

20121205-1740

forsyth committed 13 years ago

Commit 63a80ccNo parent (first commit)9462 files · +1777217 −-3784Browse files

Showing the changes to libinterp/string.c (1 of 9462 files). Show all

Unified · Split

libinterp/string.c+616−0
@@ -0,0 +1,616 @@
1+#include "lib9.h"
2+#include "isa.h"
3+#include "interp.h"
4+#include "raise.h"
5+#include "pool.h"
6+
7+#define OP(fn) void fn(void)
8+#define B(r) *((BYTE*)(R.r))
9+#define W(r) *((WORD*)(R.r))
10+#define F(r) *((REAL*)(R.r))
11+#define V(r) *((LONG*)(R.r))
12+#define S(r) *((String**)(R.r))
13+#define A(r) *((Array**)(R.r))
14+#define L(r) *((List**)(R.r))
15+#define P(r) *((WORD**)(R.r))
16+#define C(r) *((Channel**)(R.r))
17+#define T(r) *((void**)(R.r))
18+
19+OP(indc)
20+{
21+ int l;
22+ ulong v;
23+ String *ss;
24+
25+ v = W(m);
26+ ss = S(s);
27+
28+ if(ss == H)
29+ error(exNilref);
30+
31+ l = ss->len;
32+ if(l < 0) {
33+ if(v >= -l)
34+e: error(exBounds);
35+ l = ss->Srune[v];
36+ }
37+ else {
38+ if(v >= l)
39+ goto e;
40+ l = ss->Sascii[v];
41+ }
42+ W(d) = l;
43+}
44+
45+OP(insc)
46+{
47+ ulong v;
48+ int l, r, expand;
49+ String *ss, *ns, **sp;
50+
51+ r = W(s);
52+ v = W(m);
53+ ss = S(d);
54+
55+ expand = r >= Runeself;
56+
57+ if(ss == H) {
58+ ss = newstring(0);
59+ if(expand) {
60+ l = 0;
61+ ss->max /= sizeof(Rune);
62+ goto r;
63+ }
64+ }
65+ else
66+ if(D2H(ss)->ref > 1 || (expand && ss->len > 0))
67+ ss = splitc(R.d, expand);
68+
69+ l = ss->len;
70+ if(l < 0 || expand) {
71+ l = -l;
72+r:
73+ if(v < l)
74+ ss->Srune[v] = r;
75+ else
76+ if(v == l && v < ss->max) {
77+ ss->len = -(v+1);
78+ ss->Srune[v] = r;
79+ }
80+ else {
81+ if(v != l)
82+ error(exBounds);
83+ ns = newstring((v + 1 + v/4)*sizeof(Rune));
84+ memmove(ns->Srune, ss->Srune, -ss->len*sizeof(Rune));
85+ ns->Srune[v] = r;
86+ ns->len = -(v+1);
87+ ns->max /= sizeof(Rune);
88+ ss = ns;
89+ }
90+ }
91+ else {
92+ if(v < l)
93+ ss->Sascii[v] = r;
94+ else
95+ if(v == l && v < ss->max) {
96+ ss->len = v+1;
97+ ss->Sascii[v] = r;
98+ }
99+ else {
100+ if(v != l)
101+ error(exBounds);
102+ ns = newstring(v + 1 + v/4);
103+ memmove(ns->Sascii, ss->Sascii, l);
104+ ns->Sascii[v] = r;
105+ ns->len = v+1;
106+ ss = ns;
107+ }
108+ }
109+ if(ss != S(d)) {
110+ sp = R.d;
111+ destroy(*sp);
112+ *sp = ss;
113+ }
114+}
115+
116+String*
117+slicer(ulong start, ulong v, String *ds)
118+{
119+ String *ns;
120+ int l, nc;
121+
122+ if(ds == H) {
123+ if(start == 0 && v == 0)
124+ return H;
125+
126+ error(exBounds);
127+ }
128+
129+ nc = v - start;
130+ if(ds->len < 0) {
131+ l = -ds->len;
132+ if(v < start || v > l)
133+ error(exBounds);
134+ if(nc == 0)
135+ return H;
136+ ns = newrunes(nc);
137+ memmove(ns->Srune, &ds->Srune[start], nc*sizeof(Rune));
138+ }
139+ else {
140+ l = ds->len;
141+ if(v < start || v > l)
142+ error(exBounds);
143+ if(nc == 0)
144+ return H;
145+ ns = newstring(nc);
146+ memmove(ns->Sascii, &ds->Sascii[start], nc);
147+ }
148+
149+ return ns;
150+}
151+
152+OP(slicec)
153+{
154+ String *ns, **sp;
155+
156+ ns = slicer(W(s), W(m), S(d));
157+ sp = R.d;
158+ destroy(*sp);
159+ *sp = ns;
160+}
161+
162+void
163+cvtup(Rune *r, String *s)
164+{
165+ uchar *bp, *ep;
166+
167+ bp = (uchar*)s->Sascii;
168+ ep = bp + s->len;
169+ while(bp < ep)
170+ *r++ = *bp++;
171+}
172+
173+String*
174+addstring(String *s1, String *s2, int append)
175+{
176+ Rune *r;
177+ String *ns;
178+ int l, l1, l2;
179+
180+ if(s1 == H) {
181+ if(s2 == H)
182+ return H;
183+ return stringdup(s2);
184+ }
185+ if(D2H(s1)->ref > 1)
186+ append = 0;
187+ if(s2 == H) {
188+ if(append)
189+ return s1;
190+ return stringdup(s1);
191+ }
192+
193+ if(s1->len < 0) {
194+ l1 = -s1->len;
195+ if(s2->len < 0)
196+ l = l1 - s2->len;
197+ else
198+ l = l1 + s2->len;
199+ if(append && l <= s1->max)
200+ ns = s1;
201+ else {
202+ ns = newrunes(append? (l+l/4): l);
203+ memmove(ns->Srune, s1->Srune, l1*sizeof(Rune));
204+ }
205+ ns->len = -l;
206+ r = &ns->Srune[l1];
207+ if(s2->len < 0)
208+ memmove(r, s2->Srune, -s2->len*sizeof(Rune));
209+ else
210+ cvtup(r, s2);
211+
212+ return ns;
213+ }
214+
215+ if(s2->len < 0) {
216+ l2 = -s2->len;
217+ l = s1->len + l2;
218+ ns = newrunes(append? (l+l/4): l);
219+ ns->len = -l;
220+ cvtup(ns->Srune, s1);
221+ memmove(&ns->Srune[s1->len], s2->Srune, l2*sizeof(Rune));
222+ return ns;
223+ }
224+
225+ l1 = s1->len;
226+ l = l1 + s2->len;
227+ if(append && l <= s1->max)
228+ ns = s1;
229+ else {
230+ ns = newstring(append? (l+l/4): l);
231+ memmove(ns->Sascii, s1->Sascii, l1);
232+ }
233+ ns->len = l;
234+ memmove(ns->Sascii+l1, s2->Sascii, s2->len);
235+
236+ return ns;
237+}
238+
239+OP(addc)
240+{
241+ String *ns, **sp;
242+
243+ ns = addstring(S(m), S(s), R.m == R.d);
244+
245+ sp = R.d;
246+ if(ns != *sp) {
247+ destroy(*sp);
248+ *sp = ns;
249+ }
250+}
251+
252+OP(cvtca)
253+{
254+ int l;
255+ Rune *r;
256+ char *p;
257+ String *ss;
258+ Array *a, **ap;
259+
260+ ss = S(s);
261+ if(ss == H) {
262+ a = mem2array(nil, 0);
263+ goto r;
264+ }
265+ if(ss->len < 0) {
266+ l = -ss->len;
267+ a = mem2array(nil, runenlen(ss->Srune, l));
268+ p = (char*)a->data;
269+ r = ss->Srune;
270+ while(l--)
271+ p += runetochar(p, r++);
272+ goto r;
273+ }
274+ a = mem2array(ss->Sascii, ss->len);
275+
276+r: ap = R.d;
277+ destroy(*ap);
278+ *ap = a;
279+}
280+
281+OP(cvtac)
282+{
283+ Array *a;
284+ String *ds, **dp;
285+
286+ ds = H;
287+ a = A(s);
288+ if(a != H)
289+ ds = c2string((char*)a->data, a->len);
290+
291+ dp = R.d;
292+ destroy(*dp);
293+ *dp = ds;
294+}
295+
296+OP(lenc)
297+{
298+ int l;
299+ String *ss;
300+
301+ l = 0;
302+ ss = S(s);
303+ if(ss != H) {
304+ l = ss->len;
305+ if(l < 0)
306+ l = -l;
307+ }
308+ W(d) = l;
309+}
310+
311+OP(cvtcw)
312+{
313+ String *s;
314+
315+ s = S(s);
316+ if(s == H)
317+ W(d) = 0;
318+ else
319+ if(s->len < 0)
320+ W(d) = strtol(string2c(s), nil, 10);
321+ else {
322+ s->Sascii[s->len] = '\0';
323+ W(d) = strtol(s->Sascii, nil, 10);
324+ }
325+}
326+
327+OP(cvtcf)
328+{
329+ String *s;
330+
331+ s = S(s);
332+ if(s == H)
333+ F(d) = 0.0;
334+ else
335+ if(s->len < 0)
336+ F(d) = strtod(string2c(s), nil);
337+ else {
338+ s->Sascii[s->len] = '\0';
339+ F(d) = strtod(s->Sascii, nil);
340+ }
341+}
342+
343+OP(cvtwc)
344+{
345+ String *ds, **dp;
346+
347+ ds = newstring(16);
348+ ds->len = sprint(ds->Sascii, "%d", W(s));
349+
350+ dp = R.d;
351+ destroy(*dp);
352+ *dp = ds;
353+}
354+
355+OP(cvtlc)
356+{
357+ String *ds, **dp;
358+
359+ ds = newstring(16);
360+ ds->len = sprint(ds->Sascii, "%lld", V(s));
361+
362+ dp = R.d;
363+ destroy(*dp);
364+ *dp = ds;
365+}
366+
367+OP(cvtfc)
368+{
369+ String *ds, **dp;
370+
371+ ds = newstring(32);
372+ ds->len = sprint(ds->Sascii, "%g", F(s));
373+ dp = R.d;
374+ destroy(*dp);
375+ *dp = ds;
376+}
377+
378+char*
379+string2c(String *s)
380+{
381+ char *p;
382+ int c, l, nc;
383+ Rune *r, *er;
384+
385+ if(s == H)
386+ return "";
387+
388+ if(s->len >= 0) {
389+ s->Sascii[s->len] = '\0';
390+ return s->Sascii;
391+ }
392+
393+ nc = -s->len;
394+ l = (nc * UTFmax) + UTFmax;
395+ if(s->tmp == nil || msize(s->tmp) < l) {
396+ free(s->tmp);
397+ s->tmp = malloc(l);
398+ if(s->tmp == nil)
399+ error(exNomem);
400+ }
401+
402+ p = s->tmp;
403+ r = s->Srune;
404+ er = r + nc;
405+ while(r < er) {
406+ c = *r++;
407+ if(c < Runeself)
408+ *p++ = c;
409+ else
410+ p += runetochar(p, r-1);
411+ }
412+
413+ *p = 0;
414+
415+ return s->tmp;
416+}
417+
418+String*
419+c2string(char *cs, int len)
420+{
421+ uchar *p;
422+ char *ecs;
423+ String *s;
424+ Rune *r, junk;
425+ int c, nc, isrune;
426+
427+ isrune = 0;
428+ ecs = cs+len;
429+ p = (uchar*)cs;
430+ while(len--) {
431+ c = *p++;
432+ if(c >= Runeself) {
433+ isrune = 1;
434+ break;
435+ }
436+ }
437+
438+ if(isrune == 0) {
439+ nc = ecs - cs;
440+ s = newstring(nc);
441+ memmove(s->Sascii, cs, nc);
442+ return s;
443+ }
444+
445+ p--;
446+ nc = p - (uchar*)cs;
447+ while(p < (uchar*)ecs) {
448+ c = *p;
449+ if(c < Runeself)
450+ p++;
451+ else if(p+UTFmax<=(uchar*)ecs || fullrune((char*)p, (uchar*)ecs-p))
452+ p += chartorune(&junk, (char*)p);
453+ else
454+ break;
455+ nc++;
456+ }
457+ s = newrunes(nc);
458+ r = s->Srune;
459+ while(nc--)
460+ cs += chartorune(r++, cs);
461+
462+ return s;
463+}
464+
465+String*
466+newstring(int nb)
467+{
468+ Heap *h;
469+ String *s;
470+
471+ h = nheap(sizeof(String)+nb);
472+ h->t = &Tstring;
473+ Tstring.ref++;
474+ s = H2D(String*, h);
475+ s->tmp = nil;
476+ s->len = nb;
477+ s->max = hmsize(h) - (sizeof(String)+sizeof(Heap));
478+ return s;
479+}
480+
481+String*
482+newrunes(int nr)
483+{
484+ Heap *h;
485+ String *s;
486+
487+ if(nr == 0)
488+ return newstring(nr);
489+ if(nr < 0)
490+ nr = -nr;
491+ h = nheap(sizeof(String)+nr*sizeof(Rune));
492+ h->t = &Tstring;
493+ Tstring.ref++;
494+ s = H2D(String*, h);
495+ s->tmp = nil;
496+ s->len = -nr;
497+ s->max = (hmsize(h) - (sizeof(String)+sizeof(Heap)))/sizeof(Rune);
498+ return s;
499+}
500+
501+String*
502+stringdup(String *s)
503+{
504+ String *ns;
505+
506+ if(s == H)
507+ return H;
508+
509+ if(s->len >= 0) {
510+ ns = newstring(s->len);
511+ memmove(ns->Sascii, s->Sascii, s->len);
512+ return ns;
513+ }
514+
515+ ns = newrunes(-s->len);
516+ memmove(ns->Srune, s->Srune,-s->len*sizeof(Rune));
517+
518+ return ns;
519+}
520+
521+int
522+stringcmp(String *s1, String *s2)
523+{
524+ Rune *r1, *r2;
525+ char *a1, *a2;
526+ int v, n, n1, n2, c1, c2;
527+ static String snil = { 0, 0, nil };
528+
529+ if(s1 == H)
530+ s1 = &snil;
531+ if(s2 == H)
532+ s2 = &snil;
533+
534+ if(s1 == s2)
535+ return 0;
536+
537+ v = 0;
538+ n1 = s1->len;
539+ if(n1 < 0) {
540+ n1 = -n1;
541+ v |= 1;
542+ }
543+ n2 = s2->len;
544+ if(n2 < 0) {
545+ n2 = -n2;
546+ v |= 2;
547+ }
548+
549+ n = n1;
550+ if(n2 < n)
551+ n = n2;
552+
553+ switch(v) {
554+ case 0: /* Ascii Ascii */
555+ n = memcmp(s1->Sascii, s2->Sascii, n);
556+ if(n == 0)
557+ n = n1 - n2;
558+ return n;
559+ case 1: /* Rune Ascii */
560+ r1 = s1->Srune;
561+ a2 = s2->Sascii;
562+ while(n > 0) {
563+ c1 = *r1++;
564+ c2 = *a2++;
565+ if(c1 != c2)
566+ goto ne;
567+ n--;
568+ }
569+ break;
570+ case 2: /* Ascii Rune */
571+ a1 = s1->Sascii;
572+ r2 = s2->Srune;
573+ while(n > 0) {
574+ c1 = *a1++;
575+ c2 = *r2++;
576+ if(c1 != c2)
577+ goto ne;
578+ n--;
579+ }
580+ break;
581+ case 3: /* Rune Rune */
582+ r1 = s1->Srune;
583+ r2 = s2->Srune;
584+ while(n > 0) {
585+ c1 = *r1++;
586+ c2 = *r2++;
587+ if(c1 != c2)
588+ goto ne;
589+ n--;
590+ }
591+ break;
592+ }
593+ return n1 - n2;
594+
595+ne: if(c1 < c2)
596+ return -1;
597+ return 1;
598+}
599+
600+String*
601+splitc(String **s, int expand)
602+{
603+ String *ss, *ns;
604+
605+ ss = *s;
606+ if(expand && ss->len > 0) {
607+ ns = newrunes(ss->len);
608+ cvtup(ns->Srune, ss);
609+ }
610+ else
611+ ns = stringdup(ss);
612+
613+ destroy(ss);
614+ *s = ns;
615+ return ns;
616+}