|
2904
|
1 // This file is part of the uSTL library, an STL implementation. |
|
|
2 // |
|
|
3 // Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net> |
|
|
4 // This file is free software, distributed under the MIT License. |
|
|
5 |
|
|
6 #include "ofstream.h" |
|
|
7 #include "ustring.h" |
|
|
8 #include "uexception.h" |
|
|
9 #include <unistd.h> |
|
|
10 #include <errno.h> |
|
|
11 #include <stdio.h> |
|
|
12 #include <stdarg.h> |
|
|
13 |
|
|
14 namespace ustl { |
|
|
15 |
|
|
16 //---------------------------------------------------------------------- |
|
|
17 #ifdef CYGVAR_USTL_CIN_COUT_CERR |
|
|
18 ifstream cin (STDIN_FILENO); |
|
|
19 ofstream cout (STDOUT_FILENO); |
|
|
20 ofstream cerr (STDERR_FILENO); |
|
|
21 #endif |
|
|
22 //---------------------------------------------------------------------- |
|
|
23 |
|
|
24 /// Default constructor. |
|
|
25 ofstream::ofstream (void) |
|
|
26 : ostringstream (), |
|
|
27 m_File () |
|
|
28 { |
|
|
29 reserve (255); |
|
|
30 } |
|
|
31 |
|
|
32 /// Constructs a stream for writing to \p Fd. |
|
|
33 ofstream::ofstream (int Fd) |
|
|
34 : ostringstream (), |
|
|
35 m_File (Fd) |
|
|
36 { |
|
|
37 clear (m_File.rdstate()); |
|
|
38 reserve (255); |
|
|
39 } |
|
|
40 |
|
|
41 /// Constructs a stream for writing to \p filename. |
|
|
42 ofstream::ofstream (const char* filename, openmode mode) |
|
|
43 : ostringstream (), |
|
|
44 m_File (filename, mode) |
|
|
45 { |
|
|
46 clear (m_File.rdstate()); |
|
|
47 } |
|
|
48 |
|
|
49 /// Default destructor. |
|
|
50 ofstream::~ofstream (void) throw() |
|
|
51 { |
|
|
52 USTL_TRY { flush(); } USTL_CATCH_ALL; |
|
|
53 } |
|
|
54 |
|
|
55 /// Flushes the buffer and closes the file. |
|
|
56 void ofstream::close (void) |
|
|
57 { |
|
|
58 clear (m_File.rdstate()); |
|
|
59 flush(); |
|
|
60 m_File.close(); |
|
|
61 } |
|
|
62 |
|
|
63 /// Flushes the buffer to the file. |
|
|
64 ofstream& ofstream::flush (void) |
|
|
65 { |
|
|
66 clear(); |
|
|
67 while (good() && pos() && overflow (remaining())) ; |
|
|
68 m_File.sync(); |
|
|
69 clear (m_File.rdstate()); |
|
|
70 return (*this); |
|
|
71 } |
|
|
72 |
|
|
73 /// Seeks to \p p based on \p d. |
|
|
74 ofstream& ofstream::seekp (off_t p, seekdir d) |
|
|
75 { |
|
|
76 flush(); |
|
|
77 m_File.seekp (p, d); |
|
|
78 clear (m_File.rdstate()); |
|
|
79 return (*this); |
|
|
80 } |
|
|
81 |
|
|
82 /// Called when more buffer space (\p n bytes) is needed. |
|
|
83 ofstream::size_type ofstream::overflow (size_type n) |
|
|
84 { |
|
|
85 if (eof() || (n > remaining() && n < capacity() - pos())) |
|
|
86 return (ostringstream::overflow (n)); |
|
|
87 size_type bw = m_File.write (cdata(), pos()); |
|
|
88 clear (m_File.rdstate()); |
|
|
89 erase (begin(), bw); |
|
|
90 if (remaining() < n) |
|
|
91 ostringstream::overflow (n); |
|
|
92 return (remaining()); |
|
|
93 } |
|
|
94 |
|
|
95 //---------------------------------------------------------------------- |
|
|
96 |
|
|
97 /// Constructs a stream to read from \p Fd. |
|
|
98 ifstream::ifstream (int Fd) |
|
|
99 : istringstream (), |
|
|
100 m_Buffer (255), |
|
|
101 m_File (Fd) |
|
|
102 { |
|
|
103 link (m_Buffer.data(), streamsize(0)); |
|
|
104 } |
|
|
105 |
|
|
106 /// Constructs a stream to read from \p filename. |
|
|
107 ifstream::ifstream (const char* filename, openmode mode) |
|
|
108 : istringstream (), |
|
|
109 m_Buffer (255), |
|
|
110 m_File (filename, mode) |
|
|
111 { |
|
|
112 clear (m_File.rdstate()); |
|
|
113 link (m_Buffer.data(), streamsize(0)); |
|
|
114 } |
|
|
115 |
|
|
116 /// Reads at least \p n more bytes and returns available bytes. |
|
|
117 ifstream::size_type ifstream::underflow (size_type n) |
|
|
118 { |
|
|
119 if (eof()) |
|
|
120 return (istringstream::underflow (n)); |
|
|
121 |
|
|
122 const ssize_t freeSpace = m_Buffer.size() - pos(); |
|
|
123 const ssize_t neededFreeSpace = max (n, m_Buffer.size() / 2); |
|
|
124 const size_t oughtToErase = Align (max (0, neededFreeSpace - freeSpace)); |
|
|
125 const size_type nToErase = min (pos(), oughtToErase); |
|
|
126 m_Buffer.memlink::erase (m_Buffer.begin(), nToErase); |
|
|
127 const uoff_t oldPos (pos() - nToErase); |
|
|
128 |
|
|
129 size_type br = oldPos; |
|
|
130 if (m_Buffer.size() - br < n) { |
|
|
131 m_Buffer.resize (br + neededFreeSpace); |
|
|
132 link (m_Buffer.data(), streamsize(0)); |
|
|
133 } |
|
|
134 cout.flush(); |
|
|
135 |
|
|
136 size_type brn = 1; |
|
|
137 for (; br < oldPos + n && brn && m_File.good(); br += brn) |
|
|
138 brn = m_File.readsome (m_Buffer.begin() + br, m_Buffer.size() - br); |
|
|
139 clear (m_File.rdstate()); |
|
|
140 |
|
|
141 m_Buffer[br] = 0; |
|
|
142 link (m_Buffer.data(), br); |
|
|
143 seek (oldPos); |
|
|
144 return (remaining()); |
|
|
145 } |
|
|
146 |
|
|
147 /// Flushes the input. |
|
|
148 int ifstream::sync (void) |
|
|
149 { |
|
|
150 istringstream::sync(); |
|
|
151 underflow (0U); |
|
|
152 m_File.sync(); |
|
|
153 clear (m_File.rdstate()); |
|
|
154 return (-good()); |
|
|
155 } |
|
|
156 |
|
|
157 /// Seeks to \p p based on \p d. |
|
|
158 ifstream& ifstream::seekg (off_t p, seekdir d) |
|
|
159 { |
|
|
160 m_Buffer.clear(); |
|
|
161 link (m_Buffer); |
|
|
162 m_File.seekg (p, d); |
|
|
163 clear (m_File.rdstate()); |
|
|
164 return (*this); |
|
|
165 } |
|
|
166 |
|
|
167 //---------------------------------------------------------------------- |
|
|
168 |
|
|
169 } // namespace ustl |