start using global, 100% generic enum to/from string object
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 22 Dec 2006 16:09:43 +0000 (16:09 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 22 Dec 2006 16:09:43 +0000 (16:09 +0000)
git-svn-id: svn://localhost/ardour2/trunk@1246 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/SConscript
libs/ardour/ardour/types.h
libs/ardour/audioregion.cc
libs/ardour/enums.cc [new file with mode: 0644]
libs/ardour/globals.cc
libs/ardour/session.cc
libs/ardour/session_state.cc
libs/pbd/SConscript
libs/pbd/enumwriter.cc [new file with mode: 0644]
libs/pbd/pbd/enumwriter.h [new file with mode: 0644]

index 2b23f4ffac849765223589b5f3a282ee1353c046..9f77f0af9c569c0c417dd3dc8c7d5accf40d7e57 100644 (file)
@@ -48,6 +48,7 @@ crossfade.cc
 curve.cc
 cycle_timer.cc
 default_click.cc
+enums.cc
 gain.cc
 gdither.cc
 globals.cc
index 32b3231c4e3e6b1eca0f7c64972f3e3f0ec62e54..27ff8e93da90c19fa063f8a0e10a68d36a37b701 100644 (file)
@@ -324,7 +324,7 @@ namespace ARDOUR {
        };
 
        enum ShuttleUnits {
-               Percentage,
+               Percentage,
                Semitones
        };
 
index 32bd6cd6851aed6f876c77d9f90248b160a60a49..7d3c1fc54903db2461856f72ed1e85fa7112d9be 100644 (file)
@@ -32,6 +32,7 @@
 #include <pbd/basename.h>
 #include <pbd/xml++.h>
 #include <pbd/stacktrace.h>
+#include <pbd/enumwriter.h>
 
 #include <ardour/audioregion.h>
 #include <ardour/session.h>
@@ -601,8 +602,10 @@ AudioRegion::state (bool full)
        char buf2[64];
        LocaleGuard lg (X_("POSIX"));
        
-       snprintf (buf, sizeof (buf), "0x%x", (int) _flags);
-       node.add_property ("flags", buf);
+       // snprintf (buf, sizeof (buf), "0x%x", (int) _flags);
+       // node.add_property ("flags", buf);
+       node.add_property ("flags", enum_2_string (_flags));
+
        snprintf (buf, sizeof(buf), "%.12g", _scale_amplitude);
        node.add_property ("scale-gain", buf);
 
@@ -683,7 +686,9 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen
        uint32_t old_flags = _flags;
                
        if ((prop = node.property ("flags")) != 0) {
-               _flags = Flag (strtol (prop->value().c_str(), (char **) 0, 16));
+               _flags = Flag (string_2_enum (prop->value(), _flags));
+
+               //_flags = Flag (strtol (prop->value().c_str(), (char **) 0, 16));
 
                _flags = Flag (_flags & ~Region::LeftOfSplit);
                _flags = Flag (_flags & ~Region::RightOfSplit);
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
new file mode 100644 (file)
index 0000000..293ffac
--- /dev/null
@@ -0,0 +1,321 @@
+#include <pbd/enumwriter.h>
+
+#include <ardour/types.h>
+#include <ardour/session.h>
+#include <ardour/location.h>
+#include <ardour/audiofilesource.h>
+#include <ardour/diskstream.h>
+#include <ardour/audioregion.h>
+#include <ardour/route_group.h>
+#include <ardour/panner.h>
+
+using namespace std;
+using namespace PBD;
+using namespace ARDOUR;
+
+void
+setup_enum_writer ()
+{
+       EnumWriter* enum_writer = new EnumWriter();
+       vector<int> i;
+       vector<string> s;
+
+
+       OverlapType _OverlapType;
+       AlignStyle _AlignStyle;
+       MeterPoint _MeterPoint;
+       TrackMode _TrackMode;
+       MeterFalloff _MeterFalloff;
+       MeterHold _MeterHold;
+       EditMode _EditMode;
+       RegionPoint _RegionPoint;
+       Placement _Placement;
+       MonitorModel _MonitorModel;
+       CrossfadeModel _CrossfadeModel;
+       LayerModel _LayerModel;
+       SoloModel _SoloModel;
+       SampleFormat _SampleFormat;
+       HeaderFormat _HeaderFormat;
+       PluginType _PluginType;
+       SlaveSource _SlaveSource;
+       ShuttleBehaviour _ShuttleBehaviour;
+       ShuttleUnits _ShuttleUnits;
+       mute_type _mute_type;
+       Session::RecordState _Session_RecordState;
+       Session::Event::Type _Session_Event_Type;
+       Session::SmpteFormat _Session_SmpteFormat;
+       Session::PullupFormat _Session_PullupFormat;
+       AudioRegion::FadeShape _AudioRegion_FadeShape;
+       Panner::LinkDirection _Panner_LinkDirection;
+       IOChange _IOChange;
+       AutomationType _AutomationType;
+       AutoState _AutoState;
+       AutoStyle _AutoStyle;
+       AutoConnectOption _AutoConnectOption;
+       Session::StateOfTheState _Session_StateOfTheState;
+       Route::Flag _Route_Flag;
+       AudioFileSource::Flag _AudioFileSource_Flag;
+       Diskstream::Flag _Diskstream_Flag;
+       Location::Flags _Location_Flags;
+       RouteGroup::Flag _RouteGroup_Flag;
+       Region::Flag _Region_Flag;
+
+#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
+#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
+#define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e)
+#define REGISTER_CLASS_ENUM(t,e) i.push_back (t::e); s.push_back (#e)
+
+       REGISTER_ENUM (NoChange);
+       REGISTER_ENUM (ConfigurationChanged);
+       REGISTER_ENUM (ConnectionsChanged);
+       REGISTER_BITS (_IOChange);
+
+       REGISTER_ENUM (OverlapNone);
+       REGISTER_ENUM (OverlapInternal);
+       REGISTER_ENUM (OverlapStart);
+       REGISTER_ENUM (OverlapEnd);
+       REGISTER_ENUM (OverlapExternal);
+       REGISTER (_OverlapType);
+       
+       REGISTER_ENUM (GainAutomation);
+       REGISTER_ENUM (PanAutomation);
+       REGISTER_ENUM (PluginAutomation);
+       REGISTER_ENUM (SoloAutomation);
+       REGISTER_ENUM (MuteAutomation);
+       REGISTER_BITS (_AutomationType);
+
+       REGISTER_ENUM (Off);
+       REGISTER_ENUM (Write);
+       REGISTER_ENUM (Touch);
+       REGISTER_ENUM (Play);
+       REGISTER_BITS (_AutoState);
+
+       REGISTER_ENUM (Absolute);
+       REGISTER_ENUM (Trim);
+       REGISTER_BITS (_AutoStyle);
+
+       REGISTER_ENUM (CaptureTime);
+       REGISTER_ENUM (ExistingMaterial);       
+       REGISTER (_AlignStyle);
+
+       REGISTER_ENUM (MeterInput);
+       REGISTER_ENUM (MeterPreFader);
+       REGISTER_ENUM (MeterPostFader); 
+       REGISTER (_MeterPoint);
+
+       REGISTER_ENUM (Normal);
+       REGISTER_ENUM (Destructive);
+       REGISTER (_TrackMode);
+
+       REGISTER_ENUM (MeterFalloffOff);
+       REGISTER_ENUM (MeterFalloffSlowest);
+       REGISTER_ENUM (MeterFalloffSlow);
+       REGISTER_ENUM (MeterFalloffMedium);
+       REGISTER_ENUM (MeterFalloffFast);
+       REGISTER_ENUM (MeterFalloffFaster);
+       REGISTER_ENUM (MeterFalloffFastest);
+       REGISTER (_MeterFalloff);
+       
+       REGISTER_ENUM (MeterHoldOff);
+       REGISTER_ENUM (MeterHoldShort);
+       REGISTER_ENUM (MeterHoldMedium);
+       REGISTER_ENUM (MeterHoldLong);
+       REGISTER (_MeterHold);
+
+       REGISTER_ENUM (Slide);
+       REGISTER_ENUM (Splice); 
+       REGISTER (_EditMode);
+
+       REGISTER_ENUM (Start);
+       REGISTER_ENUM (End);
+       REGISTER_ENUM (SyncPoint);      
+       REGISTER (_RegionPoint);
+
+
+       REGISTER_ENUM (PreFader);
+       REGISTER_ENUM (PostFader);
+       REGISTER (_Placement);
+
+       REGISTER_ENUM (HardwareMonitoring);
+       REGISTER_ENUM (SoftwareMonitoring);
+       REGISTER_ENUM (ExternalMonitoring);
+       REGISTER (_MonitorModel);
+
+       REGISTER_ENUM (FullCrossfade);
+       REGISTER_ENUM (ShortCrossfade);
+       REGISTER (_CrossfadeModel);
+
+       REGISTER_ENUM (LaterHigher);
+       REGISTER_ENUM (MoveAddHigher);
+       REGISTER_ENUM (AddHigher);      
+       REGISTER (_LayerModel);
+
+       REGISTER_ENUM (InverseMute);
+       REGISTER_ENUM (SoloBus);        
+       REGISTER (_SoloModel);
+
+       REGISTER_ENUM (AutoConnectPhysical);
+       REGISTER_ENUM (AutoConnectMaster);
+       REGISTER_BITS (_AutoConnectOption);
+
+       REGISTER_ENUM (FormatFloat);
+       REGISTER_ENUM (FormatInt24);
+       REGISTER (_SampleFormat);
+
+       REGISTER_ENUM (BWF);
+       REGISTER_ENUM (WAVE);
+       REGISTER_ENUM (WAVE64);
+       REGISTER_ENUM (CAF);
+       REGISTER_ENUM (AIFF);
+       REGISTER_ENUM (iXML);
+       REGISTER_ENUM (RF64);   
+       REGISTER (_HeaderFormat);
+
+       REGISTER_ENUM (AudioUnit);
+       REGISTER_ENUM (LADSPA);
+       REGISTER_ENUM (VST);
+       REGISTER (_PluginType);
+
+       REGISTER_ENUM (None);
+       REGISTER_ENUM (MTC);
+       REGISTER_ENUM (JACK);   
+       REGISTER (_SlaveSource);
+
+       REGISTER_ENUM (Sprung);
+       REGISTER_ENUM (Wheel);  
+       REGISTER (_ShuttleBehaviour);
+
+       REGISTER_ENUM (Percentage);
+       REGISTER_ENUM (Semitones);      
+       REGISTER (_ShuttleUnits);
+
+       REGISTER_CLASS_ENUM (Session, Disabled);
+       REGISTER_CLASS_ENUM (Session, Enabled);
+       REGISTER_CLASS_ENUM (Session, Recording);
+       REGISTER (_Session_RecordState);
+
+       REGISTER_CLASS_ENUM (Session::Event, SetTransportSpeed);
+       REGISTER_CLASS_ENUM (Session::Event, SetDiskstreamSpeed);
+       REGISTER_CLASS_ENUM (Session::Event, Locate);
+       REGISTER_CLASS_ENUM (Session::Event, LocateRoll);
+       REGISTER_CLASS_ENUM (Session::Event, SetLoop);
+       REGISTER_CLASS_ENUM (Session::Event, PunchIn);
+       REGISTER_CLASS_ENUM (Session::Event, PunchOut);
+       REGISTER_CLASS_ENUM (Session::Event, RangeStop);
+       REGISTER_CLASS_ENUM (Session::Event, RangeLocate);
+       REGISTER_CLASS_ENUM (Session::Event, Overwrite);
+       REGISTER_CLASS_ENUM (Session::Event, SetSlaveSource);
+       REGISTER_CLASS_ENUM (Session::Event, Audition);
+       REGISTER_CLASS_ENUM (Session::Event, InputConfigurationChange);
+       REGISTER_CLASS_ENUM (Session::Event, SetAudioRange);
+       REGISTER_CLASS_ENUM (Session::Event, SetPlayRange);
+       REGISTER_CLASS_ENUM (Session::Event, StopOnce);
+       REGISTER_CLASS_ENUM (Session::Event, AutoLoop);
+       REGISTER (_Session_Event_Type);
+
+       REGISTER_CLASS_ENUM (Session, Clean);
+       REGISTER_CLASS_ENUM (Session, Dirty);
+       REGISTER_CLASS_ENUM (Session, CannotSave);
+       REGISTER_CLASS_ENUM (Session, Deletion);
+       REGISTER_CLASS_ENUM (Session, InitialConnecting);
+       REGISTER_CLASS_ENUM (Session, Loading);
+       REGISTER_CLASS_ENUM (Session, InCleanup);
+       REGISTER_BITS (_Session_StateOfTheState);
+
+       REGISTER_CLASS_ENUM (Session, smpte_23976);
+       REGISTER_CLASS_ENUM (Session, smpte_24);
+       REGISTER_CLASS_ENUM (Session, smpte_24976);
+       REGISTER_CLASS_ENUM (Session, smpte_25);
+       REGISTER_CLASS_ENUM (Session, smpte_2997);
+       REGISTER_CLASS_ENUM (Session, smpte_2997drop);
+       REGISTER_CLASS_ENUM (Session, smpte_30);
+       REGISTER_CLASS_ENUM (Session, smpte_30drop);
+       REGISTER_CLASS_ENUM (Session, smpte_5994);
+       REGISTER_CLASS_ENUM (Session, smpte_60);
+       REGISTER (_Session_SmpteFormat);
+
+       REGISTER_CLASS_ENUM (Session, pullup_Plus4Plus1);
+       REGISTER_CLASS_ENUM (Session, pullup_Plus4);
+       REGISTER_CLASS_ENUM (Session, pullup_Plus4Minus1);
+       REGISTER_CLASS_ENUM (Session, pullup_Plus1);
+       REGISTER_CLASS_ENUM (Session, pullup_None);
+       REGISTER_CLASS_ENUM (Session, pullup_Minus1);
+       REGISTER_CLASS_ENUM (Session, pullup_Minus4Plus1);
+       REGISTER_CLASS_ENUM (Session, pullup_Minus4);
+       REGISTER_CLASS_ENUM (Session, pullup_Minus4Minus1);
+       REGISTER (_Session_PullupFormat);
+
+       REGISTER_ENUM (PRE_FADER);
+       REGISTER_ENUM (POST_FADER);
+       REGISTER_ENUM (CONTROL_OUTS);
+       REGISTER_ENUM (MAIN_OUTS);
+       REGISTER (_mute_type);
+
+       REGISTER_CLASS_ENUM (Route, Hidden);
+       REGISTER_CLASS_ENUM (Route, MasterOut);
+       REGISTER_CLASS_ENUM (Route, ControlOut);
+       REGISTER_BITS (_Route_Flag);
+
+       REGISTER_CLASS_ENUM (AudioFileSource, Writable);
+       REGISTER_CLASS_ENUM (AudioFileSource, CanRename);
+       REGISTER_CLASS_ENUM (AudioFileSource, Broadcast);
+       REGISTER_CLASS_ENUM (AudioFileSource, Removable);
+       REGISTER_CLASS_ENUM (AudioFileSource, RemovableIfEmpty);
+       REGISTER_CLASS_ENUM (AudioFileSource, RemoveAtDestroy);
+       REGISTER_CLASS_ENUM (AudioFileSource, NoPeakFile);
+       REGISTER_CLASS_ENUM (AudioFileSource, Destructive);
+       REGISTER_BITS (_AudioFileSource_Flag);
+
+       REGISTER_CLASS_ENUM (AudioRegion, Linear);
+       REGISTER_CLASS_ENUM (AudioRegion, Fast);
+       REGISTER_CLASS_ENUM (AudioRegion, Slow);
+       REGISTER_CLASS_ENUM (AudioRegion, LogA);
+       REGISTER_CLASS_ENUM (AudioRegion, LogB);
+       REGISTER (_AudioRegion_FadeShape);
+
+       REGISTER_CLASS_ENUM (Diskstream, Recordable);
+       REGISTER_CLASS_ENUM (Diskstream, Hidden);
+       REGISTER_CLASS_ENUM (Diskstream, Destructive);
+       REGISTER_BITS (_Diskstream_Flag);
+
+       REGISTER_CLASS_ENUM (Location, IsMark);
+       REGISTER_CLASS_ENUM (Location, IsAutoPunch);
+       REGISTER_CLASS_ENUM (Location, IsAutoLoop);
+       REGISTER_CLASS_ENUM (Location, IsHidden);
+       REGISTER_CLASS_ENUM (Location, IsCDMarker);
+       REGISTER_CLASS_ENUM (Location, IsEnd);
+       REGISTER_CLASS_ENUM (Location, IsRangeMarker);
+       REGISTER_CLASS_ENUM (Location, IsStart);
+       REGISTER_BITS (_Location_Flags);
+
+
+       REGISTER_CLASS_ENUM (RouteGroup, Relative);
+       REGISTER_CLASS_ENUM (RouteGroup, Active);
+       REGISTER_CLASS_ENUM (RouteGroup, Hidden);
+       REGISTER_BITS (_RouteGroup_Flag);
+
+       REGISTER_CLASS_ENUM (Panner, SameDirection);
+       REGISTER_CLASS_ENUM (Panner, OppositeDirection);
+       REGISTER (_Panner_LinkDirection);
+
+       REGISTER_CLASS_ENUM (Region, Muted);
+       REGISTER_CLASS_ENUM (Region, Opaque);
+       REGISTER_CLASS_ENUM (Region, EnvelopeActive);
+       REGISTER_CLASS_ENUM (Region, DefaultFadeIn);
+       REGISTER_CLASS_ENUM (Region, DefaultFadeOut);
+       REGISTER_CLASS_ENUM (Region, Locked);
+       REGISTER_CLASS_ENUM (Region, Automatic);
+       REGISTER_CLASS_ENUM (Region, WholeFile);
+       REGISTER_CLASS_ENUM (Region, FadeIn);
+       REGISTER_CLASS_ENUM (Region, FadeOut);
+       REGISTER_CLASS_ENUM (Region, Copied);
+       REGISTER_CLASS_ENUM (Region, Import);
+       REGISTER_CLASS_ENUM (Region, External);
+       REGISTER_CLASS_ENUM (Region, SyncMarked);
+       REGISTER_CLASS_ENUM (Region, LeftOfSplit);
+       REGISTER_CLASS_ENUM (Region, RightOfSplit);
+       REGISTER_CLASS_ENUM (Region, Hidden);
+       REGISTER_CLASS_ENUM (Region, DoNotSaveState);
+       REGISTER_BITS (_Region_Flag);
+       
+}
index c68951e525a8e958abcf13ac931015a2d1ec930e..274b0f1d3cfcaf4a78d097a9b4c5dfd181bf39e1 100644 (file)
@@ -274,10 +274,14 @@ setup_hardware_optimization (bool try_optimization)
 int
 ARDOUR::init (bool use_vst, bool try_optimization)
 {
+       extern void setup_enum_writer ();
+
        (void) bindtextdomain(PACKAGE, LOCALEDIR);
 
        PBD::ID::init ();
 
+       setup_enum_writer ();
+
        lrdf_init();
        Library = new AudioLibrary;
 
index 962e8487bf0227724c8db1baf0927a45019c11ba..45be26c598fa34f2f282170c14ee7a8b2b589738 100644 (file)
@@ -2682,6 +2682,7 @@ Session::add_source (boost::shared_ptr<Source> source)
                        source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source)));
                        set_dirty();
                }
+
        } 
 }
 
index 986656af5acde4e44a5e905758033b4c6f21e554..fb15de15c4b468bea5acc7fd0457257e7252fbd9 100644 (file)
@@ -1429,6 +1429,7 @@ Session::load_sources (const XMLNode& node)
                if ((source = XMLSourceFactory (**niter)) == 0) {
                        error << _("Session: cannot create Source from XML description.") << endmsg;
                }
+
        }
 
        return 0;
index f474834fd8eef7863cd03bf80dce7b5e38e40497..b16880b2868b9b3339b3ccf7e97efb446411733b 100644 (file)
@@ -23,6 +23,7 @@ base_ui.cc
 convert.cc
 command.cc
 controllable.cc
+enumwriter.cc
 dmalloc.cc
 error.cc
 id.cc
diff --git a/libs/pbd/enumwriter.cc b/libs/pbd/enumwriter.cc
new file mode 100644 (file)
index 0000000..c42cc3a
--- /dev/null
@@ -0,0 +1,194 @@
+/* 
+    Copyright (C) 2006 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    $Id$
+*/
+
+#include <pbd/enumwriter.h>
+#include <pbd/error.h>
+#include <pbd/compose.h>
+
+using namespace std;
+using namespace PBD;
+
+#include "i18n.h"
+
+EnumWriter* EnumWriter::_instance = 0;
+
+EnumWriter::EnumWriter ()
+{
+       if (_instance == 0) {
+               _instance = this;
+       }
+}
+
+EnumWriter::~EnumWriter ()
+{
+}
+
+void
+EnumWriter::register_distinct (string type, vector<int> v, vector<string> s)
+{
+       pair<string,EnumRegistration> newpair;
+       pair<Registry::iterator,bool> result;
+
+       newpair.first = type;
+       newpair.second = EnumRegistration (v, s, false);
+       
+       result = registry.insert (newpair);
+
+       if (!result.second) {
+               warning << string_compose (_("enum type \"%1\" already registered with the enum writer"), type) << endmsg;
+       }
+}
+
+void
+EnumWriter::register_bits (string type, vector<int> v, vector<string> s)
+{
+       pair<string,EnumRegistration> newpair;
+       pair<Registry::iterator,bool> result;
+
+       newpair.first = type;
+       newpair.second = EnumRegistration (v, s, true);
+       
+       result = registry.insert (newpair);
+
+       if (!result.second) {
+               warning << _("enum type \"%1\" already registered with the enum writer") << endmsg;
+       }
+}
+
+string
+EnumWriter::write (string type, int value)
+{
+       Registry::iterator x = registry.find (type);
+
+       if (x == registry.end()) {
+               error << string_compose (_("EnumWriter: unknown enumeration type \"%1\""), type) << endmsg;
+               throw unknown_enumeration();
+       }
+
+       if (x->second.bitwise) {
+               return write_bits (x->second, value);
+       } else {
+               return write_distinct (x->second, value);
+       }
+}
+
+int
+EnumWriter::read (string type, string value)
+{
+       Registry::iterator x = registry.find (type);
+
+       if (x == registry.end()) {
+               error << string_compose (_("EnumWriter: unknown enumeration type \"%1\""), type) << endmsg;
+               throw unknown_enumeration();
+       }
+
+       if (x->second.bitwise) {
+               return read_bits (x->second, value);
+       } else {
+               return read_distinct (x->second, value);
+       }
+}      
+
+string
+EnumWriter::write_bits (EnumRegistration& er, int value)
+{
+       vector<int>::iterator i;
+       vector<string>::iterator s;
+       string result;
+
+       for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) {
+               if (value & (*i)) {
+                       if (!result.empty()) {
+                               result += ',';
+                       } 
+                       result += (*s);
+               }
+       }
+
+       return result;
+}
+
+string
+EnumWriter::write_distinct (EnumRegistration& er, int value)
+{
+       vector<int>::iterator i;
+       vector<string>::iterator s;
+
+       for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) {
+               if (value == (*i)) {
+                       return (*s);
+               }
+       }
+
+       return string();
+}
+
+int
+EnumWriter::read_bits (EnumRegistration& er, string str)
+{
+       vector<int>::iterator i;
+       vector<string>::iterator s;
+       int result = 0;
+       bool found = false;
+       string::size_type comma;
+
+       do {
+               
+               comma = str.find_first_of (',');
+               string segment = str.substr (0, comma);
+
+               for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) {
+                       if (segment == (*s)) {
+                               result |= (*i);
+                               found = true;
+                       }
+               }
+
+               if (comma == string::npos) {
+                       break;
+               }
+
+               str = str.substr (comma+1);
+
+       } while (true);
+
+       if (!found) {
+               throw unknown_enumeration();
+       }
+
+       return result;
+}
+
+int
+EnumWriter::read_distinct (EnumRegistration& er, string str)
+{
+       vector<int>::iterator i;
+       vector<string>::iterator s;
+
+       for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) {
+               if (str == (*s)) {
+                       return (*i);
+               }
+       }
+
+       throw unknown_enumeration();
+}
+
+
diff --git a/libs/pbd/pbd/enumwriter.h b/libs/pbd/pbd/enumwriter.h
new file mode 100644 (file)
index 0000000..356a0a1
--- /dev/null
@@ -0,0 +1,74 @@
+/* 
+    Copyright (C) 2006 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    $Id$
+*/
+
+#include <map>
+#include <string>
+#include <vector>
+#include <exception>
+
+
+namespace PBD {
+
+class unknown_enumeration : public std::exception {
+  public:
+       virtual const char *what() const throw() { return "unknown enumerator in PBD::EnumWriter"; }
+};
+
+class EnumWriter {
+  public:
+       EnumWriter ();
+       ~EnumWriter ();
+
+       static EnumWriter& instance() { return *_instance; }
+
+       void register_distinct (std::string type, std::vector<int>, std::vector<std::string>);
+       void register_bits     (std::string type, std::vector<int>, std::vector<std::string>);
+
+       std::string write (std::string type, int value);
+       int         read  (std::string type, std::string value);
+
+  private:
+       struct EnumRegistration {
+           std::vector<int> values;
+           std::vector<std::string> names;
+           bool bitwise;
+
+           EnumRegistration() {}
+           EnumRegistration (std::vector<int>& v, std::vector<std::string>& s, bool b) 
+                   : values (v), names (s), bitwise (b) {}
+       };
+
+       typedef std::map<std::string, EnumRegistration> Registry;
+       Registry registry;
+
+       std::string write_bits (EnumRegistration&, int value);
+       std::string write_distinct (EnumRegistration&, int value);
+
+       int read_bits (EnumRegistration&, std::string value);
+       int read_distinct (EnumRegistration&, std::string value);
+
+       static EnumWriter* _instance;
+};
+
+}
+
+#define enum_2_string(e) (PBD::EnumWriter::instance().write (typeid(e).name(), e))
+#define string_2_enum(str,e) (PBD::EnumWriter::instance().read (typeid(e).name(), (str)))
+