Merge all changes from the libaegisub branch into trunk, the effective range is r4175:4330. All options have been re-done and now use Cajun to support a json-backed format.

Initial support for low-level access and file I/O methods are included as well.

Originally committed to SVN as r4331.
This commit is contained in:
Amar Takhar 2010-05-21 01:13:36 +00:00
parent 23972b10bc
commit 40e12403d5
141 changed files with 6681 additions and 2960 deletions

View file

@ -14,6 +14,7 @@ ffmpegsource = libffms
endif
SUBDIRS = \
libaegisub \
$(ffmpegsource) \
$(libass) \
$(univchardet) \

View file

@ -22,7 +22,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="1"
InheritedPropertySheets=".\suffix_debug32.vsprops;.\wxlib_include.vsprops;.\wxlib_lib32.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\compiler_options_debug.vsprops;.\svn_rev_header_update.vsprops;.\delayload_portaudio_32.vsprops;.\delayload_openal_32.vsprops"
InheritedPropertySheets=".\suffix_debug32.vsprops;.\wxlib_include.vsprops;.\wxlib_lib32.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\compiler_options_debug.vsprops;.\svn_rev_header_update.vsprops;.\delayload_portaudio_32.vsprops;.\delayload_openal_32.vsprops;.\libaegisub_include_dir.vsprops"
CharacterSet="1"
>
<Tool
@ -88,7 +88,7 @@
<Configuration
Name="Debug|x64"
ConfigurationType="1"
InheritedPropertySheets=".\suffix_debug64.vsprops;.\wxlib_include.vsprops;.\wxlib_lib64.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\compiler_options_debug.vsprops;.\svn_rev_header_update.vsprops"
InheritedPropertySheets=".\suffix_debug64.vsprops;.\wxlib_include.vsprops;.\wxlib_lib64.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\compiler_options_debug.vsprops;.\svn_rev_header_update.vsprops;.\libaegisub_include_dir.vsprops"
CharacterSet="1"
>
<Tool
@ -154,7 +154,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="1"
InheritedPropertySheets=".\suffix_release32.vsprops;.\wxlib_include.vsprops;.\wxlib_lib32.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\svn_rev_header_update.vsprops;.\delayload_portaudio_32.vsprops;.\delayload_openal_32.vsprops"
InheritedPropertySheets=".\suffix_release32.vsprops;.\wxlib_include.vsprops;.\wxlib_lib32.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\svn_rev_header_update.vsprops;.\delayload_portaudio_32.vsprops;.\delayload_openal_32.vsprops;.\libaegisub_include_dir.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
@ -223,7 +223,7 @@
<Configuration
Name="Release|x64"
ConfigurationType="1"
InheritedPropertySheets=".\suffix_release64.vsprops;.\wxlib_include.vsprops;.\wxlib_lib64.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\svn_rev_header_update.vsprops"
InheritedPropertySheets=".\suffix_release64.vsprops;.\wxlib_include.vsprops;.\wxlib_lib64.vsprops;.\libraries_outdirs.vsprops;.\contrib_includedirs.vsprops;.\aegisub_exe_filename.vsprops;.\ffms2_lib_include_dir.vsprops;.\compiler_options.vsprops;.\svn_rev_header_update.vsprops;.\libaegisub_include_dir.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
@ -1103,14 +1103,6 @@
RelativePath="..\..\src\dialog_kara_timing_copy.h"
>
</File>
<File
RelativePath="..\..\src\dialog_options.cpp"
>
</File>
<File
RelativePath="..\..\src\dialog_options.h"
>
</File>
<File
RelativePath="..\..\src\dialog_paste_over.cpp"
>
@ -1255,10 +1247,62 @@
RelativePath="..\..\src\dialog_video_details.h"
>
</File>
<File
RelativePath="..\..\src\preferences.cpp"
>
</File>
</Filter>
<Filter
Name="Core"
>
<File
RelativePath="..\..\src\agi_pre.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\agi_pre.h"
>
</File>
<File
RelativePath="..\..\src\compat.cpp"
>
</File>
<File
RelativePath="..\..\src\compat.h"
>
</File>
<File
RelativePath="..\..\src\frame_main.cpp"
>
@ -1307,46 +1351,6 @@
RelativePath="..\..\src\setup.cpp"
>
</File>
<File
RelativePath="..\..\src\agi_pre.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\agi_pre.h"
>
</File>
<File
RelativePath="..\..\src\subs_edit_box.cpp"
>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="libaegisub_include_dir"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\libaegisub\include&quot;"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="compiler_options"
>
<Tool
Name="VCCLCompilerTool"
EnableIntrinsicFunctions="true"
RuntimeLibrary="2"
OpenMP="true"
WarningLevel="3"
WarnAsError="true"
DebugInformationFormat="3"
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateManifest="true"
GenerateDebugInformation="true"
SubSystem="2"
LargeAddressAware="2"
DataExecutionPrevention="2"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="compiler_options_debug"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
InlineFunctionExpansion="0"
EnableIntrinsicFunctions="false"
WholeProgramOptimization="false"
PreprocessorDefinitions="DEBUG;_DEBUG;_CRT_SECURE_NO_WARNINGS"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
BufferSecurityCheck="true"
EnableFunctionLevelLinking="true"
DebugInformationFormat="4"
EnablePREfast="true"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
RandomizedBaseAddress="1"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,226 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="libaegisub_vs2008"
ProjectGUID="{8732F2B6-B3C6-4AE8-986A-2A334E33334B}"
RootNamespace="libaegisub_vs2008"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="4"
InheritedPropertySheets=".\wxlib_include.vsprops;.\libraries_outdirs.vsprops;.\compiler_options_debug.vsprops;..\aegisub_vs2008\wxlib_lib32.vsprops;..\aegisub_vs2008\suffix_debug32.vsprops;.\precomp_header.vsprops;.\src_msvc_include_dir.vsprops"
CharacterSet="1"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="4"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="4"
InheritedPropertySheets=".\wxlib_include.vsprops;.\libraries_outdirs.vsprops;.\compiler_options.vsprops;..\aegisub_vs2008\wxlib_lib32.vsprops;..\aegisub_vs2008\suffix_release32.vsprops;.\precomp_header.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
</Configuration>
<Configuration
Name="Debug|x64"
ConfigurationType="4"
InheritedPropertySheets=".\wxlib_include.vsprops;.\libraries_outdirs.vsprops;.\compiler_options_debug.vsprops;..\aegisub_vs2008\wxlib_lib64.vsprops;..\aegisub_vs2008\suffix_debug64.vsprops;.\precomp_header.vsprops"
CharacterSet="1"
>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="3"
/>
</Configuration>
<Configuration
Name="Release|x64"
ConfigurationType="4"
InheritedPropertySheets=".\wxlib_include.vsprops;.\libraries_outdirs.vsprops;.\compiler_options.vsprops;..\aegisub_vs2008\wxlib_lib64.vsprops;..\aegisub_vs2008\suffix_release64.vsprops;.\precomp_header.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Common"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\libaegisub\common\mru.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\common\option.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\common\option_visit.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\common\option_visit.h"
>
</File>
<File
RelativePath="..\..\libaegisub\common\validator.cpp"
>
</File>
</Filter>
<Filter
Name="Windows"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\..\libaegisub\windows\access.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\windows\io.cpp"
>
</File>
<File
RelativePath="..\..\libaegisub\windows\lagi_pre.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\libaegisub\windows\util.cpp"
>
</File>
</Filter>
<Filter
Name="Include"
>
<File
RelativePath="..\..\libaegisub\include\libaegisub\access.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\colour.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\exception.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\io.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\mru.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\option.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\option_value.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\util.h"
>
</File>
<File
RelativePath="..\..\libaegisub\include\libaegisub\validator.h"
>
</File>
</Filter>
<File
RelativePath="..\..\libaegisub\lagi_pre.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="standard_outdirs"
OutputDirectory="$(SolutionDir)build/$(ProjectName)/$(PlatformName)/$(ConfigurationName)/"
IntermediateDirectory="$(OutDir)"
>
<Tool
Name="VCLibrarianTool"
OutputFile="$(LibraryOutDir)/$(ProjectName).lib"
/>
<Tool
Name="VCLinkerTool"
OutputFile=""
AdditionalLibraryDirectories="$(LibraryOutDir)"
ImportLibrary="$(LibraryOutDir)$(TargetName).lib"
/>
<UserMacro
Name="LibraryOutDir"
Value="$(SolutionDir)lib/$(PlatformName)/$(ConfigurationName)/"
/>
<UserMacro
Name="ExecutableOutDir"
Value="$(SolutionDir)bin/"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="precomp_header"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="../../libaegisub/lagi_pre.h"
ForcedIncludeFiles="../../libaegisub/lagi_pre.h"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="src_msvc_include_dir"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\src\msvc&quot;"
/>
</VisualStudioPropertySheet>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="wxlib_include"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(SolutionDir)/wxlib/include/&quot;;&quot;$(ProjectDir)../../libaegisub/include/&quot;"
/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories="&quot;$(SolutionDir)/wxlib/include/&quot;"
/>
</VisualStudioPropertySheet>

View file

@ -1204,6 +1204,7 @@ AC_CONFIG_FILES([
Makefile
automation/Makefile
desktop/Makefile
libaegisub/Makefile
libass/Makefile
libffms/Makefile
po/Makefile.in
@ -1214,6 +1215,7 @@ src/libosxutil/Makefile
src/libresrc/Makefile
tools/Makefile
universalchardet/Makefile
tests/Makefile
])
# Files that need substitution.

View file

@ -0,0 +1,12 @@
@INCLUDE = doxyfile_base
PROJECT_NAME = "libaegisub"
INPUT = ../../libaegisub/ ./pages_libaegisub
EXCLUDE_PATTERNS = */.svn* */.deps* */.libs*
PREDEFINED += \
__WINDOWS__ \
__UNIX__ \
__OSX__

View file

@ -17,6 +17,9 @@ case "$1" in
"reporter")
TRIM="${SRC_PWD}/reporter/"
;;
"libaegisub")
TRIM="${SRC_PWD}/libaegisub/"
;;
esac
export OUTPUT_DIR="$2"

View file

@ -0,0 +1,7 @@
/**
@defgroup base Base
@defgroup unix Unix
@defgroup windows Windows
@defgroup osx OS X
@defgroup io File I/O
*/

View file

@ -0,0 +1,11 @@
/** @mainpage
Main
- @ref base
Library
- @ref unix
- @ref windows
- @ref osx
- @ref io
*/

View file

@ -0,0 +1,5 @@
/** @page License libaegisub License
@verbinclude "LICENCE"
*/

View file

@ -0,0 +1,32 @@
# $Id$
AUTOMAKE_OPTIONS = subdir-objects
AM_CXXFLAGS=
DISTCLEANFILES=
lib_LTLIBRARIES = libaegisub-2.2.la
libaegisub_2_2_la_CPPFLAGS = -I../src/include -Iinclude -I. @WX_CPPFLAGS@
if PRECOMPILED_HEADER
BUILT_SOURCES = lagi_pre.h.gch
AM_CXXFLAGS += -include lagi_pre.h -Winvalid-pch -fpch-deps -fpch-preprocess
nodist_libaegisub_2_2_la_SOURCES = lagi_pre.h.gch
endif
if PRECOMPILED_HEADER
# This doesn't depend on Makefile on purpose, you should already know what you're doing when using this.
lagi_pre.h.gch: lagi_pre.h
@CXX@ $(libaegisub_2_2_la_CPPFLAGS) @CXXFLAGS@ @DEBUG_FLAGS@ -fPIC -DPIC lagi_pre.h
DISTCLEANFILES += lagi_pre.h.gch
endif
libaegisub_2_2_la_SOURCES = \
common/mru.cpp \
common/option.cpp \
common/option_visit.cpp \
common/validator.cpp \
unix/util.cpp \
unix/io.cpp \
unix/access.cpp
noinst_HEADERS = *.h

View file

@ -0,0 +1,203 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// $Id$
/// @file mru.cpp
/// @brief Most Recently Used (MRU) Lists
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <fstream>
#include <time.h>
#endif
#include "libaegisub/access.h"
#include "libaegisub/mru.h"
#include "libaegisub/io.h"
namespace agi {
MRUManager::MRUManager(const std::string &config, const std::string &default_config): config_name(config) {
json::UnknownElement root;
std::istream *stream;
try {
stream = io::Open(config);
} catch (const acs::AcsNotFound&) {
stream = new std::istringstream(default_config);
}
try {
json::Reader::Read(root, *stream);
} catch (const json::Exception&) {
/// @todo Do something better here, maybe print the exact error
// std::cout << "json::Exception: " << e.what() << std::endl;
stream = new std::istringstream(default_config);
json::Reader::Read(root, *stream);
}
const json::Object& root_new = (json::Object)root;
json::Object::const_iterator index_object(root_new.Begin()), index_objectEnd(root_new.End());
for (; index_object != index_objectEnd; ++index_object) {
const json::Object::Member& member = *index_object;
const std::string &member_name = member.name;
const json::UnknownElement& element = member.element;
Load(member_name, (json::Array)element);
}
delete stream;
}
MRUManager::~MRUManager() {
Flush();
}
void MRUManager::Add(const std::string &key, const std::string &entry) {
MRUMap::iterator index;
if ((index = mru.find(key)) != mru.end()) {
MRUListMap &map = *index->second;
// Remove the file before adding it.
Remove(key, entry);
map.insert(std::pair<time_t, std::string>(time(NULL), entry));
Prune(map);
} else {
throw MRUErrorInvalidKey("Invalid key value");
}
}
void MRUManager::Remove(const std::string &key, const std::string &entry) {
MRUMap::iterator index;
if ((index = mru.find(key)) != mru.end()) {
MRUListMap map = *index->second;
for (MRUListMap::iterator map_idx = map.begin(); map_idx != map.end();) {
if (map_idx->second == entry)
map.erase(map_idx++);
else
++map_idx;
}
} else {
throw MRUErrorInvalidKey("Invalid key value");
}
}
const MRUManager::MRUListMap* MRUManager::Get(const std::string &key) {
MRUMap::iterator index;
if ((index = mru.find(key)) != mru.end()) {
return index->second;
} else {
throw MRUErrorInvalidKey("Invalid key value");
}
}
const std::string MRUManager::GetEntry(const std::string &key, const int entry) {
const MRUManager::MRUListMap *map = Get(key);
MRUListMap::const_iterator index = map->begin();;
if ((unsigned int)entry > map->size())
throw MRUErrorIndexOutOfRange("Requested element index is out of range.");
std::advance(index, entry);
return index->second;
}
void MRUManager::Flush() {
json::Object out;
for (MRUMap::const_iterator i = mru.begin(); i != mru.end(); ++i) {
json::Array array;
MRUListMap *map_list = i->second;
for (MRUListMap::const_iterator i_lst = map_list->begin(); i_lst != map_list->end(); ++i_lst) {
json::Object obj;
obj["time"] = json::Number((double)i_lst->first);
obj["entry"] = json::String(i_lst->second);
array.Insert(obj);
}
out[i->first] = array;
}
io::Save file(config_name);
std::ofstream& ofp = file.Get();
json::Writer::Write(out, ofp);
}
/// @brief Prune MRUListMap to the desired length.
/// This uses the user-set values for MRU list length.
inline void MRUManager::Prune(MRUListMap& map) {
unsigned int size = 16;
MRUListMap::iterator index = map.begin();;
if (map.size() >= size) {
std::advance(index, size);
// Use a range incase the storage number shrinks.
map.erase(index, map.end());
}
}
/// @brief Load MRU Lists.
/// @param key List name.
/// @param array json::Array of values.
void MRUManager::Load(const std::string &key, const json::Array& array) {
json::Array::const_iterator index(array.Begin()), indexEnd(array.End());
MRUListMap *map = new MRUListMap();
for (; index != indexEnd; ++index) {
const json::Object& obj = *index;
time_t time = (time_t)(json::Number)obj["time"];
std::string entry = (json::String)obj["entry"];
map->insert(std::pair<time_t, std::string>(time, entry));
}
mru.insert(std::pair<std::string, MRUListMap*>(key, map));
Prune(*map);
}
}

View file

@ -0,0 +1,237 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// $Id$
/// @file option.cpp
/// @brief Option interface.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <fstream>
#include <sstream>
#include <map>
#endif
#include "libaegisub/io.h"
#include "option_visit.h"
namespace agi {
Options::Options(const std::string &file, const std::string& default_config):
config_file(file), config_default(default_config), config_loaded(false) {
std::istringstream stream(default_config);
LoadConfig(stream);
}
Options::~Options() {
Flush();
}
void Options::ConfigNext(std::istream& stream) {
LoadConfig(stream);
}
void Options::ConfigUser() {
std::istream *stream = agi::io::Open(config_file);
LoadConfig(*stream);
config_loaded = true;
delete stream;
}
void Options::LoadConfig(std::istream& stream) {
/// @todo Store all previously loaded configs in an array for bug report purposes,
/// this is just a temp stub.
json::UnknownElement config_root;
try {
json::Reader::Read(config_root, stream);
} catch (json::Reader::ParseException& e) {
std::cout << "json::ParseException: " << e.what() << ", Line/offset: " << e.m_locTokenBegin.m_nLine + 1 << '/' << e.m_locTokenBegin.m_nLineOffset + 1 << std::endl << std::endl;
} catch (json::Exception& e) {
/// @todo Do something better here, maybe print the exact error
std::cout << "json::Exception: " << e.what() << std::endl;
}
ConfigVisitor config_visitor(values, std::string(""));
config_root.Accept(config_visitor);
}
OptionValue* Options::Get(const std::string &name) {
OptionValueMap::iterator index;
if ((index = values.find(name)) != values.end())
return index->second;
std::cout << "agi::Options::Get Option not found: (" << name << ")" << std::endl;
throw OptionErrorNotFound("Option value not found");
}
void Options::Flush() {
json::Object obj_out;
bool ok;
for (OptionValueMap::const_iterator i = values.begin(); i != values.end(); ++i) {
std::string key = i->first.substr(i->first.rfind("/")+1, i->first.size());
int type = i->second->GetType();
switch (type) {
case OptionValue::Type_String: {
ok = PutOption(obj_out, i->first, (json::String)i->second->GetString());
}
break;
case OptionValue::Type_Int:
ok = PutOption(obj_out, i->first, (json::Number)(const double)i->second->GetInt());
break;
case OptionValue::Type_Double:
ok = PutOption(obj_out, i->first, (json::Number)i->second->GetDouble());
break;
case OptionValue::Type_Colour: {
std::string str = std::string(i->second->GetColour());
ok = PutOption(obj_out, i->first, (json::String)str);
}
break;
case OptionValue::Type_Bool:
ok = PutOption(obj_out, i->first, (json::Boolean)i->second->GetBool());
break;
case OptionValue::Type_List_String: {
std::vector<std::string> array_string;
i->second->GetListString(array_string);
json::Array array;
for (std::vector<std::string>::const_iterator i_str = array_string.begin(); i_str != array_string.end(); ++i_str) {
json::Object obj;
obj["string"] = json::String(*i_str);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
case OptionValue::Type_List_Int: {
std::vector<int64_t> array_int;
i->second->GetListInt(array_int);
json::Array array;
for (std::vector<int64_t>::const_iterator i_int = array_int.begin(); i_int != array_int.end(); ++i_int) {
json::Object obj;
obj["int"] = json::Number((const double)*i_int);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
case OptionValue::Type_List_Double: {
std::vector<double> array_double;
i->second->GetListDouble(array_double);
json::Array array;
for (std::vector<double>::const_iterator i_double = array_double.begin(); i_double != array_double.end(); ++i_double) {
json::Object obj;
obj["double"] = json::Number(*i_double);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
case OptionValue::Type_List_Colour: {
std::vector<Colour> array_colour;
i->second->GetListColour(array_colour);
json::Array array;
for (std::vector<Colour>::const_iterator i_colour = array_colour.begin(); i_colour != array_colour.end(); ++i_colour) {
json::Object obj;
Colour col = *i_colour;
std::string str = std::string(col);
obj["colour"] = json::String(str);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
case OptionValue::Type_List_Bool: {
std::vector<bool> array_bool;
json::Array array;
i->second->GetListBool(array_bool);
for (std::vector<bool>::const_iterator i_bool = array_bool.begin(); i_bool != array_bool.end(); ++i_bool) {
json::Object obj;
obj["bool"] = json::Boolean(*i_bool);
array.Insert(obj);
}
ok = PutOption(obj_out, i->first, (json::Array)array);
}
break;
}
}
io::Save file(config_file);
json::Writer::Write(obj_out, file.Get());
}
bool Options::PutOption(json::Object &obj, const std::string &path, const json::UnknownElement &value) {
// Having a '/' denotes it is a leaf.
if (path.find('/') == std::string::npos) {
json::Object::iterator pos = obj.Find(path);
// Fail if a key of the same name already exists.
if (pos != obj.End())
throw OptionErrorDuplicateKey("Key already exists");
obj.Insert(json::Object::Member(path, value));
return true;
} else {
std::string thispart = path.substr(0, path.find("/"));
std::string restpart = path.substr(path.find("/")+1, path.size());
json::Object::iterator pos = obj.Find(thispart);
// New key, make object.
if (pos == obj.End())
pos = obj.Insert(json::Object::Member(thispart, json::Object()));
PutOptionVisitor visitor(restpart, value);
pos->element.Accept(visitor);
return visitor.result;
}
}
} // namespace agi

View file

@ -0,0 +1,242 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// $Id$
/// @file option_visit.cpp
/// @brief Cajun JSON visitor to load config values.
/// @see option_visit.h
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <math.h>
#include <wx/colour.h>
#include <wx/wxcrtvararg.h>
#endif
#include <libaegisub/colour.h>
#include "option_visit.h"
namespace agi {
ConfigVisitor::ConfigVisitor(OptionValueMap &val, const std::string &member_name): values(val) {
// Corropsonding code is in AddOptionValue()
name = member_name + "/";
}
ConfigVisitor::~ConfigVisitor() {
}
void ConfigVisitor::Visit(const json::Object& object) {
json::Object::const_iterator index(object.Begin()), index_end(object.End());
for (; index != index_end; ++index) {
const json::Object::Member& member = *index;
const std::string &member_name = member.name;
const json::UnknownElement& element = member.element;
ConfigVisitor config_visitor(values, name + member_name);
element.Accept(config_visitor);
}
}
void ConfigVisitor::Visit(const json::Array& array) {
int init = 0;
OptionValueList *array_list;
json::Array::const_iterator index(array.Begin()), indexEnd(array.End());
for (; index != indexEnd; ++index) {
const json::Object& index_array = *index;
json::Object::const_iterator index_object(index_array.Begin()), index_objectEnd(index_array.End());
for (; index_object != index_objectEnd; ++index_object) {
const json::Object::Member& member = *index_object;
const std::string& member_name = member.name;
// This can only happen once since a list must always be of the same
// type, if we try inserting another type into it we want it to fail.
if (!init) {
if (member_name == "string") {
array_list = new OptionValueListString(name);
} else if (member_name == "int") {
array_list = new OptionValueListInt(name);
} else if (member_name == "double") {
array_list = new OptionValueListDouble(name);
} else if (member_name == "bool") {
array_list = new OptionValueListBool(name);
} else if (member_name == "colour") {
array_list = new OptionValueListColour(name);
} else {
throw OptionJsonValueArray("Array type not handled");
}
init = 1;
}
try {
if (member_name == "string") {
std::string val = (json::String)member.element;
array_list->InsertString(val);
} else if (member_name == "int") {
int64_t val = (int64_t)(json::Number)member.element;
array_list->InsertInt(val);
} else if (member_name == "double") {
double val = (json::Number)member.element;
array_list->InsertDouble(val);
} else if (member_name == "bool") {
bool val = (json::Boolean)member.element;
array_list->InsertBool(val);
} else if (member_name == "colour") {
std::string val = (json::String)member.element;
Colour col(val);
array_list->InsertColour(col);
}
AddOptionValue(array_list);
} catch (agi::Exception&) {
throw OptionJsonValueArray("Attempt to insert value into array of wrong type");
}
} // for index_object
} // for index
}
void ConfigVisitor::Visit(const json::Number& number) {
double val = number.Value();
if (int64_t(val) == ceil(val)) {
OptionValue *opt = new OptionValueInt(name, int64_t(val));
AddOptionValue(opt);
} else {
OptionValue *opt = new OptionValueDouble(name, val);
AddOptionValue(opt);
}
}
void ConfigVisitor::Visit(const json::String& string) {
OptionValue *opt;
if (string.Value().find("rgb(") == 0) {
opt = new OptionValueColour(name, string.Value());
} else {
opt = new OptionValueString(name, string.Value());
}
AddOptionValue(opt);
}
void ConfigVisitor::Visit(const json::Boolean& boolean) {
OptionValue *opt = new OptionValueBool(name, boolean.Value());
AddOptionValue(opt);
}
void ConfigVisitor::Visit(const json::Null& null) {
throw OptionJsonValueNull("Attempt to read null value");
}
void ConfigVisitor::AddOptionValue(OptionValue* opt) {
// Corrosponding code is in the constuctor.
std::string stripped = name.substr(1, name.rfind("/")-1);
OptionValue *opt_cur;
OptionValueMap::iterator index;
if ((index = values.find(stripped)) != values.end()) {
opt_cur = index->second;
} else {
values.insert(OptionValuePair(stripped, opt));
return;
}
int type = opt_cur->GetType();
switch (type) {
case OptionValue::Type_String:
opt_cur->SetString(opt->GetString());
break;
case OptionValue::Type_Int:
opt_cur->SetInt(opt->GetInt());
break;
case OptionValue::Type_Double:
opt_cur->SetDouble(opt->GetDouble());
break;
case OptionValue::Type_Colour:
opt_cur->SetColour(opt->GetColour());
break;
case OptionValue::Type_Bool:
opt_cur->SetBool(opt->GetBool());
break;
case OptionValue::Type_List_String: {
std::vector<std::string> array;
opt->GetListString(array);
opt_cur->SetListString(array);
break;
}
case OptionValue::Type_List_Int: {
std::vector<int64_t> array;
opt->GetListInt(array);
opt_cur->SetListInt(array);
break;
}
case OptionValue::Type_List_Double: {
std::vector<double> array;
opt->GetListDouble(array);
opt_cur->SetListDouble(array);
break;
}
case OptionValue::Type_List_Colour: {
std::vector<Colour> array;
opt->GetListColour(array);
opt_cur->SetListColour(array);
break;
}
case OptionValue::Type_List_Bool: {
std::vector<bool> array;
opt->GetListBool(array);
opt_cur->SetListBool(array);
break;
}
}
}
} // namespace agi

View file

@ -0,0 +1,83 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// $Id$
/// @file option_visit.h
/// @brief Cajun JSON visitor to load config values.
/// @see option_visit.cpp
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include "libaegisub/cajun/elements.h"
#include "libaegisub/cajun/visitor.h"
#endif
#pragma once
#include "libaegisub/option.h"
namespace agi {
DEFINE_BASE_EXCEPTION_NOINNER(OptionJsonValueError, Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueArray, OptionJsonValueError, "options/value/array")
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueSingle, OptionJsonValueError, "options/value")
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueNull, OptionJsonValueError, "options/value")
class ConfigVisitor : public json::ConstVisitor {
OptionValueMap &values;
std::string name;
typedef std::pair<std::string, OptionValue*> OptionValuePair;
void AddOptionValue(OptionValue* opt);
public:
ConfigVisitor(OptionValueMap &val, const std::string &member_name);
~ConfigVisitor();
void Visit(const json::Array& array);
void Visit(const json::Object& object);
void Visit(const json::Number& number);
void Visit(const json::String& string);
void Visit(const json::Boolean& boolean);
void Visit(const json::Null& null);
};
class PutOptionVisitor : public json::Visitor {
public:
bool result;
const std::string &path;
const json::UnknownElement &value;
PutOptionVisitor(const std::string &path, const json::UnknownElement &value)
: result(false), path(path), value(value)
{}
// all of these are a fail
virtual void Visit(json::Array& array) { }
virtual void Visit(json::Number& number) { }
virtual void Visit(json::String& string) { }
virtual void Visit(json::Boolean& boolean) { }
virtual void Visit(json::Null& null) { }
// this one is the win
virtual void Visit(json::Object& object) {
result = Options::PutOption(object, path, value);
}
};
} // namespace agi

View file

@ -0,0 +1,73 @@
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// $Id$
/// @file validator.cpp
/// @brief Input validation.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#endif
#include <libaegisub/validator.h>
namespace agi {
bool ValidAny::CheckType(std::string &value) {
return true;
}
bool ValidAny::Check(std::string &value) {
return true;
}
bool ValidString::CheckType(std::string &value) {
return true;
}
bool ValidString::Check(std::string &value) {
return CheckType(value);
}
bool ValidInt::CheckType(std::string &value) {
return true;
}
bool ValidInt::Check(std::string &value) {
return CheckType(value);
}
bool ValidBool::CheckType(std::string &value) {
return true;
}
bool ValidBool::Check(std::string &value) {
return CheckType(value);
}
bool ValidColour::Check(std::string &value) {
if (ValidString::CheckType(value)) {
// check if it's a valid colour
return 1;
}
return 0;
}
} // namespace agi