Line data Source code
1 : /* Copyright (C) 2018 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : #include "pari.h"
16 : #include "paripriv.h"
17 :
18 : /********************************************************************/
19 : /** **/
20 : /** CHARACTER STRINGS **/
21 : /** **/
22 : /********************************************************************/
23 :
24 : /* Utillity functions */
25 : char *
26 41431 : stack_strdup(const char *s)
27 : {
28 41431 : long n = strlen(s)+1;
29 41431 : char *t = stack_malloc(n);
30 41431 : memcpy(t,s,n); return t;
31 : }
32 : char *
33 1211 : stack_strcat(const char *s, const char *t)
34 : {
35 1211 : long ls = strlen(s), lt = strlen(t);
36 1211 : long n = ls + lt + 1;
37 1211 : char *u = stack_malloc(n);
38 1211 : memcpy(u, s, ls);
39 1211 : memcpy(u + ls,t, lt+1); return u;
40 : }
41 :
42 : char *
43 38076 : pari_strdup(const char *s)
44 : {
45 38076 : long n = strlen(s)+1;
46 38076 : char *t = (char*)pari_malloc(n);
47 38076 : memcpy(t,s,n); return t;
48 : }
49 : char *
50 5767 : pari_strndup(const char *s, long n)
51 : {
52 5767 : char *t = (char*)pari_malloc(n+1);
53 5767 : memcpy(t,s,n); t[n] = 0; return t;
54 : }
55 :
56 : /* return the first n0 chars of s as a GEN [s may not be 0-terminated] */
57 : GEN
58 958255 : strntoGENstr(const char *s, long n0)
59 : {
60 958255 : long n = nchar2nlong(n0+1); /* +1 for trailing 0 */
61 958255 : GEN x = cgetg(n+1, t_STR);
62 958255 : char *t = GSTR(x);
63 958255 : x[n] = 0; /* avoid uninitialized memory */
64 958255 : strncpy(t, s, n0); t[n0] = 0; return x;
65 : }
66 :
67 : /* strntoGENstr would trigger gcc-8 stringop-truncation warning */
68 : GEN
69 8130257 : strtoGENstr(const char *s)
70 : {
71 8130257 : long n0 = strlen(s) + 1, n = nchar2nlong(n0);
72 8130243 : GEN x = cgetg(n+1, t_STR);
73 8130214 : char *t = GSTR(x);
74 8130214 : x[n] = 0; strncpy(t, s, n0); return x;
75 : }
76 :
77 : GEN
78 340512 : chartoGENstr(char c)
79 : {
80 340512 : GEN x = cgetg(2, t_STR);
81 340512 : char *t = GSTR(x);
82 340512 : t[0] = c; t[1] = 0; return x;
83 : }
84 :
85 : const char *
86 45886 : type_name(long t)
87 : {
88 : const char *s;
89 45886 : switch(t)
90 : {
91 11025 : case t_INT : s="t_INT"; break;
92 4312 : case t_REAL : s="t_REAL"; break;
93 2576 : case t_INTMOD : s="t_INTMOD"; break;
94 595 : case t_FRAC : s="t_FRAC"; break;
95 2583 : case t_FFELT : s="t_FFELT"; break;
96 1771 : case t_COMPLEX: s="t_COMPLEX"; break;
97 896 : case t_PADIC : s="t_PADIC"; break;
98 1113 : case t_QUAD : s="t_QUAD"; break;
99 1358 : case t_POLMOD : s="t_POLMOD"; break;
100 3364 : case t_POL : s="t_POL"; break;
101 679 : case t_SER : s="t_SER"; break;
102 42 : case t_RFRAC : s="t_RFRAC"; break;
103 147 : case t_QFB : s="t_QFB"; break;
104 8306 : case t_VEC : s="t_VEC"; break;
105 3724 : case t_COL : s="t_COL"; break;
106 2310 : case t_MAT : s="t_MAT"; break;
107 91 : case t_LIST : s="t_LIST"; break;
108 469 : case t_STR : s="t_STR"; break;
109 238 : case t_VECSMALL:s="t_VECSMALL";break;
110 50 : case t_CLOSURE: s="t_CLOSURE"; break;
111 216 : case t_ERROR: s="t_ERROR"; break;
112 21 : case t_INFINITY:s="t_INFINITY";break;
113 : default: pari_err_BUG("type"); s = NULL; /* LCOV_EXCL_LINE */
114 : }
115 45886 : return s;
116 : }
117 :
118 : GEN
119 31804 : type0(GEN x)
120 : {
121 31804 : const char *s = type_name(typ(x));
122 31804 : return strtoGENstr(s);
123 : }
124 :
125 : static char
126 1960 : ltoc(long n) {
127 1960 : if (n <= 0 || n > 255)
128 7 : pari_err(e_MISC, "out of range in integer -> character conversion (%ld)", n);
129 1953 : return (char)n;
130 : }
131 : static char
132 91 : itoc(GEN x) { return ltoc(gtos(x)); }
133 :
134 : GEN
135 28 : pari_strchr(GEN g)
136 : {
137 28 : long i, l, len, t = typ(g);
138 : char *s;
139 : GEN x;
140 28 : if (is_vec_t(t)) {
141 7 : l = lg(g); len = nchar2nlong(l);
142 7 : x = cgetg(len+1, t_STR); s = GSTR(x);
143 91 : for (i=1; i<l; i++) *s++ = itoc(gel(g,i));
144 : }
145 21 : else if (t == t_VECSMALL)
146 : {
147 14 : l = lg(g); len = nchar2nlong(l);
148 14 : x = cgetg(len+1, t_STR); s = GSTR(x);
149 1883 : for (i=1; i<l; i++) *s++ = ltoc(g[i]);
150 : }
151 : else
152 7 : return chartoGENstr(itoc(g));
153 21 : *s = 0; return x;
154 : }
155 :
156 : GEN
157 70 : strsplit(GEN x, GEN p)
158 : {
159 : long i0, i, iv, ls, lt;
160 : char *s, *t;
161 : GEN v;
162 70 : if (typ(x) != t_STR) pari_err_TYPE("strsplit",x);
163 63 : s = GSTR(x); ls = strlen(s);
164 63 : if (!p) lt = 0;
165 : else
166 : {
167 56 : if (typ(p) != t_STR) pari_err_TYPE("strsplit",p);
168 49 : t = GSTR(p); lt = strlen(t);
169 : }
170 56 : if (!lt) /* empty separator: split by char */
171 : {
172 14 : v = cgetg(ls+1, t_VEC);
173 56 : for (i = 1; i <= ls; i++) gel(v,i) = chartoGENstr(s[i-1]);
174 14 : return v;
175 : }
176 42 : v = cgetg(ls + 2, t_VEC); iv = 1;
177 33957 : for (i = i0 = 0; i < ls; i++)
178 35189 : while (!strncmp(s + i, t, lt))
179 : {
180 1274 : gel(v, iv++) = strntoGENstr(s + i0, i - i0);
181 1274 : i += lt; i0 = i;
182 : }
183 42 : gel(v, iv++) = strntoGENstr(s + i0, i - i0);
184 42 : stackdummy((pari_sp)(v + iv), (pari_sp)(v + ls + 2));
185 42 : setlg(v, iv); return v;
186 : }
187 :
188 : GEN
189 63 : strjoin(GEN v, GEN p)
190 : {
191 63 : pari_sp av = avma;
192 : long i, l;
193 : GEN w;
194 63 : if (!is_vec_t(typ(v))) pari_err_TYPE("strjoin",v);
195 56 : if (p && typ(p) != t_STR) pari_err_TYPE("strjoin",p);
196 49 : l = lg(v);
197 49 : if (l == 1) return strtoGENstr("");
198 42 : if (l == 2)
199 : {
200 14 : char *s = GENtostr_unquoted(gel(v,1));
201 14 : return gerepileuptoleaf(av, strtoGENstr(s));
202 : }
203 28 : if (!p) p = strtoGENstr("");
204 28 : w = cgetg(2*l - 2, t_VEC);
205 28 : gel(w, 1) = gel(v, 1);
206 1225 : for (i = 2; i < l; i++)
207 : {
208 1197 : gel(w, 2*i-2) = p;
209 1197 : gel(w, 2*i-1) = gel(v, i);
210 : }
211 28 : return gerepileuptoleaf(av, shallowconcat1(w));
212 : }
213 :
214 : GEN
215 0 : pari_base64(const char *s)
216 : {
217 : static const char *base64 =
218 : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
219 0 : long i, j, ls = strlen(s), lt = ((ls+2)/3)*4;
220 0 : long n = nchar2nlong(lt+1);
221 0 : GEN g = cgetg(1+n, t_STR);
222 0 : char *t = GSTR(g);
223 0 : g[n] = 0L;
224 0 : for(i=j=0; i < ls; i+=3, j+=4)
225 : {
226 0 : char s0 = s[i], s1 = i+1<ls ? s[i+1]: 0, s2 = i+2<ls ? s[i+2]: 0;
227 0 : t[j] = base64[(s0 & 0xfc) >> 2];
228 0 : t[j+1] = base64[((s0 & 0x3) << 4) + ((s1 & 0xf0) >> 4)];
229 0 : t[j+2] = i+1<ls ? base64[((s1 & 0xf) << 2) + ((s2 & 0xc0) >> 6)]: '=';
230 0 : t[j+3] = i+2<ls ? base64[s2 & 0x3f]: '=';
231 : }
232 0 : return g;
233 : }
|