From 0c5d122cc5e69ae434540a9cf5aa83ce0be56e68 Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Sat, 8 Mar 2008 03:08:50 +0000 Subject: [PATCH] Some early work to get the subs lib to work. Originally committed to SVN as r1965. --- aegilib/aegilib.vcproj | 10 +- aegilib/include/aegilib/aegilib.h | 1 + aegilib/include/aegilib/aegistring.h | 2 +- aegilib/include/aegilib/exception.h | 60 ++++ aegilib/include/aegilib/file.h | 4 + aegilib/include/aegilib/format.h | 2 +- aegilib/include/aegilib/model.h | 12 +- aegilib/include/aegilib/notification.h | 1 + aegilib/src/exception.cpp | 66 ++++ aegilib/src/manipulator.cpp | 2 +- aegilib/src/model.cpp | 27 ++ aegilib/test/src/main.cpp | 63 ++++ aegilib/test/src/text_file_reader.cpp | 352 +++++++++++++++++++++ aegilib/test/src/text_file_reader.h | 87 +++++ aegilib/test/src/text_file_writer.cpp | 152 +++++++++ aegilib/test/src/text_file_writer.h | 76 +++++ aegilib/test/test.vcproj | 217 +++++++++++++ build/aegisub_vs2005/aegisub_vs2005.vcproj | 12 +- 18 files changed, 1132 insertions(+), 14 deletions(-) create mode 100644 aegilib/include/aegilib/exception.h create mode 100644 aegilib/src/exception.cpp create mode 100644 aegilib/test/src/main.cpp create mode 100644 aegilib/test/src/text_file_reader.cpp create mode 100644 aegilib/test/src/text_file_reader.h create mode 100644 aegilib/test/src/text_file_writer.cpp create mode 100644 aegilib/test/src/text_file_writer.h create mode 100644 aegilib/test/test.vcproj diff --git a/aegilib/aegilib.vcproj b/aegilib/aegilib.vcproj index df8209ed3..6949467ae 100644 --- a/aegilib/aegilib.vcproj +++ b/aegilib/aegilib.vcproj @@ -1,7 +1,7 @@ + + @@ -227,6 +231,10 @@ + + diff --git a/aegilib/include/aegilib/aegilib.h b/aegilib/include/aegilib/aegilib.h index 201a78c30..fbc649be7 100644 --- a/aegilib/include/aegilib/aegilib.h +++ b/aegilib/include/aegilib/aegilib.h @@ -41,3 +41,4 @@ #include "aegistring.h" #include "format.h" #include "manipulator.h" +#include "exception.h" diff --git a/aegilib/include/aegilib/aegistring.h b/aegilib/include/aegilib/aegistring.h index 563d289d7..f1d774872 100644 --- a/aegilib/include/aegilib/aegistring.h +++ b/aegilib/include/aegilib/aegistring.h @@ -38,6 +38,6 @@ namespace Aegilib { // Define the string type used throughout this library - typedef wxString String; + typedef std::basic_string String; }; diff --git a/aegilib/include/aegilib/exception.h b/aegilib/include/aegilib/exception.h new file mode 100644 index 000000000..dd05e4a28 --- /dev/null +++ b/aegilib/include/aegilib/exception.h @@ -0,0 +1,60 @@ +// 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/AEGILIB +// +// Website: http://www.aegisub.net +// Contact: mailto:amz@aegisub.net +// + +#pragma once + +#include "aegilib.h" + +namespace Aegilib { + + // Exception class + class Exception { + public: + enum ExceptionList { + Unknown, + No_Format_Handler, + Invalid_Manipulator + }; + + Exception(ExceptionList code); + + String GetMessage(); + int GetCode(); + + private: + ExceptionList code; + }; + +}; diff --git a/aegilib/include/aegilib/file.h b/aegilib/include/aegilib/file.h index 82587b4f8..cd7d56d32 100644 --- a/aegilib/include/aegilib/file.h +++ b/aegilib/include/aegilib/file.h @@ -41,6 +41,8 @@ namespace Aegilib { // File reader interface class FileReader { public: + virtual ~FileReader() {} + virtual String ReadLineFromFile() = 0; virtual bool HasMoreLines() = 0; virtual String GetCurrentEncoding() = 0; @@ -49,6 +51,8 @@ namespace Aegilib { // File writer interface class FileWriter { public: + virtual ~FileWriter() {} + virtual void WriteLineToFile(String line,bool addLineBreak=true) = 0; }; diff --git a/aegilib/include/aegilib/format.h b/aegilib/include/aegilib/format.h index e02b9ef96..1488463f9 100644 --- a/aegilib/include/aegilib/format.h +++ b/aegilib/include/aegilib/format.h @@ -58,7 +58,7 @@ namespace Aegilib { virtual bool HasMargins() const { return false; } virtual bool HasActors() const { return false; } virtual bool HasUserField() const { return false; } - virtual String GetUserFieldName() const { return _T(""); } + virtual String GetUserFieldName() const { return L""; } virtual int GetTimingPrecision() const { return 10; } // In milliseconds virtual int GetMaxTime() const { return 36000000-10; } // In milliseconds, default 9h 59min 59.99s diff --git a/aegilib/include/aegilib/model.h b/aegilib/include/aegilib/model.h index aa144afbd..37b86b039 100644 --- a/aegilib/include/aegilib/model.h +++ b/aegilib/include/aegilib/model.h @@ -65,13 +65,13 @@ namespace Aegilib { const Format& GetFormat() const; void AddListener(View *listener); - void LoadFile(FileReader &file); - void SaveFile(FileWriter &file); + void LoadFile(FileReader &file,Format *format=NULL); + void SaveFile(FileWriter &file,Format *format=NULL); - bool CanUndo(String owner=_T("")) const; - bool CanRedo(String owner=_T("")) const; - bool Undo(String owner=_T("")); - bool Redo(String owner=_T("")); + bool CanUndo(String owner=L"") const; + bool CanRedo(String owner=L"") const; + bool Undo(String owner=L""); + bool Redo(String owner=L""); }; }; diff --git a/aegilib/include/aegilib/notification.h b/aegilib/include/aegilib/notification.h index 540248a93..35800ce74 100644 --- a/aegilib/include/aegilib/notification.h +++ b/aegilib/include/aegilib/notification.h @@ -34,6 +34,7 @@ // #pragma once +#include #include "model.h" #include "notification.h" diff --git a/aegilib/src/exception.cpp b/aegilib/src/exception.cpp new file mode 100644 index 000000000..8685cc72c --- /dev/null +++ b/aegilib/src/exception.cpp @@ -0,0 +1,66 @@ +// 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/AEGILIB +// +// Website: http://www.aegisub.net +// Contact: mailto:amz@aegisub.net +// + +#include "exception.h" +using namespace Aegilib; + + +/////////////// +// Constructor +Exception::Exception(ExceptionList _code) +{ + code = _code; +} + + +////////////////////// +// Get message string +String Exception::GetMessage() +{ + switch (code) { + case Unknown: return L"Unknown."; + case No_Format_Handler: return L"Could not find a suitable format handler."; + case Invalid_Manipulator: return L"Invalid manipulator."; + } + return L"Invalid code."; +} + + +//////////// +// Get code +int Exception::GetCode() +{ + return code; +} diff --git a/aegilib/src/manipulator.cpp b/aegilib/src/manipulator.cpp index 82e5b3731..b2240b955 100644 --- a/aegilib/src/manipulator.cpp +++ b/aegilib/src/manipulator.cpp @@ -59,7 +59,7 @@ Manipulator::~Manipulator() // Add an action to the queue void Manipulator::AddAction(const Action &action) { - if (!valid) throw 0; // TODO + if (!valid) throw Exception(Exception::Invalid_Manipulator); actions.push_back(action); } diff --git a/aegilib/src/model.cpp b/aegilib/src/model.cpp index e63919e5e..da3175c92 100644 --- a/aegilib/src/model.cpp +++ b/aegilib/src/model.cpp @@ -82,3 +82,30 @@ Manipulator Model::CreateAntiManipulator(const Manipulator &src) // TODO return dst; } + + +/////////////// +// Load a file +void Model::LoadFile(FileReader &file,Format *format) +{ + // Detect format + if (format == NULL) { + // TODO + } + + // No format found + throw Exception(Exception::No_Format_Handler); + + // Load + (void) file; +} + + +////////////////// +// Save to a file +void Model::SaveFile(FileWriter &file,Format *format) +{ + (void) file; + (void) format; + // TODO +} diff --git a/aegilib/test/src/main.cpp b/aegilib/test/src/main.cpp new file mode 100644 index 000000000..f8a11a718 --- /dev/null +++ b/aegilib/test/src/main.cpp @@ -0,0 +1,63 @@ +// 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/AEGILIB +// +// Website: http://www.aegisub.net +// Contact: mailto:amz@aegisub.net +// + +#include +#include +#include "text_file_reader.h" +#include "text_file_writer.h" + +int main () { + using namespace std; + using namespace Aegilib; + + cout << "Aegilib test program by amz.\n\n"; + + // Subtitles model + Model subs; + + // Load subtitles + cout << "Loading file... "; + subs.LoadFile(TextFileReader(L"subs_in.ass")); + cout << "Done.\n"; + + // Modify subtitles + cout << "Modifying file..."; + cout << "Done.\n"; + + // Save subtitles + cout << "Saving file... "; + subs.SaveFile(TextFileWriter(L"subs_out.ass")); + cout << "Done.\n"; +} diff --git a/aegilib/test/src/text_file_reader.cpp b/aegilib/test/src/text_file_reader.cpp new file mode 100644 index 000000000..3ae6a4f51 --- /dev/null +++ b/aegilib/test/src/text_file_reader.cpp @@ -0,0 +1,352 @@ +// Copyright (c) 2005, 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 +#include +#include +#include "text_file_reader.h" + +#ifdef WITH_UNIVCHARDET +#include "charset_detect.h" +#endif + + +/////////////// +// Constructor +TextFileReader::TextFileReader(Aegilib::String _filename,Aegilib::String enc,bool _trim) { + // Setup + open = false; + customConv = false; + trim = _trim; + filename = _filename; + + // Open file + Open(); + + // Set encoding + encoding = enc.c_str(); + if (encoding.IsEmpty()) encoding = GetEncoding(filename.c_str()); + if (encoding == _T("binary")) return; + SetEncodingConfiguration(); +} + + +////////////// +// Destructor +TextFileReader::~TextFileReader() { + Close(); + + // Clean up conversion + if (customConv) delete conv; +} + + +/////////////////////////// +// Determine file encoding +Aegilib::String TextFileReader::GetEncoding(const Aegilib::String _filename) { + // Prepare + using namespace std; + unsigned char b[4]; + for (int i=0;i<4;i++) b[i] = 0; + + // Read four bytes from file +#ifdef TEXT_READER_USE_STDIO + // TODO: maybe make this use posix-style fopen() api's instead as well? + HANDLE ifile = CreateFile( + _filename.c_str(), // filename + FILE_READ_DATA, // access mode + FILE_SHARE_READ, // share mode + 0, // security descriptor + OPEN_EXISTING, // creation disposition + FILE_FLAG_SEQUENTIAL_SCAN, // flags + 0); // template file + if (ifile == INVALID_HANDLE_VALUE) { + return _T("unknown"); + } + DWORD numread; + if (!ReadFile(ifile, (char*)b, 4, &numread, 0)) { + // Unable to open + return _T("unknown"); + } + if (numread < 4) { + // File too short to decide, assume local + return _T("Local"); + } + CloseHandle(ifile); +#else + ifstream ifile; +#ifdef WIN32 + ifile.open(_filename.c_str()); +#else + ifile.open(wxFNCONV(_filename)); +#endif + if (!ifile.is_open()) { + return _T("unknown"); + } + ifile.read((char*)b,4); + ifile.close(); +#endif + + // Try to get the byte order mark from them + if (b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF) return _T("UTF-8"); + else if (b[0] == 0xFF && b[1] == 0xFE && b[2] == 0x00 && b[3] == 0x00) return _T("UTF-32LE"); + else if (b[0] == 0x00 && b[1] == 0x00 && b[2] == 0xFE && b[3] == 0xFF) return _T("UTF-32BE"); + else if (b[0] == 0xFF && b[1] == 0xFE) return _T("UTF-16LE"); + else if (b[0] == 0xFE && b[1] == 0xFF) return _T("UTF-16BE"); + else if (b[0] == 0x2B && b[1] == 0x2F && b[2] == 0x76) return _T("UTF-7"); + + // Try to guess UTF-16 + else if (b[0] == 0 && b[1] >= 32 && b[2] == 0 && b[3] >= 32) return _T("UTF-16BE"); + else if (b[0] >= 32 && b[1] == 0 && b[2] >= 32 && b[3] == 0) return _T("UTF-16LE"); + + // If any of the first four bytes are under 0x20 (the first printable character), + // except for 9-13 range, assume binary + for (int i=0;i<4;i++) { + if (b[i] < 9 || (b[i] > 13 && b[i] < 32)) return _T("binary"); + } + + #ifdef WITH_UNIVCHARDET + // Use universalchardet library to detect charset + CharSetDetect det; + return det.GetEncoding(_filename); + #else + // Fall back to local + return _T("Local"); + #endif +} + + +////////////////////////////// +// Set encoding configuration +void TextFileReader::SetEncodingConfiguration() { + // Set encoding configuration + swap = false; + Is16 = false; + customConv = false; + conv = NULL; + if (encoding == _T("UTF-8")) { + conv = new wxMBConvUTF8; + customConv = true; + } + else if (encoding == _T("UTF-16LE")) { + Is16 = true; + } + else if (encoding == _T("UTF-16BE")) { + Is16 = true; + swap = true; + } + else if (encoding == _T("UTF-7")) { + conv = new wxCSConv(encoding); + customConv = true; + } + else if (encoding == _T("Local")) { + conv = wxConvCurrent; + } + else { + conv = new wxCSConv(encoding); + customConv = true; + } +} + + +////////////////////////// +// Reads a line from file +Aegilib::String TextFileReader::ReadLineFromFile() { + Open(); + wxString wxbuffer; + size_t bufAlloc = 1024; + wxbuffer.Alloc(bufAlloc); +#ifdef TEXT_READER_USE_STDIO + char buffer[512]; + buffer[0] = 0; +#else + std::string buffer = ""; +#endif + + // Read UTF-16 line from file + if (Is16) { + char charbuffer[3]; + charbuffer[2] = 0; + wchar_t ch = 0; + size_t len = 0; +#ifdef TEXT_READER_USE_STDIO + while (ch != L'\n' && !feof(file)) { + // Read two chars from file + fread(charbuffer, 2, 1, file); +#else + while (ch != L'\n' && !file.eof()) { + // Read two chars from file + charbuffer[0] = 0; + charbuffer[1] = 0; + file.read(charbuffer,2); +#endif + + // Swap bytes for big endian + if (swap) { + register char aux = charbuffer[0]; + charbuffer[0] = charbuffer[1]; + charbuffer[1] = aux; + } + + // Convert two chars into a widechar and append to string + ch = *((wchar_t*)charbuffer); + if (len >= bufAlloc - 1) { + bufAlloc *= 2; + wxbuffer.Alloc(bufAlloc); + } + wxbuffer += ch; + len++; + } + } + + // Read ASCII/UTF-8 line from file + else { +#ifdef TEXT_READER_USE_STDIO + while (1) { + buffer[511] = '\1'; + if (fgets(buffer, 512, file)) { + // read succeeded + // FIXME, this might break on incomplete multibyte characters + wxString linepart(buffer, *conv); + wxbuffer += linepart; + if (buffer[511] == '\1' || buffer[510] == '\n') { + // our sentinel \1 wasn't overwritten, meaning an EOL was found + break; + } + // otherwise the sentinel \1 was overwritten (presumably with \0), so just loop on + } + else { + // hit EOF + break; + } + } +#else + getline(file,buffer); + wxbuffer.Clear(); + if (buffer.length()) wxbuffer = wxString(buffer.c_str(),*conv); +#endif + } + + // Remove line breaks + //wxbuffer.Replace(_T("\r"),_T("\0")); + //wxbuffer.Replace(_T("\n"),_T("\0")); + size_t len=wxbuffer.Length(); + for (size_t i=0;i 0 && wxbuffer[0] == 0xFEFF) { + wxbuffer = wxbuffer.Mid(1); + } + + // Trim + if (trim) { + wxbuffer.Trim(true); + wxbuffer.Trim(false); + } + return Aegilib::String(wxbuffer.c_str()); +} + + +///////////// +// Open file +void TextFileReader::Open() { + if (open) return; +#ifdef TEXT_READER_USE_STDIO + // binary mode, because ascii mode is never to be trusted + file = _tfopen(filename.c_str(), _T("rb")); + if (file == 0) { + throw _T("Failed opening file for reading."); + } +#else +#ifdef WIN32 + file.open(filename.wc_str(),std::ios::in | std::ios::binary); +#else + file.open(wxFNCONV(filename),std::ios::in | std::ios::binary); +#endif + if (!file.is_open()) { + throw _T("Failed opening file for reading."); + } +#endif + open = true; +} + + +////////////// +// Close file +void TextFileReader::Close() { + if (!open) return; +#ifdef TEXT_READER_USE_STDIO + fclose(file); +#else + file.close(); +#endif + open = false; +} + + +////////////////////////////////// +// Checks if there's more to read +bool TextFileReader::HasMoreLines() { +#ifdef TEXT_READER_USE_STDIO + if (encoding == _T("binary")) return false; + return !feof(file); +#else + return (!file.eof()); +#endif +} + + +//////////////////////////////// +// Ensure that charset is valid +void TextFileReader::EnsureValid(Aegilib::String enc) { + if (enc == _T("unknown") || enc == _T("UTF-32BE") || enc == _T("UTF-32LE")) { + wxString error = _T("Character set "); + error += enc; + error += _T(" is not supported."); + throw error.c_str(); + } +} + + +/////////////////////////// +// Get encoding being used +Aegilib::String TextFileReader::GetCurrentEncoding() { + return encoding.c_str(); +} diff --git a/aegilib/test/src/text_file_reader.h b/aegilib/test/src/text_file_reader.h new file mode 100644 index 000000000..80375db61 --- /dev/null +++ b/aegilib/test/src/text_file_reader.h @@ -0,0 +1,87 @@ +// Copyright (c) 2005, 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 +#include +#include +#include +#ifdef TEXT_READER_USE_STDIO +#include +#else +#include +#endif + + +///////// +// Class +class TextFileReader : public Aegilib::FileReader { +private: + wxString filename; + wxString encoding; +#ifdef TEXT_READER_USE_STDIO + FILE *file; +#else + std::ifstream file; +#endif + wxMBConv *conv; + bool Is16; + bool swap; + bool open; + bool customConv; + bool trim; + + void Open(); + void Close(); + void SetEncodingConfiguration(); + +public: + TextFileReader(Aegilib::String filename,Aegilib::String encoding=_T(""),bool trim=true); + ~TextFileReader(); + + Aegilib::String ReadLineFromFile(); + bool HasMoreLines(); + + static void EnsureValid(const Aegilib::String encoding); + Aegilib::String GetCurrentEncoding(); + static Aegilib::String GetEncoding(const Aegilib::String filename); +}; + + diff --git a/aegilib/test/src/text_file_writer.cpp b/aegilib/test/src/text_file_writer.cpp new file mode 100644 index 000000000..a838abbe7 --- /dev/null +++ b/aegilib/test/src/text_file_writer.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2005, 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 +#include "text_file_writer.h" + + +/////////////// +// Constructor +TextFileWriter::TextFileWriter(Aegilib::String _filename,Aegilib::String enc) { + // Setup + open = false; + customConv = false; + IsFirst = true; + filename = _filename; + + // Set encoding + encoding = enc; + if (encoding == _T("Local")) conv = &wxConvLocal; + else { + if (encoding.IsEmpty()) encoding = _T("UTF-8"); + if (encoding == _T("US-ASCII")) encoding = _T("ISO-8859-1"); + conv = new wxCSConv(encoding); + customConv = true; + IsUnicode = encoding.Left(3) == _T("UTF"); + } + + // Open file + Open(); +} + + +////////////// +// Destructor +TextFileWriter::~TextFileWriter() { + Close(); +} + + +///////////// +// Open file +void TextFileWriter::Open() { + // Open file + if (open) return; +#ifdef WIN32 + file.open(filename.wc_str(),std::ios::out | std::ios::binary | std::ios::trunc); +#else + file.open(wxFNCONV(filename),std::ios::out | std::ios::binary | std::ios::trunc); +#endif + if (!file.is_open()) { + throw _T("Failed opening file for writing."); + } + open = true; + + // Set encoding + SetEncoding(); +} + + +////////////// +// Close file +void TextFileWriter::Close() { + if (!open) return; + file.close(); + open = false; + if (customConv) delete conv; +} + + +///////////////// +// Write to file +void TextFileWriter::WriteLineToFile(Aegilib::String line,bool addLineBreak) { + // Make sure it's loaded + if (!open) Open(); + + // Add line break + wxString temp = line; + if (addLineBreak) temp += _T("\r\n"); + + // Add BOM if it's the first line and the target format is Unicode + if (IsFirst && IsUnicode) { + wchar_t bom = 0xFEFF; + temp = wxString(bom) + temp; + } + IsFirst = false; + + // 16-bit + if (Is16) { + wxWCharBuffer buf = temp.wc_str(*conv); + if (!buf.data()) + return; + size_t len = wcslen(buf.data()); + file.write((const char*)buf.data(),(std::streamsize)len*sizeof(wchar_t)); + } + + // 8-bit + else { + wxCharBuffer buf = temp.mb_str(*conv); + if (!buf.data()) + return; + size_t len = strlen(buf.data()); + file.write(buf.data(),(std::streamsize)len); + } +} + + +//////////////// +// Set encoding +void TextFileWriter::SetEncoding() { + // Prepare + Is16 = false; + + // UTF-16 + if (encoding.Left(6) == _T("UTF-16")) { + Is16 = true; + } +} diff --git a/aegilib/test/src/text_file_writer.h b/aegilib/test/src/text_file_writer.h new file mode 100644 index 000000000..b5817f922 --- /dev/null +++ b/aegilib/test/src/text_file_writer.h @@ -0,0 +1,76 @@ +// Copyright (c) 2005, 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 +// + + +#ifndef TEXT_FILE_WRITER_H +#define TEXT_FILE_WRITER_H + + +/////////// +// Headers +#include +#include +#include +#include + + +///////// +// Class +class TextFileWriter : public Aegilib::FileWriter { +private: + wxString filename; + wxString encoding; + std::ofstream file; + + wxMBConv *conv; + bool customConv; + bool open; + bool Is16; + bool IsFirst; + bool IsUnicode; + + void Open(); + void Close(); + void SetEncoding(); + +public: + TextFileWriter(Aegilib::String filename,Aegilib::String encoding=_T("")); + ~TextFileWriter(); + + void WriteLineToFile(Aegilib::String line,bool addLineBreak=true); +}; + + +#endif diff --git a/aegilib/test/test.vcproj b/aegilib/test/test.vcproj new file mode 100644 index 000000000..4b70d41ca --- /dev/null +++ b/aegilib/test/test.vcproj @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/aegisub_vs2005/aegisub_vs2005.vcproj b/build/aegisub_vs2005/aegisub_vs2005.vcproj index f2b5c5570..fae1132e3 100644 --- a/build/aegisub_vs2005/aegisub_vs2005.vcproj +++ b/build/aegisub_vs2005/aegisub_vs2005.vcproj @@ -1435,6 +1435,10 @@ RelativePath="..\..\aegisub\options.h" > + + @@ -1575,10 +1579,6 @@ RelativePath="..\..\aegisub\video_frame.h" > - - @@ -1611,6 +1611,10 @@ RelativePath="..\..\aegisub\video_provider_lavc.cpp" > + +