simplefsa_impl.hpp 2.12 KB
/* 
 * File:   simplefsa_impl.hpp
 * Author: mlenart
 *
 * Created on November 4, 2013, 1:05 PM
 */

#ifndef SIMPLEFSA_IMPL_HPP
#define	SIMPLEFSA_IMPL_HPP

#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */

struct StateData {
    unsigned transitionsNum : 7;
    unsigned accepting : 1;
};

#pragma pack(pop)   /* restore original alignment from stack */

template <class T>
SimpleFSA<T>::SimpleFSA(const unsigned char* ptr, const Deserializer<T>& deserializer)
: FSA<T>(ptr, deserializer) {
}

template <class T>
SimpleFSA<T>::~SimpleFSA() {

}

static unsigned int decodeOffset(const unsigned char* ptr) {
    unsigned int res = 0;
    res = ptr[0] << 16 | ptr[1] << 8 | ptr[2];
    return res;
}

template <class T>
void SimpleFSA<T>::proceedToNext(const char c, State<T>& state) const {
    const unsigned char* fromPointer = this->initialStatePtr + state.getOffset();
    long transitionsTableOffset = sizeof (StateData);
    if (state.isAccepting()) {
        transitionsTableOffset += state.getValueSize();
    }
    StateData stateData = *reinterpret_cast<const StateData*>(fromPointer);
    const unsigned char* foundTransition = fromPointer + transitionsTableOffset;
    bool found = false;
    for (int i = 0; i < stateData.transitionsNum; i++, foundTransition += 4) {
        if ((char) *foundTransition == c) {
            found = true;
            break;
        }
    }
    //    const_cast<Counter*>(&counter)->increment(foundTransition - transitionsStart + 1);
    if (!found) {
        state.setNextAsSink();
    }
    else {
        unsigned int offset = decodeOffset(foundTransition + 1);
        const unsigned char* nextStatePointer = this->initialStatePtr + offset;
        const StateData* nextStateData = reinterpret_cast<const StateData*>(nextStatePointer);
        if (nextStateData->accepting) {
            T object;
            long size = this->deserializer.deserialize(nextStatePointer + sizeof (StateData), object);
            state.setNext(offset, object, size);
        } else {
            state.setNext(offset);
        }
    }
}

#endif	/* SIMPLEFSA_IMPL_HPP */