Esempio n. 1
0
/*
 This gets a single data item and decodes it including preceding optional tagging. This does not
 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
 maps are handled at the next level up in GetNext().

 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
    a few forms of invalid encoded CBOR
 */
static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, const QCBORStringAllocator *pAlloc)
{
   // Stack usage: int/ptr 3 -- 24
   QCBORError nReturn;

   // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
   // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
   int      uMajorType;
   uint64_t uNumber;
   uint8_t  uAdditionalInfo;

   nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);

   // Error out here if we got into trouble on the type and number.
   // The code after this will not work if the type and number is not good.
   if(nReturn)
      goto Done;

   memset(pDecodedItem, 0, sizeof(QCBORItem));

   // At this point the major type and the value are valid. We've got the type and the number that
   // starts every CBOR data item.
   switch (uMajorType) {
      case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
      case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
         nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
         break;

      case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
      case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
         if(uAdditionalInfo == LEN_IS_INDEFINITE) {
            pDecodedItem->uDataType  = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
            pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
         } else {
            nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
         }
         break;

      case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
      case CBOR_MAJOR_TYPE_MAP:   // Major type 5
         // Record the number of items in the array or map
         if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
            nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
            goto Done;
         }
         if(uAdditionalInfo == LEN_IS_INDEFINITE) {
            pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
         } else {
            pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
         }
         pDecodedItem->uDataType  = uMajorType; // C preproc #if above makes sure constants align
         break;

      case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
         pDecodedItem->val.uTagV = uNumber;
         pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
         break;

      case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
         nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
         break;

      default: // Should never happen because DecodeTypeAndNumber() should never return > 7
         nReturn = QCBOR_ERR_UNSUPPORTED;
         break;
   }

Done:
   return nReturn;
}
Esempio n. 2
0
private boolean_t LineDecode( file_t *f, int page, line_t *line )
{
  int idx, w, width, hptr, line_size;
  boolean_t simple;
  byte *str;

  str = FileLoadLine( f, &idx, &simple );
  if( 0 == idx )
    return FALSE;

  line_size = idx / 16 + 1;	/* physical lines per logical line */

  if( line->istr )
    IstrFree( line->istr );

  if( line->head )
    free( line->head );
  line->head = (head_t *)Malloc( sizeof( head_t ) * line_size );

  if( TRUE == simple ){
    line->istr = DecodeSimple( IstrAlloc( page, idx + 1 ),
			      str, &idx );
    FileFreeLine( f );

    hptr = 0;
    w = f->width;
    width = idx;
    while( w < idx ){
      if( hptr >= line_size - 1 ){
	width = f->width;
	idx = w;
	line_truncated = TRUE;
	break;
      }
      line->head[ hptr ].width = f->width;
      line->head[ hptr++ ].ptr = w;
      width = idx - w;
      w += f->width;
    }
  } else {
    line->istr = Decode( IstrAlloc( page, idx + 1 ),
			f->inputCodingSystem, str, &idx );
    FileFreeLine( f );

    hptr = 0;
    width = 0;
    for( idx = 0 ; NOSET != line->istr[ idx ].charset ; idx++ ){
      if( HTAB == line->istr[ idx ].charset ){
	w = HTAB_WIDTH - width % HTAB_WIDTH;
	line->istr[ idx ].c &= 0x00ff;
	line->istr[ idx ].c |= ( w << 8 );
	if( width + w == f->width ){
	  if( hptr >= line_size - 1 ){
	    idx++;
	    line_truncated = TRUE;
	    break;
	  }
	  line->head[ hptr ].width = width;
	  line->head[ hptr++ ].ptr = idx + 1;
	  width = 0;
	  continue;
	}
      } else {
	w = IcharWidth( line->istr[ idx ].charset, line->istr[ idx ].c );
      }
      if( width + w > f->width ){
	if( hptr >= line_size - 1 ){
	  line_truncated = TRUE;
	  break;
	}
	line->head[ hptr ].width = width;
	line->head[ hptr++ ].ptr = idx;
	width = w;
      } else {
	width += w;
      }
    }
  }

  line->head[ hptr ].width = width;
  line->head[ hptr++ ].ptr = idx;
  line->heads = hptr;

  line->head = (head_t *)realloc( line->head, sizeof( head_t ) * hptr );
  if( NULL == line->head ){
    fprintf( stderr, "lv: realloc() failed\n" );
    exit( -1 );
  }

  if( NULL != f->find.pattern )
    (*find_func)( line );

  return TRUE;
}