Logo Search packages:      
Sourcecode: djvulibre version File versions

int IFFByteStream::get_chunk ( GUTF8String chkid,
int *  rawoffsetptr = 0,
int *  rawsizeptr = 0 
)

Enters a chunk for reading. Function get_chunk# returns zero when the last chunk has already been accessed. Otherwise it parses a chunk header, positions the IFFByteStream at the beginning of the chunk data, stores the extended chunk identifier into string chkid#, and returns the non zero chunk size. The file offset of the chunk data may be retrieved using function tell#. The chunk data can then be read using function read# until reaching the end of the chunk. Advanced users may supply two pointers to integer variables using arguments rawoffsetptr# and rawsizeptr#. These variables will be overwritten with the offset and the length of the file segment containing both the chunk header and the chunk data.

Definition at line 169 of file IFFByteStream.cpp.

References check_id(), composite(), ByteStream::EndOfFile, has_magic, ByteStream::read(), ByteStream::readall(), ByteStream::seek(), and ByteStream::size().

Referenced by compare(), DjVuFile::contains_anno(), DjVuFile::contains_chunk(), DjVuFile::contains_meta(), DjVuFile::contains_text(), DjVuAnno::decode(), DjVuFile::get_chunk_name(), DjVuFile::get_chunks_number(), DjVmDoc::get_data(), DjVuFile::insert_file(), GIFFManager::load_chunk(), GIFFManager::load_file(), DjVuFile::process_incl_chunks(), DjVmDoc::read(), DjVuFile::remove_anno(), DjVuFile::remove_meta(), DjVuFile::remove_text(), DjVuFile::unlink_file(), and DjVuImage::writeXML().

{
  int bytes;
  char buffer[8];
  
  // Check that we are allowed to read a chunk
  if (dir > 0)
    G_THROW( ERR_MSG("IFFByteStream.read_write") );
  if (ctx && !ctx->bComposite)
    G_THROW( ERR_MSG("IFFByteStream.not_ready") );
  dir = -1;

  // Seek to end of previous chunk if necessary
  if (seekto > offset)
    {
      bs->seek(seekto);
      offset = seekto;
    }

  // Skip padding byte
  if (ctx && offset == ctx->offEnd)
    return 0;
  if (offset & 1)
    {
      bytes = bs->read( (void*)buffer, 1);
      if (bytes==0 && !ctx)
        return 0;
      offset += bytes;
    }
  
  // Record raw offset
  int rawoffset = offset;
  
  // Read chunk id (skipping magic sequences inserted here to make
  // DjVu files recognizable.)
  for(;;)
  {
    if (ctx && offset == ctx->offEnd)
      return 0;
    if (ctx && offset+4 > ctx->offEnd)
      G_THROW( ERR_MSG("IFFByteStream.corrupt_end") );
    bytes = bs->readall( (void*)&buffer[0], 4);
    offset = seekto = offset + bytes;
    if (bytes==0 && !ctx)
      return 0;
    if (bytes != 4)
      G_THROW( ByteStream::EndOfFile );
    if(buffer[0] != 0x41 || buffer[1] != 0x54 ||
       buffer[2] != 0x26 || buffer[3] != 0x54 )
      break;
    has_magic=true;
  }
  
  // Read chunk size
  if (ctx && offset+4 > ctx->offEnd)
    G_THROW( ERR_MSG("IFFByteStream.corrupt_end2") );
  bytes = bs->readall( (void*)&buffer[4], 4);
  offset = seekto = offset + bytes;
  if (bytes != 4)
    G_THROW( ByteStream::EndOfFile );
  long size = ((unsigned char)buffer[4]<<24) |
              ((unsigned char)buffer[5]<<16) |
              ((unsigned char)buffer[6]<<8)  |
              ((unsigned char)buffer[7]);
  if (ctx && offset+size > ctx->offEnd)
    G_THROW( ERR_MSG("IFFByteStream.corrupt_mangled") );
  
  // Check if composite 
  int composite = check_id(buffer);
  if (composite < 0)
    G_THROW( ERR_MSG("IFFByteStream.corrupt_id") );
  
  // Read secondary id of composite chunk
  if (composite)
  {
    if (ctx && ctx->offEnd<offset+4)
      G_THROW( ERR_MSG("IFFByteStream.corrupt_header") );
    bytes = bs->readall( (void*)&buffer[4], 4);
    offset += bytes;
    if (bytes != 4)
      G_THROW( ByteStream::EndOfFile );
    if (check_id(&buffer[4]))
      G_THROW( ERR_MSG("IFFByteStream.corrupt_2nd_id") );
  }

  // Create context record
  IFFContext *nctx = new IFFContext;
  G_TRY
  {
    nctx->next = ctx;
    nctx->offStart = seekto;
    nctx->offEnd = seekto + size;
    if (composite)
    {
      memcpy( (void*)(nctx->idOne), (void*)&buffer[0], 4);
      memcpy( (void*)(nctx->idTwo), (void*)&buffer[4], 4);
      nctx->bComposite = 1;
    }
    else
    {
      memcpy( (void*)(nctx->idOne), (void*)&buffer[0], 4);
      memset( (void*)(nctx->idTwo), 0, 4);
      nctx->bComposite = 0;
    }
  }
  G_CATCH_ALL
  {
    delete nctx;
    G_RETHROW;
  }
  G_ENDCATCH;
  
  // Install context record
  ctx = nctx;
  chkid = GUTF8String(ctx->idOne, 4);
  if (composite)
    chkid = chkid + ":" + GUTF8String(ctx->idTwo, 4);

  // Return
  if (rawoffsetptr)
    *rawoffsetptr = rawoffset;
  if (rawsizeptr)
    *rawsizeptr = ( ctx->offEnd - rawoffset + 1) & ~0x1;
  return size;
}


Generated by  Doxygen 1.6.0   Back to index