source: trunk/gsdl/src/library/text_t.cpp@ 4

Last change on this file since 4 was 4, checked in by sjboddie, 25 years ago

Initial revision

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 12.0 KB
Line 
1/**************************************************************************
2 *
3 * text_t.cpp -- a simple 16-bit charater string class
4 * Copyright (c) 1998 -- Rodger McNab
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: text_t.cpp 4 1998-11-17 01:10:39Z sjboddie $
21 *
22 **************************************************************************/
23
24/*
25 $Log$
26 Revision 1.1 1998/11/17 01:11:06 sjboddie
27 Initial revision
28
29 Revision 1.7 1998/06/24 01:50:08 rjmcnab
30 Added stuff for the objectspace libraries
31
32 Revision 1.6 1998/06/22 22:11:14 rjmcnab
33 Added copy operator = for ints and c-strings for efficiency
34 Added some general functions for dealing with text_ts
35
36 Revision 1.5 1998/06/18 23:53:52 rjmcnab
37 added '+' operator for concatenation
38 removed global declaration of ascii2text_t and text_t2ascii
39 (too unfriendly for threads)
40 added support for integers
41
42 Revision 1.4 1998/06/17 04:52:32 rjmcnab
43 added support for arrays of characters
44
45 Revision 1.3 1998/06/17 02:09:42 rjmcnab
46 added getcstr
47
48 Revision 1.2 1998/06/15 22:01:19 rjmcnab
49 fixed a few bugs
50
51 Revision 1.1 1998/06/13 20:08:34 rjmcnab
52 Initial revision
53
54*/
55
56static char *RCSID = "$Id: text_t.cpp 4 1998-11-17 01:10:39Z sjboddie $";
57
58
59#ifndef USE_OBJECTSPACE
60# include <algorithm>
61#else
62# include <ospace\std\algorithm>
63#endif
64
65
66#include "text_t.h"
67
68////////////////////////////////////
69// text_t methods
70////////////////////////////////////
71
72text_t::text_t ()
73{
74 clear ();
75}
76
77text_t::text_t (int i)
78{
79 clear ();
80 appendint (i);
81}
82
83text_t::text_t (char *s)
84{
85 clear ();
86 appendcstr (s);
87}
88
89void text_t::append (const text_t &t)
90{
91 const_iterator here, end=t.end();
92 for (here=t.begin(); here!=end;here++)
93 {
94 text.push_back(*here);
95 }
96}
97
98void text_t::appendrange (iterator first, iterator last)
99{
100 while (first != last)
101 {
102 text.push_back (*first);
103 first++;
104 }
105}
106
107void text_t::appendrange (const_iterator first, const_iterator last)
108{
109 while (first != last)
110 {
111 text.push_back (*first);
112 first++;
113 }
114}
115
116void text_t::appendint (int i)
117{
118 // deal with zeros and negatives
119 if (i == 0)
120 {
121 text.push_back('0');
122 return;
123 }
124 else if (i < 0)
125 {
126 text.push_back('-');
127 i *= -1;
128 }
129
130 // get a buffer for the conversion
131 int maxbuflen = sizeof(int)*3;
132 char *buf = new char[maxbuflen];
133 int len = 0;
134
135 // get the number in reverse
136 while (i > 0)
137 {
138 buf[len++] = '0'+ (i%10);
139 i = i/10;
140 }
141
142 // reverse the number
143 while (len > 0)
144 {
145 text.push_back(buf[--len]);
146 }
147
148 delete buf;
149}
150
151int text_t::getint ()
152{
153 int i = 0;
154 int mult = 1; // become -1 for negative numbers
155
156 iterator here = text.begin();
157 iterator end = text.end();
158
159 // do plus and minus signs
160 if (here != end)
161 {
162 if (*here == '-')
163 {
164 mult = -1;
165 here++;
166 }
167 else if (*here == '+')
168 {
169 mult = 1;
170 here++;
171 }
172 }
173
174 // deal with the number
175 while ((here != end) && (*here >= '0') && (*here <= '9'))
176 {
177 i = 10*i + (*here - '0');
178 here++;
179 }
180
181 i *= mult;
182 return i;
183}
184
185
186
187void text_t::appendcarr (char *s, size_type len)
188{
189 unsigned char *us = (unsigned char *)s;
190 while (len > 0)
191 {
192 text.push_back (*us); // append this character
193 us++;
194 len--;
195 }
196}
197
198void text_t::appendcstr (char *s)
199{
200 unsigned char *us = (unsigned char *)s;
201 while (*us != '\0')
202 {
203 text.push_back (*us); // append this character
204 us++;
205 }
206}
207
208
209// strings returned from getcarr and getcstr become the callers
210// responsibility and should be deallocated with "delete"
211
212char *text_t::getcarr(size_type &len) const
213{
214 unsigned char *cstr = new unsigned char[size()];
215 const_iterator ithere = begin();
216 const_iterator itend = end();
217
218 while (ithere != itend)
219 {
220 if (*ithere >= 256) cstr[len] = ' ';
221 else cstr[len] = (*ithere);
222 len++;
223 ithere++;
224 }
225
226 return (char *)cstr;
227}
228
229char *text_t::getcstr() const
230{
231 unsigned char *cstr = new unsigned char[size() + 1];
232 const_iterator ithere = begin();
233 const_iterator itend = end();
234 int len = 0;
235
236 while (ithere != itend)
237 {
238 if (*ithere >= 256) cstr[len] = ' ';
239 else cstr[len] = (*ithere);
240 len++;
241 ithere++;
242 }
243
244 cstr[len] = '\0';
245
246 return (char *)cstr;
247}
248
249
250// general functions which work on text_ts
251
252// find a character within a range
253text_t::const_iterator findchar (text_t::const_iterator first, text_t::const_iterator last,
254 unsigned short c)
255{
256 while (first != last)
257 {
258 if (*first == c) break;
259 first++;
260 }
261 return first;
262}
263
264text_t::iterator findchar (text_t::iterator first, text_t::iterator last,
265 unsigned short c)
266{
267 while (first != last)
268 {
269 if (*first == c) break;
270 first++;
271 }
272 return first;
273}
274
275// get a string up to the next delimiter (which is skipped)
276text_t::const_iterator getdelimitstr (text_t::const_iterator first,
277 text_t::const_iterator last,
278 unsigned short c, text_t &outstr)
279{
280 text_t::const_iterator here = first;
281 here = findchar (first, last, c);
282 outstr.clear();
283 outstr.appendrange (first, here);
284 if (here != last) here++; // skip c
285 return here;
286}
287
288text_t::iterator getdelimitstr (text_t::iterator first, text_t::iterator last,
289 unsigned short c, text_t &outstr)
290{
291 text_t::iterator here = first;
292 here = findchar (first, last, c);
293 outstr.clear();
294 outstr.appendrange (first, here);
295 if (here != last) here++; // skip c
296 return here;
297}
298
299// split a string with a character
300void splitchar (text_t::const_iterator first, text_t::const_iterator last,
301 unsigned short c, text_tlist &outlist)
302{
303 outlist.erase(outlist.begin(), outlist.end());
304
305 text_t t;
306
307 while (first != last)
308 {
309 first = getdelimitstr (first, last, c, t);
310 outlist.push_back (t);
311 }
312}
313
314void splitchar (text_t::const_iterator first, text_t::const_iterator last,
315 unsigned short c, text_tarray &outlist)
316{
317 outlist.erase(outlist.begin(), outlist.end());
318
319 text_t t;
320
321 while (first != last)
322 {
323 first = getdelimitstr (first, last, c, t);
324 outlist.push_back (t);
325 }
326}
327
328// join a string using a character
329void joinchar (const text_tlist &inlist, unsigned short c, text_t &outtext)
330{
331 outtext.clear ();
332
333 text_tlist::const_iterator here = inlist.begin ();
334 text_tlist::const_iterator end = inlist.end ();
335 bool first = true;
336 while (here != end)
337 {
338 if (!first) outtext.push_back (c);
339 first = false;
340 outtext += *here;
341 here++;
342 }
343}
344
345void joinchar (const text_tarray &inlist, unsigned short c, text_t &outtext)
346{
347 outtext.clear ();
348
349 text_tarray::const_iterator here = inlist.begin ();
350 text_tarray::const_iterator end = inlist.end ();
351 bool first = true;
352 while (here != end)
353 {
354 if (!first) outtext.push_back (c);
355 first = false;
356 outtext += *here;
357 here++;
358 }
359}
360
361// count the occurances of a character within a range
362int countchar (text_t::const_iterator first, text_t::const_iterator last,
363 unsigned short c)
364{
365 int count = 0;
366 while (first != last) {
367 if (*first == c) count ++;
368 first ++;
369 }
370 return count;
371}
372
373
374
375////////////////////////////////////
376// convertclass methods
377////////////////////////////////////
378
379// conversion classes used for getting information in to and out of
380// the text_t class.
381
382convertclass::convertclass ()
383{
384 // nothing to do
385}
386
387void convertclass::reset ()
388{
389 // nothing to do
390}
391
392
393////////////////////////////////////
394// inconvertclass methods
395////////////////////////////////////
396
397// convert from a char stream to the text_t class
398// the default version assumes the input is a ascii
399// character array
400
401inconvertclass::inconvertclass ()
402{
403 start = NULL;
404 len = 0;
405}
406
407
408void inconvertclass::reset ()
409{
410 start = NULL;
411 len = 0;
412}
413
414void inconvertclass::setinput (char *thestart, size_t thelen)
415{
416 start = thestart;
417 len = thelen;
418}
419
420void inconvertclass::convert (text_t &output, status_t &status)
421{
422 if (start == NULL || len == 0)
423 {
424 status = finished;
425 return;
426 }
427
428 // don't want any funny sign conversions happening
429 unsigned char *here = (unsigned char *)start;
430 while (len > 0)
431 {
432 output.push_back (*here); // append this character
433 ++here;
434 --len;
435 }
436
437 start = (char *)here; // save current position
438 status = finished;
439}
440
441// an instance of the default inconvertclass to do simple
442// conversions. Note that any functions that use this are
443// not reentrant. If a function needs to be reentrant it
444// should declare its own instance.
445inconvertclass ascii2text_t;
446
447
448////////////////////////////////////
449// outconvertclass methods
450////////////////////////////////////
451
452// Convert from a text_t class to a char stream
453// This default version assumes the output is a ascii
454// character array. If you set the output stream you
455// can use this class to output to a stream using the
456// << operator. The << operator can also be conveniently
457// used to set the output stream by doing something like
458//
459// cout << text_t2ascii << text_tstr << anothertext_tstr;
460//
461outconvertclass::outconvertclass ()
462{
463 input = NULL;
464 outs = NULL;
465}
466
467void outconvertclass::reset ()
468{
469 input = NULL;
470 outs = NULL;
471}
472
473void outconvertclass::setinput (text_t *theinput)
474{
475 input = theinput;
476 if (input != NULL) texthere = input->begin();
477}
478
479void outconvertclass::convert (char *output, size_t maxlen,
480 size_t &len, status_t &status)
481{
482 if (input == NULL || output == NULL)
483 {
484 status = finished;
485 return;
486 }
487
488 // don't want any funny sign conversions happening
489 unsigned char *uoutput = (unsigned char *)output;
490 text_t::iterator textend = input->end();
491 len = 0;
492 while ((len < maxlen) && (texthere != textend))
493 {
494 if (*texthere < 256) *uoutput = (unsigned char)(*texthere);
495 else *uoutput = 32; // put a space where a char >= 256 exists
496 ++uoutput;
497 ++len;
498 ++texthere;
499 }
500
501 if (texthere == textend) status = finished;
502 else status = unfinished;
503}
504
505void outconvertclass::setostream (ostream *theouts)
506{
507 outs = theouts;
508}
509
510ostream *outconvertclass::getostream ()
511{
512 return outs;
513}
514
515
516
517
518// an instance of the default outconvertclass to do simple
519// conversions
520outconvertclass text_t2ascii;
521
522
523
524// stream operators for the output class
525
526outconvertclass &operator<< (ostream &theouts, outconvertclass &outconverter)
527{
528 outconverter.setostream(&theouts);
529 return outconverter;
530}
531
532
533#define STREAMBUFSIZE 256
534outconvertclass &operator<< (outconvertclass &outconverter, const text_t &t)
535{
536 ostream *outstream = outconverter.getostream();
537
538 if (outstream == NULL) return outconverter;
539
540 char outbuf[STREAMBUFSIZE];
541 size_t len;
542 outconvertclass::status_t status = outconvertclass::unfinished;
543
544 // assume that there is no data needing converting
545 // left in the converter
546 outconverter.setinput ((text_t *)(&t)); // note the const -> nonconst conversion
547
548 while (status == outconvertclass::unfinished)
549 {
550 outconverter.convert (outbuf, STREAMBUFSIZE, len, status);
551 if (len > 0) outstream->write(outbuf, len);
552 }
553
554 return outconverter;
555}
Note: See TracBrowser for help on using the repository browser.