//---------------------------------------------------------------------
//
// 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, 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);
new(this) StreamWriter(stream, encoding, bufferSize);
}
StreamWriter::StreamWriter(const wchar_t* 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);
new(this) StreamWriter(stream, encoding, bufferSize);
}
StreamWriter::StreamWriter(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)
{
if (buffer == null)
throw ArgumentNullException();
Write(buffer, 0, buffer->Length);
}
/*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::Write(const wchar_t* value)
{
if (value != null)
{
int count = (int) wcslen(value);
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;
memcpy(this->_charBuffer->GetItemAddress(this->_charPos),
value + index, n * sizeof(wchar_t));
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