root/src/Describer.cpp

////////////////////////////////////////////////////////////////////////
// Copyright (c) Nehmulos 2011-2014
// This file is part of N0 Strain Serialization Library.
//
// N0Strain-Serialization-Library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// N0Strain-Serialization-Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with N0Strain-Serialization-Library.  If not, see https://gnu.org/licenses/lgpl-3.0
////////////////////////////////////////////////////////////////////////




#include "Describer.h"
#include "PointerCollector.h"

namespace nw {

Describer::Describer() {

}
DescribedObject* (*Describer::createObjectForClassId)(ClassId) = NULL;
String Describer::encodingUsed = N0Slib_BinaryToTextEncoding_Default;

    void Describer::setPointers(const PointerCollector& pc) {
        this->unhandledPointers = pc.unhandledPointers;
        this->describePointers();
    }


void Describer::describePointers()
{
        bool hasPointers = false;

        if(this->isInWriteMode())
        {
                if(unhandledPointers.empty())
                        return;
                else
                    hasPointers = true;
        }

        push("N0Slib:Header");

        this->describe("hasPointers", hasPointers);
        if(hasPointers)
        {
                if(this->isInReadMode() && createObjectForClassId == NULL)
                {
                        std::cout << "\n\n";
                        std::cout << "IMPORTANT WARNING: createObjectForClassId not set! Don't know what objects shall be created for the saved classIds\n";
                        std::cout << "Please set a creatObjectForClassId to a function that returns a new SerializedObject* for a given classId\n";
                        std::cout << "The program will probably crash now...\n";
                }

                describeArray("Pointers", "Pointer", unhandledPointers.size());
                for (unsigned int i = 0; enterNextElement(i); ++i)
                {
                  unsigned int id;
                  ClassId classId;
                  if(isInWriteMode())
                  {
                          if(unhandledPointers.at(i) != NULL)
                          {
                                  id = i;
                                  classId = unhandledPointers.at(i)->getClassId();
                          }
                          else
                          {
                                  id = N0Slib_UndefinedPointerId;
                          }
                  }
                  describe("classId", classId);
                  describe("pId",id);
                  //TODO make the <id> tag work for xml, in xml the order is 2 important, or remove it
                  // will be transfered to handled
                  if(!isInWriteMode()) { unhandledPointers.push_back(Describer::createObjectForClassId(classId)); }
                }
        //      if(!isInWriteMode()) { SerializedObject::addSerializedObjectsToBeginning(unhandledPointers); }
                serializePointerData();
        }
        pop();
}

void Describer::serializePointerData()
{
        handledPointers = unhandledPointers;
        unhandledPointers.clear();
        //TODO think about using iterators, compare them with indices
        describeArray("PointerData", "Pointer", handledPointers.size());
          for (unsigned int i = 0; this->enterNextElement(i); ++i)
          {
                  if(handledPointers.at(i) != NULL)
                  {
                          int pid = i;
                          this->describe("pId", pid);
                          handledPointers.at(i)->describeObject(this);
                  }
          }
}

Describer::~Describer() {
        for (unsigned int i = 0; i < states.size(); ++i) {
                delete states.at(i);
        }
}


bool Describer::getBooleanState(String stateName)
{
        for (unsigned int i = 0; i < states.size(); ++i)
        {
                if(states.at(i)->getName() == stateName)
                {
                        return states.at(i)->getBooleanValue();
                }
        }
        return false;
}


void Describer::setState(String stateName, bool value)
{
        Tag* newTag = new Tag(stateName);
        String stringValue;
        std::stringstream ss;
        ss << value;
        ss >> stringValue;
        newTag->setValue(stringValue);
        states.push_back(newTag);
}

void Describer::setState(String stateName, void* value)
{
        Tag* newTag = new Tag(stateName);
        String stringValue;
        std::stringstream ss;
        ss << value;
        ss >> stringValue;
        newTag->setValue(stringValue);
        states.push_back(newTag);
}

void Describer::getState(String stateName, void* pointerToPointer)
{
        void** realPointer = (void**)pointerToPointer;
        for (unsigned int i = 0; i < states.size(); ++i)
        {
                if(states.at(i)->getName() == stateName)
                {
                        std::stringstream ss(states.at(i)->getValue());
                        ss >> *realPointer;
                        return;
                }
        }
}

bool Describer::hasState(String stateName)
{
        for (unsigned int i = 0; i < states.size(); ++i)
        {
                if(states.at(i)->getName() == stateName)
                {
                        return true;
                }
        }
        return false;
}

DescribedObject* Describer::getSerializedObjectForId(unsigned int id)
{
        if(id != N0Slib_UndefinedPointerId && id < handledPointers.size())
                return handledPointers.at(id);
        if(id != N0Slib_UndefinedPointerId)
                std::cout << "Pointer not Found for id " << id << std::endl;
        return NULL;
}

unsigned int Describer::getIDForSerializedObject(Pointer ref)
{
        if(ref == NULL)
                return N0Slib_UndefinedPointerId;

        for (unsigned int i = 0; i < handledPointers.size(); ++i)
        {
                if(handledPointers.at(i) == ref)
                {
                        return i;
                }
        }
        std::cout << "Requested an id for an unkown pointer " << ref << std::endl;
        return N0Slib_UndefinedPointerId; //not knowing, just null it; maybe I should register it
}

bool Describer::pointerIsKnown(DescribedObject* pointer)
{
        unsigned int numberOfCollectedPointers = unhandledPointers.size();
        for (unsigned int i = 0; i < numberOfCollectedPointers; ++i)
        {
                if(unhandledPointers.at(i) == pointer)
                {
                        return true;
                }
        }
        return false;
}

bool Describer::isInReadMode()
{
        return !this->isInWriteMode();
}

bool Describer::isSilentCrawler()
{
        return false;
}

bool Describer::conditionalPush(String tagname, bool condition)
{
        if(this->isInWriteMode())
        {
                if(condition)
                {
                        return push(tagname);
                }
        }
        else
        {
                return push(tagname);
        }
        return false;
}

std::string Describer::getErrorMessage() {
        return errorMessage.str();
}

}  // namespace nw