diff --git a/aegisub/build/libaegisub_vs2008/libaegisub_vs2008.vcproj b/aegisub/build/libaegisub_vs2008/libaegisub_vs2008.vcproj
index e125cbc06..e06fa785d 100644
--- a/aegisub/build/libaegisub_vs2008/libaegisub_vs2008.vcproj
+++ b/aegisub/build/libaegisub_vs2008/libaegisub_vs2008.vcproj
@@ -505,32 +505,32 @@
+
+
-
-
diff --git a/aegisub/build/msbuild/libaegisub/libaegisub.vcxproj b/aegisub/build/msbuild/libaegisub/libaegisub.vcxproj
index a46e9a9ad..a262bd495 100644
--- a/aegisub/build/msbuild/libaegisub/libaegisub.vcxproj
+++ b/aegisub/build/msbuild/libaegisub/libaegisub.vcxproj
@@ -83,6 +83,9 @@
Create
lagi_pre.h
+
+
+
@@ -107,8 +110,5 @@
-
-
-
-
\ No newline at end of file
+
diff --git a/aegisub/build/msbuild/libaegisub/libaegisub.vcxproj.filters b/aegisub/build/msbuild/libaegisub/libaegisub.vcxproj.filters
index 59d3ba579..0ad646cf3 100644
--- a/aegisub/build/msbuild/libaegisub/libaegisub.vcxproj.filters
+++ b/aegisub/build/msbuild/libaegisub/libaegisub.vcxproj.filters
@@ -193,19 +193,19 @@
Source Files\Common
+
+ cajun
+
+
+ cajun
+
+
+ cajun
+
Header Files
-
- cajun
-
-
- cajun
-
-
- cajun
-
-
\ No newline at end of file
+
diff --git a/aegisub/libaegisub/Makefile b/aegisub/libaegisub/Makefile
index 374ea516d..f76f7b3de 100644
--- a/aegisub/libaegisub/Makefile
+++ b/aegisub/libaegisub/Makefile
@@ -20,6 +20,9 @@ common/charset_conv.o: CXXFLAGS += $(CFLAGS_ICONV)
unix/path.o: CXXFLAGS += -DP_DATA=\"$(P_DATA)\" -DP_DOC=\"$(P_DOC)\" -DP_LOCALE=\"$(P_LOCALE)\"
SRC = \
+ common/cajun/elements.cpp \
+ common/cajun/reader.cpp \
+ common/cajun/writer.cpp \
common/charset.cpp \
common/charset_conv.cpp \
common/charset_ucd.cpp \
diff --git a/aegisub/libaegisub/common/cajun/elements.cpp b/aegisub/libaegisub/common/cajun/elements.cpp
new file mode 100644
index 000000000..c3f9b97ce
--- /dev/null
+++ b/aegisub/libaegisub/common/cajun/elements.cpp
@@ -0,0 +1,174 @@
+/**********************************************
+
+License: BSD
+Project Webpage: http://cajun-jsonapi.sourceforge.net/
+Author: Terry Caton
+***********************************************/
+
+#include "libaegisub/cajun/elements.h"
+
+#include "libaegisub/cajun/visitor.h"
+
+#ifndef LAGI_PRE
+#include
+#include
+#endif
+
+namespace json
+{
+
+/////////////////////////
+// UnknownElement members
+class CastVisitor : public ConstVisitor
+{
+ virtual void Visit(const Array&) { }
+ virtual void Visit(const Object&) { }
+ virtual void Visit(const Number&) { }
+ virtual void Visit(const String&) { }
+ virtual void Visit(const Boolean&) { }
+ virtual void Visit(const Null&) { }
+};
+
+template
+class CastVisitor_T : public CastVisitor
+{
+public:
+ const ElementTypeT *element;
+ CastVisitor_T() : element(0) { }
+
+ // we don't know what this is, but it overrides one of the base's no-op functions
+ void Visit(const ElementTypeT& element) { this->element = &element; }
+};
+
+class UnknownElement::Imp
+{
+public:
+ virtual ~Imp() {}
+ virtual Imp* Clone() const = 0;
+
+ virtual bool Compare(const Imp& imp) const = 0;
+
+ virtual void Accept(ConstVisitor& visitor) const = 0;
+ virtual void Accept(Visitor& visitor) = 0;
+};
+
+
+template
+class UnknownElement::Imp_T : public UnknownElement::Imp
+{
+public:
+ Imp_T(const ElementTypeT& element) : m_Element(element) {}
+ virtual Imp* Clone() const { return new Imp_T(*this); }
+
+ virtual void Accept(ConstVisitor& visitor) const { visitor.Visit(m_Element); }
+ virtual void Accept(Visitor& visitor) { visitor.Visit(m_Element); }
+
+ virtual bool Compare(const Imp& imp) const
+ {
+ CastVisitor_T castVisitor;
+ imp.Accept(castVisitor);
+ return castVisitor.element && m_Element == *castVisitor.element;
+ }
+
+private:
+ ElementTypeT m_Element;
+};
+
+UnknownElement::UnknownElement() : m_pImp( new Imp_T( Null() ) ) {}
+UnknownElement::UnknownElement(const UnknownElement& unknown) : m_pImp( unknown.m_pImp->Clone()) {}
+UnknownElement::UnknownElement(const Object& object) : m_pImp( new Imp_T