From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1Q9iLC-0007Ab-5v for garchives@archives.gentoo.org; Tue, 12 Apr 2011 18:29:30 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id D2C9A1C064; Tue, 12 Apr 2011 18:29:22 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id 758D31C063 for ; Tue, 12 Apr 2011 18:29:22 +0000 (UTC) Received: from pelican.gentoo.org (unknown [66.219.59.40]) (using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id DC3531B4109 for ; Tue, 12 Apr 2011 18:29:21 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by pelican.gentoo.org (Postfix) with ESMTP id 3789F80065 for ; Tue, 12 Apr 2011 18:29:21 +0000 (UTC) From: "Petteri Räty" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Petteri Räty" Message-ID: Subject: [gentoo-commits] proj/libbash:master commit in: src/core/, src/core/tests/ X-VCS-Repository: proj/libbash X-VCS-Files: src/core/interpreter.h src/core/symbols.hpp src/core/tests/interpreter_test.cpp src/core/tests/symbols_test.cpp X-VCS-Directories: src/core/ src/core/tests/ X-VCS-Committer: betelgeuse X-VCS-Committer-Name: Petteri Räty X-VCS-Revision: b37f97adcfaf9aea824aa5f1bacae4c326973434 Date: Tue, 12 Apr 2011 18:29:21 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: X-Archives-Hash: 48e7d82c8059fe48f376e81cac16c16a commit: b37f97adcfaf9aea824aa5f1bacae4c326973434 Author: Mu Qiao gentoo org> AuthorDate: Mon Apr 11 13:25:42 2011 +0000 Commit: Petteri R=C3=A4ty gentoo org> CommitDate: Tue Apr 12 07:22:36 2011 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/libbash.git;a= =3Dcommit;h=3Db37f97ad Implement array symbol Bash uses normal variables and arrays interchangeably. So we use an internal map no matter if it's an array or variable. --- src/core/interpreter.h | 12 ++++++--- src/core/symbols.hpp | 44 +++++++++++++++++++++++++++--= ----- src/core/tests/interpreter_test.cpp | 27 +++++++++++++++++++++ src/core/tests/symbols_test.cpp | 31 +++++++++++++++++++++++- 4 files changed, 100 insertions(+), 14 deletions(-) diff --git a/src/core/interpreter.h b/src/core/interpreter.h index 8fcab60..7155639 100644 --- a/src/core/interpreter.h +++ b/src/core/interpreter.h @@ -363,15 +363,16 @@ public: =20 /// \brief resolve any variable /// \param variable name + /// \param array index, use index=3D0 if it's not an array /// \return the value of the variable, call default constructor if // it's undefined template - T resolve(const std::string& name) + T resolve(const std::string& name, const unsigned index=3D0) { std::shared_ptr value =3D members.resolve(name); if(!value) return T(); - return value->get_value(); + return value->get_value(index); } =20 /// \brief check whether the value of the variable is null, return tru= e @@ -399,15 +400,18 @@ public: /// it's readonly, will define the variable if it doesn't exist /// \param variable name /// \param new value + /// \param array index, use index=3D0 if it's not an array /// \return the new value of the variable template - const T& set_value(const std::string& name, const T& new_value) + const T& set_value(const std::string& name, + const T& new_value, + const unsigned index=3D0) { std::shared_ptr value =3D members.resolve(name); if(!value) define(name, new_value, false); else - value->set_value(new_value); + value->set_value(new_value, index); return new_value; } =20 diff --git a/src/core/symbols.hpp b/src/core/symbols.hpp index 077065e..f645047 100644 --- a/src/core/symbols.hpp +++ b/src/core/symbols.hpp @@ -25,6 +25,7 @@ #ifndef LIBBASH_CORE_SYMBOLS_HPP_ #define LIBBASH_CORE_SYMBOLS_HPP_ =20 +#include #include #include #include @@ -115,8 +116,10 @@ class variable std::string name; =20 /// \var private::value - /// \brief actual value of the variable - boost::variant value; + /// \brief actual value of the variable. We put string in front of int + /// because we want "" as default string value; Otherwise we + /// will get "0". + std::map> value; =20 /// \var private::readonly /// \brief whether the variable is readonly @@ -136,30 +139,43 @@ public: =20 template variable(const std::string& name, - T v, + const T& v, bool ro=3Dfalse, bool is_null=3Dfalse) - : name(name), value(v), readonly(ro), null_value(is_null){} + : name(name), readonly(ro), null_value(is_null) + { + value[0] =3D v; + } =20 - /// \brief retrieve actual value of the variable + /// \brief retrieve actual value of the variable, if index is out of b= ound, + /// will return the default value of type T /// \return the value of the variable template - T get_value() const + T get_value(const unsigned index=3D0) const { static converter visitor; - return boost::apply_visitor(visitor, value); + + auto iter =3D value.find(index); + if(iter =3D=3D value.end()) + return T{}; + + return boost::apply_visitor(visitor, iter->second); } =20 /// \brief set the value of the variable, raise exception if it's read= only /// \param the new value to be set + /// \param array index, use index=3D0 if it's not an array /// \param whether to set the variable to null value, default is false template - void set_value(T new_value, bool is_null=3Dfalse) + void set_value(const T& new_value, + const unsigned index=3D0, + bool is_null=3Dfalse) { if(readonly) throw interpreter_exception(get_name() + " is readonly variable"); + null_value =3D is_null; - value =3D new_value; + value[index] =3D new_value; } =20 /// \brief check whether the value of the variable is null @@ -170,6 +186,16 @@ public: } }; =20 +// specialization for arrays +template <> +inline variable::variable<>(const std::string& name, + const std::map& v, + bool ro, + bool is_null) + : name(name), value(v.begin(), v.end()), readonly(ro), null_value(is= _null) +{ +} + /// /// class scope /// \brief implementation for symbol table diff --git a/src/core/tests/interpreter_test.cpp b/src/core/tests/interpr= eter_test.cpp index 6cc2df9..28f8d35 100644 --- a/src/core/tests/interpreter_test.cpp +++ b/src/core/tests/interpreter_test.cpp @@ -44,6 +44,17 @@ TEST(interpreter, define_resolve_string) EXPECT_STREQ("", walker.resolve("undefined").c_str()); } =20 +TEST(interpreter, define_resolve_array) +{ + interpreter walker; + std::map values =3D {{0, "1"}, {1, "2"}, {2, "3"}}; + walker.define("array", values); + EXPECT_STREQ("1", walker.resolve("array", 0).c_str()); + EXPECT_STREQ("2", walker.resolve("array", 1).c_str()); + EXPECT_STREQ("3", walker.resolve("array", 2).c_str()); + EXPECT_STREQ("", walker.resolve("undefined",100).c_str()); +} + TEST(interpreter, is_unset_or_null) { interpreter walker; @@ -91,6 +102,22 @@ TEST(interpreter, set_string_value) EXPECT_STREQ("hi", walker.resolve("astring_ro").c_str()); } =20 +TEST(interpreter, set_array_value) +{ + interpreter walker; + std::map values =3D {{0, "1"}, {1, "2"}, {2, "3"}}; + walker.define("array", values); + EXPECT_STREQ("2", walker.set_value("array", "2", 0).c_str()); + EXPECT_STREQ("2", walker.resolve("array", 0).c_str()); + EXPECT_STREQ("out_of_bound", walker.set_value("array", "out_of= _bound", 10).c_str()); + EXPECT_STREQ("out_of_bound", walker.resolve("array",10).c_str(= )); + + walker.define("ro_array", values, true); + EXPECT_THROW(walker.set_value("ro_array", "hello", 1), + interpreter_exception); + EXPECT_STREQ("2", walker.resolve("ro_array", 1).c_str()); +} + TEST(interperter, substring_expansion_exception) { interpreter walker; diff --git a/src/core/tests/symbols_test.cpp b/src/core/tests/symbols_tes= t.cpp index 73a6a9c..2b7a65e 100644 --- a/src/core/tests/symbols_test.cpp +++ b/src/core/tests/symbols_test.cpp @@ -65,11 +65,40 @@ TEST(symbol_test, string_variable) EXPECT_EQ(123, int_string.get_value()); } =20 +TEST(symbol_test, array_variable) +{ + map values =3D {{0, "1"}, {1, "2"}, {2, "3"}}; + + // readonly array + variable ro_array("foo", values, true); + EXPECT_STREQ("foo", ro_array.get_name().c_str()); + EXPECT_STREQ("1", ro_array.get_value(0).c_str()); + EXPECT_STREQ("2", ro_array.get_value(1).c_str()); + EXPECT_STREQ("3", ro_array.get_value(2).c_str()); + EXPECT_THROW(ro_array.set_value("4", 0), interpreter_exception); + EXPECT_STREQ("1", ro_array.get_value(0).c_str()); + + // out of bound + EXPECT_STREQ("", ro_array.get_value(100).c_str()); + + // normal array + variable normal_array("foo", values); + normal_array.set_value("5", 4); + EXPECT_STREQ("1", normal_array.get_value(0).c_str()); + EXPECT_STREQ("2", normal_array.get_value(1).c_str()); + EXPECT_STREQ("3", normal_array.get_value(2).c_str()); + EXPECT_STREQ("", normal_array.get_value(3).c_str()); + EXPECT_STREQ("5", normal_array.get_value(4).c_str()); + + // get integer value + EXPECT_EQ(3, normal_array.get_value(2)); +} + TEST(symbol_test, is_null) { variable var("foo", 10); EXPECT_FALSE(var.is_null()); - var.set_value("bar", true); + var.set_value("bar", 0, true); EXPECT_TRUE(var.is_null()); EXPECT_TRUE(variable("foo", "", false, true).is_null()); }