Doing things the hard way...accessing an array as different data types

From: J. Campbell (mango_maniac_at_yahoo.com)
Date: 11/26/03


Date: 26 Nov 2003 10:21:43 -0800

I have a feeling that I'm doing things all ass-backwards (again ;-),
and would like some advice. What I want to do is:

put some data to memory and then access that memory space as an array
of data-types of my choosing (eg an array of char, short, or int).

The application has to do with generating checksum-type values for
files or strings, so speed is important, as I just want to quickly get
this value then move on to the next task. As such, I don't want to
"properly" bit-shift bytes to ints...rather, I want to put all the
bits in sequential order then access them in chunks sized to the
machine's native integer for bitwise operations.

I had been doing this by using the fstream write() function to dump
the file to a char array (on the heap sized to filesize), then casting
the char array to an int*. This worked fine, but then I learned about
potential alignment problems...that there could be cases that the
location of the char* might be an invalid location for an int*. To
circumvent this potential problem, I made a class, align_int, that
reverses the order...first creating the int array, then casting the
array to a char*, then dumping the file to the char*. This works
because every int* address is accessable as a char*, even though some
char* addresses may NOT be accessable as an int*.

So...now I've got my big, ugly, class that offers pointers of every
native int type to the same memory-space...and it works fine...but I
realize that the class contains pointers that are never used on any
given run. I'm wondering if there's an easier way to do this using a
single void* cast to the proper type as the return value of getter
member functions?

What I need from the class is the ability to request a pointer to the
file as any of the integer data-types. My dumb-ass class follows...

//AlignInt_class.h
#include <string>

class AlignInt{
   private:
      bool fileOKd(std::string filespec);
      void load_file();
      std::string type;
         
   public:
      AlignInt();
      ~AlignInt();
      
      void loadfile(std::string filespec);
      void loadstring(std::string stringin);
      void prealigned(unsigned long* parray, unsigned int byte_len);
      
      unsigned int* ui;
      unsigned long* ul;
      unsigned short* us;
      unsigned char* uc;
                 int* i;
                long* l;
               short* s;
                char* c;
      
      std::string filespec;
      unsigned int len_c; // len of file in bytes (char)
      unsigned int len_s; // len of file in shorts
      unsigned int len_i; // len of file in int
      unsigned int len_l; // len of file in long
      bool ok;
      void verify();
};

//alignint.cpp
#include "AlignInt_class.h"
#include <iostream>
#include <fstream>

using namespace std;

AlignInt::AlignInt(){
   ok = 0;
}

AlignInt::~AlignInt(){
  if(ok) delete[] ul;
}

void AlignInt::loadfile(string filename){
   if(ok) cout << "ERROR...memory redesignation ERROR 1" << endl;
   else{
        filespec = filename;
        ok = fileOKd(filespec);
        if(ok){
          load_file();
           
        //ul....defined in load_file
          uc = reinterpret_cast<unsigned char*>(ul);
          ui = reinterpret_cast<unsigned int*>(ul);
          us = reinterpret_cast<unsigned short*>(ul);
          i = reinterpret_cast<int*> (ul);
          l = reinterpret_cast<long int*> (ul);
          s = reinterpret_cast<short int*> (ul);
        //c....defined in load_file
     
       // len_c....defined in load_file
       // len_l....defined in load_file
          len_i = len_l * (sizeof(long int)/sizeof(unsigned int));
          len_s = len_l * (sizeof(long int)/sizeof(unsigned short
int));
          type = "file";
      }else cout << "FILE ERROR: Cannot load: " << filespec << endl;
   }
}

void AlignInt::load_file(){
     int wordsize = sizeof(unsigned long int);
     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 unsigned long int[len_l];
     ul[len_l - 1] = 0; //make sure last byte is cleared before
putting file in array
     c = reinterpret_cast<char*>(ul);
     
     in.seekg(0, ios::beg);
     in.read(c, len_c);
     in.close();
}

void AlignInt::loadstring (string stringin){
   if(ok) cout << "ERROR...memory redesignation ERROR 2" << endl;
   else{
       int wordsize = sizeof(unsigned long int);
       len_c = stringin.size();
       len_l = (len_c / wordsize) + ((len_c % wordsize) > 0);
       ul = new unsigned long int[len_l];
       ul[len_l - 1] = 0;
       c = reinterpret_cast<char*>(ul);
       for(unsigned int j = 0; j < len_c; ++j)
          c[j] = stringin[j];
       
       uc = reinterpret_cast<unsigned char*>(ul);
       ui = reinterpret_cast<unsigned int*>(ul);
       us = reinterpret_cast<unsigned short*>(ul);
       i = reinterpret_cast<int*> (ul);
       l = reinterpret_cast<long int*> (ul);
       s = reinterpret_cast<short int*> (ul);
       len_i = len_l * (sizeof(long int)/sizeof(unsigned int));
       len_s = len_l * (sizeof(long int)/sizeof(unsigned short int));
       
       ok = true; //string is in memory
       type = "string";
   }
}

void AlignInt::prealigned(unsigned long* parray, unsigned int
byte_len){
   if(!ok){ //ok must == 0
       int wordsize = sizeof(unsigned long int);
       ul = parray;
       len_c = byte_len;
       len_l = (len_c / wordsize) + ((len_c % wordsize) > 0);
       uc = reinterpret_cast<unsigned char*>(ul);
       ui = reinterpret_cast<unsigned int*>(ul);
       us = reinterpret_cast<unsigned short*>(ul);
       i = reinterpret_cast<int*> (ul);
       l = reinterpret_cast<long int*> (ul);
       s = reinterpret_cast<short int*> (ul);
       c = reinterpret_cast<char*>(ul);
       len_i = len_l * (sizeof(long int)/sizeof(unsigned int));
       len_s = len_l * (sizeof(long int)/sizeof(unsigned short int));
       type = "prealigned array";
   }else cout << "ERROR...memory redesignation ERROR 3";
}

bool AlignInt::fileOKd(string filespec){
   ifstream in(filespec.c_str());
   return in.good();
}

void AlignInt::verify(){
      cout << "Verifying...\n"
           << "The " << type
           << " Contains " << len_c << " chars\n"
           << "Fits into an array of " << len_s << " short int\n"
           << "Fits into an array of " << len_i << " int\n"
           << "Fits into an array of " << len_l << " long int\n\n"
           << "The following should all point to the same memory
space\n"
           << "p ulong " << ul << "\n"
           << "p long " << l << "\n"
           << "p uint " << ui << "\n"
           << "p int " << i << "\n"
           << "p short " << s << "\n"
           << "p ushort " << s << "\n"
           << "p uchar " << reinterpret_cast<unsigned int*>(uc) <<
"\n"
           << "p char " << reinterpret_cast<int*>(c) << endl;
}



Relevant Pages