1 /**
2  * D-LevelDB Slice
3  *
4  * Pointer Slice
5  *
6  * Copyright: Copyright © 2013 Byron Heads
7  * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
8  * Authors: Byron Heads
9 */
10 /*          Copyright  © 2013 Byron Heads
11  * Distributed under the Boost Software License, Version 1.0.
12  *    (See accompanying file LICENSE_1_0.txt or copy at
13  *          http://www.boost.org/LICENSE_1_0.txt)
14  */
15 module leveldb.slice;
16 
17 private:
18 import leveldb.exceptions;
19 import deimos.leveldb.leveldb : leveldb_free;
20 import std.traits : isBasicType, isArray, isPointer, ForeachType;
21 
22 
23 package:
24 
25 template isPrimitive(T) 
26 {
27     static if(isBasicType!T || (isArray!T && isBasicType!(ForeachType!T))) {
28         enum isPrimitive = true;
29     } else {
30         enum isPrimitive = false;
31     }
32 }
33 
34 /**
35  * Holds a pointer returned from leveldb, or passed to leveldb.
36  *
37  * Leveldb memory is freed on destruction.
38  */
39 struct Slice
40 {
41 private:
42     void* _ptr;         // the pointer
43     size_t len;         // the size of the data block
44     bool free = false;  // should this block be freed by leveldb_free
45 
46     this(void* p, size_t l, bool f = false)
47     {
48         debug {
49             import std.stdio;
50             writeln("length: ", l);
51         }
52         _ptr = p;
53         len = l;
54         free = f;
55     }
56 
57 public:
58 
59     /// Calles free on leveldb raw memory
60     ~this()
61     {
62         if(free) {
63             leveldb_free(_ptr);
64         }
65     }
66 
67 
68     /// length or size of slice
69     @property
70     size_t size() inout pure nothrow
71     {
72         return len;
73     }
74     
75     /// Get slice pointer
76     @property
77     const(char)* cptr() inout pure nothrow
78     {
79         return cast(const(char)*)_ptr;
80     }
81 
82     @property
83     inout(T) ptr(T)() inout pure nothrow
84         if(isPointer!T)
85     {
86         return cast(inout(T))_ptr;
87     }
88 
89     /// Test is slice is valid
90     @property
91     bool ok() inout pure nothrow
92     {
93         return _ptr !is null;
94     }
95 
96     /// Get slice as a data type
97     alias to = as;
98     @property
99     auto as(T)()
100         if(isPrimitive!T)
101     {
102         static if(isArray!T) {
103             return  cast(T)(_ptr[0..size]).dup;
104         } else {
105             return *cast(T*)_ptr;
106         }
107     }
108 
109     /// Slice casting
110     inout(T) opCast(T)() inout
111     {
112         return as!T;
113     }
114 
115     // helper
116     auto static make(T)(T t) 
117         if(isPrimitive!T) 
118     out(slice){
119             static if(isArray!T) {
120                 assert(slice._ptr == t.ptr);
121             } else {
122                 assert(slice._ptr == &t);
123                 assert(slice.as!T == t);
124             }
125     } body {
126         debug {
127             import std.stdio;
128             writeln("T: ", T.stringof, " t: ", t);
129         }
130         static if(isArray!T) {
131             return Slice(cast(void*)t.ptr, t.length * (ForeachType!T).sizeof);
132         } else {
133             return Slice(cast(void*)&t, T.sizeof);
134         }
135     }
136 
137     // helper
138     auto static make(T)(T t, size_t size, bool free = false) if(isPointer!T) {
139         debug {
140             import std.stdio;
141             writeln("T", T.stringof, " size: ", size, " free: ", free);
142         }
143         return Slice(cast(void*)t, size, free);
144     }
145 }
146