source: main/trunk/greenstone2/common-src/src/lib/text_t.cpp@ 24110

Last change on this file since 24110 was 24110, checked in by sjm84, 13 years ago

Added a trim function to text_t that removes leading and trailing whitespace

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 21.9 KB
Line 
1/**********************************************************************
2 *
3 * text_t.cpp -- a simple 16-bit character string class
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * $Id: text_t.cpp 24110 2011-06-02 21:19:39Z sjm84 $
25 *
26 *********************************************************************/
27
28#include "text_t.h"
29
30#if defined(GSDL_USE_OBJECTSPACE)
31# include <ospace\std\algorithm>
32#elif defined(GSDL_USE_STL_H)
33# if defined(GSDL_USE_ALGO_H)
34# include <algo.h>
35# else
36# include <algorithm.h>
37# endif
38#else
39# include <algorithm>
40#endif
41
42#ifdef HAVE_CONFIG_H
43# ifdef __WIN32__
44# include "win32cfg.h"
45# else
46# include "config.h"
47# endif
48#endif
49
50#include <cstring>
51
52#include "unitool.h"
53#include <iostream>
54
55const text_t g_EmptyText("");
56
57////////////////////////////////////
58// text_t methods
59////////////////////////////////////
60
61// new stream converter ...
62ostream& operator<< (ostream &o, const text_t &text)
63{
64 text_t::const_iterator ithere = text.begin();
65 text_t::const_iterator itend = text.end();
66
67 while (ithere != itend)
68 {
69 if (*ithere < 256)
70 {
71 o << (unsigned char)(*ithere);
72 }
73 else
74 {
75 // put a space or a question mark depending on what
76 // the character is. Question marks tell the user that
77 // they are missing some information.
78 if (is_unicode_space (*ithere))
79 o << ' ';
80 else
81 o << '?';
82 }
83 ++ithere;
84 }
85
86 return o;
87}
88
89text_t::text_t ()
90{
91 setencoding(0);
92 clear ();
93}
94
95text_t::text_t (int i)
96{
97 setencoding(0);
98 clear ();
99 appendint (i);
100}
101
102text_t::text_t (const char *s)
103{
104 setencoding(0);
105 clear ();
106 appendcstr (s);
107}
108
109text_t::text_t (const char *s, size_type nLength)
110{
111 setencoding(0);
112 clear ();
113 appendcarr(s, nLength);
114}
115
116
117void text_t::append (const text_t &t)
118{
119 text.insert(text.end(), t.begin(), t.end());
120}
121
122void text_t::appendrange (iterator first, iterator last)
123{
124 text.insert(text.end(), first, last);
125}
126
127void text_t::appendrange (const_iterator first, const_iterator last)
128{
129 text.insert(text.end(), first, last);
130}
131
132void text_t::appendint (int i)
133{
134 // deal with zeros and negatives
135 if (i == 0)
136 {
137 text.push_back('0');
138 return;
139 }
140 else if (i < 0)
141 {
142 text.push_back('-');
143 i *= -1;
144 }
145
146 // get a buffer for the conversion
147 int maxbuflen = sizeof(int)*3;
148 char *buf = new char[maxbuflen];
149 int len = 0;
150
151 // get the number in reverse
152 while (i > 0)
153 {
154 buf[len++] = '0'+ (i%10);
155 i = i/10;
156 }
157
158 // reverse the number
159 while (len > 0)
160 {
161 text.push_back(buf[--len]);
162 }
163
164 delete []buf;
165}
166
167int text_t::getint () const
168{
169 int i = 0;
170 int mult = 1; // become -1 for negative numbers
171
172 const_iterator here = text.begin();
173 const_iterator end = text.end();
174
175 // do plus and minus signs
176 if (here != end)
177 {
178 if (*here == '-')
179 {
180 mult = -1;
181 ++here;
182 }
183 else if (*here == '+')
184 {
185 mult = 1;
186 ++here;
187 }
188 }
189
190 // deal with the number
191 while ((here != end) && (*here >= '0') && (*here <= '9'))
192 {
193 i = 10*i + (*here - '0');
194 ++here;
195 }
196
197 i *= mult;
198 return i;
199}
200
201unsigned long text_t::getulong () const
202{
203 unsigned long i = 0;
204
205 const_iterator here = text.begin();
206 const_iterator end = text.end();
207
208 while ((here != end) && (*here >= '0') && (*here <= '9'))
209 {
210 i = 10*i + (*here - '0');
211 ++here;
212 }
213
214 return i;
215}
216
217void text_t::appendcarr (const char *s, size_type len)
218{
219 unsigned char *us = (unsigned char *)s;
220 if (text.capacity() < (text.size() + len + 2)) {
221 text.reserve(text.size() + len + 2);
222 }
223
224 while (len > 0)
225 {
226 text.push_back (*us); // append this character
227 ++us;
228 --len;
229 }
230}
231
232void text_t::appendcstr (const char *s)
233{
234 size_t len = strlen(s);
235 if (text.capacity() < (text.size() + len + 2)) {
236 text.reserve(text.size() + len + 2);
237 }
238
239 unsigned char *us = (unsigned char *)s;
240 while (*us != '\0')
241 {
242 text.push_back (*us); // append this character
243 ++us;
244 }
245}
246
247
248// strings returned from getcarr and getcstr become the callers
249// responsibility and should be deallocated with "delete []"
250
251char *text_t::getcarr(size_type &len) const
252{
253 unsigned char *cstr = new unsigned char[size()];
254 len = 0;
255
256 const_iterator ithere = begin();
257 const_iterator itend = end();
258 while (ithere != itend)
259 {
260 if (*ithere < 256) cstr[len] = (unsigned char)(*ithere);
261 else {
262 // put a space or a question mark depending on what
263 // the character is. Question marks tell the user that
264 // they are missing some information.
265 if (is_unicode_space (*ithere)) cstr[len] = ' ';
266 else cstr[len] = '?';
267 }
268 ++len;
269 ++ithere;
270 }
271
272 return (char *)cstr;
273}
274
275char *text_t::getcstr() const
276{
277 unsigned char *cstr = new unsigned char[size() + 1];
278 const_iterator ithere = begin();
279 const_iterator itend = end();
280 int len = 0;
281
282 while (ithere != itend)
283 {
284 if (*ithere < 256) cstr[len] = (unsigned char)(*ithere);
285 else {
286 // put a space or a question mark depending on what
287 // the character is. Question marks tell the user that
288 // they are missing some information.
289 if (is_unicode_space (*ithere)) cstr[len] = ' ';
290 else cstr[len] = '?';
291 }
292 ++len;
293 ++ithere;
294 }
295
296 cstr[len] = '\0';
297
298 return (char *)cstr;
299}
300
301
302int text_t::replace(text_t toreplace, text_t replacement)
303{
304 // Get the beginning and end of the current text
305 text_t::iterator text_begin = text.begin(), text_end = text.end();
306 int count = 0;
307 text_t new_text, temp_text;
308
309 // Loop through and grab the text off the end
310 while (text_begin < text_end)
311 {
312 // Find where the next toreplace is
313 text_t::iterator next_toreplace = findword(text_begin, text_end, toreplace);
314
315 // We've found a match
316 if (next_toreplace != text_end)
317 {
318 new_text.append(substr(text_begin, next_toreplace));
319 new_text.append(replacement);
320 count++;
321 text_begin = next_toreplace + toreplace.size();
322 }
323 // We haven't found a match
324 else
325 {
326 new_text.append(substr(text_begin, text_end));
327 text_begin = text_end;
328 }
329 }
330
331 text.clear();
332 text = new_text.text_as_usvector();
333 return count;
334}
335
336
337// general functions which work on text_ts
338
339// find a character within a range
340text_t::const_iterator findchar (text_t::const_iterator first, text_t::const_iterator last,
341 unsigned short c)
342{
343 while (first != last)
344 {
345 if (*first == c) break;
346 ++first;
347 }
348 return first;
349}
350
351text_t::iterator findchar (text_t::iterator first, text_t::iterator last,
352 unsigned short c)
353{
354 while (first != last)
355 {
356 if (*first == c) break;
357 ++first;
358 }
359 return first;
360}
361
362text_t::iterator findlastchar (text_t::iterator first, text_t::iterator last_plus_one,
363 unsigned short c)
364{
365 text_t::iterator current = (last_plus_one != first) ? last_plus_one - 1 : first;
366 while (current != first) {
367 if (*current == c) break;
368 --current;
369 }
370 if (current == first) {
371 if (*current == c) return current;
372 return last_plus_one;
373 }
374
375 return current;
376}
377
378text_t::const_iterator findword (text_t::const_iterator first,
379 text_t::const_iterator last,
380 const text_t& word)
381{
382 text_t::const_iterator word_begin = word.begin();
383 text_t::const_iterator word_end = word.end();
384
385 while (first != last)
386 {
387 text_t::const_iterator char_match = first;
388 text_t::const_iterator word_here = word_begin;
389 while (word_here != word_end && char_match != last)
390 {
391 if (*char_match != *word_here)
392 {
393 break;
394 }
395 ++char_match;
396 ++word_here;
397 }
398 if (word_here==word_end)
399 {
400 return first;
401 }
402 ++first;
403 }
404 return last; // get to here only if there is no match
405}
406
407text_t::iterator findword (text_t::iterator first,
408 text_t::iterator last,
409 const text_t& word)
410{
411 text_t::const_iterator word_begin = word.begin();
412 text_t::const_iterator word_end = word.end();
413
414 while (first != last)
415 {
416 text_t::iterator char_match = first;
417 text_t::const_iterator word_here = word_begin;
418 while (word_here != word_end && char_match != last)
419 {
420 if (*char_match != *word_here)
421 {
422 break;
423 }
424 ++char_match;
425 ++word_here;
426 }
427 if (word_here==word_end)
428 {
429 return first;
430 }
431 ++first;
432 }
433 return last; // get to here only if there is no match
434}
435
436// get a string up to the next delimiter (which is skipped)
437text_t::const_iterator getdelimitstr (text_t::const_iterator first,
438 text_t::const_iterator last,
439 unsigned short c, text_t &outstr)
440{
441 text_t::const_iterator here = first;
442 here = findchar (first, last, c);
443 outstr.clear();
444 outstr.appendrange (first, here);
445 if (here != last) ++here; // skip c
446 return here;
447}
448
449text_t::iterator getdelimitstr (text_t::iterator first, text_t::iterator last,
450 unsigned short c, text_t &outstr)
451{
452 text_t::iterator here = first;
453 here = findchar (first, last, c);
454 outstr.clear();
455 outstr.appendrange (first, here);
456 if (here != last) ++here; // skip c
457 return here;
458}
459
460text_t::const_iterator getdelimitstr (text_t::const_iterator first, text_t::const_iterator last,
461 text_t w, text_t &outstr)
462{
463 text_t::const_iterator here = first;
464 here = findword (first, last, w);
465 outstr.clear();
466 outstr.appendrange (first, here);
467 if (here != last) here += w.size(); // skip w
468 return here;
469}
470
471// split a string with a character
472void splitchar (text_t::const_iterator first, text_t::const_iterator last,
473 unsigned short c, text_tset &outlist)
474{
475 outlist.erase(outlist.begin(), outlist.end());
476
477 text_t t;
478
479 while (first != last)
480 {
481 first = getdelimitstr (first, last, c, t);
482 outlist.insert (t);
483 }
484}
485
486void splitchar (text_t::const_iterator first, text_t::const_iterator last,
487 unsigned short c, text_tlist &outlist)
488{
489 outlist.erase(outlist.begin(), outlist.end());
490
491 text_t t;
492
493 while (first != last)
494 {
495 first = getdelimitstr (first, last, c, t);
496 outlist.push_back (t);
497 }
498}
499
500void splitchar (text_t::const_iterator first, text_t::const_iterator last,
501 unsigned short c, text_tarray &outlist)
502{
503 outlist.erase(outlist.begin(), outlist.end());
504
505 text_t t;
506
507 while (first != last)
508 {
509 first = getdelimitstr (first, last, c, t);
510 outlist.push_back (t);
511 }
512}
513
514void splitword (text_t::const_iterator first, text_t::const_iterator last,
515 text_t w, text_tlist &outlist)
516{
517 outlist.erase(outlist.begin(), outlist.end());
518
519 text_t t;
520
521 while (first != last)
522 {
523 first = getdelimitstr (first, last, w, t);
524 outlist.push_back (t);
525 }
526}
527
528// join a string using a character
529void joinchar (const text_tset &inlist, unsigned short c, text_t &outtext)
530{
531 outtext.clear ();
532
533 text_tset::const_iterator here = inlist.begin ();
534 text_tset::const_iterator end = inlist.end ();
535
536 if (here != end) {
537 outtext += *here; ++here;
538 while (here != end) {
539 outtext.push_back (c);
540 outtext += *here;
541 ++here;
542 }
543 }
544}
545
546void joinchar (const text_tlist &inlist, unsigned short c, text_t &outtext)
547{
548 outtext.clear ();
549
550 text_tlist::const_iterator here = inlist.begin ();
551 text_tlist::const_iterator end = inlist.end ();
552 if (here != end) {
553 outtext += *here; ++here;
554 while (here != end) {
555 outtext.push_back (c);
556 outtext += *here;
557 ++here;
558 }
559 }
560}
561
562void joinchar (const text_tarray &inlist, unsigned short c, text_t &outtext)
563{
564 outtext.clear ();
565
566 text_tarray::const_iterator here = inlist.begin ();
567 text_tarray::const_iterator end = inlist.end ();
568 if (here != end) {
569 outtext += *here; ++here;
570 while (here != end) {
571 outtext.push_back (c);
572 outtext += *here;
573 ++here;
574 }
575 }
576}
577
578void joinchar (const text_tlist &inlist, const text_t &c, text_t &outtext)
579{
580 outtext.clear ();
581
582 text_tlist::const_iterator here = inlist.begin ();
583 text_tlist::const_iterator end = inlist.end ();
584 if (here != end) {
585 outtext += *here; ++here;
586 while (here != end) {
587 outtext += c;
588 outtext += *here;
589 ++here;
590 }
591 }
592}
593
594void joinchar (const text_tset &inlist, const text_t &c, text_t &outtext)
595{
596 outtext.clear ();
597
598 text_tset::const_iterator here = inlist.begin ();
599 text_tset::const_iterator end = inlist.end ();
600 if (here != end) {
601 outtext += *here; ++here;
602 while (here != end) {
603 outtext += c;
604 outtext += *here;
605 ++here;
606 }
607 }
608}
609
610void joinchar (const text_tarray &inlist, const text_t &c, text_t &outtext)
611{
612 outtext.clear ();
613
614 text_tarray::const_iterator here = inlist.begin ();
615 text_tarray::const_iterator end = inlist.end ();
616 if (here != end) {
617 outtext += *here; ++here;
618 while (here != end) {
619 outtext += c;
620 outtext += *here;
621 ++here;
622 }
623 }
624}
625
626// count the occurances of a character within a range
627int countchar (text_t::const_iterator first, text_t::const_iterator last,
628 unsigned short c)
629{
630 int count = 0;
631 while (first != last) {
632 if (*first == c) ++count;
633 ++first;
634 }
635 return count;
636}
637
638// return a substring of string from first up to but not including last
639text_t substr (text_t::const_iterator first, text_t::const_iterator last) {
640
641 text_t substr; substr.reserve(last - first + 2);
642 while (first != last) {
643 substr.push_back(*first);
644 ++first;
645 }
646 return substr;
647}
648
649
650// convert to lowercase
651void lc (text_t::iterator first, text_t::iterator last) {
652 while (first != last) {
653 *first = unicode_tolower(*first);
654 ++first;
655 }
656}
657
658// convert to uppercase
659void uc (text_t::iterator first, text_t::iterator last) {
660 while (first != last) {
661 *first = unicode_toupper(*first);
662 ++first;
663 }
664}
665
666
667// checks to see if it is a number (i.e. contains only 0-9)
668bool is_number (const text_t &text) {
669
670 text_t::const_iterator here = text.begin();
671 text_t::const_iterator end = text.end();
672
673 while (here != end) {
674 if ((*here!='0') && (*here!='1') && (*here!='2') &&
675 (*here!='3') && (*here!='4') && (*here!='5') &&
676 (*here!='6') && (*here!='7') && (*here!='8') &&
677 (*here!='9')) return false;
678 ++here;
679 }
680 return true;
681}
682
683
684// checks to see if the text has any letters or digits
685bool has_unicode_letdig (const text_t &text) {
686 if (text.empty()) return false;
687
688 text_t::const_iterator here = text.begin();
689 text_t::const_iterator end = text.end();
690 while (here != end) {
691 if (is_unicode_letdig (*here)) return true;
692 ++here;
693 }
694
695 return false;
696}
697
698// checks to see if a text_t starts with the specified prefix
699bool starts_with(const text_t& text, const text_t& prefix) {
700 if (prefix.empty()) return true;
701 if (text.empty() || text.size()<prefix.size()) return false;
702 text_t substring = substr(text.begin(), text.begin()+prefix.size());
703 return substring == prefix;
704}
705// checks to see if a text_t ends with the specified suffix
706bool ends_with(const text_t& text, const text_t& suffix) {
707 if (suffix.empty()) return true;
708 if (text.empty() || text.size() < suffix.size()) return false;
709 text_t substring = substr(text.end()-suffix.size(),text.end());
710 return substring == suffix;
711
712}
713
714//Trims the whitespace off the beginning and end of a given string
715text_t trim (const text_t& text) {
716
717 if(text.size() == 0) {
718 return text;
719 }
720
721 text_t::const_iterator firstLetter = text.begin();
722 text_t::const_iterator lastLetter = text.end();
723
724 //Find the start
725 while (firstLetter != lastLetter) {
726 if(!is_unicode_space(*firstLetter)) {
727 break;
728 }
729 firstLetter++;
730 }
731
732 //Find the end
733 while (lastLetter != firstLetter) {
734 if(!is_unicode_space(*lastLetter)) {
735 break;
736 }
737 lastLetter--;
738 }
739
740 return substr(firstLetter, lastLetter+1);
741}
742
743////////////////////////////////////
744// convertclass methods
745////////////////////////////////////
746
747// conversion classes used for getting information in to and out of
748// the text_t class.
749
750convertclass::convertclass ()
751{
752 // nothing to do
753}
754
755convertclass::~convertclass ()
756{
757 // nothing to do
758}
759
760void convertclass::reset ()
761{
762 // nothing to do
763}
764
765
766////////////////////////////////////
767// inconvertclass methods
768////////////////////////////////////
769
770// convert from a char stream to the text_t class
771// the default version assumes the input is a ascii
772// character array
773
774inconvertclass::inconvertclass ()
775{
776 start = NULL;
777 len = 0;
778}
779
780inconvertclass::~inconvertclass ()
781{
782 // nothing to do
783}
784
785
786void inconvertclass::reset ()
787{
788 start = NULL;
789 len = 0;
790}
791
792void inconvertclass::setinput (char *thestart, size_t thelen)
793{
794 start = thestart;
795 len = thelen;
796}
797
798void inconvertclass::convert (text_t &output, status_t &status)
799{
800 output.clear();
801
802 if (start == NULL || len == 0)
803 {
804 status = finished;
805 return;
806 }
807
808 if (output.capacity() < len + 2)
809 output.reserve(len + 2);
810
811 // don't want any funny sign conversions happening
812 unsigned char *here = (unsigned char *)start;
813 while (len > 0)
814 {
815 output.push_back (*here); // append this character
816 ++here;
817 --len;
818 }
819
820 start = (char *)here; // save current position
821 status = finished;
822}
823
824// will treat the text_t as a 8-bit string and convert
825// it to a 16-bit string using the about convert method.
826text_t inconvertclass::convert (const text_t &t) {
827 text_t out;
828 text_t tmpout;
829 status_t status;
830 text_t::const_iterator here = t.begin();
831 text_t::const_iterator end = t.end();
832 unsigned char cbuf[256];
833 size_t cbuflen = 0;
834
835 out.clear();
836 if (out.capacity() < t.size() + 2)
837 out.reserve(t.size() + 2);
838 while (here != end) {
839 while (here != end && cbuflen < 256) {
840 cbuf[cbuflen++] = (unsigned char)(*here & 0xff);
841 ++here;
842 }
843
844 if (cbuflen > 0) {
845 setinput ((char *)cbuf, cbuflen);
846 status = unfinished;
847 while (status == unfinished) {
848 convert (tmpout, status);
849 out += tmpout;
850 }
851 cbuflen = 0;
852 }
853 }
854
855 out.setencoding (0); // unicode
856
857 return out;
858}
859
860// an instance of the default inconvertclass to do simple
861// conversions. Note that any functions that use this are
862// not reentrant. If a function needs to be reentrant it
863// should declare its own instance.
864inconvertclass ascii2text_t;
865
866
867////////////////////////////////////
868// outconvertclass methods
869////////////////////////////////////
870
871// Convert from a text_t class to a char stream
872// This default version assumes the output is a ascii
873// character array. If you set the output stream you
874// can use this class to output to a stream using the
875// << operator. The << operator can also be conveniently
876// used to set the output stream by doing something like
877//
878// cout << text_t2ascii << text_tstr << anothertext_tstr;
879//
880outconvertclass::outconvertclass ()
881{
882 input = NULL;
883 outs = NULL;
884}
885
886outconvertclass::~outconvertclass ()
887{
888 // nothing to do
889}
890
891
892void outconvertclass::reset ()
893{
894 input = NULL;
895 outs = NULL;
896}
897
898void outconvertclass::setinput (text_t *theinput)
899{
900 input = theinput;
901 if (input != NULL) texthere = input->begin();
902}
903
904void outconvertclass::setdata(text_t *theinput, text_t::iterator thetexthere)
905{
906 input = theinput;
907 texthere = thetexthere;
908}
909
910void outconvertclass::convert (char *output, size_t maxlen,
911 size_t &len, status_t &status)
912{
913 if (input == NULL || output == NULL)
914 {
915 status = finished;
916 return;
917 }
918
919 // don't want any funny sign conversions happening
920 unsigned char *uoutput = (unsigned char *)output;
921 text_t::iterator textend = input->end();
922 len = 0;
923 while ((len < maxlen) && (texthere != textend))
924 {
925 if (*texthere < 256) *uoutput = (unsigned char)(*texthere);
926 else {
927 // put a space or a question mark depending on what
928 // the character is. Question marks tell the user that
929 // they are missing some information.
930 if (is_unicode_space (*texthere)) *uoutput = ' ';
931 else *uoutput = '?';
932 }
933 ++uoutput;
934 ++len;
935 ++texthere;
936 }
937
938 if (texthere == textend) status = finished;
939 else status = unfinished;
940}
941
942// will convert the 16-bit string to a 8-bit stream
943// and place the result in a text_t. This method uses
944// the above convert function.
945text_t outconvertclass::convert (const text_t &t) {
946 text_t out;
947 unsigned char cbuf[256];
948 size_t cbuflen = 0;
949 status_t status = unfinished;
950
951 out.clear();
952 if (out.capacity() < t.size() + 2)
953 out.reserve(t.size() + 2);
954 setinput ((text_t *)&t); // discard constant
955 while (status == unfinished) {
956 convert ((char *)cbuf, 256, cbuflen, status);
957 out.appendcarr ((char *)cbuf, cbuflen);
958 }
959
960 out.setencoding (1); // other encoding
961
962 return out;
963}
964
965
966void outconvertclass::setostream (ostream *theouts)
967{
968 outs = theouts;
969}
970
971ostream *outconvertclass::getostream ()
972{
973 return outs;
974}
975
976
977
978
979// an instance of the default outconvertclass to do simple
980// conversions
981outconvertclass text_t2ascii;
982
983
984
985// stream operators for the output class
986
987outconvertclass &operator<< (ostream &theouts, outconvertclass &outconverter)
988{
989 outconverter.setostream(&theouts);
990 return outconverter;
991}
992
993
994#define STREAMBUFSIZE 256
995outconvertclass &operator<< (outconvertclass &outconverter, const text_t &t)
996{
997 ostream *outstream = outconverter.getostream();
998
999 if (outstream == NULL) return outconverter;
1000
1001 char outbuf[STREAMBUFSIZE];
1002 size_t len;
1003 outconvertclass::status_t status = outconvertclass::unfinished;
1004
1005 // assume that there is no data needing converting
1006 // left in the converter
1007 outconverter.setinput ((text_t *)(&t)); // note the const -> nonconst conversion
1008
1009 while (status == outconvertclass::unfinished)
1010 {
1011 outconverter.convert (outbuf, STREAMBUFSIZE, len, status);
1012 if (len > 0) outstream->write(outbuf, len);
1013 }
1014
1015 return outconverter;
1016}
Note: See TracBrowser for help on using the repository browser.