//---------------------------------------------------------------------
//
// Copyright (C) 2004 Yingle Jia
//
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
#include "stdafx.h"
namespace Acf {
namespace IO {
// Constructors
StreamWriter::StreamWriter(String* path, bool append)
{
EncodingPtr encoding = new UTF8Encoding(false, true);
ctor(path, append, encoding, DefaultBufferSize);
}
StreamWriter::StreamWriter(String* path, bool append, Acf::Text::Encoding* encoding,
int bufferSize)
{
ctor(path, append, encoding, bufferSize);
}
void StreamWriter::ctor(String* path, bool append, Acf::Text::Encoding* encoding, int bufferSize)
{
if (path == null || encoding == null)
throw ArgumentNullException();
if (bufferSize <= 0)
throw ArgumentOutOfRangeException();
FileMode mode = append ? FileMode::Append : FileMode::Create;
FileStreamPtr stream = new FileStream(path, mode, FileAccess::Write, FileShare::Read,
DefaultFileStreamBufferSize);
ctor(stream, encoding, bufferSize);
}
StreamWriter::StreamWriter(Stream* stream)
{
EncodingPtr encoding = new UTF8Encoding(false, true);
ctor(stream, encoding, DefaultBufferSize);
}
StreamWriter::StreamWriter(Stream* stream, Acf::Text::Encoding* encoding, int bufferSize)
{
ctor(stream, encoding, bufferSize);
}
void StreamWriter::ctor(Stream* stream, Acf::Text::Encoding* encoding, int bufferSize)
{
if (stream == null || encoding == null)
throw ArgumentNullException();
if (bufferSize <= 0)
throw ArgumentOutOfRangeException();
if (bufferSize < MinBufferSize)
bufferSize = MinBufferSize;
this->_stream = stream;
this->_encoding = encoding;
this->_encoder = encoding->GetEncoder();
this->_charBuffer = new Array<wchar_t>(bufferSize);
this->_byteBuffer = new Array<byte>(encoding->GetMaxByteCount(bufferSize));
// If we're appending to a Stream that already has data, don't write
// the preamble junk.
if (stream->CanSeek && stream->Position > 0)
this->_haveWrittenPreamble = true;
this->_closable = true;
}
// Destructor
/*virtual*/ StreamWriter::~StreamWriter()
{
Close();
}
// Properties
/*virtual*/ StreamPtr StreamWriter::get_BaseStream()
{
return this->_stream;
}
/*override*/ EncodingPtr StreamWriter::get_Encoding()
{
return this->_encoding;
}
/*virtual*/ bool StreamWriter::get_AutoFlush()
{
return this->_autoFlush;
}
/*virtual*/ void StreamWriter::set_AutoFlush(bool value)
{
this->_autoFlush = value;
if (value)
Flush(true, false);
}
// Methods
/*override*/ void StreamWriter::Write(wchar_t value)
{
if (this->_charPos == this->_charBuffer->Length)
Flush(false, false);
this->_charBuffer->Item[this->_charPos++] = value;
if (this->_autoFlush)
Flush(true, false);
}
/*override*/ void StreamWriter::Write(Array<wchar_t>* buffer, int index, int count)
{
Acf::VerifyArrayRange(buffer, index, count);
while (count > 0)
{
if (this->_charPos == this->_charBuffer->Length)
Flush(false, false);
int n = this->_charBuffer->Length - this->_charPos;
if (n > count)
n = count;
Array<wchar_t>::Copy(buffer, index, this->_charBuffer, this->_charPos, n);
this->_charPos += n;
index += n;
count -= n;
}
if (this->_autoFlush)
Flush(true, false);
}
/*override*/ void StreamWriter::Write(String* value)
{
if (value != null)
{
int count = value->Length;
int index = 0;
while (count > 0)
{
if (this->_charPos == this->_charBuffer->Length)
Flush(false, false);
int n = this->_charBuffer->Length - this->_charPos;
if (n > count)
n = count;
value->CopyTo(index, this->_charBuffer, this->_charPos, n);
this->_charPos += n;
index += n;
count -= n;
}
if (this->_autoFlush)
Flush(true, false);
}
}
/*override*/ void StreamWriter::Flush()
{
Flush(true, true);
}
/*override*/ void StreamWriter::Close()
{
if (this->_stream != null)
{
Flush();
if (this->_closable)
this->_stream->Close();
}
if (this->_closable && this->_stream != null)
{
this->_stream = null;
this->_byteBuffer = null;
this->_charBuffer = null;
this->_encoding = null;
this->_encoder = null;
}
}
void StreamWriter::Flush(bool flushStream, bool flushEncoder)
{
if (this->_stream == null)
throw InvalidOperationException();
if (this->_charPos == 0 && !flushStream && !flushEncoder)
return;
if (!this->_haveWrittenPreamble)
{
RefPtr<Array<byte> > preamble = this->_encoding->GetPreamble();
if (preamble->Length > 0)
this->_stream->Write(preamble, 0, preamble->Length);
this->_haveWrittenPreamble = true;
}
int count = this->_encoder->GetBytes(this->_charBuffer, 0, this->_charPos,
this->_byteBuffer, 0, flushEncoder);
if (count > 0)
this->_stream->Write(this->_byteBuffer, 0, count);
this->_charPos = 0;
if (flushStream)
this->_stream->Flush();
}
} // namespace IO
} // namespace Acf