1 /*************************************************************************
2  *  TinyFugue - programmable mud client
3  *  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2002, 2003, 2004, 2005, 2006-2007 Ken Keys
4  *
5  *  TinyFugue (aka "tf") is protected under the terms of the GNU
6  *  General Public License.  See the file "COPYING" for details.
7  ************************************************************************/
8 
9 #ifndef DSTRING_H
10 #define DSTRING_H
11 
12 #define ALLOCSIZE		(32L)
13 
14 typedef struct String {
15     char *data;			/* pointer to space holding text */
16     int len;			/* length of actual data (not counting NUL) */
17     int size;			/* length allocated */
18     short links;		/* number of pointers to this structure */
19     unsigned int static_struct: 1;	/* is struct static (not automatic)? */
20     unsigned int dynamic_struct: 1;	/* was struct malloc'd? */
21     unsigned int dynamic_data: 1;	/* was data malloc'd? */
22     /* unsigned dynamic_charattrs:1; */	/* charattrs is always dynamic */
23     unsigned int resizable: 1;		/* can data be resized? */
24     attr_t attrs;		/* whole-line attributes */
25     cattr_t *charattrs;		/* per-character attributes */
26     struct timeval time;	/* timestamp */
27 #if USE_MMALLOC		/* don't waste the space if not using mmalloc */
28     void *md;			/* mmalloc descriptor */
29 #endif
30     const char *file;
31     int line;
32 } String, Stringp[1];
33 
34 /* A conString is a String with const *data and *charattrs. */
35 typedef struct conString {
36     const char *data;		/* pointer to space holding text */
37     int len;			/* length of actual data (not counting NUL) */
38     int size;			/* length allocated */
39     short links;		/* number of pointers to this structure */
40     unsigned int static_struct: 1;	/* is struct static (not automatic)? */
41     unsigned int dynamic_struct: 1;	/* was struct malloc'd? */
42     unsigned int dynamic_data: 1;	/* was data malloc'd? */
43     /* unsigned dynamic_charattrs:1; */	/* charattrs is always dynamic */
44     unsigned int resizable: 1;		/* can data be resized? */
45     attr_t attrs;		/* whole-line attributes */
46     const cattr_t *charattrs;	/* per-character attributes */
47     struct timeval time;	/* timestamp */
48 #if USE_MMALLOC		/* don't waste the space if not using mmalloc */
49     void *md;			/* mmalloc descriptor */
50 #endif
51     const char *file;
52     int line;
53 } conString;
54 
55 /* safely cast String* to conString* */
CS(String * s)56 static inline conString *CS(String *s) { return (conString*)s; }
57 
58 #if USE_MMALLOC
59 # define MD_INIT	NULL,
60 #else
61 # define MD_INIT	/* blank */
62 #endif
63 
64 #define STRING_LITERAL_ATTR(data, attrs) \
65     { (data), sizeof(data)-1, sizeof(data), 1, 1,0,0,0, \
66 	attrs, NULL, { -1, -1 }, MD_INIT __FILE__, __LINE__ }
67 #define STRING_LITERAL(data) STRING_LITERAL_ATTR(data, 0)
68 #define STRING_NULL \
69     { NULL, 0, 0, 1, 1,0,0,0, \
70 	0, NULL, { -1, -1 }, MD_INIT __FILE__, __LINE__ }
71 
72 /* AUTO_BUFFER: The structure is allocated automatically in a function's
73  * (file's) scope; if it is used, it must be Stringfree()'d before
74  * before function (program) exit, and it it safe to Stringfree() even if
75  * it wasn't used.  Its data may be modifed and resized.
76  */
77 # define AUTO_BUFFER(name) \
78      Stringp (name) = {{ NULL, 0, 0, 1, 0,0,1,1, \
79 	0, NULL, { -1, -1 }, MD_INIT __FILE__, __LINE__ }}
80 
81 /* STATIC_BUFFER: The structure has static storage, and its data is allocated
82  * the first time it's needed, but not freed, and reused after that to save
83  * time.  It never needs to be Stringfree()'d.  Its data may be
84  * modified and resized.  Not reentrant-safe.
85  */
86 #define STATIC_BUFFER_INIT \
87     {{ NULL, 0, 0, 1, 1,0,1,1, 0, NULL, { -1,-1 }, MD_INIT __FILE__, __LINE__ }}
88 #define STATIC_BUFFER(name) \
89     static Stringp (name) = STATIC_BUFFER_INIT
90 
91 /* STATIC_STRING: The structure and data have static storage.  It can never
92  * be modified or resized.
93  */
94 #define STATIC_STRING(name, sl, attrs) \
95     static conString (name)[1] = \
96         {{ (sl), sizeof(sl)-1, sizeof(sl), 1, 1,0,0,0, \
97 	    (attrs), NULL, {-1,-1}, MD_INIT __FILE__, __LINE__ }}
98 
99 
100 /* String*init() sets links=1 to indicate the implicit ownership by whoever
101  * created the structure.
102  */
103 #define Stringdup(src) \
104     SStringcpy(Stringnew(NULL, -1, 0), (src))
105 #define Stringodup(src, start) \
106     SStringocat(Stringnew(NULL, -1, 0), (src), (start))
107 #define StringnewM(data, len, attrs, arena) \
108     dSinit(NULL, (data), (len), (attrs), (arena), __FILE__, __LINE__)
109 #define Stringnew(data, len, attrs) \
110     StringnewM(data, len, attrs, NULL)
111 #define Stringinit(str) \
112     ((void)(dSinit((str), NULL, 0, 0, NULL, __FILE__, __LINE__)->links++))
113 #define Stringninit(str, size) \
114     ((void)(dSinit((str), NULL, (size), 0, NULL, __FILE__, __LINE__)->links++))
115 #define Stringzero(str)		Stringninit((str), 0)
116 
117 #define Stringfree(str)		Stringfree_fl(str, __FILE__, __LINE__)
118 #define Stringfree_fl(str, file, line) \
119     do { \
120 	String *temp = (str);  /* must evaluate str exactly once */ \
121 	if (--temp->links <= 0) dSfree(temp, (file), (line)); \
122     } while (0)
123 
124 #define conStringfree(str)	conStringfree_fl(str, __FILE__, __LINE__)
125 #define conStringfree_fl(str, file, line) \
126     do { \
127 	conString *temp = (str);  /* must evaluate str exactly once */ \
128 	if (--temp->links <= 0) dSfree((String*)temp, (file), (line)); \
129     } while (0)
130 
131 #define Stringadd(str, c)	dSadd((str), (c), __FILE__, __LINE__)
132 #define Stringnadd(str, c, n)	dSnadd((str), (c), (n), __FILE__, __LINE__)
133 #define Stringtrunc(str, n)	dStrunc((str), (n), __FILE__, __LINE__)
134 #define Stringshift(str, n)     dSshift((str), (n), __FILE__, __LINE__)
135 #define Stringcpy(dst, src)	dScpy((dst), (src), __FILE__, __LINE__)
136 #define SStringcpy(dst, src)	dSScpy((dst), (src), __FILE__, __LINE__)
137 #define Stringncpy(dst, src, n)	dSncpy((dst), (src), (n), __FILE__, __LINE__)
138 #define Stringcat(dst, src)	dScat((dst), (src), __FILE__, __LINE__)
139 #define Stringncat(dst, src, n)	dSncat((dst), (src), (n), __FILE__, __LINE__)
140 #define Stringfncat(dst, src, n) dSfncat((dst), (src), (n), __FILE__, __LINE__)
141 
142 /* the following macros use -1 instead of src->len so src isn't evaled twice */
143 #define SStringcat(dst, src) \
144 	dSSoncat((dst), (src), 0, -1, __FILE__, __LINE__)
145 #define SStringncat(dst, src, len) \
146 	dSSoncat((dst), (src), 0, (len), __FILE__, __LINE__)
147 #define SStringocat(dst, src, start) \
148 	dSSoncat((dst), (src), (start), -1, __FILE__,__LINE__)
149 #define SStringoncat(dst, src, start, len) \
150 	dSSoncat((dst), (src), (start), (len), __FILE__, __LINE__)
151 
152 #define FL	const char *file, int line
153 
154 extern String *dSinit  (String *str, const char *data, int len,
155                attr_t attrs, void *arena, FL);
156 extern void    dSfree  (String *str, FL);  /* call via Stringfree() */
157 extern String *dSadd   (String *str, int c, FL);
158 extern String *dSnadd  (String *str, int c, int n, FL);
159 extern String *dStrunc (String *str, int n, FL);
160 extern String *dSshift (String *str, int n, FL);
161 extern String *dScpy   (String *dest, const char *src, FL);
162 extern String *dSScpy  (String *dest, const conString *src, FL);
163 extern String *dSncpy  (String *dest, const char *src, int n, FL);
164 extern String *dScat   (String *dest, const char *src, FL);
165 extern String *dSSoncat(String *dest, const conString *src, int start, int len, FL);
166 extern String *dSncat  (String *dest, const char *src, int n, FL);
167 extern String *dSfncat (String *dest, const char *src, int n, FL);
168 extern String *Stringstriptrail(String *str);
169 extern int Stringcmp(const conString *s, const conString *t);
170 
171 extern void check_charattrs(String *str, int n, cattr_t attrs,
172     const char *file, int line);
173 extern void extend_charattrs(String *str, int oldlen, cattr_t attrs);
174 
175 #if USE_DMALLOC
176 extern void free_dstring(void);
177 #endif
178 
179 
180 extern conString blankline[1];
181 
182 #undef FL
183 
184 #endif /* DSTRING_H */
185