1 |
786 |
skrzyp |
// This file is part of the uSTL library, an STL implementation.
|
2 |
|
|
//
|
3 |
|
|
// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net>
|
4 |
|
|
// This file is free software, distributed under the MIT License.
|
5 |
|
|
|
6 |
|
|
#include "mistream.h"
|
7 |
|
|
#include "memblock.h"
|
8 |
|
|
#include "ualgo.h"
|
9 |
|
|
#include "umemory.h"
|
10 |
|
|
#ifdef CYGCLS_USTL_FSTREAMS
|
11 |
|
|
#include "fstream.h"
|
12 |
|
|
#endif
|
13 |
|
|
#include <errno.h>
|
14 |
|
|
#include "config.h"
|
15 |
|
|
|
16 |
|
|
namespace ustl {
|
17 |
|
|
|
18 |
|
|
memblock::memblock (void) : memlink (), m_Capacity (0) { }
|
19 |
|
|
memblock::memblock (const void* p, size_type n) : memlink (), m_Capacity (0) { assign (p, n); }
|
20 |
|
|
memblock::memblock (size_type n) : memlink (), m_Capacity (0) { resize (n); }
|
21 |
|
|
memblock::memblock (const cmemlink& b) : memlink (), m_Capacity (0) { assign (b); }
|
22 |
|
|
memblock::memblock (const memlink& b) : memlink (), m_Capacity (0) { assign (b); }
|
23 |
|
|
memblock::memblock (const memblock& b) : memlink (), m_Capacity (0) { assign (b); }
|
24 |
|
|
memblock::~memblock (void) throw() { deallocate(); }
|
25 |
|
|
|
26 |
|
|
void memblock::unlink (void) throw()
|
27 |
|
|
{
|
28 |
|
|
m_Capacity = 0;
|
29 |
|
|
memlink::unlink();
|
30 |
|
|
}
|
31 |
|
|
|
32 |
|
|
/// resizes the block to \p newSize bytes, reallocating if necessary.
|
33 |
|
|
void memblock::resize (size_type newSize, bool bExact)
|
34 |
|
|
{
|
35 |
|
|
if (m_Capacity < newSize + minimumFreeCapacity())
|
36 |
|
|
reserve (newSize, bExact);
|
37 |
|
|
memlink::resize (newSize);
|
38 |
|
|
}
|
39 |
|
|
|
40 |
|
|
/// Frees internal data.
|
41 |
|
|
void memblock::deallocate (void) throw()
|
42 |
|
|
{
|
43 |
|
|
if (m_Capacity) {
|
44 |
|
|
assert (cdata() && "Internal error: space allocated, but the pointer is NULL");
|
45 |
|
|
assert (data() && "Internal error: read-only block is marked as allocated space");
|
46 |
|
|
free (data());
|
47 |
|
|
}
|
48 |
|
|
unlink();
|
49 |
|
|
}
|
50 |
|
|
|
51 |
|
|
/// Assumes control of the memory block \p p of size \p n.
|
52 |
|
|
/// The block assigned using this function will be freed in the destructor.
|
53 |
|
|
void memblock::manage (void* p, size_type n)
|
54 |
|
|
{
|
55 |
|
|
assert (p || !n);
|
56 |
|
|
assert (!m_Capacity && "Already managing something. deallocate or unlink first.");
|
57 |
|
|
link (p, n);
|
58 |
|
|
m_Capacity = n;
|
59 |
|
|
}
|
60 |
|
|
|
61 |
|
|
/// "Instantiate" a linked block by allocating and copying the linked data.
|
62 |
|
|
void memblock::copy_link (void)
|
63 |
|
|
{
|
64 |
|
|
const pointer p (begin());
|
65 |
|
|
const size_t sz (size());
|
66 |
|
|
if (is_linked())
|
67 |
|
|
unlink();
|
68 |
|
|
assign (p, sz);
|
69 |
|
|
}
|
70 |
|
|
|
71 |
|
|
/// Copies data from \p p, \p n.
|
72 |
|
|
void memblock::assign (const void* p, size_type n)
|
73 |
|
|
{
|
74 |
|
|
assert ((p != (const void*) cdata() || size() == n) && "Self-assignment can not resize");
|
75 |
|
|
resize (n);
|
76 |
|
|
copy (p, n);
|
77 |
|
|
}
|
78 |
|
|
|
79 |
|
|
/// \brief Reallocates internal block to hold at least \p newSize bytes.
|
80 |
|
|
///
|
81 |
|
|
/// Additional memory may be allocated, but for efficiency it is a very
|
82 |
|
|
/// good idea to call reserve before doing byte-by-byte edit operations.
|
83 |
|
|
/// The block size as returned by size() is not altered. reserve will not
|
84 |
|
|
/// reduce allocated memory. If you think you are wasting space, call
|
85 |
|
|
/// deallocate and start over. To avoid wasting space, use the block for
|
86 |
|
|
/// only one purpose, and try to get that purpose to use similar amounts
|
87 |
|
|
/// of memory on each iteration.
|
88 |
|
|
///
|
89 |
|
|
void memblock::reserve (size_type newSize, bool bExact)
|
90 |
|
|
{
|
91 |
|
|
if ((newSize += minimumFreeCapacity()) <= m_Capacity)
|
92 |
|
|
return;
|
93 |
|
|
pointer oldBlock (is_linked() ? NULL : data());
|
94 |
|
|
const size_t alignedSize (Align (newSize, 64));
|
95 |
|
|
if (!bExact)
|
96 |
|
|
newSize = alignedSize;
|
97 |
|
|
pointer newBlock = (pointer) realloc (oldBlock, newSize);
|
98 |
|
|
if (!newBlock)
|
99 |
|
|
USTL_THROW(bad_alloc (newSize));
|
100 |
|
|
if (!oldBlock & (cdata() != NULL))
|
101 |
|
|
copy_n (cdata(), min (size() + 1, newSize), newBlock);
|
102 |
|
|
link (newBlock, size());
|
103 |
|
|
m_Capacity = newSize;
|
104 |
|
|
}
|
105 |
|
|
|
106 |
|
|
/// Shifts the data in the linked block from \p start to \p start + \p n.
|
107 |
|
|
memblock::iterator memblock::insert (iterator start, size_type n)
|
108 |
|
|
{
|
109 |
|
|
const uoff_t ip = start - begin();
|
110 |
|
|
assert (ip <= size());
|
111 |
|
|
resize (size() + n, false);
|
112 |
|
|
memlink::insert (iat(ip), n);
|
113 |
|
|
return (iat (ip));
|
114 |
|
|
}
|
115 |
|
|
|
116 |
|
|
/// Shifts the data in the linked block from \p start + \p n to \p start.
|
117 |
|
|
memblock::iterator memblock::erase (iterator start, size_type n)
|
118 |
|
|
{
|
119 |
|
|
const uoff_t ep = start - begin();
|
120 |
|
|
assert (ep + n <= size());
|
121 |
|
|
memlink::erase (start, n);
|
122 |
|
|
memlink::resize (size() - n);
|
123 |
|
|
return (iat (ep));
|
124 |
|
|
}
|
125 |
|
|
|
126 |
|
|
/// Reads the object from stream \p s
|
127 |
|
|
void memblock::read (istream& is)
|
128 |
|
|
{
|
129 |
|
|
written_size_type n = 0;
|
130 |
|
|
is >> n;
|
131 |
|
|
if (!is.verify_remaining ("read", "ustl::memblock", n))
|
132 |
|
|
return;
|
133 |
|
|
resize (n);
|
134 |
|
|
is.read (data(), writable_size());
|
135 |
|
|
is.align (alignof (n));
|
136 |
|
|
}
|
137 |
|
|
|
138 |
|
|
#ifdef CYGCLS_USTL_FSTREAMS
|
139 |
|
|
/// Reads the entire file \p "filename".
|
140 |
|
|
void memblock::read_file (const char* filename)
|
141 |
|
|
{
|
142 |
|
|
fstream f;
|
143 |
|
|
f.exceptions (fstream::allbadbits);
|
144 |
|
|
f.open (filename, fstream::in);
|
145 |
|
|
const off_t fsize (f.size());
|
146 |
|
|
reserve (fsize);
|
147 |
|
|
f.read (data(), fsize);
|
148 |
|
|
f.close();
|
149 |
|
|
resize (fsize);
|
150 |
|
|
}
|
151 |
|
|
#endif // CYGCLS_USTL_FSTREAMS
|
152 |
|
|
|
153 |
|
|
memblock::size_type memblock::minimumFreeCapacity (void) const throw() { return (0); }
|
154 |
|
|
|
155 |
|
|
} // namespace ustl
|