Концептуальные проблемы с итератором - PullRequest
0 голосов
/ 23 июня 2009

Я пытаюсь написать свой первый класс итератор / тип контейнера. По сути, я хочу иметь возможность перебирать файл, конвертировать файл в HEX на лету и передавать результат в библиотеку boost :: xpressive. Я не хочу выполнять однократное преобразование в строку в ОЗУ, поскольку некоторые файлы, которые мне нужно обработать, больше, чем ожидаемая системная ОЗУ (несколько ГБ).

Вот как выглядит мой код. Я использую MSVC ++ 2008.

Заголовок для итератора:

class hexFile;

class hexIterator : public std::iterator<std::bidirectional_iterator_tag, wchar_t>
{
    hexFile *parent;
    __int64 cacheCurrentFor;
    wchar_t cacheCharacters[2];
    void updateCache();
public:
    bool highCharacter;
    __int64 filePosition;
    hexIterator();
    hexIterator(hexFile *file, bool begin);
    hexIterator operator++();
    hexIterator operator++(int)
    {
        return ++(*this);
    }
    hexIterator operator--();
    hexIterator operator--(int)
    {
        return --(*this);
    }
    bool operator==(const hexIterator& toCompare) const;
    bool operator!=(const hexIterator& toCompare) const;
    wchar_t& operator*();
    wchar_t* operator->();
};

Реализация для итератора:

#include <stdafx.h>
class hexFile;
hexIterator::hexIterator()
{
    parent = NULL;
    highCharacter = false;
    filePosition = 0;
}
hexIterator::hexIterator(hexFile *file, bool begin) : parent(file)
{
    if(begin)
    {
        filePosition = 0;
        highCharacter = false;
    } else
    {
        filePosition = parent->fileLength;
        highCharacter = true;
    }
}

hexIterator hexIterator::operator++()
{
    if (highCharacter)
    {
        highCharacter = false;
        filePosition++;
    } else
    {
        highCharacter = true;
    }
    return (*this);
}

hexIterator hexIterator::operator--()
{
    if (highCharacter)
    {
        highCharacter = false;
    } else
    {
        filePosition--;
        highCharacter = true;
    }
    return (*this);
}

bool hexIterator::operator==(const hexIterator& toCompare) const
{
    if (toCompare.filePosition == filePosition &&
        toCompare.highCharacter == highCharacter)
        return true;
    else return false;
}

bool hexIterator::operator!=(const hexIterator& toCompare) const
{
    if (toCompare.filePosition == filePosition &&
        toCompare.highCharacter == highCharacter)
        return false;
    else return true;
}
wchar_t& hexIterator::operator*()
{
    updateCache();
    if (highCharacter)
        return cacheCharacters[1];
    return cacheCharacters[0];
}

wchar_t* hexIterator::operator->()
{
    updateCache();
    if (highCharacter)
        return cacheCharacters + 1;
    return cacheCharacters;
}

void hexIterator::updateCache()
{
    if (filePosition == cacheCurrentFor)
        return;
    BYTE rawData;
    DWORD numberRead;
    LONG lowValue = static_cast<LONG>(filePosition);
    LONG highValue = static_cast<LONG>(filePosition >> 32);
    SetFilePointer(parent->theFile, lowValue, &highValue, FILE_BEGIN);
    if (!ReadFile(parent->theFile, &rawData, 1, &numberRead, 0))
        throw std::runtime_error(eAsciiMsg("Error reading from file."));
    static const wchar_t hexCharacters[] = L"0123456789ABCDEF";
    cacheCharacters[0] = hexCharacters[rawData & 0x0F];
    cacheCharacters[1] = hexCharacters[rawData >> 4];
    cacheCurrentFor = filePosition;
}

Заголовок контейнера

class hexFile {
public: 
    HANDLE theFile;
    unsigned __int64 fileLength;
    hexFile(const std::wstring& fileName)
    {
        theFile = CreateFile(fileName.c_str(),GENERIC_READ,FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,NULL,NULL);
        if (theFile == INVALID_HANDLE_VALUE)
        {
            throw std::runtime_error(eAsciiMsg("Could not open file!"));
        }
        BY_HANDLE_FILE_INFORMATION sizeFinder;
        GetFileInformationByHandle(theFile, &sizeFinder);
        fileLength = sizeFinder.nFileSizeHigh;
        fileLength <<= 32;
        fileLength += sizeFinder.nFileSizeLow;
    };
    ~hexFile()
    {
        CloseHandle(theFile);
    };
    hexIterator begin()
    {
        hexIterator theIterator(this, true);
        return theIterator;
    };
    hexIterator end()
    {
        hexIterator theIterator(this, false);
        return theIterator;
    };
};

Однако, независимо от того, какой тестовый пример я пробую, регулярное выражение никогда не будет совпадать. Я предполагаю, что это некоторая концептуальная проблема с моим итератором ... он должен быть постоянным двунаправленным итератором во всех случаях.

Что-нибудь, по чему я скучаю, или есть более простой способ сделать это?

Billy3

Ответы [ 4 ]

1 голос
/ 23 июня 2009

Ну ... оказывается, я полный идиот.

boost :: xpressive :: regex_match (fileInstance.begin (), fileInstance.end (), результаты, internalRegex);

Ну ... то, что я хотел сделать, это

boost :: xpressive :: regex _search (fileInstance.begin (), fileInstance.end (), результаты, internalRegex);

Итератор никогда не ошибался.

Извините, что потратил чужое время, Billy3

1 голос
/ 23 июня 2009

Это довольно много кода для чтения; на первый взгляд я ничего не вижу.

Для замечаний по реализации это звучит как скорее iostream, чем итератор, который с буферизацией может быть значительно быстрее. Boost имеет библиотеку, чтобы помочь реализовать те .

Если вы хотите использовать итератор, у них также есть библиотека , чтобы помочь с этим, она гарантирует, что вы получите все необходимые методы, одновременно упрощая реализацию.

Для отладки я бы попробовал для модульных тестов; надеюсь, это должно указывать на проблему; начните с чего-то маленького, например файла с двумя символами, пройдитесь по отладчику, чтобы увидеть, что происходит, и повторяйте, пока не пройдете все.

1 голос
/ 23 июня 2009

operator++(int) следует определять в терминах operator++(), а не наоборот. Попробуйте переключить их. То же самое для operator--.

0 голосов
/ 23 июня 2009

Попробуйте использовать Boost :: transform_iterator .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...