blob: 0948a4d35cc0ef9b76186630c7546899775fe8d3 [file] [log] [blame]
// This file is part of the ustl library, an STL implementation.
//
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
// This file is free software, distributed under the MIT License.
//
// ofstream.cc
//
#include "ofstream.h"
#include "ustring.h"
#include "uexception.h"
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
namespace ustl {
//----------------------------------------------------------------------
ifstream cin (STDIN_FILENO);
ofstream cout (STDOUT_FILENO);
ofstream cerr (STDERR_FILENO);
//----------------------------------------------------------------------
/// Default constructor.
ofstream::ofstream (void)
: ostringstream (),
m_File ()
{
reserve (255);
}
/// Constructs a stream for writing to \p Fd.
ofstream::ofstream (int Fd)
: ostringstream (),
m_File (Fd)
{
clear (m_File.rdstate());
reserve (255);
}
/// Constructs a stream for writing to \p filename.
ofstream::ofstream (const char* filename, openmode mode)
: ostringstream (),
m_File (filename, mode)
{
clear (m_File.rdstate());
}
/// Default destructor.
ofstream::~ofstream (void)
{
#if PLATFORM_ANDROID
flush();
#else /* !PLATFORM_ANDROID */
try { flush(); } catch (...) {}
#endif
}
/// Flushes the buffer to the file.
void ofstream::flush (void)
{
while (pos() && overflow (remaining()));
m_File.sync();
clear (m_File.rdstate());
}
/// Seeks to \p p based on \p d.
void ofstream::seekp (off_t p, seekdir d)
{
flush();
m_File.seekp (p, d);
clear (m_File.rdstate());
}
/// Called when more buffer space (\p n bytes) is needed.
ofstream::size_type ofstream::overflow (size_type n)
{
if (eof() || (n > remaining() && n < capacity() - pos()))
return (ostringstream::overflow (n));
size_type bw = m_File.write (cdata(), pos());
clear (m_File.rdstate());
erase (begin(), bw);
if (remaining() < n)
ostringstream::overflow (n);
return (remaining());
}
//----------------------------------------------------------------------
/// Constructs a stream to read from \p Fd.
ifstream::ifstream (int Fd)
: istringstream (),
m_Buffer (255),
m_File (Fd)
{
link (m_Buffer.data(), 0U);
}
/// Constructs a stream to read from \p filename.
ifstream::ifstream (const char* filename, openmode mode)
: istringstream (),
m_Buffer (255),
m_File (filename, mode)
{
clear (m_File.rdstate());
link (m_Buffer.data(), 0U);
}
/// Reads at least \p n more bytes and returns available bytes.
ifstream::size_type ifstream::underflow (size_type n)
{
if (eof())
return (istringstream::underflow (n));
const ssize_t freeSpace = m_Buffer.size() - pos();
const ssize_t neededFreeSpace = max (n, m_Buffer.size() / 2);
const size_t oughtToErase = Align (max (0, neededFreeSpace - freeSpace));
const size_t nToErase = min (pos(), oughtToErase);
m_Buffer.memlink::erase (m_Buffer.begin(), nToErase);
const uoff_t oldPos (pos() - nToErase);
size_type br = oldPos;
if (m_Buffer.size() - br < n) {
m_Buffer.resize (br + neededFreeSpace);
link (m_Buffer.data(), 0U);
}
cout.flush();
while (br - oldPos < n && m_File.good())
br += m_File.readsome (m_Buffer.begin() + br, m_Buffer.size() - br);
clear (m_File.rdstate());
m_Buffer[br] = string::c_Terminator;
link (m_Buffer.data(), br);
seek (oldPos);
return (remaining());
}
/// Flushes the input.
void ifstream::sync (void)
{
istringstream::sync();
underflow (0U);
m_File.sync();
clear (m_File.rdstate());
}
/// Seeks to \p p based on \p d.
void ifstream::seekg (off_t p, seekdir d)
{
m_Buffer.clear();
link (m_Buffer);
m_File.seekg (p, d);
clear (m_File.rdstate());
}
//----------------------------------------------------------------------
} // namespace ustl