1 /*******************************************************************************
2 
3     Implementation of buffer which contains elements with indirections
4     within them. Such elements can't be implicitly converted between const
5     and mutable and thus API must be conservatively mutable.
6 
7     Copyright:
8         Copyright (c) 2016 dunnhumby Germany GmbH.
9         All rights reserved.
10 
11     License:
12         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
13         Alternatively, this file may be distributed under the terms of the Tango
14         3-Clause BSD License (see LICENSE_BSD.txt for details).
15 
16 *******************************************************************************/
17 
18 module ocean.core.buffer.WithIndirections;
19 
20 template WithIndirectionsBufferImpl ( )
21 {
22     /***************************************************************************
23 
24         Plain D array internally used as buffer storage
25 
26     ***************************************************************************/
27 
28     private T[] data;
29 
30     /***************************************************************************
31 
32         Assigns data to stored data from other slice
33 
34         Params:
35             rhs   = slice to assign from
36 
37     ***************************************************************************/
38 
39     void opAssign ( T[] rhs )
40     {
41         this.length = rhs.length;
42         this.data[] = rhs[];
43     }
44 
45     /***************************************************************************
46 
47         Assigns data to stored data from other slice
48 
49         Params:
50             rhs   = slice to assign from
51             begin = starting index for local data
52             end   = end index for local data
53 
54     ***************************************************************************/
55 
56     void opSliceAssign ( U ) ( U[] rhs, ptrdiff_t begin = 0,
57         ptrdiff_t end = -1 )
58     {
59         if (end < 0)
60             end = this.length();
61         this.data[begin .. end] = rhs[];
62     }
63 
64     /***************************************************************************
65 
66         Individual element access.
67 
68         Params:
69             i = element index
70 
71         Returns:
72             Pointer to requested element
73 
74     ***************************************************************************/
75 
76     T* opIndex ( size_t i )
77     {
78         return &this.data[i];
79     }
80 
81     /***************************************************************************
82 
83         Invidual element assignment
84 
85         Params:
86             value = new element value
87             i = element index
88 
89     ***************************************************************************/
90 
91     void opIndexAssign ( T value, size_t i )
92     {
93         this.data[i] = value;
94     }
95 
96     /***************************************************************************
97 
98         Appends to current buffer
99 
100         Params:
101             op = operation to perform
102             rhs = array or element to append
103 
104     ***************************************************************************/
105 
106     void opOpAssign (string op) ( T rhs ) if (op == "~")
107     {
108         this.length = this.data.length + 1;
109         this.data[$-1] = rhs;
110     }
111 
112     /***************************************************************************
113 
114         ditto
115 
116     ***************************************************************************/
117 
118     void opOpAssign (string op) ( T[] rhs ) if (op == "~")
119     {
120         this.length = this.data.length + rhs.length;
121         this.data[$-rhs.length .. $] = rhs[];
122     }
123 
124     /***************************************************************************
125 
126         Buffer element iteration
127 
128         Params:
129             dg = foreach loop body
130 
131     ***************************************************************************/
132 
133     int opApply ( scope int delegate(ref T) dg )
134     {
135         foreach (elem; this.data)
136         {
137             auto status = dg(elem);
138             if (status != 0)
139                 return status;
140         }
141 
142         return 0;
143     }
144 
145     /***************************************************************************
146 
147         Buffer element iteration (with index)
148 
149         Params:
150             dg = foreach loop body
151 
152     ***************************************************************************/
153 
154     int opApply ( scope int delegate(ref size_t, ref T) dg )
155     {
156         foreach (index, elem; this.data)
157         {
158             auto status = dg(index, elem);
159             if (status != 0)
160                 return status;
161         }
162 
163         return 0;
164     }
165 }