Added static_assert from Loki
[ustl.git] / memblock.cc
blobaf0c93efa5ec05e000c1b9a61cf976623dd5b12e
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 cmemlink l (*this);
111 if (is_linked())
112 unlink();
113 assign (l);
116 /// Copies data from \p p, \p n.
117 void memblock::assign (const void* p, size_type n)
119 assert ((p != (const void*) cdata() || size() == n) && "Self-assignment can not resize");
120 resize (n);
121 copy (p, n);
124 /// \brief Reallocates internal block to hold at least \p newSize bytes.
126 /// Additional memory may be allocated, but for efficiency it is a very
127 /// good idea to call reserve before doing byte-by-byte edit operations.
128 /// The block size as returned by size() is not altered. reserve will not
129 /// reduce allocated memory. If you think you are wasting space, call
130 /// deallocate and start over. To avoid wasting space, use the block for
131 /// only one purpose, and try to get that purpose to use similar amounts
132 /// of memory on each iteration.
134 void memblock::reserve (size_type newSize, bool bExact)
136 if ((newSize += minimumFreeCapacity()) <= m_Capacity)
137 return;
138 pointer oldBlock (is_linked() ? NULL : data());
139 const size_t alignedSize (Align (newSize, c_PageSize));
140 if (!bExact)
141 newSize = alignedSize;
142 pointer newBlock = (pointer) realloc (oldBlock, newSize);
143 if (!newBlock)
144 throw bad_alloc (newSize);
145 if (!oldBlock & (cdata() != NULL))
146 copy_n (cdata(), min (size() + 1, newSize), newBlock);
147 link (newBlock, size());
148 m_Capacity = newSize;
151 /// Swaps the contents with \p l
152 void memblock::swap (memblock& l)
154 memlink::swap (l);
155 ::ustl::swap (m_Capacity, l.m_Capacity);
158 /// Shifts the data in the linked block from \p start to \p start + \p n.
159 memblock::iterator memblock::insert (iterator start, size_type n)
161 const uoff_t ip = start - begin();
162 assert (ip <= size());
163 resize (size() + n, false);
164 memlink::insert (iat(ip), n);
165 return (iat (ip));
168 /// Shifts the data in the linked block from \p start + \p n to \p start.
169 memblock::iterator memblock::erase (iterator start, size_type n)
171 const uoff_t ep = start - begin();
172 assert (ep + n <= size());
173 memlink::erase (start, n);
174 memlink::resize (size() - n);
175 return (iat (ep));
178 /// Unlinks object.
179 void memblock::unlink (void)
181 memlink::unlink();
182 m_Capacity = 0;
185 /// Reads the object from stream \p s
186 void memblock::read (istream& is)
188 written_size_type n;
189 is >> n;
190 is.verify_remaining ("read", "ustl::memblock", n);
191 resize (n);
192 is.read (data(), writable_size());
193 is.align (alignof (n));
196 /// Reads the entire file \p "filename".
197 void memblock::read_file (const char* filename)
199 fstream f;
200 f.exceptions (fstream::allbadbits);
201 f.open (filename, fstream::in);
202 const off_t fsize (f.size());
203 reserve (fsize);
204 f.read (data(), fsize);
205 f.close();
206 resize (fsize);
209 } // namespace ustl