Umm... wow... what are you doing to my C++ :(
- We don't need anything platform-specific to read files. Oh, and there's also this totally new (
if you call 9 years old new) I/O library in C++, called <iostream>, which tends to provide much better type safety, avoids messing around with pointers (because your stream is now represented by a class instance), doesn't require you to close things explicitly (in normal cases), uses flags to specify the file mode instead of a weird magic string, and doesn't have you worrying about distinguishing the size of a read-in thing from the number of things to read in. (BTW, for what you're doing, I don't see why you'd need an "r+" mode instead of just "r"... and like I said, nothing platform specific is needed - why not just have added a "b" to the magic string?)
- Keeping *any* kind of representation of a file stream as a data member of an object is usually a bad idea. Trust me on this one.
- There are nicer ways to indicate success or failure. If there is only one way to fail, then why not just use one of these 'bool's that you apparently know about? On the other hand, maybe it would do you some good to learn about exceptions, too... (I'll spare you for now, though).
- There should never be any need for a BYTE typedef. sizeof(char) is 1. By definition. Always.
- There are standard library containers that will automatically manage memory for you. In particular, std::vector carries pretty much an absolute minimum of overhead (in terms of both speed and size), and is quite a bit harder to mess up with (because you can just treat it like a local variable). Of course, there's no reason you'd ever use malloc() - or worse yet, a platform-specific memory allocation routine - in a *normal* C++ program, because 'new' and 'delete' do the job just fine. Of course, with the vector, you can avoid even worrying about that much.
Better yet, the std::vector is resizeable - it automatically wraps any sort of realloc() work you might have been thinking of doing - and the generated code will do basically just the same as anything you'd write yourself, because there's pretty much only the one way to do it.
- Please, don't *ever* write something like this again:
if(bytes & j) m_bits.push_back(true);else m_bits.push_back(false);
Consider which you would more likely say in English:
a) "Do I need an umbrella? Depends if it is raining."
b) "Do I need an umbrella? If it is raining, then yes; otherwise no."
Correspondingly, the proper way to write things is:
// the cast to bool here is optional depending on your usual style for// interpreting integers in a boolean context. If you use it, it may be read as// "whether".m_bits.push_back(bool(bytes & j));
Here, I show code to read an entire file into a vector of char (Vectors of bools are a bit sketchy; they're a specialized type that's designed to keep the bits packed together so they don't use a byte each, but that in turn means you can't address separate bits as array elements, because memory simply isn't bit-addressable.), and a helper function that picks a given bit value out of a vector of char. Note that passing the vector by reference avoids copying the data; it gives you the same efficiency that you are probably used to getting by passing things by pointer. But it also avoids having to deal with pointers.
// We will need:#include <iostream>#include <vector>#include <algorithm>#include <iterator>typedef std::vector<char> buffer;bool readFile(buffer& destination) { // Using an 'i'fstream implicitly sets the ios::in flag for the stream. std::ifstream file(filename.c_str(), ios::binary); if (!file.good()) { // which is prettier than '== 0' or '!= 0'; but note that we can also // use plain old 'if (file)', exactly as we could in C. return false; } // We don't even have to do any iteration to read each byte of the file. // And because the vector automatically resizes, we don't even have to // determine the size of the file first. typedef std::istreambuf_iterator<char> filePosition; std::copy(filePosition(file), filePosition(), std::back_inserter<char>(destination)); return true;}bool getBit(const buffer& data, int position) { char c = data[position / CHAR_BITS]; // You might need to modify this depending on your interpretation of the // "bit-endianness". return bool(c & (1 << (position % CHAR_BITS)));}