I was making sure I knew how to do the op= and copy constructor correctly in order to sort()
properly, so I wrote up a test case. After getting it to work, I realized that the op= was hard-copying all the data_
.
I figure if I wanted to sort a container with this structure (its elements have heap allocated char buffer arrays), it'd be faster to just swap the pointers around. Is there a way to do that? Would I have to write my own sort/swap function?
#include <deque>
//#include <string>
//#include <utility>
//#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fstream>
#include <algorithm> // I use sort(), so why does this still compile when commented out?
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
using namespace std;
namespace fs = boost::filesystem;
class Page
{
public:
// constructor
Page(const char* path, const char* data, int size) :
path_(fs::path(path)),
size_(size),
rawdata_(new char[size])
{
// cout << "Creating Page..." << endl;
strncpy(rawdata_, data, size);
// cout << "done creating Page..." << endl;
}
// copy constructor
Page(const Page& other) :
path_(fs::path(other.path())),
size_(other.size()),
rawdata_(new char[other.size()])
{
// cout << "Copying Page..." << endl;
strncpy(data_, other.data(), size_);
// cout << "done copying Page..." << endl;
}
// destructor
~Page() { delete[] data_; }
// accessors
const fs::path& path() const { return path_; }
const char* data() const { return rawdata_; }
int size() const { return size_; }
// operators
Page& operator = (const Page& other) {
if (this == &other)
return *this;
char* newImage = new char[other.size()];
strncpy(newImage, other.data(), other.size());
delete[] data_;
rawdata_ = newImage;
path_ = fs::path(other.path());
size_ = other.size();
return *this;
}
bool operator < (const Page& other) const { return path_ < other.path(); }
private:
fs::path path_;
int size_;
char* rawdata_;
};
class Book
{
public:
Book(const char* path) :
path_(fs::path(path))
{
cout << "Creating Book..." << endl;
cout << "pushing back #1" << endl;
// below, the RawData will be coming from methods like
// fstream.read(char* buffer, int filesize); or
// unzReadCurrentFile(unzFile zipFile, char* buffer, int size);
pages_.push_back(Page("image1.jpg", "firstImageRawData", 17));
cout << "pushing back #3" << endl;
pages_.push_back(Page("image3.jpg", "thirdImageRawData", 17));
cout << "pushing back #2" << endl;
pages_.push_back(Page("image2.jpg", "secondImageRawData", 18));
cout << "testing operator <" << endl;
cout << pages_[0].path().string() << (pages_[0] < pages_[1]? " < " : " > ") << pages_[1].path().string() << endl;
cout << pages_[1].path().string() << (pages_[1] < pages_[2]? " < " : " > ") << pages_[2].path().string() << endl;
cout << pages_[0].path().string() << (pages_[0] < pages_[2]? " < " : " > ") << pages_[2].path().string() << endl;
cout << "sorting" << endl;
BOOST_FOREACH (Page p, pages_)
cout << p.path().string() << endl;
sort(pages_.begin(), pages_.end());
cout << "done sorting\n";
BOOST_FOREACH (Page p, pages_)
cout << p.path().string() << endl;
cout << "checking datas" << endl;
BOOST_FOREACH (Page p, pages_) {
char data[p.size() + 1];
strncpy((char*)&data, p.data(), p.size());
data[p.size()] = '\0';
cout << p.path().string() << " " << data << endl;
}
cout << "done Creating Book" << endl;
}
const Page& getFirstPage() { return pages_[0]; }
private:
deque<Page> pages_;
fs::path path_;
};
int main() {
Book* book = new Book("/some/path/");
// below is an example of where the rawdata is used
// by a method that has a char* parameter
ofstream outFile("outimage.jpg");
outFile.write(book->getFirstPage().data(), book->getFirstPage().size());
}