1 /****************************************************************************
2 **
3 **  This file is part of GAP, a system for computational discrete algebra.
4 **
5 **  Copyright of GAP belongs to its developers, whose names are too numerous
6 **  to list here. Please refer to the COPYRIGHT file for details.
7 **
8 **  SPDX-License-Identifier: GPL-2.0-or-later
9 **
10 **  This file declares the functions which mainly deal with strings.
11 **
12 **  A *string* is a  list that  has no  holes, and  whose  elements  are  all
13 **  characters.  For the full definition of strings see chapter  "Strings" in
14 **  the {\GAP} manual.  Read also "More about Strings" about the  string flag
15 **  and the compact representation of strings.
16 **
17 **  Strings in compact representation  can be accessed and handled through
18 **  the functions 'NEW_STRING', 'CHARS_STRING' (and 'CSTR_STRING'),
19 **  'GET_LEN_STRING', 'SET_LEN_STRING', 'GROW_STRING' and more.
20 */
21 
22 #ifndef GAP_STRINGOBJ_H
23 #define GAP_STRINGOBJ_H
24 
25 #include "objects.h"
26 
27 
28 /****************************************************************************
29 **
30 *F * * * * * * * * * * * * * * character functions  * * * * * * * * * * * * *
31 */
32 
33 
34 /****************************************************************************
35 **
36 *V  ObjsChar[<chr>] . . . . . . . . . . . . . . . . table of character values
37 **
38 **  'ObjsChar' contains all the character values.  That way we do not need to
39 **  allocate new bags for new characters.
40 */
41 extern Obj ObjsChar[256];
42 
43 
44 /****************************************************************************
45 **
46 *F  CHAR_VALUE( <charObj> )
47 */
CHAR_VALUE(Obj charObj)48 EXPORT_INLINE UChar CHAR_VALUE(Obj charObj)
49 {
50     GAP_ASSERT(TNUM_OBJ(charObj) == T_CHAR);
51     return *(const UChar *)CONST_ADDR_OBJ(charObj);
52 }
53 
54 
55 /****************************************************************************
56 **
57 *F  SET_CHAR_VALUE( <charObj>, <c> )
58 */
SET_CHAR_VALUE(Obj charObj,UChar c)59 EXPORT_INLINE void SET_CHAR_VALUE(Obj charObj, UChar c)
60 {
61     GAP_ASSERT(TNUM_OBJ(charObj) == T_CHAR);
62     *(UChar *)ADDR_OBJ(charObj) = c;
63 }
64 
65 
66 /****************************************************************************
67 **
68 *F  SINT_CHAR(a)
69 **
70 **  'SINT_CHAR' converts the character a (a UInt1) into a signed (C) integer.
71 */
SINT_CHAR(UInt1 a)72 EXPORT_INLINE Int SINT_CHAR(UInt1 a)
73 {
74     return a < 128 ? (Int)a : (Int)a-256;
75 }
76 
77 
78 /****************************************************************************
79 **
80 *F  CHAR_SINT(n)
81 **
82 **  'CHAR_SINT' converts the signed (C) integer n into an (UInt1) character.
83 */
CHAR_SINT(Int n)84 EXPORT_INLINE UInt1 CHAR_SINT(Int n)
85 {
86     return (UInt1)(n >= 0 ? n : n+256);
87 }
88 
89 
90 /****************************************************************************
91 **
92 *F * * * * * * * * * * * * * * * string functions * * * * * * * * * * * * * *
93 */
94 
95 /****************************************************************************
96 **
97 *F  IS_STRING_REP( <list> ) . . . . . . . .  check if <list> is in string rep
98 */
IS_STRING_REP(Obj list)99 EXPORT_INLINE Int IS_STRING_REP(Obj list)
100 {
101     return (T_STRING <= TNUM_OBJ(list) &&
102             TNUM_OBJ(list) <= T_STRING_SSORT + IMMUTABLE);
103 }
104 
105 
106 /****************************************************************************
107 **
108 *F  SIZEBAG_STRINGLEN( <len> ) . . . . size of Bag for string of length <len>
109 **
110 */
SIZEBAG_STRINGLEN(UInt len)111 EXPORT_INLINE UInt SIZEBAG_STRINGLEN(UInt len)
112 {
113     return len + 1 + sizeof(UInt);
114 }
115 
116 /****************************************************************************
117 **
118 *F  CSTR_STRING( <list> ) . . . . . . . . . . . . . . .  C string of a string
119 *F  CHARS_STRING( <list> ) . . . . . . . . . . . . . .   same pointer
120 **
121 **  'CSTR_STRING'  returns the (address  of the)  C  character string of  the
122 **  string <list>. 'CHARS_STRING' is the same, but returns a pointer to an
123 **  unsigned char.
124 **
125 **  Remember that GAP strings can contain embedded NULLs, so do not assume
126 **  the string stops at the first null character, instead use
127 **  GET_LEN_STRING.
128 */
129 
CSTR_STRING(Obj list)130 EXPORT_INLINE Char * CSTR_STRING(Obj list)
131 {
132     GAP_ASSERT(IS_STRING_REP(list));
133     return (Char *)ADDR_OBJ(list) + sizeof(UInt);
134 }
135 
CONST_CSTR_STRING(Obj list)136 EXPORT_INLINE const Char * CONST_CSTR_STRING(Obj list)
137 {
138     GAP_ASSERT(IS_STRING_REP(list));
139     return (const Char *)CONST_ADDR_OBJ(list) + sizeof(UInt);
140 }
141 
CHARS_STRING(Obj list)142 EXPORT_INLINE UChar * CHARS_STRING(Obj list)
143 {
144     GAP_ASSERT(IS_STRING_REP(list));
145     return (UChar *)ADDR_OBJ(list) + sizeof(UInt);
146 }
147 
CONST_CHARS_STRING(Obj list)148 EXPORT_INLINE const UChar * CONST_CHARS_STRING(Obj list)
149 {
150     GAP_ASSERT(IS_STRING_REP(list));
151     return (const UChar *)CONST_ADDR_OBJ(list) + sizeof(UInt);
152 }
153 
154 /****************************************************************************
155 **
156 *F  GET_LEN_STRING( <list> )  . . . . . . . . . . . . . .  length of a string
157 **
158 **  'GET_LEN_STRING' returns the length of the string <list>, as a C integer.
159 */
160 
GET_LEN_STRING(Obj list)161 EXPORT_INLINE UInt GET_LEN_STRING(Obj list)
162 {
163     GAP_ASSERT(IS_STRING_REP(list));
164     return INT_INTOBJ(CONST_ADDR_OBJ(list)[0]);
165 }
166 
167 /****************************************************************************
168 **
169 *F  SET_LEN_STRING( <list>, <len> ) . . . . . . . . . set length of a string
170 **
171 **  'SET_LEN_STRING' sets length of the string <list> to C integer <len>.
172 */
173 
SET_LEN_STRING(Obj list,Int len)174 EXPORT_INLINE void SET_LEN_STRING(Obj list, Int len)
175 {
176     GAP_ASSERT(IS_STRING_REP(list));
177     GAP_ASSERT(len >= 0);
178     GAP_ASSERT(SIZEBAG_STRINGLEN(len) <= SIZE_OBJ(list));
179     ADDR_OBJ(list)[0] = INTOBJ_INT(len);
180 }
181 
182 /****************************************************************************
183 **
184 *F  NEW_STRING( <len> ) . . . . . . . . . . . . . . . . . . make a new string
185 **
186 **  'NEW_STRING' returns a new string with room for <len> characters. It also
187 **  sets its length to len.
188 **
189 */
190 Obj NEW_STRING(Int len);
191 
192 /****************************************************************************
193 **
194 *F  GROW_STRING(<list>, <len>) . . . .  make sure a string is large enough
195 **
196 **  'GROW_STRING' grows  the string <list>  if necessary to ensure that it
197 **  has room for at least <len> elements.
198 **
199 */
200 
201 Int GrowString(Obj list, UInt need);
202 
GROW_STRING(Obj list,Int len)203 EXPORT_INLINE void GROW_STRING(Obj list, Int len)
204 {
205     GAP_ASSERT(IS_STRING_REP(list));
206     GAP_ASSERT(len >= 0);
207     if (SIZEBAG_STRINGLEN(len) > SIZE_OBJ(list)) {
208         GrowString(list, len);
209     }
210 }
211 
212 /****************************************************************************
213 **
214 *F  SHRINK_STRING(<list>) . . . . . . . . .  shrink a string to minimal size
215 **
216 **  'SHRINK_STRING' gives back not needed memory allocated by string.
217 */
SHRINK_STRING(Obj list)218 EXPORT_INLINE void SHRINK_STRING(Obj list)
219 {
220     GAP_ASSERT(IS_STRING_REP(list));
221     ResizeBag(list, SIZEBAG_STRINGLEN(GET_LEN_STRING((list))));
222 }
223 
224 /****************************************************************************
225 **
226 *F  COPY_CHARS( <str>, <charpnt>, <n> ) . . . copies <n> chars, starting
227 **  from character pointer <charpnt>, to beginning of string
228 **
229 **  It assumes that the data area in <str> is large enough. It does not add
230 **  a terminating null character and not change the length of the string.
231 */
COPY_CHARS(Obj str,const UChar * pnt,Int n)232 EXPORT_INLINE void COPY_CHARS(Obj str, const UChar * pnt, Int n)
233 {
234     GAP_ASSERT(IS_STRING_REP(str));
235     GAP_ASSERT(n >= 0);
236     GAP_ASSERT(SIZEBAG_STRINGLEN(n) <= SIZE_OBJ(str));
237     memcpy(CHARS_STRING(str), pnt, n);
238 }
239 
240 /****************************************************************************
241 **
242 *F  PrintString( <list> ) . . . . . . . . . . . . . . . . . .  print a string
243 **
244 **  'PrintString' prints the string with the handle <list>.
245 **
246 **  No  linebreaks are allowed,  if one must be  inserted  anyhow, it must be
247 **  escaped by a backslash '\', which is done in 'Pr'.
248 */
249 void PrintString(Obj list);
250 
251 
252 /****************************************************************************
253 **
254 *F  PrintString1( <list> )  . . . . . . . . . . .  print a string for 'Print'
255 **
256 **  'PrintString1' prints the string  constant  in  the  format  used  by  the
257 **  'Print' and 'PrintTo' function.
258 */
259 void PrintString1(Obj list);
260 
261 
262 /****************************************************************************
263 **
264 *F  IS_STRING( <obj> )  . . . . . . . . . . . . test if an object is a string
265 **
266 **  'IS_STRING' returns 1  if the object <obj>  is a string  and 0 otherwise.
267 **  It does not change the representation of <obj>.
268 */
269 extern  Int             (*IsStringFuncs [LAST_REAL_TNUM+1]) ( Obj obj );
270 
IS_STRING(Obj obj)271 EXPORT_INLINE Int IS_STRING(Obj obj)
272 {
273     return (*IsStringFuncs[TNUM_OBJ(obj)])(obj);
274 }
275 
276 
277 /****************************************************************************
278 **
279 *F  IsString( <obj> ) . . . . . . . . . . . . . test if an object is a string
280 **
281 **  'IsString' returns 1 if the object <obj> is a string and 0 otherwise.  It
282 **  does not change the representation of <obj>.
283 */
284 Int IsString(Obj obj);
285 
286 
287 /****************************************************************************
288 **
289 *F  CopyToStringRep( <string> ) . . .  copy a string to string representation
290 **
291 **  'CopyToStringRep' copies the string <string> to a new mutable string in
292 **  string representation.
293 */
294 Obj CopyToStringRep(Obj string);
295 
296 
297 /****************************************************************************
298 **
299 *F  ImmutableString( <string> ) . . . copy to immutable string in string rep.
300 **
301 **  'ImmutableString' returns an immutable string in string representation
302 **  equal to <string>. This may return <string> if it already satisfies these
303 **  criteria.
304 */
305 Obj ImmutableString(Obj string);
306 
307 
308 /****************************************************************************
309 **
310 *F  ConvString( <string> ) . . . .  convert a string to string representation
311 **
312 **  'ConvString' converts the string <string> to string representation.
313 */
314 void ConvString(Obj string);
315 
316 
317 /****************************************************************************
318 **
319 *F  IsStringConv( <obj> ) . . . . . test if an object is a string and convert
320 **
321 **  'IsStringConv'   returns 1  if   the object <obj>  is   a  string,  and 0
322 **  otherwise.   If <obj> is a  string it  changes  its representation to the
323 **  string representation.
324 */
325 Int IsStringConv(Obj obj);
326 
327 
328 // Functions to create mutable and immutable GAP strings from C strings.
329 // MakeString and MakeImmString are inlineable so 'strlen' can be optimised
330 // away for constant strings.
331 
MakeStringWithLen(const char * buf,size_t len)332 EXPORT_INLINE Obj MakeStringWithLen(const char * buf, size_t len)
333 {
334     Obj result = NEW_STRING(len);
335     memcpy(CHARS_STRING(result), buf, len);
336     return result;
337 }
338 
MakeString(const char * cstr)339 EXPORT_INLINE Obj MakeString(const char * cstr)
340 {
341     return MakeStringWithLen(cstr, strlen(cstr));
342 }
343 
MakeImmString(const char * cstr)344 EXPORT_INLINE Obj MakeImmString(const char * cstr)
345 {
346     Obj result = MakeString(cstr);
347     MakeImmutableNoRecurse(result);
348     return result;
349 }
350 
MakeImmStringWithLen(const char * buf,size_t len)351 EXPORT_INLINE Obj MakeImmStringWithLen(const char * buf, size_t len)
352 {
353     Obj result = MakeStringWithLen(buf, len);
354     MakeImmutableNoRecurse(result);
355     return result;
356 }
357 
358 
359 /****************************************************************************
360 **
361 *F  C_NEW_STRING( <string>, <len>, <cstring> )  . . . . . . create GAP string
362 **
363 **  This macro is deprecated and only provided for backwards compatibility
364 **  with some package kernel extensions. Use 'MakeStringWithLen' and
365 **  'MakeImmStringWithLen' instead.
366 */
367 #define C_NEW_STRING(string,len,cstr) \
368     string = MakeStringWithLen( (cstr), (len) )
369 
370 
371 /****************************************************************************
372 **
373 *F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
374 */
375 
376 /****************************************************************************
377 **
378 *F  InitInfoString()  . . . . . . . . . . . . . . . . table of init functions
379 */
380 StructInitInfo * InitInfoString ( void );
381 
382 
383 #endif // GAP_STRINGOBJ_H
384