-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/develop'
- Loading branch information
Showing
60 changed files
with
2,137 additions
and
996 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -117,38 +117,3 @@ | |
|
||
====================================================== | ||
|
||
1. Jared Deckard | ||
Github account: deckar01 | ||
Email: [email protected] | ||
|
||
2. Stu Kabakoff | ||
Github account: sakabako | ||
Email: [email protected] | ||
|
||
3. Yoshihiro Iwanaga | ||
Github account: iwanaga | ||
Email: [email protected] | ||
|
||
4. ARJUNKUMAR KRISHNAMOORTHY | ||
Github account: tk120404 | ||
Email: [email protected] | ||
|
||
5. Rob Witoff | ||
Github account: witoff | ||
Email: [email protected] | ||
|
||
6. Richard Pearson | ||
Github account: catdevnull | ||
Email: [email protected] | ||
|
||
7. Ben Nortier | ||
Github account: bjnortier | ||
Email: [email protected] | ||
|
||
8. Andrew Kennedy | ||
Github account: akenn | ||
Email: [email protected] | ||
|
||
9. Victor Norgren | ||
Github account: logotype | ||
Email: [email protected] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,179 @@ | ||
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. | ||
#pragma once | ||
#include "AutoConfigBase.h" | ||
#include "Autowired.h" | ||
#include "AutoConfigManager.h" | ||
#include "ConfigRegistry.h" | ||
|
||
#include <string> | ||
#include TYPE_INDEX_HEADER | ||
|
||
struct AnySharedPointer; | ||
|
||
/// \internal | ||
/// <summary> | ||
/// Utility base type for configuration members | ||
/// </summary> | ||
class AutoConfigBase | ||
{ | ||
public: | ||
AutoConfigBase(const std::type_info& tiName); | ||
|
||
// Key used to identify this config value | ||
const std::string m_key; | ||
}; | ||
|
||
/// The type underlying the AutoConfig System. | ||
/// Represents a unique type created by the combination of the type and a set of sigils. | ||
/// Responsible for tracking changes to the underlying value and triggering signals, | ||
/// making sure values are inherited correctly from enclosing contexts, and providing | ||
/// a primitive polymorphic get/set interface (void*) | ||
/// <summary> | ||
/// Register an attribute with the AutoConfig system. For example | ||
/// | ||
/// AutoConfig<int, struct MyNamespace, struct MyKey> m_myVal; | ||
/// defines the key "MyNamespace.MyKey" | ||
/// | ||
/// The Namespace field is optional, so | ||
/// AutoConfig<int, struct MyKey> m_myVal; | ||
/// defines the key "MyKey" | ||
/// | ||
/// AutoConfig values can be set from the AutoConfigManager. The string key | ||
/// is used as the identifier for the value | ||
/// </summary> | ||
|
||
template<class T, class... TKey> | ||
class AutoConfig: | ||
public AutoConfigBase | ||
class AutoConfigVar: | ||
public AutoConfigVarBase | ||
{ | ||
public: | ||
static_assert(sizeof...(TKey) >= 1, "Must provide a key and optionally at least one namespace"); | ||
static_assert(sizeof...(TKey) >= 1, "Must provide a key and optionally a set of namespaces"); | ||
|
||
template<typename t_Arg, typename ...t_Args> | ||
AutoConfig(t_Arg &&arg, t_Args&&... args) : | ||
AutoConfigBase(typeid(ConfigTypeExtractor<TKey...>)) | ||
AutoConfigVar(t_Arg &&arg, t_Args&&... args) : | ||
AutoConfigVarBase(typeid(ConfigTypeExtractor<TKey...>), true), | ||
m_value(std::forward<t_Arg>(arg), std::forward<t_Args>(args)...) | ||
{ | ||
// Register with config registry | ||
(void)RegConfig<T, TKey...>::r; | ||
(void)AutoConfigVar<T, TKey...>::RegistryEntry; | ||
|
||
if (!IsConfigured()){ | ||
m_manager->Set(m_key, T(std::forward<t_Arg>(arg), std::forward<t_Args>(args)...)); | ||
if (RegistryEntry.m_hasValidator) { | ||
if (!RegistryEntry.validatorInternal()(m_value)) { | ||
throw autowiring_error("Cannot construct AutoConfigVar with a value that fails validation"); | ||
} | ||
} | ||
|
||
onChangedSignal(*this); | ||
} | ||
|
||
AutoConfig() : | ||
AutoConfigBase(typeid(ConfigTypeExtractor<TKey...>)) | ||
AutoConfigVar() : | ||
AutoConfigVarBase(typeid(ConfigTypeExtractor<TKey...>)), | ||
m_value() | ||
{ | ||
// Register with config registry | ||
(void)RegConfig<T, TKey...>::r; | ||
} | ||
(void)AutoConfigVar<T, TKey...>::RegistryEntry; | ||
|
||
const auto ctxt = m_context.lock(); | ||
if (!ctxt) | ||
return; | ||
|
||
protected: | ||
AutoRequired<AutoConfigManager> m_manager; | ||
//This will wind up being recursive | ||
auto parent = ctxt->GetParentContext(); | ||
if (parent != nullptr) { | ||
auto parentVar = parent->template Inject<AutoConfigVar<T, TKey...>>(); | ||
|
||
public: | ||
const T& operator*() const { | ||
return *m_manager->Get(m_key).template as<T>().get(); | ||
} | ||
//Only copy the value if it's initalized. Base::AutoInit will take care of | ||
//the various listing notifications. | ||
if (parentVar->IsConfigured()) { | ||
m_isConfigured = true; | ||
m_value = parentVar->m_value; | ||
} | ||
|
||
const T* operator->(void) const { | ||
return m_manager->Get(m_key)->template as<T>().get(); | ||
m_parentRegistration = *parentVar += [this](const T& val){ | ||
RunValidation(val); | ||
SetInternal(val); | ||
}; | ||
} | ||
} | ||
|
||
public: | ||
|
||
operator const T&() const { return m_value; } | ||
const T* operator->() const { return &m_value; } | ||
|
||
void operator=(const T& newValue) { | ||
return m_manager->Set(m_key, newValue); | ||
RunValidation(newValue); | ||
|
||
if (m_parentRegistration) { | ||
auto parent_ctxt = m_context.lock()->GetParentContext(); | ||
AutowiredFast<AutoConfigVar<T, TKey...>> parentVar(parent_ctxt); | ||
*parentVar -= m_parentRegistration; | ||
m_parentRegistration = nullptr; | ||
OnSetLocally(); | ||
} | ||
|
||
SetInternal(newValue); | ||
} | ||
|
||
/// <returns> | ||
/// True if this configurable field has been satisfied with a value | ||
/// </returns> | ||
bool IsConfigured(void) const { | ||
return m_manager->IsConfigured(m_key); | ||
void Get(void* pValue) const override { *reinterpret_cast<T*>(pValue) = m_value; } | ||
void Set(const void* pValue) override { *this = *reinterpret_cast<const T*>(pValue); } | ||
|
||
void SetParsed(const std::string& value) override { | ||
*this = RegistryEntry.template parseInternal<T>(value); | ||
} | ||
|
||
// Add a callback for when this config value changes | ||
void operator+=(std::function<void(const T&)>&& fx) { | ||
m_manager->AddCallback(m_key, [fx](const AnySharedPointer& val){ | ||
fx(*val.template as<T>().get()); | ||
}); | ||
t_OnChangedSignal::registration_t* operator+=(std::function<void(const T&)>&& fx) { | ||
return onChangedSignal += [fx](const AutoConfigVarBase& var){ | ||
fx(reinterpret_cast<const AutoConfigVar<T,TKey...>*>(&var)->m_value); | ||
}; | ||
} | ||
|
||
void operator-=(t_OnChangedSignal::registration_t* node) { onChangedSignal -= node; } | ||
|
||
private: | ||
T m_value; | ||
|
||
void RunValidation(const T& val) { | ||
if (RegistryEntry.m_hasValidator) { | ||
if (!RegistryEntry.validatorInternal()(val)) { | ||
throw autowiring_error("Validator rejected set for config value"); | ||
} | ||
} | ||
} | ||
|
||
void SetInternal(const T& val) { | ||
m_isConfigured = true; | ||
m_value = val; | ||
onChangedSignal(*this); | ||
} | ||
|
||
public: | ||
static std::shared_ptr<AutoConfigVarBase> Inject(const std::shared_ptr<CoreContext>& ctxt, const void* value) { | ||
if (!value) | ||
return ctxt->Inject<AutoConfigVar<T, TKey...>>(); | ||
else | ||
return ctxt->Inject<AutoConfigVar<T, TKey...>>(*reinterpret_cast<const T*>(value)); | ||
} | ||
|
||
static const ConfigRegistryEntryT<T, TKey...> RegistryEntry; | ||
}; | ||
|
||
template<class T, class... TKey> | ||
const ConfigRegistryEntryT<T, TKey...> AutoConfigVar<T, TKey...>::RegistryEntry(&AutoConfigVar<T, TKey...>::Inject); | ||
|
||
|
||
/// <summary> | ||
/// Register an attribute with the AutoConfig system. For example | ||
/// | ||
/// AutoConfig<int, struct MyNamespace, struct MyKey> m_myVal; | ||
/// defines the key "MyNamespace.MyKey" | ||
/// | ||
/// The Namespace field is optional, so | ||
/// AutoConfig<int, struct MyKey> m_myVal; | ||
/// defines the key "MyKey" | ||
/// | ||
/// AutoConfig values can also be set from the AutoConfigListing in the same context. The string key | ||
/// is used as the identifier for the value. | ||
/// </summary> | ||
template<class T, class... TKeys> | ||
class AutoConfig : public AutoRequired<AutoConfigVar<T, TKeys...>> { | ||
public: | ||
typedef AutoConfigVar<T, TKeys...> t_Var; | ||
|
||
using AutoRequired<t_Var>::operator*; | ||
|
||
AutoConfig(const std::shared_ptr<CoreContext>& ctxt = CoreContext::CurrentContext()) : | ||
AutoRequired<t_Var>(ctxt) | ||
{ | ||
} | ||
|
||
AutoConfig(T&& initialValue, const std::shared_ptr<CoreContext>& ctxt = CoreContext::CurrentContext()) : | ||
AutoRequired<t_Var>(ctxt, std::move(initialValue)) | ||
{ | ||
if (!(*this)->IsLocal()) { | ||
**this = std::move(initialValue); | ||
} | ||
} | ||
|
||
template<typename t_Arg, typename ...t_Args> | ||
explicit AutoConfig(t_Arg&& arg, t_Args&&... args) : | ||
AutoRequired<t_Var>(CoreContext::CurrentContext(), std::forward<t_Arg>(arg), std::forward<t_Args>(args)...) | ||
{ | ||
//If we wind up being a reference to an existing value, we may still want to set it... | ||
if (!(*this)->IsLocal()) { | ||
**this = T(std::forward<t_Arg>(arg), std::forward<t_Args>(args)...); | ||
} | ||
} | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. | ||
#pragma once | ||
#include "ContextMember.h" | ||
#include "auto_signal.h" | ||
|
||
#include <string> | ||
#include "C++11/cpp11.h" | ||
#include TYPE_INDEX_HEADER | ||
|
||
struct AnySharedPointer; | ||
|
||
/// \internal | ||
/// <summary> | ||
/// Utility base type & interface for configuration members | ||
/// </summary> | ||
class AutoConfigVarBase : public ContextMember | ||
{ | ||
public: | ||
AutoConfigVarBase(const std::type_info& tiName, bool configured = false); | ||
void AutoInit(); | ||
|
||
// Key used to identify this config value | ||
const std::string m_key; | ||
|
||
// True if this config was set at all | ||
bool IsConfigured() const { return m_isConfigured; } | ||
bool IsInherited() const { return m_parentRegistration != nullptr; } | ||
//True if the config was set from within this context (isn't inherited) | ||
bool IsLocal() const { return IsConfigured() && !IsInherited(); } | ||
|
||
typedef autowiring::signal<void(const AutoConfigVarBase& val)> t_OnChangedSignal; | ||
t_OnChangedSignal onChangedSignal; | ||
|
||
virtual void Get(void* pValue) const = 0; | ||
virtual void Set(const void* pValue) = 0; | ||
virtual void SetParsed(const std::string& value) = 0; | ||
|
||
protected: | ||
void OnSetLocally(); | ||
|
||
bool m_isConfigured; | ||
t_OnChangedSignal::registration_t* m_parentRegistration; | ||
}; |
Oops, something went wrong.