srecord  1.65.0
memory.h
Go to the documentation of this file.
1 //
2 // srecord - manipulate eprom load files
3 // Copyright (C) 1998-2003, 2006-2008, 2010, 2012-2014 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program. If not, see
17 // <http://www.gnu.org/licenses/>.
18 //
19 
20 #ifndef SRECORD_MEMORY_H
21 #define SRECORD_MEMORY_H
22 
23 #include <string>
24 
25 #include <srecord/defcon.h>
26 #include <srecord/input.h>
27 #include <srecord/memory/chunk.h>
28 #include <srecord/memory/walker.h>
29 #include <srecord/string.h>
30 
31 namespace srecord {
32 
33 class record; // forward
34 
35 /**
36  * The srecord::memory class is used to simulate memory contents.
37  * This allows staging of reord adta, and also validation of contents.
38  */
39 class memory
40 {
41 public:
42  /**
43  * The default constructor.
44  */
45  memory();
46 
47  /**
48  * The copy constructor.
49  */
50  memory(const memory &);
51 
52  /**
53  * The assignment operator.
54  */
55  memory &operator=(const memory &);
56 
57  /**
58  * The destructor.
59  */
61 
62  /**
63  * The set method is used to set the byte at the given `address'
64  * to the given `value'.
65  *
66  * Uses the find() method to locate the chunk, and then calls
67  * the memory_chunk::set method, to set the byte within
68  * the chunk.
69  */
70  void set(unsigned long address, int value);
71 
72  /**
73  * The get method is used to fetch the value of the byte at
74  * the given 'address'.
75  *
76  * If you fo a get on an address which has not been set() yet,
77  * the results are undefined.
78  *
79  * Uses the find() method to locate the chunk, and then calls
80  * the memory_chunk::get method, to get the byte within
81  * the chunk.
82  */
83  int get(unsigned long address) const;
84 
85  /**
86  * The set_p method is used to determine whether the byte at
87  * the given address has been set() yet. Returns true if
88  * already set, false if never been set.
89  *
90  * Uses the find() method to locate the chunk, and then calls
91  * the memory_chunk::set_p method, to get the status of
92  * the byte within the chunk.
93  */
94  bool set_p(unsigned long address) const;
95 
96  /**
97  * The walk method is used to apply a memory_walker derived
98  * class to every byte of memory.
99  */
101 
102  /**
103  * The reader method is used to read the given `input' source
104  * into memory. This method may be called multiple times,
105  * for multiple input files.
106  *
107  * If the input format supports headers, and the file has a
108  * header, the first header will be remembered, if set_header()
109  * was not called previously.
110  *
111  * @param input
112  * The source of the byte stream
113  * @param redundant_bytes
114  * ignore: do nothing
115  * warning: issue a warning and continue (default)
116  * error: issuse a atal error message, and exit failure.
117  * @param contradictory_bytes
118  * If the value at any address is set more than once,
119  * Thid argument controls what happeens.
120  * ignore: do nothing
121  * warning: issue a warning and continue (default)
122  * error: issuse a atal error message, and exit failure (default).
123  */
124  void reader(const input::pointer &input, defcon_t redundant_bytes,
125  defcon_t contradictory_bytes);
126 
127  /**
128  * The equal method may be used to determine if two memory
129  * instances are equal.
130  */
131  static bool equal(const memory &, const memory &);
132 
133  /**
134  * The compare method may be used to determine if two memory
135  * instances are equal. Verbose messages concerning the exact
136  * differences are printed if they are not equal.
137  */
138  static bool compare(const memory &, const memory &);
139 
140  /**
141  * The find_next_data method may be used to locate data at or
142  * following the `address' given. Returns false if there is
143  * no data meeting this criteria.
144  *
145  * If there is data, the `address' will be set to the start
146  * address of the data block. At most `nbytes' of data will
147  * be transfetrred into the `data' array. Then `nbytes' wil
148  * be set to the number of bytes transferred. Returns true.
149  *
150  * Calls the find_next_chunk() method.
151  */
152  bool find_next_data(unsigned long &address, void *data,
153  size_t &nbytes) const;
154 
155  /**
156  * The get_header method is used to determine the value of the
157  * header record set by either the reader() or set_header()
158  * methods. If neither has set a header, a NULL is returned.
159  */
160  record *get_header(void) const;
161 
162  /**
163  * The set_header method may be used to set the header command.
164  *
165  * @param value
166  * The `value' string, to set the header. The user may use URL
167  * encoding for of the more interesting non-printable byte values
168  * (eg. "%3F").
169  */
170  void set_header(const std::string &value);
171 
172  /**
173  * The get_execution_start_address method is used to determine the
174  * value of the execution start address record set by either the
175  * reader() or set_execution_start_address() methods. If neither
176  * has set an execution start address, NULL is returned.
177  */
179 
180  /**
181  * The set_execution_start_address method may be used to set the
182  * execution start address record.
183  */
184  void set_execution_start_address(unsigned long value);
185 
186  /**
187  * The has_holes method may be used to determine whether or not the
188  * memory data has "holes" in it.
189  *
190  * @returns
191  * true if the memory data is not continuous (has at least
192  * one hole), false if the memory data is continuous (has no
193  * holes).
194  */
195  bool has_holes(void) const;
196 
197  /**
198  * The get_lower_bound method is used to obtain the lower bound
199  * (lowest address) of the memory image.
200  */
201  unsigned long get_lower_bound() const;
202 
203  /**
204  * The get_upper_bound method is used to obtain the upper bound
205  * (maximum address plus one) of the memory image.
206  */
207  unsigned long get_upper_bound() const;
208 
209  /**
210  * The is_well_aligned method is used to test whether or not
211  * all of the data in the memory buffer is well aligned, on the
212  * given byte boundary.
213  *
214  * @param multiple
215  * The desired byte alignment.
216  *
217  * @note
218  * This isn't about holes, it's about the beginnings and
219  * endings of each consecitice run of bytes.
220  */
221  bool is_well_aligned(unsigned multiple) const;
222 
223  /**
224  * The empty method is used to determine whether or not this memory
225  * image has no data in it.
226  */
227  bool
228  empty(void)
229  const
230  {
231  return (nchunks == 0);
232  }
233 
234 private:
235  /**
236  * The nchunks instance variable is used to member how large
237  * our pool of memory chunks is. It is always <= nchunks_max;
238  */
239  mutable int nchunks;
240 
241  /**
242  * The max_chunks instance variable is used to rememberf the
243  * size of the chunk array, which holds the pool of memory chunks.
244  */
245  mutable int nchunks_max;
246 
247  /**
248  * The chunk instance variable is used to hold the pointer to
249  * the base of the chunk array. These chunks remember the
250  * settings of the various bytes. By using a sparse array,
251  * we can cope with arbitrary memory usages.
252  */
253  mutable memory_chunk **chunk;
254 
255  /**
256  * The find method is used to find the chunk which contains
257  * the given `address'. The chunk will be created if it
258  * doesn't exist.
259  *
260  * Called by the get(), set() and set_p() methods.
261  */
262  memory_chunk *find(unsigned long address) const;
263 
264  /**
265  * The cache instance variable is used to accellerate the find()
266  * method, based on the fact that most memory accesses are
267  * sequential, in the same chunk.
268  */
269  mutable memory_chunk *cache;
270 
271  /**
272  * The find_next_chunk method is used to visit each and every
273  * byte, in cases where the walk() method is not appropriate.
274  * Called by the find_next_data() method.
275  */
276  memory_chunk *find_next_chunk(unsigned long) const;
277 
278  /**
279  * The find_next_chunk_index instance variable is used by
280  * the find_next_chunk() method to keep track of where it is
281  * positioned across the chunk array.
282  */
283  mutable int find_next_chunk_index;
284 
285  /**
286  * The header instance variable is used to track the file header.
287  * It is set by the reader() and set_header() methods. It is
288  * read by the get_header() method.
289  */
290  record *header;
291 
292  /**
293  * The execution_start_address instance variable is used to track
294  * the execution start address. It is set by the reader() and
295  * set_execution_start_address() methods. It is read by the
296  * get_execution_start_address() method.
297  */
298  record *execution_start_address;
299 
300  /**
301  * The clear method is used to discard all data, as if when
302  * the instance was first constructed. Alsu used by the destructor.
303  */
304  void clear(void);
305 
306  /**
307  * The copy method is used to copy the chunks from the `src' into
308  * this object. Only to be used the the assignment operator.
309  */
310  void copy(const memory &src);
311 };
312 
313 };
314 
315 /**
316  * The equality operator. Used to test if two srecord::memory objects
317  * are equal. Calls the srecord::memory::equal() method.
318  */
320 
321 /**
322  * The inequality operator. Used to test if two srecord::memory objects
323  * are not equal. Calls the srecord::memory::equal() method.
324  */
326 
327 // vim: set ts=8 sw=4 et :
328 #endif // SRECORD_MEMORY_H
The srecord::input class is used to represent an abstract EPROM load file source.
Definition: input.h:39
std::shared_ptr< input > pointer
Definition: input.h:41
The srecord::memory_chunk class is used to represent portion of memory.
Definition: chunk.h:34
std::shared_ptr< memory_walker > pointer
Definition: walker.h:36
The srecord::memory class is used to simulate memory contents.
Definition: memory.h:40
void set_execution_start_address(unsigned long value)
The set_execution_start_address method may be used to set the execution start address record.
static bool compare(const memory &, const memory &)
The compare method may be used to determine if two memory instances are equal.
unsigned long get_upper_bound() const
The get_upper_bound method is used to obtain the upper bound (maximum address plus one) of the memory...
bool empty(void) const
The empty method is used to determine whether or not this memory image has no data in it.
Definition: memory.h:228
int get(unsigned long address) const
The get method is used to fetch the value of the byte at the given 'address'.
record * get_header(void) const
The get_header method is used to determine the value of the header record set by either the reader() ...
memory(const memory &)
The copy constructor.
void set_header(const std::string &value)
The set_header method may be used to set the header command.
bool is_well_aligned(unsigned multiple) const
The is_well_aligned method is used to test whether or not all of the data in the memory buffer is wel...
void walk(memory_walker::pointer) const
The walk method is used to apply a memory_walker derived class to every byte of memory.
~memory()
The destructor.
memory()
The default constructor.
static bool equal(const memory &, const memory &)
The equal method may be used to determine if two memory instances are equal.
record * get_execution_start_address(void) const
The get_execution_start_address method is used to determine the value of the execution start address ...
memory & operator=(const memory &)
The assignment operator.
void set(unsigned long address, int value)
The set method is used to set the byte at the given ‘address’ to the given ‘value’.
bool find_next_data(unsigned long &address, void *data, size_t &nbytes) const
The find_next_data method may be used to locate data at or following the ‘address’ given.
void reader(const input::pointer &input, defcon_t redundant_bytes, defcon_t contradictory_bytes)
The reader method is used to read the given ‘input’ source into memory.
bool set_p(unsigned long address) const
The set_p method is used to determine whether the byte at the given address has been set() yet.
bool has_holes(void) const
The has_holes method may be used to determine whether or not the memory data has "holes" in it.
unsigned long get_lower_bound() const
The get_lower_bound method is used to obtain the lower bound (lowest address) of the memory image.
The srecord::record class is used to represent a data record read from a file.
Definition: record.h:35
bool operator!=(const srecord::memory &, const srecord::memory &)
The inequality operator.
bool operator==(const srecord::memory &, const srecord::memory &)
The equality operator.
defcon_t
Definition: defcon.h:26