aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ext_depends/d2sqlite3/source/d2sqlite3/internal/util.d
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext_depends/d2sqlite3/source/d2sqlite3/internal/util.d')
-rw-r--r--src/ext_depends/d2sqlite3/source/d2sqlite3/internal/util.d211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/ext_depends/d2sqlite3/source/d2sqlite3/internal/util.d b/src/ext_depends/d2sqlite3/source/d2sqlite3/internal/util.d
new file mode 100644
index 0000000..3efd351
--- /dev/null
+++ b/src/ext_depends/d2sqlite3/source/d2sqlite3/internal/util.d
@@ -0,0 +1,211 @@
+/+
+This module is part of d2sqlite3.
+
+Authors:
+ Nicolas Sicard (biozic) and other contributors at $(LINK https://github.com/biozic/d2sqlite3)
+
+Copyright:
+ Copyright 2011-18 Nicolas Sicard.
+
+License:
+ $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
++/
+module d2sqlite3.internal.util;
+
+import std.traits : isBoolean, isIntegral, isFloatingPoint, isSomeString,
+ isArray, isStaticArray, isDynamicArray;
+import std.typecons : Nullable;
+import d2sqlite3.sqlite3;
+import d2sqlite3.internal.memory;
+
+package(d2sqlite3):
+
+string errmsg(sqlite3* db) nothrow
+{
+ import std.conv : to;
+ return sqlite3_errmsg(db).to!string;
+}
+
+string errmsg(sqlite3_stmt* stmt) nothrow
+{
+ return errmsg(sqlite3_db_handle(stmt));
+}
+
+auto byStatement(string sql)
+{
+ static struct ByStatement
+ {
+ string sql;
+ size_t end;
+
+ this(string sql)
+ {
+ this.sql = sql;
+ end = findEnd();
+ }
+
+ bool empty() const @safe pure nothrow @nogc
+ {
+ return !sql.length;
+ }
+
+ string front() const @safe pure nothrow @nogc
+ {
+ return sql[0 .. end];
+ }
+
+ void popFront()
+ {
+ sql = sql[end .. $];
+ end = findEnd();
+ }
+
+ private:
+ size_t findEnd()
+ {
+ import std.algorithm : countUntil;
+ import std.string : toStringz;
+ import std.utf : byCodeUnit;
+
+ size_t pos;
+ bool complete;
+ do
+ {
+ auto tail = sql[pos .. $];
+ immutable offset = tail.byCodeUnit.countUntil(';') + 1;
+ pos += offset;
+ if (offset == 0)
+ pos = sql.length;
+ auto part = sql[0 .. pos];
+ complete = cast(bool) sqlite3_complete(part.toStringz);
+ }
+ while (!complete && pos < sql.length);
+ return pos;
+ }
+ }
+
+ return ByStatement(sql);
+}
+unittest
+{
+ import std.algorithm : equal, map;
+ import std.string : strip;
+
+ auto sql = "CREATE TABLE test (dummy);
+ CREATE TRIGGER trig INSERT ON test BEGIN SELECT 1; SELECT 'a;b'; END;
+ SELECT 'c;d';;
+ CREATE";
+ assert(equal(sql.byStatement.map!(s => s.strip), [
+ "CREATE TABLE test (dummy);",
+ "CREATE TRIGGER trig INSERT ON test BEGIN SELECT 1; SELECT 'a;b'; END;",
+ "SELECT 'c;d';",
+ ";",
+ "CREATE"
+ ]));
+}
+
+// getValue and setResult function templates
+// used by createFunction and createAggregate
+
+auto getValue(T)(sqlite3_value* argv)
+ if (isBoolean!T)
+{
+ return sqlite3_value_int64(argv) != 0;
+}
+
+auto getValue(T)(sqlite3_value* argv)
+ if (isIntegral!T)
+{
+ import std.conv : to;
+ return sqlite3_value_int64(argv).to!T;
+}
+
+auto getValue(T)(sqlite3_value* argv)
+ if (isFloatingPoint!T)
+{
+ import std.conv : to;
+ if (sqlite3_value_type(argv) == SQLITE_NULL)
+ return double.nan;
+ return sqlite3_value_double(argv).to!T;
+}
+
+auto getValue(T)(sqlite3_value* argv)
+ if (isSomeString!T)
+{
+ import std.conv : to;
+ return (cast(const(char)*) sqlite3_value_text(argv)).to!T;
+}
+
+auto getValue(T)(sqlite3_value* argv)
+ if (isArray!T && !isSomeString!T)
+{
+ import std.conv : to;
+ import core.stdc.string : memcpy;
+
+ auto n = sqlite3_value_bytes(argv);
+ ubyte[] blob;
+ blob.length = n;
+ memcpy(blob.ptr, sqlite3_value_blob(argv), n);
+ return cast(T) blob;
+}
+
+auto getValue(T : Nullable!U, U...)(sqlite3_value* argv)
+{
+ if (sqlite3_value_type(argv) == SQLITE_NULL)
+ return T.init;
+ return T(getValue!(U[0])(argv));
+}
+
+void setResult(T)(sqlite3_context* context, T value)
+ if (isIntegral!T || isBoolean!T)
+{
+ import std.conv : to;
+ sqlite3_result_int64(context, value.to!long);
+}
+
+void setResult(T)(sqlite3_context* context, T value)
+ if (isFloatingPoint!T)
+{
+ import std.conv : to;
+ sqlite3_result_double(context, value.to!double);
+}
+
+void setResult(T)(sqlite3_context* context, T value)
+ if (isSomeString!T)
+{
+ import std.conv : to;
+ auto val = value.to!string;
+ sqlite3_result_text64(context, cast(const(char)*) anchorMem(cast(void*) val.ptr),
+ val.length, &releaseMem, SQLITE_UTF8);
+}
+
+void setResult(T)(sqlite3_context* context, T value)
+ if (isDynamicArray!T && !isSomeString!T)
+{
+ auto val = cast(void[]) value;
+ sqlite3_result_blob64(context, anchorMem(val.ptr), val.length, &releaseMem);
+}
+
+void setResult(T)(sqlite3_context* context, T value)
+ if (isStaticArray!T)
+{
+ auto val = cast(void[]) value;
+ sqlite3_result_blob64(context, val.ptr, val.sizeof, SQLITE_TRANSIENT);
+}
+
+void setResult(T : Nullable!U, U...)(sqlite3_context* context, T value)
+{
+ if (value.isNull)
+ sqlite3_result_null(context);
+ else
+ setResult(context, value.get);
+}
+
+string nothrowFormat(Args...)(string fmt, Args args) nothrow
+{
+ import std.string : format;
+ try
+ return fmt.format(args);
+ catch (Exception e)
+ throw new Error("Error: " ~ e.msg);
+}