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