/libinterp/string.c

https://gitlab.com/BGCX261/znos-git · C · 612 lines · 532 code · 80 blank · 0 comment · 132 complexity · 45734bfe9b2a96a88ba58a9561aca08b MD5 · raw file

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