<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id: vmware4.cc,v 1.1 2006/12/17 08:17:28 vruppert Exp $
/////////////////////////////////////////////////////////////////////////

/*
 * This file provides support for VMWare's virtual disk image
 * format version 4 and above.
 *
 * Author: Sharvil Nanavati
 * Contact: snrrrub@gmail.com
 *
 * Copyright (C) 2006 Sharvil Nanavati.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

// Define BX_PLUGGABLE in files that can be compiled into plugins.  For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE

#define NO_DEVICE_INCLUDES

#include "iodev.h"
#include "hdimage.h"
#include "vmware4.h"

#define LOG_THIS bx_devices.pluginHardDrive->
const off_t vmware4_image_t::INVALID_OFFSET = (off_t)-1;
const int vmware4_image_t::SECTOR_SIZE = 512;

vmware4_image_t::vmware4_image_t()
    : file_descriptor(-1),
      tlb(0),
      tlb_offset(INVALID_OFFSET),
      current_offset(INVALID_OFFSET),
      is_dirty(false)
{
}

vmware4_image_t::~vmware4_image_t()
{
    close();
}

int vmware4_image_t::open(const char * pathname)
{
    close();

    int flags = O_RDWR;
#ifdef O_BINARY
    flags |= O_BINARY;
#endif

    file_descriptor = ::open(pathname, flags);

    if(!is_open())
        return -1;

    if(!read_header())
        BX_PANIC(("unable to read vmware4 virtual disk header from file '%s'", pathname));

    tlb = new Bit8u [header.tlb_size_sectors * SECTOR_SIZE];
    if(tlb == 0)
        BX_PANIC(("unable to allocate %lld bytes for vmware4 image's tlb", header.tlb_size_sectors * SECTOR_SIZE));

    tlb_offset = INVALID_OFFSET;
    current_offset = 0;
    is_dirty = false;

    hd_size = header.total_sectors * SECTOR_SIZE;
    cylinders = hd_size / (16 * 63);
    heads = 16;
    sectors = 63;

    BX_DEBUG(("VMware 4 disk geometry:"));
    BX_DEBUG(("   .size      = %lld", hd_size));
    BX_DEBUG(("   .cylinders = %d", cylinders));
    BX_DEBUG(("   .heads     = %d", heads));
    BX_DEBUG(("   .sectors   = %d", sectors));

    return 1;
}

void vmware4_image_t::close()
{
    if(file_descriptor == -1)
        return;

    flush();
    delete [] tlb, tlb = 0;

    ::close(file_descriptor);
    file_descriptor = -1;
}

Bit64s vmware4_image_t::lseek(Bit64s offset, int whence)
{
    switch(whence)
    {
        case SEEK_SET:
            current_offset = (off_t)offset;
            return current_offset;
        case SEEK_CUR:
            current_offset += (off_t)offset;
            return current_offset;
        case SEEK_END:
            current_offset = header.total_sectors * SECTOR_SIZE + (off_t)offset;
            return current_offset;
        default:
            BX_DEBUG(("unknown 'whence' value (%d) when trying to seek vmware4 image", whence));
            return INVALID_OFFSET;
    }
}

ssize_t vmware4_image_t::read(void * buf, size_t count)
{
    ssize_t total = 0;
    while(count > 0)
    {
        off_t readable = perform_seek();
        if(readable == INVALID_OFFSET)
        {
            BX_DEBUG(("vmware4 disk image read failed on %d bytes at " FMT_LL "d", count, current_offset));
            return -1;
        }

        off_t copysize = (count > readable) ? readable : count;
        memcpy(buf, tlb + current_offset - tlb_offset, copysize);

        current_offset += copysize;
        total += copysize;
        count -= copysize;
    }
    return total;
}

ssize_t vmware4_image_t::write(const void * buf, size_t count)
{
    ssize_t total = 0;
    while(count > 0)
    {
        off_t writable = perform_seek();
        if(writable == INVALID_OFFSET)
        {
            BX_DEBUG(("vmware4 disk image write failed on %d bytes at " FMT_LL "d", count, current_offset));
            return -1;
        }

        off_t writesize = (count > writable) ? writable : count;
        memcpy(tlb + current_offset - tlb_offset, buf, writesize);

        current_offset += writesize;
        total += writesize;
        count -= writesize;
        is_dirty = true;
    }
    return total;
}

bool vmware4_image_t::is_open() const
{
    return (file_descriptor != -1);
}

bool vmware4_image_t::is_valid_header() const
{
    if(header.id[0] != 'K' || header.id[1] != 'D' || header.id[2] != 'M' ||
       header.id[3] != 'V')
    {
        BX_DEBUG(("not a vmware4 image"));
        return false;
    }

    if(header.version != 1)
    {
        BX_DEBUG(("unsupported vmware4 image version"));
        return false;
    }

    return true;
}

bool vmware4_image_t::read_header()
{
    if(!is_open())
        BX_PANIC(("attempt to read vmware4 header from a closed file"));

    if(::read(file_descriptor, &header, sizeof(VM4_Header)) != sizeof(VM4_Header))
        return false;

    header.version = dtoh32(header.version);
    header.flags = dtoh32(header.flags);
    header.total_sectors = dtoh64(header.total_sectors);
    header.tlb_size_sectors = dtoh64(header.tlb_size_sectors);
    header.description_offset_sectors = dtoh64(header.description_offset_sectors);
    header.description_size_sectors = dtoh64(header.description_size_sectors);
    header.slb_count = dtoh32(header.slb_count);
    header.flb_offset_sectors = dtoh64(header.flb_offset_sectors);
    header.flb_copy_offset_sectors = dtoh64(header.flb_copy_offset_sectors);
    header.tlb_offset_sectors = dtoh64(header.tlb_offset_sectors);

    if(!is_valid_header())
        BX_PANIC(("invalid vmware4 virtual disk image"));

    BX_DEBUG(("VM4_Header (size=%d)", sizeof(VM4_Header)));
    BX_DEBUG(("   .version                    = %d", header.version));
    BX_DEBUG(("   .flags                      = %d", header.flags));
    BX_DEBUG(("   .total_sectors              = %lld", header.total_sectors));
    BX_DEBUG(("   .tlb_size_sectors           = %lld", header.tlb_size_sectors));
    BX_DEBUG(("   .description_offset_sectors = %lld", header.description_offset_sectors));
    BX_DEBUG(("   .description_size_sectors   = %lld", header.description_size_sectors));
    BX_DEBUG(("   .slb_count                  = %d", header.slb_count));
    BX_DEBUG(("   .flb_offset_sectors         = %lld", header.flb_offset_sectors));
    BX_DEBUG(("   .flb_copy_offset_sectors    = %lld", header.flb_copy_offset_sectors));
    BX_DEBUG(("   .tlb_offset_sectors         = %lld", header.tlb_offset_sectors));

    return true;
}

//
// Returns the number of bytes that can be read from the current offset before needing
// to perform another seek.
//
off_t vmware4_image_t::perform_seek()
{
    if(current_offset == INVALID_OFFSET)
    {
        BX_DEBUG(("invalid offset specified in vmware4 seek"));
        return INVALID_OFFSET;
    }

    //
    // The currently loaded tlb can service the request.
    //
    if(tlb_offset / (header.tlb_size_sectors * SECTOR_SIZE) == current_offset / (header.tlb_size_sectors * SECTOR_SIZE))
        return (header.tlb_size_sectors * SECTOR_SIZE) - (current_offset - tlb_offset);

    flush();

    Bit64u index = current_offset / (header.tlb_size_sectors * SECTOR_SIZE);
    Bit32u slb_index = (Bit32u)(index % header.slb_count);
    Bit32u flb_index = (Bit32u)(index / header.slb_count);

    Bit32u slb_sector = read_block_index(header.flb_offset_sectors, flb_index);
    Bit32u slb_copy_sector = read_block_index(header.flb_copy_offset_sectors, flb_index);

    if(slb_sector == 0 && slb_copy_sector == 0)
    {
        BX_DEBUG(("loaded vmware4 disk image requires un-implemented feature"));
        return INVALID_OFFSET;
    }
    if(slb_sector == 0)
        slb_sector = slb_copy_sector;

    Bit32u tlb_sector = read_block_index(slb_sector, slb_index);
    tlb_offset = index * header.tlb_size_sectors * SECTOR_SIZE;
    if(tlb_sector == 0)
    {
        //
        // Allocate a new tlb
        //
        memset(tlb, 0, header.tlb_size_sectors * SECTOR_SIZE);

        //
        // Instead of doing a write to increase the file size, we could use
        // ftruncate but it is not portable.
        //
        off_t eof = ((::lseek(file_descriptor, 0, SEEK_END) + SECTOR_SIZE - 1) / SECTOR_SIZE) * SECTOR_SIZE;
        ::write(file_descriptor, tlb, header.tlb_size_sectors * SECTOR_SIZE);
        tlb_sector = eof / SECTOR_SIZE;

        write_block_index(slb_sector, slb_index, tlb_sector);
        write_block_index(slb_copy_sector, slb_index, tlb_sector);

        ::lseek(file_descriptor, eof, SEEK_SET);
    }
    else
    {
        ::lseek(file_descriptor, tlb_sector * SECTOR_SIZE, SEEK_SET);
        ::read(file_descriptor, tlb, header.tlb_size_sectors * SECTOR_SIZE);
        ::lseek(file_descriptor, tlb_sector * SECTOR_SIZE, SEEK_SET);
    }

    return (header.tlb_size_sectors * SECTOR_SIZE) - (current_offset - tlb_offset);
}

void vmware4_image_t::flush()
{
    if(!is_dirty)
        return;

    //
    // Write dirty sectors to disk first. Assume that the file is already at the
    // position for the current tlb.
    //
    ::write(file_descriptor, tlb, header.tlb_size_sectors * SECTOR_SIZE);
    is_dirty = false;
}

Bit32u vmware4_image_t::read_block_index(Bit64u sector, Bit32u index)
{
    Bit32u ret;

    ::lseek(file_descriptor, sector * SECTOR_SIZE + index * sizeof(Bit32u), SEEK_SET);
    ::read(file_descriptor, &ret, sizeof(Bit32u));

    return dtoh32(ret);
}

void vmware4_image_t::write_block_index(Bit64u sector, Bit32u index, Bit32u block_sector)
{
    block_sector = htod32(block_sector);

    ::lseek(file_descriptor, sector * SECTOR_SIZE + index * sizeof(Bit32u), SEEK_SET);
    ::write(file_descriptor, &block_sector, sizeof(Bit32u));
}
<commit_msg>- fixed several MSVC warnings<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id: vmware4.cc,v 1.2 2006/12/19 16:42:27 vruppert Exp $
/////////////////////////////////////////////////////////////////////////

/*
 * This file provides support for VMWare's virtual disk image
 * format version 4 and above.
 *
 * Author: Sharvil Nanavati
 * Contact: snrrrub@gmail.com
 *
 * Copyright (C) 2006 Sharvil Nanavati.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

// Define BX_PLUGGABLE in files that can be compiled into plugins.  For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE

#define NO_DEVICE_INCLUDES

#include "iodev.h"
#include "hdimage.h"
#include "vmware4.h"

#define LOG_THIS bx_devices.pluginHardDrive->
const off_t vmware4_image_t::INVALID_OFFSET = (off_t)-1;
const int vmware4_image_t::SECTOR_SIZE = 512;

vmware4_image_t::vmware4_image_t()
    : file_descriptor(-1),
      tlb(0),
      tlb_offset(INVALID_OFFSET),
      current_offset(INVALID_OFFSET),
      is_dirty(false)
{
}

vmware4_image_t::~vmware4_image_t()
{
    close();
}

int vmware4_image_t::open(const char * pathname)
{
    close();

    int flags = O_RDWR;
#ifdef O_BINARY
    flags |= O_BINARY;
#endif

    file_descriptor = ::open(pathname, flags);

    if(!is_open())
        return -1;

    if(!read_header())
        BX_PANIC(("unable to read vmware4 virtual disk header from file '%s'", pathname));

    tlb = new Bit8u[(unsigned)header.tlb_size_sectors * SECTOR_SIZE];
    if(tlb == 0)
        BX_PANIC(("unable to allocate %lld bytes for vmware4 image's tlb", header.tlb_size_sectors * SECTOR_SIZE));

    tlb_offset = INVALID_OFFSET;
    current_offset = 0;
    is_dirty = false;

    hd_size = header.total_sectors * SECTOR_SIZE;
    cylinders = (unsigned)hd_size / (16 * 63);
    heads = 16;
    sectors = 63;

    BX_DEBUG(("VMware 4 disk geometry:"));
    BX_DEBUG(("   .size      = %lld", hd_size));
    BX_DEBUG(("   .cylinders = %d", cylinders));
    BX_DEBUG(("   .heads     = %d", heads));
    BX_DEBUG(("   .sectors   = %d", sectors));

    return 1;
}

void vmware4_image_t::close()
{
    if(file_descriptor == -1)
        return;

    flush();
    delete [] tlb, tlb = 0;

    ::close(file_descriptor);
    file_descriptor = -1;
}

Bit64s vmware4_image_t::lseek(Bit64s offset, int whence)
{
    switch(whence)
    {
        case SEEK_SET:
            current_offset = (off_t)offset;
            return current_offset;
        case SEEK_CUR:
            current_offset += (off_t)offset;
            return current_offset;
        case SEEK_END:
            current_offset = header.total_sectors * SECTOR_SIZE + (off_t)offset;
            return current_offset;
        default:
            BX_DEBUG(("unknown 'whence' value (%d) when trying to seek vmware4 image", whence));
            return INVALID_OFFSET;
    }
}

ssize_t vmware4_image_t::read(void * buf, size_t count)
{
    ssize_t total = 0;
    while(count > 0)
    {
        off_t readable = perform_seek();
        if(readable == INVALID_OFFSET)
        {
            BX_DEBUG(("vmware4 disk image read failed on %d bytes at " FMT_LL "d", count, current_offset));
            return -1;
        }

        off_t copysize = (count > readable) ? readable : count;
        memcpy(buf, tlb + current_offset - tlb_offset, (size_t)copysize);

        current_offset += copysize;
        total += (long)copysize;
        count -= (size_t)copysize;
    }
    return total;
}

ssize_t vmware4_image_t::write(const void * buf, size_t count)
{
    ssize_t total = 0;
    while(count > 0)
    {
        off_t writable = perform_seek();
        if(writable == INVALID_OFFSET)
        {
            BX_DEBUG(("vmware4 disk image write failed on %d bytes at " FMT_LL "d", count, current_offset));
            return -1;
        }

        off_t writesize = (count > writable) ? writable : count;
        memcpy(tlb + current_offset - tlb_offset, buf, (size_t)writesize);

        current_offset += writesize;
        total += (long)writesize;
        count -= (size_t)writesize;
        is_dirty = true;
    }
    return total;
}

bool vmware4_image_t::is_open() const
{
    return (file_descriptor != -1);
}

bool vmware4_image_t::is_valid_header() const
{
    if(header.id[0] != 'K' || header.id[1] != 'D' || header.id[2] != 'M' ||
       header.id[3] != 'V')
    {
        BX_DEBUG(("not a vmware4 image"));
        return false;
    }

    if(header.version != 1)
    {
        BX_DEBUG(("unsupported vmware4 image version"));
        return false;
    }

    return true;
}

bool vmware4_image_t::read_header()
{
    if(!is_open())
        BX_PANIC(("attempt to read vmware4 header from a closed file"));

    if(::read(file_descriptor, &header, sizeof(VM4_Header)) != sizeof(VM4_Header))
        return false;

    header.version = dtoh32(header.version);
    header.flags = dtoh32(header.flags);
    header.total_sectors = dtoh64(header.total_sectors);
    header.tlb_size_sectors = dtoh64(header.tlb_size_sectors);
    header.description_offset_sectors = dtoh64(header.description_offset_sectors);
    header.description_size_sectors = dtoh64(header.description_size_sectors);
    header.slb_count = dtoh32(header.slb_count);
    header.flb_offset_sectors = dtoh64(header.flb_offset_sectors);
    header.flb_copy_offset_sectors = dtoh64(header.flb_copy_offset_sectors);
    header.tlb_offset_sectors = dtoh64(header.tlb_offset_sectors);

    if(!is_valid_header())
        BX_PANIC(("invalid vmware4 virtual disk image"));

    BX_DEBUG(("VM4_Header (size=%d)", sizeof(VM4_Header)));
    BX_DEBUG(("   .version                    = %d", header.version));
    BX_DEBUG(("   .flags                      = %d", header.flags));
    BX_DEBUG(("   .total_sectors              = %lld", header.total_sectors));
    BX_DEBUG(("   .tlb_size_sectors           = %lld", header.tlb_size_sectors));
    BX_DEBUG(("   .description_offset_sectors = %lld", header.description_offset_sectors));
    BX_DEBUG(("   .description_size_sectors   = %lld", header.description_size_sectors));
    BX_DEBUG(("   .slb_count                  = %d", header.slb_count));
    BX_DEBUG(("   .flb_offset_sectors         = %lld", header.flb_offset_sectors));
    BX_DEBUG(("   .flb_copy_offset_sectors    = %lld", header.flb_copy_offset_sectors));
    BX_DEBUG(("   .tlb_offset_sectors         = %lld", header.tlb_offset_sectors));

    return true;
}

//
// Returns the number of bytes that can be read from the current offset before needing
// to perform another seek.
//
off_t vmware4_image_t::perform_seek()
{
    if(current_offset == INVALID_OFFSET)
    {
        BX_DEBUG(("invalid offset specified in vmware4 seek"));
        return INVALID_OFFSET;
    }

    //
    // The currently loaded tlb can service the request.
    //
    if(tlb_offset / (header.tlb_size_sectors * SECTOR_SIZE) == current_offset / (header.tlb_size_sectors * SECTOR_SIZE))
        return (header.tlb_size_sectors * SECTOR_SIZE) - (current_offset - tlb_offset);

    flush();

    Bit64u index = current_offset / (header.tlb_size_sectors * SECTOR_SIZE);
    Bit32u slb_index = (Bit32u)(index % header.slb_count);
    Bit32u flb_index = (Bit32u)(index / header.slb_count);

    Bit32u slb_sector = read_block_index(header.flb_offset_sectors, flb_index);
    Bit32u slb_copy_sector = read_block_index(header.flb_copy_offset_sectors, flb_index);

    if(slb_sector == 0 && slb_copy_sector == 0)
    {
        BX_DEBUG(("loaded vmware4 disk image requires un-implemented feature"));
        return INVALID_OFFSET;
    }
    if(slb_sector == 0)
        slb_sector = slb_copy_sector;

    Bit32u tlb_sector = read_block_index(slb_sector, slb_index);
    tlb_offset = index * header.tlb_size_sectors * SECTOR_SIZE;
    if(tlb_sector == 0)
    {
        //
        // Allocate a new tlb
        //
        memset(tlb, 0, (size_t)header.tlb_size_sectors * SECTOR_SIZE);

        //
        // Instead of doing a write to increase the file size, we could use
        // ftruncate but it is not portable.
        //
        off_t eof = ((::lseek(file_descriptor, 0, SEEK_END) + SECTOR_SIZE - 1) / SECTOR_SIZE) * SECTOR_SIZE;
        ::write(file_descriptor, tlb, (unsigned)header.tlb_size_sectors * SECTOR_SIZE);
        tlb_sector = (Bit32u)eof / SECTOR_SIZE;

        write_block_index(slb_sector, slb_index, tlb_sector);
        write_block_index(slb_copy_sector, slb_index, tlb_sector);

        ::lseek(file_descriptor, eof, SEEK_SET);
    }
    else
    {
        ::lseek(file_descriptor, tlb_sector * SECTOR_SIZE, SEEK_SET);
        ::read(file_descriptor, tlb, (unsigned)header.tlb_size_sectors * SECTOR_SIZE);
        ::lseek(file_descriptor, tlb_sector * SECTOR_SIZE, SEEK_SET);
    }

    return (header.tlb_size_sectors * SECTOR_SIZE) - (current_offset - tlb_offset);
}

void vmware4_image_t::flush()
{
    if(!is_dirty)
        return;

    //
    // Write dirty sectors to disk first. Assume that the file is already at the
    // position for the current tlb.
    //
    ::write(file_descriptor, tlb, (unsigned)header.tlb_size_sectors * SECTOR_SIZE);
    is_dirty = false;
}

Bit32u vmware4_image_t::read_block_index(Bit64u sector, Bit32u index)
{
    Bit32u ret;

    ::lseek(file_descriptor, sector * SECTOR_SIZE + index * sizeof(Bit32u), SEEK_SET);
    ::read(file_descriptor, &ret, sizeof(Bit32u));

    return dtoh32(ret);
}

void vmware4_image_t::write_block_index(Bit64u sector, Bit32u index, Bit32u block_sector)
{
    block_sector = htod32(block_sector);

    ::lseek(file_descriptor, sector * SECTOR_SIZE + index * sizeof(Bit32u), SEEK_SET);
    ::write(file_descriptor, &block_sector, sizeof(Bit32u));
}
<|endoftext|>


<commit_before>//
//  StaticAnalyser.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 03/05/2018.
//  Copyright © 2018 Thomas Harte. All rights reserved.
//

#include "StaticAnalyser.hpp"

#include "../AppleII/Target.hpp"
#include "../Oric/Target.hpp"
#include "../Disassembler/6502.hpp"
#include "../Disassembler/AddressMapper.hpp"

#include "../../../Storage/Disk/Track/TrackSerialiser.hpp"
#include "../../../Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp"

namespace {

Analyser::Static::Target *AppleTarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) {
	using Target = Analyser::Static::AppleII::Target;
	auto *target = new Target;
	target->machine = Analyser::Machine::AppleII;

	if(sector_zero && sector_zero->encoding == Storage::Encodings::AppleGCR::Sector::Encoding::FiveAndThree) {
		target->disk_controller = Target::DiskController::ThirteenSector;
	} else {
		target->disk_controller = Target::DiskController::SixteenSector;
	}

	return target;
}

Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) {
	using Target = Analyser::Static::Oric::Target;
	auto *target = new Target;
	target->machine = Analyser::Machine::Oric;

	// TODO: configure the Oric as a Pravetz 8D with 8DOS.

	return target;
}

}

Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) {
	// This analyser can comprehend disks only.
	if(media.disks.empty()) return {};

	// Grab track 0, sector 0: the boot sector.
	auto track_zero = media.disks.front()->get_track_at_position(Storage::Disk::Track::Address(0, 0));
	auto sector_map = Storage::Encodings::AppleGCR::sectors_from_segment(
		Storage::Disk::track_serialisation(*track_zero, Storage::Time(1, 50000)));

	const Storage::Encodings::AppleGCR::Sector *sector_zero = nullptr;
	for(const auto &pair: sector_map) {
		if(!pair.second.address.sector) {
			sector_zero = &pair.second;
			break;
		}
	}

	// If there's no boot sector then if there are also no sectors at all,
	// decline to nominate a machine. Otherwise go with an Apple as the default.
	TargetList targets;
	if(!sector_zero) {
		if(sector_map.empty()) {
			return targets;
		} else {
			targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleTarget(nullptr)));
			return targets;
		}
	}

	// If the boot sector looks like it's intended for the Oric, create an Oric.
	// Otherwise go with the Apple II.

	auto disassembly = Analyser::Static::MOS6502::Disassemble(sector_zero->data, Analyser::Static::Disassembler::OffsetMapper(0xb800), {0xb800});

	bool did_read_shift_register = false;
	bool is_oric = false;

	// Look for a tight BPL loop reading the Oric's shift register address of 0x31c. The Apple II just has RAM there,
	// so the probability of such a loop is infinitesimal.
	for(const auto &instruction: disassembly.instructions_by_address) {
		// Is this a read of the shift register?
		if(
			(
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDA) ||
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDX) ||
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDY)
			) &&
			instruction.second.addressing_mode == Analyser::Static::MOS6502::Instruction::Absolute &&
			instruction.second.address == 0x031c) {
			did_read_shift_register = true;
			continue;
		}

		if(did_read_shift_register) {
			if(
				instruction.second.operation == Analyser::Static::MOS6502::Instruction::BPL &&
				instruction.second.address == 0xfb) {
				is_oric = true;
				break;
			}

			did_read_shift_register = false;
		}
	}

	// Check also for calls into the 0x3xx page above 0x320, as that's where the Oric's boot ROM is.
	for(const auto address: disassembly.outward_calls) {
		is_oric |= address >= 0x320 && address < 0x400;
	}

	if(is_oric) {
		targets.push_back(std::unique_ptr<Analyser::Static::Target>(OricTarget(sector_zero)));
	} else {
		targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleTarget(sector_zero)));
	}
	return targets;
}
<commit_msg>Ensures media is passed on from the Disk II analyser.<commit_after>//
//  StaticAnalyser.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 03/05/2018.
//  Copyright © 2018 Thomas Harte. All rights reserved.
//

#include "StaticAnalyser.hpp"

#include "../AppleII/Target.hpp"
#include "../Oric/Target.hpp"
#include "../Disassembler/6502.hpp"
#include "../Disassembler/AddressMapper.hpp"

#include "../../../Storage/Disk/Track/TrackSerialiser.hpp"
#include "../../../Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp"

namespace {

Analyser::Static::Target *AppleTarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) {
	using Target = Analyser::Static::AppleII::Target;
	auto *target = new Target;
	target->machine = Analyser::Machine::AppleII;

	if(sector_zero && sector_zero->encoding == Storage::Encodings::AppleGCR::Sector::Encoding::FiveAndThree) {
		target->disk_controller = Target::DiskController::ThirteenSector;
	} else {
		target->disk_controller = Target::DiskController::SixteenSector;
	}

	return target;
}

Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) {
	using Target = Analyser::Static::Oric::Target;
	auto *target = new Target;
	target->machine = Analyser::Machine::Oric;

	// TODO: configure the Oric as a Pravetz 8D with 8DOS.

	return target;
}

}

Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &media, const std::string &file_name, TargetPlatform::IntType potential_platforms) {
	// This analyser can comprehend disks only.
	if(media.disks.empty()) return {};

	// Grab track 0, sector 0: the boot sector.
	auto track_zero = media.disks.front()->get_track_at_position(Storage::Disk::Track::Address(0, 0));
	auto sector_map = Storage::Encodings::AppleGCR::sectors_from_segment(
		Storage::Disk::track_serialisation(*track_zero, Storage::Time(1, 50000)));

	const Storage::Encodings::AppleGCR::Sector *sector_zero = nullptr;
	for(const auto &pair: sector_map) {
		if(!pair.second.address.sector) {
			sector_zero = &pair.second;
			break;
		}
	}

	// If there's no boot sector then if there are also no sectors at all,
	// decline to nominate a machine. Otherwise go with an Apple as the default.
	TargetList targets;
	if(!sector_zero) {
		if(sector_map.empty()) {
			return targets;
		} else {
			targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleTarget(nullptr)));
			targets.back()->media = media;
			return targets;
		}
	}

	// If the boot sector looks like it's intended for the Oric, create an Oric.
	// Otherwise go with the Apple II.

	auto disassembly = Analyser::Static::MOS6502::Disassemble(sector_zero->data, Analyser::Static::Disassembler::OffsetMapper(0xb800), {0xb800});

	bool did_read_shift_register = false;
	bool is_oric = false;

	// Look for a tight BPL loop reading the Oric's shift register address of 0x31c. The Apple II just has RAM there,
	// so the probability of such a loop is infinitesimal.
	for(const auto &instruction: disassembly.instructions_by_address) {
		// Is this a read of the shift register?
		if(
			(
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDA) ||
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDX) ||
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDY)
			) &&
			instruction.second.addressing_mode == Analyser::Static::MOS6502::Instruction::Absolute &&
			instruction.second.address == 0x031c) {
			did_read_shift_register = true;
			continue;
		}

		if(did_read_shift_register) {
			if(
				instruction.second.operation == Analyser::Static::MOS6502::Instruction::BPL &&
				instruction.second.address == 0xfb) {
				is_oric = true;
				break;
			}

			did_read_shift_register = false;
		}
	}

	// Check also for calls into the 0x3xx page above 0x320, as that's where the Oric's boot ROM is.
	for(const auto address: disassembly.outward_calls) {
		is_oric |= address >= 0x320 && address < 0x400;
	}

	if(is_oric) {
		targets.push_back(std::unique_ptr<Analyser::Static::Target>(OricTarget(sector_zero)));
	} else {
		targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleTarget(sector_zero)));
	}
	targets.back()->media = media;
	return targets;
}
<|endoftext|>


<commit_before>#include "natives.hpp"
#include "LogManager.hpp"
#include "PluginLog.hpp"

#include <fmt/format.h>

// native Logger:CreateLog(const name[], bool:debuginfo = true);
AMX_DECLARE_NATIVE(Native::CreateLog)
{
	ScopedDebugInfo dbg_info(amx, "CreateLog", params, "sd");

	const char *name = nullptr;
	amx_StrParam(amx, params[1], name);

	if (name == nullptr)
	{
		PluginLog::Get()->LogNative(LogLevel::ERROR, "invalid logger name");
		return 0;
	}

	auto ret_val = static_cast<cell>(LogManager::Get()->Create(name, params[2] != 0));
	PluginLog::Get()->LogNative(LogLevel::DEBUG, "return value: '{}'", ret_val);
	return ret_val;
}

// native DestroyLog(Logger:logger);
AMX_DECLARE_NATIVE(Native::DestroyLog)
{
	ScopedDebugInfo dbg_info(amx, "DestroyLog", params, "d");

	const Logger::Id logid = params[1];
	if (LogManager::Get()->IsValid(logid) == false)
	{
		PluginLog::Get()->LogNative(LogLevel::ERROR, "invalid log id '{}'", logid);
		return 0;
	}

	cell ret_val = LogManager::Get()->Destroy(logid) ? 1 : 0;
	PluginLog::Get()->LogNative(LogLevel::DEBUG, "return value: '{}'", ret_val);
	return ret_val;
}

// native bool:IsLogLevel(Logger:logger, E_LOGLEVEL:level);
AMX_DECLARE_NATIVE(Native::IsLogLevel)
{
	ScopedDebugInfo dbg_info(amx, "IsLogLevel", params, "dd");

	const Logger::Id logid = params[1];
	if (LogManager::Get()->IsValid(logid) == false)
	{
		PluginLog::Get()->LogNative(LogLevel::ERROR, "invalid log id '{}'", logid);
		return 0;
	}

	cell ret_val = LogManager::Get()->GetLogger(logid).
		IsLogLevel(static_cast<samplog::LogLevel>(params[2])) ? 1 : 0;
	PluginLog::Get()->LogNative(LogLevel::DEBUG, "return value: '{}'", ret_val);
	return ret_val;
}

// native Log(Logger:logger, E_LOGLEVEL:level, const msg[], {Float,_}:...);
AMX_DECLARE_NATIVE(Native::Log)
{
	ScopedDebugInfo dbg_info(amx, "Log", params, "dds");

	const Logger::Id logid = params[1];
	if (LogManager::Get()->IsValid(logid) == false)
	{
		PluginLog::Get()->LogNative(LogLevel::ERROR, "invalid log id '{}'", logid);
		return 0;
	}

	auto &logger = LogManager::Get()->GetLogger(logid);

	const samplog::LogLevel loglevel = static_cast<decltype(loglevel)>(params[2]);
	if (!logger.IsLogLevel(loglevel))
	{
		PluginLog::Get()->LogNative(LogLevel::DEBUG,
			"log level not set, not logging message");
		return 0;
	}

	std::string format_str = amx_GetCppString(amx, params[3]);

	const unsigned int
		first_param_idx = 4,
		num_args = (params[0] / sizeof(cell)),
		num_dyn_args = num_args - (first_param_idx - 1);
	unsigned int param_counter = 0;

	fmt::memory_buffer str_writer;

	size_t
		spec_pos = std::string::npos,
		spec_offset = 0;

	while ((spec_pos = format_str.find('%', spec_offset)) != std::string::npos)
	{
		if (spec_pos == (format_str.length() - 1))
		{
			PluginLog::Get()->LogNative(LogLevel::ERROR,
				"invalid specifier at string end");
			return 0;
		}

		fmt::format_to(str_writer, "{:s}",
			format_str.substr(spec_offset, spec_pos - spec_offset));
		spec_offset = spec_pos + 2; // 2 = '%' + char specifier (like 'd' or 's')

		const char format_spec = format_str.at(spec_pos + 1);
		if (format_spec == '%')
		{
			str_writer.push_back('%');
			continue;
		}

		if (param_counter >= num_dyn_args)
		{
			PluginLog::Get()->LogNative(LogLevel::ERROR,
				"format specifier at position {} has no argument passed", spec_pos);
			return 0;
		}

		cell
			*param_addr = nullptr,
			&param = params[first_param_idx + param_counter++];

		switch (format_spec)
		{
		case 's': // string
			fmt::format_to(str_writer, "{:s}", amx_GetCppString(amx, param));
			break;
		case 'd': // decimal
		case 'i': // integer
			if (amx_GetAddr(amx, param, &param_addr) != AMX_ERR_NONE || param_addr == nullptr)
			{
				PluginLog::Get()->LogNative(LogLevel::ERROR,
					"error while retrieving AMX address");
				return 0;
			}
			fmt::format_to(str_writer, "{:d}", static_cast<int>(*param_addr));
			break;
		case 'f': // float
			if (amx_GetAddr(amx, param, &param_addr) != AMX_ERR_NONE || param_addr == nullptr)
			{
				PluginLog::Get()->LogNative(LogLevel::ERROR,
					"error while retrieving AMX address");
				return 0;
			}
			fmt::format_to(str_writer, "{:f}", amx_ctof(*param_addr));
			break;
		default:
			PluginLog::Get()->LogNative(LogLevel::ERROR,
				"invalid format specifier '%{:c}'", format_spec); // TODO test "c"
			return 0;
		}
	}

	// copy rest of format string
	fmt::format_to(str_writer, "{:s}", format_str.substr(spec_offset));

	cell ret_val = logger.Log(loglevel, fmt::to_string(str_writer), amx) ? 1 : 0;
	PluginLog::Get()->LogNative(LogLevel::DEBUG, "return value: '{}'", ret_val);
	return ret_val;
}
<commit_msg>add more format specifiers<commit_after>#include "natives.hpp"
#include "LogManager.hpp"
#include "PluginLog.hpp"

#include <fmt/format.h>

// native Logger:CreateLog(const name[], bool:debuginfo = true);
AMX_DECLARE_NATIVE(Native::CreateLog)
{
	ScopedDebugInfo dbg_info(amx, "CreateLog", params, "sd");

	const char *name = nullptr;
	amx_StrParam(amx, params[1], name);

	if (name == nullptr)
	{
		PluginLog::Get()->LogNative(LogLevel::ERROR, "invalid logger name");
		return 0;
	}

	auto ret_val = static_cast<cell>(LogManager::Get()->Create(name, params[2] != 0));
	PluginLog::Get()->LogNative(LogLevel::DEBUG, "return value: '{}'", ret_val);
	return ret_val;
}

// native DestroyLog(Logger:logger);
AMX_DECLARE_NATIVE(Native::DestroyLog)
{
	ScopedDebugInfo dbg_info(amx, "DestroyLog", params, "d");

	const Logger::Id logid = params[1];
	if (LogManager::Get()->IsValid(logid) == false)
	{
		PluginLog::Get()->LogNative(LogLevel::ERROR, "invalid log id '{}'", logid);
		return 0;
	}

	cell ret_val = LogManager::Get()->Destroy(logid) ? 1 : 0;
	PluginLog::Get()->LogNative(LogLevel::DEBUG, "return value: '{}'", ret_val);
	return ret_val;
}

// native bool:IsLogLevel(Logger:logger, E_LOGLEVEL:level);
AMX_DECLARE_NATIVE(Native::IsLogLevel)
{
	ScopedDebugInfo dbg_info(amx, "IsLogLevel", params, "dd");

	const Logger::Id logid = params[1];
	if (LogManager::Get()->IsValid(logid) == false)
	{
		PluginLog::Get()->LogNative(LogLevel::ERROR, "invalid log id '{}'", logid);
		return 0;
	}

	cell ret_val = LogManager::Get()->GetLogger(logid).
		IsLogLevel(static_cast<samplog::LogLevel>(params[2])) ? 1 : 0;
	PluginLog::Get()->LogNative(LogLevel::DEBUG, "return value: '{}'", ret_val);
	return ret_val;
}

// native Log(Logger:logger, E_LOGLEVEL:level, const msg[], {Float,_}:...);
AMX_DECLARE_NATIVE(Native::Log)
{
	ScopedDebugInfo dbg_info(amx, "Log", params, "dds");

	const Logger::Id logid = params[1];
	if (LogManager::Get()->IsValid(logid) == false)
	{
		PluginLog::Get()->LogNative(LogLevel::ERROR, "invalid log id '{}'", logid);
		return 0;
	}

	auto &logger = LogManager::Get()->GetLogger(logid);

	const samplog::LogLevel loglevel = static_cast<decltype(loglevel)>(params[2]);
	if (!logger.IsLogLevel(loglevel))
	{
		PluginLog::Get()->LogNative(LogLevel::DEBUG,
			"log level not set, not logging message");
		return 0;
	}

	std::string format_str = amx_GetCppString(amx, params[3]);

	const unsigned int
		first_param_idx = 4,
		num_args = (params[0] / sizeof(cell)),
		num_dyn_args = num_args - (first_param_idx - 1);
	unsigned int param_counter = 0;

	fmt::memory_buffer str_writer;

	size_t
		spec_pos = std::string::npos,
		spec_offset = 0;

	while ((spec_pos = format_str.find('%', spec_offset)) != std::string::npos)
	{
		if (spec_pos == (format_str.length() - 1))
		{
			PluginLog::Get()->LogNative(LogLevel::ERROR,
				"invalid specifier at string end");
			return 0;
		}

		fmt::format_to(str_writer, "{:s}",
			format_str.substr(spec_offset, spec_pos - spec_offset));
		spec_offset = spec_pos + 2; // 2 = '%' + char specifier (like 'd' or 's')

		const char format_spec = format_str.at(spec_pos + 1);
		if (format_spec == '%')
		{
			str_writer.push_back('%');
			continue;
		}

		if (param_counter >= num_dyn_args)
		{
			PluginLog::Get()->LogNative(LogLevel::ERROR,
				"format specifier at position {} has no argument passed", spec_pos);
			return 0;
		}

		cell
			*param_addr = nullptr,
			&param = params[first_param_idx + param_counter++];

		auto fmt_str = fmt::format("{{:{:c}}}", format_spec == 'i' ? 'd' : format_spec);
		switch (format_spec)
		{
		case 's': // string
			fmt::format_to(str_writer, fmt_str, amx_GetCppString(amx, param));
			break;
		case 'd': // decimal
		case 'i': // custom decimal alias
		case 'o': // octal
		case 'x': // hex lowercase
		case 'X': // hex uppercase
		case 'b': // binary
			if (amx_GetAddr(amx, param, &param_addr) != AMX_ERR_NONE || param_addr == nullptr)
			{
				PluginLog::Get()->LogNative(LogLevel::ERROR,
					"error while retrieving AMX address");
				return 0;
			}
			fmt::format_to(str_writer, fmt_str, static_cast<int>(*param_addr));
			break;
		case 'f': // float
		case 'F': // float with uppercase 'NAN' and 'INF'
		case 'e': // exponent notation
		case 'E': // exponent notation (uppercase 'E')
		case 'g': // general format (combination of 'f' and 'e')
		case 'G': // general format (uppercase)
			if (amx_GetAddr(amx, param, &param_addr) != AMX_ERR_NONE || param_addr == nullptr)
			{
				PluginLog::Get()->LogNative(LogLevel::ERROR,
					"error while retrieving AMX address");
				return 0;
			}
			fmt::format_to(str_writer, fmt_str, amx_ctof(*param_addr));
			break;
		default:
			PluginLog::Get()->LogNative(LogLevel::ERROR,
				"invalid format specifier '%{:c}'", format_spec);
			return 0;
		}
	}

	// copy rest of format string
	fmt::format_to(str_writer, "{:s}", format_str.substr(spec_offset));

	cell ret_val = logger.Log(loglevel, fmt::to_string(str_writer), amx) ? 1 : 0;
	PluginLog::Get()->LogNative(LogLevel::DEBUG, "return value: '{}'", ret_val);
	return ret_val;
}
<|endoftext|>


<commit_before>#define DEBUG // Allow debugging
#define DEBUG2 // Allow debug lvl 2
#include <os>
#include <net/ip4.hpp>
#include <net/ip4/packet_ip4.hpp>
#include <net/packet.hpp>

using namespace net;

int IP4::bottom(Packet_ptr pckt){
  debug2("<IP4 handler> got the data. \n");

  const uint8_t* data = pckt->buffer();
  ip_header* hdr = &((full_header*)data)->ip_hdr;

  debug2("\t Source IP: %s Dest.IP: %s type: ",
        hdr->saddr.str().c_str(), hdr->daddr.str().c_str() );

  switch(hdr->protocol){
  case IP4_ICMP:
    debug2("\t ICMP \n");
    icmp_handler_(pckt);
    break;
  case IP4_UDP:
    debug2("\t UDP \n");
    udp_handler_(pckt);
    break;
  case IP4_TCP:
    tcp_handler_(pckt);
    debug2("\t TCP \n");
    break;
  default:
    debug("\t UNKNOWN %i \n", hdr->protocol);
    break;
  }

  return -1;
};

uint16_t IP4::checksum(ip_header* hdr)
{
  return net::checksum((uint16_t*) hdr, sizeof(ip_header));
}

int IP4::transmit(Packet_ptr pckt)
{
  //DEBUG Issue #102 :
  // Now _local_ip fails first, while _netmask fails if we remove local ip
  assert(pckt->size() > sizeof(IP4::full_header));

  full_header* full_hdr = (full_header*) pckt->buffer();
  ip_header* hdr = &full_hdr->ip_hdr;

  /*
  hdr->version_ihl = 0x45; // IPv.4, Size 5 x 32-bit
  hdr->tos = 0; // Unused
  hdr->tot_len = __builtin_bswap16(pckt->size() - sizeof(Ethernet::header));
  hdr->id = 0; // Fragment ID (we don't fragment yet)
  hdr->frag_off_flags = 0x40; // "No fragment" flag set, nothing else
  hdr->ttl = 64; // What Linux / netcat does

  // Checksum is 0 while calculating
  hdr->check = 0;
  hdr->check = checksum(hdr);

  // Make sure it's right
  //assert(checksum(hdr) == 0);

  // Calculate next-hop
  //assert(pckt->next_hop().whole == 0);

  // Set destination address to "my ip"
  // @TODO Don't know if this is good for routing...
  hdr->saddr.whole = local_ip_.whole;
  //ASSERT(! hdr->saddr.whole)

  std::shared_ptr<PacketIP4> p4 =
      std::static_pointer_cast<PacketIP4> (pckt);

  debug2("<IP4 TOP> Dest: %s, Source: %s\n",
        p4->dst().str().c_str(),
        p4->src().str().c_str());
  */

  // create local and target subnets
  addr target, local;
  target.whole = hdr->daddr.whole & netmask_.whole;
  local.whole  = local_ip_.whole  & netmask_.whole;
  // compare subnets to know where to send packet
  pckt->next_hop(target == local ? hdr->daddr : gateway_);

  debug2("<IP4 TOP> Next hop for %s, (netmask %s, local IP: %s, gateway: %s) == %s\n",
        hdr->daddr.str().c_str(),
        netmask_.str().c_str(),
        local_ip_.str().c_str(),
        gateway_.str().c_str(),
        target == local ? "DIRECT" : "GATEWAY");

  debug2("<IP4 transmit> my ip: %s, Next hop: %s\n",
        local_ip_.str().c_str(),
        pckt->next_hop().str().c_str());

  return linklayer_out_(pckt);
}

/** Empty handler for delegates initialization */
int net::ignore_ip4_up(std::shared_ptr<Packet> UNUSED(pckt)){
  debug("<IP4> Empty handler. Ignoring.\n");
  return -1;
}

int net::ignore_ip4_down(std::shared_ptr<Packet> UNUSED(pckt)){

  debug("<IP4->Link layer> No handler - DROP!\n");
  return 0;
}

IP4::IP4(Inet<LinkLayer, IP4>& inet) :
  local_ip_(inet.ip_addr()),
  netmask_(inet.netmask())
{
  // Default gateway is addr 1 in the subnet.
  const uint32_t DEFAULT_GATEWAY = __builtin_bswap32(1);

  gateway_.whole = (local_ip_.whole & netmask_.whole) | DEFAULT_GATEWAY;

  debug("<IP4> Local IP @ %p, Netmask @ %p \n",
        (void*) &local_ip_,
        (void*) &netmask_);
}
<commit_msg>Added back IP4 checksumming<commit_after>#define DEBUG // Allow debugging
#define DEBUG2 // Allow debug lvl 2
#include <os>
#include <net/ip4.hpp>
#include <net/ip4/packet_ip4.hpp>
#include <net/packet.hpp>

using namespace net;

int IP4::bottom(Packet_ptr pckt){
  debug2("<IP4 handler> got the data. \n");

  const uint8_t* data = pckt->buffer();
  ip_header* hdr = &((full_header*)data)->ip_hdr;

  debug2("\t Source IP: %s Dest.IP: %s type: ",
        hdr->saddr.str().c_str(), hdr->daddr.str().c_str() );

  switch(hdr->protocol){
  case IP4_ICMP:
    debug2("\t ICMP \n");
    icmp_handler_(pckt);
    break;
  case IP4_UDP:
    debug2("\t UDP \n");
    udp_handler_(pckt);
    break;
  case IP4_TCP:
    tcp_handler_(pckt);
    debug2("\t TCP \n");
    break;
  default:
    debug("\t UNKNOWN %i \n", hdr->protocol);
    break;
  }

  return -1;
};

uint16_t IP4::checksum(ip_header* hdr)
{
  return net::checksum((uint16_t*) hdr, sizeof(ip_header));
}

int IP4::transmit(Packet_ptr pckt)
{
  //DEBUG Issue #102 :
  // Now _local_ip fails first, while _netmask fails if we remove local ip
  assert(pckt->size() > sizeof(IP4::full_header));

  full_header* full_hdr = (full_header*) pckt->buffer();
  ip_header* hdr = &full_hdr->ip_hdr;

  /*
  hdr->version_ihl = 0x45; // IPv.4, Size 5 x 32-bit
  hdr->tos = 0; // Unused
  hdr->tot_len = __builtin_bswap16(pckt->size() - sizeof(Ethernet::header));
  hdr->id = 0; // Fragment ID (we don't fragment yet)
  hdr->frag_off_flags = 0x40; // "No fragment" flag set, nothing else
  hdr->ttl = 64; // What Linux / netcat does
  */

  // Checksum is 0 while calculating
  hdr->check = 0;
  hdr->check = checksum(hdr);

  /*
  // Make sure it's right
  //assert(checksum(hdr) == 0);

  // Calculate next-hop
  //assert(pckt->next_hop().whole == 0);

  // Set destination address to "my ip"
  // @TODO Don't know if this is good for routing...
  hdr->saddr.whole = local_ip_.whole;
  //ASSERT(! hdr->saddr.whole)

  std::shared_ptr<PacketIP4> p4 =
      std::static_pointer_cast<PacketIP4> (pckt);

  debug2("<IP4 TOP> Dest: %s, Source: %s\n",
        p4->dst().str().c_str(),
        p4->src().str().c_str());
  */

  // create local and target subnets
  addr target, local;
  target.whole = hdr->daddr.whole & netmask_.whole;
  local.whole  = local_ip_.whole  & netmask_.whole;
  // compare subnets to know where to send packet
  pckt->next_hop(target == local ? hdr->daddr : gateway_);

  debug2("<IP4 TOP> Next hop for %s, (netmask %s, local IP: %s, gateway: %s) == %s\n",
        hdr->daddr.str().c_str(),
        netmask_.str().c_str(),
        local_ip_.str().c_str(),
        gateway_.str().c_str(),
        target == local ? "DIRECT" : "GATEWAY");

  debug2("<IP4 transmit> my ip: %s, Next hop: %s\n",
        local_ip_.str().c_str(),
        pckt->next_hop().str().c_str());

  return linklayer_out_(pckt);
}

/** Empty handler for delegates initialization */
int net::ignore_ip4_up(std::shared_ptr<Packet> UNUSED(pckt)){
  debug("<IP4> Empty handler. Ignoring.\n");
  return -1;
}

int net::ignore_ip4_down(std::shared_ptr<Packet> UNUSED(pckt)){

  debug("<IP4->Link layer> No handler - DROP!\n");
  return 0;
}

IP4::IP4(Inet<LinkLayer, IP4>& inet) :
  local_ip_(inet.ip_addr()),
  netmask_(inet.netmask())
{
  // Default gateway is addr 1 in the subnet.
  const uint32_t DEFAULT_GATEWAY = __builtin_bswap32(1);

  gateway_.whole = (local_ip_.whole & netmask_.whole) | DEFAULT_GATEWAY;

  debug("<IP4> Local IP @ %p, Netmask @ %p \n",
        (void*) &local_ip_,
        (void*) &netmask_);
}
<|endoftext|>


<commit_before>void    readCDB (TObject *task1);
//_____________________________________________________________________________
AliAnalysisTask  *AddTaskT0Calib(Int_t runNumber)
{
  //
  // add calibration task
  //
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskT0Calib", "No analysis manager to connect to.");
    return NULL;
  }

  // check the input handler
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskT0Calib", "This task requires an input event handler");
    return NULL;
  }

  // set TPC OCDB parameters
  //ConfigOCDB(runNumber);

  // setup task
  AliT0CalibOffsetChannelsTask  *task1 = new AliT0CalibOffsetChannelsTask("CalibObjectsTrain1");
  readCDB(task1, runNumber);
   mgr->AddTask(task1);

  //  AliT0AnalysisTaskQA * task2 = new AliT0AnalysisTaskQA("QA task");
  //    mgr->AddTask(task2);

  AliAnalysisDataContainer *cinput1 = mgr->GetCommonInputContainer();
  if (!cinput1) cinput1 = mgr->CreateContainer("cchain",TChain::Class(),
                                      AliAnalysisManager::kInputContainer);
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("T0Calib",TObjArray::Class(), AliAnalysisManager::kOutputContainer, "AliESDfriends_v1.root");

  mgr->ConnectInput(task1,0,cinput1);
  mgr->ConnectOutput(task1,1,coutput1);
  return task1;
}
//_____________________________________________________________________________
void    readCDB (TObject *task1,  Int_t runNumber) {

  Float_t zero_timecdb[24]={0};
  Float_t *timecdb = zero_timecdb;
  Float_t cfdvalue[24][5];
  for(Int_t i=0; i<24; i++)
    for (Int_t i0=0; i0<5; i0++)
      cfdvalue[i][i0] = 0;

  Float_t zero_shiftcdb[4]={0};
  Float_t *shiftcdb = zero_shiftcdb;
  AliT0CalibOffsetChannelsTask *mytask = (AliT0CalibOffsetChannelsTask*)task1;

  AliCDBManager* man = AliCDBManager::Instance();
  AliCDBEntry *entry = AliCDBManager::Instance()->Get("GRP/CTP/CTPtiming");
  if (!entry) AliFatal("CTP timing parameters are not found in OCDB !");
  AliCTPTimeParams *ctpParams = (AliCTPTimeParams*)entry->GetObject();
  Float_t l1Delay = (Float_t)ctpParams->GetDelayL1L0()*25.0;

  AliCDBEntry *entry1 = AliCDBManager::Instance()->Get("GRP/CTP/TimeAlign");
  if (!entry1) AliFatal("CTP time-alignment is not found in OCDB !");
  AliCTPTimeParams *ctpTimeAlign = (AliCTPTimeParams*)entry1->GetObject();
  l1Delay += ((Float_t)ctpTimeAlign->GetDelayL1L0()*25.0);

  AliCDBEntry *entry4 = AliCDBManager::Instance()->Get("GRP/Calib/LHCClockPhase");
  if (!entry4) AliFatal("LHC clock-phase shift is not found in OCDB !");
  AliLHCClockPhase *phase = (AliLHCClockPhase*)entry4->GetObject();
  Float_t fGRPdelays = l1Delay - phase->GetMeanPhase();

  AliCDBEntry* entry5 = AliCDBManager::Instance()->Get("GRP/GRP/Data");
  AliGRPObject* grpData = dynamic_cast<AliGRPObject*>(entry5->GetObject());
  if (!grpData) {
    ::Error("AddTaskT0Calib","Failed to get GRP data for run %d",runNumber);
    return;
  }

  TString LHCperiod = grpData->GetLHCPeriod();
  Bool_t isLHC10b =  LHCperiod.Contains("LHC10b");
  Bool_t isLHC10c =  LHCperiod.Contains("LHC10c");

  ::Info("AddTaskT0Calib","LHCperiod:%s  --->  isLHC10b:%d isLHC10c:%d",
	 LHCperiod.Data(),(Int_t)isLHC10b, (Int_t)isLHC10c);

  if(isLHC10b || isLHC10c) mytask-> SetRefPMT(12,2);

  AliCDBEntry *entryCalib0 = man->Get("T0/Calib/Latency");
  if(!entryCalib0) {
    ::Error("AddTastT0Calib","Cannot find any AliCDBEntry for [Calib, Latency]!");
    return;
  }
  AliT0CalibLatency *calibda=(AliT0CalibLatency*)entryCalib0->GetObject();
  Float_t fLatencyL1 = calibda->GetLatencyL1();
  Float_t fLatencyHPTDC = calibda->GetLatencyHPTDC();

  AliCDBEntry *entryCalib1 = man->Get("T0/Calib/TimeDelay");
  if(!entryCalib1) {
    ::Error("AddTaskT0Calib","Cannot find any AliCDBEntry for [Calib, TimeDelay]!");
    return;
  }
  else
    {
      AliT0CalibTimeEq *clb = (AliT0CalibTimeEq*)entryCalib1->GetObject();
      timecdb = clb->GetTimeEq();
      for(Int_t i=0; i<24; i++)
	for (Int_t i0=0; i0<5; i0++){
	  cfdvalue[i][i0] = clb->GetCFDvalue(i, i0);
	}
    }

  for (Int_t i=0; i<24; i++) {
    Float_t cfdmean = cfdvalue[i][0];
    if( cfdvalue[i][0] < 500 || cfdvalue[i][0] > 50000) cfdmean = ( 1000.*fLatencyHPTDC - 1000.*fLatencyL1 + 1000.*fGRPdelays)/24.4;
     mytask->SetCFDvalue(i, cfdmean);
    mytask->SetTimeEq(i, timecdb[i]);
  }

  AliCDBEntry *entryCalib2 = man->Get("T0/Calib/TimeAdjust");
  if(!entryCalib2) {
    ::Error("AddTaskT0Calib","Cannot find any AliCDBEntry for [Calib, TimeAdjust]!");
  }
 else
    {
      AliT0CalibSeasonTimeShift *clb1 = (AliT0CalibSeasonTimeShift*)entryCalib2->GetObject();
      shiftcdb = clb1->GetT0Means();
    }

  for (Int_t i=0; i<4; i++)  mytask->SetT0Means(i,shiftcdb[i]);
}
<commit_msg>Revert "set refrence PMT=2 if LHC10bc"<commit_after>
void    readCDB (TObject *task1);
//_____________________________________________________________________________
AliAnalysisTask  *AddTaskT0Calib(Int_t runNumber)
{
  //
  // add calibration task
  //
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskT0Calib", "No analysis manager to connect to.");
    return NULL;
  }

  // check the input handler
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskT0Calib", "This task requires an input event handler");
    return NULL;
  }

  // set TPC OCDB parameters
  //ConfigOCDB(runNumber);

  // setup task
  AliT0CalibOffsetChannelsTask  *task1 = new AliT0CalibOffsetChannelsTask("CalibObjectsTrain1");
  readCDB(task1, runNumber);
   mgr->AddTask(task1);

  //  AliT0AnalysisTaskQA * task2 = new AliT0AnalysisTaskQA("QA task");
  //    mgr->AddTask(task2);

  AliAnalysisDataContainer *cinput1 = mgr->GetCommonInputContainer();
  if (!cinput1) cinput1 = mgr->CreateContainer("cchain",TChain::Class(),
                                      AliAnalysisManager::kInputContainer);
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("T0Calib",TObjArray::Class(), AliAnalysisManager::kOutputContainer, "AliESDfriends_v1.root");

  mgr->ConnectInput(task1,0,cinput1);
  mgr->ConnectOutput(task1,1,coutput1);
  return task1;
}
//_____________________________________________________________________________
void    readCDB (TObject *task1,  Int_t runNumber) {

  Float_t zero_timecdb[24]={0};
  Float_t *timecdb = zero_timecdb;
  Float_t cfdvalue[24][5];
  for(Int_t i=0; i<24; i++)
    for (Int_t i0=0; i0<5; i0++)
      cfdvalue[i][i0] = 0;

  Float_t zero_shiftcdb[4]={0};
  Float_t *shiftcdb = zero_shiftcdb;
  AliT0CalibOffsetChannelsTask *mytask = (AliT0CalibOffsetChannelsTask*)task1;

  AliCDBManager* man = AliCDBManager::Instance();
  AliCDBEntry *entry = AliCDBManager::Instance()->Get("GRP/CTP/CTPtiming");
  if (!entry) AliFatal("CTP timing parameters are not found in OCDB !");
  AliCTPTimeParams *ctpParams = (AliCTPTimeParams*)entry->GetObject();
  Float_t l1Delay = (Float_t)ctpParams->GetDelayL1L0()*25.0;

  AliCDBEntry *entry1 = AliCDBManager::Instance()->Get("GRP/CTP/TimeAlign");
  if (!entry1) AliFatal("CTP time-alignment is not found in OCDB !");
  AliCTPTimeParams *ctpTimeAlign = (AliCTPTimeParams*)entry1->GetObject();
  l1Delay += ((Float_t)ctpTimeAlign->GetDelayL1L0()*25.0);

  AliCDBEntry *entry4 = AliCDBManager::Instance()->Get("GRP/Calib/LHCClockPhase");
  if (!entry4) AliFatal("LHC clock-phase shift is not found in OCDB !");
  AliLHCClockPhase *phase = (AliLHCClockPhase*)entry4->GetObject();
  Float_t fGRPdelays = l1Delay - phase->GetMeanPhase();

  AliCDBEntry* entry5 = AliCDBManager::Instance()->Get("GRP/GRP/Data");
  AliGRPObject* grpData = dynamic_cast<AliGRPObject*>(entry5->GetObject());
  if (!grpData) {
    ::Error("AddTaskT0Calib","Failed to get GRP data for run %d",runNumber);
    return;
  }

  TString LHCperiod = grpData->GetLHCPeriod();
  Bool_t isLHC10b =  LHCperiod.Contains("LHC10b");
  Bool_t isLHC10c =  LHCperiod.Contains("LHC10c");

  ::Info("AddTaskT0Calib","LHCperiod:%s  --->  isLHC10b:%d isLHC10c:%d",
	 LHCperiod.Data(),(Int_t)isLHC10b, (Int_t)isLHC10c);

  if(isLHC10b || isLHC10c) mytask-> SetRefPMT(12,2);

  AliCDBEntry *entryCalib0 = man->Get("T0/Calib/Latency");
  if(!entryCalib0) {
    ::Error("AddTastT0Calib","Cannot find any AliCDBEntry for [Calib, Latency]!");
    return;
  }
  AliT0CalibLatency *calibda=(AliT0CalibLatency*)entryCalib0->GetObject();
  Float_t fLatencyL1 = calibda->GetLatencyL1();
  Float_t fLatencyHPTDC = calibda->GetLatencyHPTDC();

  AliCDBEntry *entryCalib1 = man->Get("T0/Calib/TimeDelay");
  if(!entryCalib1) {
    ::Error("AddTaskT0Calib","Cannot find any AliCDBEntry for [Calib, TimeDelay]!");
    return;
  }
  else
    {
      AliT0CalibTimeEq *clb = (AliT0CalibTimeEq*)entryCalib1->GetObject();
      timecdb = clb->GetTimeEq();
      for(Int_t i=0; i<24; i++)
	for (Int_t i0=0; i0<5; i0++){
	  cfdvalue[i][i0] = clb->GetCFDvalue(i, i0);
	}
    }

  for (Int_t i=0; i<24; i++) {
    Float_t cfdmean = cfdvalue[i][0];
    if( cfdvalue[i][0] < 500 || cfdvalue[i][0] > 50000) cfdmean = ( 1000.*fLatencyHPTDC - 1000.*fLatencyL1 + 1000.*fGRPdelays)/24.4;
     mytask->SetCFDvalue(i, cfdmean);
    mytask->SetTimeEq(i, timecdb[i]);
  }

  AliCDBEntry *entryCalib2 = man->Get("T0/Calib/TimeAdjust");
  if(!entryCalib2) {
    ::Error("AddTaskT0Calib","Cannot find any AliCDBEntry for [Calib, TimeAdjust]!");
  }
 else
    {
      AliT0CalibSeasonTimeShift *clb1 = (AliT0CalibSeasonTimeShift*)entryCalib2->GetObject();
      shiftcdb = clb1->GetT0Means();
    }

  for (Int_t i=0; i<4; i++)  mytask->SetT0Means(i,shiftcdb[i]);
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestAMRBox.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkAMRBox.h"

int TestAMRBox(int , char *[])
{
  // Equality.
  {
  vtkAMRBox A(-8,-8,-8,-4,-4,-4);
  vtkAMRBox B(-8,-8,-8,-4,-4,-4);
  vtkAMRBox C(-8,-8,-8,-1,-1,-1);
  vtkAMRBox D;
  vtkAMRBox E(-8,-8,-4,-4);
  vtkAMRBox F(-8,-8,-4,-4);
  vtkAMRBox G(-12,-12,-4,-4);
  if ( !(A==A)
    || !(A==B)
    || A==C
    || A==D
    || D==A
    || A==E
    || E==A
    || !(E==E)
    || !(E==F)
    || E==G)
    {
    A.Print(cerr) << endl;
    B.Print(cerr) << endl;
    C.Print(cerr) << endl;
    D.Print(cerr) << endl;
    E.Print(cerr) << endl;
    F.Print(cerr) << endl;
    G.Print(cerr) << endl;
    cerr << "Failed testing operator===." << endl;
    return 1;
    }
  }
  // Coarsen then refine.
  {
  vtkAMRBox A0(-8,-8,-8,7,7,7);
  vtkAMRBox B0(-8,-8,-8,8,8,8); // can't coarsen
  vtkAMRBox C(-1,-1,-1,0,0,0);

  vtkAMRBox A1(A0);
  A1.Coarsen(8);      // ==C
  vtkAMRBox A2(A1);
  A2.Refine(8);       // ==A0

  vtkAMRBox B1(B0);
  B1.Coarsen(8);      // ==B0

  vtkAMRBox D0(-8,-8,7,7);
  vtkAMRBox E0(-8,-8,8,8); // can't coarsen
  vtkAMRBox F(-1,-1,0,0);

  vtkAMRBox D1(D0);
  D1.Coarsen(8);      // ==F
  vtkAMRBox D2(D1);
  D2.Refine(8);       // ==D0

  vtkAMRBox E1(E0);
  E1.Coarsen(8);      // ==E0

  if ( !(A1==C)
    || !(B1==B0)
    || !(A2==A0)
    || !(D1==F)
    || !(D2==D0)
    || !(E1==E0))
    {
    A0.Print(cerr) << endl;
    B0.Print(cerr) << endl;
    C.Print(cerr) << endl;
    A1.Print(cerr) << endl;
    A2.Print(cerr) << endl;
    B1.Print(cerr) << endl;
    D0.Print(cerr) << endl;
    E0.Print(cerr) << endl;
    F.Print(cerr) << endl;
    D1.Print(cerr) << endl;
    D2.Print(cerr) << endl;
    E1.Print(cerr) << endl;
    cerr << "Failed testing refine coarsened." << endl;
    return 1;
    }
  }
  // Refine then coarsen.
  {
  vtkAMRBox A0(-1,-1,-1,0,0,0);
  vtkAMRBox B(-8,-8,-8,7,7,7);

  vtkAMRBox A1(A0);
  A1.Refine(8);      // ==B
  vtkAMRBox A2(A1);
  A2.Coarsen(8);     // ==A0

  vtkAMRBox D0(-1,-1,0,0);
  vtkAMRBox E(-8,-8,7,7);

  vtkAMRBox D1(D0);
  D1.Refine(8);      // ==E
  vtkAMRBox D2(D1);
  D2.Coarsen(8);     // ==D0

  if ( !(A1==B)
    || !(A2==A0)
    || !(D1==E)
    || !(D2==D0))
    {
    A0.Print(cerr) << endl;
    B.Print(cerr) << endl;
    A1.Print(cerr) << endl;
    A2.Print(cerr) << endl;
    D0.Print(cerr) << endl;
    E.Print(cerr) << endl;
    D1.Print(cerr) << endl;
    D2.Print(cerr) << endl;
    cerr << "Failed testing coarsen refined." << endl;
    return 1;
    }
  }
  // Shift.
  {
  vtkAMRBox A(-2,-2,-2,2,2,2);
  vtkAMRBox B(A);
  B.Shift(100,0,0);
  B.Shift(0,100,0);
  B.Shift(0,0,100);
  B.Shift(-200,-200,-200);
  B.Shift(100,0,0);
  B.Shift(0,100,0);
  B.Shift(0,0,100); // ==A

  vtkAMRBox C(-2,-2,2,2);
  vtkAMRBox D(C);
  D.Shift(100,0,0);
  D.Shift(0,100,0);
  D.Shift(0,0,100);
  D.Shift(-200,-200,-200);
  D.Shift(100,0,0);
  D.Shift(0,100,0);
  D.Shift(0,0,100); // ==C

  if ( !(B==A)
    || !(D==C))
    {
    A.Print(cerr) << endl;
    B.Print(cerr) << endl;
    C.Print(cerr) << endl;
    D.Print(cerr) << endl;
    cerr << "Failed testing shift." << endl;
    return 1;
    }
  }
  // Grow/shrink.
  {
  vtkAMRBox A(-2,-2,-2,2,2,2);
  vtkAMRBox B(-4,-4,-4,4,4,4);
  vtkAMRBox A1(A);
  A1.Grow(2);       // ==B
  vtkAMRBox A2(A1);
  A2.Shrink(2);     // ==A

  vtkAMRBox C(-2,-2,2,2);
  vtkAMRBox D(-4,-4,4,4);
  vtkAMRBox C1(C);
  C1.Grow(2);       // ==D
  vtkAMRBox C2(C1);
  C2.Shrink(2);     // ==C

  if ( !(A2==A)
    || !(A1==B)
    || !(C2==C)
    || !(C1==D))
    {
    A.Print(cerr) << endl;
    B.Print(cerr) << endl;
    A1.Print(cerr) << endl;
    A2.Print(cerr) << endl;
    C.Print(cerr) << endl;
    D.Print(cerr) << endl;
    C1.Print(cerr) << endl;
    C2.Print(cerr) << endl;
    cerr << "Failed tetsing grow/shrink." << endl;
    return 1;
    }
  }
  // Intersect.
  {
  vtkAMRBox A(-4,-4,-4,4,4,4);
  vtkAMRBox B(-4,-4,-4,-1,-1,-1);
  vtkAMRBox C(1,1,1,4,4,4);
  vtkAMRBox AA(A);
  AA&=A;              // ==A
  vtkAMRBox AB(A);
  AB&=B;              // ==B
  vtkAMRBox BA(B);
  BA&=A;              // ==B
  vtkAMRBox AC(A);
  AC&=C;              // ==C
  vtkAMRBox CA(C);
  CA&=A;              // ==C
  vtkAMRBox BC(B);
  BC&=C;              // ==NULL
  vtkAMRBox CB(C);
  CB&=B;              // ==NULL

  vtkAMRBox D(-4,-4,4,4);
  vtkAMRBox E(-4,-4,-1,-1);
  vtkAMRBox F(1,1,4,4);
  vtkAMRBox DD(D);
  DD&=D;              // ==D
  vtkAMRBox DE(D);
  DE&=E;              // ==E
  vtkAMRBox ED(E);
  ED&=D;              // ==E
  vtkAMRBox DF(D);
  DF&=F;              // ==F
  vtkAMRBox FD(F);
  FD&=D;              // ==F
  vtkAMRBox EF(E);
  EF&=F;              // ==NULL
  vtkAMRBox FE(F);
  FE&=E;              // ==NULL

  vtkAMRBox AD(A);
  AD&=D;              // ==NULL
  vtkAMRBox DA(D);
  DA&=A;              // ==NULL

  if (!(AA==A)
   || !(AB==B) || !(BA==AB)
   || !(AC==C) || !(AC==CA)
   || !BC.Empty() || !CB.Empty()
   || !(DD==D)
   || !(DE==E) || !(DE==ED)
   || !(DF==F) || !(DF==FD)
   || !EF.Empty() || !FE.Empty()
   || !(AD==A)
   || !(DA==D))
    {
    A.Print(cerr) << endl;
    B.Print(cerr) << endl;
    C.Print(cerr) << endl;
    AA.Print(cerr) << endl;
    AB.Print(cerr) << endl;
    BA.Print(cerr) << endl;
    AC.Print(cerr) << endl;
    CA.Print(cerr) << endl;
    BC.Print(cerr) << endl;
    CB.Print(cerr) << endl;
    D.Print(cerr) << endl;
    E.Print(cerr) << endl;
    F.Print(cerr) << endl;
    DD.Print(cerr) << endl;
    DE.Print(cerr) << endl;
    ED.Print(cerr) << endl;
    DF.Print(cerr) << endl;
    FD.Print(cerr) << endl;
    FE.Print(cerr) << endl;
    EF.Print(cerr) << endl;
    AD.Print(cerr) << endl;
    DA.Print(cerr) << endl;
    cerr << "Failed testing operator&=." << endl;
    return 1;
    }
  }
  // Serialize/Deserialize
  {
    vtkAMRBox A( 0,0,0, 9,9,9 );
    unsigned char *buffer = NULL;
    size_t bytesize       = 0;
    A.Serialize( buffer, bytesize );
    if( (buffer == NULL) || (bytesize == 0) )
      {
      std::cerr << "Failed serializing AMR box." << std::endl;
      return 1;
      }
    size_t expectedByteSize = sizeof( int )+( 6*sizeof(double) );
    if( bytesize != expectedByteSize )
      {
      std::cerr << "Bytesize of buffer did not match expected size.\n";
      return 1;
      }

    vtkAMRBox B;
    B.Deserialize( buffer, bytesize );

    if( !(A == B) )
      {
      std::cerr << "Deserialization of AMR box did not match initial box.\n";
      return 1;
      }

  }
  return 0;
}

<commit_msg>ENH: Updated Serialization/Deserialization test<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestAMRBox.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkAMRBox.h"

int TestAMRBox(int , char *[])
{
  // Equality.
  {
  vtkAMRBox A(-8,-8,-8,-4,-4,-4);
  vtkAMRBox B(-8,-8,-8,-4,-4,-4);
  vtkAMRBox C(-8,-8,-8,-1,-1,-1);
  vtkAMRBox D;
  vtkAMRBox E(-8,-8,-4,-4);
  vtkAMRBox F(-8,-8,-4,-4);
  vtkAMRBox G(-12,-12,-4,-4);
  if ( !(A==A)
    || !(A==B)
    || A==C
    || A==D
    || D==A
    || A==E
    || E==A
    || !(E==E)
    || !(E==F)
    || E==G)
    {
    A.Print(cerr) << endl;
    B.Print(cerr) << endl;
    C.Print(cerr) << endl;
    D.Print(cerr) << endl;
    E.Print(cerr) << endl;
    F.Print(cerr) << endl;
    G.Print(cerr) << endl;
    cerr << "Failed testing operator===." << endl;
    return 1;
    }
  }
  // Coarsen then refine.
  {
  vtkAMRBox A0(-8,-8,-8,7,7,7);
  vtkAMRBox B0(-8,-8,-8,8,8,8); // can't coarsen
  vtkAMRBox C(-1,-1,-1,0,0,0);

  vtkAMRBox A1(A0);
  A1.Coarsen(8);      // ==C
  vtkAMRBox A2(A1);
  A2.Refine(8);       // ==A0

  vtkAMRBox B1(B0);
  B1.Coarsen(8);      // ==B0

  vtkAMRBox D0(-8,-8,7,7);
  vtkAMRBox E0(-8,-8,8,8); // can't coarsen
  vtkAMRBox F(-1,-1,0,0);

  vtkAMRBox D1(D0);
  D1.Coarsen(8);      // ==F
  vtkAMRBox D2(D1);
  D2.Refine(8);       // ==D0

  vtkAMRBox E1(E0);
  E1.Coarsen(8);      // ==E0

  if ( !(A1==C)
    || !(B1==B0)
    || !(A2==A0)
    || !(D1==F)
    || !(D2==D0)
    || !(E1==E0))
    {
    A0.Print(cerr) << endl;
    B0.Print(cerr) << endl;
    C.Print(cerr) << endl;
    A1.Print(cerr) << endl;
    A2.Print(cerr) << endl;
    B1.Print(cerr) << endl;
    D0.Print(cerr) << endl;
    E0.Print(cerr) << endl;
    F.Print(cerr) << endl;
    D1.Print(cerr) << endl;
    D2.Print(cerr) << endl;
    E1.Print(cerr) << endl;
    cerr << "Failed testing refine coarsened." << endl;
    return 1;
    }
  }
  // Refine then coarsen.
  {
  vtkAMRBox A0(-1,-1,-1,0,0,0);
  vtkAMRBox B(-8,-8,-8,7,7,7);

  vtkAMRBox A1(A0);
  A1.Refine(8);      // ==B
  vtkAMRBox A2(A1);
  A2.Coarsen(8);     // ==A0

  vtkAMRBox D0(-1,-1,0,0);
  vtkAMRBox E(-8,-8,7,7);

  vtkAMRBox D1(D0);
  D1.Refine(8);      // ==E
  vtkAMRBox D2(D1);
  D2.Coarsen(8);     // ==D0

  if ( !(A1==B)
    || !(A2==A0)
    || !(D1==E)
    || !(D2==D0))
    {
    A0.Print(cerr) << endl;
    B.Print(cerr) << endl;
    A1.Print(cerr) << endl;
    A2.Print(cerr) << endl;
    D0.Print(cerr) << endl;
    E.Print(cerr) << endl;
    D1.Print(cerr) << endl;
    D2.Print(cerr) << endl;
    cerr << "Failed testing coarsen refined." << endl;
    return 1;
    }
  }
  // Shift.
  {
  vtkAMRBox A(-2,-2,-2,2,2,2);
  vtkAMRBox B(A);
  B.Shift(100,0,0);
  B.Shift(0,100,0);
  B.Shift(0,0,100);
  B.Shift(-200,-200,-200);
  B.Shift(100,0,0);
  B.Shift(0,100,0);
  B.Shift(0,0,100); // ==A

  vtkAMRBox C(-2,-2,2,2);
  vtkAMRBox D(C);
  D.Shift(100,0,0);
  D.Shift(0,100,0);
  D.Shift(0,0,100);
  D.Shift(-200,-200,-200);
  D.Shift(100,0,0);
  D.Shift(0,100,0);
  D.Shift(0,0,100); // ==C

  if ( !(B==A)
    || !(D==C))
    {
    A.Print(cerr) << endl;
    B.Print(cerr) << endl;
    C.Print(cerr) << endl;
    D.Print(cerr) << endl;
    cerr << "Failed testing shift." << endl;
    return 1;
    }
  }
  // Grow/shrink.
  {
  vtkAMRBox A(-2,-2,-2,2,2,2);
  vtkAMRBox B(-4,-4,-4,4,4,4);
  vtkAMRBox A1(A);
  A1.Grow(2);       // ==B
  vtkAMRBox A2(A1);
  A2.Shrink(2);     // ==A

  vtkAMRBox C(-2,-2,2,2);
  vtkAMRBox D(-4,-4,4,4);
  vtkAMRBox C1(C);
  C1.Grow(2);       // ==D
  vtkAMRBox C2(C1);
  C2.Shrink(2);     // ==C

  if ( !(A2==A)
    || !(A1==B)
    || !(C2==C)
    || !(C1==D))
    {
    A.Print(cerr) << endl;
    B.Print(cerr) << endl;
    A1.Print(cerr) << endl;
    A2.Print(cerr) << endl;
    C.Print(cerr) << endl;
    D.Print(cerr) << endl;
    C1.Print(cerr) << endl;
    C2.Print(cerr) << endl;
    cerr << "Failed tetsing grow/shrink." << endl;
    return 1;
    }
  }
  // Intersect.
  {
  vtkAMRBox A(-4,-4,-4,4,4,4);
  vtkAMRBox B(-4,-4,-4,-1,-1,-1);
  vtkAMRBox C(1,1,1,4,4,4);
  vtkAMRBox AA(A);
  AA&=A;              // ==A
  vtkAMRBox AB(A);
  AB&=B;              // ==B
  vtkAMRBox BA(B);
  BA&=A;              // ==B
  vtkAMRBox AC(A);
  AC&=C;              // ==C
  vtkAMRBox CA(C);
  CA&=A;              // ==C
  vtkAMRBox BC(B);
  BC&=C;              // ==NULL
  vtkAMRBox CB(C);
  CB&=B;              // ==NULL

  vtkAMRBox D(-4,-4,4,4);
  vtkAMRBox E(-4,-4,-1,-1);
  vtkAMRBox F(1,1,4,4);
  vtkAMRBox DD(D);
  DD&=D;              // ==D
  vtkAMRBox DE(D);
  DE&=E;              // ==E
  vtkAMRBox ED(E);
  ED&=D;              // ==E
  vtkAMRBox DF(D);
  DF&=F;              // ==F
  vtkAMRBox FD(F);
  FD&=D;              // ==F
  vtkAMRBox EF(E);
  EF&=F;              // ==NULL
  vtkAMRBox FE(F);
  FE&=E;              // ==NULL

  vtkAMRBox AD(A);
  AD&=D;              // ==NULL
  vtkAMRBox DA(D);
  DA&=A;              // ==NULL

  if (!(AA==A)
   || !(AB==B) || !(BA==AB)
   || !(AC==C) || !(AC==CA)
   || !BC.Empty() || !CB.Empty()
   || !(DD==D)
   || !(DE==E) || !(DE==ED)
   || !(DF==F) || !(DF==FD)
   || !EF.Empty() || !FE.Empty()
   || !(AD==A)
   || !(DA==D))
    {
    A.Print(cerr) << endl;
    B.Print(cerr) << endl;
    C.Print(cerr) << endl;
    AA.Print(cerr) << endl;
    AB.Print(cerr) << endl;
    BA.Print(cerr) << endl;
    AC.Print(cerr) << endl;
    CA.Print(cerr) << endl;
    BC.Print(cerr) << endl;
    CB.Print(cerr) << endl;
    D.Print(cerr) << endl;
    E.Print(cerr) << endl;
    F.Print(cerr) << endl;
    DD.Print(cerr) << endl;
    DE.Print(cerr) << endl;
    ED.Print(cerr) << endl;
    DF.Print(cerr) << endl;
    FD.Print(cerr) << endl;
    FE.Print(cerr) << endl;
    EF.Print(cerr) << endl;
    AD.Print(cerr) << endl;
    DA.Print(cerr) << endl;
    cerr << "Failed testing operator&=." << endl;
    return 1;
    }
  }
  // Serialize/Deserialize
  {
    vtkAMRBox A( 0,0,0, 9,9,9 );
    unsigned char *buffer = NULL;
    size_t bytesize       = 0;
    A.Serialize( buffer, bytesize );
    if( (buffer == NULL) || (bytesize == 0) )
      {
      std::cerr << "Failed serializing AMR box." << std::endl;
      return 1;
      }
    size_t expectedByteSize = vtkAMRBox::GetBytesize();
    if( bytesize != expectedByteSize )
      {
      std::cerr << "Bytesize of buffer did not match expected size.\n";
      return 1;
      }

    vtkAMRBox B;
    B.Deserialize( buffer, bytesize );

    if( !(A == B) )
      {
      std::cerr << "Deserialization of AMR box did not match initial box.\n";
      return 1;
      }

  }
  return 0;
}

<|endoftext|>