diff --git a/src/lib/format-obj.cpp b/src/lib/format-obj.cpp index 4c40c3069..7c8d79a8a 100644 --- a/src/lib/format-obj.cpp +++ b/src/lib/format-obj.cpp @@ -42,6 +42,7 @@ #include "lib/error.hpp" #include "lib/format-obj.hpp" +#include "lib/ios-savepoint.hpp" //#include "lib/format-string.hpp" #include "lib/unique-malloc-owner.hpp" #include "lib/symbol.hpp" @@ -375,6 +376,7 @@ namespace util { ostream& showAddr (ostream& stream, void const* addr) { + IosSavepoint save{stream}; size_t suffix_modulus = size_t(1) << DIAGNOSTICS_ADDRESS_SUFFIX_LEN * 8; return stream << "╲" << hex diff --git a/src/lib/ios-savepoint.hpp b/src/lib/ios-savepoint.hpp new file mode 100644 index 000000000..14e334def --- /dev/null +++ b/src/lib/ios-savepoint.hpp @@ -0,0 +1,82 @@ +/* + IOS-SAVEPOINT.hpp - capture and restore std::ostream format settings + + Copyright (C) Lumiera.org + 2022, Hermann Vosseler + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file ios-savepoint.hpp + ** Capture previous settings of an `std::ostream` and restore them when leaving scope. + ** The stream manipulators of the IOS-Framework from the C++ standard lib allow to adjust + ** various aspects of output formatting for following data fed to the output stream. + ** Unfortunately many of these settings are _sticky_ and thus may "taint" common + ** output streams like `std::cout`. By planting this RAII capsule into a local scope, + ** the internal settings of an output stream can be recorded and restored automatically, + ** once control flow leaves the scope. + ** @remark based on this [stackoverflow] by «[qbert220]», 2013 + ** + ** @see IosSavepoint_test + ** + ** [qbert220]: https://stackoverflow.com/users/617617/qbert220 + ** [stackoverflow]: https://stackoverflow.com/a/18822888 "Restore state of `std::cout` after manipulating it" + ** + ** + */ + + +#ifndef LIB_IOS_SAVEPOINT_H +#define LIB_IOS_SAVEPOINT_H + +#include "lib/nocopy.hpp" + +#include + + + +namespace util { + + /** + * RAII helper to capture and restore + * output stream format settings. + */ + class IosSavepoint + : MoveOnly + { + std::ostream& theStream_; + std::ios_base::fmtflags prevFlags_; + char fillChar_; + + public: + explicit + IosSavepoint(std::ostream& stream_to_capture) + : theStream_{stream_to_capture} + , prevFlags_{theStream_.flags()} + , fillChar_{theStream_.fill()} + { } + + ~IosSavepoint() + { + theStream_.flags(prevFlags_); + theStream_.fill(fillChar_); + } + }; + + +} // namespace util +#endif /*LIB_IOS_SAVEPOINT_H*/ diff --git a/src/lib/meta/function.hpp b/src/lib/meta/function.hpp index 5ac064e8d..548269b66 100644 --- a/src/lib/meta/function.hpp +++ b/src/lib/meta/function.hpp @@ -85,7 +85,7 @@ namespace meta{ * The following explicit specialisations handle the other cases, which are * not objects, but primitive types (function (member) pointers and references). * @remarks The key trick of this solution is to rely on `decltype` of `operator()` - * and was proposed 10/2011 by user "[kennytm]" in this [stackoverflow]. + * and was proposed 10/2011 by user «[kennytm]» in this [stackoverflow]. * @note for a member pointer to function, only the actual arguments in the * function signature are reflected. But if you bind such a member * pointer into a `std::function`, an additional first parameter @@ -102,7 +102,7 @@ namespace meta{ * @see FunctionSignature_test * * [kennytm]: http://stackoverflow.com/users/224671/kennytm - * [stackoverflow] : http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765 "answer on stackoverflow" + * [stackoverflow]: http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765 "figure out parameter and return type of a Lambda" */ template struct _Fun diff --git a/src/stage/ui-bus.hpp b/src/stage/ui-bus.hpp index dda3fa750..102ec2ab3 100644 --- a/src/stage/ui-bus.hpp +++ b/src/stage/ui-bus.hpp @@ -38,7 +38,7 @@ ** ** # Rationale ** The UI-Bus acts as a **mediating backbone**, impersonating the role - ** of the _Model_ and the _Controller_ in the [MVC-Pattern]in common UI architecture. + ** of the _Model_ and the _Controller_ in the [MVC-Pattern] in common UI architecture. ** ** The MVC-Pattern as such is fine, and probably the best we know for construction of ** user interfaces. But it doesn't scale well towards the integration into a larger and @@ -66,9 +66,9 @@ ** directed towards individual elements. The interactions at the bus are closely interrelated ** with the [elementary UI-Element operations](\ref tangible.hpp). ** - ** - *act*: send a [GenNode] representing the action + ** - *act*: send a \ref GenNode representing the action ** - the ID is either a globally registered command-ID or an explicitly - ** ["opened"](\ref steam::control::SessionCommand::cycle(Symbol,string)) command instance ID. + ** [opened](\ref steam::control::SessionCommand::cycle(Symbol,string const&)) command instance ID. ** - the payload is a Record holding the actual command arguments ** - on reception, an _instance_ (anonymous clone copy) of the command is created, bound ** with the arguments and handed over to the SteamDispatcher to be enqueued for execution. diff --git a/tests/15library.tests b/tests/15library.tests index e5a926d9e..e847ae880 100644 --- a/tests/15library.tests +++ b/tests/15library.tests @@ -424,6 +424,21 @@ return: 0 END +TEST "IOS restore format" IosSavepoint_test < + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + +/** @file ios-savepoint-test.cpp + ** unit test \ref IosSavepoint_test + */ + + +#include "lib/test/run.hpp" +#include "lib/format-cout.hpp" +#include "lib/ios-savepoint.hpp" + +#include + + +using std::string; + + +namespace util { +namespace test { + + + + + /***************************************************************************//** + * @test verifies capturing and restoring of std::ostream formatting state. + * @see ios-savepoint.hpp + */ + class IosSavepoint_test + : public Test + { + void + run (Arg) + { + switchToHex(); + __verifySane(); + + setFill(); + __verifySane(); + + nested(); + __verifySane(); + + try { + restoreAfterException(); + } catch(...){ + cout << "Tilt" < float + { throw 42; }; + + IosSavepoint save{cout}; + cout << std::hexfloat + << 1234 + << endl + << boom() + << endl; + } + }; + + LAUNCHER (IosSavepoint_test, "unit common"); + + +}} // namespace util::test + diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 78d16a33e..9693ca3d5 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -18862,8 +18862,30 @@ - + + + + + + + +

+ Die meisten IOS-Stream-Manipulatoren sind »sticky«, d.h. sie verändern per Seiteneffekt den Zustand im jeweiligen ostream. Ich hatte eine Methode zum Ausgeben einer Addresse, eingebaut im to-String-Framework, und diese hat std::output auf Hex-Ausgabe umgeschaltet. Erstaunlich daß ich das jahrelang nicht gemerkt habe! +

+ +
+ +
+ + + + + + + + +