Beispiel #1
0
TA_RetCode TA_ReadOpInfoAlloc( const char *sourceInfo,
                               TA_ReadOpInfo **allocatedInfo,
                               unsigned int readOpFlags )
{
   TA_PROLOG
   TA_RetCode retCode;

   TA_ReadOp readOp;
   TA_ReadOp *arrayReadOp;
   TA_ReadOpInfo *newReadOpInfo;
   TA_Field fieldMask, fieldProvided;
   unsigned int timeframeIdx;
   unsigned int intraDayIncPeriod;
   TA_TokenId   intraDayIncToken;
   TA_TokenId   tempToken;
   unsigned int tempInt;
   unsigned int period;
   unsigned int errorOccurred;

   const char *pos;
   unsigned int inField;
   unsigned int nbField;
   unsigned int nbCharInField;
   unsigned int skipNonDigitLine;
   const char *ptrFirstCarInField;

   unsigned char localBuf[10];
   unsigned int bufIdx, opIdx, i;

   register unsigned int flagSet;
   register TA_ReadOp *ptrReadOp;
   
   TA_TRACE_BEGIN(  TA_BuildArrayReadOp );

   newReadOpInfo = (TA_ReadOpInfo *)TA_Malloc( sizeof( TA_ReadOpInfo ) );

   /* These variables are resolved within this function. */
   memset( newReadOpInfo, 0, sizeof( TA_ReadOpInfo ) );

   /* At this point, TA_ReadOpInfoFree can be safely called. */

   /* Keep track of some user provided parameter. */
   newReadOpInfo->sourceInfo = sourceInfo;
   newReadOpInfo->readOpFlags = readOpFlags;

   /* Initialize some defaults. */
   newReadOpInfo->openInterestMult = 100;
   newReadOpInfo->volumeMult       = 100;

   nbField = 0;
   intraDayIncPeriod = 0;
   intraDayIncToken = TA_TOK_END;

   pos = newReadOpInfo->sourceInfo;
   if( !pos || (*pos == '\0') )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_MISSING_FIELD );
   }

   /* Find how many fields are defined and check some syntax
    * at the same time.
    */
   if( *pos != '[' )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_INVALID_FIELD );
   }

   inField = 0;
   nbCharInField = 0;
   skipNonDigitLine = 0;
   ptrFirstCarInField = NULL;
   while( *pos != '\0' )
   {
      switch( *pos )
      {
      case '[':
         if( inField )
         {
            TA_ReadOpInfoFree( newReadOpInfo );
            TA_TRACE_RETURN( TA_INVALID_FIELD );
         }
         inField = 1;
         break;
      case ']':
         if( (!inField) || (nbCharInField == 0) )
         {
            TA_ReadOpInfoFree( newReadOpInfo );
            TA_TRACE_RETURN( TA_INVALID_FIELD );
         }

         nbField++;

         /* Exclude fields not generating a TA_ReadOp.
          * For the time being that means only the -H and -NDL field.
          */
         if( nbCharInField >= 2 )
         {
            TA_ASSERT( ptrFirstCarInField != NULL );
            if( ptrFirstCarInField[0] == '-' ) 
            {
               if( toupper(ptrFirstCarInField[1]) == 'H' )
                  nbField--;
               else if( (toupper(ptrFirstCarInField[1]) == 'N') &&
                        (toupper(ptrFirstCarInField[2]) == 'D') &&
                        (toupper(ptrFirstCarInField[3]) == 'L') )
               {
                  skipNonDigitLine = 1;
                  nbField--;
               }               
             }
         }

         inField = 0;
         nbCharInField = 0;
         ptrFirstCarInField = NULL;
         break;
      default:
         if( !inField )
         {
            TA_ReadOpInfoFree( newReadOpInfo );
            TA_TRACE_RETURN( TA_INVALID_FIELD );
         }

         if( nbCharInField == 0 )
            ptrFirstCarInField = pos;
         nbCharInField++;
         break;
      }

      pos++;
   }

   if( inField || *(pos-1) != ']' )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_INVALID_FIELD );
   }

   /* Build the TA_ReadOp array */
   arrayReadOp = (TA_ReadOp *)TA_Malloc( sizeof( TA_ReadOp ) * nbField );

   if( !arrayReadOp )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   newReadOpInfo->arrayReadOp = arrayReadOp;

   pos = TA_StringToChar(newReadOpInfo->sourceInfo);

   bufIdx = 0;
   opIdx = 0;
   while( *pos != '\0' && (opIdx < nbField) )
   {
      switch( *pos )
      {
      case '[':
        break;

      case ']':
        localBuf[bufIdx] ='\0';
        bufIdx = 0;

        /* Identify the field and build the TA_ReadOp. */
        tempInt = 0;
        retCode = buildReadOp( newReadOpInfo,
                               (const char *)&localBuf[0],
                               &arrayReadOp[opIdx],
                               &tempToken, &tempInt );
        if( retCode != TA_SUCCESS )
        {
           TA_ReadOpInfoFree( newReadOpInfo );
           TA_TRACE_RETURN( retCode );
        }

        if( arrayReadOp[opIdx] != 0 )
        {
           /* Set the replace zero flag as needed */
           if( TA_IS_REPLACE_ZERO(readOpFlags) && TA_IS_REAL_CMD(arrayReadOp[opIdx]) )
           {
              TA_SET_REPLACE_ZERO(arrayReadOp[opIdx]);
           }

           /* Set the skipNonDigitLine flag as needed. */
           if( skipNonDigitLine == 1 )
           {
              TA_SET_SKIP_NDL_FLAG(arrayReadOp[opIdx]);
           }

           /* Ooof... this readOp is now all build! */
           opIdx++;
        }

        /* If this is a time token, make sure this
         * is not in contradiction with an already
         * specified increment.
         */
        if( intraDayIncPeriod )
        {
           errorOccurred = 0;
           switch( tempToken )
           {
           case TA_TOK_SEC:
           case TA_TOK_SS:
              if( (intraDayIncToken == TA_TOK_MIN) ||
                  (intraDayIncToken == TA_TOK_MN) )
                 errorOccurred = 1;
              /* no break */
           case TA_TOK_MIN:
           case TA_TOK_MN:
              if( (intraDayIncToken == TA_TOK_HOUR) ||
                  (intraDayIncToken == TA_TOK_HH) )
                 errorOccurred = 1;
              break;
           case TA_TOK_HOUR:
           case TA_TOK_HH:
              errorOccurred = 1;
              break;
           default:
              /* Do nothing */
              break;
           }

           if( errorOccurred )
           {
              TA_ReadOpInfoFree( newReadOpInfo );
              TA_TRACE_RETURN( TA_INVALID_FIELD );
           }
        }

        /* Check if a period increment is specified. */
        if( (tempInt != 0) && (tempInt != 1) )
        {
           if( intraDayIncPeriod != 0 )
           {
              TA_ReadOpInfoFree( newReadOpInfo );
              TA_TRACE_RETURN( TA_INVALID_FIELD );
           }

           intraDayIncPeriod = tempInt;
           intraDayIncToken  = tempToken;
        }
        break;

      default:
        if( bufIdx >= sizeof(localBuf)-1 )
        {
           TA_ReadOpInfoFree( newReadOpInfo );
           TA_TRACE_RETURN( TA_INVALID_FIELD );
        }

        localBuf[bufIdx++] = *pos;
        break;
      }

      pos++;
   }

   if( opIdx != nbField )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(89) );
   }

   arrayReadOp[opIdx-1] |= TA_CMD_LAST_FLAG;

   /* Build the mask representing the fields provided. */
   fieldProvided = 0;
   timeframeIdx = TA_INTEGER_ARRAY_SIZE;

   for( opIdx=0; opIdx < nbField; opIdx++ )
   {
      readOp = arrayReadOp[opIdx];

      TA_ASSERT( readOp != 0 ); /* Parano test */

      if( !TA_IS_PERMANENT_SKIP_SET(readOp) )
      {
         /* Make sure this field was not specified twice. */
         for( i=opIdx+1; i < nbField; i++ )
         {
            if( (TA_IS_REAL_CMD(readOp) && TA_IS_REAL_CMD(arrayReadOp[i])) ||
                (TA_IS_INTEGER_CMD(readOp) && TA_IS_INTEGER_CMD(arrayReadOp[i])) )
            {
               if( (TA_GET_IDX(readOp) == TA_GET_IDX(arrayReadOp[i])) &&
                   !TA_IS_PERMANENT_SKIP_SET(arrayReadOp[i]) )
               {
                  TA_ReadOpInfoFree( newReadOpInfo );
                  TA_TRACE_RETURN( TA_REDUNDANT_FIELD );
               }
            }
         }

         /* Parano test: Double-check redundant field in a different way. */
         fieldMask = TA_ReadOpToField( readOp );
         TA_ASSERT( fieldMask != 0 );
         if( !(fieldMask & TA_TIMESTAMP) && (fieldProvided & fieldMask) )
         {
            TA_ReadOpInfoFree( newReadOpInfo );
            TA_TRACE_RETURN( TA_REDUNDANT_FIELD );
         }

         /* Set the field. */
         fieldProvided |= fieldMask;

         /* Keep track of the smallest granularity of the timestamp. */
         if( fieldMask & TA_TIMESTAMP )
         {
            if( (timeframeIdx == TA_INTEGER_ARRAY_SIZE) ||
                (TA_GET_IDX(readOp) < timeframeIdx) )
               timeframeIdx = TA_GET_IDX(readOp);
         }
      }
   }


   /* No date/time reference provided!? This is considered an error
    * in the current implementation.
    */
   if( timeframeIdx == TA_INTEGER_ARRAY_SIZE )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_MISSING_DATE_OR_TIME_FIELD );
   }

   /* Determine at which point the timestamp is completed. */
   flagSet = 0;
   for( opIdx=nbField; opIdx > 0; opIdx-- )
   {
      ptrReadOp = &arrayReadOp[opIdx-1];
      readOp = *ptrReadOp;

      if( !flagSet                          && 
          TA_IS_INTEGER_CMD(readOp)         && 
          (TA_GET_IDX(readOp)<=TA_YEAR_IDX) && 
          !TA_IS_PERMANENT_SKIP_SET(readOp) )
      {
         TA_SET_TIMESTAMP_COMPLETE(*ptrReadOp);
         flagSet = 1;
      }
      else
      {
         TA_CLR_TIMESTAMP_COMPLETE(*ptrReadOp);
      }
   }

   /* Validate and identify the period. */
   period = 0;
   if( intraDayIncPeriod )
   {
      errorOccurred = 0;
      switch( timeframeIdx )
      {
      case TA_YEAR_IDX:
      case TA_MONTH_IDX:
      case TA_DAY_IDX:
         errorOccurred = 1;
         break;
      case TA_HOUR_IDX:
         if( (intraDayIncPeriod < TA_1HOUR) || (intraDayIncPeriod >= TA_DAILY) )
            errorOccurred = 1;
         break;
      case TA_MIN_IDX:
         if( (intraDayIncPeriod < TA_1MIN) || (intraDayIncPeriod >= TA_1HOUR) )
            errorOccurred = 1;
         break;
      case TA_SEC_IDX:
         if( (intraDayIncPeriod < TA_1SEC) || (intraDayIncPeriod >= TA_1MIN) )
            errorOccurred = 1;
         break;
      default:
         TA_ReadOpInfoFree( newReadOpInfo );
         TA_FATAL(  NULL, timeframeIdx, fieldProvided );
      }

      if( errorOccurred )
      {
         TA_ReadOpInfoFree( newReadOpInfo );
         TA_TRACE_RETURN( TA_INVALID_FIELD );
      }
            
      period = intraDayIncPeriod;
   }
   else
   {
      switch( timeframeIdx )
      {
      case TA_YEAR_IDX:
         period = TA_YEARLY;
         break;
      case TA_MONTH_IDX:
         period = TA_MONTHLY;
         break;
      case TA_DAY_IDX:
         period = TA_DAILY;
         break;
      case TA_HOUR_IDX:
         period = TA_1HOUR;
         break;
      case TA_MIN_IDX:
         period = TA_1MIN;
         break;
      case TA_SEC_IDX:
         period = TA_1SEC;
         break;
      default:
         TA_FATAL(  NULL, timeframeIdx, fieldProvided );
      }
   }

   /* A last check... */
   if( period == 0 )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_INVALID_FIELD );
   }
         
   /* Everything is fine, let's return the information. */
   newReadOpInfo->arrayReadOp = arrayReadOp;
   newReadOpInfo->fieldProvided = fieldProvided;
   newReadOpInfo->nbReadOp = nbField;
   newReadOpInfo->period = period;

   *allocatedInfo = newReadOpInfo;

   TA_TRACE_RETURN( TA_SUCCESS );
}
Beispiel #2
0
/**** 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 );
}