1 /*
2  * Kiss - A refined core library for D programming language.
3  *
4  * Copyright (C) 2015-2018  Shanghai Putao Technology Co., Ltd
5  *
6  * Developer: HuntLabs.cn
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11  
12 module kiss.container.array;
13 
14 import core.stdc.string : memcpy;
15 /**
16 *
17 */
18 size_t arrayRemove(E)(ref E[] ary, auto ref E e, bool one = false) {
19     E tv = E.init;
20     size_t rm = 0;
21     size_t site = 0;
22     bool unRemove = false;
23     for (size_t j = site; j < ary.length; ++j) {
24         if (ary[j] != e || unRemove) {
25             if(site != j) 
26                 memcpy(&ary[site], &ary[j], E.sizeof);
27             site++;
28         } else {
29             doInitVaule(ary[j]);
30             rm++;
31             if(one) 
32                 unRemove = true;
33         }
34     }
35     if(rm > 0) {
36         auto size = ary.length - rm;
37         auto rmed = ary[size .. $];
38         ary = ary[0..size];
39         fillWithMemcpy(rmed, tv);
40     }
41     return rm;
42 }
43 
44 E[] removeSite(E)(ref E[] _array,size_t site) 
45     in {
46         assert(site < _array.length);
47     } body{
48         const size_t len = _array.length - 1;
49         doInitVaule(_array[site]);
50         for (size_t i = site; i < len; ++i) {
51             memcpy(&(_array[i]), &(_array[i + 1]), E.sizeof);
52         }
53         E v = E.init;
54         memcpy(&(_array[len]), &v, E.sizeof);
55         _array = _array[0..len];
56         return _array;
57     }
58 
59 void doInitVaule(E)(ref E v){
60     static if(is(E == struct) && hasElaborateDestructor!E) {
61         destroy(v);
62     }
63     memcpy(&v,&v,E.sizeof);
64 }
65 
66 //from std.experimental.allocator.package;
67 void fillWithMemcpy(T)(void[] array, auto ref T filler) nothrow
68 {
69     import core.stdc.string : memcpy;
70     import std.algorithm.comparison : min;
71     if (!array.length) return;
72     memcpy(array.ptr, &filler, T.sizeof);
73     // Fill the array from the initialized portion of itself exponentially.
74     for (size_t offset = T.sizeof; offset < array.length; )
75     {
76         size_t extent = min(offset, array.length - offset);
77         memcpy(array.ptr + offset, array.ptr, extent);
78         offset += extent;
79     }
80 }
81 
82 unittest {
83     import std.stdio;
84 
85     int[] a = [0, 0, 0, 4, 5, 4, 0, 8, 0, 2, 0, 0, 0, 1, 2, 5, 8, 0];
86     writeln("length a  = ", a.length, "   a is : ", a);
87     int[] b = a.dup;
88     auto rm = arrayRemove(b, 0);
89     writeln("length b  = ", b.length, "   b is : ", b);
90     assert(b == [4, 5, 4, 8, 2, 1, 2, 5, 8]);
91 
92     int[] c = a.dup;
93     rm = arrayRemove(c, 8);
94     writeln("length c  = ", c.length, "   c is : ", c);
95 
96     assert(c == [0, 0, 0, 4, 5, 4, 0, 0, 2, 0, 0, 0, 1, 2, 5, 0]);
97 
98     int[] d = a.dup;
99     rm = arrayRemove(d, 9);
100     writeln("length d = ", d.length, "   d is : ", d);
101     assert(d == a);
102 }