commit 63c6bde2acac363c8c5e7fd3d744e17ea99e20ab
Author: Malcolm Humphreys <malcolmhumphreys@gmail.com>
Date:   Thu Jan 30 12:42:21 2014 +0000

    * added support form yaml-cpp > 5.0.1
    * when yaml-cpp < 5.0.0 define OLDYAML
    * added yaml-cpp 5.0.1 tarball in preparation for moving to the new api
    * added OCIOYaml class and moved all yaml-cpp code into OCIOYaml.cpp
    * moved Config serialize code into OCIOYaml.cpp
    * added Config::setEnvironmentMode(), Config::getEnvironmentMode(), Config::loadEnvironment()
    * moved Display code from Config.cpp into it's own files

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 13e2d64..ea3fb8b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -225,13 +225,15 @@ else(USE_EXTERNAL_YAML)
     endif()
 endif(USE_EXTERNAL_YAML)
 
-
+if(YAML_CPP_VERSION VERSION_LESS "0.5.0")
+    set(YAML_CPP_COMPILE_FLAGS "-DOLDYAML")
+endif()
 
 ###############################################################################
 ### Externals ###
 
 set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}/ext/dist/include)
-set(EXTERNAL_COMPILE_FLAGS "-DTIXML_USE_STL")
+set(EXTERNAL_COMPILE_FLAGS "-DTIXML_USE_STL ${YAML_CPP_COMPILE_FLAGS}")
 
 if(CMAKE_COMPILER_IS_GNUCXX)
     
diff --git a/export/OpenColorIO/OpenColorIO.h b/export/OpenColorIO/OpenColorIO.h
index 561ce50..00716fa 100644
--- a/export/OpenColorIO/OpenColorIO.h
+++ b/export/OpenColorIO/OpenColorIO.h
@@ -279,6 +279,12 @@ OCIO_NAMESPACE_ENTER
         const char * getEnvironmentVarDefault(const char * name) const;
         //!cpp:function::
         void clearEnvironmentVars();
+        //!cpp:function::
+        void setEnvironmentMode(EnvironmentMode mode);
+        //!cpp:function::
+        EnvironmentMode getEnvironmentMode() const;
+        //!cpp:function::
+        void loadEnvironment();
         
         //!cpp:function::
         const char * getSearchPath() const;
diff --git a/ext/yaml-cpp-0.5.1.patch b/ext/yaml-cpp-0.5.1.patch
new file mode 100644
index 0000000..23433cb
--- /dev/null
+++ b/ext/yaml-cpp-0.5.1.patch
@@ -0,0 +1,12 @@
+diff -Naur yaml-cpp-0.5.1.orig/CMakeLists.txt yaml-cpp-0.5.1/CMakeLists.txt
+--- yaml-cpp-0.5.1.orig/CMakeLists.txt	2014-01-30 09:45:54.000000000 +0000
++++ yaml-cpp-0.5.1/CMakeLists.txt	2014-01-30 09:51:04.000000000 +0000
+@@ -140,7 +140,7 @@
+ 		set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
+ 	endif()
+ 	#
+-	set(CMAKE_CXX_FLAGS "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
++	set(CMAKE_CXX_FLAGS "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long -fPIC -fvisibility-inlines-hidden -fvisibility=hidden ${CMAKE_CXX_FLAGS}")
+ 	#
+ 	add_custom_target(debuggable $(MAKE) clean
+ 		COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
diff --git a/ext/yaml-cpp-0.5.1.tar.gz b/ext/yaml-cpp-0.5.1.tar.gz
new file mode 100644
index 0000000..f087742
Binary files /dev/null and b/ext/yaml-cpp-0.5.1.tar.gz differ
diff --git a/src/core/Config.cpp b/src/core/Config.cpp
index 00e1e70..82b5073 100644
--- a/src/core/Config.cpp
+++ b/src/core/Config.cpp
@@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "HashUtils.h"
 #include "Logging.h"
 #include "LookParse.h"
+#include "Display.h"
 #include "MathUtils.h"
 #include "Mutex.h"
 #include "OpBuilders.h"
@@ -208,7 +209,6 @@ OCIO_NAMESPACE_ENTER
         if(csname.empty()) return false;
         
         std::string csnamelower = pystring::lower(csname);
-        
         for(unsigned int i = 0; i < colorspaces.size(); ++i)
         {
             if(csnamelower == pystring::lower(colorspaces[i]->getName()))
@@ -220,184 +220,7 @@ OCIO_NAMESPACE_ENTER
         
         return false;
     }
-    
-    
-    // Displays
-    struct View
-    {
-        std::string name;
-        std::string colorspace;
-        std::string looks;
-        
-        View() { }
-        
-        View(const std::string & name_,
-             const std::string & colorspace_,
-             const std::string & looksList_) :
-                name(name_),
-                colorspace(colorspace_),
-                looks(looksList_)
-        { }
-    };
-    
-    typedef std::vector<View> ViewVec;
-    typedef std::map<std::string, ViewVec> DisplayMap;  // (display name : ViewVec)
-    
-    void operator >> (const YAML::Node& node, View& v)
-    {
-        if(node.Tag() != "View")
-            return;
-        
-        std::string key, stringval;
-        
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
-        {
-            iter.first() >> key;
-            
-            if(key == "name")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                    v.name = stringval;
-            }
-            else if(key == "colorspace")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                    v.colorspace = stringval;
-            }
-            else if(key == "looks" || key == "look")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                    v.looks = stringval;
-            }
-            else
-            {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
-            }
-        }
-        
-        if(v.name.empty())
-        {
-            throw Exception("View does not specify 'name'.");
-        }
-        if(v.colorspace.empty())
-        {
-            std::ostringstream os;
-            os << "View '" << v.name << "' ";
-            os << "does not specify colorspace.";
-            throw Exception(os.str().c_str());
-        }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, View view)
-    {
-        out << YAML::VerbatimTag("View");
-        out << YAML::Flow;
-        out << YAML::BeginMap;
-        out << YAML::Key << "name" << YAML::Value << view.name;
-        out << YAML::Key << "colorspace" << YAML::Value << view.colorspace;
-        if(!view.looks.empty()) out << YAML::Key << "looks" << YAML::Value << view.looks;
-        out << YAML::EndMap;
-        return out;
-    }
-    
-    DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display)
-    {
-        for(DisplayMap::iterator iter = displays.begin();
-            iter != displays.end();
-            ++iter)
-        {
-            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
-        }
-        return displays.end();
-    }
-    
-    DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display)
-    {
-        for(DisplayMap::const_iterator iter = displays.begin();
-            iter != displays.end();
-            ++iter)
-        {
-            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
-        }
-        return displays.end();
-    }
-    
-    int find_view(const ViewVec & vec, const std::string & name)
-    {
-        for(unsigned int i=0; i<vec.size(); ++i)
-        {
-            if(StrEqualsCaseIgnore(name, vec[i].name)) return i;
-        }
-        return -1;
-    }
-    
-    void AddDisplay(DisplayMap & displays,
-                    const std::string & display,
-                    const std::string & view,
-                    const std::string & colorspace,
-                    const std::string & looks)
-    {
-        DisplayMap::iterator iter = find_display(displays, display);
-        if(iter == displays.end())
-        {
-            ViewVec views;
-            views.push_back( View(view, colorspace, looks) );
-            displays[display] = views;
-        }
-        else
-        {
-            ViewVec & views = iter->second;
-            int index = find_view(views, view);
-            if(index<0)
-            {
-                views.push_back( View(view, colorspace, looks) );
-            }
-            else
-            {
-                views[index].colorspace = colorspace;
-                views[index].looks = looks;
-            }
-        }
-    }
-    
-    void ComputeDisplays(StringVec & displayCache,
-                         const DisplayMap & displays,
-                         const StringVec & activeDisplays,
-                         const StringVec & activeDisplaysEnvOverride)
-    {
-        displayCache.clear();
         
-        StringVec displayMasterList;
-        for(DisplayMap::const_iterator iter = displays.begin();
-            iter != displays.end();
-            ++iter)
-        {
-            displayMasterList.push_back(iter->first);
-        }
-        
-        // Apply the env override if it's not empty.
-        if(!activeDisplaysEnvOverride.empty())
-        {
-            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplaysEnvOverride);
-            if(!displayCache.empty()) return;
-        }
-        // Otherwise, aApply the active displays if it's not empty.
-        else if(!activeDisplays.empty())
-        {
-            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplays);
-            if(!displayCache.empty()) return;
-        }
-        
-        displayCache = displayMasterList;
-    }
-    
-    
-    
     } // namespace
     
     class Config::Impl
@@ -431,6 +254,8 @@ OCIO_NAMESPACE_ENTER
         mutable StringMap cacheids_;
         mutable std::string cacheidnocontext_;
         
+        OCIOYaml io_;
+        
         Impl() : 
             context_(Context::Create()),
             strictParsing_(true),
@@ -497,8 +322,6 @@ OCIO_NAMESPACE_ENTER
             return *this;
         }
         
-        void load(std::istream & istream, const char * name);
-        
         // Any time you modify the state of the config, you must call this
         // to reset internal cache states.  You also should do this in a
         // thread safe manner by acquiring the cacheidMutex_;
@@ -536,7 +359,7 @@ OCIO_NAMESPACE_ENTER
         istream.str(INTERNAL_RAW_PROFILE);
         
         ConfigRcPtr config = Config::Create();
-        config->getImpl()->load(istream, "");
+        config->getImpl()->io_.open(istream, config);
         return config;
     }
     
@@ -551,14 +374,14 @@ OCIO_NAMESPACE_ENTER
         }
         
         ConfigRcPtr config = Config::Create();
-        config->getImpl()->load(istream, filename);
+        config->getImpl()->io_.open(istream, config, filename);
         return config;
     }
     
     ConstConfigRcPtr Config::CreateFromStream(std::istream & istream)
     {
         ConfigRcPtr config = Config::Create();
-        config->getImpl()->load(istream, "");
+        config->getImpl()->io_.open(istream, config);
         return config;
     }
     
@@ -893,6 +716,27 @@ OCIO_NAMESPACE_ENTER
         getImpl()->resetCacheIDs();
     }
     
+    void Config::setEnvironmentMode(EnvironmentMode mode)
+    {
+        getImpl()->context_->setEnvironmentMode(mode);
+        
+        AutoMutex lock(getImpl()->cacheidMutex_);
+        getImpl()->resetCacheIDs();
+    }
+    
+    EnvironmentMode Config::getEnvironmentMode() const
+    {
+        return getImpl()->context_->getEnvironmentMode();
+    }
+    
+    void Config::loadEnvironment()
+    {
+        getImpl()->context_->loadEnvironment();
+        
+        AutoMutex lock(getImpl()->cacheidMutex_);
+        getImpl()->resetCacheIDs();
+    }
+    
     const char * Config::getSearchPath() const
     {
         return getImpl()->context_->getSearchPath();
@@ -1647,60 +1491,7 @@ OCIO_NAMESPACE_ENTER
     {
         try
         {
-            YAML::Emitter out;
-            out << YAML::Block;
-            out << YAML::BeginMap;
-            out << YAML::Key << "ocio_profile_version" << YAML::Value << 1;
-            out << YAML::Newline;
-            if(getImpl()->env_.size() > 0) {
-                out << YAML::Key << "environment";
-                out << YAML::Value << getImpl()->env_;
-                out << YAML::Newline;
-            }
-            out << YAML::Key << "search_path" << YAML::Value << getImpl()->context_->getSearchPath();
-            out << YAML::Key << "strictparsing" << YAML::Value << getImpl()->strictParsing_;
-            out << YAML::Key << "luma" << YAML::Value << YAML::Flow << getImpl()->defaultLumaCoefs_;
-            
-            if(getImpl()->description_ != "")
-            {
-                out << YAML::Newline;
-                out << YAML::Key << "description";
-                out << YAML::Value << getImpl()->description_;
-            }
-            
-            // Roles
-            out << YAML::Newline;
-            out << YAML::Key << "roles";
-            out << YAML::Value << getImpl()->roles_;
-            
-            // Displays
-            out << YAML::Newline;
-            out << YAML::Key << "displays";
-            out << YAML::Value << getImpl()->displays_;
-            out << YAML::Newline;
-            out << YAML::Key << "active_displays";
-            out << YAML::Value << YAML::Flow << getImpl()->activeDisplays_;
-            out << YAML::Key << "active_views";
-            out << YAML::Value << YAML::Flow << getImpl()->activeViews_;
-            
-            // Looks
-            if(!getImpl()->looksList_.empty())
-            {
-                out << YAML::Newline;
-                out << YAML::Key << "looks";
-                out << YAML::Value << getImpl()->looksList_;
-            }
-            
-            // ColorSpaces
-            {
-                out << YAML::Newline;
-                out << YAML::Key << "colorspaces";
-                out << YAML::Value << getImpl()->colorspaces_;
-            }
-            
-            out << YAML::EndMap;
-            
-            os << out.c_str();
+            getImpl()->io_.write(os, this);
         }
         catch( const std::exception & e)
         {
@@ -1710,246 +1501,6 @@ OCIO_NAMESPACE_ENTER
         }
     }
     
-    void Config::Impl::load(std::istream & istream, const char * filename)
-    {
-        try
-        {
-            YAML::Parser parser(istream);
-            YAML::Node node;
-            parser.GetNextDocument(node);
-            
-            // check profile version
-            int profile_version = 0;
-            if(node.FindValue("ocio_profile_version") == NULL)
-            {
-                std::ostringstream os;
-                os << "The specified file ";
-                os << "does not appear to be an OCIO configuration.";
-                throw Exception (os.str().c_str());
-            }
-            
-            node["ocio_profile_version"] >> profile_version;
-            if(profile_version > 1)
-            {
-                std::ostringstream os;
-                os << "This .ocio config ";
-                if(filename && *filename)
-                {
-                    os << " '" << filename << "' ";
-                }
-                os << "is version " << profile_version << ". ";
-                os << "This version of the OpenColorIO library (" << OCIO_VERSION ") ";
-                os << "is not known to be able to load this profile. ";
-                os << "An attempt will be made, but there are no guarantees that the ";
-                os << "results will be accurate. Continue at your own risk.";
-                LogWarning(os.str());
-            }
-            
-            
-            std::string key, stringval;
-            bool boolval = false;
-            EnvironmentMode mode = ENV_ENVIRONMENT_LOAD_ALL;
-            
-            for (YAML::Iterator iter = node.begin();
-                 iter != node.end();
-                 ++iter)
-            {
-                iter.first() >> key;
-                
-                if(key == "ocio_profile_version") { } // Already handled above.
-                else if(key == "environment")
-                {
-                    mode = ENV_ENVIRONMENT_LOAD_PREDEFINED;
-                    const YAML::Node& environment = iter.second();
-                    if(environment.Type() != YAML::NodeType::Map)
-                    {
-                        std::ostringstream os;
-                        os << "'environment' field needs to be a (name: key) map.";
-                        throw Exception(os.str().c_str());
-                    }
-                    for (YAML::Iterator it  = environment.begin();
-                                        it != environment.end(); ++it)
-                    {
-                        std::string k, v;
-                        it.first() >> k;
-                        it.second() >> v;
-                        env_[k] = v;
-                        context_->setStringVar(k.c_str(), v.c_str());
-                    }
-                }
-                else if(key == "search_path" || key == "resource_path")
-                {
-                    if (iter.second().Type() != YAML::NodeType::Null && 
-                        iter.second().Read<std::string>(stringval))
-                        context_->setSearchPath(stringval.c_str());
-                }
-                else if(key == "strictparsing")
-                {
-                    if (iter.second().Type() != YAML::NodeType::Null && 
-                        iter.second().Read<bool>(boolval))
-                        strictParsing_ = boolval;
-                }
-                else if(key == "description")
-                {
-                    if (iter.second().Type() != YAML::NodeType::Null && 
-                        iter.second().Read<std::string>(stringval))
-                        description_ = stringval;
-                }
-                else if(key == "luma")
-                {
-                    std::vector<float> val;
-                    if (iter.second().Type() != YAML::NodeType::Null)
-                    {
-                        iter.second() >> val;
-                        if(val.size() != 3)
-                        {
-                            std::ostringstream os;
-                            os << "'luma' field must be 3 ";
-                            os << "floats. Found '" << val.size() << "'.";
-                            throw Exception(os.str().c_str());
-                        }
-                        defaultLumaCoefs_ = val;
-                    }
-                }
-                else if(key == "roles")
-                {
-                    const YAML::Node& roles = iter.second();
-                    if(roles.Type() != YAML::NodeType::Map)
-                    {
-                        std::ostringstream os;
-                        os << "'roles' field needs to be a (name: key) map.";
-                        throw Exception(os.str().c_str());
-                    }
-                    for (YAML::Iterator it  = roles.begin();
-                                        it != roles.end(); ++it)
-                    {
-                        std::string k, v;
-                        it.first() >> k;
-                        it.second() >> v;
-                        roles_[pystring::lower(k)] = v;
-                    }
-                }
-                else if(key == "displays")
-                {
-                    if (iter.second().Type() != YAML::NodeType::Null)
-                    {
-                        iter.second() >> displays_;
-                    }
-                }
-                else if(key == "active_displays")
-                {
-                    if (iter.second().Type() != YAML::NodeType::Null)
-                    {
-                        iter.second() >> activeDisplays_;
-                    }
-                }
-                else if(key == "active_views")
-                {
-                    if (iter.second().Type() != YAML::NodeType::Null)
-                    {
-                        iter.second() >> activeViews_;
-                    }
-                }
-                else if(key == "colorspaces")
-                {
-                    const YAML::Node& colorspaces = iter.second();
-                    
-                    if(colorspaces.Type() != YAML::NodeType::Sequence)
-                    {
-                        std::ostringstream os;
-                        os << "'colorspaces' field needs to be a (- !<ColorSpace>) list.";
-                        throw Exception(os.str().c_str());
-                    }
-                    
-                    for(unsigned i = 0; i < colorspaces.size(); ++i)
-                    {
-                        if(colorspaces[i].Tag() == "ColorSpace")
-                        {
-                            ColorSpaceRcPtr cs = ColorSpace::Create();
-                            colorspaces[i] >> cs;
-                            colorspaces_.push_back( cs );
-                        }
-                        else
-                        {
-                            std::ostringstream os;
-                            os << "Unknown element found in colorspaces:";
-                            os << colorspaces[i].Tag() << ". Only ColorSpace(s)";
-                            os << " currently handled.";
-                            LogWarning(os.str());
-                        }
-                    }
-                }
-                else if(key == "looks")
-                {
-                    const YAML::Node& looks = iter.second();
-                    
-                    if(looks.Type() != YAML::NodeType::Sequence)
-                    {
-                        std::ostringstream os;
-                        os << "'looks' field needs to be a (- !<Look>) list.";
-                        throw Exception(os.str().c_str());
-                    }
-                    
-                    for(unsigned i = 0; i < looks.size(); ++i)
-                    {
-                        if(looks[i].Tag() == "Look")
-                        {
-                            LookRcPtr look = Look::Create();
-                            looks[i] >> look;
-                            looksList_.push_back( look );
-                        }
-                        else
-                        {
-                            std::ostringstream os;
-                            os << "Unknown element found in looks:";
-                            os << looks[i].Tag() << ". Only Look(s)";
-                            os << " currently handled.";
-                            LogWarning(os.str());
-                        }
-                    }
-                }
-                else
-                {
-                    LogUnknownKeyWarning("profile", iter.first());
-                }
-            }
-            
-            if(filename)
-            {
-                std::string realfilename = pystring::os::path::abspath(filename);
-                std::string configrootdir = pystring::os::path::dirname(realfilename);
-                context_->setWorkingDir(configrootdir.c_str());
-            }
-            
-            context_->setEnvironmentMode(mode);
-            context_->loadEnvironment();
-            
-            if(mode == ENV_ENVIRONMENT_LOAD_ALL)
-            {
-                std::ostringstream os;
-                os << "This .ocio config ";
-                if(filename && *filename)
-                {
-                    os << " '" << filename << "' ";
-                }
-                os << "has no environment section defined. The default behaviour is to ";
-                os << "load all environment variables (" << context_->getNumStringVars() << ")";
-                os << ", which reduces the efficiency of OCIO's caching. Considering ";
-                os << "predefining the environment variables used.";
-                LogDebug(os.str());
-            }
-            
-        }
-        catch( const std::exception & e)
-        {
-            std::ostringstream os;
-            os << "Error: Loading the OCIO profile ";
-            if(filename) os << "'" << filename << "' ";
-            os << "failed. " << e.what();
-            throw Exception(os.str().c_str());
-        }
-    }
-    
     void Config::Impl::resetCacheIDs()
     {
         cacheids_.clear();
@@ -2287,9 +1838,7 @@ OIIO_ADD_TEST(Config, SanityCheck)
     std::istringstream is;
     is.str(SIMPLE_PROFILE);
     OCIO::ConstConfigRcPtr config;
-    OIIO_CHECK_NO_THOW(config = OCIO::Config::CreateFromStream(is));
-    
-    OIIO_CHECK_THOW(config->sanityCheck(), OCIO::Exception);
+    OIIO_CHECK_THOW(config = OCIO::Config::CreateFromStream(is), OCIO::Exception);
     }
     
     {
@@ -2330,8 +1879,6 @@ OIIO_ADD_TEST(Config, EnvCheck)
     "colorspaces:\n"
     "  - !<ColorSpace>\n"
     "      name: raw\n"
-    "  - !<ColorSpace>\n"
-    "      name: raw\n"
     "strictparsing: false\n"
     "roles:\n"
     "  default: raw\n"
@@ -2345,8 +1892,6 @@ OIIO_ADD_TEST(Config, EnvCheck)
     "colorspaces:\n"
     "  - !<ColorSpace>\n"
     "      name: raw\n"
-    "  - !<ColorSpace>\n"
-    "      name: raw\n"
     "strictparsing: false\n"
     "roles:\n"
     "  default: raw\n"
@@ -2370,7 +1915,6 @@ OIIO_ADD_TEST(Config, EnvCheck)
         "testbarchedder") == 0);
     OIIO_CHECK_ASSERT(strcmp(config->getCurrentContext()->resolveStringVar("${SHOW}"),
         "bar") == 0);
-    OIIO_CHECK_THOW(config->sanityCheck(), OCIO::Exception);
     OIIO_CHECK_ASSERT(strcmp(config->getEnvironmentVarDefault("SHOW"), "super") == 0);
     
     OCIO::ConfigRcPtr edit = config->createEditableCopy();
@@ -2403,6 +1947,10 @@ OIIO_ADD_TEST(Config, EnvCheck)
         "lighting") == 0);
     OCIO::SetLoggingLevel(loglevel);
     
+    OIIO_CHECK_EQUAL(edit->getEnvironmentMode(), OCIO::ENV_ENVIRONMENT_LOAD_PREDEFINED);
+    edit->setEnvironmentMode(OCIO::ENV_ENVIRONMENT_LOAD_ALL);
+    OIIO_CHECK_EQUAL(edit->getEnvironmentMode(), OCIO::ENV_ENVIRONMENT_LOAD_ALL);
+    
     }
 }
 
diff --git a/src/core/Display.cpp b/src/core/Display.cpp
new file mode 100644
index 0000000..7c0a1ef
--- /dev/null
+++ b/src/core/Display.cpp
@@ -0,0 +1,145 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+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 Sony Pictures Imageworks 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.
+*/
+
+#include <string>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Display.h"
+#include "ParseUtils.h"
+
+OCIO_NAMESPACE_ENTER
+{
+    
+    DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display)
+    {
+        for(DisplayMap::iterator iter = displays.begin();
+            iter != displays.end();
+            ++iter)
+        {
+            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
+        }
+        return displays.end();
+    }
+    
+    DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display)
+    {
+        for(DisplayMap::const_iterator iter = displays.begin();
+            iter != displays.end();
+            ++iter)
+        {
+            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
+        }
+        return displays.end();
+    }
+    
+    int find_view(const ViewVec & vec, const std::string & name)
+    {
+        for(unsigned int i=0; i<vec.size(); ++i)
+        {
+            if(StrEqualsCaseIgnore(name, vec[i].name)) return i;
+        }
+        return -1;
+    }
+    
+    void AddDisplay(DisplayMap & displays,
+                    const std::string & display,
+                    const std::string & view,
+                    const std::string & colorspace,
+                    const std::string & looks)
+    {
+        DisplayMap::iterator iter = find_display(displays, display);
+        if(iter == displays.end())
+        {
+            ViewVec views;
+            views.push_back( View(view, colorspace, looks) );
+            displays[display] = views;
+        }
+        else
+        {
+            ViewVec & views = iter->second;
+            int index = find_view(views, view);
+            if(index<0)
+            {
+                views.push_back( View(view, colorspace, looks) );
+            }
+            else
+            {
+                views[index].colorspace = colorspace;
+                views[index].looks = looks;
+            }
+        }
+    }
+    
+    void ComputeDisplays(StringVec & displayCache,
+                         const DisplayMap & displays,
+                         const StringVec & activeDisplays,
+                         const StringVec & activeDisplaysEnvOverride)
+    {
+        displayCache.clear();
+        
+        StringVec displayMasterList;
+        for(DisplayMap::const_iterator iter = displays.begin();
+            iter != displays.end();
+            ++iter)
+        {
+            displayMasterList.push_back(iter->first);
+        }
+        
+        // Apply the env override if it's not empty.
+        if(!activeDisplaysEnvOverride.empty())
+        {
+            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplaysEnvOverride);
+            if(!displayCache.empty()) return;
+        }
+        // Otherwise, aApply the active displays if it's not empty.
+        else if(!activeDisplays.empty())
+        {
+            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplays);
+            if(!displayCache.empty()) return;
+        }
+        
+        displayCache = displayMasterList;
+    }
+
+}
+OCIO_NAMESPACE_EXIT
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(Display, Basic)
+{
+    
+}
+
+#endif // OCIO_UNIT_TEST
\ No newline at end of file
diff --git a/src/core/Display.h b/src/core/Display.h
new file mode 100644
index 0000000..6d63a43
--- /dev/null
+++ b/src/core/Display.h
@@ -0,0 +1,85 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+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 Sony Pictures Imageworks 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.
+*/
+
+
+#ifndef INCLUDED_OCIO_DISPLAY_H
+#define INCLUDED_OCIO_DISPLAY_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "PrivateTypes.h"
+
+OCIO_NAMESPACE_ENTER
+{
+    
+    // Displays
+    struct View
+    {
+        std::string name;
+        std::string colorspace;
+        std::string looks;
+        
+        View() { }
+        
+        View(const std::string & name_,
+             const std::string & colorspace_,
+             const std::string & looksList_) :
+                name(name_),
+                colorspace(colorspace_),
+                looks(looksList_)
+        { }
+    };
+    
+    typedef std::vector<View> ViewVec;
+    typedef std::map<std::string, ViewVec> DisplayMap;  // (display name : ViewVec)
+    
+    DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display);
+    
+    DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display);
+    
+    int find_view(const ViewVec & vec, const std::string & name);
+    
+    void AddDisplay(DisplayMap & displays,
+                    const std::string & display,
+                    const std::string & view,
+                    const std::string & colorspace,
+                    const std::string & looks);
+    
+    void ComputeDisplays(StringVec & displayCache,
+                         const DisplayMap & displays,
+                         const StringVec & activeDisplays,
+                         const StringVec & activeDisplaysEnvOverride);
+    
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
\ No newline at end of file
diff --git a/src/core/OCIOYaml.cpp b/src/core/OCIOYaml.cpp
index 7089318..fc2f5f8 100644
--- a/src/core/OCIOYaml.cpp
+++ b/src/core/OCIOYaml.cpp
@@ -30,1188 +30,1787 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <OpenColorIO/OpenColorIO.h>
 
+#ifndef WINDOWS
+
+// fwd declare yaml-cpp visibility
+#pragma GCC visibility push(hidden)
+namespace YAML {
+    class Exception;
+    class BadDereference;
+    class RepresentationException;
+    class EmitterException;
+    class ParserException;
+    class InvalidScalar;
+    class KeyNotFound;
+    template <typename T> class TypedKeyNotFound;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpace>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Config>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Exception>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GpuShaderDesc>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ImageDesc>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Look>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Processor>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Transform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::AllocationTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::CDLTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpaceTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::DisplayTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ExponentTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::FileTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GroupTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LogTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LookTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::MatrixTransform>;
+    template <> class TypedKeyNotFound<OCIO_NAMESPACE::TruelightTransform>;
+}
+#pragma GCC visibility pop
+
+#endif
+
+#include <yaml-cpp/yaml.h>
+
 #include "Logging.h"
 #include "MathUtils.h"
+#include "pystring/pystring.h"
+#include "PathUtils.h"
+#include "ParseUtils.h"
+#include "Display.h"
 #include "OCIOYaml.h"
 
 OCIO_NAMESPACE_ENTER
 {
-    ///////////////////////////////////////////////////////////////////////////
-    //  Core
     
-    void LogUnknownKeyWarning(const std::string & name, const YAML::Node& tag)
+    namespace
     {
-        std::string key;
-        tag >> key;
-        
-        std::ostringstream os;
-        os << "Unknown key in " << name << ": ";
-        os << "'" << key << "'. (line ";
-        os << (tag.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
-        os << tag.GetMark().column << ")";
-        LogWarning(os.str());
-    }
     
-    void operator >> (const YAML::Node& node, ColorSpaceRcPtr& cs)
-    {
-        if(node.Tag() != "ColorSpace")
-            return; // not a !<ColorSpace> tag
+#ifdef OLDYAML
+        typedef YAML::Iterator Iterator;
+#else
+        typedef YAML::const_iterator Iterator;
+#endif
         
-        std::string key, stringval;
-        bool boolval;
+        // Iterator access
         
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
-        {
-            iter.first() >> key;
-            
-            if(key == "name")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                    cs->setName(stringval.c_str());
-            }
-            else if(key == "description")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                    cs->setDescription(stringval.c_str());
-            }
-            else if(key == "family")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                    cs->setFamily(stringval.c_str());
-            }
-            else if(key == "equalitygroup")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                    cs->setEqualityGroup(stringval.c_str());
-            }
-            else if(key == "bitdepth")
-            {
-                BitDepth ret;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<BitDepth>(ret))
-                    cs->setBitDepth(ret);
-            }
-            else if(key == "isdata")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<bool>(boolval))
-                    cs->setIsData(boolval);
-            }
-            else if(key == "allocation")
-            {
-                Allocation val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<Allocation>(val))
-                    cs->setAllocation(val);
-            }
-            else if(key == "allocationvars")
-            {
-                std::vector<float> val;
-                if (iter.second().Type() != YAML::NodeType::Null)
-                {
-                    iter.second() >> val;
-                    if(!val.empty())
-                    {
-                        cs->setAllocationVars(static_cast<int>(val.size()), &val[0]);
-                    }
-                }
-            }
-            else if(key == "to_reference")
-            {
-                TransformRcPtr val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformRcPtr>(val))
-                  cs->setTransform(val, COLORSPACE_DIR_TO_REFERENCE);
-            }
-            else if(key == "from_reference")
-            {
-                TransformRcPtr val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformRcPtr>(val))
-                  cs->setTransform(val, COLORSPACE_DIR_FROM_REFERENCE);
-            }
-            else
-            {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
-            }
-        }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceRcPtr cs)
-    {
-        out << YAML::VerbatimTag("ColorSpace");
-        out << YAML::BeginMap;
-        
-        out << YAML::Key << "name" << YAML::Value << cs->getName();
-        out << YAML::Key << "family" << YAML::Value << cs->getFamily();
-        out << YAML::Key << "equalitygroup" << YAML::Value << cs->getEqualityGroup();
-        out << YAML::Key << "bitdepth" << YAML::Value << cs->getBitDepth();
-        if(strlen(cs->getDescription()) > 0)
+        inline const YAML::Node& get_first(const Iterator it)
         {
-            out << YAML::Key << "description";
-            out << YAML::Value << YAML::Literal << cs->getDescription();
+#ifdef OLDYAML
+            return it.first();
+#else
+            return it->first;
+#endif
         }
-        out << YAML::Key << "isdata" << YAML::Value << cs->isData();
         
-        out << YAML::Key << "allocation" << YAML::Value << cs->getAllocation();
-        if(cs->getAllocationNumVars() > 0)
+        inline const YAML::Node& get_second(const Iterator it)
         {
-            std::vector<float> allocationvars(cs->getAllocationNumVars());
-            cs->getAllocationVars(&allocationvars[0]);
-            out << YAML::Key << "allocationvars";
-            out << YAML::Flow << YAML::Value << allocationvars;
+#ifdef OLDYAML
+            return it.second();
+#else
+            return it->second;
+#endif
         }
         
-        ConstTransformRcPtr toref = \
-            cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
-        if(toref)
-            out << YAML::Key << "to_reference" << YAML::Value << toref;
-        
-        ConstTransformRcPtr fromref = \
-            cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE);
-        if(fromref)
-            out << YAML::Key << "from_reference" << YAML::Value << fromref;
-        
-        out << YAML::EndMap;
-        out << YAML::Newline;
-        
-        return out;
-    }
-    
-    
-    ///////////////////////////////////////////////////////////////////////////
-    
-    // Look. (not the transform, the top-level class)
-    
-    void operator >> (const YAML::Node& node, LookRcPtr& look)
-    {
-        if(node.Tag() != "Look")
-            return;
-        
-        std::string key, stringval;
+        // Basic types
         
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
+        inline void load(const YAML::Node& node, bool& x)
         {
-            iter.first() >> key;
-            
-            if(key == "name")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                    look->setName(stringval.c_str());
-            }
-            else if(key == "process_space")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                    look->setProcessSpace(stringval.c_str());
-            }
-            else if(key == "transform")
-            {
-                TransformRcPtr val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformRcPtr>(val))
-                    look->setTransform(val);
-            }
-            else if(key == "inverse_transform")
-            {
-                TransformRcPtr val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformRcPtr>(val))
-                    look->setInverseTransform(val);
-            }
-            else
-            {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
-            }
+#ifdef OLDYAML
+            node.Read<bool>(x);
+#else
+            x = node.as<bool>();
+#endif
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, LookRcPtr look)
-    {
-        out << YAML::VerbatimTag("Look");
-        out << YAML::BeginMap;
-        out << YAML::Key << "name" << YAML::Value << look->getName();
-        out << YAML::Key << "process_space" << YAML::Value << look->getProcessSpace();
         
-        if(look->getTransform())
+        inline void load(const YAML::Node& node, int& x)
         {
-            out << YAML::Key << "transform";
-            out << YAML::Value << look->getTransform();
+#ifdef OLDYAML
+            node.Read<int>(x);
+#else
+            x = node.as<int>();
+#endif
         }
         
-        if(look->getInverseTransform())
+        inline void load(const YAML::Node& node, float& x)
         {
-            out << YAML::Key << "inverse_transform";
-            out << YAML::Value << look->getInverseTransform();
+#ifdef OLDYAML
+            node.Read<float>(x);
+#else
+            x = node.as<float>();
+#endif
         }
         
-        out << YAML::EndMap;
-        out << YAML::Newline;
+        inline void load(const YAML::Node& node, std::string& x)
+        {
+#ifdef OLDYAML
+            node.Read<std::string>(x);
+#else
+            x = node.as<std::string>();
+#endif
+        }
         
-        return out;
-    }
-    
-    
-    
-    ///////////////////////////////////////////////////////////////////////////
-    
-    
-    namespace
-    {
-        void EmitBaseTransformKeyValues(YAML::Emitter & out,
-                                        const ConstTransformRcPtr & t)
+        inline void load(const YAML::Node& node, std::vector<std::string>& x)
         {
-            if(t->getDirection() != TRANSFORM_DIR_FORWARD)
-            {
-                out << YAML::Key << "direction";
-                out << YAML::Value << YAML::Flow << t->getDirection();
-            }
+#ifdef OLDYAML
+            node >> x;
+#else
+            x = node.as<std::vector<std::string> >();
+#endif
         }
-    }
-    
-    void operator >> (const YAML::Node& node, TransformRcPtr& t)
-    {
-        if(node.Type() != YAML::NodeType::Map)
+        
+        inline void load(const YAML::Node& node, std::vector<float>& x)
         {
-            std::ostringstream os;
-            os << "Unsupported Transform type encountered: (" << node.Type() << ") in OCIO profile. ";
-            os << "Only Mapping types supported. (line ";
-            os << (node.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
-            os << node.GetMark().column << ")";
-            throw Exception(os.str().c_str());
+#ifdef OLDYAML
+            node >> x;
+#else
+            x = node.as<std::vector<float> >();
+#endif
         }
         
-        std::string type = node.Tag();
+        // Enums
         
-        if(type == "AllocationTransform") {
-            AllocationTransformRcPtr temp;
-            node.Read<AllocationTransformRcPtr>(temp);
-            t = temp;
+        inline void load(const YAML::Node& node, BitDepth& depth)
+        {
+            std::string str;
+            load(node, str);
+            depth = BitDepthFromString(str.c_str());
         }
-        else if(type == "CDLTransform") {
-            CDLTransformRcPtr temp;
-            node.Read<CDLTransformRcPtr>(temp);
-            t = temp;
+        
+        inline void save(YAML::Emitter& out, BitDepth depth)
+        {
+            out << BitDepthToString(depth);
         }
-        else if(type == "ColorSpaceTransform")  {
-            ColorSpaceTransformRcPtr temp;
-            node.Read<ColorSpaceTransformRcPtr>(temp);
-            t = temp;
+        
+        inline void load(const YAML::Node& node, Allocation& alloc)
+        {
+            std::string str;
+            load(node, str);
+            alloc = AllocationFromString(str.c_str());
         }
-        // TODO: DisplayTransform
-        else if(type == "ExponentTransform")  {
-            ExponentTransformRcPtr temp;
-            node.Read<ExponentTransformRcPtr>(temp);
-            t = temp;
+        
+        inline void save(YAML::Emitter& out, Allocation alloc)
+        {
+            out << AllocationToString(alloc);
         }
-        else if(type == "FileTransform")  {
-            FileTransformRcPtr temp;
-            node.Read<FileTransformRcPtr>(temp);
-            t = temp;
+        
+        inline void load(const YAML::Node& node, ColorSpaceDirection& dir)
+        {
+            std::string str;
+            load(node, str);
+            dir = ColorSpaceDirectionFromString(str.c_str());
         }
-        else if(type == "GroupTransform") {
-            GroupTransformRcPtr temp;
-            node.Read<GroupTransformRcPtr>(temp);
-            t = temp;
+        
+        inline void save(YAML::Emitter& out, ColorSpaceDirection dir)
+        {
+            out << ColorSpaceDirectionToString(dir);
         }
-        else if(type == "LogTransform") {
-            LogTransformRcPtr temp;
-            node.Read<LogTransformRcPtr>(temp);
-            t = temp;
+        
+        inline void load(const YAML::Node& node, TransformDirection& dir)
+        {
+            std::string str;
+            load(node, str);
+            dir = TransformDirectionFromString(str.c_str());
         }
-        else if(type == "LookTransform") {
-            LookTransformRcPtr temp;
-            node.Read<LookTransformRcPtr>(temp);
-            t = temp;
+        
+        inline void save(YAML::Emitter& out, TransformDirection dir)
+        {
+            out << TransformDirectionToString(dir);
         }
-        else if(type == "MatrixTransform")  {
-            MatrixTransformRcPtr temp;
-            node.Read<MatrixTransformRcPtr>(temp);
-            t = temp;
+        
+        inline void load(const YAML::Node& node, Interpolation& interp)
+        {
+            std::string str;
+            load(node, str);
+            interp = InterpolationFromString(str.c_str());
         }
-        else if(type == "TruelightTransform")  {
-            TruelightTransformRcPtr temp;
-            node.Read<TruelightTransformRcPtr>(temp);
-            t = temp;
+        
+        inline void save(YAML::Emitter& out, Interpolation interp)
+        {
+            out << InterpolationToString(interp);
         }
-        else
+        
+        //
+        
+        inline void LogUnknownKeyWarning(const std::string & name,
+                                         const YAML::Node& tag)
         {
-            // TODO: add a new empty (better name?) aka passthru Transform()
-            // which does nothing. This is so upsupported !<tag> types don't
-            // throw an exception. Alternativly this could be caught in the
-            // GroupTransformRcPtr >> operator with some type of
-            // supported_tag() method
-            
-            // TODO: consider the forwards-compatibility implication of
-            // throwing an exception.  Should this be a warning, instead?
-            
-            //  t = EmptyTransformRcPtr(new EmptyTransform(), &deleter);
+            std::string key;
+            load(tag, key);
+        
             std::ostringstream os;
-            os << "Unsupported transform type !<" << type << "> in OCIO profile. ";
-            os << " (line ";
-            os << (node.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
-            os << node.GetMark().column << ")";
-            throw Exception(os.str().c_str());
+            os << "Unknown key in " << name << ": '" << key << "'.";
+            LogWarning(os.str());
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstTransformRcPtr t)
-    {
-        if(ConstAllocationTransformRcPtr Allocation_tran = \
-            DynamicPtrCast<const AllocationTransform>(t))
-            out << Allocation_tran;
-        else if(ConstCDLTransformRcPtr CDL_tran = \
-            DynamicPtrCast<const CDLTransform>(t))
-            out << CDL_tran;
-        else if(ConstColorSpaceTransformRcPtr ColorSpace_tran = \
-            DynamicPtrCast<const ColorSpaceTransform>(t))
-            out << ColorSpace_tran;
-        else if(ConstExponentTransformRcPtr Exponent_tran = \
-            DynamicPtrCast<const ExponentTransform>(t))
-            out << Exponent_tran;
-        else if(ConstFileTransformRcPtr File_tran = \
-            DynamicPtrCast<const FileTransform>(t))
-            out << File_tran;
-        else if(ConstGroupTransformRcPtr Group_tran = \
-            DynamicPtrCast<const GroupTransform>(t))
-            out << Group_tran;
-        else if(ConstLogTransformRcPtr Log_tran = \
-            DynamicPtrCast<const LogTransform>(t))
-            out << Log_tran;
-        else if(ConstLookTransformRcPtr Look_tran = \
-            DynamicPtrCast<const LookTransform>(t))
-            out << Look_tran;
-        else if(ConstMatrixTransformRcPtr Matrix_tran = \
-            DynamicPtrCast<const MatrixTransform>(t))
-            out << Matrix_tran;
-        else if(ConstTruelightTransformRcPtr Truelight_tran = \
-            DynamicPtrCast<const TruelightTransform>(t))
-            out << Truelight_tran;
-        else
-            throw Exception("Unsupported Transform() type for serialization.");
-        
-        return out;
-    }
-    
-    
-    ///////////////////////////////////////////////////////////////////////////
-    //  Transforms
-    
-    void operator >> (const YAML::Node& node, GroupTransformRcPtr& t)
-    {
-        t = GroupTransform::Create();
         
-        std::string key;
+        // View
         
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
+        inline void load(const YAML::Node& node, View& v)
         {
-            iter.first() >> key;
+            if(node.Tag() != "View")
+                return;
             
-            if(key == "children")
-            {
-                const YAML::Node & children = iter.second();
-                for(unsigned i = 0; i <children.size(); ++i)
+            std::string key, stringval;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "name")
                 {
-                    TransformRcPtr childTransform;
-                    children[i].Read<TransformRcPtr>(childTransform);
-                    
-                    // TODO: consider the forwards-compatibility implication of
-                    // throwing an exception.  Should this be a warning, instead?
-                    if(!childTransform)
-                    {
-                        throw Exception("Child transform could not be parsed.");
-                    }
-                    
-                    t->push_back(childTransform);
+                    load(second, stringval);
+                    v.name = stringval;
+                }
+                else if(key == "colorspace")
+                {
+                    load(second, stringval);
+                    v.colorspace = stringval;
+                }
+                else if(key == "looks" || key == "look")
+                {
+                    load(second, stringval);
+                    v.looks = stringval;
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
                 }
             }
-            else if(key == "direction")
+            
+            if(v.name.empty())
             {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
+                throw Exception("View does not specify 'name'.");
             }
-            else
+            if(v.colorspace.empty())
             {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
+                std::ostringstream os;
+                os << "View '" << v.name << "' ";
+                os << "does not specify colorspace.";
+                throw Exception(os.str().c_str());
             }
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstGroupTransformRcPtr t)
-    {
-        out << YAML::VerbatimTag("GroupTransform");
-        out << YAML::BeginMap;
-        EmitBaseTransformKeyValues(out, t);
-        
-        out << YAML::Key << "children";
-        out << YAML::Value;
         
-        out << YAML::BeginSeq;
-        for(int i = 0; i < t->size(); ++i)
+        inline void save(YAML::Emitter& out, View view)
         {
-            out << t->getTransform(i);
+            out << YAML::VerbatimTag("View");
+            out << YAML::Flow;
+            out << YAML::BeginMap;
+            out << YAML::Key << "name" << YAML::Value << view.name;
+            out << YAML::Key << "colorspace" << YAML::Value << view.colorspace;
+            if(!view.looks.empty()) out << YAML::Key << "looks" << YAML::Value << view.looks;
+            out << YAML::EndMap;
         }
-        out << YAML::EndSeq;
-        
-        out << YAML::EndMap;
-        
-        return out;
-    }
-    
-    
-    
-    void operator >> (const YAML::Node& node, FileTransformRcPtr& t)
-    {
-        t = FileTransform::Create();
         
-        std::string key, stringval;
+        // Common Transform
         
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
+        inline void EmitBaseTransformKeyValues(YAML::Emitter & out,
+                                               const ConstTransformRcPtr & t)
         {
-            iter.first() >> key;
-            
-            if(key == "src")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setSrc(stringval.c_str());
-            }
-            else if(key == "cccid")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setCCCId(stringval.c_str());
-            }
-            else if(key == "interpolation")
-            {
-                Interpolation val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<Interpolation>(val))
-                  t->setInterpolation(val);
-            }
-            else if(key == "direction")
-            {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
-            }
-            else
+            if(t->getDirection() != TRANSFORM_DIR_FORWARD)
             {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
+                out << YAML::Key << "direction";
+                out << YAML::Value << YAML::Flow;
+                save(out, t->getDirection());
             }
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstFileTransformRcPtr t)
-    {
-        out << YAML::VerbatimTag("FileTransform");
-        out << YAML::Flow << YAML::BeginMap;
-        out << YAML::Key << "src" << YAML::Value << t->getSrc();
-        const char * cccid = t->getCCCId();
-        if(cccid && *cccid)
-        {
-            out << YAML::Key << "cccid" << YAML::Value << t->getCCCId();
-        }
-        out << YAML::Key << "interpolation";
-        out << YAML::Value << t->getInterpolation();
-        
-        EmitBaseTransformKeyValues(out, t);
-        out << YAML::EndMap;
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, ColorSpaceTransformRcPtr& t)
-    {
-        t = ColorSpaceTransform::Create();
         
-        std::string key, stringval;
+        // AllocationTransform
         
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
+        inline void load(const YAML::Node& node, AllocationTransformRcPtr& t)
         {
-            iter.first() >> key;
+            t = AllocationTransform::Create();
             
-            if(key == "src")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setSrc(stringval.c_str());
-            }
-            else if(key == "dst")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setDst(stringval.c_str());
-            }
-            else if(key == "direction")
-            {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
-            }
-            else
-            {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
+            std::string key;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "allocation")
+                {
+                    Allocation val;
+                    load(second, val);
+                    t->setAllocation(val);
+                }
+                else if(key == "vars")
+                {
+                    std::vector<float> val;
+                    load(second, val);
+                    if(!val.empty())
+                    {
+                        t->setVars(static_cast<int>(val.size()), &val[0]);
+                    }
+                }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
+                }
             }
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstColorSpaceTransformRcPtr t)
-    {
-        out << YAML::VerbatimTag("ColorSpaceTransform");
-        out << YAML::Flow << YAML::BeginMap;
-        out << YAML::Key << "src" << YAML::Value << t->getSrc();
-        out << YAML::Key << "dst" << YAML::Value << t->getDst();
-        EmitBaseTransformKeyValues(out, t);
-        out << YAML::EndMap;
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, LookTransformRcPtr& t)
-    {
-        t = LookTransform::Create();
-        
-        std::string key, stringval;
         
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
+        inline void save(YAML::Emitter& out, ConstAllocationTransformRcPtr t)
         {
-            iter.first() >> key;
+            out << YAML::VerbatimTag("AllocationTransform");
+            out << YAML::Flow << YAML::BeginMap;
             
-            if(key == "src")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setSrc(stringval.c_str());
-            }
-            else if(key == "dst")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setDst(stringval.c_str());
-            }
-            else if(key == "looks")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setLooks(stringval.c_str());
-            }
-            else if(key == "direction")
-            {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
-            }
-            else
+            out << YAML::Key << "allocation";
+            out << YAML::Value << YAML::Flow;
+            save(out, t->getAllocation());
+            
+            if(t->getNumVars() > 0)
             {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
+                std::vector<float> vars(t->getNumVars());
+                t->getVars(&vars[0]);
+                out << YAML::Key << "vars";
+                out << YAML::Flow << YAML::Value << vars;
             }
+            
+            EmitBaseTransformKeyValues(out, t);
+            out << YAML::EndMap;
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstLookTransformRcPtr t)
-    {
-        out << YAML::VerbatimTag("LookTransform");
-        out << YAML::Flow << YAML::BeginMap;
-        out << YAML::Key << "src" << YAML::Value << t->getSrc();
-        out << YAML::Key << "dst" << YAML::Value << t->getDst();
-        out << YAML::Key << "looks" << YAML::Value << t->getLooks();
-        EmitBaseTransformKeyValues(out, t);
-        out << YAML::EndMap;
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, ExponentTransformRcPtr& t)
-    {
-        t = ExponentTransform::Create();
         
-        std::string key;
+        // CDLTransform
         
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
+        inline void load(const YAML::Node& node, CDLTransformRcPtr& t)
         {
-            iter.first() >> key;
+            t = CDLTransform::Create();
             
-            if(key == "value")
-            {
-                std::vector<float> val;
-                if (iter.second().Type() != YAML::NodeType::Null)
+            std::string key;
+            std::vector<float> floatvecval;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "slope")
                 {
-                    iter.second() >> val;
-                    if(val.size() != 4)
+                    load(second, floatvecval);
+                    if(floatvecval.size() != 3)
                     {
                         std::ostringstream os;
-                        os << "ExponentTransform parse error, value field must be 4 ";
-                        os << "floats. Found '" << val.size() << "'.";
+                        os << "CDLTransform parse error, 'slope' field must be 3 ";
+                        os << "floats. Found '" << floatvecval.size() << "'.";
                         throw Exception(os.str().c_str());
                     }
-                    t->setValue(&val[0]);
+                    t->setSlope(&floatvecval[0]);
                 }
-            }
-            else if(key == "direction")
-            {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
-            }
-            else
-            {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
-            }
-        }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstExponentTransformRcPtr t)
-    {
-        out << YAML::VerbatimTag("ExponentTransform");
-        out << YAML::Flow << YAML::BeginMap;
-        
-        std::vector<float> value(4, 0.0);
-        t->getValue(&value[0]);
-        out << YAML::Key << "value";
-        out << YAML::Value << YAML::Flow << value;
-        EmitBaseTransformKeyValues(out, t);
-        out << YAML::EndMap;
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, LogTransformRcPtr& t)
-    {
-        t = LogTransform::Create();
-        
-        std::string key;
-        
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
-        {
-            iter.first() >> key;
-            
-            if(key == "base")
-            {
-                float val = 0.0f;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<float>(val))
-                  t->setBase(val);
-            }
-            else if(key == "direction")
-            {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
-            }
-            else
-            {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
-            }
-        }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstLogTransformRcPtr t)
-    {
-        out << YAML::VerbatimTag("LogTransform");
-        out << YAML::Flow << YAML::BeginMap;
-        out << YAML::Key << "base" << YAML::Value << t->getBase();
-        EmitBaseTransformKeyValues(out, t);
-        out << YAML::EndMap;
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, MatrixTransformRcPtr& t)
-    {
-        t = MatrixTransform::Create();
-        
-        std::string key;
-        
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
-        {
-            iter.first() >> key;
-            
-            if(key == "matrix")
-            {
-                std::vector<float> val;
-                if (iter.second().Type() != YAML::NodeType::Null)
+                else if(key == "offset")
                 {
-                    iter.second() >> val;
-                    if(val.size() != 16)
+                    load(second, floatvecval);
+                    if(floatvecval.size() != 3)
                     {
                         std::ostringstream os;
-                        os << "MatrixTransform parse error, matrix field must be 16 ";
-                        os << "floats. Found '" << val.size() << "'.";
+                        os << "CDLTransform parse error, 'offset' field must be 3 ";
+                        os << "floats. Found '" << floatvecval.size() << "'.";
                         throw Exception(os.str().c_str());
                     }
-                    t->setMatrix(&val[0]);
+                    t->setOffset(&floatvecval[0]);
                 }
-            }
-            else if(key == "offset")
-            {
-                std::vector<float> val;
-                if (iter.second().Type() != YAML::NodeType::Null)
+                else if(key == "power")
                 {
-                    iter.second() >> val;
-                    if(val.size() != 4)
+                    load(second, floatvecval);
+                    if(floatvecval.size() != 3)
                     {
                         std::ostringstream os;
-                        os << "MatrixTransform parse error, offset field must be 4 ";
-                        os << "floats. Found '" << val.size() << "'.";
+                        os << "CDLTransform parse error, 'power' field must be 3 ";
+                        os << "floats. Found '" << floatvecval.size() << "'.";
                         throw Exception(os.str().c_str());
                     }
-                    t->setOffset(&val[0]);
+                    t->setPower(&floatvecval[0]);
+                }
+                else if(key == "saturation" || key == "sat")
+                {
+                    float val = 0.0f;
+                    load(second, val);
+                    t->setSat(val);
                 }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
+                }
+            }
+        }
+        
+        inline void save(YAML::Emitter& out, ConstCDLTransformRcPtr t)
+        {
+            out << YAML::VerbatimTag("CDLTransform");
+            out << YAML::Flow << YAML::BeginMap;
+            
+            std::vector<float> slope(3);
+            t->getSlope(&slope[0]);
+            if(!IsVecEqualToOne(&slope[0], 3))
+            {
+                out << YAML::Key << "slope";
+                out << YAML::Value << YAML::Flow << slope;
             }
-            else if(key == "direction")
+            
+            std::vector<float> offset(3);
+            t->getOffset(&offset[0]);
+            if(!IsVecEqualToZero(&offset[0], 3))
             {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
+                out << YAML::Key << "offset";
+                out << YAML::Value << YAML::Flow << offset;
             }
-            else
+            
+            std::vector<float> power(3);
+            t->getPower(&power[0]);
+            if(!IsVecEqualToOne(&power[0], 3))
+            {
+                out << YAML::Key << "power";
+                out << YAML::Value << YAML::Flow << power;
+            }
+            
+            if(!IsScalarEqualToOne(t->getSat()))
             {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
+                out << YAML::Key << "sat" << YAML::Value << t->getSat();
             }
+            
+            EmitBaseTransformKeyValues(out, t);
+            out << YAML::EndMap;
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstMatrixTransformRcPtr t)
-    {
-        out << YAML::VerbatimTag("MatrixTransform");
-        out << YAML::Flow << YAML::BeginMap;
         
-        std::vector<float> matrix(16, 0.0);
-        t->getMatrix(&matrix[0]);
-        if(!IsM44Identity(&matrix[0]))
+        // ColorSpaceTransform
+        
+        inline void load(const YAML::Node& node, ColorSpaceTransformRcPtr& t)
         {
-            out << YAML::Key << "matrix";
-            out << YAML::Value << YAML::Flow << matrix;
+            t = ColorSpaceTransform::Create();
+            
+            std::string key, stringval;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "src")
+                {
+                    load(second, stringval);
+                    t->setSrc(stringval.c_str());
+                }
+                else if(key == "dst")
+                {
+                    load(second, stringval);
+                    t->setDst(stringval.c_str());
+                }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
+                }
+            }
         }
         
-        std::vector<float> offset(4, 0.0);
-        t->getOffset(&offset[0]);
-        if(!IsVecEqualToZero(&offset[0],4))
+        inline void save(YAML::Emitter& out, ConstColorSpaceTransformRcPtr t)
         {
-            out << YAML::Key << "offset";
-            out << YAML::Value << YAML::Flow << offset;
+            out << YAML::VerbatimTag("ColorSpaceTransform");
+            out << YAML::Flow << YAML::BeginMap;
+            out << YAML::Key << "src" << YAML::Value << t->getSrc();
+            out << YAML::Key << "dst" << YAML::Value << t->getDst();
+            EmitBaseTransformKeyValues(out, t);
+            out << YAML::EndMap;
         }
         
-        EmitBaseTransformKeyValues(out, t);
-        out << YAML::EndMap;
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, CDLTransformRcPtr& t)
-    {
-        t = CDLTransform::Create();
+        // ExponentTransform
         
-        std::string key;
-        std::vector<float> floatvecval;
-        
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
+        inline void load(const YAML::Node& node, ExponentTransformRcPtr& t)
         {
-            iter.first() >> key;
+            t = ExponentTransform::Create();
             
-            if(key == "slope")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null)
+            std::string key;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "value")
                 {
-                    iter.second() >> floatvecval;
-                    if(floatvecval.size() != 3)
+                    std::vector<float> val;
+                    load(second, val);
+                    if(val.size() != 4)
                     {
                         std::ostringstream os;
-                        os << "CDLTransform parse error, 'slope' field must be 3 ";
-                        os << "floats. Found '" << floatvecval.size() << "'.";
+                        os << "ExponentTransform parse error, value field must be 4 ";
+                        os << "floats. Found '" << val.size() << "'.";
                         throw Exception(os.str().c_str());
                     }
-                    t->setSlope(&floatvecval[0]);
+                    t->setValue(&val[0]);
+                }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
                 }
             }
-            else if(key == "offset")
-            {
-                if (iter.second().Type() != YAML::NodeType::Null)
+        }
+        
+        inline void save(YAML::Emitter& out, ConstExponentTransformRcPtr t)
+        {
+            out << YAML::VerbatimTag("ExponentTransform");
+            out << YAML::Flow << YAML::BeginMap;
+            
+            std::vector<float> value(4, 0.0);
+            t->getValue(&value[0]);
+            out << YAML::Key << "value";
+            out << YAML::Value << YAML::Flow << value;
+            EmitBaseTransformKeyValues(out, t);
+            out << YAML::EndMap;
+        }
+        
+        // FileTransform
+        
+        inline void load(const YAML::Node& node, FileTransformRcPtr& t)
+        {
+            t = FileTransform::Create();
+            
+            std::string key, stringval;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "src")
                 {
-                    iter.second() >> floatvecval;
-                    if(floatvecval.size() != 3)
-                    {
-                        std::ostringstream os;
-                        os << "CDLTransform parse error, 'offset' field must be 3 ";
-                        os << "floats. Found '" << floatvecval.size() << "'.";
-                        throw Exception(os.str().c_str());
-                    }
-                    t->setOffset(&floatvecval[0]);
+                    load(second, stringval);
+                    t->setSrc(stringval.c_str());
+                }
+                else if(key == "cccid")
+                {
+                    load(second, stringval);
+                    t->setCCCId(stringval.c_str());
+                }
+                else if(key == "interpolation")
+                {
+                    Interpolation val;
+                    load(second, val);
+                    t->setInterpolation(val);
+                }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
                 }
             }
-            else if(key == "power")
+        }
+        
+        inline void save(YAML::Emitter& out, ConstFileTransformRcPtr t)
+        {
+            out << YAML::VerbatimTag("FileTransform");
+            out << YAML::Flow << YAML::BeginMap;
+            out << YAML::Key << "src" << YAML::Value << t->getSrc();
+            const char * cccid = t->getCCCId();
+            if(cccid && *cccid)
             {
-                if (iter.second().Type() != YAML::NodeType::Null)
+                out << YAML::Key << "cccid" << YAML::Value << t->getCCCId();
+            }
+            out << YAML::Key << "interpolation";
+            out << YAML::Value;
+            save(out, t->getInterpolation());
+            
+            EmitBaseTransformKeyValues(out, t);
+            out << YAML::EndMap;
+        }
+        
+        // GroupTransform
+        
+        void load(const YAML::Node& node, TransformRcPtr& t);
+        void save(YAML::Emitter& out, ConstTransformRcPtr t);
+        
+        inline void load(const YAML::Node& node, GroupTransformRcPtr& t)
+        {
+            t = GroupTransform::Create();
+            
+            std::string key;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "children")
                 {
-                    iter.second() >> floatvecval;
-                    if(floatvecval.size() != 3)
+                    for(unsigned i = 0; i < second.size(); ++i)
                     {
-                        std::ostringstream os;
-                        os << "CDLTransform parse error, 'power' field must be 3 ";
-                        os << "floats. Found '" << floatvecval.size() << "'.";
-                        throw Exception(os.str().c_str());
+                        TransformRcPtr childTransform;
+                        load(second[i], childTransform);
+                        
+                        // TODO: consider the forwards-compatibility implication of
+                        // throwing an exception.  Should this be a warning, instead?
+                        if(!childTransform)
+                        {
+                            throw Exception("Child transform could not be parsed.");
+                        }
+                        
+                        t->push_back(childTransform);
                     }
-                    t->setPower(&floatvecval[0]);
+                }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
                 }
             }
-            else if(key == "saturation" || key == "sat")
-            {
-                float val = 0.0f;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<float>(val))
-                  t->setSat(val);
-            }
-            else if(key == "direction")
-            {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
-            }
-            else
+        }
+        
+        inline void save(YAML::Emitter& out, ConstGroupTransformRcPtr t)
+        {
+            out << YAML::VerbatimTag("GroupTransform");
+            out << YAML::BeginMap;
+            EmitBaseTransformKeyValues(out, t);
+            
+            out << YAML::Key << "children";
+            out << YAML::Value;
+            
+            out << YAML::BeginSeq;
+            for(int i = 0; i < t->size(); ++i)
             {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
+                save(out, t->getTransform(i));
             }
+            out << YAML::EndSeq;
+            
+            out << YAML::EndMap;
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstCDLTransformRcPtr t)
-    {
-        out << YAML::VerbatimTag("CDLTransform");
-        out << YAML::Flow << YAML::BeginMap;
         
-        std::vector<float> slope(3);
-        t->getSlope(&slope[0]);
-        if(!IsVecEqualToOne(&slope[0], 3))
+        // LogTransform
+        
+        inline void load(const YAML::Node& node, LogTransformRcPtr& t)
         {
-            out << YAML::Key << "slope";
-            out << YAML::Value << YAML::Flow << slope;
+            t = LogTransform::Create();
+            
+            std::string key;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "base")
+                {
+                    float val = 0.0f;
+                    load(second, val);
+                    t->setBase(val);
+                }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
+                }
+            }
         }
         
-        std::vector<float> offset(3);
-        t->getOffset(&offset[0]);
-        if(!IsVecEqualToZero(&offset[0], 3))
+        inline void save(YAML::Emitter& out, ConstLogTransformRcPtr t)
         {
-            out << YAML::Key << "offset";
-            out << YAML::Value << YAML::Flow << offset;
+            out << YAML::VerbatimTag("LogTransform");
+            out << YAML::Flow << YAML::BeginMap;
+            out << YAML::Key << "base" << YAML::Value << t->getBase();
+            EmitBaseTransformKeyValues(out, t);
+            out << YAML::EndMap;
         }
         
-        std::vector<float> power(3);
-        t->getPower(&power[0]);
-        if(!IsVecEqualToOne(&power[0], 3))
+        // LookTransform
+        
+        inline void load(const YAML::Node& node, LookTransformRcPtr& t)
         {
-            out << YAML::Key << "power";
-            out << YAML::Value << YAML::Flow << power;
+            t = LookTransform::Create();
+            
+            std::string key, stringval;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "src")
+                {
+                    load(second, stringval);
+                    t->setSrc(stringval.c_str());
+                }
+                else if(key == "dst")
+                {
+                    load(second, stringval);
+                    t->setDst(stringval.c_str());
+                }
+                else if(key == "looks")
+                {
+                    load(second, stringval);
+                    t->setLooks(stringval.c_str());
+                }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
+                }
+            }
         }
         
-        if(!IsScalarEqualToOne(t->getSat()))
+        inline void save(YAML::Emitter& out, ConstLookTransformRcPtr t)
         {
-            out << YAML::Key << "sat" << YAML::Value << t->getSat();
+            out << YAML::VerbatimTag("LookTransform");
+            out << YAML::Flow << YAML::BeginMap;
+            out << YAML::Key << "src" << YAML::Value << t->getSrc();
+            out << YAML::Key << "dst" << YAML::Value << t->getDst();
+            out << YAML::Key << "looks" << YAML::Value << t->getLooks();
+            EmitBaseTransformKeyValues(out, t);
+            out << YAML::EndMap;
         }
         
-        EmitBaseTransformKeyValues(out, t);
-        out << YAML::EndMap;
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, AllocationTransformRcPtr& t)
-    {
-        t = AllocationTransform::Create();
-        
-        std::string key;
+        // MatrixTransform
         
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
+        inline void load(const YAML::Node& node, MatrixTransformRcPtr& t)
         {
-            iter.first() >> key;
+            t = MatrixTransform::Create();
             
-            if(key == "allocation")
-            {
-                Allocation val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<Allocation>(val))
-                  t->setAllocation(val);
-            }
-            else if(key == "vars")
-            {
-                std::vector<float> val;
-                if (iter.second().Type() != YAML::NodeType::Null)
+            std::string key;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "matrix")
                 {
-                    iter.second() >> val;
-                    if(!val.empty())
+                    std::vector<float> val;
+                    load(second, val);
+                    if(val.size() != 16)
                     {
-                        t->setVars(static_cast<int>(val.size()), &val[0]);
+                        std::ostringstream os;
+                        os << "MatrixTransform parse error, matrix field must be 16 ";
+                        os << "floats. Found '" << val.size() << "'.";
+                        throw Exception(os.str().c_str());
+                    }
+                    t->setMatrix(&val[0]);
+                }
+                else if(key == "offset")
+                {
+                    std::vector<float> val;
+                    load(second, val);
+                    if(val.size() != 4)
+                    {
+                        std::ostringstream os;
+                        os << "MatrixTransform parse error, offset field must be 4 ";
+                        os << "floats. Found '" << val.size() << "'.";
+                        throw Exception(os.str().c_str());
                     }
+                    t->setOffset(&val[0]);
+                }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
                 }
             }
-            else if(key == "direction")
+        }
+        
+        inline void save(YAML::Emitter& out, ConstMatrixTransformRcPtr t)
+        {
+            out << YAML::VerbatimTag("MatrixTransform");
+            out << YAML::Flow << YAML::BeginMap;
+            
+            std::vector<float> matrix(16, 0.0);
+            t->getMatrix(&matrix[0]);
+            if(!IsM44Identity(&matrix[0]))
             {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
+                out << YAML::Key << "matrix";
+                out << YAML::Value << YAML::Flow << matrix;
             }
-            else
+            
+            std::vector<float> offset(4, 0.0);
+            t->getOffset(&offset[0]);
+            if(!IsVecEqualToZero(&offset[0],4))
             {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
+                out << YAML::Key << "offset";
+                out << YAML::Value << YAML::Flow << offset;
             }
+            
+            EmitBaseTransformKeyValues(out, t);
+            out << YAML::EndMap;
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstAllocationTransformRcPtr t)
-    {
-        out << YAML::VerbatimTag("AllocationTransform");
-        out << YAML::Flow << YAML::BeginMap;
         
-        out << YAML::Key << "allocation";
-        out << YAML::Value << YAML::Flow << t->getAllocation();
+        // TruelightTransform
         
-        if(t->getNumVars() > 0)
+        inline void load(const YAML::Node& node, TruelightTransformRcPtr& t)
         {
-            std::vector<float> vars(t->getNumVars());
-            t->getVars(&vars[0]);
-            out << YAML::Key << "vars";
-            out << YAML::Flow << YAML::Value << vars;
+            t = TruelightTransform::Create();
+            
+            std::string key, stringval;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "config_root")
+                {
+                    load(second, stringval);
+                    t->setConfigRoot(stringval.c_str());
+                }
+                else if(key == "profile")
+                {
+                    load(second, stringval);
+                    t->setProfile(stringval.c_str());
+                }
+                else if(key == "camera")
+                {
+                    load(second, stringval);
+                    t->setCamera(stringval.c_str());
+                }
+                else if(key == "input_display")
+                {
+                    load(second, stringval);
+                    t->setInputDisplay(stringval.c_str());
+                }
+                else if(key == "recorder")
+                {
+                    load(second, stringval);
+                    t->setRecorder(stringval.c_str());
+                }
+                else if(key == "print")
+                {
+                    load(second, stringval);
+                    t->setPrint(stringval.c_str());
+                }
+                else if(key == "lamp")
+                {
+                    load(second, stringval);
+                    t->setLamp(stringval.c_str());
+                }
+                else if(key == "output_camera")
+                {
+                    load(second, stringval);
+                    t->setOutputCamera(stringval.c_str());
+                }
+                else if(key == "display")
+                {
+                    load(second, stringval);
+                    t->setDisplay(stringval.c_str());
+                }
+                else if(key == "cube_input")
+                {
+                    load(second, stringval);
+                     t->setCubeInput(stringval.c_str());
+                }
+                else if(key == "direction")
+                {
+                    TransformDirection val;
+                    load(second, val);
+                    t->setDirection(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
+                }
+            }
         }
         
-        EmitBaseTransformKeyValues(out, t);
-        out << YAML::EndMap;
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, TruelightTransformRcPtr& t)
-    {
-        t = TruelightTransform::Create();
-        
-        std::string key, stringval;
-        
-        for (YAML::Iterator iter = node.begin();
-             iter != node.end();
-             ++iter)
+        inline void save(YAML::Emitter& out, ConstTruelightTransformRcPtr t)
         {
-            iter.first() >> key;
             
-            if(key == "config_root")
+            out << YAML::VerbatimTag("TruelightTransform");
+            out << YAML::Flow << YAML::BeginMap;
+            if(strcmp(t->getConfigRoot(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setConfigRoot(stringval.c_str());
+                out << YAML::Key << "config_root";
+                out << YAML::Value << YAML::Flow << t->getConfigRoot();
             }
-            else if(key == "profile")
+            if(strcmp(t->getProfile(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setProfile(stringval.c_str());
+                out << YAML::Key << "profile";
+                out << YAML::Value << YAML::Flow << t->getProfile();
             }
-            else if(key == "camera")
+            if(strcmp(t->getCamera(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setCamera(stringval.c_str());
+                out << YAML::Key << "camera";
+                out << YAML::Value << YAML::Flow << t->getCamera();
             }
-            else if(key == "input_display")
+            if(strcmp(t->getInputDisplay(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setInputDisplay(stringval.c_str());
+                out << YAML::Key << "input_display";
+                out << YAML::Value << YAML::Flow << t->getInputDisplay();
             }
-            else if(key == "recorder")
+            if(strcmp(t->getRecorder(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setRecorder(stringval.c_str());
+                out << YAML::Key << "recorder";
+                out << YAML::Value << YAML::Flow << t->getRecorder();
             }
-            else if(key == "print")
+            if(strcmp(t->getPrint(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setPrint(stringval.c_str());
+                out << YAML::Key << "print";
+                out << YAML::Value << YAML::Flow << t->getPrint();
             }
-            else if(key == "lamp")
+            if(strcmp(t->getLamp(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setLamp(stringval.c_str());
+                out << YAML::Key << "lamp";
+                out << YAML::Value << YAML::Flow << t->getLamp();
             }
-            else if(key == "output_camera")
+            if(strcmp(t->getOutputCamera(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setOutputCamera(stringval.c_str());
+                out << YAML::Key << "output_camera";
+                out << YAML::Value << YAML::Flow << t->getOutputCamera();
             }
-            else if(key == "display")
+            if(strcmp(t->getDisplay(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setDisplay(stringval.c_str());
+                out << YAML::Key << "display";
+                out << YAML::Value << YAML::Flow << t->getDisplay();
             }
-            else if(key == "cube_input")
+            if(strcmp(t->getCubeInput(), "") != 0)
             {
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<std::string>(stringval))
-                  t->setCubeInput(stringval.c_str());
+                out << YAML::Key << "cube_input";
+                out << YAML::Value << YAML::Flow << t->getCubeInput();
             }
-            else if(key == "direction")
+            
+            EmitBaseTransformKeyValues(out, t);
+            
+            out << YAML::EndMap;
+        }
+        
+        // Transform
+        
+        void load(const YAML::Node& node, TransformRcPtr& t)
+        {
+            if(node.Type() != YAML::NodeType::Map)
             {
-                TransformDirection val;
-                if (iter.second().Type() != YAML::NodeType::Null && 
-                    iter.second().Read<TransformDirection>(val))
-                  t->setDirection(val);
+                std::ostringstream os;
+                os << "Unsupported Transform type encountered: (" << node.Type() << ") in OCIO profile. ";
+                os << "Only Mapping types supported.";
+                throw Exception(os.str().c_str());
+            }
+            
+            std::string type = node.Tag();
+            
+            if(type == "AllocationTransform") {
+                AllocationTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
+            }
+            else if(type == "CDLTransform") {
+                CDLTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
+            }
+            else if(type == "ColorSpaceTransform")  {
+                ColorSpaceTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
+            }
+            // TODO: DisplayTransform
+            else if(type == "ExponentTransform")  {
+                ExponentTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
+            }
+            else if(type == "FileTransform")  {
+                FileTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
+            }
+            else if(type == "GroupTransform") {
+                GroupTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
+            }
+            else if(type == "LogTransform") {
+                LogTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
+            }
+            else if(type == "LookTransform") {
+                LookTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
+            }
+            else if(type == "MatrixTransform")  {
+                MatrixTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
+            }
+            else if(type == "TruelightTransform")  {
+                TruelightTransformRcPtr temp;
+                load(node, temp);
+                t = temp;
             }
             else
             {
-                LogUnknownKeyWarning(node.Tag(), iter.first());
+                // TODO: add a new empty (better name?) aka passthru Transform()
+                // which does nothing. This is so upsupported !<tag> types don't
+                // throw an exception. Alternativly this could be caught in the
+                // GroupTransformRcPtr >> operator with some type of
+                // supported_tag() method
+                
+                // TODO: consider the forwards-compatibility implication of
+                // throwing an exception.  Should this be a warning, instead?
+                
+                //  t = EmptyTransformRcPtr(new EmptyTransform(), &deleter);
+                std::ostringstream os;
+                os << "Unsupported transform type !<" << type << "> in OCIO profile. ";
+                throw Exception(os.str().c_str());
             }
         }
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ConstTruelightTransformRcPtr t)
-    {
         
-        out << YAML::VerbatimTag("TruelightTransform");
-        out << YAML::Flow << YAML::BeginMap;
-        if(strcmp(t->getConfigRoot(), "") != 0)
-        {
-            out << YAML::Key << "config_root";
-            out << YAML::Value << YAML::Flow << t->getConfigRoot();
-        }
-        if(strcmp(t->getProfile(), "") != 0)
+        void save(YAML::Emitter& out, ConstTransformRcPtr t)
         {
-            out << YAML::Key << "profile";
-            out << YAML::Value << YAML::Flow << t->getProfile();
-        }
-        if(strcmp(t->getCamera(), "") != 0)
-        {
-            out << YAML::Key << "camera";
-            out << YAML::Value << YAML::Flow << t->getCamera();
-        }
-        if(strcmp(t->getInputDisplay(), "") != 0)
-        {
-            out << YAML::Key << "input_display";
-            out << YAML::Value << YAML::Flow << t->getInputDisplay();
+            if(ConstAllocationTransformRcPtr Allocation_tran = \
+                DynamicPtrCast<const AllocationTransform>(t))
+                save(out, Allocation_tran);
+            else if(ConstCDLTransformRcPtr CDL_tran = \
+                DynamicPtrCast<const CDLTransform>(t))
+                save(out, CDL_tran);
+            else if(ConstColorSpaceTransformRcPtr ColorSpace_tran = \
+                DynamicPtrCast<const ColorSpaceTransform>(t))
+                save(out, ColorSpace_tran);
+            else if(ConstExponentTransformRcPtr Exponent_tran = \
+                DynamicPtrCast<const ExponentTransform>(t))
+                save(out, Exponent_tran);
+            else if(ConstFileTransformRcPtr File_tran = \
+                DynamicPtrCast<const FileTransform>(t))
+                save(out, File_tran);
+            else if(ConstGroupTransformRcPtr Group_tran = \
+                DynamicPtrCast<const GroupTransform>(t))
+                save(out, Group_tran);
+            else if(ConstLogTransformRcPtr Log_tran = \
+                DynamicPtrCast<const LogTransform>(t))
+                save(out, Log_tran);
+            else if(ConstLookTransformRcPtr Look_tran = \
+                DynamicPtrCast<const LookTransform>(t))
+                save(out, Look_tran);
+            else if(ConstMatrixTransformRcPtr Matrix_tran = \
+                DynamicPtrCast<const MatrixTransform>(t))
+                save(out, Matrix_tran);
+            else if(ConstTruelightTransformRcPtr Truelight_tran = \
+                DynamicPtrCast<const TruelightTransform>(t))
+                save(out, Truelight_tran);
+            else
+                throw Exception("Unsupported Transform() type for serialization.");
         }
-        if(strcmp(t->getRecorder(), "") != 0)
+        
+        // ColorSpace
+        
+        inline void load(const YAML::Node& node, ColorSpaceRcPtr& cs)
         {
-            out << YAML::Key << "recorder";
-            out << YAML::Value << YAML::Flow << t->getRecorder();
+            if(node.Tag() != "ColorSpace")
+                return; // not a !<ColorSpace> tag
+            
+            std::string key, stringval;
+            bool boolval;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "name")
+                {
+                    load(second, stringval);
+                    cs->setName(stringval.c_str());
+                }
+                else if(key == "description")
+                {
+                    load(second, stringval);
+                    cs->setDescription(stringval.c_str());
+                }
+                else if(key == "family")
+                {
+                    load(second, stringval);
+                    cs->setFamily(stringval.c_str());
+                }
+                else if(key == "equalitygroup")
+                {
+                    load(second, stringval);
+                    cs->setEqualityGroup(stringval.c_str());
+                }
+                else if(key == "bitdepth")
+                {
+                    BitDepth ret;
+                    load(second, ret);
+                    cs->setBitDepth(ret);
+                }
+                else if(key == "isdata")
+                {
+                    load(second, boolval);
+                    cs->setIsData(boolval);
+                }
+                else if(key == "allocation")
+                {
+                    Allocation val;
+                    load(second, val);
+                    cs->setAllocation(val);
+                }
+                else if(key == "allocationvars")
+                {
+                    std::vector<float> val;
+                    load(second, val);
+                    if(!val.empty())
+                        cs->setAllocationVars(static_cast<int>(val.size()), &val[0]);
+                }
+                else if(key == "to_reference")
+                {
+                    TransformRcPtr val;
+                    load(second, val);
+                    cs->setTransform(val, COLORSPACE_DIR_TO_REFERENCE);
+                }
+                else if(key == "from_reference")
+                {
+                    TransformRcPtr val;
+                    load(second, val);
+                    cs->setTransform(val, COLORSPACE_DIR_FROM_REFERENCE);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
+                }
+            }
         }
-        if(strcmp(t->getPrint(), "") != 0)
+        
+        inline void save(YAML::Emitter& out, ConstColorSpaceRcPtr cs)
         {
-            out << YAML::Key << "print";
-            out << YAML::Value << YAML::Flow << t->getPrint();
+            out << YAML::VerbatimTag("ColorSpace");
+            out << YAML::BeginMap;
+            
+            out << YAML::Key << "name" << YAML::Value << cs->getName();
+            out << YAML::Key << "family" << YAML::Value << cs->getFamily();
+            out << YAML::Key << "equalitygroup" << YAML::Value << cs->getEqualityGroup();
+            out << YAML::Key << "bitdepth" << YAML::Value;
+            save(out, cs->getBitDepth());
+            if(cs->getDescription() != NULL && strlen(cs->getDescription()) > 0)
+            {
+                out << YAML::Key << "description";
+                out << YAML::Value << YAML::Literal << cs->getDescription();
+            }
+            out << YAML::Key << "isdata" << YAML::Value << cs->isData();
+            
+            out << YAML::Key << "allocation" << YAML::Value;
+            save(out, cs->getAllocation());
+            if(cs->getAllocationNumVars() > 0)
+            {
+                std::vector<float> allocationvars(cs->getAllocationNumVars());
+                cs->getAllocationVars(&allocationvars[0]);
+                out << YAML::Key << "allocationvars";
+                out << YAML::Flow << YAML::Value << allocationvars;
+            }
+            
+            ConstTransformRcPtr toref = \
+                cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
+            if(toref)
+            {
+                out << YAML::Key << "to_reference" << YAML::Value;
+                save(out, toref);
+            }
+            
+            ConstTransformRcPtr fromref = \
+                cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE);
+            if(fromref)
+            {
+                out << YAML::Key << "from_reference" << YAML::Value;
+                save(out, fromref);
+            }
+            
+            out << YAML::EndMap;
+            out << YAML::Newline;
         }
-        if(strcmp(t->getLamp(), "") != 0)
+        
+        // Look
+        
+        inline void load(const YAML::Node& node, LookRcPtr& look)
         {
-            out << YAML::Key << "lamp";
-            out << YAML::Value << YAML::Flow << t->getLamp();
+            if(node.Tag() != "Look")
+                return;
+            
+            std::string key, stringval;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "name")
+                {
+                    load(second, stringval);
+                    look->setName(stringval.c_str());
+                }
+                else if(key == "process_space")
+                {
+                    load(second, stringval);
+                    look->setProcessSpace(stringval.c_str());
+                }
+                else if(key == "transform")
+                {
+                    TransformRcPtr val;
+                    load(second, val);
+                    look->setTransform(val);
+                }
+                else if(key == "inverse_transform")
+                {
+                    TransformRcPtr val;
+                    load(second, val);
+                    look->setInverseTransform(val);
+                }
+                else
+                {
+                    LogUnknownKeyWarning(node.Tag(), first);
+                }
+            }
         }
-        if(strcmp(t->getOutputCamera(), "") != 0)
+        
+        inline void save(YAML::Emitter& out, ConstLookRcPtr look)
         {
-            out << YAML::Key << "output_camera";
-            out << YAML::Value << YAML::Flow << t->getOutputCamera();
+            out << YAML::VerbatimTag("Look");
+            out << YAML::BeginMap;
+            out << YAML::Key << "name" << YAML::Value << look->getName();
+            out << YAML::Key << "process_space" << YAML::Value << look->getProcessSpace();
+            
+            if(look->getTransform())
+            {
+                out << YAML::Key << "transform";
+                out << YAML::Value;
+                save(out, look->getTransform());
+            }
+            
+            if(look->getInverseTransform())
+            {
+                out << YAML::Key << "inverse_transform";
+                out << YAML::Value;
+                save(out, look->getInverseTransform());
+            }
+            
+            out << YAML::EndMap;
+            out << YAML::Newline;
         }
-        if(strcmp(t->getDisplay(), "") != 0)
+        
+        // Config
+        
+        inline void load(const YAML::Node& node, ConfigRcPtr& c, const char* filename)
         {
-            out << YAML::Key << "display";
-            out << YAML::Value << YAML::Flow << t->getDisplay();
+            
+            // check profile version
+            int profile_version = 0;
+#ifdef OLDYAML
+            if(node.FindValue("ocio_profile_version") == NULL)
+#else
+            if(node["ocio_profile_version"] == NULL)
+#endif
+            {
+                std::ostringstream os;
+                os << "The specified file ";
+                os << "does not appear to be an OCIO configuration.";
+                throw Exception (os.str().c_str());
+            }
+            
+            load(node["ocio_profile_version"], profile_version);
+            if(profile_version > 1)
+            {
+                std::ostringstream os;
+                os << "This .ocio config ";
+                if(filename && *filename)
+                {
+                    os << " '" << filename << "' ";
+                }
+                os << "is version " << profile_version << ". ";
+                os << "This version of the OpenColorIO library (" << OCIO_VERSION ") ";
+                os << "is not known to be able to load this profile. ";
+                os << "An attempt will be made, but there are no guarantees that the ";
+                os << "results will be accurate. Continue at your own risk.";
+                LogWarning(os.str());
+            }
+            
+            std::string key, stringval;
+            bool boolval = false;
+            EnvironmentMode mode = ENV_ENVIRONMENT_LOAD_ALL;
+            
+            for (Iterator iter = node.begin();
+                 iter != node.end();
+                 ++iter)
+            {
+                const YAML::Node& first = get_first(iter);
+                const YAML::Node& second = get_second(iter);
+                
+                load(first, key);
+                
+                if (second.Type() == YAML::NodeType::Null) continue;
+                
+                if(key == "ocio_profile_version") { } // Already handled above.
+                else if(key == "environment")
+                {
+                    mode = ENV_ENVIRONMENT_LOAD_PREDEFINED;
+                    if(second.Type() != YAML::NodeType::Map)
+                    {
+                        std::ostringstream os;
+                        os << "'environment' field needs to be a (name: key) map.";
+                        throw Exception(os.str().c_str());
+                    }
+                    for (Iterator it = second.begin();
+                         it != second.end();
+                         ++it)
+                    {
+                        std::string k, v;
+                        load(get_first(it), k);
+                        load(get_second(it), v);
+                        c->addEnvironmentVar(k.c_str(), v.c_str());
+                    }
+                }
+                else if(key == "search_path" || key == "resource_path")
+                {
+                    load(second, stringval);
+                    c->setSearchPath(stringval.c_str());
+                }
+                else if(key == "strictparsing")
+                {
+                    load(second, boolval);
+                    c->setStrictParsingEnabled(boolval);
+                }
+                else if(key == "description")
+                {
+                    load(second, stringval);
+                    c->setDescription(stringval.c_str());
+                }
+                else if(key == "luma")
+                {
+                    std::vector<float> val;
+                    load(second, val);
+                    if(val.size() != 3)
+                    {
+                        std::ostringstream os;
+                        os << "'luma' field must be 3 ";
+                        os << "floats. Found '" << val.size() << "'.";
+                        throw Exception(os.str().c_str());
+                    }
+                    c->setDefaultLumaCoefs(&val[0]);
+                }
+                else if(key == "roles")
+                {
+                    if(second.Type() != YAML::NodeType::Map)
+                    {
+                        std::ostringstream os;
+                        os << "'roles' field needs to be a (name: key) map.";
+                        throw Exception(os.str().c_str());
+                    }
+                    for (Iterator it = second.begin();
+                         it != second.end();
+                         ++it)
+                    {
+                        std::string k, v;
+                        load(get_first(it), k);
+                        load(get_second(it), v);
+                        c->setRole(k.c_str(), v.c_str());
+                    }
+                }
+                else if(key == "displays")
+                {
+                    if(second.Type() != YAML::NodeType::Map)
+                    {
+                        std::ostringstream os;
+                        os << "'displays' field needs to be a (name: key) map.";
+                        throw Exception(os.str().c_str());
+                    }
+                    for (Iterator it = second.begin();
+                         it != second.end();
+                         ++it)
+                    {
+                        std::string display;
+                        load(get_first(it), display);
+                        const YAML::Node& dsecond = get_second(it);
+                        for(unsigned i = 0; i < dsecond.size(); ++i)
+                        {
+                            View view;
+                            load(dsecond[i], view);
+                            c->addDisplay(display.c_str(), view.name.c_str(),
+                                          view.colorspace.c_str(), view.looks.c_str());
+                        }
+                    }
+                }
+                else if(key == "active_displays")
+                {
+                    std::vector<std::string> display;
+                    load(second, display);
+                    const char* displays = JoinStringEnvStyle(display).c_str();
+                    c->setActiveDisplays(displays);
+                }
+                else if(key == "active_views")
+                {
+                    std::vector<std::string> view;
+                    load(second, view);
+                    const char* views = JoinStringEnvStyle(view).c_str();
+                    c->setActiveViews(views);
+                }
+                else if(key == "colorspaces")
+                {
+                    if(second.Type() != YAML::NodeType::Sequence)
+                    {
+                        std::ostringstream os;
+                        os << "'colorspaces' field needs to be a (- !<ColorSpace>) list.";
+                        throw Exception(os.str().c_str());
+                    }
+                    for(unsigned i = 0; i < second.size(); ++i)
+                    {
+                        if(second[i].Tag() == "ColorSpace")
+                        {
+                            ColorSpaceRcPtr cs = ColorSpace::Create();
+                            load(second[i], cs);
+                            for(int ii = 0; ii < c->getNumColorSpaces(); ++ii)
+                            {
+                                if(strcmp(c->getColorSpaceNameByIndex(ii), cs->getName()) == 0)
+                                {
+                                    std::ostringstream os;
+                                    os << "Colorspace with name '" << cs->getName() << "' already defined.";
+                                    throw Exception(os.str().c_str());
+                                }
+                            }
+                            c->addColorSpace(cs);
+                        }
+                        else
+                        {
+                            std::ostringstream os;
+                            os << "Unknown element found in colorspaces:";
+                            os << second[i].Tag() << ". Only ColorSpace(s)";
+                            os << " currently handled.";
+                            LogWarning(os.str());
+                        }
+                    }
+                }
+                else if(key == "looks")
+                {
+                    if(second.Type() != YAML::NodeType::Sequence)
+                    {
+                        std::ostringstream os;
+                        os << "'looks' field needs to be a (- !<Look>) list.";
+                        throw Exception(os.str().c_str());
+                    }
+                    
+                    for(unsigned i = 0; i < second.size(); ++i)
+                    {
+                        if(second[i].Tag() == "Look")
+                        {
+                            LookRcPtr look = Look::Create();
+                            load(second[i], look);
+                            c->addLook(look);
+                        }
+                        else
+                        {
+                            std::ostringstream os;
+                            os << "Unknown element found in looks:";
+                            os << second[i].Tag() << ". Only Look(s)";
+                            os << " currently handled.";
+                            LogWarning(os.str());
+                        }
+                    }
+                }
+                else
+                {
+                    LogUnknownKeyWarning("profile", first);
+                }
+            }
+            
+            if(filename)
+            {
+                std::string realfilename = pystring::os::path::abspath(filename);
+                std::string configrootdir = pystring::os::path::dirname(realfilename);
+                c->setWorkingDir(configrootdir.c_str());
+            }
+            
+            c->setEnvironmentMode(mode);
+            c->loadEnvironment();
+            
+            if(mode == ENV_ENVIRONMENT_LOAD_ALL)
+            {
+                std::ostringstream os;
+                os << "This .ocio config ";
+                if(filename && *filename)
+                {
+                    os << " '" << filename << "' ";
+                }
+                os << "has no environment section defined. The default behaviour is to ";
+                os << "load all environment variables (" << c->getNumEnvironmentVars() << ")";
+                os << ", which reduces the efficiency of OCIO's caching. Considering ";
+                os << "predefining the environment variables used.";
+                LogDebug(os.str());
+            }
+            
         }
-        if(strcmp(t->getCubeInput(), "") != 0)
+        
+        inline void save(YAML::Emitter& out, const Config* c)
         {
-            out << YAML::Key << "cube_input";
-            out << YAML::Value << YAML::Flow << t->getCubeInput();
+            out << YAML::Block;
+            out << YAML::BeginMap;
+            out << YAML::Key << "ocio_profile_version" << YAML::Value << 1;
+            out << YAML::Newline;
+#ifndef OLDYAML
+            out << YAML::Newline;
+#endif
+            
+            if(c->getNumEnvironmentVars() > 0)
+            {
+                out << YAML::Key << "environment";
+                out << YAML::Value << YAML::BeginMap;
+                for(unsigned i = 0; i < c->getNumEnvironmentVars(); ++i)
+                {   
+                    const char* name = c->getEnvironmentVarNameByIndex(i);
+                    out << YAML::Key << name;
+                    out << YAML::Value << c->getEnvironmentVarDefault(name);
+                }
+                out << YAML::EndMap;
+                out << YAML::Newline;
+            }
+            out << YAML::Key << "search_path" << YAML::Value << c->getSearchPath();
+            out << YAML::Key << "strictparsing" << YAML::Value << c->isStrictParsingEnabled();
+            
+            std::vector<float> luma(3, 0.f);
+            c->getDefaultLumaCoefs(&luma[0]);
+            out << YAML::Key << "luma" << YAML::Value << YAML::Flow << luma;
+            
+            if(c->getDescription() != NULL && strlen(c->getDescription()) > 0)
+            {
+                out << YAML::Newline;
+                out << YAML::Key << "description";
+                out << YAML::Value << c->getDescription();
+                out << YAML::Newline;
+            }
+            
+            // Roles
+            out << YAML::Newline;
+#ifndef OLDYAML
+            out << YAML::Newline;
+#endif
+            out << YAML::Key << "roles";
+            out << YAML::Value << YAML::BeginMap;
+            for(unsigned i = 0; i < c->getNumRoles(); ++i)
+            {
+                const char* role = c->getRoleName(i);
+                out << YAML::Key << role;
+                out << YAML::Value << c->getColorSpace(role)->getName();
+            }
+            out << YAML::EndMap;
+#ifndef OLDYAML
+            out << YAML::Newline;
+#endif
+            
+            // Displays
+            out << YAML::Newline;
+            out << YAML::Key << "displays";
+            out << YAML::Value << YAML::BeginMap;
+            for(unsigned i = 0; i < c->getNumDisplays(); ++i)
+            {
+                const char* display = c->getDisplay(i);
+                out << YAML::Key << display;
+                out << YAML::Value << YAML::BeginSeq;
+                for(unsigned v = 0; v < c->getNumViews(display); ++v)
+                {
+                    View dview;
+                    dview.name = c->getView(display, v);
+                    dview.colorspace = c->getDisplayColorSpaceName(display, dview.name.c_str());
+                    if(c->getDisplayLooks(display, dview.name.c_str()) != NULL)
+                        dview.looks = c->getDisplayLooks(display, dview.name.c_str());
+                    save(out, dview);
+                
+                }
+                out << YAML::EndSeq;
+            }
+            out << YAML::EndMap;
+            
+#ifndef OLDYAML
+            out << YAML::Newline;
+#endif
+            out << YAML::Newline;
+            out << YAML::Key << "active_displays";
+            std::vector<std::string> active_displays;
+            if(c->getActiveDisplays() != NULL && strlen(c->getActiveDisplays()) > 0)
+                SplitStringEnvStyle(active_displays, c->getActiveDisplays());
+            out << YAML::Value << YAML::Flow << active_displays;
+            out << YAML::Key << "active_views";
+            std::vector<std::string> active_views;
+            if(c->getActiveViews() != NULL && strlen(c->getActiveViews()) > 0)
+                SplitStringEnvStyle(active_views, c->getActiveViews());
+            out << YAML::Value << YAML::Flow << active_views;
+#ifndef OLDYAML
+            out << YAML::Newline;
+#endif
+            
+            // Looks
+            if(c->getNumLooks() > 0)
+            {
+                out << YAML::Newline;
+                out << YAML::Key << "looks";
+                out << YAML::Value << YAML::BeginSeq;
+                for(unsigned i = 0; i < c->getNumLooks(); ++i)
+                {
+                    const char* name = c->getLookNameByIndex(i);
+                    save(out, c->getLook(name));
+                }
+                out << YAML::EndSeq;
+                out << YAML::Newline;
+            }
+            
+            // ColorSpaces
+            {
+                out << YAML::Newline;
+                out << YAML::Key << "colorspaces";
+                out << YAML::Value << YAML::BeginSeq;
+                for(unsigned i = 0; i < c->getNumColorSpaces(); ++i)
+                {
+                    const char* name = c->getColorSpaceNameByIndex(i);
+                    save(out, c->getColorSpace(name));
+                }
+                out << YAML::EndSeq;
+            }
+            
+            out << YAML::EndMap;
         }
         
-        EmitBaseTransformKeyValues(out, t);
-        
-        out << YAML::EndMap;
-        return out;
     }
     
     ///////////////////////////////////////////////////////////////////////////
-    //  Enums
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, BitDepth depth) {
-        out << BitDepthToString(depth);
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, BitDepth& depth) {
-        std::string str;
-        node.Read<std::string>(str);
-        depth = BitDepthFromString(str.c_str());
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, Allocation alloc) {
-        out << AllocationToString(alloc);
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, Allocation& alloc) {
-        std::string str;
-        node.Read<std::string>(str);
-        alloc = AllocationFromString(str.c_str());
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceDirection dir) {
-        out << ColorSpaceDirectionToString(dir);
-        return out;
-    }
     
-    void operator >> (const YAML::Node& node, ColorSpaceDirection& dir) {
-        std::string str;
-        node.Read<std::string>(str);
-        dir = ColorSpaceDirectionFromString(str.c_str());
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, TransformDirection dir) {
-        out << TransformDirectionToString(dir);
-        return out;
-    }
-    
-    void operator >> (const YAML::Node& node, TransformDirection& dir) {
-        std::string str;
-        node.Read<std::string>(str);
-        dir = TransformDirectionFromString(str.c_str());
-    }
-    
-    YAML::Emitter& operator << (YAML::Emitter& out, Interpolation interp) {
-        out << InterpolationToString(interp);
-        return out;
+    void OCIOYaml::open(std::istream& istream, ConfigRcPtr& c, const char* filename) const
+    {
+        try
+        {
+#ifdef OLDYAML
+            YAML::Parser parser(istream);
+            YAML::Node node;
+            parser.GetNextDocument(node);
+#else
+            YAML::Node node = YAML::Load(istream);
+#endif
+            load(node, c, filename);
+        }
+        catch(const std::exception & e)
+        {
+            std::ostringstream os;
+            os << "Error: Loading the OCIO profile ";
+            if(filename) os << "'" << filename << "' ";
+            os << "failed. " << e.what();
+            throw Exception(os.str().c_str());
+        }
     }
     
-    void operator >> (const YAML::Node& node, Interpolation& interp) {
-        std::string str;
-        node.Read<std::string>(str);
-        interp = InterpolationFromString(str.c_str());
+    void OCIOYaml::write(std::ostream& ostream, const Config* c) const
+    {
+        YAML::Emitter out;
+        save(out, c);
+        ostream << out.c_str();
     }
     
 }
diff --git a/src/core/OCIOYaml.h b/src/core/OCIOYaml.h
index 7104123..364a262 100644
--- a/src/core/OCIOYaml.h
+++ b/src/core/OCIOYaml.h
@@ -28,97 +28,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <OpenColorIO/OpenColorIO.h>
 
-#include "Platform.h"
-
-#ifndef WINDOWS
-
-// fwd declare yaml-cpp visibility
-#pragma GCC visibility push(hidden)
-namespace YAML {
-    class Exception;
-    class BadDereference;
-    class RepresentationException;
-    class EmitterException;
-    class ParserException;
-    class InvalidScalar;
-    class KeyNotFound;
-    template <typename T> class TypedKeyNotFound;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpace>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Config>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Exception>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GpuShaderDesc>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ImageDesc>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Look>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Processor>;
-    
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Transform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::AllocationTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::CDLTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpaceTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::DisplayTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ExponentTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::FileTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GroupTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LogTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LookTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::MatrixTransform>;
-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::TruelightTransform>;
-}
-#pragma GCC visibility pop
-
-#endif 
-
-#include <yaml-cpp/yaml.h>
-
 #ifndef INCLUDED_OCIO_YAML_H
 #define INCLUDED_OCIO_YAML_H
 
 OCIO_NAMESPACE_ENTER
 {
     
-    // Core
-    OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceRcPtr& cs);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceRcPtr cs);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, GroupTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstGroupTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, TransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, LookRcPtr& cs);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, LookRcPtr cs);
-    
-    // Transforms
-    OCIOHIDDEN void operator >> (const YAML::Node& node, AllocationTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstAllocationTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, CDLTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstCDLTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstColorSpaceTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, ExponentTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstExponentTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, FileTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstFileTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, LogTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstLogTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, LookTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstLookTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, MatrixTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstMatrixTransformRcPtr t);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, TruelightTransformRcPtr& t);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstTruelightTransformRcPtr t);
-    
-    // Enums
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, BitDepth depth);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, BitDepth& depth);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, Allocation alloc);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, Allocation& alloc);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceDirection dir);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceDirection& dir);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, TransformDirection dir);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, TransformDirection& dir);
-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, Interpolation iterp);
-    OCIOHIDDEN void operator >> (const YAML::Node& node, Interpolation& iterp);
+    class OCIOYaml
+    {
+    public:
+        void open(std::istream& istream, ConfigRcPtr& c, const char* filename = NULL) const;
+        void write(std::ostream& ostream, const Config* c) const;
+    };
     
-    void LogUnknownKeyWarning(const std::string & name, const YAML::Node& tag);
 }
 OCIO_NAMESPACE_EXIT
 
