esphome/esphome/core/optional.h
Otto Winter 6682c43dfa
🏗 Merge C++ into python codebase (#504)
## Description:

Move esphome-core codebase into esphome (and a bunch of other refactors). See https://github.com/esphome/feature-requests/issues/97

Yes this is a shit ton of work and no there's no way to automate it :( But it will be worth it 👍

Progress:
- Core support (file copy etc): 80%
- Base Abstractions (light, switch): ~50%
- Integrations: ~10%
- Working? Yes, (but only with ported components).

Other refactors:
- Moves all codegen related stuff into a single class: `esphome.codegen` (imported as `cg`)
- Rework coroutine syntax
- Move from `component/platform.py` to `domain/component.py` structure as with HA
- Move all defaults out of C++ and into config validation.
- Remove `make_...` helpers from Application class. Reason: Merge conflicts with every single new integration.
- Pointer Variables are stored globally instead of locally in setup(). Reason: stack size limit.

Future work:
- Rework const.py - Move all `CONF_...` into a conf class (usage `conf.UPDATE_INTERVAL` vs `CONF_UPDATE_INTERVAL`). Reason: Less convoluted import block
- Enable loading from `custom_components` folder.

**Related issue (if applicable):** https://github.com/esphome/feature-requests/issues/97

**Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here>

## Checklist:
  - [ ] The code change is tested and works locally.
  - [ ] Tests have been added to verify that the new code works (under `tests/` folder).

If user exposed functionality or configuration variables are added/changed:
  - [ ] Documentation added/updated in [esphomedocs](https://github.com/OttoWinter/esphomedocs).
2019-04-17 12:06:00 +02:00

214 lines
6.6 KiB
C++

#pragma once
//
// Copyright (c) 2017 Martin Moene
//
// https://github.com/martinmoene/optional-bare
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Modified by Otto Winter on 18.05.18
namespace esphome {
// type for nullopt
struct nullopt_t { // NOLINT
struct init {}; // NOLINT
nullopt_t(init) {}
};
// extra parenthesis to prevent the most vexing parse:
const nullopt_t nullopt((nullopt_t::init())); // NOLINT
// Simplistic optional: requires T to be default constructible, copyable.
template<typename T> class optional { // NOLINT
private:
using safe_bool = void (optional::*)() const;
public:
using value_type = T;
optional() {}
optional(nullopt_t) {}
optional(T const &arg) : has_value_(true), value_(arg) {}
template<class U> optional(optional<U> const &other) : has_value_(other.has_value()), value_(other.value()) {}
optional &operator=(nullopt_t) {
reset();
return *this;
}
template<class U> optional &operator=(optional<U> const &other) {
has_value_ = other.has_value();
value_ = other.value();
return *this;
}
void swap(optional &rhs) {
using std::swap;
if (has_value() && rhs.has_value()) {
swap(**this, *rhs);
} else if (!has_value() && rhs.has_value()) {
initialize(*rhs);
rhs.reset();
} else if (has_value() && !rhs.has_value()) {
rhs.initialize(**this);
reset();
}
}
// observers
value_type const *operator->() const { return &value_; }
value_type *operator->() { return &value_; }
value_type const &operator*() const { return value_; }
value_type &operator*() { return value_; }
operator safe_bool() const { return has_value() ? &optional::this_type_does_not_support_comparisons : nullptr; }
bool has_value() const { return has_value_; }
value_type const &value() const { return value_; }
value_type &value() { return value_; }
template<class U> value_type value_or(U const &v) const { return has_value() ? value() : static_cast<value_type>(v); }
// modifiers
void reset() { has_value_ = false; }
private:
void this_type_does_not_support_comparisons() const {} // NOLINT
template<typename V> void initialize(V const &value) { // NOLINT
value_ = value;
has_value_ = true;
}
private:
bool has_value_{false}; // NOLINT
value_type value_; // NOLINT
};
// Relational operators
template<typename T, typename U> inline bool operator==(optional<T> const &x, optional<U> const &y) {
return bool(x) != bool(y) ? false : !bool(x) ? true : *x == *y;
}
template<typename T, typename U> inline bool operator!=(optional<T> const &x, optional<U> const &y) {
return !(x == y);
}
template<typename T, typename U> inline bool operator<(optional<T> const &x, optional<U> const &y) {
return (!y) ? false : (!x) ? true : *x < *y;
}
template<typename T, typename U> inline bool operator>(optional<T> const &x, optional<U> const &y) { return (y < x); }
template<typename T, typename U> inline bool operator<=(optional<T> const &x, optional<U> const &y) { return !(y < x); }
template<typename T, typename U> inline bool operator>=(optional<T> const &x, optional<U> const &y) { return !(x < y); }
// Comparison with nullopt
template<typename T> inline bool operator==(optional<T> const &x, nullopt_t) { return (!x); }
template<typename T> inline bool operator==(nullopt_t, optional<T> const &x) { return (!x); }
template<typename T> inline bool operator!=(optional<T> const &x, nullopt_t) { return bool(x); }
template<typename T> inline bool operator!=(nullopt_t, optional<T> const &x) { return bool(x); }
template<typename T> inline bool operator<(optional<T> const &, nullopt_t) { return false; }
template<typename T> inline bool operator<(nullopt_t, optional<T> const &x) { return bool(x); }
template<typename T> inline bool operator<=(optional<T> const &x, nullopt_t) { return (!x); }
template<typename T> inline bool operator<=(nullopt_t, optional<T> const &) { return true; }
template<typename T> inline bool operator>(optional<T> const &x, nullopt_t) { return bool(x); }
template<typename T> inline bool operator>(nullopt_t, optional<T> const &) { return false; }
template<typename T> inline bool operator>=(optional<T> const &, nullopt_t) { return true; }
template<typename T> inline bool operator>=(nullopt_t, optional<T> const &x) { return (!x); }
// Comparison with T
template<typename T, typename U> inline bool operator==(optional<T> const &x, U const &v) {
return bool(x) ? *x == v : false;
}
template<typename T, typename U> inline bool operator==(U const &v, optional<T> const &x) {
return bool(x) ? v == *x : false;
}
template<typename T, typename U> inline bool operator!=(optional<T> const &x, U const &v) {
return bool(x) ? *x != v : true;
}
template<typename T, typename U> inline bool operator!=(U const &v, optional<T> const &x) {
return bool(x) ? v != *x : true;
}
template<typename T, typename U> inline bool operator<(optional<T> const &x, U const &v) {
return bool(x) ? *x < v : true;
}
template<typename T, typename U> inline bool operator<(U const &v, optional<T> const &x) {
return bool(x) ? v < *x : false;
}
template<typename T, typename U> inline bool operator<=(optional<T> const &x, U const &v) {
return bool(x) ? *x <= v : true;
}
template<typename T, typename U> inline bool operator<=(U const &v, optional<T> const &x) {
return bool(x) ? v <= *x : false;
}
template<typename T, typename U> inline bool operator>(optional<T> const &x, U const &v) {
return bool(x) ? *x > v : false;
}
template<typename T, typename U> inline bool operator>(U const &v, optional<T> const &x) {
return bool(x) ? v > *x : true;
}
template<typename T, typename U> inline bool operator>=(optional<T> const &x, U const &v) {
return bool(x) ? *x >= v : false;
}
template<typename T, typename U> inline bool operator>=(U const &v, optional<T> const &x) {
return bool(x) ? v >= *x : true;
}
// Specialized algorithms
template<typename T> void swap(optional<T> &x, optional<T> &y) { x.swap(y); }
// Convenience function to create an optional.
template<typename T> inline optional<T> make_optional(T const &v) { return optional<T>(v); }
} // namespace esphome