diff options
Diffstat (limited to 'src/compat')
-rw-r--r-- | src/compat/attr.hpp | 28 | ||||
-rw-r--r-- | src/compat/attr_test.cpp | 50 | ||||
-rw-r--r-- | src/compat/option.hpp | 9 | ||||
-rw-r--r-- | src/compat/option_test.cpp | 4 |
4 files changed, 82 insertions, 9 deletions
diff --git a/src/compat/attr.hpp b/src/compat/attr.hpp index 5322a14..9ddf654 100644 --- a/src/compat/attr.hpp +++ b/src/compat/attr.hpp @@ -1,7 +1,7 @@ #pragma once // attr.hpp - Attributes. // -// Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> +// Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com> // // This file is part of The Mana World (Athena server) // @@ -31,7 +31,27 @@ namespace tmwa #define JOIN(a, b) a##b -#define WITH_VAR(ty, var, expr) \ - for (bool JOIN(var, _guard) = true; JOIN(var, _guard); ) \ - for (ty var = expr; JOIN(var, _guard); JOIN(var, _guard) = false) +// first loop: +// declare flag 'guard' (initially true) +// declare flag 'broken' (initially false) +// condition is 'guard' must be true, which is the case only for the first iteration +// post checks 'broken' and if set, break the loop +// second loop: +// declare public 'var' variable +// condition is that 'guard' must be true +// post sets 'guard' to false to make this loop run only once +// third loop: +// enable broken flag; it will remain set if 'break' is in the loop +// condition is that 'broken' must be true +// post sets 'broken' to false, which then fails the condition +// if user has a 'break' inside, then 'broken' will be true +// in either case, go back to the second loop's post +#define WITH_VAR_INLOOP(ty, var, expr) \ + for (bool JOIN(var, _guard) = true, JOIN(var, _broken) = false; JOIN(var, _guard); ({if (JOIN(var, _broken)) { break; } })) \ + for (ty var = expr; JOIN(var, _guard); JOIN(var, _guard) = false) \ + for (JOIN(var, _broken) = true; JOIN(var, _broken); JOIN(var, _broken) = false) +#define WITH_VAR_NOLOOP(ty, var, expr) \ + for (bool JOIN(var, _guard) = true, JOIN(var, _broken) = false; JOIN(var, _guard); ({if (JOIN(var, _broken)) {abort();} })) \ + for (ty var = expr; JOIN(var, _guard); JOIN(var, _guard) = false) \ + for (JOIN(var, _broken) = true; JOIN(var, _broken); JOIN(var, _broken) = false) } // namespace tmwa diff --git a/src/compat/attr_test.cpp b/src/compat/attr_test.cpp new file mode 100644 index 0000000..eb9042d --- /dev/null +++ b/src/compat/attr_test.cpp @@ -0,0 +1,50 @@ +#include "attr.hpp" +// attr_test.cpp - Tests for attributes +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// 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 3 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, see <http://www.gnu.org/licenses/>. + +#include <gtest/gtest.h> + +#include "../poison.hpp" + + +namespace tmwa +{ +TEST(attr, withvar) +{ + int x = 41; + for (int i = 0; i < 2; ++i) + { + WITH_VAR_NOLOOP(auto, y, x + 1) + { + x = y; + } + } + EXPECT_EQ(x, 43); + for (int i = 0; i < 2; ++i) + { + if (i == 1) + WITH_VAR_INLOOP(auto, y, i) + { + x = y; + break; + } + } + EXPECT_EQ(x, 1); +} +} // namespace tmwa diff --git a/src/compat/option.hpp b/src/compat/option.hpp index 1976589..7beef6f 100644 --- a/src/compat/option.hpp +++ b/src/compat/option.hpp @@ -424,9 +424,12 @@ namespace option tmwa::option::option_unwrap(std::move(o)); \ }).maybe_ref_fun() // immediately preceded by 'if'; not double-eval-safe -#define OPTION_IS_SOME(var, expr) \ - ((expr).is_some()) \ - WITH_VAR(auto&, var, *(expr).ptr_or(nullptr)) +#define OPTION_IS_SOME_INLOOP(var, expr) \ + ((expr).is_some()) \ + WITH_VAR_INLOOP(auto&, var, *(expr).ptr_or(nullptr)) +#define OPTION_IS_SOME_NOLOOP(var, expr) \ + ((expr).is_some()) \ + WITH_VAR_NOLOOP(auto&, var, *(expr).ptr_or(nullptr)) } // namespace option //using option::Option; diff --git a/src/compat/option_test.cpp b/src/compat/option_test.cpp index ac95424..f9cec0e 100644 --- a/src/compat/option_test.cpp +++ b/src/compat/option_test.cpp @@ -398,7 +398,7 @@ TEST(Option, unwrap) v = None; TRY_UNWRAP(fcr(), v = Some(1)); v = None; - if OPTION_IS_SOME(o, v) + if OPTION_IS_SOME_NOLOOP(o, v) { EXPECT_NE(o, o); } @@ -408,7 +408,7 @@ TEST(Option, unwrap) } v = Some(1); - if OPTION_IS_SOME(o, v) + if OPTION_IS_SOME_NOLOOP(o, v) { EXPECT_EQ(o, 1); } |