Added static_assert from Loki
[ustl.git] / ofstream.cc
blob75258e69cbfc0a007876daa38fa83dccbaa660db
1 // This file is part of the ustl library, an STL implementation.
2 //
3 // Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
5 //
6 // ofstream.cc
7 //
9 #include "ofstream.h"
10 #include "ustring.h"
11 #include "uexception.h"
12 #include <unistd.h>
13 #include <errno.h>
14 #include <stdio.h>
15 #include <stdarg.h>
17 namespace ustl {
19 //----------------------------------------------------------------------
21 ifstream cin (STDIN_FILENO);
22 ofstream cout (STDOUT_FILENO);
23 ofstream cerr (STDERR_FILENO);
25 //----------------------------------------------------------------------
27 /// Default constructor.
28 ofstream::ofstream (void)
29 : ostringstream (),
30 m_File ()
32 reserve (255);
35 /// Constructs a stream for writing to \p Fd.
36 ofstream::ofstream (int Fd)
37 : ostringstream (),
38 m_File (Fd)
40 clear (m_File.rdstate());
41 reserve (255);
44 /// Constructs a stream for writing to \p filename.
45 ofstream::ofstream (const char* filename, openmode mode)
46 : ostringstream (),
47 m_File (filename, mode)
49 clear (m_File.rdstate());
52 /// Default destructor.
53 ofstream::~ofstream (void)
55 try { flush(); } catch (...) {}
58 /// Flushes the buffer to the file.
59 void ofstream::flush (void)
61 while (pos() && overflow (remaining()));
62 m_File.sync();
63 clear (m_File.rdstate());
66 /// Seeks to \p p based on \p d.
67 void ofstream::seekp (off_t p, seekdir d)
69 flush();
70 m_File.seekp (p, d);
71 clear (m_File.rdstate());
74 /// Called when more buffer space (\p n bytes) is needed.
75 ofstream::size_type ofstream::overflow (size_type n)
77 if (eof() || (n > remaining() && n < capacity() - pos()))
78 return (ostringstream::overflow (n));
79 size_type bw = m_File.write (cdata(), pos());
80 clear (m_File.rdstate());
81 erase (begin(), bw);
82 if (remaining() < n)
83 ostringstream::overflow (n);
84 return (remaining());
87 //----------------------------------------------------------------------
89 /// Constructs a stream to read from \p Fd.
90 ifstream::ifstream (int Fd)
91 : istringstream (),
92 m_Buffer (255),
93 m_File (Fd)
95 link (m_Buffer.data(), size_t(0));
98 /// Constructs a stream to read from \p filename.
99 ifstream::ifstream (const char* filename, openmode mode)
100 : istringstream (),
101 m_Buffer (255),
102 m_File (filename, mode)
104 clear (m_File.rdstate());
105 link (m_Buffer.data(), size_t(0));
108 /// Reads at least \p n more bytes and returns available bytes.
109 ifstream::size_type ifstream::underflow (size_type n)
111 if (eof())
112 return (istringstream::underflow (n));
114 const ssize_t freeSpace = m_Buffer.size() - pos();
115 const ssize_t neededFreeSpace = max (n, m_Buffer.size() / 2);
116 const size_t oughtToErase = Align (max (0, neededFreeSpace - freeSpace));
117 const size_t nToErase = min (pos(), oughtToErase);
118 m_Buffer.memlink::erase (m_Buffer.begin(), nToErase);
119 const uoff_t oldPos (pos() - nToErase);
121 size_type br = oldPos;
122 if (m_Buffer.size() - br < n) {
123 m_Buffer.resize (br + neededFreeSpace);
124 link (m_Buffer.data(), size_t(0));
126 cout.flush();
128 size_type brn = 1;
129 for (; br < oldPos + n && brn && m_File.good(); br += brn)
130 brn = m_File.readsome (m_Buffer.begin() + br, m_Buffer.size() - br);
131 clear (m_File.rdstate());
133 m_Buffer[br] = string::c_Terminator;
134 link (m_Buffer.data(), br);
135 seek (oldPos);
136 return (remaining());
139 /// Flushes the input.
140 void ifstream::sync (void)
142 istringstream::sync();
143 underflow (0U);
144 m_File.sync();
145 clear (m_File.rdstate());
148 /// Seeks to \p p based on \p d.
149 void ifstream::seekg (off_t p, seekdir d)
151 m_Buffer.clear();
152 link (m_Buffer);
153 m_File.seekg (p, d);
154 clear (m_File.rdstate());
157 //----------------------------------------------------------------------
159 } // namespace ustl