Logo Search packages:      
Sourcecode: djvulibre version File versions

void DjVmDoc::write ( const GP< ByteStream > &  str,
const GMap< GUTF8String, void * > &  reserved 
)

Writes the multipage DjVu document in the {bundled} format into the stream, reserving any of the specified names.

Definition at line 274 of file DjVmDoc.cpp.

References IFFByteStream::close_chunk(), GMapTemplate< KTYPE, VTYPE, TI >::contains(), GMapTemplate< KTYPE, VTYPE, VTYPE >::contains(), IFFByteStream::copy(), DataPool::create(), ByteStream::create(), DjVmDir::encode(), IFFByteStream::flush(), IFFByteStream::get_bytestream(), get_data(), IFFByteStream::put_chunk(), DjVmDir::resolve_duplicates(), GBaseString::rsearch(), save_file(), DjVmDir::set_file_name(), GUTF8String::substr(), and IFFByteStream::tell().

{
  DEBUG_MSG("DjVmDoc::write(): Storing document into the byte stream.\n");
  DEBUG_MAKE_INDENT(3);

  GPList<DjVmDir::File> files_list=dir->resolve_duplicates(true);
  bool do_rename=false;
  GPosition pos(reserved);

  GMap<GUTF8String,GUTF8String> incl;
  DEBUG_MSG("pass 1: looking for reserved names.");
  if(pos)
  {
      // Check if there are any conflicting file names.
    for(pos=files_list;pos;++pos)
    {
      GP<DjVmDir::File> file=files_list[pos];
      if((do_rename=(reserved.contains(file->get_load_name())?true:false))
              ||(do_rename=(reserved.contains(file->get_save_name())?true:false)))
      {
        break;
      }
    }
    // If there are conflicting file names, check if the save names
    // are OK.  If not, generate new save names.
    if(do_rename)
    {
      DEBUG_MSG("pass 1: renaming reserved names.");
      for(;;files_list=dir->resolve_duplicates(true))
      {
        GMap<GUTF8String,void *> this_doc;
        for(pos=files_list;pos;++pos)
        {
          GP<DjVmDir::File> file=files_list[pos];
          this_doc[::get_name(*file)]=0;
        }
        bool need_new_list=false;
        for(pos=files_list;pos;++pos)
        {
          GP<DjVmDir::File> file=files_list[pos];
          const GUTF8String name(::get_name(*file));
          if(reserved.contains(name))
          {
            GUTF8String new_name;
            int series=0;
            do
            {
              int dot=name.rsearch('.');
              if(dot>0)
              {
                new_name=name.substr(0,dot)+
                  "_"+GUTF8String(++series)+name.substr(dot,-1);
              }else
              {
                new_name=name+"_"+GUTF8String(++series);
              }
            } while(reserved.contains(new_name)||this_doc.contains(new_name));
            dir->set_file_name(file->get_load_name(),new_name);
            need_new_list=true;
          }
        }
        if(!need_new_list)
          break;
      }
    }
  }

  DEBUG_MSG("pass 2: create dummy DIRM chunk and calculate offsets...\n");
  for(pos=files_list;pos;++pos)
  {
    GP<DjVmDir::File> file=files_list[pos];
    file->offset=0xffffffff;
    GPosition data_pos=data.contains(file->get_load_name());
    if (!data_pos)
      G_THROW( ERR_MSG("DjVmDoc.no_data") "\t" + file->get_load_name());
    if(do_rename)
    {
      GP<ByteStream> gout(ByteStream::create());
      {
        const GP<IFFByteStream> giff_in(
          IFFByteStream::create(data[data_pos]->get_stream()));
        const GP<IFFByteStream> giff_out(IFFByteStream::create(gout));
        ::save_file(*giff_in,*giff_out,*dir,incl);
      }
      gout->seek(0L);
      data[data_pos]=DataPool::create(gout);
    }
    file->size=data[data_pos]->get_length();
    if (!file->size)
      G_THROW( ERR_MSG("DjVmDoc.zero_file") );
  }
   
  const GP<ByteStream> tmp_str(ByteStream::create());
  const GP<IFFByteStream> gtmp_iff(IFFByteStream::create(tmp_str));
  IFFByteStream &tmp_iff=*gtmp_iff;
  tmp_iff.put_chunk("FORM:DJVM", 1);
  tmp_iff.put_chunk("DIRM");
  dir->encode(tmp_iff.get_bytestream(),do_rename);
  tmp_iff.close_chunk();
  tmp_iff.close_chunk();
  int offset=tmp_iff.tell();

  for(pos=files_list;pos;++pos)
  {
    if ((offset & 1)!=0)
      offset++;
      
    GP<DjVmDir::File> & file=files_list[pos];
    file->offset=offset;
    offset+=file->size; // file->size has been set in the first pass
  }

  DEBUG_MSG("pass 3: store the file contents.\n");

  GP<IFFByteStream> giff=IFFByteStream::create(gstr);
  IFFByteStream &iff=*giff;
  iff.put_chunk("FORM:DJVM", 1);
  iff.put_chunk("DIRM");
  dir->encode(iff.get_bytestream(),do_rename);
  iff.close_chunk();

  for(pos=files_list;pos;++pos)
  {
    GP<DjVmDir::File> & file=files_list[pos];

    const GP<DataPool> pool=get_data(file->get_load_name());
    const GP<ByteStream> str_in(pool->get_stream());
    if ((iff.tell() & 1)!=0)
    {
      iff.get_bytestream()->write8(0);
    }
    iff.copy(*str_in);
  }

  iff.close_chunk();
  iff.flush();

  DEBUG_MSG("done storing DjVm file.\n");
}


Generated by  Doxygen 1.6.0   Back to index