1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/******************************************************************************
*
*
*
* Copyright (C) 1997-2015 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
#ifndef STORE_H
#define STORE_H
#include <qglobal.h>
#include <stdio.h>
#include "portable.h"
/*! @brief Abstract interface for file based memory storage operations */
class StorageIntf
{
public:
/*! Required by gcc */
virtual ~StorageIntf() {}
/*! Read \a size bytes from the store into \a buf. */
virtual int read(char *buf,uint size) = 0;
/*! Write \a size bytes from \a buf into the store. */
virtual int write(const char *buf,uint size) = 0;
};
/*! @brief The Store is a file based memory manager.
*
* You can open the store using open(). Then obtain a handle via alloc()
* followed by a sequence of write() commands to store information,
* and finalize it using end().
*
* Later on you locate the information
* with seek() using the handle obtained with alloc(), and then use a
* sequence of read() calls to read the information back.
*
* If no longer needed the storage space can be freed using release().
*
* The store will dynamically grow the file on disk if needed.
*/
class Store : public StorageIntf
{
public:
/*! Creates a store. */
Store();
/*! Releases the store object. Will close the underlying file if opened. */
~Store();
/*! Opens the file underlying the store using \a name as the file name.
* Returns 0 upon success, or -1 otherwise.
*/
int open(const char *name);
/*! Allocates a handle to write to and read from. */
portable_off_t alloc();
/*! Writes \a size bytes in array \a buf to the store.
* First alloc() has to be called.
* \note The information can only be read after end() has been called.
*/
int write(const char *buf,uint size);
/*! Ends the sequence of writes.
* \note After this call, first alloc() has to be called
* before new writes can be done.
*/
void end();
/*! Releases the memory corresponding to the handle returned with alloc() */
void release(portable_off_t handle);
/*! Closes the store */
void close();
/*! Goes to the start of information corresponding to handle \a pos */
void seek(portable_off_t handle);
/*! Reads \a size bytes from the store into the array pointed to be \a buf.
* \note Before reading seek() has to be called to set the right start of the store.
*/
int read(char *buf,uint size);
void printStats();
portable_off_t pos() const { return m_cur; }
void dumpBlock(portable_off_t start,portable_off_t end);
private:
enum State
{
Init,
Reading,
Writing
};
struct Node
{
portable_off_t pos;
struct Node *next;
};
void printFreeList();
FILE *m_file;
portable_off_t m_front;
portable_off_t m_cur;
Node *m_head;
State m_state;
int m_reads;
int m_writes;
};
#endif
|