Some refactoring of file I/O.

Originally committed to SVN as r2465.
This commit is contained in:
Rodrigo Braz Monteiro 2008-11-20 03:21:00 +00:00
parent e255222316
commit 6f94248289
10 changed files with 244 additions and 110 deletions

View file

@ -467,6 +467,22 @@
RelativePath=".\src\text_file_writer.h"
>
</File>
<File
RelativePath=".\src\text_reader.cpp"
>
</File>
<File
RelativePath=".\src\text_reader.h"
>
</File>
<File
RelativePath=".\src\text_writer.cpp"
>
</File>
<File
RelativePath=".\src\text_writer.h"
>
</File>
</Filter>
</Files>
<Globals>

View file

@ -38,8 +38,8 @@
#include "format_ass.h"
#include "format_ass_plain.h"
#include "version.h"
#include "../text_file_reader.h"
#include "../text_file_writer.h"
#include "../text_reader.h"
#include "../text_writer.h"
#include <iostream>
#include <algorithm>
#include <wx/tokenzr.h>
@ -108,7 +108,7 @@ FormatHandlerASS::~FormatHandlerASS()
void FormatHandlerASS::Load(IModel &model,wxInputStream &file,const String encoding)
{
// Make text file reader
TextFileReader reader(file,encoding);
shared_ptr<TextReader> reader = TextReader::GetReader(file,encoding);
// Variables
int version = 1;
@ -117,9 +117,9 @@ void FormatHandlerASS::Load(IModel &model,wxInputStream &file,const String encod
Section section = Section();
// Read file
while (reader.HasMoreLines()) {
while (reader->HasMoreLines()) {
// Read a line
String cur = reader.ReadLineFromFile();
String cur = reader->ReadLineFromFile();
if (cur.IsEmpty()) continue;
// Process group
@ -151,7 +151,7 @@ void FormatHandlerASS::Load(IModel &model,wxInputStream &file,const String encod
void FormatHandlerASS::Save(const IModel& model,wxOutputStream &file,const String encoding) const
{
// Make text file writer
TextFileWriter writer(file,encoding);
shared_ptr<TextWriter> writer = TextWriter::GetWriter(file,encoding);
// Set up list of sections to write
StringArray sections;
@ -178,7 +178,7 @@ void FormatHandlerASS::Save(const IModel& model,wxOutputStream &file,const Strin
ConstSection section = GetSection(model,sections[i]);
if (section) {
// Add a spacer
if (i != 0) writer.WriteLineToFile("");
if (i != 0) writer->WriteLineToFile("");
// Write the section
WriteSection(writer,section);
@ -334,11 +334,11 @@ void FormatHandlerASS::ProcessGroup(String cur,String &curGroup,int &version) {
///////////////////////////////
// Write a section to the file
void FormatHandlerASS::WriteSection(TextFileWriter &writer,ConstSection section) const
void FormatHandlerASS::WriteSection(shared_ptr<TextWriter> writer,ConstSection section) const
{
// Write name
String name = section->GetName();
writer.WriteLineToFile("[" + name + "]");
writer->WriteLineToFile("[" + name + "]");
// Write program and library credits
if (name == "Script Info") {
@ -346,17 +346,17 @@ void FormatHandlerASS::WriteSection(TextFileWriter &writer,ConstSection section)
String programURL = GetHostApplicationURL();
String libVersion = GetLibraryVersionString();
String libURL = GetLibraryURL();
writer.WriteLineToFile("; Script generated by " + programName);
if (!programURL.IsEmpty()) writer.WriteLineToFile("; " + programURL);
writer.WriteLineToFile("; With " + libVersion);
if (programURL != libURL) writer.WriteLineToFile("; " + libURL);
writer->WriteLineToFile("; Script generated by " + programName);
if (!programURL.IsEmpty()) writer->WriteLineToFile("; " + programURL);
writer->WriteLineToFile("; With " + libVersion);
if (programURL != libURL) writer->WriteLineToFile("; " + libURL);
}
// Write properties
size_t props = section->GetPropertyCount();
for (size_t i=0;i<props;i++) {
String propName = section->GetPropertyName(i);
writer.WriteLineToFile(propName + ": " + section->GetProperty(propName));
writer->WriteLineToFile(propName + ": " + section->GetProperty(propName));
}
// Write contents
@ -364,7 +364,7 @@ void FormatHandlerASS::WriteSection(TextFileWriter &writer,ConstSection section)
for (size_t i=0;i<entries;i++) {
ConstEntry entry = section->GetEntry(i);
shared_ptr<const SerializeText> serial = dynamic_pointer_cast<const SerializeText>(entry);
writer.WriteLineToFile(serial->ToText(formatVersion));
writer->WriteLineToFile(serial->ToText(formatVersion));
}
}

View file

@ -46,7 +46,7 @@ namespace Athenasub {
// Prototypes
class CModel;
class TextFileWriter;
class TextWriter;
// Advanced Substation Alpha format handler
class FormatHandlerASS : public CFormatHandler {
@ -55,7 +55,7 @@ namespace Athenasub {
Entry MakeEntry(const String &data,Section section,int version);
void ProcessGroup(String cur,String &curGroup,int &version);
void WriteSection(TextFileWriter &writer,ConstSection section) const;
void WriteSection(shared_ptr<TextWriter> writer,ConstSection section) const;
void MakeValid(IModel &model);
public:

View file

@ -49,13 +49,11 @@ using namespace Athenasub;
///////////////
// Constructor
TextFileReader::TextFileReader(wxInputStream &stream,String enc,bool _trim,bool prefetch)
TextFileReader::TextFileReader(wxInputStream &stream,String enc,bool _trim)
: file(stream)
{
// Setup
trim = _trim;
threaded = prefetch && false;
thread = NULL;
// Set encoding
encoding = enc.GetWxString();
@ -68,8 +66,6 @@ TextFileReader::TextFileReader(wxInputStream &stream,String enc,bool _trim,bool
// Destructor
TextFileReader::~TextFileReader()
{
wxCriticalSectionLocker locker(mutex);
if (thread) thread->Delete();
}
@ -191,7 +187,7 @@ void ParseLine(FastBuffer<T> &_buffer,wxInputStream &file,String &stringBuffer,s
//////////////////////////
// Reads a line from file
Athenasub::String TextFileReader::ActuallyReadLine()
Athenasub::String TextFileReader::ReadLineFromFile()
{
String stringBuffer;
size_t bufAlloc = 1024;
@ -225,8 +221,6 @@ Athenasub::String TextFileReader::ActuallyReadLine()
// Checks if there's more to read
bool TextFileReader::HasMoreLines()
{
if (cache.size()) return true;
wxCriticalSectionLocker locker(mutex);
return (!file.Eof() || buffer1.GetSize() || buffer2.GetSize());
}
@ -252,68 +246,9 @@ String TextFileReader::GetCurrentEncoding()
}
///////////////////////////
// Reads a line from cache
String TextFileReader::ReadLineFromFile()
///////////////////
// Rewind the file
void TextFileReader::Rewind()
{
// Not threaded, just return it
if (!threaded) return ActuallyReadLine();
// Load into cache if needed
String final;
{
wxCriticalSectionLocker locker(mutex);
if (cache.size() == 0) {
cache.push_back(ActuallyReadLine());
}
}
{
// Retrieve from cache
wxCriticalSectionLocker locker(mutex);
if (cache.size()) {
final = cache.front();
cache.pop_front();
}
// Start the thread to prefetch more
if (cache.size() < 3 && thread == NULL) {
thread = new PrefetchThread(this);
thread->Create();
thread->Run();
}
}
return final;
}
////////////////
// Thread entry
wxThread::ExitCode PrefetchThread::Entry()
{
// Lock
bool run = true;
while (run) {
if (TestDestroy()) {
parent->thread = NULL;
return 0;
}
{
wxCriticalSectionLocker locker(parent->mutex);
if (parent->cache.size() < 6) {
if (!parent->file.Eof()) {
// Get line
parent->cache.push_back(parent->ActuallyReadLine());
}
else run = false;
}
}
Sleep(50);
}
// Die
wxCriticalSectionLocker locker(parent->mutex);
parent->thread = NULL;
return 0;
}

View file

@ -1,4 +1,4 @@
// Copyright (c) 2005, Rodrigo Braz Monteiro
// Copyright (c) 2008, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -39,19 +39,15 @@
// Headers
#include "athenasub.h"
#include "text_reader.h"
#include "fastbuffer.h"
#include <wx/stream.h>
namespace Athenasub {
// Text file reader
class TextFileReader {
friend class PrefetchThread;
class TextFileReader : public TextReader {
private:
wxCriticalSection mutex;
std::list<String> cache;
FastBuffer<char> buffer1;
FastBuffer<wchar_t> buffer2;
@ -62,33 +58,21 @@ namespace Athenasub {
bool isUtf8;
bool swap;
bool trim;
bool threaded;
wxThread *thread;
void SetEncodingConfiguration();
String ActuallyReadLine();
public:
TextFileReader(wxInputStream &stream,String encoding="",bool trim=true,bool prefetch=true);
TextFileReader(wxInputStream &stream,String encoding="",bool trim=true);
~TextFileReader();
String ReadLineFromFile();
bool HasMoreLines();
void Rewind();
static void EnsureValid(const String encoding);
String GetCurrentEncoding();
static String GetEncoding(const String filename);
};
// Prefetch thread
class PrefetchThread : public wxThread {
private:
TextFileReader *parent;
public:
wxThread::ExitCode Entry();
PrefetchThread(TextFileReader *_parent) : parent(_parent) {}
};
}

View file

@ -35,12 +35,13 @@
#pragma once
#include "Athenasub.h"
#include "athenasub.h"
#include "text_writer.h"
#include <wx/stream.h>
namespace Athenasub {
class TextFileWriter {
class TextFileWriter : public TextWriter {
private:
wxString encoding;
wxOutputStream &file;

View file

@ -0,0 +1,45 @@
// Copyright (c) 2008, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
// Headers
#include "text_reader.h"
#include "text_file_reader.h"
using namespace Athenasub;
shared_ptr<TextReader> TextReader::GetReader(wxInputStream &stream,String encoding)
{
return shared_ptr<TextReader>(new TextFileReader(stream,encoding));
}

View file

@ -0,0 +1,55 @@
// Copyright (c) 2008, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
#pragma once
// Headers
#include "athenasub.h"
namespace Athenasub {
class TextReader {
public:
virtual ~TextReader() {}
virtual String ReadLineFromFile() = 0;
virtual bool HasMoreLines() = 0;
virtual void Rewind() = 0;
static shared_ptr<TextReader> GetReader(wxInputStream &stream,String encoding);
};
}

View file

@ -0,0 +1,45 @@
// Copyright (c) 2008, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
// Headers
#include "text_writer.h"
#include "text_file_writer.h"
using namespace Athenasub;
shared_ptr<TextWriter> TextWriter::GetWriter(wxOutputStream &stream,String encoding)
{
return shared_ptr<TextWriter>(new TextFileWriter(stream,encoding));
}

View file

@ -0,0 +1,53 @@
// Copyright (c) 2008, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
#pragma once
// Headers
#include "athenasub.h"
namespace Athenasub {
class TextWriter {
public:
virtual ~TextWriter() {}
virtual void WriteLineToFile(String line,bool addLineBreak=true) = 0;
static shared_ptr<TextWriter> GetWriter(wxOutputStream &stream,String encoding);
};
}