1 module tagion.betterC.utils.Memory; 2 3 import core.stdc.string : memcpy; 4 import std.conv : emplace; 5 import std.traits : ForeachType, PointerTarget, Unqual, isArray, isPointer; 6 import tagion.betterC.utils.platform; 7 8 private import tagion.crypto.secp256k1.c.secp256k1; 9 private import tagion.crypto.secp256k1.c.secp256k1_ecdh; 10 11 @nogc: 12 13 version (memtrace) { 14 enum memalloc_format = "#%p:%06d\t\t\t\t%04d %c %s\n"; 15 static const memalloc_trace = memalloc_format.ptr; 16 enum memfree_format = "#%p:000000\t\t\t\t%04d %c %s\n"; 17 static const memfree_trace = memfree_format.ptr; 18 enum mempos_format = "#%p:%06d\t\t\t\t%d:%s\n"; 19 static const mempos = mempos_format.ptr; 20 static uint block; 21 } 22 23 @trusted 24 T create(T)(const size_t size, string file = __FILE__, size_t line = __LINE__) if (isArray!T) { 25 alias BaseT = ForeachType!T; 26 auto mem = calloc(size, BaseT.sizeof); 27 version (memtrace) { 28 const _size = size * BaseT.sizeof; 29 printf(memalloc_trace, mem, _size, block, 'a', T.stringof.ptr); 30 printf(mempos, mem, _size, line, file.ptr); 31 block++; 32 } 33 return (cast(BaseT*) mem)[0 .. size]; 34 } 35 36 @trusted 37 void create(T)(ref T data, const size_t size, string file = __FILE__, size_t line = __LINE__) if (isArray!T) 38 in { 39 assert(data is null); 40 } 41 do { 42 alias BaseT = ForeachType!T; 43 auto mem = calloc(size, BaseT.sizeof); 44 version (memtrace) { 45 const _size = size * BaseT.sizeof; 46 printf(memalloc_trace, mem, _size, block, 'A', T.stringof.ptr); 47 printf(mempos, mem, _size, line, file.ptr); 48 block++; 49 50 } 51 data = (cast(BaseT*) mem)[0 .. size]; 52 } 53 54 @trusted 55 void create(U)(ref U[] data, const(U[]) src, string file = __FILE__, size_t line = __LINE__) 56 in { 57 assert(data is null); 58 } 59 do { 60 alias BaseU = Unqual!U; 61 auto mem = calloc(src.length, U.sizeof); 62 version (memtrace) { 63 printf(memalloc_trace, mem, src.length * U.sizeof, block, 'B', (U[]).stringof.ptr); 64 printf(mempos, mem, 0, line, file.ptr); 65 block++; 66 67 } 68 auto temp = (cast(BaseU*) mem)[0 .. src.length]; 69 temp[0 .. src.length] = src; 70 data = cast(U[]) temp; 71 } 72 73 @trusted 74 T* create(T, Args...)(Args args, string file = __FILE__, size_t line = __LINE__) if (is(T == struct)) { 75 auto mem = calloc(T.sizeof, 1); 76 version (memtrace) { 77 const _size = T.sizeof; 78 printf(memalloc_trace, mem, _size, block, 'S', T.stringof.ptr); 79 printf(mempos, mem, _size, line, file.ptr); 80 block++; 81 } 82 auto result = cast(T*) mem; 83 emplace!T(result, args); 84 return result; 85 } 86 87 @trusted 88 T create(T)(string file = __FILE__, size_t line = __LINE__) if (isPointer!T) { 89 auto mem = calloc(PointerTarget!(T).sizeof, 1); 90 version (memtrace) { 91 const _size = PointerTarget!(T).sizeof; 92 printf(memalloc_trace, mem, _size, block, '*', T.stringof.ptr); 93 printf(mempos, mem, _size, line, file.ptr); 94 block++; 95 96 } 97 return cast(T) mem; 98 } 99 100 @trusted 101 void resize(T)(ref T data, const size_t len, string file = __FILE__, size_t line = __LINE__) if (isArray!T) { 102 alias BaseT = ForeachType!T; 103 const size = len * BaseT.sizeof; 104 auto mem = realloc(cast(void*) data.ptr, size); 105 version (memtrace) { 106 printf(memfree_trace, &data, block, 'R', T.stringof.ptr); 107 printf(memalloc_trace, mem, size, block, 'R', T.stringof.ptr); 108 printf(mempos, mem, size, line, file.ptr); 109 } 110 data = (cast(BaseT*) mem)[0 .. len]; 111 } 112 113 @trusted 114 void dispose(T)(ref T die, string file = __FILE__, size_t line = __LINE__) if (isArray!T) { 115 if (die !is null) { 116 static if (__traits(compiles, die[0].dispose)) { 117 foreach (ref d; die) { 118 d.dispose; 119 } 120 } 121 version (memtrace) { 122 block--; 123 printf(memfree_trace, die.ptr, block, 'd', T.stringof.ptr); 124 printf(mempos, die.ptr, 0, line, file.ptr); 125 } 126 free(cast(void*) die.ptr); 127 die = null; 128 } 129 } 130 131 @trusted 132 void dispose(bool OWNS = true, T)(ref T die, string file = __FILE__, size_t line = __LINE__) if (isPointer!T) { 133 if (die !is null) { 134 static if (OWNS && __traits(compiles, (*die).dispose)) { 135 (*die).dispose; 136 } 137 version (memtrace) { 138 block--; 139 printf(memfree_trace, die, block, 'D', T.stringof.ptr); 140 printf(mempos, die, 0, line, file.ptr); 141 } 142 free(die); 143 die = null; 144 } 145 } 146 147 @trusted 148 void memcpy_wrapper(T)(ref T desination, T source) { 149 if (desination.length == source.length) { 150 memcpy(desination, source, source.length); 151 } 152 } 153 154 enum SECP256K1 : uint { 155 FLAGS_TYPE_MASK = SECP256K1_FLAGS_TYPE_MASK, 156 FLAGS_TYPE_CONTEXT = SECP256K1_FLAGS_TYPE_CONTEXT, 157 FLAGS_TYPE_COMPRESSION = SECP256K1_FLAGS_TYPE_COMPRESSION, 158 /** The higher bits contain the actual data. Do not use directly. */ 159 FLAGS_BIT_CONTEXT_VERIFY = SECP256K1_FLAGS_BIT_CONTEXT_VERIFY, 160 FLAGS_BIT_CONTEXT_SIGN = SECP256K1_FLAGS_BIT_CONTEXT_SIGN, 161 FLAGS_BIT_COMPRESSION = FLAGS_BIT_CONTEXT_SIGN, 162 163 /** Flags to pass to secp256k1_context_create. */ 164 CONTEXT_VERIFY = SECP256K1_CONTEXT_VERIFY, 165 CONTEXT_SIGN = SECP256K1_CONTEXT_SIGN, 166 CONTEXT_NONE = SECP256K1_CONTEXT_NONE, 167 168 /** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ 169 EC_COMPRESSED = SECP256K1_EC_COMPRESSED, 170 EC_UNCOMPRESSED = SECP256K1_EC_UNCOMPRESSED, 171 172 /** Prefix byte used to tag various encoded curvepoints for specific purposes */ 173 TAG_PUBKEY_EVEN = SECP256K1_TAG_PUBKEY_EVEN, 174 TAG_PUBKEY_ODD = SECP256K1_TAG_PUBKEY_ODD, 175 TAG_PUBKEY_UNCOMPRESSED = SECP256K1_TAG_PUBKEY_UNCOMPRESSED, 176 TAG_PUBKEY_HYBRID_EVEN = SECP256K1_TAG_PUBKEY_HYBRID_EVEN, 177 TAG_PUBKEY_HYBRID_ODD = SECP256K1_TAG_PUBKEY_HYBRID_ODD 178 } 179 180 @trusted 181 bool randomize(immutable(ubyte[]) seed) 182 in { 183 assert(seed.length == 32 || seed is null); 184 } 185 do { 186 secp256k1_context* _ctx; 187 // const int flag = 0; 188 _ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); 189 // auto ctx=getContext(); 190 // immutable(ubyte)* _seed = seed.ptr; 191 return secp256k1_context_randomize(_ctx, &seed[0]) == 1; 192 } 193 194 unittest { 195 { // Check Array 196 uint[] array; 197 const(uint[6]) table = [5, 6, 7, 3, 2, 1]; 198 array.create(table.length); 199 scope (exit) { 200 array.dispose; 201 assert(array.length == 0); 202 assert(array is null); 203 } 204 205 foreach (a; array) { 206 assert(a == a.init); 207 } 208 209 foreach (i, c; table) { 210 array[i] = c; 211 } 212 213 foreach (i, a; array) { 214 assert(a == table[i]); 215 } 216 assert(array.length == table.length); 217 } 218 219 { // Struct 220 struct S { 221 bool b; 222 int x; 223 } 224 225 auto s = create!S(true, 42); 226 scope (exit) { 227 s.dispose; 228 } 229 230 assert(s.b == true); 231 assert(s.x == 42); 232 } 233 234 }