Peter van Merkerk said:
Thanks Peter for the replies. These authors address the same issues I
was attempting to deal with. My understanding of the STL is too weak
to follow the advice for writing my own allocators for use with the
STL. My AlignInt class takes a file, string, or another class object
to initialize. The data is word-aligned in memory so that
word-oriented operations are guaranteed to work on the data, however a
pointer to the data as bytes is also offered to the class user. data
may be concatinated and assigned, and the class can return it's data
(or a subset of it's data) as a string. I realize that a weakness of
my approach is that it gives direct (public) access to the memory. I
chose to do things this way because I was writing the the class to
support a specific application, not as a general-use container.
However, I've now opted to use the container in several other
projects. I would love receive criticism/comments on how to
better-implement a data-container with these properties. I have
attached the declaration/implementation of the current iteration of my
container. I appologize that I didn't write/edit the code to make it
easy to read on the news-reader. Also...it may not be clear why I
have some particular functions in the class...they were all written to
address specific issues for a particular program, and it is likely
that better, more general solutions exist, which is why I post.
begin------->Align_int_class.h
// Class to put data on the heap and forces the data to be aligned
// with native words...then offer pointers to that data as either
native
// integer or byte. Class overwrites data before releasing so that
data
// does not linger in memory.
// I've tried to keep this class light, but have freely added methods
as/when it's
// been convenient.
#ifndef ALIGNINT
#define ALIGNINT
#include <string>
#include <stdint.h>
class AlignInt{
private:
bool haveMemory;
unsigned int wordsize;
public:
unsigned int len_c; // len of memory in bytes (char)
unsigned int len_l; // len of memory in words (long)
uint32_t* ul; // points to memory
char* c; // points to same memory
// Constructors
AlignInt(); // default constructor...uninitialized pointer
AlignInt(int byte_len); // new empty with space reserved =
byte_len
AlignInt(uint32_t* parray, unsigned int byte_len); // new
object points to preexisting memory. memory must be freed elsewhere
AlignInt(const std::string& stringin); // copy string to new
properly sized AlignInt object
// Copy Constructors
AlignInt(const AlignInt& rhs); //copy
constructor
AlignInt(const AlignInt& rhs1, const AlignInt& rhs2);
//overloaded copy constructor..concatinates 2 objects
// Overloaded operator
AlignInt operator=(const AlignInt&); // assign AlignInt
to AlignInt
AlignInt operator=(const std::string& rhs); // assign string
to AlignInt
AlignInt operator+(const AlignInt& rhs); // concatinate
// Destructor
~AlignInt(); // clears mem on
close
// Other Methods
void loadfile(const std::string& filespec); // puts file
into object
bool hasData(){return haveMemory;} // has 'new'
been called by this object? If yes, clear memory upon destruction.
void clearend(); // since data is
'int-aligned' there may be trailing bytes that are not part of the
real data. This function clears them.
std::string str(); // returns data
as new std::string
std::string str(int offset, int chars_to_get);// similar to
std::string.substr()
void resizeEmpty(int byte_len); // erases old
data and makes a new resized
};
#endif //ALIGNINT
end------->Align_int_class.h
begin------->Align_int_class.cpp
#include "align_int_class.h"
#include "file_ok.h"
#include <iostream>
#include <fstream>
using namespace std;
//constructors
// default new empty
AlignInt::AlignInt()
:
haveMemory(false)
,wordsize(sizeof(*ul))
,len_c(0)
,len_l(0)
,ul(NULL)
,c(NULL)
{}
// new empty of defined length
AlignInt::AlignInt(int byte_len)
:
haveMemory(true)
,wordsize(sizeof(*ul))
,len_c(byte_len)
,len_l((len_c / wordsize) + ((len_c % wordsize) > 0))
,ul(new uint32_t[len_l])
,c(reinterpret_cast<char*>(ul))
{
memset(c, 0, len_l * wordsize );
}
//prealigned memory must be deallocated elsewhere
AlignInt::AlignInt(uint32_t* parray, unsigned int byte_len)
:
haveMemory(false)
,wordsize(sizeof(*ul))
,len_c(byte_len)
,len_l((len_c / wordsize) + ((len_c % wordsize) > 0))
,ul(parray)
,c(reinterpret_cast<char*>(ul))
{
clearend();
}
AlignInt::AlignInt(const string& stringin) // copy string
:
haveMemory(true)
,wordsize(sizeof(*ul))
,len_c(stringin.size())
,len_l((len_c / wordsize) + ((len_c % wordsize) > 0))
,ul(new uint32_t[len_l])
,c(reinterpret_cast<char*>(ul))
{
for(unsigned int j = 0; j < len_c; ++j){
c[j] = stringin[j];
}
clearend();
}
// Copy Constructors
AlignInt::AlignInt(const AlignInt& rhs) //copy constructor
:
haveMemory(true)
,wordsize(sizeof(*ul))
,len_c(rhs.len_c)
,len_l(rhs.len_l)
,ul(new uint32_t[rhs.len_l])
,c(reinterpret_cast<char*>(ul))
{
memcpy(c, rhs.c, rhs.len_c);
clearend();
}
AlignInt::AlignInt(const AlignInt& rhs1, const AlignInt& rhs2)
//overloaded copy-constructor, used to concatinate
:
haveMemory(true)
,wordsize(sizeof(*ul))
,len_c(rhs1.len_c + rhs2.len_c)
,len_l((len_c / wordsize) + ((len_c % wordsize) > 0))
,ul(new uint32_t[len_l])
,c(reinterpret_cast<char*>(ul))
{
memcpy(c, rhs1.c, rhs1.len_c);
memcpy((c + rhs1.len_c), rhs2.c, rhs2.len_c);
clearend();
}
// Assignment operator
AlignInt AlignInt:
perator=(const AlignInt& rhs){
if(this != &rhs){
if(haveMemory){ //indicated memory has been allocated
memset(c, 0, len_l * wordsize);
delete[] ul;
}
len_c = rhs.len_c;
len_l = rhs.len_l;
ul = new uint32_t[rhs.len_l];
c = reinterpret_cast<char*>(ul);
haveMemory = true;
wordsize = sizeof(*ul);
memcpy(c, rhs.c, len_c);
clearend();
}
return *this;
}
AlignInt AlignInt:
perator=(const string& rhs){
if(haveMemory){ //indicated memory has been allocated
memset(c, 0, len_l * wordsize);
delete[] ul;
}
len_c = rhs.size();
len_l = (len_c / wordsize) + ((len_c % wordsize) > 0);
ul = new uint32_t[len_l];
c = reinterpret_cast<char*>(ul);
haveMemory = true;
wordsize = sizeof(*ul);
for(unsigned int i = 0; i < len_c; ++i){
c
= rhs;
}
clearend();
return *this;
}
AlignInt AlignInt:perator+(const AlignInt& rhs){
AlignInt temp(this->len_c + rhs.len_c);
memcpy(temp.c, this->c, this->len_c);
memcpy(temp.c + this->len_c, rhs.c, rhs.len_c);
temp.clearend();
return temp;
}
// Destructors
AlignInt::~AlignInt(){
if(haveMemory){
memset(c, 0, len_l * wordsize);
delete[] ul;
}
}
void AlignInt::loadfile(const string& filespec){
if(haveMemory){
cout << "ERROR...memory redesignation ERROR 1" << endl;
}else{
haveMemory = fileOK(filespec);
if(haveMemory){
ifstream in (filespec.c_str(), ios::in | ios::binary);
in.seekg(0, ios::end);
len_c = in.tellg(); // file length in bytes
len_l = (len_c / wordsize) + ((len_c % wordsize) > 0);
//^^^adds one if remainder^^^//
ul = new uint32_t[len_l];
ul[len_l - 1] = 0; // clear last word
c = reinterpret_cast<char*>(ul);
in.seekg(0, ios::beg);
in.read(c, (len_c));
in.close();
}else cout << "FILE ERROR: Cannot load: " << filespec << endl;
}
}
void AlignInt::clearend(){
memset(c + len_c, 0, (len_l * wordsize) - len_c);
}
string AlignInt::str(){
return string(c, len_c);
}
string AlignInt::str(int offset, int chars_to_get){
return string(c + offset, chars_to_get);
}
void AlignInt::resizeEmpty(int byte_len){
if(haveMemory){
memset(c, 0, len_l * wordsize);
delete[] ul;
}
haveMemory = true;
len_c = byte_len;
len_l = (len_c / wordsize) + ((len_c % wordsize) > 0);
ul = new uint32_t[len_l];
c = reinterpret_cast<char*>(ul);
memset(c, 0, len_l * wordsize);
}
end------->Align_int_class.cpp