From fd9b7ebdff8a301c9633c269acc78c088692baea Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Thu, 19 Oct 2017 21:07:31 +0200 Subject: [PATCH 1/4] public nogc ObjectPath.isValid function + ~ operator --- source/ddbus/thin.d | 62 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index c98527e..b5e624e 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -18,8 +18,8 @@ public import ddbus.exception : wrapErrors, DBusException; struct ObjectPath { private string _value; - this(string objPath) { - enforce(_isValid(objPath)); + this(string objPath) @safe { + enforce(isValid(objPath)); _value = objPath; } @@ -27,17 +27,62 @@ struct ObjectPath { return _value; } - size_t toHash() const pure nothrow @trusted { + /// Returns the string representation of this ObjectPath. + string value() const pure @nogc nothrow @safe { + return _value; + } + + size_t toHash() const pure @nogc nothrow @trusted { return hashOf(_value); } - bool opEquals(ref const typeof(this) b) const pure nothrow @safe { + bool opEquals(ref const typeof(this) b) const pure @nogc nothrow @safe { return _value == b._value; } - private static bool _isValid(string objPath) { - import std.regex : matchFirst, ctRegex; - return cast(bool) objPath.matchFirst(ctRegex!("^((/[0-9A-Za-z_]+)+|/)$")); + ObjectPath opBinary(string op : "~")(string rhs) const pure @safe { + return opBinary!"~"(ObjectPath(rhs)); + } + + ObjectPath opBinary(string op : "~")(ObjectPath rhs) const pure @safe { + if (!_value.length || _value[$ - 1] != '/') { + ObjectPath ret; + // Is safe if both sides were safe and isValid enforces a starting / + ret._value = _value ~ rhs._value; + return ret; + } else { + ObjectPath ret; + ret._value = _value[0 .. $ - 1] ~ rhs._value; + return ret; + } + } + + void opOpAssign(string op : "~")(string rhs) pure @safe { + _value = opBinary!"~"(rhs)._value; + } + + void opOpAssign(string op : "~")(ObjectPath rhs) pure @safe { + _value = opBinary!"~"(rhs)._value; + } + + /// Returns: false for empty strings or strings that don't match the pattern `(/[0-9A-Za-z_]+)+|/` + static bool isValid(string objPath) pure @nogc nothrow @safe { + import std.ascii : isAlphaNum; + + if (!objPath.length) + return false; + if (objPath == "/") + return true; + if (objPath[0] != '/' || objPath[$ - 1] == '/') + return false; + // .representation to avoid unicode exceptions -> @nogc & nothrow + return objPath.representation.splitter('/').drop(1) + .all!(a => + a.length && + a.all!(c => + c.isAlphaNum || c == '_' + ) + ); } } @@ -46,9 +91,10 @@ unittest { ObjectPath("some.invalid/object_path").assertThrow(); ObjectPath("/path/with/TrailingSlash/").assertThrow(); + ObjectPath("/path/without/TrailingSlash").assertNotThrown(); string path = "/org/freedesktop/DBus"; auto obj = ObjectPath(path); - obj.toString().assertEqual(path); + obj.value.assertEqual(path); obj.toHash().assertEqual(path.hashOf); } From eeab02685241142ce99c19f66491fc1c4e8b8ed0 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Thu, 19 Oct 2017 21:07:39 +0200 Subject: [PATCH 2/4] Allow ObjectPath in PathIface constructor --- source/ddbus/simple.d | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/ddbus/simple.d b/source/ddbus/simple.d index 96cd6aa..d58ac12 100644 --- a/source/ddbus/simple.d +++ b/source/ddbus/simple.d @@ -8,6 +8,10 @@ import std.string; import std.traits; class PathIface { + this(Connection conn, string dest, ObjectPath path, string iface) { + this(conn, dest, path.value, iface); + } + this(Connection conn, string dest, string path, string iface) { this.conn = conn; this.dest = dest.toStringz(); From 92447921a7d918df327f7c2ae925300eee681ef9 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Fri, 20 Oct 2017 12:47:31 +0200 Subject: [PATCH 3/4] unittest ObjectPath concat & allow strings without leading / --- source/ddbus/thin.d | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index b5e624e..bd3c3df 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -18,7 +18,7 @@ public import ddbus.exception : wrapErrors, DBusException; struct ObjectPath { private string _value; - this(string objPath) @safe { + this(string objPath) pure @safe { enforce(isValid(objPath)); _value = objPath; } @@ -41,20 +41,26 @@ struct ObjectPath { } ObjectPath opBinary(string op : "~")(string rhs) const pure @safe { - return opBinary!"~"(ObjectPath(rhs)); + if (!rhs.startsWith("/")) + return opBinary!"~"(ObjectPath("/" ~ rhs)); + else + return opBinary!"~"(ObjectPath(rhs)); } - ObjectPath opBinary(string op : "~")(ObjectPath rhs) const pure @safe { - if (!_value.length || _value[$ - 1] != '/') { - ObjectPath ret; - // Is safe if both sides were safe and isValid enforces a starting / + ObjectPath opBinary(string op : "~")(ObjectPath rhs) const pure @safe + in { + assert(ObjectPath.isValid(_value) && ObjectPath.isValid(rhs._value)); + } out (v) { + assert(ObjectPath.isValid(v._value)); + } body { + ObjectPath ret; + + if (_value == "/") + ret._value = rhs._value; + else ret._value = _value ~ rhs._value; - return ret; - } else { - ObjectPath ret; - ret._value = _value[0 .. $ - 1] ~ rhs._value; - return ret; - } + + return ret; } void opOpAssign(string op : "~")(string rhs) pure @safe { @@ -98,6 +104,19 @@ unittest { obj.toHash().assertEqual(path.hashOf); } +unittest { + import dunit.toolkit; + + ObjectPath a = ObjectPath("/org/freedesktop"); + a.assertEqual(ObjectPath("/org/freedesktop")); + a ~= ObjectPath("/UPower"); + a.assertEqual(ObjectPath("/org/freedesktop/UPower")); + a ~= "Device"; + a.assertEqual(ObjectPath("/org/freedesktop/UPower/Device")); + (a ~ "0").assertEqual(ObjectPath("/org/freedesktop/UPower/Device/0")); + a.assertEqual(ObjectPath("/org/freedesktop/UPower/Device")); +} + /// Structure allowing typeless parameters struct DBusAny { /// DBus type of the value (never 'v'), see typeSig!T From 34e42b9aa2d2c35a0b0a894ba279f53034d66051 Mon Sep 17 00:00:00 2001 From: "Harry T. Vennik" Date: Sat, 4 Nov 2017 10:59:41 +0100 Subject: [PATCH 4/4] Improved code formatting --- source/ddbus/thin.d | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index bd3c3df..3cd9411 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -27,7 +27,9 @@ struct ObjectPath { return _value; } - /// Returns the string representation of this ObjectPath. + /++ + Returns the string representation of this ObjectPath. + +/ string value() const pure @nogc nothrow @safe { return _value; } @@ -71,7 +73,10 @@ struct ObjectPath { _value = opBinary!"~"(rhs)._value; } - /// Returns: false for empty strings or strings that don't match the pattern `(/[0-9A-Za-z_]+)+|/` + /++ + Returns: `false` for empty strings or strings that don't match the + pattern `(/[0-9A-Za-z_]+)+|/`. + +/ static bool isValid(string objPath) pure @nogc nothrow @safe { import std.ascii : isAlphaNum; @@ -83,12 +88,12 @@ struct ObjectPath { return false; // .representation to avoid unicode exceptions -> @nogc & nothrow return objPath.representation.splitter('/').drop(1) - .all!(a => - a.length && - a.all!(c => - c.isAlphaNum || c == '_' - ) - ); + .all!(a => + a.length && + a.all!(c => + c.isAlphaNum || c == '_' + ) + ); } }