|  | /* | 
|  | *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #ifndef WEBRTC_COMMON_H | 
|  | #define WEBRTC_COMMON_H | 
|  |  | 
|  | #include <map> | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | // Class Config is designed to ease passing a set of options across webrtc code. | 
|  | // Options are identified by typename in order to avoid incorrect casts. | 
|  | // | 
|  | // Usage: | 
|  | // * declaring an option: | 
|  | //    struct Algo1_CostFunction { | 
|  | //      virtual float cost(int x) const { return x; } | 
|  | //      virtual ~Algo1_CostFunction() {} | 
|  | //    }; | 
|  | // | 
|  | // * accessing an option: | 
|  | //    config.Get<Algo1_CostFunction>().cost(value); | 
|  | // | 
|  | // * setting an option: | 
|  | //    struct SqrCost : Algo1_CostFunction { | 
|  | //      virtual float cost(int x) const { return x*x; } | 
|  | //    }; | 
|  | //    config.Set<Algo1_CostFunction>(new SqrCost()); | 
|  | // | 
|  | // Note: This class is thread-compatible (like STL containers). | 
|  | class Config { | 
|  | public: | 
|  | // Returns the option if set or a default constructed one. | 
|  | // Callers that access options to often are encouraged to cache the result. | 
|  | // Returned references are owned by this. | 
|  | // | 
|  | // Requires std::is_default_constructible<T> | 
|  | template<typename T> const T& Get() const; | 
|  |  | 
|  | // Set the option, deleting any previous instance of the same. | 
|  | // This instance gets ownership of the newly setted value. | 
|  | template<typename T> void Set(T* value); | 
|  |  | 
|  | Config() {} | 
|  | ~Config() { | 
|  | // Note: this method is inline so webrtc public API depends only | 
|  | // on the headers. | 
|  | for (OptionMap::iterator it = options_.begin(); | 
|  | it != options_.end(); ++it) { | 
|  | delete it->second; | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | typedef void* OptionIdentifier; | 
|  |  | 
|  | struct BaseOption { | 
|  | virtual ~BaseOption() {} | 
|  | }; | 
|  |  | 
|  | template<typename T> | 
|  | struct Option : BaseOption { | 
|  | explicit Option(T* v): value(v) {} | 
|  | ~Option() { | 
|  | delete value; | 
|  | } | 
|  | T* value; | 
|  | }; | 
|  |  | 
|  | // Own implementation of rtti-subset to avoid depending on rtti and its costs. | 
|  | template<typename T> | 
|  | static OptionIdentifier identifier() { | 
|  | static char id_placeholder; | 
|  | return &id_placeholder; | 
|  | } | 
|  |  | 
|  | // Used to instantiate a default constructed object that doesn't needs to be | 
|  | // owned. This allows Get<T> to be implemented without requiring explicitly | 
|  | // locks. | 
|  | template<typename T> | 
|  | static const T& default_value() { | 
|  | static const T def; | 
|  | return def; | 
|  | } | 
|  |  | 
|  | typedef std::map<OptionIdentifier, BaseOption*> OptionMap; | 
|  | OptionMap options_; | 
|  |  | 
|  | // DISALLOW_COPY_AND_ASSIGN | 
|  | Config(const Config&); | 
|  | void operator=(const Config&); | 
|  | }; | 
|  |  | 
|  | template<typename T> | 
|  | const T& Config::Get() const { | 
|  | OptionMap::const_iterator it = options_.find(identifier<T>()); | 
|  | if (it != options_.end()) { | 
|  | const T* t = static_cast<Option<T>*>(it->second)->value; | 
|  | if (t) { | 
|  | return *t; | 
|  | } | 
|  | } | 
|  | return default_value<T>(); | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | void Config::Set(T* value) { | 
|  | BaseOption*& it = options_[identifier<T>()]; | 
|  | delete it; | 
|  | it = new Option<T>(value); | 
|  | } | 
|  | }  // namespace webrtc | 
|  | #endif  // WEBRTC_COMMON_H |