Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added sqlite3_serialize() and sqlite3_deserialize() (src) #536

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/SQLitePCLRaw.core/isqlite3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ public interface ISQLite3Provider
int sqlite3_stricmp(IntPtr p, IntPtr q);
int sqlite3_strnicmp(IntPtr p, IntPtr q, int n);

IntPtr sqlite3_malloc(int n);
IntPtr sqlite3_malloc64(ulong n);
void sqlite3_free(IntPtr p);

int sqlite3_key(sqlite3 db, ReadOnlySpan<byte> key);
Expand Down Expand Up @@ -276,6 +278,9 @@ public interface ISQLite3Provider

int sqlite3_keyword_count();
int sqlite3_keyword_name(int i, out string name);

IntPtr sqlite3_serialize(sqlite3 db, utf8z schema, out long size, uint flags);
int sqlite3_deserialize(sqlite3 db, utf8z schema, IntPtr data, long szDb, long szBuf, uint flags);
}
}

127 changes: 127 additions & 0 deletions src/SQLitePCLRaw.core/raw.cs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,12 @@ static public string GetNativeLibraryName()
public const int SQLITE_TRACE_ROW = 0x04;
public const int SQLITE_TRACE_CLOSE = 0x08;

public const int SQLITE_SERIALIZE_NOCOPY = 0x001; /* Do no memory allocations */

public const int SQLITE_DESERIALIZE_FREEONCLOSE = 1; /* Call sqlite3_free() on close */
public const int SQLITE_DESERIALIZE_RESIZEABLE = 2; /* Resize using sqlite3_realloc64() */
public const int SQLITE_DESERIALIZE_READONLY = 4; /* Database is read-only */

static public int sqlite3_open(utf8z filename, out sqlite3 db)
{
int rc = Provider.sqlite3_open(filename, out var p_db);
Expand Down Expand Up @@ -1494,5 +1500,126 @@ static public int sqlite3_keyword_name(int i, out string name)
{
return Provider.sqlite3_keyword_name(i, out name);
}

static public byte[] sqlite3_serialize(sqlite3 db, utf8z schema)
{
var p = Provider.sqlite3_serialize(db, schema, out var size, 0);
if (p == IntPtr.Zero)
{
return null;
}

try
{
if (size > int.MaxValue)
{
throw new OverflowException();
}
unsafe
{
return new ReadOnlySpan<byte>(p.ToPointer(), (int)size).ToArray();
}
}
finally
{
Provider.sqlite3_free(p);
}
}

static public byte[] sqlite3_serialize(sqlite3 db, string schema)
{
return sqlite3_serialize(db, schema.to_utf8z());
}

static public long sqlite3_serialize(sqlite3 db, utf8z schema, System.IO.Stream stream)
{
var p = Provider.sqlite3_serialize(db, schema, out var size, 0);
if (p == IntPtr.Zero)
{
return -1;
}

try
{
unsafe
{
new System.IO.UnmanagedMemoryStream((byte*)p, size).CopyTo(stream);
}
return size;
}
finally
{
Provider.sqlite3_free(p);
}
}

static public long sqlite3_serialize(sqlite3 db, string schema, System.IO.Stream stream)
{
return sqlite3_serialize(db, schema.to_utf8z(), stream);
}

static public int sqlite3_deserialize(sqlite3 db, utf8z schema, ReadOnlySpan<byte> data)
{
var size = data.Length;

var p = Provider.sqlite3_malloc(size);
if (p == IntPtr.Zero)
{
return SQLITE_NOMEM;
}

try
{
unsafe
{
data.CopyTo(new Span<byte>(p.ToPointer(), size));
}
}
catch
{
Provider.sqlite3_free(p);
throw;
}

uint flags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
return Provider.sqlite3_deserialize(db, schema, p, size, size, flags);
}

static public int sqlite3_deserialize(sqlite3 db, string schema, ReadOnlySpan<byte> data)
{
return sqlite3_deserialize(db, schema.to_utf8z(), data);
}

static public int sqlite3_deserialize(sqlite3 db, utf8z schema, System.IO.Stream stream)
{
var size = stream.Length;

var p = Provider.sqlite3_malloc64((ulong)size);
if (p == IntPtr.Zero)
{
return SQLITE_NOMEM;
}

try
{
unsafe
{
stream.CopyTo(new System.IO.UnmanagedMemoryStream((byte*)p, size, size, System.IO.FileAccess.Write));
}
}
catch
{
Provider.sqlite3_free(p);
throw;
}

uint flags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
return Provider.sqlite3_deserialize(db, schema, p, size, size, flags);
}

static public int sqlite3_deserialize(sqlite3 db, string schema, System.IO.Stream stream)
{
return sqlite3_deserialize(db, schema.to_utf8z(), stream);
}
}
}
55 changes: 55 additions & 0 deletions src/providers/provider.tt
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,16 @@ namespace SQLitePCL
return rc;
}

IntPtr ISQLite3Provider.sqlite3_malloc(int n)
{
return NativeMethods.sqlite3_malloc(n);
}

IntPtr ISQLite3Provider.sqlite3_malloc64(ulong n)
{
return NativeMethods.sqlite3_malloc64(n);
}

void ISQLite3Provider.sqlite3_free(IntPtr p)
{
NativeMethods.sqlite3_free(p);
Expand Down Expand Up @@ -1788,6 +1798,22 @@ namespace SQLitePCL
return rc;
}

unsafe IntPtr ISQLite3Provider.sqlite3_serialize(sqlite3 db, utf8z schema, out long size, uint flags)
{
fixed (byte* p_schema = schema)
{
return NativeMethods.sqlite3_serialize(db, p_schema, out size, flags);
}
}

unsafe int ISQLite3Provider.sqlite3_deserialize(sqlite3 db, utf8z schema, IntPtr data, long szDb, long szBuf, uint flags)
{
fixed (byte* p_schema = schema)
{
return NativeMethods.sqlite3_deserialize(db, p_schema, data, szDb, szBuf, flags);
}
}

static class NativeMethods
{
<#
Expand Down Expand Up @@ -2181,6 +2207,13 @@ namespace SQLitePCL
new Parm("int", "n"),
}
),
new Function(
"IntPtr",
"sqlite3_malloc64",
new Parm[] {
new Parm("ulong", "n"),
}
),
new Function(
"IntPtr",
"sqlite3_realloc",
Expand Down Expand Up @@ -3151,6 +3184,28 @@ namespace SQLitePCL
new Parm("int", "length").SetIsOut(true),
}
),
new Function(
"IntPtr",
"sqlite3_serialize",
new Parm[] {
new Parm("sqlite3", "db"),
new Parm("byte*", "schema"),
new Parm("long", "size").SetIsOut(true),
new Parm("uint", "flags"),
}
),
new Function(
"int",
"sqlite3_deserialize",
new Parm[] {
new Parm("sqlite3", "db"),
new Parm("byte*", "schema"),
new Parm("IntPtr", "data"),
new Parm("long", "szDb"),
new Parm("long", "szBuf"),
new Parm("uint", "flags"),
}
),


};
Expand Down