Link with C++ linker
[oweals/cde.git] / cde / programs / nsgmls / OutputCharStream.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: OutputCharStream.C /main/1 1996/07/29 16:59:34 cde-hp $ */
24 // Copyright (c) 1994 James Clark
25 // See the file COPYING for copying permission.
26
27 #include "splib.h"
28 #include "OutputCharStream.h"
29 #include "CodingSystem.h"
30 #include "macros.h"
31 #include <iostream.h>
32 #include <stdio.h>
33
34 #ifdef SP_NAMESPACE
35 namespace SP_NAMESPACE {
36 #endif
37
38 OutputCharStream::OutputCharStream()
39 : ptr_(0), end_(0), escaper_(0)
40 {
41 }
42
43 OutputCharStream::~OutputCharStream()
44 {
45 }
46
47 OutputCharStream &OutputCharStream::write(const Char *s, size_t n)
48 {
49   for (;;) {
50     size_t spare = end_ - ptr_;
51     if (n <= spare) {
52       memcpy(ptr_, s, n*sizeof(Char));
53       ptr_ += n;
54       break;
55     }
56     if (spare > 0) {
57       memcpy(ptr_, s, spare*sizeof(Char));
58       ptr_ += spare;
59       s += spare;
60       n -= spare;
61     }
62     n--;
63     flushBuf(*s++);
64   }
65   return *this;
66 }
67
68 OutputCharStream &OutputCharStream::operator<<(const char *s)
69 {
70   while (*s)
71     put(*s++);
72   return *this;
73 }
74
75 // FIXME Avoid stdio
76
77 OutputCharStream &OutputCharStream::operator<<(unsigned long n)
78 {
79   char buf[sizeof(unsigned long)*3 + 1];
80   sprintf(buf, "%lu", n);
81   return *this << buf;
82 }
83
84 OutputCharStream &OutputCharStream::operator<<(int n)
85 {
86   char buf[sizeof(int)*3 + 2];
87   sprintf(buf, "%d", n);
88   return *this << buf;
89 }
90
91
92 IosOutputCharStream::IosOutputCharStream()
93 : buf_(0), byteStream_(0)
94 {
95 }
96
97 IosOutputCharStream::IosOutputCharStream(streambuf *byteStream,
98                                          const OutputCodingSystem *codingSystem)
99 : buf_(0),
100   byteStream_(byteStream),
101   ownedEncoder_(codingSystem->makeEncoder())
102 {
103   encoder_ = ownedEncoder_.pointer();
104   encoder_->setUnencodableHandler(this);
105   allocBuf(codingSystem->fixedBytesPerChar());
106   encoder_->startFile(byteStream_);
107 }
108
109 IosOutputCharStream::IosOutputCharStream(streambuf *byteStream,
110                                          Encoder *encoder)
111 : buf_(0),
112   byteStream_(byteStream),
113   encoder_(encoder)
114 {
115   allocBuf(0);
116 }
117
118 IosOutputCharStream::~IosOutputCharStream()
119 {
120   if (byteStream_)
121     flush();
122   delete [] buf_;
123 }
124
125 void IosOutputCharStream::open(streambuf *byteStream,
126                                const OutputCodingSystem *codingSystem)
127 {
128   if (byteStream_)
129     flush();
130   byteStream_ = byteStream;
131   ownedEncoder_ = codingSystem->makeEncoder();
132   encoder_ = ownedEncoder_.pointer();
133   encoder_->setUnencodableHandler(this);
134   delete [] buf_;
135   buf_ = 0;
136   ptr_ = end_ = buf_;
137   allocBuf(codingSystem->fixedBytesPerChar());
138   encoder_->startFile(byteStream_);
139 }
140
141 void IosOutputCharStream::flush()
142 {
143   if (ptr_ > buf_) {
144     encoder_->output(buf_, ptr_ - buf_, byteStream_);
145     ptr_ = buf_;
146   }
147   byteStream_->sync();
148 }
149
150 void IosOutputCharStream::flushBuf(Char c)
151 {
152   ASSERT(buf_ != 0);
153   encoder_->output(buf_, ptr_ - buf_, byteStream_);
154   ptr_ = buf_;
155   *ptr_++ = c;
156 }
157
158 void IosOutputCharStream::allocBuf(int bytesPerChar)
159 {
160   const int blockSize = 1024;
161   size_t bufSize = bytesPerChar ? blockSize/bytesPerChar : blockSize;
162   ptr_ = buf_ = new Char[bufSize];
163   end_ = buf_ + bufSize;
164 }
165
166 void IosOutputCharStream::handleUnencodable(Char c, streambuf *)
167 {
168   IosOutputCharStream tem(byteStream_, encoder_);
169   escape(tem, c);
170 }
171
172 StrOutputCharStream::StrOutputCharStream()
173 : buf_(0), bufSize_(0)
174 {
175   sync(0);
176 }
177
178 StrOutputCharStream::~StrOutputCharStream()
179 {
180   delete [] buf_;
181 }
182
183 void StrOutputCharStream::extractString(StringC &str)
184 {
185   str.assign(buf_, ptr_ - buf_);
186   sync(0);
187 }
188
189 void StrOutputCharStream::flushBuf(Char c)
190 {
191   size_t used = ptr_ - buf_;
192   size_t oldSize = bufSize_;
193   bufSize_ = oldSize ? 2*oldSize : 10;
194   Char *oldBuf = buf_;
195   buf_ = new Char[bufSize_];
196   if (oldSize) {
197     memcpy(buf_, oldBuf, oldSize * sizeof(Char));
198     delete [] oldBuf;
199   }
200   sync(used);
201   *ptr_++ = c;
202 }
203
204 void StrOutputCharStream::flush()
205 {
206 }
207
208 void StrOutputCharStream::sync(size_t length)
209 {
210   ptr_ = buf_ + length;
211   end_ = buf_ + bufSize_;
212 }
213
214 RecordOutputCharStream::RecordOutputCharStream(OutputCharStream *os)
215 : os_(os)
216 {
217   ptr_ = buf_;
218   end_ = buf_ + bufSize_;
219 }
220
221 RecordOutputCharStream::~RecordOutputCharStream()
222 {
223   outputBuf();
224   delete os_;
225 }
226
227 void RecordOutputCharStream::flush()
228 {
229   outputBuf();
230   os_->flush();
231 }
232
233 void RecordOutputCharStream::flushBuf(Char c)
234 {
235   outputBuf();
236   *ptr_++ = c;
237 }
238
239 void RecordOutputCharStream::outputBuf()
240 {
241   Char *start = buf_;
242   Char *p = start;
243   while (p < ptr_) {
244     switch (*p) {
245     case '\r':                  // translate RE to newline
246       if (start < p)
247         os_->write(start, p - start);
248       start = ++p;
249       *os_ << newline;
250       break;
251     case '\n':                  // ignore RS
252       if (start < p)
253         os_->write(start, p - start);
254       start = ++p;
255       break;
256     default:
257       ++p;
258       break;
259     }
260   }
261   if (start < p)
262     os_->write(start, p - start);
263   ptr_ = buf_;
264   end_ = buf_ + bufSize_;
265 }
266
267 #ifdef SP_NAMESPACE
268 }
269 #endif