Cleanup ACE_HAS_PTHREAD_SIGMASK_PROTOTYPE, all platforms support it so far as I can...
[ACE_TAO.git] / ACE / ACEXML / common / FileCharStream.cpp
blobeba9e8b26600854f71d44e02f2dd9000611ab029
1 #include "ACEXML/common/FileCharStream.h"
2 #include "ace/ACE.h"
3 #include "ace/Log_Msg.h"
4 #include "ace/OS_NS_stdio.h"
5 #include "ace/OS_NS_sys_stat.h"
6 #include "ace/Truncate.h"
8 #if defined (ACE_USES_WCHAR)
9 # include "ace/OS_NS_wchar.h"
10 #endif /* ACE_USES_WCHAR */
12 ACEXML_FileCharStream::ACEXML_FileCharStream ()
13 : filename_ (0), encoding_ (0), size_ (0), infile_ (0),
14 close_infile_ (true), peek_ (0)
18 ACEXML_FileCharStream::~ACEXML_FileCharStream ()
20 this->close();
23 int
24 ACEXML_FileCharStream::use_stream_i (FILE* open_file, const ACEXML_Char *name)
26 delete[] this->filename_;
27 this->filename_ = 0;
29 delete[] this->encoding_;
30 this->encoding_ = 0;
32 this->infile_ = open_file;
33 if (this->infile_ == 0)
34 return -1;
36 ACE_stat statbuf;
37 if (ACE_OS::stat (name, &statbuf) < 0)
38 return -1;
40 this->size_ = ACE_Utils::truncate_cast<ACE_OFF_T> (statbuf.st_size);
41 this->filename_ = ACE::strnew (name);
42 return this->determine_encoding();
45 int
46 ACEXML_FileCharStream::use_stream (FILE* open_file, const ACEXML_Char *name)
48 if (open_file != 0)
49 ACE_OS::rewind(open_file);
51 this->close_infile_ = false;
52 return use_stream_i(open_file, name);
55 int
56 ACEXML_FileCharStream::open (const ACEXML_Char *name)
58 this->close_infile_ = true;
59 return use_stream_i(ACE_OS::fopen (name, ACE_TEXT ("r")), name);
62 int
63 ACEXML_FileCharStream::determine_encoding ()
65 if (this->infile_ == 0)
66 return -1;
68 char input[4];
69 int retval = 0;
70 int i = 0;
71 for (; i < 4 && retval != -1; ++i)
72 retval = this->getchar_i(input[i]);
73 if (i < 4)
74 return -1;
76 // Rewind the stream
77 ACE_OS::rewind (this->infile_);
79 const ACEXML_Char* temp = ACEXML_Encoding::get_encoding (input);
80 if (!temp)
81 return -1;
82 else
84 delete [] this->encoding_;
85 this->encoding_ = ACE::strnew (temp);
86 // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("File's encoding is %s\n"),
87 // this->encoding_));
89 // Move over the byte-order-mark if present.
90 char ch;
91 for (int j = 0; j < 3; ++j)
93 if (this->getchar_i (ch) < 0)
94 return -1;
95 if (ch == '\xFF' || ch == '\xFE' || ch == '\xEF' || ch == '\xBB' ||
96 ch == '\xBF')
97 continue;
98 else
100 ACE_OS::ungetc (ch, this->infile_);
101 break;
104 return 0;
107 void
108 ACEXML_FileCharStream::rewind()
110 if (this->infile_ == 0)
111 return;
112 ACE_OS::rewind (this->infile_);
113 this->determine_encoding();
117 ACEXML_FileCharStream::available ()
119 if (this->infile_ == 0)
120 return -1;
122 long curr;
123 if ((curr = ACE_OS::ftell (this->infile_)) < 0)
124 return -1;
125 return static_cast<int> (this->size_ - curr);
129 ACEXML_FileCharStream::close ()
131 if (this->infile_ != 0)
133 if (this->close_infile_)
135 ACE_OS::fclose (this->infile_);
137 this->infile_ = 0;
139 delete[] this->filename_;
140 this->filename_ = 0;
141 delete[] this->encoding_;
142 this->encoding_ = 0;
143 this->size_ = 0;
144 this->peek_ = 0;
145 return 0;
150 ACEXML_FileCharStream::getchar_i (char& ch)
152 ch = static_cast<char> (ACE_OS::fgetc (this->infile_));
153 return (feof(this->infile_) ? -1 : 0);
157 ACEXML_FileCharStream::read (ACEXML_Char *str,
158 size_t len)
160 if (this->infile_ == 0)
161 return -1;
163 return static_cast<int> (ACE_OS::fread (str, sizeof (ACEXML_Char), len, this->infile_));
167 ACEXML_FileCharStream::get (ACEXML_Char& ch)
169 if (this->infile_ == 0)
170 return -1;
171 #if defined (ACE_USES_WCHAR)
172 return this->get_i (ch);
173 #else
174 ch = (ACEXML_Char) ACE_OS::fgetc (this->infile_);
175 return (feof(this->infile_) ? -1 : 0);
176 #endif /* ACE_USES_WCHAR */
180 ACEXML_FileCharStream::peek ()
182 if (this->infile_ == 0)
183 return -1;
184 #if defined (ACE_USES_WCHAR)
185 return this->peek_i();
186 #else
188 ACEXML_Char ch = static_cast<ACEXML_Char> (ACE_OS::fgetc (this->infile_));
189 ACE_OS::ungetc (ch, this->infile_);
190 return ch;
191 #endif /* ACE_USES_WCHAR */
194 #if defined (ACE_USES_WCHAR)
196 ACEXML_FileCharStream::get_i (ACEXML_Char& ch)
198 if (ACE_OS::strcmp (this->encoding_, ACE_TEXT ("UTF-8")) == 0)
200 ch = (ACEXML_Char) ACE_OS::fgetc (this->infile_);
201 return (feof(this->infile_) ? -1 : 0);
203 // If we have a value in peek_, return it.
204 if (this->peek_ != 0)
206 ch = this->peek_;
207 this->peek_ = 0;
208 return 0;
211 int BE = (ACE_OS::strcmp (this->encoding_,
212 ACE_TEXT ("UTF-16BE")) == 0) ? 1 : 0;
213 ACEXML_Char input[2];
214 int i = 0;
215 for (; i < 2 && !feof (this->infile_); ++i)
217 input[i] = ACE_OS::fgetwc (this->infile_);
219 if (i < 2)
221 ch = 0;
222 return -1;
224 ch = BE ? input[0] << 8 | input[1] : input[1] << 8 | input[0];
225 return 0;
229 ACEXML_FileCharStream::peek_i ()
231 // If we are reading a UTF-8 encoded file, just use the plain unget.
232 if (ACE_OS::strcmp (this->encoding_, ACE_TEXT ("UTF-8")) == 0)
234 ACEXML_Char ch = (ACEXML_Char) ACE_OS::fgetc (this->infile_);
235 ACE_OS::ungetc (ch, this->infile_);
236 return ch;
239 // If somebody had already called peek() and not consumed it, return the
240 // value held in this->peek_.
241 if (this->peek_ != 0)
242 return this->peek_;
244 // Peek into the stream. This reads two characters off the stream, keeps
245 // it in peek_.
246 int BE = (ACE_OS::strcmp (this->encoding_,
247 ACE_TEXT ("UTF-16BE")) == 0) ? 1 : 0;
248 ACEXML_Char input[2];
249 int i = 0;
250 for (; i < 2 && !feof (this->infile_); ++i)
252 input[i] = ACE_OS::fgetwc (this->infile_);
254 if (i < 2)
256 this->peek_ = 0;
257 return -1;
259 this->peek_ = BE ? input[0] << 8 | input[1] : input[1] << 8 | input[0];
260 return this->peek_;
262 #endif /* ACE_USES_WCHAR */
264 const ACEXML_Char*
265 ACEXML_FileCharStream::getEncoding ()
267 return this->encoding_;
270 const ACEXML_Char*
271 ACEXML_FileCharStream::getSystemId ()
273 return this->filename_;