ofstream.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
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//
8
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>
16
17namespace ustl {
18
19//----------------------------------------------------------------------
20
21ifstream cin  (STDIN_FILENO);
22ofstream cout (STDOUT_FILENO);
23ofstream cerr (STDERR_FILENO);
24
25//----------------------------------------------------------------------
26
27/// Default constructor.
28ofstream::ofstream (void)
29: ostringstream (),
30  m_File ()
31{
32    reserve (255);
33}
34
35/// Constructs a stream for writing to \p Fd.
36ofstream::ofstream (int Fd)
37: ostringstream (),
38  m_File (Fd)
39{
40    clear (m_File.rdstate());
41    reserve (255);
42}
43
44/// Constructs a stream for writing to \p filename.
45ofstream::ofstream (const char* filename, openmode mode)
46: ostringstream (),
47  m_File (filename, mode)
48{
49    clear (m_File.rdstate());
50}
51
52/// Default destructor.
53ofstream::~ofstream (void)
54{
55#if PLATFORM_ANDROID
56    flush();
57#else /* !PLATFORM_ANDROID */
58    try { flush(); } catch (...) {}
59#endif
60}
61
62/// Flushes the buffer to the file.
63void ofstream::flush (void)
64{
65    while (pos() && overflow (remaining()));
66    m_File.sync();
67    clear (m_File.rdstate());
68}
69
70/// Seeks to \p p based on \p d.
71void ofstream::seekp (off_t p, seekdir d)
72{
73    flush();
74    m_File.seekp (p, d);
75    clear (m_File.rdstate());
76}
77
78/// Called when more buffer space (\p n bytes) is needed.
79ofstream::size_type ofstream::overflow (size_type n)
80{
81    if (eof() || (n > remaining() && n < capacity() - pos()))
82	return (ostringstream::overflow (n));
83    size_type bw = m_File.write (cdata(), pos());
84    clear (m_File.rdstate());
85    erase (begin(), bw);
86    if (remaining() < n)
87	ostringstream::overflow (n);
88    return (remaining());
89}
90
91//----------------------------------------------------------------------
92
93/// Constructs a stream to read from \p Fd.
94ifstream::ifstream (int Fd)
95: istringstream (),
96  m_Buffer (255),
97  m_File (Fd)
98{
99    link (m_Buffer.data(), 0U);
100}
101
102/// Constructs a stream to read from \p filename.
103ifstream::ifstream (const char* filename, openmode mode)
104: istringstream (),
105  m_Buffer (255),
106  m_File (filename, mode)
107{
108    clear (m_File.rdstate());
109    link (m_Buffer.data(), 0U);
110}
111
112/// Reads at least \p n more bytes and returns available bytes.
113ifstream::size_type ifstream::underflow (size_type n)
114{
115    if (eof())
116	return (istringstream::underflow (n));
117
118    const ssize_t freeSpace = m_Buffer.size() - pos();
119    const ssize_t neededFreeSpace = max (n, m_Buffer.size() / 2);
120    const size_t oughtToErase = Align (max (0, neededFreeSpace - freeSpace));
121    const size_t nToErase = min (pos(), oughtToErase);
122    m_Buffer.memlink::erase (m_Buffer.begin(), nToErase);
123    const uoff_t oldPos (pos() - nToErase);
124
125    size_type br = oldPos;
126    if (m_Buffer.size() - br < n) {
127	m_Buffer.resize (br + neededFreeSpace);
128	link (m_Buffer.data(), 0U);
129    }
130    cout.flush();
131
132    while (br - oldPos < n && m_File.good())
133	br += m_File.readsome (m_Buffer.begin() + br, m_Buffer.size() - br);
134    clear (m_File.rdstate());
135
136    m_Buffer[br] = string::c_Terminator;
137    link (m_Buffer.data(), br);
138    seek (oldPos);
139    return (remaining());
140}
141
142/// Flushes the input.
143void ifstream::sync (void)
144{
145    istringstream::sync();
146    underflow (0U);
147    m_File.sync();
148    clear (m_File.rdstate());
149}
150
151/// Seeks to \p p based on \p d.
152void ifstream::seekg (off_t p, seekdir d)
153{
154    m_Buffer.clear();
155    link (m_Buffer);
156    m_File.seekg (p, d);
157    clear (m_File.rdstate());
158}
159
160//----------------------------------------------------------------------
161
162} // namespace ustl
163
164