1 // Copyright (c) 1997 James Clark
2 // See the file COPYING for copying permission.
3 #pragma ident	"%Z%%M%	%I%	%E% SMI"
4 
5 #include "splib.h"
6 #include "OutputByteStream.h"
7 
8 #include <sys/types.h>
9 
10 #ifdef SP_INCLUDE_IO_H
11 #include <io.h>		// for open, fstat, lseek, read prototypes
12 #endif
13 
14 #ifdef SP_INCLUDE_UNISTD_H
15 #include <unistd.h>
16 #endif
17 
18 #ifdef SP_INCLUDE_OSFCN_H
19 #include <osfcn.h>
20 #endif
21 
22 #include <fcntl.h>
23 #include <sys/stat.h>
24 #include <errno.h>
25 #include <stdio.h>
26 
27 #ifdef SP_WIDE_SYSTEM
28 #define STRICT
29 #include <windows.h>
30 #endif
31 
32 #ifndef O_CREAT
33 #ifdef _O_CREAT
34 #define O_CREAT _O_CREAT
35 #endif
36 #endif
37 
38 #ifndef O_WRONLY
39 #ifdef _O_WRONLY
40 #define O_WRONLY _O_WRONLY
41 #endif
42 #endif
43 
44 #ifndef O_TRUNC
45 #ifdef _O_TRUNC
46 #define O_TRUNC _O_TRUNC
47 #endif
48 #endif
49 
50 #ifndef O_BINARY
51 #ifdef _O_BINARY
52 #define O_BINARY _O_BINARY
53 #else
54 #define O_BINARY 0
55 #endif
56 #endif
57 
58 #ifndef S_IRUSR
59 #if defined(S_IREAD)
60 #define S_IRUSR S_IREAD
61 #elif defined(_S_IREAD)
62 #define S_IRUSR _S_IREAD
63 #else
64 #define S_IRUSR 0400
65 #endif
66 #endif
67 
68 #ifndef S_IWUSR
69 #if defined(S_IWRITE)
70 #define S_IWUSR S_IWRITE
71 #elif defined(_S_IWRITE)
72 #define S_IWUSR _S_IWRITE
73 #else
74 #define S_IWUSR 0200
75 #endif
76 #endif
77 
78 #ifndef S_IRGRP
79 #if defined(S_IREAD)
80 #define S_IRGRP S_IREAD
81 #elif defined(_S_IREAD)
82 #define S_IRGRP _S_IREAD
83 #else
84 #define S_IRGRP 0040
85 #endif
86 #endif
87 
88 #ifndef S_IWGRP
89 #if defined(S_IWRITE)
90 #define S_IWGRP S_IWRITE
91 #elif defined(_S_IWRITE)
92 #define S_IWGRP _S_IWRITE
93 #else
94 #define S_IWGRP 0020
95 #endif
96 #endif
97 
98 #ifndef S_IROTH
99 #if defined(S_IREAD)
100 #define S_IROTH S_IREAD
101 #elif defined(_S_IREAD)
102 #define S_IROTH _S_IREAD
103 #else
104 #define S_IROTH 0004
105 #endif
106 #endif
107 
108 #ifndef S_IWOTH
109 #if defined(S_IWRITE)
110 #define S_IWOTH S_IWRITE
111 #elif defined(_S_IWRITE)
112 #define S_IWOTH _S_IWRITE
113 #else
114 #define S_IWOTH 0002
115 #endif
116 #endif
117 
118 #ifdef SP_NAMESPACE
119 namespace SP_NAMESPACE {
120 #endif
121 
122 const int openFlags = O_CREAT|O_WRONLY|O_TRUNC|O_BINARY;
123 const int protMode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
124 const int bufSize = 8192;
125 
OutputByteStream()126 OutputByteStream::OutputByteStream()
127 : ptr_(0), end_(0)
128 {
129 }
130 
~OutputByteStream()131 OutputByteStream::~OutputByteStream()
132 {
133 }
134 
sputn(const char * s,size_t n)135 void OutputByteStream::sputn(const char *s, size_t n)
136 {
137   for (; n > 0; n--, s++)
138     sputc(*s);
139 }
140 
operator <<(long n)141 OutputByteStream &OutputByteStream::operator<<(long n)
142 {
143   char buf[32];
144   sprintf(buf, "%ld", n);
145   return *this << buf;
146 }
147 
operator <<(unsigned long n)148 OutputByteStream &OutputByteStream::operator<<(unsigned long n)
149 {
150   char buf[32];
151   sprintf(buf, "%lu", n);
152   return *this << buf;
153 }
154 
operator <<(const char * s)155 OutputByteStream &OutputByteStream::operator<<(const char *s)
156 {
157   while (*s)
158     sputc(*s++);
159   return *this;
160 }
161 
StrOutputByteStream()162 StrOutputByteStream::StrOutputByteStream()
163 {
164 }
165 
extractString(String<char> & str)166 void StrOutputByteStream::extractString(String<char> &str)
167 {
168   if (ptr_)
169     buf_.resize(ptr_ - &buf_[0]);
170   str.resize(0);
171   buf_.swap(str);
172   ptr_ = end_ = 0;
173 }
174 
flush()175 void StrOutputByteStream::flush()
176 {
177 }
178 
flushBuf(char c)179 void StrOutputByteStream::flushBuf(char c)
180 {
181   if (!ptr_) {
182     buf_.resize(16);
183     ptr_ = &buf_[0];
184   }
185   else {
186     size_t i = ptr_ - &buf_[0];
187     buf_.resize(buf_.size()*2);
188     ptr_ = &buf_[0] + i;
189   }
190   end_ = &buf_[0] + buf_.size();
191   *ptr_++ = c;
192 }
193 
FileOutputByteStream()194 FileOutputByteStream::FileOutputByteStream()
195 : fd_(-1)
196 {
197 }
198 
FileOutputByteStream(int fd,Boolean closeFd)199 FileOutputByteStream::FileOutputByteStream(int fd, Boolean closeFd)
200 : fd_(-1)
201 {
202   attach(fd, closeFd);
203 }
204 
~FileOutputByteStream()205 FileOutputByteStream::~FileOutputByteStream()
206 {
207   close();
208 }
209 
210 #ifdef SP_WIDE_SYSTEM
211 
open(const wchar_t * filename)212 Boolean FileOutputByteStream::open(const wchar_t *filename)
213 {
214   int fd = _wopen(filename, openFlags, protMode);
215   if (fd >= 0)
216     return attach(fd);
217   // _wopen will always fail on Windows 95
218   String<char> buf;
219   int len = WideCharToMultiByte(CP_ACP, 0, filename, -1, 0, 0, 0, 0);
220   buf.resize(len + 1);
221   WideCharToMultiByte(CP_ACP, 0, filename, -1, buf.begin(), len, 0, 0);
222   buf[len] = '\0';
223   return attach(::open(buf.data(), openFlags, protMode));
224 }
225 
226 #else /* not SP_WIDE_SYSTEM */
227 
open(const char * filename)228 Boolean FileOutputByteStream::open(const char *filename)
229 {
230   return attach(::open(filename, openFlags, protMode));
231 }
232 
233 #endif /* not SP_WIDE_SYSTEM */
234 
attach(int fd,Boolean closeFd)235 Boolean FileOutputByteStream::attach(int fd, Boolean closeFd)
236 {
237   close();
238   fd_ = fd;
239   closeFd_ = closeFd;
240   return fd_ >= 0;
241 }
242 
close()243 Boolean FileOutputByteStream::close()
244 {
245   if (fd_ < 0)
246     return 0;
247   flush();
248   int fd = fd_;
249   fd_ = -1;
250   if (!closeFd_)
251     return 1;
252   return ::close(fd) == 0;
253 }
254 
flush()255 void FileOutputByteStream::flush()
256 {
257   if (!buf_.size()) {
258     if (fd_ < 0)
259       return;
260     buf_.resize(bufSize);
261     ptr_ = &buf_[0];
262     end_ = ptr_ + buf_.size();
263   }
264   size_t n = ptr_ - &buf_[0];
265   const char *s = buf_.data();
266   while (n > 0) {
267     int nw = ::write(fd_, s, n);
268     if (nw < 0)
269       break;
270     n -= nw;
271     s += nw;
272   }
273   ptr_ = &buf_[0];
274 }
275 
flushBuf(char c)276 void FileOutputByteStream::flushBuf(char c)
277 {
278   flush();
279   *ptr_++ = c;
280 }
281 
282 #ifdef SP_NAMESPACE
283 }
284 #endif
285