//
// srecord - manipulate eprom load files
// Copyright (C) 1998-2003, 2006, 2007 Peter Miller
//
// 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 3 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, see
// .
//
#ifndef INCLUDE_SREC_MEMORY_H
#define INCLUDE_SREC_MEMORY_H
#include
class srec_record; // forward
/**
* The srec_memory class is used to simulate memory contents.
* This allows staging of reord adta, and also validation of contents.
*/
class srec_memory
{
public:
/**
* The default constructor.
*/
srec_memory();
/**
* The copy constructor.
*/
srec_memory(const srec_memory &);
/**
* The assignment operator.
*/
srec_memory &operator=(const srec_memory &);
/**
* The destructor.
*/
~srec_memory();
/**
* The set method is used to set the byte at the given `address'
* to the given `value'.
*
* Uses the find() method to locate the chunk, and then calls
* the srec_memory_chunk::set method, to set the byte within
* the chunk.
*/
void set(unsigned long address, int value);
/**
* The get method is used to fetch the value of the byte at
* the given 'address'.
*
* If you fo a get on an address which has not been set() yet,
* the results are undefined.
*
* Uses the find() method to locate the chunk, and then calls
* the srec_memory_chunk::get method, to get the byte within
* the chunk.
*/
int get(unsigned long address) const;
/**
* The set_p method is used to determine whether the byte at
* the given address has been set() yet. Returns true if
* already set, false if never been set.
*
* Uses the find() method to locate the chunk, and then calls
* the srec_memory_chunk::set_p method, to get the status of
* the byte within the chunk.
*/
bool set_p(unsigned long address) const;
/**
* The walk method is used to apply a srec_memory_walker derived
* class to every byte of memory.
*/
void walk(class srec_memory_walker *) const;
/**
* The reader method is used to read the given `input' source
* into memory. This method may be called multiple times,
* for multiple input files.
*
* If the input format supports headers, and the file has a
* header, the first header will be remembered, if set_header()
* was not called previously.
*
* If the value at any address is set more than once, a fatal
* error will be issued, informing the user of the address
* and the contradictory values. If the allow_overwriting()
* method has been called previously, this will be a non-fatal
* warning, instead. If `barf' is false, no checking of any
* kind is performed.
*/
void reader(class srec_input *input, bool barf = false);
/**
* The equal method may be used to determine if two srec_memory
* instances are equal.
*/
static bool equal(const srec_memory &, const srec_memory &);
/**
* The compare method may be used to determine if two srec_memory
* instances are equal. Verbose messages concerning the exact
* differences are printed if they are not equal.
*/
static bool compare(const srec_memory &, const srec_memory &);
/**
* The find_next_data method may be used to locate data at or
* following the `address' given. Returns false if there is
* no data meeting this criteria.
*
* If there is data, the `address' will be set to the start
* address of the data block. At most `nbytes' of data will
* be transfetrred into the `data' array. Then `nbytes' wil
* be set to the number of bytes transferred. Returns true.
*
* Calls the find_next_chunk() method.
*/
bool find_next_data(unsigned long &address, void *data,
size_t &nbytes) const;
/**
* The allow_overwriting controls the error message behaviour of
* the reader() method. Once called, redundant and contradictory
* settings generate warnings, rather than fatal errors.
*/
static void allow_overwriting();
/**
* The get_header method is used to determine the value of the
* header record set by either the reader() or set_header()
* methods. If neither has set a header, NULL is returned.
*/
srec_record *get_header() const;
/**
* The set_header method may be used to set the header command.
* The `value' is a NUL terminated C string.
*/
void set_header(const char *value);
/**
* The get_start_address method is used to determine the value
* of the start address record set by either the reader()
* or set_start_address() methods. If neither has set a
* start_address, NULL is returned.
*/
srec_record *get_start_address() const;
/**
* The set_start_address method may be used to set the start
* address record.
*/
void set_start_address(unsigned long value);
/**
* The has_holes method may be used to determine whether or not the
* memory data has "holes" in it.
*
* @returns
* true if the memory data is not continuous (has at least
* one hole), false if the memory data is continuous (has no
* holes).
*/
bool has_holes() const;
private:
/**
* The overwrite static variable is used to remember whether
* or not we generate warnings when redundant or contradictory
* settings are deteccted by the reader() method.
*/
static bool overwrite;
/**
* The nchunks instance variable is used to member how large
* our pool of memory chunks is. It is always <= nchunks_max;
*/
mutable int nchunks;
/**
* The max_chunks instance variable is used to rememberf the
* size of the chunk array, which holds the pool of memory chunks.
*/
mutable int nchunks_max;
/**
* The chunk instance variable is used to hold the pointer to
* the base of the chunk array. These chuinks remember the
* settings of the various bytes. By using a sparse array,
* we can cope with arbitrary memory usages.
*/
mutable srec_memory_chunk **chunk;
/**
* The find method is used to find the chunk which contains
* the given `address'. The chunk will be created if it
* doesn't exist.
*
* Called by the get(), set() and set_p() methods.
*/
srec_memory_chunk *find(unsigned long address) const;
/**
* The cache instance variable is used to accellerate the find()
* method, based on the fact that most memory accesses are
* sequential, in the same chunk.
*/
mutable srec_memory_chunk *cache;
/**
* The find_next_chunk method is used to visit each and every
* byte, in cases where the walk() method is not appropriate.
* Called by the find_next_data() method.
*/
srec_memory_chunk *find_next_chunk(unsigned long) const;
/**
* The find_next_chunk_index instance variable is used by
* the find_next_chunk() method to keep track of where it is
* positioned across the chunk array.
*/
mutable int find_next_chunk_index;
/**
* The header instance variable is used to track the file header.
* It is set by the reader() and set_header() methods. It is
* read by the get_header() method.
*/
srec_record *header;
/**
* The start_address instance variable is used to track the start
* address. It is set by the reader() and set_start_address()
* methods. It is read by the get_start_address() method.
*/
srec_record *start_address;
/**
* The clear method is used to discard all data, as if when
* the instance was first constructed. Alsu used by the destructor.
*/
void clear();
/**
* The copy method is used to copy the chunks from the `src' into
* this object. Only to be used the the assignment operator.
*/
void copy(const srec_memory &src);
/**
* The get_upper_bound method is used to obtain the upper bound
* (maximum address plus one) of the memory image.
*/
unsigned long get_upper_bound() const;
};
/**
* The equality operator. Used to test if two srec_memory objects
* are equal. Calls the srec_memory::equal() method.
*/
bool operator == (const srec_memory &, const srec_memory &);
/**
* The inequality operator. Used to test if two srec_memory objects
* are not equal. Calls the srec_memory::equal() method.
*/
bool operator != (const srec_memory &, const srec_memory &);
#endif // INCLUDE_SREC_MEMORY_H