static TA_RetCode buildReadOp( TA_ReadOpInfo *readOpInfo, const char *localBuf, TA_ReadOp *readOp, TA_TokenId *tokenId, unsigned int *intraDayIncrementInSeconds ) { TA_PROLOG TA_TokenId id; TA_ReadOp tmpReadOp; TA_RetCode retCode; TA_Integer optionalParam; unsigned int mult, intraDayIncrement; TA_TRACE_BEGIN( buildReadOp ); if( !readOp || !intraDayIncrementInSeconds || !tokenId ) { TA_TRACE_RETURN( TA_INTERNAL_ERROR(9) ); } *intraDayIncrementInSeconds = 0; *readOp = 0; *tokenId = 0; retCode = findTokenId( localBuf, &id, &optionalParam ); if( retCode != TA_SUCCESS ) { TA_TRACE_RETURN( retCode ); } TA_ASSERT( id != TA_TOK_END ); /* Trap special token not generating a TA_ReadOp. */ if( id == TA_TOK_SKIP_N_HEADER_LINE ) { if( optionalParam == 0 ) { TA_TRACE_RETURN( TA_INVALID_FIELD ); } readOpInfo->nbHeaderLineToSkip = optionalParam; TA_TRACE_RETURN( TA_SUCCESS ); } if( id == TA_TOK_SKIP_NON_DIGIT_LINE ) { if( optionalParam != 1 ) { TA_TRACE_RETURN( TA_INVALID_FIELD ); } TA_TRACE_RETURN( TA_SUCCESS ); } /* Integer or Real operation? */ switch( id ) { case TA_TOK_OPEN: case TA_TOK_HIGH: case TA_TOK_LOW: case TA_TOK_CLOSE: case TA_TOK_SKIP_N_REAL: tmpReadOp = TA_CMD_READ_REAL; break; case TA_TOK_YYYY: case TA_TOK_YY: case TA_TOK_Y: case TA_TOK_M: case TA_TOK_MM: case TA_TOK_MMM: case TA_TOK_D: case TA_TOK_DD: case TA_TOK_VOLUME: case TA_TOK_OPENINTEREST: case TA_TOK_HOUR: case TA_TOK_MIN: case TA_TOK_SEC: case TA_TOK_HH: case TA_TOK_MN: case TA_TOK_SS: case TA_TOK_SKIP_N_INTEGER: tmpReadOp = TA_CMD_READ_INTEGER; break; case TA_TOK_SKIP_N_CHAR: case TA_TOK_SKIP_NON_DIGIT_LINE: tmpReadOp = 0; break; default: TA_TRACE_RETURN( TA_INVALID_FIELD ); } /* Is this a permanent skip operation? */ switch( id ) { case TA_TOK_SKIP_N_CHAR: case TA_TOK_SKIP_N_INTEGER: case TA_TOK_SKIP_N_REAL: TA_SET_PERMANENT_SKIP_FLAG( tmpReadOp ); TA_SET_SKIP_FLAG( tmpReadOp ); break; default: TA_CLR_PERMANENT_SKIP_FLAG( tmpReadOp ); TA_CLR_SKIP_FLAG( tmpReadOp ); } /* Set the "numeric" parameter */ switch( id ) { case TA_TOK_SKIP_N_INTEGER: case TA_TOK_SKIP_N_REAL: case TA_TOK_SKIP_N_CHAR: TA_SET_NB_NUMERIC( tmpReadOp, optionalParam ); break; case TA_TOK_OPENINTEREST: readOpInfo->openInterestMult = optionalParam; TA_SET_NB_NUMERIC( tmpReadOp, 0 ); break; case TA_TOK_VOLUME: readOpInfo->volumeMult = optionalParam; TA_SET_NB_NUMERIC( tmpReadOp, 0 ); break; default: TA_SET_NB_NUMERIC( tmpReadOp, TA_TokenMaxSize(id) ); break; } /* Set the index information. */ switch( id ) { case TA_TOK_YYYY: case TA_TOK_YY: case TA_TOK_Y: TA_SET_IDX( tmpReadOp, TA_YEAR_IDX ); break; case TA_TOK_M: case TA_TOK_MM: case TA_TOK_MMM: TA_SET_IDX( tmpReadOp, TA_MONTH_IDX ); break; case TA_TOK_D: case TA_TOK_DD: TA_SET_IDX( tmpReadOp, TA_DAY_IDX ); break; case TA_TOK_OPEN: TA_SET_IDX( tmpReadOp, TA_OPEN_IDX ); break; case TA_TOK_HIGH: TA_SET_IDX( tmpReadOp, TA_HIGH_IDX ); break; case TA_TOK_LOW: TA_SET_IDX( tmpReadOp, TA_LOW_IDX ); break; case TA_TOK_CLOSE: TA_SET_IDX( tmpReadOp, TA_CLOSE_IDX ); break; case TA_TOK_VOLUME: TA_SET_IDX( tmpReadOp, TA_VOLUME_IDX ); break; case TA_TOK_OPENINTEREST: TA_SET_IDX( tmpReadOp, TA_OPENINTEREST_IDX ); break; case TA_TOK_HOUR: case TA_TOK_HH: TA_SET_IDX( tmpReadOp, TA_HOUR_IDX ); break; case TA_TOK_MIN: case TA_TOK_MN: TA_SET_IDX( tmpReadOp, TA_MIN_IDX ); break; case TA_TOK_SEC: case TA_TOK_SS: TA_SET_IDX( tmpReadOp, TA_SEC_IDX ); break; default: /* Do nothing. */ break; } /* Set a special flag for the TA_TOK_MMM because * it must do chat to integer processing. */ if( id == TA_TOK_MMM ) tmpReadOp |= TA_CMD_READ_MONTH_CHAR; /* Identify the time increments. */ mult = 1; intraDayIncrement = 0; switch( id ) { case TA_TOK_HOUR: case TA_TOK_HH: mult *= 60; case TA_TOK_MIN: case TA_TOK_MN: mult *= 60; case TA_TOK_SEC: case TA_TOK_SS: if( optionalParam < 1 ) { /* Shall be at least '1'... */ TA_TRACE_RETURN( TA_INVALID_FIELD ); } else if( optionalParam > 1 ) { /* When the default '1' is specified, do * not return the increment to the caller. */ intraDayIncrement = optionalParam * mult; } break; default: /* Do nothing */ break; } /* Everything is fine, return the info to the caller. */ *readOp = tmpReadOp; *intraDayIncrementInSeconds = intraDayIncrement; *tokenId = id; TA_TRACE_RETURN( TA_SUCCESS ); }
/**** Global functions definitions. ****/ TA_RetCode TA_ReadOp_Optimize( TA_ReadOpInfo *readOpInfo, TA_Period period, TA_Field fieldToAlloc ) { TA_PROLOG TA_ReadOp *lastOp; unsigned int tmpIdx; unsigned int i, nbReadOp; unsigned int flagSet; TA_Field field; TA_ReadOp *readOp; TA_TRACE_BEGIN( TA_OptimizeReadOp ); TA_ASSERT( fieldToAlloc != 0 ); nbReadOp = readOpInfo->nbReadOp; readOp = readOpInfo->arrayReadOp; /* Skip all fields not requested. */ for( i=0; i < nbReadOp; i++ ) { if( TA_IS_PERMANENT_SKIP_SET(readOp[i]) ) { TA_SET_SKIP_FLAG(readOp[i]); } else { TA_CLR_SKIP_FLAG(readOp[i]); field = TA_ReadOpToField( readOp[i] ); if( field == TA_TIMESTAMP ) { tmpIdx = TA_GET_IDX(readOp[i]); switch( period ) { case TA_YEARLY: /* No need for anything shorter than year in the timestamp. */ if( tmpIdx <= TA_MONTH_IDX ) { TA_SET_SKIP_FLAG(readOp[i]); TA_SET_NB_NUMERIC(readOp[i],1); } break; case TA_MONTHLY: /* No need for anything shorter than days in the timestamp. */ if( tmpIdx <= TA_DAY_IDX ) { TA_SET_SKIP_FLAG(readOp[i]); TA_SET_NB_NUMERIC(readOp[i],1); } break; case TA_DAILY: /* No need for hour,min,sec in the timestamp. */ if( tmpIdx <= TA_HOUR_IDX ) { TA_SET_SKIP_FLAG(readOp[i]); TA_SET_NB_NUMERIC(readOp[i],1); } break; default: /* Do nothing. */ break; } } else if( !(field&fieldToAlloc) ) { /* This field is not requested for being allocated. */ TA_SET_SKIP_FLAG(readOp[i]); TA_SET_NB_NUMERIC(readOp[i],1); } } } TA_ASSERT( TA_IS_LAST_SET(readOp[nbReadOp-1]) ); /* Determine the last needed field. Mark it with the STOP flag. * Make sure all previous get their STOP flag clear. */ flagSet = 0; for( i=nbReadOp; i > 0; i-- ) { lastOp = &readOp[i-1]; if( flagSet ) { TA_CLR_READ_STOP_FLAG(*lastOp); } else { TA_SET_READ_STOP_FLAG(*lastOp); if( !TA_IS_SKIP_SET(*lastOp) ) flagSet = 1; } } TA_TRACE_RETURN( TA_SUCCESS ); }