1 #ifndef TA_MEMORY_H
2 #define TA_MEMORY_H
3 
4 #if !defined( _MANAGED ) && !defined( _JAVA )
5    #ifndef TA_COMMON_H
6       #include "ta_common.h"
7    #endif
8 
9    #include <stdlib.h>
10 
11    /* Interface macros */
12    #define TA_Malloc(a)       malloc(a)
13    #define TA_Realloc(a,b)    realloc((a),(b))
14    #define TA_Free(a)         free(a)
15 
16    #define FREE_IF_NOT_NULL(x) { if((x)!=NULL) {TA_Free((void *)(x)); (x)=NULL;} }
17 
18 #endif /* !defined(_MANAGED) && !defined( _JAVA ) */
19 
20 
21 /* ARRAY : Macros to manipulate arrays of value type.
22  *
23  * Using temporary array of double and integer are often needed for the
24  * TA functions.
25  *
26  * These macros allow basic operations to alloc/copy/free array of value type.
27  *
28  * These macros works in plain old C/C++, managed C++.and Java.
29  *
30  * (Use ARRAY_REF and ARRAY_INT_REF for double/integer arrays).
31  */
32 #if defined( _MANAGED )
33    #define ARRAY_VTYPE_REF(type,name)             cli::array<type>^ name
34    #define ARRAY_VTYPE_LOCAL(type,name,size)      cli::array<type>^ name = gcnew cli::array<type>(size)
35    #define ARRAY_VTYPE_ALLOC(type,name,size)      name = gcnew cli::array<type>(size)
36    #define ARRAY_VTYPE_COPY(type,dest,src,size)   cli::array<type>::Copy( src, 0, dest, 0, size )
37    #define ARRAY_VTYPE_MEMMOVE(type,dest,destIdx,src,srcIdx,size) cli::array<type>::Copy( src, srcIdx, dest, destIdx, size )
38    #define ARRAY_VTYPE_FREE(type,name)
39    #define ARRAY_VTYPE_FREE_COND(type,cond,name)
40 #elif defined( _JAVA )
41    #define ARRAY_VTYPE_REF(type,name)             type []name
42    #define ARRAY_VTYPE_LOCAL(type,name,size)      type []name = new type[size]
43    #define ARRAY_VTYPE_ALLOC(type,name,size)      name = new type[size]
44    #define ARRAY_VTYPE_COPY(type,dest,src,size)   System.arraycopy(src,0,dest,0,size)
45    #define ARRAY_VTYPE_MEMMOVE(type,dest,destIdx,src,srcIdx,size) System.arraycopy(src,srcIdx,dest,destIdx,size)
46    #define ARRAY_VTYPE_FREE(type,name)
47    #define ARRAY_VTYPE_FREE_COND(type,cond,name)
48 #else
49    #define ARRAY_VTYPE_REF(type,name)             type *name
50    #define ARRAY_VTYPE_LOCAL(type,name,size)      type name[size]
51    #define ARRAY_VTYPE_ALLOC(type,name,size)      name = (type *)TA_Malloc( sizeof(type)*(size))
52    #define ARRAY_VTYPE_COPY(type,dest,src,size)   memcpy(dest,src,sizeof(type)*(size))
53    #define ARRAY_VTYPE_MEMMOVE(type,dest,destIdx,src,srcIdx,size) memmove( &dest[destIdx], &src[srcIdx], (size)*sizeof(type) )
54    #define ARRAY_VTYPE_FREE(type,name)            TA_Free(name)
55    #define ARRAY_VTYPE_FREE_COND(type,cond,name)  if( cond ){ TA_Free(name); }
56 #endif
57 
58 /* ARRAY : Macros to manipulate arrays of double. */
59 #define ARRAY_REF(name)             ARRAY_VTYPE_REF(double,name)
60 #define ARRAY_LOCAL(name,size)      ARRAY_VTYPE_LOCAL(double,name,size)
61 #define ARRAY_ALLOC(name,size)      ARRAY_VTYPE_ALLOC(double,name,size)
62 #define ARRAY_COPY(dest,src,size)   ARRAY_VTYPE_COPY(double,dest,src,size)
63 #define ARRAY_MEMMOVE(dest,destIdx,src,srcIdx,size) ARRAY_VTYPE_MEMMOVE(double,dest,destIdx,src,srcIdx,size)
64 #define ARRAY_FREE(name)            ARRAY_VTYPE_FREE(double,name)
65 #define ARRAY_FREE_COND(cond,name)  ARRAY_VTYPE_FREE_COND(double,cond,name)
66 
67 /* ARRAY : Macros to manipulate arrays of integer. */
68 #define ARRAY_INT_REF(name)             ARRAY_VTYPE_REF(int,name)
69 #define ARRAY_INT_LOCAL(name,size)      ARRAY_VTYPE_LOCAL(int,name,size)
70 #define ARRAY_INT_ALLOC(name,size)      ARRAY_VTYPE_ALLOC(int,name,size)
71 #define ARRAY_INT_COPY(dest,src,size)   ARRAY_VTYPE_COPY(int,dest,src,size)
72 #define ARRAY_INT_MEMMOVE(dest,destIdx,src,srcIdx,size) ARRAY_VTYPE_MEMMOVE(int,dest,destIdx,src,srcIdx,size)
73 #define ARRAY_INT_FREE(name)            ARRAY_VTYPE_FREE(int,name)
74 #define ARRAY_INT_FREE_COND(cond,name)  ARRAY_VTYPE_FREE_COND(int,cond,name)
75 
76 /* Access to "Globals"
77  *
78  * The globals here just means that these variables are accessible from
79  * all technical analysis functions.
80  *
81  * Depending of the language/platform, the globals might be in reality
82  * a private member variable of an object...
83  */
84 #if defined( _MANAGED )
85    #define TA_GLOBALS_UNSTABLE_PERIOD(x,y) (Globals->unstablePeriod[(int)(FuncUnstId::y)])
86    #define TA_GLOBALS_COMPATIBILITY        (Globals->compatibility)
87 #elif defined( _JAVA )
88    #define TA_GLOBALS_UNSTABLE_PERIOD(x,y) (this.unstablePeriod[FuncUnstId.y.ordinal()])
89    #define TA_GLOBALS_COMPATIBILITY        (this.compatibility)
90 #else
91    #define TA_GLOBALS_UNSTABLE_PERIOD(x,y) (TA_Globals->unstablePeriod[x])
92    #define TA_GLOBALS_COMPATIBILITY        (TA_Globals->compatibility)
93 #endif
94 
95 
96 
97 /* CIRCBUF : Circular Buffer Macros.
98  *
99  * The CIRCBUF is like a FIFO buffer (First In - First Out), except
100  * that the rate of data coming out is the same as the rate of
101  * data coming in (for simplification and speed optimization).
102  * In other word, when you add one new value, you must also consume
103  * one value (if not consume, the value is lost).
104  *
105  * The CIRCBUF size is unlimited, so it will automatically allocate and
106  * de-allocate memory as needed. In C/C++. when small enough, CIRCBUF will
107  * instead use a buffer "allocated" on the stack (automatic variable).
108  *
109  * Multiple CIRCBUF can be used within the same function. To make that
110  * possible the first parameter of the MACRO is an "Id" that can be
111  * any string.
112  *
113  * The macros offer the advantage to work in C/C++ and managed C++.
114  *
115  * CIRCBUF_PROLOG(Id,Type,Size);
116  *          Will declare all the needed variables. 2 variables are
117  *          important:
118  *                 1) 'Id' will be a ptr of the specified Type.
119  *                 2) 'Id'_Idx indicates from where to consume and
120  *                     to add the data.
121  *
122  *          Important: You must consume the oldest data before
123  *                     setting the new data!
124  *
125  *          The Size must be reasonable since it might "allocate"
126  *          an array of this size on the stack (each element are 'Type').
127  *
128  * CIRCBUF_CONSTRUCT(Id,Type,Size);
129  *         Must be called prior to use the remaining macros. Must be
130  *         followed by CIRCBUF_DESTROY when leaving the function.
131  *         The Size here can be large. If the static Size specified
132  *         with CIRCBUF_PROLOG is not sufficient, this MACRO will
133  *         allocate a new buffer from the Heap.
134  *
135  * CIRCBUF_DESTROY(Id,Size);
136  *         Must be call prior to leave the function.
137  *
138  * CIRCBUF_NEXT(Id);
139  *         Move forward the indexes.
140  *
141  * Example:
142  *     TA_RetCode MyFunc( int size )
143  *     {
144  *        CIRCBUF_PROLOG(MyBuf,int,4);
145  *        int i, value;
146  *        ...
147  *        CIRCBUF_CONSTRUCT(MyBuf,int,size);
148  *        ...
149  *        // 1st Loop: Fill MyBuf with initial values
150  *        //           (must be done).
151  *        value = 0;
152  *        for( i=0; i < size; i++ )
153  *        {
154  *           // Set the data
155  *           MyBuf[MyBuf_Idx] = value++;
156  *           CIRCBUF_NEXT(MyBuf);
157  *        }
158  *
159  *        // 2nd Loop: Get and Add subsequent values
160  *        //           in MyBuf (optional)
161  *        for( i=0; i < 3; i++ )
162  *        {
163  *           // Consume the data (must be done first)
164  *           printf( "%d ", MyBuf[MyBuf_Idx] );
165  *
166  *           // Set the new data (must be done second)
167  *           MyBuf[MyBuf_Idx] = value++;
168  *
169  *           // Move the index forward
170  *           CIRCBUF_NEXT(MyBuf);
171  *        }
172  *
173  *        // 3rd Loop: Empty MyBuf (optional)
174  *        for( i=0; i < size; i++ )
175  *        {
176  *           printf( "%d ", MyBuf[MyBuf_Idx] );
177  *           CIRCBUF_NEXT(MyBuf);
178  *        }
179  *
180  *        CIRCBUF_DESTROY(MyBuf);
181  *        return TA_SUCCESS;
182  *     }
183  *
184  *
185  * A call to MyFunc(5) will output:
186  *    0 1 2 3 4 5 6 7
187  *
188  * The value 0 to 4 are added by the 1st loop.
189  * The value 5 to 7 are added by the 2nd loop.
190  *
191  * The value 0 to 2 are displayed by the 2nd loop.
192  * The value 3 to 7 are displayed by the 3rd loop.
193  *
194  * Because the size 5 is greater than the
195  * value provided in CIRCBUF_PROLOG, a buffer will
196  * be dynamically allocated (and freed).
197  */
198 #if defined( _MANAGED )
199 
200 #define CIRCBUF_PROLOG(Id,Type,Size) int Id##_Idx = 0; \
201                                      cli::array<Type>^ Id; \
202                                      int maxIdx_##Id = (Size-1)
203 
204 /* Use this macro instead if the Type is a class or a struct. */
205 #define CIRCBUF_PROLOG_CLASS(Id,Type,Size) int Id##_Idx = 0; \
206                                            cli::array<Type^>^ Id; \
207                                            int maxIdx_##Id = (Size-1)
208 
209 #define CIRCBUF_INIT(Id,Type,Size) \
210    { \
211       if( Size <= 0 ) \
212          return ENUM_VALUE(RetCode,TA_ALLOC_ERR,AllocErr); \
213       Id = gcnew cli::array<Type>(Size); \
214       if( !Id ) \
215          return ENUM_VALUE(RetCode,TA_ALLOC_ERR,AllocErr); \
216       maxIdx_##Id = (Size-1); \
217    }
218 
219 #define CIRCBUF_INIT_CLASS(Id,Type,Size) \
220    { \
221       if( Size <= 0 ) \
222          return ENUM_VALUE(RetCode,TA_ALLOC_ERR,AllocErr); \
223       Id = gcnew cli::array<Type^>(Size); \
224       for( int _##Id##_index=0; _##Id##_index<Id->Length; _##Id##_index++) \
225       { \
226          Id[_##Id##_index]=gcnew Type(); \
227       } \
228       if( !Id ) \
229          return ENUM_VALUE(RetCode,TA_ALLOC_ERR,AllocErr); \
230       maxIdx_##Id = (Size-1); \
231    }
232 
233 #define CIRCBUF_INIT_LOCAL_ONLY(Id,Type) \
234    { \
235       Id = gcnew cli::array<Type>(maxIdx_##Id+1); \
236       if( !Id ) \
237          return ENUM_VALUE(RetCode,TA_ALLOC_ERR,AllocErr); \
238    }
239 
240 #define CIRCBUF_DESTROY(Id)
241 
242 /* Use this macro to access the member when type is a class or a struct. */
243 #define CIRCBUF_REF(x) (x)->
244 
245 #elif defined(_JAVA)
246 
247 #define CIRCBUF_PROLOG(Id,Type,Size) int Id##_Idx = 0; \
248                                      Type []Id; \
249                                      int maxIdx_##Id = (Size-1)
250 
251 /* Use this macro instead if the Type is a class or a struct. */
252 #define CIRCBUF_PROLOG_CLASS(Id,Type,Size) int Id##_Idx = 0; \
253                                            Type []Id; \
254                                            int maxIdx_##Id = (Size-1)
255 
256 #define CIRCBUF_INIT(Id,Type,Size) \
257    { \
258       if( Size <= 0 ) \
259          return ENUM_VALUE(RetCode,TA_ALLOC_ERR,AllocErr); \
260       Id = new Type[Size]; \
261       maxIdx_##Id = (Size-1); \
262    }
263 
264 #define CIRCBUF_INIT_CLASS(Id,Type,Size) \
265    { \
266       if( Size <= 0 ) \
267          return ENUM_VALUE(RetCode,TA_ALLOC_ERR,AllocErr); \
268       Id = new Type[Size]; \
269       for( int _##Id##_index=0; _##Id##_index<Id.length; _##Id##_index++) \
270       { \
271          Id[_##Id##_index]=new Type(); \
272       } \
273       maxIdx_##Id = (Size-1); \
274    }
275 
276 #define CIRCBUF_INIT_LOCAL_ONLY(Id,Type) \
277    { \
278       Id = new Type[maxIdx_##Id+1]; \
279    }
280 
281 #define CIRCBUF_DESTROY(Id)
282 
283 /* Use this macro to access the member when type is a class or a struct. */
284 #define CIRCBUF_REF(x) (x).
285 
286 #else
287 
288 #define CIRCBUF_PROLOG(Id,Type,Size) Type local_##Id[Size]; \
289                                   int Id##_Idx; \
290                                   Type *Id; \
291                                   int maxIdx_##Id
292 
293 /* Use this macro instead if the Type is a class or a struct. */
294 #define CIRCBUF_PROLOG_CLASS(Id,Type,Size) CIRCBUF_PROLOG(Id,Type,Size)
295 
296 #define CIRCBUF_INIT(Id,Type,Size) \
297    { \
298       if( Size < 1 ) \
299          return TA_INTERNAL_ERROR(137); \
300       if( (int)Size > (int)(sizeof(local_##Id)/sizeof(Type)) ) \
301       { \
302          Id = TA_Malloc( sizeof(Type)*Size ); \
303          if( !Id ) \
304             return TA_ALLOC_ERR; \
305       } \
306       else \
307          Id = &local_##Id[0]; \
308       maxIdx_##Id = (Size-1); \
309       Id##_Idx = 0; \
310    }
311 
312 #define CIRCBUF_INIT_CLASS(Id,Type,Size) CIRCBUF_INIT(Id,Type,Size)
313 
314 #define CIRCBUF_INIT_LOCAL_ONLY(Id,Type) \
315    { \
316       Id = &local_##Id[0]; \
317       maxIdx_##Id = (int)(sizeof(local_##Id)/sizeof(Type))-1; \
318       Id##_Idx = 0; \
319    }
320 
321 #define CIRCBUF_DESTROY(Id) \
322    { \
323       if( Id != &local_##Id[0] ) \
324          TA_Free( Id ); \
325    }
326 
327 /* Use this macro to access the member when Type is a class or a struct. */
328 #define CIRCBUF_REF(x) (x).
329 
330 #endif
331 
332 #define CIRCBUF_NEXT(Id) \
333    { \
334       Id##_Idx++; \
335       if( Id##_Idx > maxIdx_##Id ) \
336          Id##_Idx = 0; \
337    }
338 
339 
340 #endif
341 
342