view src/lumpdir.cc @ 93:5652866f31eb

Cleanups.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 06 Oct 2014 00:33:26 +0300
parents 99242b34e6dc
children
line wrap: on
line source

/*
 *        lumpdir.cc
 *        Lump_dir class
 *        AYM 1999-11-25
 */


/*
This file is part of Yadex.

Yadex incorporates code from DEU 5.21 that was put in the public domain in
1994 by Raphaël Quinet and Brendon Wyber.

The rest of Yadex is Copyright © 1997-2003 André Majorel and others.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307, USA.
*/


#include "yadex.h"
#include "dependcy.h"
#include "lumpdir.h"
#include "wadname.h"
#include "wadnamec.h"
#include "wadfile.h"



/*
 *        Lump_dir::Lump_dir - ctor 
 *
 *        <md> is a pointer to the master directory on which the
 *        lump directory is based.
 *        <l> is the first character of the label.
 *        <sn> is a pointer to the Serial_num of the master
 *        directory.
 */

Lump_dir::Lump_dir(MDirPtr * md, char l, Serial_num * sn)
{
    have_prev = false;
    dependency = new Dependency(sn);
    master_dir = md;
    label = l;
}


/*
 *        Lump_dir::~Lump_dir - dtor
 */
Lump_dir::~Lump_dir()
{
    if (dependency)
        delete dependency;
    if (!lump_map.empty())
        lump_map.clear();
}


/*
 *        Lump_dir::loc_by_name - find a lump by name
 *
 *        Return the (wad, offset, length) location of the lump
 *        named <name>. If not found, set loc.wad to 0.
 */
void Lump_dir::loc_by_name(const char *name, Lump_loc & loc)
{
    if (dependency->outdated())
        refresh();

    /* Caller asked for same lump twice in a row. Save us a second
       search. */
    if (have_prev && !y_strnicmp(name, name_prev, WAD_NAME))
    {
        loc = loc_prev;
        return;
    }

    Lump_map::const_iterator i = lump_map.find(name);
    have_prev = true;
    if (i == lump_map.end())
        loc.wad = loc_prev.wad = 0;
    else
        loc = loc_prev = i->second;
}


/*
 *        Lump_dir::list - return an array of lump names
 *
 *        Put a list of all lumps in the list, sorted by name and
 *        with duplicates removed, in <l>.
 */
void Lump_dir::list(Lump_list & l)
{
    if (dependency->outdated())
        refresh();
    l.set(lump_map);
}


/*
 *        Lump_dir::refresh - update the lump dir. wrt to the master dir.
 *
 *        This is called automatically if the master directory has
 *        changed since the last refresh.
 */
void Lump_dir::refresh()
{
    /* refresh() can be called more than once one the same object.
       And usually is ! */
    have_prev = false;
    if (!lump_map.empty())
        lump_map.clear();

    /* Get list of lumps in the master directory. Everything
       that is between X_START/X_END or XX_START/XX_END and that
       is not a label is supposed to be added to the Lump_dir. */
    Wad_name_c x_start("%c_START", label);
    Wad_name_c x_end("%c_END", label);
    Wad_name_c xx_start("%c%c_START", label, label);
    Wad_name_c xx_end("%c%c_END", label, label);
    for (MDirPtr dir = *master_dir; dir && (dir = FindMasterDir(dir, x_start.name, xx_start.name));)
    {
        MDirPtr start_label = dir;
        const char *end_label = 0;
        if (!x_start.cmp(dir->dir.name))
            end_label = x_end.name;
        else if (!xx_start.cmp(dir->dir.name))
            end_label = xx_end.name;
        else
            fatal_error("Bad start label \"%.*s\"", (int) WAD_NAME,
                        dir->dir.name);
        dir = dir->next;
        for (;; dir = dir->next)
        {
            if (!dir)
            {
                warn("%.128s: no matching %s for %.*s\n",
                     start_label->wadfile->pathname(),
                     end_label, (int) WAD_NAME, start_label->dir.name);
                break;
            }
            // Ended by X_END or, if started by XX_START, XX_END.
            if (!x_end.cmp(dir->dir.name) ||
                (end_label == xx_end.name && !xx_end.cmp(dir->dir.name)))
            {
                if (dir->dir.size != 0)
                {
                    warn("%.128s: label %.*s has non-zero size %ld\n",
                         dir->wadfile->pathname(),
                         (int) WAD_NAME, dir->dir.name, (long) dir->dir.size);
                }
                dir = dir->next;
                break;
            }
            // Ignore inner labels (X[123]_START, X[123]_END)
            if (dir->dir.start == 0 || dir->dir.size == 0)
            {
                if (!(toupper(dir->dir.name[0]) == label &&
                     (dir->dir.name[1] == '1' || dir->dir.name[1] == '2' || dir->dir.name[1] == '3')
                      && dir->dir.name[2] == '_' &&
                      (!y_strnicmp(dir->dir.name + 3, "START", WAD_NAME - 3)
                       || !y_strnicmp(dir->dir.name + 3, "END",
                                      WAD_NAME - 3))))
                {
                    warn("%.128s: unexpected label \"%.*s\" in %s group\n",
                         dir->wadfile->pathname(), (int) WAD_NAME,
                         dir->dir.name, start_label->dir.name);
                }
                continue;
            }

            wad_flat_name_t name;
            memcpy(name, dir->dir.name, sizeof name);
            lump_map[name] = Lump_loc(dir->wadfile, dir->dir.start, dir->dir.size);
        }
        if (dir)
            dir = dir->next;
    }
#ifdef DEBUG
    for (Lump_lumps_map::const_iterator i = lump_map.begin();
         i != lump_map.end(); i++)
    {
        printf("%-8.8s %p %08lX %ld\n",
               i->first._name, i->second.wad, i->second.ofs, i->second.len);
    }
#endif
    dependency->update();
}


/*-------------------------- Lump_list --------------------------*/


Lump_list::Lump_list()
{
    array = 0;
    nelements = 0;
}


Lump_list::~Lump_list()
{
    clear();
}


void Lump_list::set(Lump_map & lump_map)
{
    clear();
    nelements = lump_map.size();
    array = new char *[nelements];

    Lump_map::const_iterator i = lump_map.begin();
    for (size_t n = 0; n < nelements; n++)
    {
        array[n] = new char[WAD_NAME + 1];
        *array[n] = '\0';
        strncat(array[n], i++->first.name, WAD_NAME);
    }
}


void Lump_list::clear()
{
    if (array != 0)
    {
        for (size_t n = 0; n < nelements; n++)
            delete[]array[n];
        delete[]array;
    }
}


const char **Lump_list::data()
{
    return (const char **) array;
}


size_t Lump_list::size()
{
    return nelements;
}


/*------------------------- Lump_map_key -------------------------*/


//Lump_map_key::Lump_map_key (const char *name)
//{
//  memcpy (_name, name, sizeof _name);
//}


/*------------------------ Lump_map_less -------------------------*/


bool Lump_map_less::operator ()
    (const Wad_name & name1, const Wad_name & name2)
     const
     {
         return name1.less(name2);
         //return y_strnicmp ((const char *) &p1, (const char *) &p2, WAD_NAME) < 0;
     }