Logo Search packages:      
Sourcecode: djvulibre version File versions

void DjVmDir::decode ( const GP< ByteStream > &  stream  ) 

Decodes the directory from the specified stream.

Definition at line 213 of file DjVmDir.cpp.

References ByteStream::create(), ByteStream::read(), ByteStream::read16(), ByteStream::read24(), ByteStream::read32(), ByteStream::read8(), GArrayTemplate< TYPE >::resize(), and GArrayTemplate< TYPE >::size().

Referenced by DjVmDoc::read().

{
   ByteStream &str=*gstr;
   DEBUG_MSG("DjVmDir::decode(): decoding contents of 'DIRM' chunk...\n");
   DEBUG_MAKE_INDENT(3);
   
   GCriticalSectionLock lock(&class_lock);

   GPosition pos;

   files_list.empty();
   page2file.resize(-1);
   name2file.empty();
   id2file.empty();
   title2file.empty();

   int ver=str.read8();
   bool bundled=(ver & 0x80)!=0;
   ver&=0x7f;

   DEBUG_MSG("DIRM version=" << ver << ", our version=" << version << "\n");
   if (ver>version)
      G_THROW( ERR_MSG("DjVmDir.version_error") "\t" 
               + GUTF8String(version) + "\t" + GUTF8String(ver));
   // Unable to read DJVM directories of versions higher than xxx
   // Data version number is yyy.
   DEBUG_MSG("bundled directory=" << bundled << "\n");
   DEBUG_MSG("reading the directory records...\n");
   int files=str.read16();
   DEBUG_MSG("number of files=" << files << "\n");

   if (files)
   {
      DEBUG_MSG("reading offsets (and sizes for ver==0)\n");
      for(int nfile=0;nfile<files;nfile++)
      {
         GP<File> file=new File();
         files_list.append(file);
         if (bundled)
         {
            file->offset=str.read32();
            if (ver==0)
              file->size=str.read24();
            if (file->offset==0)
               G_THROW( ERR_MSG("DjVmDir.no_indirect") );
         } else
         {
           file->offset=file->size=0;
         }
      }

      GP<ByteStream> gbs_str=BSByteStream::create(gstr);
      ByteStream &bs_str=*gbs_str;
      if (ver>0)
      {
         DEBUG_MSG("reading and decompressing sizes...\n");
         for(GPosition pos=files_list;pos;++pos)
            files_list[pos]->size=bs_str.read24();
      }
         
      DEBUG_MSG("reading and decompressing flags...\n");
      for(pos=files_list;pos;++pos)
         files_list[pos]->flags=bs_str.read8();

      if (!ver)
      {
         DEBUG_MSG("converting flags from version 0...\n");
         for(pos=files_list;pos;++pos)
         {
            unsigned char flags_0=files_list[pos]->flags;
            unsigned char flags_1;
            flags_1=(flags_0 & File::IS_PAGE_0)?(File::PAGE):(File::INCLUDE);
            if (flags_0 & File::HAS_NAME_0)
              flags_1|=File::HAS_NAME;
            if (flags_0 & File::HAS_TITLE_0)
              flags_1|=File::HAS_TITLE;
            files_list[pos]->flags=flags_1;
         }
      }
   
      DEBUG_MSG("reading and decompressing names...\n");
      GTArray<char> strings;
      char buffer[1024];
      int length;
      while((length=bs_str.read(buffer, 1024)))
      {
         int strings_size=strings.size();
         strings.resize(strings_size+length-1);
         memcpy((char*) strings+strings_size, buffer, length);
      }
      DEBUG_MSG("size of decompressed names block=" << strings.size() << "\n");
   
         // Copy names into the files
      const char * ptr=strings;
      for(pos=files_list;pos;++pos)
      {
         GP<File> file=files_list[pos];

         file->id=ptr;
         ptr+=file->id.length()+1;
         if (file->flags & File::HAS_NAME)
         {
            file->name=ptr;
            ptr+=file->name.length()+1;
         } else
         {
            file->name=file->id;
         }
         if (file->flags & File::HAS_TITLE)
         {
            file->title=ptr;
       ptr+=file->title.length()+1;
         } else
       file->title=file->id;
   /* msr debug:  multipage file, file->title is null.  
         DEBUG_MSG(file->name << ", " << file->id << ", " << file->title << ", " <<
                   file->offset << ", " << file->size << ", " <<
                   file->is_page() << "\n"); */
      }

         // Check that there is only one file with SHARED_ANNO flag on
      int shared_anno_cnt=0;
      for(pos=files_list;pos;++pos)
      {
         if (files_list[pos]->is_shared_anno())
         {
            shared_anno_cnt++;
         }
      }
      if (shared_anno_cnt>1)
        G_THROW( ERR_MSG("DjVmDir.corrupt") );

         // Now generate page=>file array for direct access
      int pages=0;
      for(pos=files_list;pos;++pos)
              pages+=files_list[pos]->is_page() ? 1 : 0;
      DEBUG_MSG("got " << pages << " pages\n");
      page2file.resize(pages-1);
      int page_num=0;
      for(pos=files_list;pos;++pos)
      {
               GP<File> file=files_list[pos];
               if (file->is_page())
               {
                  page2file[page_num]=file;
                  file->page_num=page_num++;
               }
      }

         // Generate name2file map
      for(pos=files_list;pos;++pos)
      {
             GP<File> file=files_list[pos];
             if (name2file.contains(file->name))
                G_THROW( ERR_MSG("DjVmDir.dupl_name") "\t" + file->name );
             name2file[file->name]=file;
      }

         // Generate id2file map
      for(pos=files_list;pos;++pos)
      {
             GP<File> file=files_list[pos];
             if (id2file.contains(file->id))
                G_THROW( ERR_MSG("DjVmDir.dupl_id") "\t" + file->id);
             id2file[file->id]=file;
      }

         // Generate title2file map
      for(pos=files_list;pos;++pos)
      {
             GP<File> file=files_list[pos];
             if (file->title.length())
             {
                if (title2file.contains(file->title))
                   G_THROW( ERR_MSG("DjVmDir.dupl_title") "\t" + file->title);
                title2file[file->title]=file;
             }
      }
   }
}


Generated by  Doxygen 1.6.0   Back to index