1 /*******************************************************************************
2 
3     Utility that resets value state in a way that its memory can be reused again
4     as much as possible. Resets arrays to 0 length and values to their init
5     state.
6 
7     Copyright:
8         Copyright (c) 2018 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.meta.values.Reset;
19 
20 import ocean.meta.types.Qualifiers;
21 
22 import ocean.meta.values.VisitValue;
23 import ocean.meta.traits.Basic;
24 
25 import ocean.core.Test;
26 
27 /*******************************************************************************
28 
29     Utility that resets value state in a way that its memory can be reused again
30     as much as possible. Resets arrays to 0 length and values to their init
31     state.
32 
33     Non-class references are ignored. For classes it tries to recurse
34     into fields of the class instance without nullifying actual reference.
35 
36     Params:
37         value = value to reset
38 
39 *******************************************************************************/
40 
41 public void reset ( T ) ( ref T value )
42 {
43     Reset visitor;
44     visitValue(value, visitor);
45 }
46 
47 ///
48 unittest
49 {
50     // Can reset single value:
51     int x = 42;
52     reset(x);
53     test!("==")(x, 0);
54 
55     // Or some array:
56     int[] arr = [ 1, 2, 3 ];
57     reset(arr);
58     test!("==")(arr.length, 0);
59     test!("!=")(arr.ptr, null);
60 
61     // Or some aggregate recursively:
62     struct S
63     {
64         int x;
65         mstring buf;
66     }
67 
68     auto s = S(42, "abcd".dup);
69     reset(s);
70     test!("==")(s.x, 0);
71     test!("==")(s.buf.length, 0);
72 }
73 
74 /// Visitor for ocean.meta.values.VisitValue
75 private struct Reset
76 {
77     // has to be public to be usable from VisitValue module
78     public bool visit ( T ) ( T* value )
79     {
80         static if (isArrayType!(T) == ArrayKind.Dynamic)
81         {
82             (*value).length = 0;
83             assumeSafeAppend(*value);
84         }
85         else static if (isPrimitiveType!(T))
86         {
87             *value = T.init;
88         }
89 
90         return is(T == class) || !isReferenceType!(T);
91     }
92 }