Build system improvements
[ustl.git] / memblock.cc
blobae285429b3e3b2aaba60152de7134596db67ebe7
1 // This file is part of the ustl library, an STL implementation.
2 //
3 // Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
5 //
6 // memblock.cc
7 //
8 // Allocated memory block.
9 //
11 #include "mistream.h"
12 #include "memblock.h"
13 #include "ualgo.h"
14 #include "umemory.h"
15 #include "fstream.h"
16 #include <errno.h>
18 namespace ustl {
20 /// Allocates 0 bytes for the internal block.
21 memblock::memblock (void)
22 : memlink (),
23 m_Capacity (0)
27 /// Allocates \p n bytes for the internal block.
28 memblock::memblock (size_type n)
29 : memlink (),
30 m_Capacity (0)
32 resize (n);
35 /// links to \p p, \p n. Data can not be modified and will not be freed.
36 memblock::memblock (const void* p, size_type n)
37 : memlink (),
38 m_Capacity (0)
40 assign (p, n);
43 /// Links to what \p b is linked to.
44 memblock::memblock (const cmemlink& b)
45 : memlink (),
46 m_Capacity (0)
48 assign (b);
51 /// Links to what \p b is linked to.
52 memblock::memblock (const memlink& b)
53 : memlink (),
54 m_Capacity (0)
56 assign (b);
59 /// Links to what \p b is linked to.
60 memblock::memblock (const memblock& b)
61 : memlink (),
62 m_Capacity (0)
64 assign (b);
67 /// Frees internal data, if appropriate
68 /// Only if the block was allocated using resize, or linked to using Manage,
69 /// will it be freed. Also, Derived classes should call DestructBlock from
70 /// their destructor, because upstream virtual functions are unavailable at
71 /// this point and will not be called automatically.
72 ///
73 memblock::~memblock (void)
75 deallocate();
78 /// resizes the block to \p newSize bytes, reallocating if necessary.
79 void memblock::resize (size_type newSize, bool bExact)
81 if (m_Capacity < newSize + minimumFreeCapacity())
82 reserve (newSize, bExact);
83 memlink::resize (newSize);
86 /// Frees internal data.
87 void memblock::deallocate (void) throw()
89 if (m_Capacity) {
90 assert (cdata() && "Internal error: space allocated, but the pointer is NULL");
91 assert (data() && "Internal error: read-only block is marked as allocated space");
92 free (data());
94 unlink();
97 /// Assumes control of the memory block \p p of size \p n.
98 /// The block assigned using this function will be freed in the destructor.
99 void memblock::manage (void* p, size_type n)
101 assert (p || !n);
102 assert (!m_Capacity && "Already managing something. deallocate or unlink first.");
103 link (p, n);
104 m_Capacity = n;
107 /// "Instantiate" a linked block by allocating and copying the linked data.
108 void memblock::copy_link (void)
110 const pointer p (begin());
111 const size_t sz (size());
112 if (is_linked())
113 unlink();
114 assign (p, sz);
117 /// Copies data from \p p, \p n.
118 void memblock::assign (const void* p, size_type n)
120 assert ((p != (const void*) cdata() || size() == n) && "Self-assignment can not resize");
121 resize (n);
122 copy (p, n);
125 /// \brief Reallocates internal block to hold at least \p newSize bytes.
127 /// Additional memory may be allocated, but for efficiency it is a very
128 /// good idea to call reserve before doing byte-by-byte edit operations.
129 /// The block size as returned by size() is not altered. reserve will not
130 /// reduce allocated memory. If you think you are wasting space, call
131 /// deallocate and start over. To avoid wasting space, use the block for
132 /// only one purpose, and try to get that purpose to use similar amounts
133 /// of memory on each iteration.
135 void memblock::reserve (size_type newSize, bool bExact)
137 if ((newSize += minimumFreeCapacity()) <= m_Capacity)
138 return;
139 pointer oldBlock (is_linked() ? NULL : data());
140 const size_t alignedSize (Align (newSize, c_PageSize));
141 if (!bExact)
142 newSize = alignedSize;
143 pointer newBlock = (pointer) realloc (oldBlock, newSize);
144 if (!newBlock)
145 throw bad_alloc (newSize);
146 if (!oldBlock & (cdata() != NULL))
147 copy_n (cdata(), min (size() + 1, newSize), newBlock);
148 link (newBlock, size());
149 m_Capacity = newSize;
152 /// Swaps the contents with \p l
153 void memblock::swap (memblock& l)
155 memlink::swap (l);
156 ::ustl::swap (m_Capacity, l.m_Capacity);
159 /// Shifts the data in the linked block from \p start to \p start + \p n.
160 memblock::iterator memblock::insert (iterator start, size_type n)
162 const uoff_t ip = start - begin();
163 assert (ip <= size());
164 resize (size() + n, false);
165 memlink::insert (iat(ip), n);
166 return (iat (ip));
169 /// Shifts the data in the linked block from \p start + \p n to \p start.
170 memblock::iterator memblock::erase (iterator start, size_type n)
172 const uoff_t ep = start - begin();
173 assert (ep + n <= size());
174 memlink::erase (start, n);
175 memlink::resize (size() - n);
176 return (iat (ep));
179 /// Unlinks object.
180 void memblock::unlink (void) throw()
182 memlink::unlink();
183 m_Capacity = 0;
186 /// Reads the object from stream \p s
187 void memblock::read (istream& is)
189 written_size_type n;
190 is >> n;
191 is.verify_remaining ("read", "ustl::memblock", n);
192 resize (n);
193 is.read (data(), writable_size());
194 is.align (alignof (n));
197 /// Reads the entire file \p "filename".
198 void memblock::read_file (const char* filename)
200 fstream f;
201 f.exceptions (fstream::allbadbits);
202 f.open (filename, fstream::in);
203 const off_t fsize (f.size());
204 reserve (fsize);
205 f.read (data(), fsize);
206 f.close();
207 resize (fsize);
210 } // namespace ustl