Blame libdjvu/GIFFManager.cpp

Packit df99a1
//C-  -*- C++ -*-
Packit df99a1
//C- -------------------------------------------------------------------
Packit df99a1
//C- DjVuLibre-3.5
Packit df99a1
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
Packit df99a1
//C- Copyright (c) 2001  AT&T
Packit df99a1
//C-
Packit df99a1
//C- This software is subject to, and may be distributed under, the
Packit df99a1
//C- GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- or (at your option) any later version. The license should have
Packit df99a1
//C- accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C-
Packit df99a1
//C- This program is distributed in the hope that it will be useful,
Packit df99a1
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
//C- GNU General Public License for more details.
Packit df99a1
//C- 
Packit df99a1
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
Packit df99a1
//C- Lizardtech Software.  Lizardtech Software has authorized us to
Packit df99a1
//C- replace the original DjVu(r) Reference Library notice by the following
Packit df99a1
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
Packit df99a1
//C-
Packit df99a1
//C-  ------------------------------------------------------------------
Packit df99a1
//C- | DjVu (r) Reference Library (v. 3.5)
Packit df99a1
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
Packit df99a1
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
Packit df99a1
//C- | 6,058,214 and patents pending.
Packit df99a1
//C- |
Packit df99a1
//C- | This software is subject to, and may be distributed under, the
Packit df99a1
//C- | GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- | or (at your option) any later version. The license should have
Packit df99a1
//C- | accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- | from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C- |
Packit df99a1
//C- | The computer code originally released by LizardTech under this
Packit df99a1
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
Packit df99a1
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
Packit df99a1
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
Packit df99a1
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
Packit df99a1
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
Packit df99a1
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
Packit df99a1
//C- | General Public License.   This grant only confers the right to 
Packit df99a1
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
Packit df99a1
//C- | the extent such infringement is reasonably necessary to enable 
Packit df99a1
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
Packit df99a1
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
Packit df99a1
//C- | any greater extent that may be necessary to utilize further 
Packit df99a1
//C- | modifications or combinations.
Packit df99a1
//C- |
Packit df99a1
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
Packit df99a1
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
Packit df99a1
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
Packit df99a1
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Packit df99a1
//C- +------------------------------------------------------------------
Packit df99a1
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
# include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma implementation
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#include "GIFFManager.h"
Packit df99a1
#include "GException.h"
Packit df99a1
#include "debug.h"
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
namespace DJVU {
Packit df99a1
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
GIFFChunk::~GIFFChunk(void) {}
Packit df99a1
Packit df99a1
GIFFManager::~GIFFManager(void) {}
Packit df99a1
Packit df99a1
GP<GIFFManager> 
Packit df99a1
GIFFManager::create(void)
Packit df99a1
{
Packit df99a1
  GIFFManager *iff=new GIFFManager();
Packit df99a1
  GP<GIFFManager> retval=iff;
Packit df99a1
  iff->init();
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<GIFFManager> 
Packit df99a1
GIFFManager::create(const GUTF8String &name)
Packit df99a1
{
Packit df99a1
  GIFFManager *iff=new GIFFManager();
Packit df99a1
  GP<GIFFManager> retval=iff;
Packit df99a1
  iff->init(name);
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFChunk::set_name(GUTF8String name)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFChunk::set_name(): name='" << name << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
  const int colon=name.search(':');
Packit df99a1
  if(colon>=0)
Packit df99a1
  {
Packit df99a1
    type=name.substr(0,colon);
Packit df99a1
    name=name.substr(colon+1,(unsigned int)-1);
Packit df99a1
    if(name.search(':')>=0)
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.one_colon") );
Packit df99a1
  }
Packit df99a1
Packit df99a1
  DEBUG_MSG("auto-setting type to '" << type << "'\n");
Packit df99a1
Packit df99a1
  if (name.contains(".[]")>=0)
Packit df99a1
    G_THROW( ERR_MSG("GIFFManager.bad_char") );
Packit df99a1
Packit df99a1
  strncpy(GIFFChunk::name, (const char *)name, 4);
Packit df99a1
  GIFFChunk::name[4]=0;
Packit df99a1
  for(int i=strlen(GIFFChunk::name);i<4;i++)
Packit df99a1
    GIFFChunk::name[i]=' ';
Packit df99a1
}
Packit df99a1
Packit df99a1
bool
Packit df99a1
GIFFChunk::check_name(GUTF8String name)
Packit df99a1
{
Packit df99a1
  GUTF8String type;
Packit df99a1
  const int colon=name.search(':');
Packit df99a1
  if(colon>=0)
Packit df99a1
    {
Packit df99a1
      type=name.substr(0,colon);
Packit df99a1
      name=name.substr(colon+1,(unsigned int)-1);
Packit df99a1
    }
Packit df99a1
Packit df99a1
  const GUTF8String sname=(name.substr(0,4)+"    ").substr(0,4);
Packit df99a1
Packit df99a1
  DEBUG_MSG("GIFFChunk::check_name(): type='" << type << "' name='" << sname << "'\n");
Packit df99a1
  return (type==GIFFChunk::type || (!type.length() && GIFFChunk::type=="FORM"))
Packit df99a1
    && sname==GIFFChunk::name;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFChunk::save(IFFByteStream & istr, bool use_trick)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFChunk::save(): saving chunk '" << get_full_name() << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
  if (is_container())
Packit df99a1
  {
Packit df99a1
    istr.put_chunk(get_full_name(), use_trick);
Packit df99a1
    if (chunks.size())
Packit df99a1
    {
Packit df99a1
      GPosition pos;
Packit df99a1
      for(pos=chunks;pos;++pos)
Packit df99a1
        if (chunks[pos]->get_type()=="PROP")
Packit df99a1
          chunks[pos]->save(istr);
Packit df99a1
      for(pos=chunks;pos;++pos)
Packit df99a1
        if (chunks[pos]->get_type()!="PROP")
Packit df99a1
          chunks[pos]->save(istr);
Packit df99a1
    } else
Packit df99a1
    {
Packit df99a1
      DEBUG_MSG("but it's empty => saving empty container.\n");
Packit df99a1
    }
Packit df99a1
    istr.close_chunk();
Packit df99a1
  } else
Packit df99a1
  {
Packit df99a1
    istr.put_chunk(get_name(), use_trick);
Packit df99a1
    istr.get_bytestream()->writall((const char *) data, data.size());
Packit df99a1
    istr.close_chunk();
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFChunk::add_chunk(const GP<GIFFChunk> & chunk, int position)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFChunk::add_chunk(): Adding chunk to '" << get_name() <<
Packit df99a1
     "' @ position=" << position << "\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
  if (!type.length())
Packit df99a1
  {
Packit df99a1
    DEBUG_MSG("Converting the parent to FORM\n");
Packit df99a1
    type="FORM";
Packit df99a1
  }
Packit df99a1
Packit df99a1
  if (chunk->get_type()=="PROP")
Packit df99a1
  {
Packit df99a1
    DEBUG_MSG("Converting the parent to LIST\n");
Packit df99a1
    type="LIST";
Packit df99a1
  }
Packit df99a1
Packit df99a1
  GPosition pos;
Packit df99a1
  if (position>=0 && chunks.nth(position, pos))
Packit df99a1
  {
Packit df99a1
    chunks.insert_before(pos, chunk);
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    chunks.append(chunk);
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String 
Packit df99a1
GIFFChunk::decode_name(const GUTF8String &name, int &number)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFChunk::decode_name(): Checking brackets in name '" << name << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
   
Packit df99a1
  if (name.search('.')>=0)
Packit df99a1
    G_THROW( ERR_MSG("GIFFManager.no_dots") );
Packit df99a1
Packit df99a1
  number=0;
Packit df99a1
  const int obracket=name.search('[');
Packit df99a1
  GUTF8String short_name;
Packit df99a1
  if (obracket >= 0)
Packit df99a1
  {
Packit df99a1
    const int cbracket=name.search(']',obracket+1);
Packit df99a1
    if (cbracket < 0)
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.unmatched") );
Packit df99a1
    if (name.length() > (unsigned int)(cbracket+1))
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.garbage") );
Packit df99a1
//    number =atoi((const char *)name.substr(obracket+1,cbracket-obracket-1));
Packit df99a1
    number= name.substr(obracket+1,cbracket-obracket-1).toInt(); 
Packit df99a1
    short_name=name.substr(0,obracket);
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    short_name=name;
Packit df99a1
  }
Packit df99a1
Packit df99a1
  const int colon=short_name.search(':');
Packit df99a1
  if (colon>=0)
Packit df99a1
    short_name=short_name.substr(colon+1,(unsigned int)-1);
Packit df99a1
Packit df99a1
  for(int i=short_name.length();i<4;i++)
Packit df99a1
    short_name.setat(i, ' ');
Packit df99a1
   
Packit df99a1
  DEBUG_MSG("short_name='" << short_name << "'\n");
Packit df99a1
  DEBUG_MSG("number=" << number << "\n");
Packit df99a1
   
Packit df99a1
  return short_name;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFChunk::del_chunk(const GUTF8String &name)
Packit df99a1
   // The name may contain brackets to specify the chunk number
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFChunk::del_chunk(): Deleting chunk '" << name <<
Packit df99a1
     "' from '" << get_name() << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
  int number;
Packit df99a1
  const GUTF8String short_name=decode_name(name,number);
Packit df99a1
Packit df99a1
  GPosition pos=chunks;
Packit df99a1
  for(int num=0;pos;++pos)
Packit df99a1
  {
Packit df99a1
    if ((chunks[pos]->get_name()==short_name)&&(num++ == number))
Packit df99a1
    {
Packit df99a1
      chunks.del(pos);
Packit df99a1
      break;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  if(! pos)
Packit df99a1
  {
Packit df99a1
    G_THROW( ERR_MSG("GIFFManager.no_chunk") "\t"+short_name+"\t"+GUTF8String(number)+"\t"+get_name());
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<GIFFChunk>
Packit df99a1
GIFFChunk::get_chunk(const GUTF8String &name, int * pos_ptr)
Packit df99a1
   // The name may contain brackets to specify the chunk number
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFChunk::get_chunk(): Returning chunk '" << name <<
Packit df99a1
     "' from '" << get_name() << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
  int number;
Packit df99a1
  const GUTF8String short_name=decode_name(name,number);
Packit df99a1
Packit df99a1
  int num=0;
Packit df99a1
  int pos_num;
Packit df99a1
  GP<GIFFChunk> retval;
Packit df99a1
  GPosition pos;
Packit df99a1
  for(pos=chunks, pos_num=0;pos;++pos, pos_num++)
Packit df99a1
  {
Packit df99a1
    if (chunks[pos]->get_name()==short_name && num++==number)
Packit df99a1
    {
Packit df99a1
      if (pos_ptr)
Packit df99a1
        *pos_ptr=pos_num;
Packit df99a1
      retval=chunks[pos];
Packit df99a1
      break;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
GIFFChunk::get_chunks_number(void)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFChunk::get_chunks_number(): Returning number of chunks '" << name <<
Packit df99a1
     "' in '" << get_name() << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
  return chunks.size();
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
GIFFChunk::get_chunks_number(const GUTF8String &name)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFChunk::get_chunks_number(): Returning number of chunks '" << name <<
Packit df99a1
     "' in '" << get_name() << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
  if (name.contains("[]")>=0)
Packit df99a1
    G_THROW( ERR_MSG("GIFFManager.no_brackets") );
Packit df99a1
  
Packit df99a1
  int number; 
Packit df99a1
  GUTF8String short_name=decode_name(name,number);
Packit df99a1
   
Packit df99a1
  int num=0;
Packit df99a1
  for(GPosition pos=chunks;pos;++pos)
Packit df99a1
     num+=(chunks[pos]->get_name()==short_name);
Packit df99a1
  return num;
Packit df99a1
}
Packit df99a1
Packit df99a1
//************************************************************************
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFManager::add_chunk(GUTF8String parent_name, const GP<GIFFChunk> & chunk,
Packit df99a1
		       int pos)
Packit df99a1
      // parent_name is the fully qualified name of the PARENT
Packit df99a1
      //             IT MAY BE EMPTY
Packit df99a1
      // All the required chunks will be created
Packit df99a1
      // pos=-1 means to append the chunk
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFManager::add_chunk(): Adding chunk to name='" << parent_name << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
   
Packit df99a1
  if (!top_level->get_name().length())
Packit df99a1
  {
Packit df99a1
    if ((!parent_name.length())||(parent_name[0]!='.'))
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.no_top_name") );
Packit df99a1
    if (parent_name.length() < 2)
Packit df99a1
    {
Packit df99a1
      // 'chunk' is actually the new top-level chunk
Packit df99a1
      DEBUG_MSG("since parent_name=='.', making the chunk top-level\n");
Packit df99a1
      if (!chunk->is_container())
Packit df99a1
        G_THROW( ERR_MSG("GIFFManager.no_top_cont") );
Packit df99a1
      top_level=chunk;
Packit df99a1
      return;
Packit df99a1
    }
Packit df99a1
Packit df99a1
    DEBUG_MSG("Setting the name of the top-level chunk\n");
Packit df99a1
    const int next_dot=parent_name.search('.',1);
Packit df99a1
    if(next_dot>=0)
Packit df99a1
    {
Packit df99a1
      top_level->set_name(parent_name.substr(1,next_dot-1));
Packit df99a1
    }else
Packit df99a1
    {
Packit df99a1
      top_level->set_name(parent_name.substr(1,(unsigned int)-1));
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
Packit df99a1
  DEBUG_MSG("top level chunk name='" << top_level->get_name() << "'\n");
Packit df99a1
   
Packit df99a1
  if (parent_name.length() && parent_name[0] == '.')
Packit df99a1
  {
Packit df99a1
    int next_dot=parent_name.search('.',1);
Packit df99a1
    if(next_dot<0)
Packit df99a1
    {
Packit df99a1
      next_dot=parent_name.length();
Packit df99a1
    }
Packit df99a1
    GUTF8String top_name=parent_name.substr(1,next_dot-1);
Packit df99a1
    if (!top_level->check_name(top_name))
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.wrong_name") "\t"+top_name);
Packit df99a1
    parent_name=parent_name.substr(next_dot,(unsigned int)-1);
Packit df99a1
  }
Packit df99a1
Packit df99a1
  GP<GIFFChunk> cur_sec=top_level;
Packit df99a1
  const char * start, * end=(const char *)parent_name-1;
Packit df99a1
  do
Packit df99a1
  {
Packit df99a1
    for(start=++end;*end&&(*end!='.');end++)
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
    if (end>start)
Packit df99a1
    {
Packit df99a1
      GUTF8String name(start,end-start);
Packit df99a1
      GUTF8String short_name;
Packit df99a1
      int number=0;
Packit df99a1
      const int obracket=name.search('[');
Packit df99a1
      if (obracket >= 0)
Packit df99a1
      {
Packit df99a1
        const int cbracket=name.search(']',obracket+1);
Packit df99a1
        if (cbracket < 0)
Packit df99a1
          G_THROW( ERR_MSG("GIFFManager.unmatched") );
Packit df99a1
//        number=atoi((const char *)name.substr(obracket+1,cbracket-obracket-1));
Packit df99a1
        number = name.substr(obracket+1,cbracket-obracket-1).toInt();
Packit df99a1
        short_name=name.substr(0,obracket);
Packit df99a1
      }else
Packit df99a1
      {
Packit df99a1
        short_name=name;
Packit df99a1
      }
Packit df99a1
Packit df99a1
      for(int i=cur_sec->get_chunks_number(short_name);i
Packit df99a1
        cur_sec->add_chunk(GIFFChunk::create(short_name));
Packit df99a1
      cur_sec=cur_sec->get_chunk(name);
Packit df99a1
      if (!cur_sec)
Packit df99a1
        G_THROW( ERR_MSG("GIFFManager.unknown") "\t"+name);
Packit df99a1
    }
Packit df99a1
  } while(*end);
Packit df99a1
  cur_sec->add_chunk(chunk, pos);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFManager::add_chunk(GUTF8String name, const TArray<char> & data)
Packit df99a1
      // name is fully qualified name of the chunk TO BE INSERTED.
Packit df99a1
      //      it may contain brackets at the end to set the position
Packit df99a1
      // All the required chunks will be created
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFManager::add_chunk(): adding plain chunk with name='" << name << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
  GUTF8String chunk_name;
Packit df99a1
  const int lastdot=name.rsearch('.');
Packit df99a1
  if(lastdot < 0)
Packit df99a1
  {
Packit df99a1
    chunk_name=name;
Packit df99a1
    name=name.substr(0,lastdot);
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    chunk_name=name.substr(lastdot+1,(unsigned int)-1);
Packit df99a1
  }
Packit df99a1
Packit df99a1
  int pos=-1;
Packit df99a1
  const int obracket=chunk_name.search('[');
Packit df99a1
  if (obracket >= 0)
Packit df99a1
  {
Packit df99a1
    const int cbracket=chunk_name.search(']',obracket+1);
Packit df99a1
    if (cbracket < 0)
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.unmatched") );
Packit df99a1
    if (name.length() > (unsigned int)(cbracket+1))
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.garbage") );
Packit df99a1
//    pos=atoi((const char *)chunk_name.substr(obracket+1,cbracket-obracket-1));
Packit df99a1
    pos = chunk_name.substr(obracket+1,cbracket-obracket-1).toInt();
Packit df99a1
    chunk_name=chunk_name.substr(0,obracket);
Packit df99a1
  }
Packit df99a1
  DEBUG_MSG("Creating new chunk with name " << chunk_name << "\n");
Packit df99a1
  GP<GIFFChunk> chunk;
Packit df99a1
  chunk=GIFFChunk::create(chunk_name, data);
Packit df99a1
  add_chunk(name, chunk, pos);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFManager::del_chunk(void)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFManager::del_chunk(): Deleting chunk\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
   
Packit df99a1
  G_THROW( ERR_MSG("GIFFManager.del_empty") );
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFManager::del_chunk(GUTF8String name)
Packit df99a1
      // "name" should be fully qualified, that is contain dots.
Packit df99a1
      // It may also end with [] to set the chunk order number
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFManager::del_chunk(): Deleting chunk '" << name << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
   
Packit df99a1
  if (!name.length())
Packit df99a1
    G_THROW( ERR_MSG("GIFFManager.del_empty") );
Packit df99a1
Packit df99a1
  if (name[0]=='.')
Packit df99a1
  {
Packit df99a1
    const int next_dot=name.search('.',1);
Packit df99a1
    if (next_dot < 0)
Packit df99a1
    {
Packit df99a1
      if (top_level->check_name(name.substr(1,(unsigned int)-1)))
Packit df99a1
      {
Packit df99a1
        DEBUG_MSG("Removing top level chunk..\n");
Packit df99a1
        top_level=GIFFChunk::create();
Packit df99a1
        return;
Packit df99a1
      }
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+name.substr(1,(unsigned int)-1));
Packit df99a1
    }
Packit df99a1
    const GUTF8String top_name=name.substr(1,next_dot-1);
Packit df99a1
    if (!top_level->check_name(top_name))
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+top_name);
Packit df99a1
    name=name.substr(next_dot+1,(unsigned int)-1);
Packit df99a1
  }
Packit df99a1
   
Packit df99a1
  GP<GIFFChunk> cur_sec=top_level;
Packit df99a1
  const char * start, * end=(const char *)name-1;
Packit df99a1
  do
Packit df99a1
  {
Packit df99a1
    for(start=++end;*end&&(*end!='.');end++)
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
    if (end>start && *end=='.')
Packit df99a1
      cur_sec=cur_sec->get_chunk(GUTF8String(start, end-start));
Packit df99a1
    if (!cur_sec)
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.cant_find") "\t"+GUTF8String(name));
Packit df99a1
  } while(*end);
Packit df99a1
   
Packit df99a1
  if (!start[0])
Packit df99a1
  {
Packit df99a1
    G_THROW(GUTF8String( ERR_MSG("GIFFManager.malformed") "\t")+name);
Packit df99a1
  }
Packit df99a1
   
Packit df99a1
  cur_sec->del_chunk(start);
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<GIFFChunk>
Packit df99a1
GIFFManager::get_chunk(GUTF8String name, int * pos_num)
Packit df99a1
      // "name" should be fully qualified, that is contain dots.
Packit df99a1
      // It may also end with [] to set the chunk order number
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFManager::get_chunk(): Returning chunk '" << name << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
   
Packit df99a1
  if (!name.length())
Packit df99a1
    G_THROW( ERR_MSG("GIFFManager.get_empty") );
Packit df99a1
Packit df99a1
  if (name[0]=='.')
Packit df99a1
  {
Packit df99a1
    const int next_dot=name.search('.',1);
Packit df99a1
    if (next_dot < 0)
Packit df99a1
    {
Packit df99a1
      if (top_level->check_name(name.substr(1,(unsigned int)-1)))
Packit df99a1
      {
Packit df99a1
        DEBUG_MSG("Removing top level chunk..\n");
Packit df99a1
        return top_level;
Packit df99a1
      }
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+name.substr(1,(unsigned int)-1));
Packit df99a1
    }
Packit df99a1
    const GUTF8String top_name=name.substr(1,next_dot-1);
Packit df99a1
    if (!top_level->check_name(top_name))
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+top_name);
Packit df99a1
    name=name.substr(next_dot+1,(unsigned int)-1);
Packit df99a1
  }
Packit df99a1
   
Packit df99a1
  GP<GIFFChunk> cur_sec=top_level;
Packit df99a1
  const char * start, * end=(const char *) name-1;
Packit df99a1
  do
Packit df99a1
  {
Packit df99a1
    for(start=++end;*end&&(*end!='.');end++)
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
    if (end>start)
Packit df99a1
      cur_sec=cur_sec->get_chunk(GUTF8String(start, end-start), pos_num);
Packit df99a1
    if (!cur_sec)
Packit df99a1
      break;
Packit df99a1
  } while(*end);
Packit df99a1
   
Packit df99a1
  return cur_sec;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
GIFFManager::get_chunks_number(void)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFManager::get_chunks_number()\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
  return top_level->get_chunks_number();
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
GIFFManager::get_chunks_number(const GUTF8String &name)
Packit df99a1
   // Returns the number of chunks with given fully qualified name
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFManager::get_chunks_number(): name='" << name << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
  int retval;
Packit df99a1
  const int last_dot=name.rsearch('.');
Packit df99a1
  if (last_dot<0)
Packit df99a1
  {
Packit df99a1
    retval=top_level->get_chunks_number(name);
Packit df99a1
  }else if(!last_dot)
Packit df99a1
  {
Packit df99a1
    retval=(top_level->get_name()==name.substr(1,(unsigned int)-1))?1:0;
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    GP<GIFFChunk> chunk=get_chunk(name.substr(0,last_dot));
Packit df99a1
    retval=( chunk
Packit df99a1
      ?(chunk->get_chunks_number(name.substr(last_dot+1,(unsigned int)-1)))
Packit df99a1
      :0 );
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFManager::load_chunk(IFFByteStream & istr, GP<GIFFChunk> chunk)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFManager::load_chunk(): loading contents of chunk '" <<
Packit df99a1
    chunk->get_name() << "'\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
   
Packit df99a1
  int chunk_size;
Packit df99a1
  GUTF8String chunk_id;
Packit df99a1
  while ((chunk_size=istr.get_chunk(chunk_id)))
Packit df99a1
  {
Packit df99a1
    if (istr.check_id(chunk_id))
Packit df99a1
    {
Packit df99a1
      GP<GIFFChunk> ch=GIFFChunk::create(chunk_id);
Packit df99a1
      load_chunk(istr, ch);
Packit df99a1
      chunk->add_chunk(ch);
Packit df99a1
    } else
Packit df99a1
    {
Packit df99a1
      TArray<char> data(chunk_size-1);
Packit df99a1
      istr.get_bytestream()->readall( (char*)data, data.size());
Packit df99a1
      GP<GIFFChunk> ch=GIFFChunk::create(chunk_id, data);
Packit df99a1
      chunk->add_chunk(ch);
Packit df99a1
    }
Packit df99a1
    istr.close_chunk();
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFManager::load_file(const TArray<char> & data)
Packit df99a1
{
Packit df99a1
  GP<ByteStream> str=ByteStream::create((const char *)data, data.size());
Packit df99a1
  load_file(str);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFManager::load_file(GP<ByteStream> str)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("GIFFManager::load_file(): Loading IFF file.\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
   
Packit df99a1
  GP<IFFByteStream> gistr=IFFByteStream::create(str);
Packit df99a1
  IFFByteStream &istr=*gistr;
Packit df99a1
  GUTF8String chunk_id;
Packit df99a1
  if (istr.get_chunk(chunk_id))
Packit df99a1
  {
Packit df99a1
    if (chunk_id.substr(0,5) != "FORM:")
Packit df99a1
      G_THROW( ERR_MSG("GIFFManager.cant_find2") );
Packit df99a1
    set_name(chunk_id);
Packit df99a1
    load_chunk(istr, top_level);
Packit df99a1
    istr.close_chunk();
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFManager::save_file(TArray<char> & data)
Packit df99a1
{
Packit df99a1
  GP<ByteStream> gstr=ByteStream::create();
Packit df99a1
  save_file(gstr);
Packit df99a1
  data=gstr->get_data();
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GIFFManager::save_file(GP<ByteStream> str)
Packit df99a1
{
Packit df99a1
  GP<IFFByteStream> istr=IFFByteStream::create(str);
Packit df99a1
  top_level->save(*istr, 1);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
}
Packit df99a1
# ifndef NOT_USING_DJVU_NAMESPACE
Packit df99a1
using namespace DJVU;
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1