From patchwork Mon Aug 13 10:50:17 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: alexandros.frantzis@linaro.org X-Patchwork-Id: 10697 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 876EF23E29 for ; Mon, 13 Aug 2012 10:50:21 +0000 (UTC) Received: from mail-gh0-f180.google.com (mail-gh0-f180.google.com [209.85.160.180]) by fiordland.canonical.com (Postfix) with ESMTP id 2C34AA184EC for ; Mon, 13 Aug 2012 10:50:21 +0000 (UTC) Received: by ghbg10 with SMTP id g10so2822857ghb.11 for ; Mon, 13 Aug 2012 03:50:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf :content-type:mime-version:x-launchpad-project:x-launchpad-branch :x-launchpad-message-rationale:x-launchpad-branch-revision-number :x-launchpad-notification-type:to:from:subject:message-id:date :reply-to:sender:errors-to:precedence:x-generated-by :x-launchpad-hash:x-gm-message-state; bh=YmswJ/fuFzQqhbL36Wq28jGG+bg8uzexOGmPM9DVjF0=; b=DTATpFjUBMQJjX5jwqEIXGKtIWRvgZ4FFIyBEZ7RO4hz6Wfto8iMlYXYf0oC/IrxOa IXUAOnHXSAK150QzIAKD5T7Okb4sXtTc/k678SKdiPAqr5Ig22D/l9SKl4WskLoOEswx w9+p95qH9Od1ZsSf0BsZQMtA5hFdgWHIzs2sldWxu5iV8THpPN9tqfVu0qQtb/GnE0tr P9goidOK6/3JhyCa2c8DSIyjpW8Q3H58qxy6CeQipkdobDPvvWfmJC0JHxQC2zf2QzpX FW32d9GCeRKfPGTZPoyEx9mMqh8qbT20LjR87Z81OgUO/32fkPNbw+pykEweZ16cX2aD stww== Received: by 10.50.170.3 with SMTP id ai3mr4815568igc.9.1344855020491; Mon, 13 Aug 2012 03:50:20 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.184.200 with SMTP id ew8csp171038igc; Mon, 13 Aug 2012 03:50:18 -0700 (PDT) Received: by 10.180.84.1 with SMTP id u1mr17496095wiy.15.1344855018034; Mon, 13 Aug 2012 03:50:18 -0700 (PDT) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id p10si16983179wiv.21.2012.08.13.03.50.17 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 13 Aug 2012 03:50:18 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1T0sDx-0005WU-BN for ; Mon, 13 Aug 2012 10:50:17 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 0F222E03E6 for ; Mon, 13 Aug 2012 10:50:17 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: glmark2 X-Launchpad-Branch: ~glmark2-dev/glmark2/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 244 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 244: libmatrix: Sync with lp:libmatrix revision 41. Message-Id: <20120813105017.1482.80648.launchpad@ackee.canonical.com> Date: Mon, 13 Aug 2012 10:50:17 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="15791"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: 5d18067dbaccf9e1984f7bc61d3944671d060870 X-Gm-Message-State: ALoCoQlHwHj1yc72YE+WUvvObSEswcz+4IPKPrj0s4onwCTfh8yQr9r0hcaesMJEGPDbwy8rrMaW ------------------------------------------------------------ revno: 244 committer: Alexandros Frantzis branch nick: trunk timestamp: Mon 2012-08-13 13:09:08 +0300 message: libmatrix: Sync with lp:libmatrix revision 41. Update Util::split() invocations in glmark2 to use the new interface. added: src/libmatrix/test/util_split_test.cc src/libmatrix/test/util_split_test.h modified: src/android.cpp src/benchmark.cpp src/gl-visual-config.cpp src/libmatrix/Makefile src/libmatrix/shader-source.cc src/libmatrix/test/libmatrix_test.cc src/libmatrix/util.cc src/libmatrix/util.h src/main-loop.cpp src/options.cpp src/scene-effect-2d.cpp src/scene.cpp --- lp:glmark2 https://code.launchpad.net/~glmark2-dev/glmark2/trunk You are subscribed to branch lp:glmark2. To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription === modified file 'src/android.cpp' --- src/android.cpp 2012-07-30 12:28:16 +0000 +++ src/android.cpp 2012-08-13 10:09:08 +0000 @@ -101,7 +101,7 @@ std::string line; while (getline(ifs, line)) { if (!line.empty()) - Util::split(line, ' ', arguments); + Util::split(line, ' ', arguments, Util::SplitModeQuoted); } } @@ -118,7 +118,7 @@ get_args_from_string(const std::string &args_str, int &argc, char **&argv) { std::vector arguments; - Util::split(args_str, ' ', arguments); + Util::split(args_str, ' ', arguments, Util::SplitModeQuoted); arg_vector_to_argv(arguments, argc, argv); } === modified file 'src/benchmark.cpp' --- src/benchmark.cpp 2012-07-17 09:29:41 +0000 +++ src/benchmark.cpp 2012-08-13 10:09:08 +0000 @@ -35,7 +35,7 @@ { vector elems; - Util::split(s, ':', elems); + Util::split(s, ':', elems, Util::SplitModeNormal); const string &name = !elems.empty() ? elems[0] : ""; @@ -48,7 +48,7 @@ vector options; vector elems; - Util::split(s, ':', elems); + Util::split(s, ':', elems, Util::SplitModeNormal); for (vector::const_iterator iter = elems.begin() + 1; iter != elems.end(); @@ -56,7 +56,7 @@ { vector opt; - Util::split(*iter, '=', opt); + Util::split(*iter, '=', opt, Util::SplitModeNormal); if (opt.size() == 2) options.push_back(Benchmark::OptionPair(opt[0], opt[1])); else === modified file 'src/gl-visual-config.cpp' --- src/gl-visual-config.cpp 2012-05-11 13:49:53 +0000 +++ src/gl-visual-config.cpp 2012-08-13 10:09:08 +0000 @@ -30,7 +30,7 @@ { std::vector elems; - Util::split(s, ':', elems); + Util::split(s, ':', elems, Util::SplitModeNormal); for (std::vector::const_iterator iter = elems.begin(); iter != elems.end(); @@ -38,7 +38,7 @@ { std::vector opt; - Util::split(*iter, '=', opt); + Util::split(*iter, '=', opt, Util::SplitModeNormal); if (opt.size() == 2) { if (opt[0] == "r" || opt[0] == "red") red = Util::fromString(opt[1]); === modified file 'src/libmatrix/Makefile' --- src/libmatrix/Makefile 2012-05-22 09:43:45 +0000 +++ src/libmatrix/Makefile 2012-08-13 10:09:08 +0000 @@ -9,6 +9,7 @@ $(TESTDIR)/inverse_test.cc \ $(TESTDIR)/transpose_test.cc \ $(TESTDIR)/shader_source_test.cc \ + $(TESTDIR)/util_split_test.cc \ $(TESTDIR)/libmatrix_test.cc TESTOBJS = $(TESTSRCS:.cc=.o) @@ -32,6 +33,7 @@ $(TESTDIR)/inverse_test.o: $(TESTDIR)/inverse_test.cc $(TESTDIR)/inverse_test.h $(TESTDIR)/libmatrix_test.h mat.h $(TESTDIR)/transpose_test.o: $(TESTDIR)/transpose_test.cc $(TESTDIR)/transpose_test.h $(TESTDIR)/libmatrix_test.h mat.h $(TESTDIR)/shader_source_test.o: $(TESTDIR)/shader_source_test.cc $(TESTDIR)/shader_source_test.h $(TESTDIR)/libmatrix_test.h shader-source.h +$(TESTDIR)/util_split_test.o: $(TESTDIR)/util_split_test.cc $(TESTDIR)/util_split_test.h $(TESTDIR)/libmatrix_test.h util.h $(TESTDIR)/libmatrix_test: $(TESTOBJS) libmatrix.a $(CXX) -o $@ $^ run_tests: $(LIBMATRIX_TESTS) === modified file 'src/libmatrix/shader-source.cc' --- src/libmatrix/shader-source.cc 2012-01-26 17:00:43 +0000 +++ src/libmatrix/shader-source.cc 2012-08-13 10:09:08 +0000 @@ -589,7 +589,7 @@ { std::vector elems; - Util::split(precision_values, ',', elems); + Util::split(precision_values, ',', elems, Util::SplitModeNormal); for (size_t i = 0; i < elems.size() && i < 4; i++) { const std::string& pstr(elems[i]); === modified file 'src/libmatrix/test/libmatrix_test.cc' --- src/libmatrix/test/libmatrix_test.cc 2012-01-26 17:00:43 +0000 +++ src/libmatrix/test/libmatrix_test.cc 2012-08-13 10:09:08 +0000 @@ -8,6 +8,7 @@ // // Contributors: // Jesse Barker - original implementation. +// Alexandros Frantzis - Util::split tests // #include #include @@ -17,6 +18,7 @@ #include "transpose_test.h" #include "const_vec_test.h" #include "shader_source_test.h" +#include "util_split_test.h" using std::cerr; using std::cout; @@ -42,6 +44,8 @@ testVec.push_back(new MatrixTest3x3Transpose()); testVec.push_back(new MatrixTest4x4Transpose()); testVec.push_back(new ShaderSourceBasic()); + testVec.push_back(new UtilSplitTestNormal()); + testVec.push_back(new UtilSplitTestQuoted()); for (vector::iterator testIt = testVec.begin(); testIt != testVec.end(); === added file 'src/libmatrix/test/util_split_test.cc' --- src/libmatrix/test/util_split_test.cc 1970-01-01 00:00:00 +0000 +++ src/libmatrix/test/util_split_test.cc 2012-08-13 10:09:08 +0000 @@ -0,0 +1,180 @@ +// +// Copyright (c) 2012 Linaro Limited +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the MIT License which accompanies +// this distribution, and is available at +// http://www.opensource.org/licenses/mit-license.php +// +// Contributors: +// Alexandros Frantzis - original implementation. +// +#include +#include +#include +#include "libmatrix_test.h" +#include "util_split_test.h" +#include "../util.h" + +using std::cout; +using std::endl; +using std::string; +using std::vector; + +template static bool +areVectorsEqual(vector& vec1, vector& vec2) +{ + if (vec1.size() != vec2.size()) + return false; + + for (unsigned int i = 0; i < vec1.size(); i++) + { + if (vec1[i] != vec2[i]) + return false; + } + + return true; +} + +template static void +printVector(vector& vec) +{ + cout << "["; + for (unsigned int i = 0; i < vec.size(); i++) + { + cout << '"' << vec[i] << '"'; + if (i < vec.size() - 1) + cout << ", "; + } + cout << "]"; +} + +void +UtilSplitTestNormal::run(const Options& options) +{ + const string test1("abc def ghi"); + const string test2(" abc: def :ghi "); + vector expected1; + vector expected2; + vector results; + + expected1.push_back("abc"); + expected1.push_back("def"); + expected1.push_back("ghi"); + + expected2.push_back(" abc"); + expected2.push_back(" def "); + expected2.push_back("ghi "); + + if (options.beVerbose()) + { + cout << "Testing string \"" << test1 << "\"" << endl; + } + + Util::split(test1, ' ', results, Util::SplitModeNormal); + + if (options.beVerbose()) + { + cout << "Split result: "; + printVector(results); + cout << endl << "Expected: "; + printVector(expected1); + cout << endl; + } + + if (!areVectorsEqual(results, expected1)) + { + return; + } + + results.clear(); + + if (options.beVerbose()) + { + cout << "Testing string \"" << test2 << "\"" << endl; + } + + Util::split(test2, ':', results, Util::SplitModeNormal); + + if (options.beVerbose()) + { + cout << "Split result: "; + printVector(results); + cout << endl << "Expected: "; + printVector(expected2); + cout << endl; + } + + if (!areVectorsEqual(results, expected2)) + { + return; + } + + pass_ = true; +} + +void +UtilSplitTestQuoted::run(const Options& options) +{ + const string test1("abc \"def' ghi\" klm\\ nop -b qr:title='123 \"456'"); + const string test2("abc: def='1:2:3:'ghi : \":jk\""); + vector expected1; + vector expected2; + vector results; + + expected1.push_back("abc"); + expected1.push_back("def' ghi"); + expected1.push_back("klm nop"); + expected1.push_back("-b"); + expected1.push_back("qr:title=123 \"456"); + + expected2.push_back("abc"); + expected2.push_back(" def=1:2:3:ghi "); + expected2.push_back(" :jk"); + + if (options.beVerbose()) + { + cout << "Testing string \"" << test1 << "\"" << endl; + } + + Util::split(test1, ' ', results, Util::SplitModeQuoted); + + if (options.beVerbose()) + { + cout << "Split result: "; + printVector(results); + cout << endl << "Expected: "; + printVector(expected1); + cout << endl; + } + + if (!areVectorsEqual(results, expected1)) + { + return; + } + + results.clear(); + + if (options.beVerbose()) + { + cout << "Testing string \"" << test2 << "\"" << endl; + } + + Util::split(test2, ':', results, Util::SplitModeQuoted); + + if (options.beVerbose()) + { + cout << "Split result: "; + printVector(results); + cout << endl << "Expected: "; + printVector(expected2); + cout << endl; + } + + if (!areVectorsEqual(results, expected2)) + { + return; + } + + pass_ = true; +} === added file 'src/libmatrix/test/util_split_test.h' --- src/libmatrix/test/util_split_test.h 1970-01-01 00:00:00 +0000 +++ src/libmatrix/test/util_split_test.h 2012-08-13 10:09:08 +0000 @@ -0,0 +1,31 @@ +// +// Copyright (c) 2012 Linaro Limited +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the MIT License which accompanies +// this distribution, and is available at +// http://www.opensource.org/licenses/mit-license.php +// +// Contributors: +// Alexandros Frantzis - original implementation. +// +#ifndef UTIL_SPLIT_TEST_H_ +#define UTIL_SPLIT_TEST_H_ + +class MatrixTest; +class Options; + +class UtilSplitTestNormal : public MatrixTest +{ +public: + UtilSplitTestNormal() : MatrixTest("Util::split::normal") {} + virtual void run(const Options& options); +}; + +class UtilSplitTestQuoted : public MatrixTest +{ +public: + UtilSplitTestQuoted() : MatrixTest("Util::split::quoted") {} + virtual void run(const Options& options); +}; +#endif // UTIL_SPLIT_TEST_H_ === modified file 'src/libmatrix/util.cc' --- src/libmatrix/util.cc 2012-05-22 09:33:07 +0000 +++ src/libmatrix/util.cc 2012-08-13 10:09:08 +0000 @@ -25,25 +25,102 @@ using std::string; using std::vector; -void -Util::split(const string& src, char delim, vector& elementVec, bool fuzzy) -{ - // Trivial rejection - if (src.empty()) - { - return; - } - - // Simple case: we want to enforce the value of 'delim' strictly - if (!fuzzy) - { - std::stringstream ss(src); - string item; - while(std::getline(ss, item, delim)) - elementVec.push_back(item); - return; - } - +/* + * State machine for bash-like quoted string escaping: + * + * \ + * -----------> +---------+ + * | ---------- | Escaped | + * | | *,ESC +---------+ + * | | + * | v ' + * +--------+ ---> +--------------+ ----- + * | Normal | <--- | SingleQuoted | | *, ESC + * +--------+ ' +--------------+ <---- + * | ^ + * | | + * | | " +--------------+ ---- + * | ---------- | DoubleQuoted | | *, ESC + * -----------> +--------------+ <--- + * " | ^ + * \ | | *, ESC + * v | + * +---------------------+ + * | DoubleQuotedEscaped | + * +---------------------+ + * + * ESC: Mark character as Escaped + */ +static void +fill_escape_vector(const string &str, vector &esc_vec) +{ + enum State { + StateNormal, + StateEscaped, + StateDoubleQuoted, + StateDoubleQuotedEscaped, + StateSingleQuoted + }; + + State state = StateNormal; + + for (string::const_iterator iter = str.begin(); + iter != str.end(); + iter++) + { + const char c(*iter); + bool esc = false; + + switch (state) { + case StateNormal: + if (c == '"') + state = StateDoubleQuoted; + else if (c == '\\') + state = StateEscaped; + else if (c == '\'') + state = StateSingleQuoted; + break; + case StateEscaped: + esc = true; + state = StateNormal; + break; + case StateDoubleQuoted: + if (c == '"') + state = StateNormal; + else if (c == '\\') + state = StateDoubleQuotedEscaped; + else + esc = true; + break; + case StateDoubleQuotedEscaped: + esc = true; + state = StateDoubleQuoted; + break; + case StateSingleQuoted: + if (c == '\'') + state = StateNormal; + else + esc = true; + default: + break; + } + + esc_vec.push_back(esc); + } +} + +static void +split_normal(const string& src, char delim, vector& elementVec) +{ + std::stringstream ss(src); + string item; + while(std::getline(ss, item, delim)) + elementVec.push_back(item); +} + +static void +split_fuzzy(const string& src, char delim, vector& elementVec) +{ // Fuzzy case: Initialize our delimiter string based upon the caller's plus // a space to allow for more flexibility. string delimiter(" "); @@ -76,6 +153,70 @@ elementVec.push_back(str); } +static void +split_quoted(const string& src, char delim, vector& elementVec) +{ + std::stringstream ss; + vector escVec; + + /* Mark characters in the string as escaped or not */ + fill_escape_vector(src, escVec); + + /* Sanity check... */ + if (src.length() != escVec.size()) + return; + + for (vector::const_iterator iter = escVec.begin(); + iter != escVec.end(); + iter++) + { + bool escaped = static_cast(*iter); + char c = src[iter - escVec.begin()]; + + /* Output all characters, except unescaped ",\,' */ + if ((c != '"' && c != '\\' && c != '\'') || escaped) { + /* If we reach an unescaped delimiter character, do a split */ + if (c == delim && !escaped) { + elementVec.push_back(ss.str()); + ss.str(""); + ss.clear(); + } + else { + ss << c; + } + } + + } + + /* Handle final element, delimited by end of string */ + const string &finalElement(ss.str()); + if (!finalElement.empty()) + elementVec.push_back(finalElement); +} + +void +Util::split(const string& src, char delim, vector& elementVec, + Util::SplitMode mode) +{ + // Trivial rejection + if (src.empty()) + { + return; + } + + switch (mode) + { + case Util::SplitModeNormal: + return split_normal(src, delim, elementVec); + case Util::SplitModeFuzzy: + return split_fuzzy(src, delim, elementVec); + case Util::SplitModeQuoted: + return split_quoted(src, delim, elementVec); + default: + break; + } +} + uint64_t Util::get_timestamp_us() { === modified file 'src/libmatrix/util.h' --- src/libmatrix/util.h 2012-05-22 09:33:07 +0000 +++ src/libmatrix/util.h 2012-08-13 10:09:08 +0000 @@ -25,21 +25,33 @@ struct Util { /** + * How to perform the split() operation + */ + enum SplitMode { + /** Normal split operation */ + SplitModeNormal, + /** Allow for spaces and multiple consecutive occurences of the delimiter */ + SplitModeFuzzy, + /** Take into account bash-like quoting and escaping rules */ + SplitModeQuoted + }; + + /** * split() - Splits a string into elements using a provided delimiter * * @s: the string to split * @delim: the delimiter to use * @elems: the string vector to populate - * @fuzzy: (optional) enable/disable strict handling of @delim + * @mode: the SplitMode to use * * Using @delim to determine field boundaries, splits @s into separate * string elements. These elements are returned in the string vector - * @elems. If @fuzzy is true, then the handling of @delim allows for - * spaces and multiple consecutive occurences of @delim in determining - * field boundaries. As long as @s is non-empty, there will be at least - * one element in @elems. + * @elems. As long as @s is non-empty, there will be at least one + * element in @elems. */ - static void split(const std::string &s, char delim, std::vector &elems, bool fuzzy = false); + static void split(const std::string& src, char delim, + std::vector& elems, + Util::SplitMode mode); /** * get_timestamp_us() - Returns the current time in microseconds */ === modified file 'src/main-loop.cpp' --- src/main-loop.cpp 2012-06-15 13:24:32 +0000 +++ src/main-loop.cpp 2012-08-13 10:09:08 +0000 @@ -252,7 +252,7 @@ { LibMatrix::vec2 v(0.0, 0.0); std::vector elems; - Util::split(s, ',', elems); + Util::split(s, ',', elems, Util::SplitModeNormal); if (elems.size() > 0) v.x(Util::fromString(elems[0])); === modified file 'src/options.cpp' --- src/options.cpp 2012-06-15 09:03:04 +0000 +++ src/options.cpp 2012-08-13 10:09:08 +0000 @@ -74,7 +74,7 @@ parse_size(const std::string &str, std::pair &size) { std::vector d; - Util::split(str, 'x', d); + Util::split(str, 'x', d, Util::SplitModeNormal); size.first = Util::fromString(d[0]); === modified file 'src/scene-effect-2d.cpp' --- src/scene-effect-2d.cpp 2012-07-16 14:25:30 +0000 +++ src/scene-effect-2d.cpp 2012-08-13 10:09:08 +0000 @@ -194,7 +194,7 @@ std::vector rows; unsigned int w = UINT_MAX; - Util::split(str, ';', rows); + Util::split(str, ';', rows, Util::SplitModeNormal); Log::debug("Parsing kernel matrix:\n"); static const std::string format("%f "); @@ -206,7 +206,7 @@ iter++) { std::vector elems; - Util::split(*iter, ',', elems); + Util::split(*iter, ',', elems, Util::SplitModeNormal); if (w != UINT_MAX && elems.size() != w) { Log::error("Matrix row %u contains %u elements, whereas previous" === modified file 'src/scene.cpp' --- src/scene.cpp 2012-07-17 09:12:39 +0000 +++ src/scene.cpp 2012-08-13 10:09:08 +0000 @@ -38,7 +38,7 @@ const std::string &values) : name(nam), value(val), default_value(val), description(desc), set(false) { - Util::split(values, ',', acceptable_values); + Util::split(values, ',', acceptable_values, Util::SplitModeNormal); } Scene::Scene(Canvas &pCanvas, const string &name) :