/*
 *  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
