<commit_before>#include "SyntaxTree.h"

#include <list>
#include <vector>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <assert.h>

#include <boost/format.hpp>

#include "parser.tab.hh"

#include "template.common.h"
#include "template.cs.h"

using namespace std;
using namespace boost;
using namespace Krystal;

// class Node
// {
// public:
    Krystal::Node::Node(Context* _context)
    {
        context = _context;
    }

    Krystal::Node::~Node()
    {
    }

    int Krystal::Node::getType() { return 0; } //TODO: remove getType() if unnecessary
    size_t Krystal::Node::getHash(vector<Node*>* referencingStack) { return 0; }
    string* Krystal::Node::getParsed(int as) { return 0; }

// };

// class NodeKst : public Node
// {
    // list<Node*>* commands;
    // string* fileName;
    // public:
    Krystal::NodeKst::NodeKst(Context* _context, list<Node*>* _commands, string* _fileName) : Node(_context)
    {
        commands = _commands;
        fileName = _fileName;
    }

    int Krystal::NodeKst::getType()
    {
       return CsNodeType::kst;
    }

    size_t Krystal::NodeKst::getHash(vector<Node*>* referencingStack)
    {
        return 0;
    }

    string* Krystal::NodeKst::getParsed(int as)
    {
        stringstream parsed;

        parsed << format(TCS_HEADER) % *fileName;
        parsed << TCS_USINGS;

        string namespaceByFileName = fileName->substr(0, fileName->find("."));

        parsed << format(TCS_NAMESPACE_BEGIN) % namespaceByFileName;

        list<Node*>::iterator i = commands->begin();
        list<Node*>::iterator end = commands->end();

        string* temp;

        for (; i != end; i++)
        {
            temp = (*i)->getParsed(CsParseAs::Default);
            temp = indent(temp);
            parsed << *temp;
            parsed << "\n";
        }

        parsed << TCS_NAMESPACE_END;

        parsed << "\n\n";

        return new string(parsed.str());
    }
// };

// class NodeInclude : public Node
// {
//     string* value;
//     public:
    Krystal::NodeInclude::NodeInclude(Context* _context, string* _value) : Node(_context)
    {
        value = _value;
    }

    int Krystal::NodeInclude::getType()
    {
       return CsNodeType::include;
    }

    size_t Krystal::NodeInclude::getHash(vector<Node*>* referencingStack)
    {
        return 0;
    }

    string* Krystal::NodeInclude::getParsed(int as)
    {
        stringstream parsed;

        parsed << "#include \"";
        parsed << *(value);
        parsed << "\"";

        return new string(parsed.str());
    }
// };

// class NodePacket : public Node
// {
//     string* packetName;
//     list<Node*>* packetMembers;
//     public:
    Krystal::NodePacket::NodePacket(Context* _context, string* _packetName, list<Node*>* _packetMembers) : Node(_context)
    {
        packetName = _packetName;
        packetMembers = _packetMembers;
    }

    int Krystal::NodePacket::getType()
    {
       return CsNodeType::packet;
    }

    size_t Krystal::NodePacket::getHash(vector<Node*>* referencingStack)
    {
        if (referencingStack == NULL)
        {
            referencingStack = new vector<Node*>();
        }
        else // check circular reference
        {
            vector<Node*>::iterator end = referencingStack->end();
            for (vector<Node*>::iterator i = referencingStack->begin(); i != end; i++)
            {
                if (*i == this)
                {
                    throw(runtime_error("Circular reference between packets"));
                }
            }
        }

        referencingStack->push_back(this);

        size_t packetHash = getHashCode(packetName);

        list<Node*>::iterator i = packetMembers->begin();
        list<Node*>::iterator end = packetMembers->end();
        for (; i != end; i++)
        {
            combineHashCode(packetHash, (*i)->getHash(referencingStack));
        }

        referencingStack->pop_back();

        return packetHash;
    }

    string* Krystal::NodePacket::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                parsed << format(TCS_PACKET_BEGIN) % *packetName;

                {
                    stringstream body;

                    body << format(TCS_PACKET_ID_FIELD) % ((TCS_PACKET_ID_TYPE)getHash(NULL));

                    body << TCS_PACKET_COOKIE_FIELD;

                    // Member Variables
                    list<Node*>::iterator i = packetMembers->begin();
                    list<Node*>::iterator end = packetMembers->end();
                    for (; i != end; i++)
                    {
                        body << *((*i)->getParsed(CsParseAs::Default));
                    }

                    body << format(TCS_PACKET_CONSTRUCTOR) % *packetName;

                    body << TCS_PACKET_GET_ID;

                    body << TCS_PACKET_SET_COOKIE;
                    body << TCS_PACKET_GET_COOKIE;

                    body << TCS_PACKET_GET_LENGTH_BEGIN;
                    {
                        stringstream bodyGetLengthBlock;
                        for (i = packetMembers->begin(); i != end; i++)
                        {
                            bodyGetLengthBlock << *((*i)->getParsed(CsParseAs::GetLength));
                        }

                        body << *(indent(new string(bodyGetLengthBlock.str())));
                    }
                    body << TCS_PACKET_GET_LENGTH_END;

                    parsed << *(indent(new string(body.str())));
                }

                parsed << TCS_PACKET_END;
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMember : public Node
// {
//     Node* memberType;
//     Node* memberName;
//     public:
    Krystal::NodePacketMember::NodePacketMember(Context* _context, Node* _memberType, Node* _memberName) : Node(_context)
    {
        memberType = _memberType;
        memberName = _memberName;
    }

    int Krystal::NodePacketMember::getType()
    {
       return CsNodeType::packetMember;
    }

    size_t Krystal::NodePacketMember::getHash(vector<Node*>* referencingStack)
    {
        assert(referencingStack != NULL);

        size_t packetMemberHash = memberType->getHash(referencingStack);
        combineHashCode(packetMemberHash, memberName->getHash(referencingStack));

        return packetMemberHash;
    }

    string* Krystal::NodePacketMember::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                parsed << format(TCS_PACKET_MEMBER_AS_DEFAULT)
                    % *(memberType->getParsed(CsParseAs::Default))
                    % *(memberName->getParsed(CsParseAs::Default))
                    % *(memberType->getParsed(CsParseAs::Initialization));
            }
            break;
            case CsParseAs::GetLength:
            {
                int typeType = memberType->getType();
                switch (typeType)
                {
                    case CsNodeType::packetMemberTypePrimitive:
                    {
                        string* serializerName = lookupSerializerName(memberType->getParsed(CsParseAs::Default));
                        parsed << format(TCS_PACKET_MEMBER_AS_GET_LENGTH_PRIMITIVE)
                            % *serializerName
                            % *(memberName->getParsed(CsParseAs::Default));
                    }
                    break;

                    case CsNodeType::packetMemberTypeReference:
                    {
                        parsed << format(TCS_PACKET_MEMBER_AS_GET_LENGTH_REFERENCE)
                            % *(memberName->getParsed(CsParseAs::Default));
                    }
                    break;

                    case CsNodeType::packetMemberTypeMap:
                    {
                        parsed << format(TCS_PACKET_MEMBER_AS_GET_LENGTH_MAP)
                            % *(memberType->getParsed(CsParseAs::GenericType1))
                            % *(memberType->getParsed(CsParseAs::GenericType2))
                            % *(memberName->getParsed(CsParseAs::Default))
                            % *(memberType->getParsed(CsParseAs::GenericTypeSerializer1))
                            % *(memberType->getParsed(CsParseAs::GenericTypeSerializer2));
                    }
                    break;

                    case CsNodeType::packetMemberTypeList:
                    {
                        parsed << "<temp> length += 4;\nforeach(...list...)\n{\n}\n";
                    }
                    break;
                }
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMemberType : public Node
// {
//     int typeType; // one of PRIMITIVE_DATA_TYPE, REFERENCE_DATA_TYPE, MAP, LIST
//     string* value; // "int", "bool", ..., "MyPacket", "Skill" or NULL when type is MAP or LIST
//     Node* generic1; // LIST<generic1>
//     Node* generic2; // MAP <generic1, generic2>
//     Node* generic3; // reserved
//     public:
    Krystal::NodePacketMemberType::NodePacketMemberType(Context* _context, int _type, string* _value) : Node(_context)
    {
        typeType = _type;
        value = _value;
        generic1 = NULL;
        generic2 = NULL;
        generic3 = NULL;
    }

    Krystal::NodePacketMemberType::NodePacketMemberType(Context* _context, int _type, Node* _generic1) : Node(_context)
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = NULL;
        generic3 = NULL;
    }

    Krystal::NodePacketMemberType::NodePacketMemberType(Context* _context, int _type, Node* _generic1, Node* _generic2) : Node(_context)
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = _generic2;
        generic3 = NULL;
    }

    Krystal::NodePacketMemberType::NodePacketMemberType(Context* _context, int _type, Node* _generic1, Node* _generic2, Node* _generic3) : Node(_context)
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = _generic2;
        generic3 = _generic3;
    }

    int Krystal::NodePacketMemberType::getType()
    {
        switch (typeType)
        {
            case Parser::token::PRIMITIVE_DATA_TYPE:
            {
                return CsNodeType::packetMemberTypePrimitive;
            }
            break;

            case Parser::token::REFERENCE_DATA_TYPE:
            {
                return CsNodeType::packetMemberTypeReference;
            }
            break;

            case Parser::token::MAP:
            {
                return CsNodeType::packetMemberTypeMap;
            }
            break;

            case Parser::token::LIST:
            {
                return CsNodeType::packetMemberTypeList;
            }
            break;
        }
        return CsNodeType::packetMemberType;
    }

    size_t Krystal::NodePacketMemberType::getHash(vector<Node*>* referencingStack)
    {
        assert(referencingStack != NULL);

        size_t packetMemberTypeHash = 0;
        switch(typeType)
        {
            case Parser::token::PRIMITIVE_DATA_TYPE:
            {
                packetMemberTypeHash = getHashCode(value);
            }
            break;

            case Parser::token::REFERENCE_DATA_TYPE:
            {
                // lookup Context::declarations table
                Node* typePacketNode = context->getDeclarationNode(value);
                if (typePacketNode == NULL)
                {
                    throw(runtime_error("No such packet type."));
                }
                packetMemberTypeHash = typePacketNode->getHash(referencingStack);
            }
            break;

            case Parser::token::MAP:
            {
                // must be specified this is map type
                // in case of other generic<t1, t2> added.
                packetMemberTypeHash = getHashCode((int)Parser::token::MAP);
                combineHashCode(packetMemberTypeHash, generic1->getHash(referencingStack));
                combineHashCode(packetMemberTypeHash, generic2->getHash(referencingStack));
            }
            break;

            case Parser::token::LIST:
            {
                // must be specified this is list type
                // in case of other generic<t> added.
                packetMemberTypeHash = getHashCode((int)Parser::token::LIST);
                combineHashCode(packetMemberTypeHash, generic1->getHash(referencingStack));
            }
            break;
        }

        return packetMemberTypeHash;
    }

    string* Krystal::NodePacketMemberType::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                switch (typeType)
                {
                    case Parser::token::PRIMITIVE_DATA_TYPE:
                    case Parser::token::REFERENCE_DATA_TYPE:
                    {
                        parsed << *value;
                    }
                    break;

                    case Parser::token::MAP:
                    {
                        parsed << format(TCS_PACKET_MEMBER_TYPE_MAP_AS_DEFAULT)
                            % *(generic1->getParsed(CsParseAs::Default))
                            % *(generic2->getParsed(CsParseAs::Default));
                    }
                    break;

                    case Parser::token::LIST:
                    {
                        parsed << format(TCS_PACKET_MEMBER_TYPE_LIST_AS_DEFAULT)
                            % *(generic1->getParsed(CsParseAs::Default));
                    }
                    break;

                    default:
                    {
                        throw(runtime_error("Unknown NodePacketMemberType type."));
                    }
                    break;
                }
            }
            break;

            case CsParseAs::GenericType1:
            {
                parsed << *(generic1->getParsed(CsParseAs::Default));
            }
            break;

            case CsParseAs::GenericType2:
            {
                parsed << *(generic2->getParsed(CsParseAs::Default));
            }
            break;

            case CsParseAs::GenericType3:
            {
                parsed << *(generic3->getParsed(CsParseAs::Default));
            }
            break;

            case CsParseAs::GenericTypeSerializer1:
            {
                parsed << *(generic1->getParsed(CsParseAs::SerializerName));
            }
            break;

            case CsParseAs::GenericTypeSerializer2:
            {
                parsed << *(generic2->getParsed(CsParseAs::SerializerName));
            }
            break;

            case CsParseAs::GenericTypeSerializer3:
            {
                parsed << *(generic3->getParsed(CsParseAs::SerializerName));
            }
            break;

            case CsParseAs::SerializerName:
            {
                switch (typeType)
                {
                    case Parser::token::PRIMITIVE_DATA_TYPE:
                    {
                        string* serializerName = lookupSerializerName(value);
                        parsed << *serializerName;
                    }
                    break;

                    case Parser::token::REFERENCE_DATA_TYPE:
                    {
                        parsed << TCS_PACKET_CUSTOM_SERIALIZER_NAME;
                    }
                    break;

                    default:
                    {
                        throw(runtime_error("Serializer not supported for nested generic type"));
                    }
                    break;
                }
            }
            break;

            case CsParseAs::Initialization:
            {
                switch (typeType)
                {
                    case Parser::token::PRIMITIVE_DATA_TYPE:
                    {
                        parsed << "";
                    }
                    break;

                    case Parser::token::REFERENCE_DATA_TYPE:
                    case Parser::token::MAP:
                    case Parser::token::LIST:
                    {
                        parsed << format(TCS_PACKET_MEMBER_TYPE_NEW_AS_INITIALIZATION)
                            % *(getParsed(CsParseAs::Default));
                    }
                    break;

                    default:
                    {
                        throw(runtime_error("Unknown NodePacketMemberType type."));
                    }
                    break;
                }
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMemberName : public Node
// {
//     string* value;
//     public:
    Krystal::NodePacketMemberName::NodePacketMemberName(Context* _context, string* _value) : Node(_context)
    {
        value = _value;
    }

    int Krystal::NodePacketMemberName::getType()
    {
       return CsNodeType::packetMemberName;
    }

    size_t Krystal::NodePacketMemberName::getHash(vector<Node*>* referencingStack)
    {
        size_t packetMemberNameHash = getHashCode(value);
        return packetMemberNameHash;
    }

    string* Krystal::NodePacketMemberName::getParsed(int as)
    {
       return value;
    }
// };

<commit_msg>print LIST type packet member's GetLength code<commit_after>#include "SyntaxTree.h"

#include <list>
#include <vector>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <assert.h>

#include <boost/format.hpp>

#include "parser.tab.hh"

#include "template.common.h"
#include "template.cs.h"

using namespace std;
using namespace boost;
using namespace Krystal;

// class Node
// {
// public:
    Krystal::Node::Node(Context* _context)
    {
        context = _context;
    }

    Krystal::Node::~Node()
    {
    }

    int Krystal::Node::getType() { return 0; } //TODO: remove getType() if unnecessary
    size_t Krystal::Node::getHash(vector<Node*>* referencingStack) { return 0; }
    string* Krystal::Node::getParsed(int as) { return 0; }

// };

// class NodeKst : public Node
// {
    // list<Node*>* commands;
    // string* fileName;
    // public:
    Krystal::NodeKst::NodeKst(Context* _context, list<Node*>* _commands, string* _fileName) : Node(_context)
    {
        commands = _commands;
        fileName = _fileName;
    }

    int Krystal::NodeKst::getType()
    {
       return CsNodeType::kst;
    }

    size_t Krystal::NodeKst::getHash(vector<Node*>* referencingStack)
    {
        return 0;
    }

    string* Krystal::NodeKst::getParsed(int as)
    {
        stringstream parsed;

        parsed << format(TCS_HEADER) % *fileName;
        parsed << TCS_USINGS;

        string namespaceByFileName = fileName->substr(0, fileName->find("."));

        parsed << format(TCS_NAMESPACE_BEGIN) % namespaceByFileName;

        list<Node*>::iterator i = commands->begin();
        list<Node*>::iterator end = commands->end();

        string* temp;

        for (; i != end; i++)
        {
            temp = (*i)->getParsed(CsParseAs::Default);
            temp = indent(temp);
            parsed << *temp;
            parsed << "\n";
        }

        parsed << TCS_NAMESPACE_END;

        parsed << "\n\n";

        return new string(parsed.str());
    }
// };

// class NodeInclude : public Node
// {
//     string* value;
//     public:
    Krystal::NodeInclude::NodeInclude(Context* _context, string* _value) : Node(_context)
    {
        value = _value;
    }

    int Krystal::NodeInclude::getType()
    {
       return CsNodeType::include;
    }

    size_t Krystal::NodeInclude::getHash(vector<Node*>* referencingStack)
    {
        return 0;
    }

    string* Krystal::NodeInclude::getParsed(int as)
    {
        stringstream parsed;

        parsed << "#include \"";
        parsed << *(value);
        parsed << "\"";

        return new string(parsed.str());
    }
// };

// class NodePacket : public Node
// {
//     string* packetName;
//     list<Node*>* packetMembers;
//     public:
    Krystal::NodePacket::NodePacket(Context* _context, string* _packetName, list<Node*>* _packetMembers) : Node(_context)
    {
        packetName = _packetName;
        packetMembers = _packetMembers;
    }

    int Krystal::NodePacket::getType()
    {
       return CsNodeType::packet;
    }

    size_t Krystal::NodePacket::getHash(vector<Node*>* referencingStack)
    {
        if (referencingStack == NULL)
        {
            referencingStack = new vector<Node*>();
        }
        else // check circular reference
        {
            vector<Node*>::iterator end = referencingStack->end();
            for (vector<Node*>::iterator i = referencingStack->begin(); i != end; i++)
            {
                if (*i == this)
                {
                    throw(runtime_error("Circular reference between packets"));
                }
            }
        }

        referencingStack->push_back(this);

        size_t packetHash = getHashCode(packetName);

        list<Node*>::iterator i = packetMembers->begin();
        list<Node*>::iterator end = packetMembers->end();
        for (; i != end; i++)
        {
            combineHashCode(packetHash, (*i)->getHash(referencingStack));
        }

        referencingStack->pop_back();

        return packetHash;
    }

    string* Krystal::NodePacket::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                parsed << format(TCS_PACKET_BEGIN) % *packetName;

                {
                    stringstream body;

                    body << format(TCS_PACKET_ID_FIELD) % ((TCS_PACKET_ID_TYPE)getHash(NULL));

                    body << TCS_PACKET_COOKIE_FIELD;

                    // Member Variables
                    list<Node*>::iterator i = packetMembers->begin();
                    list<Node*>::iterator end = packetMembers->end();
                    for (; i != end; i++)
                    {
                        body << *((*i)->getParsed(CsParseAs::Default));
                    }

                    body << format(TCS_PACKET_CONSTRUCTOR) % *packetName;

                    body << TCS_PACKET_GET_ID;

                    body << TCS_PACKET_SET_COOKIE;
                    body << TCS_PACKET_GET_COOKIE;

                    body << TCS_PACKET_GET_LENGTH_BEGIN;
                    {
                        stringstream bodyGetLengthBlock;
                        for (i = packetMembers->begin(); i != end; i++)
                        {
                            bodyGetLengthBlock << *((*i)->getParsed(CsParseAs::GetLength));
                        }

                        body << *(indent(new string(bodyGetLengthBlock.str())));
                    }
                    body << TCS_PACKET_GET_LENGTH_END;

                    parsed << *(indent(new string(body.str())));
                }

                parsed << TCS_PACKET_END;
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMember : public Node
// {
//     Node* memberType;
//     Node* memberName;
//     public:
    Krystal::NodePacketMember::NodePacketMember(Context* _context, Node* _memberType, Node* _memberName) : Node(_context)
    {
        memberType = _memberType;
        memberName = _memberName;
    }

    int Krystal::NodePacketMember::getType()
    {
       return CsNodeType::packetMember;
    }

    size_t Krystal::NodePacketMember::getHash(vector<Node*>* referencingStack)
    {
        assert(referencingStack != NULL);

        size_t packetMemberHash = memberType->getHash(referencingStack);
        combineHashCode(packetMemberHash, memberName->getHash(referencingStack));

        return packetMemberHash;
    }

    string* Krystal::NodePacketMember::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                parsed << format(TCS_PACKET_MEMBER_AS_DEFAULT)
                    % *(memberType->getParsed(CsParseAs::Default))
                    % *(memberName->getParsed(CsParseAs::Default))
                    % *(memberType->getParsed(CsParseAs::Initialization));
            }
            break;
            case CsParseAs::GetLength:
            {
                int typeType = memberType->getType();
                switch (typeType)
                {
                    case CsNodeType::packetMemberTypePrimitive:
                    {
                        string* serializerName = lookupSerializerName(memberType->getParsed(CsParseAs::Default));
                        parsed << format(TCS_PACKET_MEMBER_AS_GET_LENGTH_PRIMITIVE)
                            % *serializerName
                            % *(memberName->getParsed(CsParseAs::Default));
                    }
                    break;

                    case CsNodeType::packetMemberTypeReference:
                    {
                        parsed << format(TCS_PACKET_MEMBER_AS_GET_LENGTH_REFERENCE)
                            % *(memberName->getParsed(CsParseAs::Default));
                    }
                    break;

                    case CsNodeType::packetMemberTypeMap:
                    {
                        parsed << format(TCS_PACKET_MEMBER_AS_GET_LENGTH_MAP)
                            % *(memberType->getParsed(CsParseAs::GenericType1))
                            % *(memberType->getParsed(CsParseAs::GenericType2))
                            % *(memberName->getParsed(CsParseAs::Default))
                            % *(memberType->getParsed(CsParseAs::GenericTypeSerializer1))
                            % *(memberType->getParsed(CsParseAs::GenericTypeSerializer2));
                    }
                    break;

                    case CsNodeType::packetMemberTypeList:
                    {
                        parsed << format(TCS_PACKET_MEMBER_AS_GET_LENGTH_LIST)
                            % *(memberType->getParsed(CsParseAs::GenericType1))
                            % *(memberName->getParsed(CsParseAs::Default))
                            % *(memberType->getParsed(CsParseAs::GenericTypeSerializer1));
                    }
                    break;
                }
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMemberType : public Node
// {
//     int typeType; // one of PRIMITIVE_DATA_TYPE, REFERENCE_DATA_TYPE, MAP, LIST
//     string* value; // "int", "bool", ..., "MyPacket", "Skill" or NULL when type is MAP or LIST
//     Node* generic1; // LIST<generic1>
//     Node* generic2; // MAP <generic1, generic2>
//     Node* generic3; // reserved
//     public:
    Krystal::NodePacketMemberType::NodePacketMemberType(Context* _context, int _type, string* _value) : Node(_context)
    {
        typeType = _type;
        value = _value;
        generic1 = NULL;
        generic2 = NULL;
        generic3 = NULL;
    }

    Krystal::NodePacketMemberType::NodePacketMemberType(Context* _context, int _type, Node* _generic1) : Node(_context)
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = NULL;
        generic3 = NULL;
    }

    Krystal::NodePacketMemberType::NodePacketMemberType(Context* _context, int _type, Node* _generic1, Node* _generic2) : Node(_context)
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = _generic2;
        generic3 = NULL;
    }

    Krystal::NodePacketMemberType::NodePacketMemberType(Context* _context, int _type, Node* _generic1, Node* _generic2, Node* _generic3) : Node(_context)
    {
        typeType = _type;
        value = NULL;
        generic1 = _generic1;
        generic2 = _generic2;
        generic3 = _generic3;
    }

    int Krystal::NodePacketMemberType::getType()
    {
        switch (typeType)
        {
            case Parser::token::PRIMITIVE_DATA_TYPE:
            {
                return CsNodeType::packetMemberTypePrimitive;
            }
            break;

            case Parser::token::REFERENCE_DATA_TYPE:
            {
                return CsNodeType::packetMemberTypeReference;
            }
            break;

            case Parser::token::MAP:
            {
                return CsNodeType::packetMemberTypeMap;
            }
            break;

            case Parser::token::LIST:
            {
                return CsNodeType::packetMemberTypeList;
            }
            break;
        }
        return CsNodeType::packetMemberType;
    }

    size_t Krystal::NodePacketMemberType::getHash(vector<Node*>* referencingStack)
    {
        assert(referencingStack != NULL);

        size_t packetMemberTypeHash = 0;
        switch(typeType)
        {
            case Parser::token::PRIMITIVE_DATA_TYPE:
            {
                packetMemberTypeHash = getHashCode(value);
            }
            break;

            case Parser::token::REFERENCE_DATA_TYPE:
            {
                // lookup Context::declarations table
                Node* typePacketNode = context->getDeclarationNode(value);
                if (typePacketNode == NULL)
                {
                    throw(runtime_error("No such packet type."));
                }
                packetMemberTypeHash = typePacketNode->getHash(referencingStack);
            }
            break;

            case Parser::token::MAP:
            {
                // must be specified this is map type
                // in case of other generic<t1, t2> added.
                packetMemberTypeHash = getHashCode((int)Parser::token::MAP);
                combineHashCode(packetMemberTypeHash, generic1->getHash(referencingStack));
                combineHashCode(packetMemberTypeHash, generic2->getHash(referencingStack));
            }
            break;

            case Parser::token::LIST:
            {
                // must be specified this is list type
                // in case of other generic<t> added.
                packetMemberTypeHash = getHashCode((int)Parser::token::LIST);
                combineHashCode(packetMemberTypeHash, generic1->getHash(referencingStack));
            }
            break;
        }

        return packetMemberTypeHash;
    }

    string* Krystal::NodePacketMemberType::getParsed(int as)
    {
        stringstream parsed;

        switch (as)
        {
            case CsParseAs::Default:
            {
                switch (typeType)
                {
                    case Parser::token::PRIMITIVE_DATA_TYPE:
                    case Parser::token::REFERENCE_DATA_TYPE:
                    {
                        parsed << *value;
                    }
                    break;

                    case Parser::token::MAP:
                    {
                        parsed << format(TCS_PACKET_MEMBER_TYPE_MAP_AS_DEFAULT)
                            % *(generic1->getParsed(CsParseAs::Default))
                            % *(generic2->getParsed(CsParseAs::Default));
                    }
                    break;

                    case Parser::token::LIST:
                    {
                        parsed << format(TCS_PACKET_MEMBER_TYPE_LIST_AS_DEFAULT)
                            % *(generic1->getParsed(CsParseAs::Default));
                    }
                    break;

                    default:
                    {
                        throw(runtime_error("Unknown NodePacketMemberType type."));
                    }
                    break;
                }
            }
            break;

            case CsParseAs::GenericType1:
            {
                parsed << *(generic1->getParsed(CsParseAs::Default));
            }
            break;

            case CsParseAs::GenericType2:
            {
                parsed << *(generic2->getParsed(CsParseAs::Default));
            }
            break;

            case CsParseAs::GenericType3:
            {
                parsed << *(generic3->getParsed(CsParseAs::Default));
            }
            break;

            case CsParseAs::GenericTypeSerializer1:
            {
                parsed << *(generic1->getParsed(CsParseAs::SerializerName));
            }
            break;

            case CsParseAs::GenericTypeSerializer2:
            {
                parsed << *(generic2->getParsed(CsParseAs::SerializerName));
            }
            break;

            case CsParseAs::GenericTypeSerializer3:
            {
                parsed << *(generic3->getParsed(CsParseAs::SerializerName));
            }
            break;

            case CsParseAs::SerializerName:
            {
                switch (typeType)
                {
                    case Parser::token::PRIMITIVE_DATA_TYPE:
                    {
                        string* serializerName = lookupSerializerName(value);
                        parsed << *serializerName;
                    }
                    break;

                    case Parser::token::REFERENCE_DATA_TYPE:
                    {
                        parsed << TCS_PACKET_CUSTOM_SERIALIZER_NAME;
                    }
                    break;

                    default:
                    {
                        throw(runtime_error("Serializer not supported for nested generic type"));
                    }
                    break;
                }
            }
            break;

            case CsParseAs::Initialization:
            {
                switch (typeType)
                {
                    case Parser::token::PRIMITIVE_DATA_TYPE:
                    {
                        parsed << "";
                    }
                    break;

                    case Parser::token::REFERENCE_DATA_TYPE:
                    case Parser::token::MAP:
                    case Parser::token::LIST:
                    {
                        parsed << format(TCS_PACKET_MEMBER_TYPE_NEW_AS_INITIALIZATION)
                            % *(getParsed(CsParseAs::Default));
                    }
                    break;

                    default:
                    {
                        throw(runtime_error("Unknown NodePacketMemberType type."));
                    }
                    break;
                }
            }
            break;
        }

        return new string(parsed.str());
    }
// };

// class NodePacketMemberName : public Node
// {
//     string* value;
//     public:
    Krystal::NodePacketMemberName::NodePacketMemberName(Context* _context, string* _value) : Node(_context)
    {
        value = _value;
    }

    int Krystal::NodePacketMemberName::getType()
    {
       return CsNodeType::packetMemberName;
    }

    size_t Krystal::NodePacketMemberName::getHash(vector<Node*>* referencingStack)
    {
        size_t packetMemberNameHash = getHashCode(value);
        return packetMemberNameHash;
    }

    string* Krystal::NodePacketMemberName::getParsed(int as)
    {
       return value;
    }
// };

<|endoftext|>


<commit_before>#include <cassert>
#include <cstring>
#include <sstream>
#include <sys/time.h>
#include <unordered_set>

#include <derecho/conf/conf.hpp>
#include <derecho/core/detail/p2p_connection_manager.hpp>
#include <derecho/sst/detail/poll_utils.hpp>
#include <derecho/utils/logger.hpp>
namespace sst {
P2PConnectionManager::P2PConnectionManager(const P2PParams params)
        : my_node_id(params.my_node_id),
          failure_upcall(params.failure_upcall) {

    // HARD-CODED. Adding another request type will break this

    request_params.window_sizes[P2P_REPLY] = params.p2p_window_size;
    request_params.window_sizes[P2P_REQUEST] = params.p2p_window_size;
    request_params.window_sizes[RPC_REPLY] = params.rpc_window_size;
    request_params.max_msg_sizes[P2P_REPLY] = params.max_p2p_reply_size;
    request_params.max_msg_sizes[P2P_REQUEST] = params.max_p2p_request_size;
    request_params.max_msg_sizes[RPC_REPLY] = params.max_rpc_reply_size;

    p2p_buf_size = 0;
    for(uint8_t i = 0; i < num_request_types; ++i) {
        request_params.offsets[i] = p2p_buf_size;
        p2p_buf_size += request_params.window_sizes[i] * request_params.max_msg_sizes[i];
    }
    p2p_buf_size += sizeof(bool);

    p2p_connections[my_node_id] = std::make_unique<P2PConnection>(my_node_id, my_node_id, p2p_buf_size, request_params);

    // external client doesn't need failure checking
    if (!params.is_external) {
        timeout_thread = std::thread(&P2PConnectionManager::check_failures_loop, this);
    }
}

P2PConnectionManager::~P2PConnectionManager() {
    shutdown_failures_thread();
}

void P2PConnectionManager::add_connections(const std::vector<node_id_t>& node_ids) {
    std::lock_guard<std::mutex> lock(connections_mutex);
    for (const node_id_t remote_id : node_ids) {
	if (p2p_connections.find(remote_id) == p2p_connections.end()) {
	    p2p_connections.emplace(remote_id, std::make_unique<P2PConnection>(my_node_id, remote_id, p2p_buf_size, request_params));
    	}
    }
}

void P2PConnectionManager::remove_connections(const std::vector<node_id_t>& node_ids) {
    std::lock_guard<std::mutex> lock(connections_mutex);
    for(const node_id_t remote_id : node_ids) {
        p2p_connections.erase(remote_id);
    }
}

bool P2PConnectionManager::contains_node(const node_id_t node_id) {
    std::lock_guard<std::mutex> lock(connections_mutex);
    return (p2p_connections.find(node_id) != p2p_connections.end());
}

void P2PConnectionManager::shutdown_failures_thread() {
    thread_shutdown = true;
    if(timeout_thread.joinable()) {
        timeout_thread.join();
    }
}

uint64_t P2PConnectionManager::get_max_p2p_reply_size() {
    return request_params.max_msg_sizes[P2P_REPLY] - sizeof(uint64_t);
}

void P2PConnectionManager::update_incoming_seq_num() {
    p2p_connections[last_node_id]->update_incoming_seq_num();
}

// check if there's a new request from any node
std::optional<std::pair<node_id_t, char*>> P2PConnectionManager::probe_all() {
    for(const auto& [node_id, p2p_conn] : p2p_connections) {
        auto buf = p2p_conn->probe();
        if(buf && buf[0]) {
            last_node_id = node_id;
            return std::pair<node_id_t, char*>(node_id, buf);
        } else if(buf) {
            // this means that we have a null reply
            // we don't need to process it, but we still want to increment the seq num
            p2p_conn->update_incoming_seq_num();
            return std::pair<node_id_t, char*>(INVALID_NODE_ID, nullptr);
        }
    }
    return {};
}

char* P2PConnectionManager::get_sendbuffer_ptr(node_id_t node_id, REQUEST_TYPE type) {
    return p2p_connections.at(node_id)->get_sendbuffer_ptr(type);
}

void P2PConnectionManager::send(node_id_t node_id) {
    p2p_connections.at(node_id)->send();
    if(node_id != my_node_id) {
        p2p_connections.at(node_id)->num_rdma_writes++;
    }
}

void P2PConnectionManager::check_failures_loop() {
    pthread_setname_np(pthread_self(), "p2p_timeout");

    // using CONF_DERECHO_HEARTBEAT_MS from derecho.cfg
    uint32_t heartbeat_ms = derecho::getConfUInt32(CONF_DERECHO_HEARTBEAT_MS);
    const auto tid = std::this_thread::get_id();
    // get id first
    uint32_t ce_idx = util::polling_data.get_index(tid);

    uint16_t tick_count = 0;
    const uint16_t one_second_count = 1000/heartbeat_ms;
    while(!thread_shutdown) {
        std::this_thread::sleep_for(std::chrono::milliseconds(heartbeat_ms));
        tick_count++;
        std::unordered_set<node_id_t> posted_write_to;

        util::polling_data.set_waiting(tid);
#ifdef USE_VERBS_API
        std::map<uint32_t, verbs_sender_ctxt> sctxt;
#else
        std::map<uint32_t, lf_sender_ctxt> sctxt;
#endif

        for(const auto& [node_id, p2p_conn] : p2p_connections) {
            // checks every second regardless of num_rdma_writes
            if (node_id == my_node_id || (p2p_conn->num_rdma_writes < 1000 && tick_count < one_second_count)) {
                continue;
            }
            p2p_conn->num_rdma_writes = 0;
            sctxt[node_id].set_remote_id(node_id);
            sctxt[node_id].set_ce_idx(ce_idx);

            p2p_conn->get_res()->post_remote_write_with_completion(&sctxt[node_id], p2p_buf_size - sizeof(bool), sizeof(bool));
            posted_write_to.insert(node_id);
        }
        if (tick_count >= one_second_count) {
            tick_count = 0;
        }

        // track which nodes respond successfully
        std::unordered_set<node_id_t> polled_successfully_from;
        std::vector<node_id_t> failed_node_indexes;

        /** Completion Queue poll timeout in millisec */
        const unsigned int MAX_POLL_CQ_TIMEOUT = derecho::getConfUInt32(CONF_DERECHO_SST_POLL_CQ_TIMEOUT_MS);
        unsigned long start_time_msec;
        unsigned long cur_time_msec;
        struct timeval cur_time;

        // wait for completion for a while before giving up of doing it ..
        gettimeofday(&cur_time, NULL);
        start_time_msec = (cur_time.tv_sec * 1000) + (cur_time.tv_usec / 1000);

        for(unsigned int i = 0; i < posted_write_to.size(); i++) {
            std::optional<std::pair<int32_t, int32_t>> ce;
            while(true) {
                // check if polling result is available
                ce = util::polling_data.get_completion_entry(tid);
                if(ce) {
                    break;
                }
                gettimeofday(&cur_time, NULL);
                cur_time_msec = (cur_time.tv_sec * 1000) + (cur_time.tv_usec / 1000);
                if((cur_time_msec - start_time_msec) >= MAX_POLL_CQ_TIMEOUT) {
                    tick_count += MAX_POLL_CQ_TIMEOUT;
                    break;
                }
            }
            // if waiting for a completion entry timed out
            if(!ce) {
                // mark all nodes that have not yet responded as failed
                for(const auto& pair : p2p_connections) {
                    const auto& node_id = pair.first;
                    if(posted_write_to.find(node_id) == posted_write_to.end()
                    || polled_successfully_from.find(node_id) != polled_successfully_from.end()) {
                        continue;
                    }
                    failed_node_indexes.push_back(node_id);
                }
                break;
            }

            auto ce_v = ce.value();
            int remote_id = ce_v.first;
            int result = ce_v.second;
            if(result == 1) {
                polled_successfully_from.insert(remote_id);
            } else if(result == -1) {
                failed_node_indexes.push_back(remote_id);
            }
        }
        util::polling_data.reset_waiting(tid);

        for(auto nid : failed_node_indexes) {
            dbg_default_debug("p2p_connection_manager detected failure/timeout on node {}", nid);
            p2p_connections.at(nid)->get_res()->report_failure();
            if(failure_upcall) {
                failure_upcall(nid);
            }
        }
    }
}

void P2PConnectionManager::filter_to(const std::vector<node_id_t>& live_nodes_list) {
    std::vector<node_id_t> prev_nodes_list;
    for (const auto& e : p2p_connections ) {
        prev_nodes_list.push_back(e.first);
    }
    std::vector<node_id_t> departed;
    std::set_difference(prev_nodes_list.begin(), prev_nodes_list.end(),
                        live_nodes_list.begin(), live_nodes_list.end(),
                        std::back_inserter(departed));
    remove_connections(departed);
}
void P2PConnectionManager::debug_print() {
    // std::cout << "Members: " << std::endl;
    // for(const auto& [node_id, p2p_conn] : p2p_connections) {
    //     std::cout << node_id << " ";
    // }
    // std::cout << std::endl;

    // for(const auto& type : p2p_request_types) {
    //     std::cout << "P2PConnections: Request type " << type << std::endl;
    //     for(uint32_t node = 0; node < num_members; ++node) {
    //         std::cout << "Node " << node << std::endl;
    //         std::cout << "incoming seq_nums:";
    //         for(uint32_t i = 0; i < request_params.window_sizes[type]; ++i) {
    //             uint64_t offset = request_params.max_msg_sizes[type] * (type * request_params.window_sizes[type] + i + 1) - sizeof(uint64_t);
    //             std::cout << " " << (uint64_t&)p2p_connections[node]->incoming_p2p_buffer[offset];
    //         }
    //         std::cout << std::endl
    //                   << "outgoing seq_nums:";
    //         for(uint32_t i = 0; i < request_params.window_sizes[type]; ++i) {
    //             uint64_t offset = request_params.max_msg_sizes[type] * (type * request_params.window_sizes[type] + i + 1) - sizeof(uint64_t);
    //             std::cout << " " << (uint64_t&)p2p_connections[node]->outgoing_p2p_buffer[offset];
    //         }
    //         std::cout << std::endl;
    //     }
    // }
}
}  // namespace sst
<commit_msg>bugfix: testing null reply condition using the first byte in the buffer is not reliable. #187<commit_after>#include <cassert>
#include <cstring>
#include <sstream>
#include <sys/time.h>
#include <unordered_set>

#include <derecho/conf/conf.hpp>
#include <derecho/core/detail/p2p_connection_manager.hpp>
#include <derecho/sst/detail/poll_utils.hpp>
#include <derecho/utils/logger.hpp>
namespace sst {
P2PConnectionManager::P2PConnectionManager(const P2PParams params)
        : my_node_id(params.my_node_id),
          failure_upcall(params.failure_upcall) {

    // HARD-CODED. Adding another request type will break this

    request_params.window_sizes[P2P_REPLY] = params.p2p_window_size;
    request_params.window_sizes[P2P_REQUEST] = params.p2p_window_size;
    request_params.window_sizes[RPC_REPLY] = params.rpc_window_size;
    request_params.max_msg_sizes[P2P_REPLY] = params.max_p2p_reply_size;
    request_params.max_msg_sizes[P2P_REQUEST] = params.max_p2p_request_size;
    request_params.max_msg_sizes[RPC_REPLY] = params.max_rpc_reply_size;

    p2p_buf_size = 0;
    for(uint8_t i = 0; i < num_request_types; ++i) {
        request_params.offsets[i] = p2p_buf_size;
        p2p_buf_size += request_params.window_sizes[i] * request_params.max_msg_sizes[i];
    }
    p2p_buf_size += sizeof(bool);

    p2p_connections[my_node_id] = std::make_unique<P2PConnection>(my_node_id, my_node_id, p2p_buf_size, request_params);

    // external client doesn't need failure checking
    if (!params.is_external) {
        timeout_thread = std::thread(&P2PConnectionManager::check_failures_loop, this);
    }
}

P2PConnectionManager::~P2PConnectionManager() {
    shutdown_failures_thread();
}

void P2PConnectionManager::add_connections(const std::vector<node_id_t>& node_ids) {
    std::lock_guard<std::mutex> lock(connections_mutex);
    for (const node_id_t remote_id : node_ids) {
	if (p2p_connections.find(remote_id) == p2p_connections.end()) {
	    p2p_connections.emplace(remote_id, std::make_unique<P2PConnection>(my_node_id, remote_id, p2p_buf_size, request_params));
    	}
    }
}

void P2PConnectionManager::remove_connections(const std::vector<node_id_t>& node_ids) {
    std::lock_guard<std::mutex> lock(connections_mutex);
    for(const node_id_t remote_id : node_ids) {
        p2p_connections.erase(remote_id);
    }
}

bool P2PConnectionManager::contains_node(const node_id_t node_id) {
    std::lock_guard<std::mutex> lock(connections_mutex);
    return (p2p_connections.find(node_id) != p2p_connections.end());
}

void P2PConnectionManager::shutdown_failures_thread() {
    thread_shutdown = true;
    if(timeout_thread.joinable()) {
        timeout_thread.join();
    }
}

uint64_t P2PConnectionManager::get_max_p2p_reply_size() {
    return request_params.max_msg_sizes[P2P_REPLY] - sizeof(uint64_t);
}

void P2PConnectionManager::update_incoming_seq_num() {
    p2p_connections[last_node_id]->update_incoming_seq_num();
}

// check if there's a new request from any node
std::optional<std::pair<node_id_t, char*>> P2PConnectionManager::probe_all() {
    for(const auto& [node_id, p2p_conn] : p2p_connections) {
        auto buf = p2p_conn->probe();
        // In include/derecho/core/detail/rpc_utils.hpp:
        // Please note that populate_header() put payload_size(size_t) at the beginning of buffer.
        // If we only test buf[0], it will fall in the wrong path if the least significant byte of the payload size is
        // zero.
        if(buf && reinterpret_cast<size_t*>(buf)[0]) {
            last_node_id = node_id;
            return std::pair<node_id_t, char*>(node_id, buf);
        } else if(buf) {
            // this means that we have a null reply
            // we don't need to process it, but we still want to increment the seq num
            p2p_conn->update_incoming_seq_num();
            return std::pair<node_id_t, char*>(INVALID_NODE_ID, nullptr);
        }
    }
    return {};
}

char* P2PConnectionManager::get_sendbuffer_ptr(node_id_t node_id, REQUEST_TYPE type) {
    return p2p_connections.at(node_id)->get_sendbuffer_ptr(type);
}

void P2PConnectionManager::send(node_id_t node_id) {
    p2p_connections.at(node_id)->send();
    if(node_id != my_node_id) {
        p2p_connections.at(node_id)->num_rdma_writes++;
    }
}

void P2PConnectionManager::check_failures_loop() {
    pthread_setname_np(pthread_self(), "p2p_timeout");

    // using CONF_DERECHO_HEARTBEAT_MS from derecho.cfg
    uint32_t heartbeat_ms = derecho::getConfUInt32(CONF_DERECHO_HEARTBEAT_MS);
    const auto tid = std::this_thread::get_id();
    // get id first
    uint32_t ce_idx = util::polling_data.get_index(tid);

    uint16_t tick_count = 0;
    const uint16_t one_second_count = 1000/heartbeat_ms;
    while(!thread_shutdown) {
        std::this_thread::sleep_for(std::chrono::milliseconds(heartbeat_ms));
        tick_count++;
        std::unordered_set<node_id_t> posted_write_to;

        util::polling_data.set_waiting(tid);
#ifdef USE_VERBS_API
        std::map<uint32_t, verbs_sender_ctxt> sctxt;
#else
        std::map<uint32_t, lf_sender_ctxt> sctxt;
#endif

        for(const auto& [node_id, p2p_conn] : p2p_connections) {
            // checks every second regardless of num_rdma_writes
            if (node_id == my_node_id || (p2p_conn->num_rdma_writes < 1000 && tick_count < one_second_count)) {
                continue;
            }
            p2p_conn->num_rdma_writes = 0;
            sctxt[node_id].set_remote_id(node_id);
            sctxt[node_id].set_ce_idx(ce_idx);

            p2p_conn->get_res()->post_remote_write_with_completion(&sctxt[node_id], p2p_buf_size - sizeof(bool), sizeof(bool));
            posted_write_to.insert(node_id);
        }
        if (tick_count >= one_second_count) {
            tick_count = 0;
        }

        // track which nodes respond successfully
        std::unordered_set<node_id_t> polled_successfully_from;
        std::vector<node_id_t> failed_node_indexes;

        /** Completion Queue poll timeout in millisec */
        const unsigned int MAX_POLL_CQ_TIMEOUT = derecho::getConfUInt32(CONF_DERECHO_SST_POLL_CQ_TIMEOUT_MS);
        unsigned long start_time_msec;
        unsigned long cur_time_msec;
        struct timeval cur_time;

        // wait for completion for a while before giving up of doing it ..
        gettimeofday(&cur_time, NULL);
        start_time_msec = (cur_time.tv_sec * 1000) + (cur_time.tv_usec / 1000);

        for(unsigned int i = 0; i < posted_write_to.size(); i++) {
            std::optional<std::pair<int32_t, int32_t>> ce;
            while(true) {
                // check if polling result is available
                ce = util::polling_data.get_completion_entry(tid);
                if(ce) {
                    break;
                }
                gettimeofday(&cur_time, NULL);
                cur_time_msec = (cur_time.tv_sec * 1000) + (cur_time.tv_usec / 1000);
                if((cur_time_msec - start_time_msec) >= MAX_POLL_CQ_TIMEOUT) {
                    tick_count += MAX_POLL_CQ_TIMEOUT;
                    break;
                }
            }
            // if waiting for a completion entry timed out
            if(!ce) {
                // mark all nodes that have not yet responded as failed
                for(const auto& pair : p2p_connections) {
                    const auto& node_id = pair.first;
                    if(posted_write_to.find(node_id) == posted_write_to.end()
                    || polled_successfully_from.find(node_id) != polled_successfully_from.end()) {
                        continue;
                    }
                    failed_node_indexes.push_back(node_id);
                }
                break;
            }

            auto ce_v = ce.value();
            int remote_id = ce_v.first;
            int result = ce_v.second;
            if(result == 1) {
                polled_successfully_from.insert(remote_id);
            } else if(result == -1) {
                failed_node_indexes.push_back(remote_id);
            }
        }
        util::polling_data.reset_waiting(tid);

        for(auto nid : failed_node_indexes) {
            dbg_default_debug("p2p_connection_manager detected failure/timeout on node {}", nid);
            p2p_connections.at(nid)->get_res()->report_failure();
            if(failure_upcall) {
                failure_upcall(nid);
            }
        }
    }
}

void P2PConnectionManager::filter_to(const std::vector<node_id_t>& live_nodes_list) {
    std::vector<node_id_t> prev_nodes_list;
    for (const auto& e : p2p_connections ) {
        prev_nodes_list.push_back(e.first);
    }
    std::vector<node_id_t> departed;
    std::set_difference(prev_nodes_list.begin(), prev_nodes_list.end(),
                        live_nodes_list.begin(), live_nodes_list.end(),
                        std::back_inserter(departed));
    remove_connections(departed);
}
void P2PConnectionManager::debug_print() {
    // std::cout << "Members: " << std::endl;
    // for(const auto& [node_id, p2p_conn] : p2p_connections) {
    //     std::cout << node_id << " ";
    // }
    // std::cout << std::endl;

    // for(const auto& type : p2p_request_types) {
    //     std::cout << "P2PConnections: Request type " << type << std::endl;
    //     for(uint32_t node = 0; node < num_members; ++node) {
    //         std::cout << "Node " << node << std::endl;
    //         std::cout << "incoming seq_nums:";
    //         for(uint32_t i = 0; i < request_params.window_sizes[type]; ++i) {
    //             uint64_t offset = request_params.max_msg_sizes[type] * (type * request_params.window_sizes[type] + i + 1) - sizeof(uint64_t);
    //             std::cout << " " << (uint64_t&)p2p_connections[node]->incoming_p2p_buffer[offset];
    //         }
    //         std::cout << std::endl
    //                   << "outgoing seq_nums:";
    //         for(uint32_t i = 0; i < request_params.window_sizes[type]; ++i) {
    //             uint64_t offset = request_params.max_msg_sizes[type] * (type * request_params.window_sizes[type] + i + 1) - sizeof(uint64_t);
    //             std::cout << " " << (uint64_t&)p2p_connections[node]->outgoing_p2p_buffer[offset];
    //         }
    //         std::cout << std::endl;
    //     }
    // }
}
}  // namespace sst
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/common/adapters/adapter_manager.h"

#include "modules/common/adapters/adapter_gflags.h"
#include "modules/common/util/util.h"

namespace apollo {
namespace common {
namespace adapter {

AdapterManager::AdapterManager() {}

void AdapterManager::Observe() {
  for (const auto observe : instance()->observers_) {
    observe();
  }
}

bool AdapterManager::Initialized() {
  return instance()->initialized_;
}

void AdapterManager::Reset() {
  instance()->initialized_ = false;
}

void AdapterManager::Init(const std::string &adapter_config_filename) {
  // Parse config file
  AdapterManagerConfig configs;
  CHECK(util::GetProtoFromFile(adapter_config_filename, &configs))
      << "Unable to parse adapter config file " << adapter_config_filename;
  AINFO << "Init AdapterManger config:" << configs.DebugString();
  Init(configs);
}

void AdapterManager::Init(const AdapterManagerConfig &configs) {
  if (Initialized()) {
    return;
  }

  instance()->initialized_ = true;
  if (configs.is_ros()) {
    instance()->node_handle_.reset(new ros::NodeHandle());
  }

  for (const auto &config : configs.config()) {
    switch (config.type()) {
      case AdapterConfig::POINT_CLOUD:
        EnablePointCloud(FLAGS_pointcloud_topic, config.mode(),
                         config.message_history_limit());
        break;
      case AdapterConfig::GPS:
        EnableGps(FLAGS_gps_topic, config.mode(),
                  config.message_history_limit());
        break;
      case AdapterConfig::IMU:
        EnableImu(FLAGS_imu_topic, config.mode(),
                  config.message_history_limit());
        break;
      case AdapterConfig::CHASSIS:
        EnableChassis(FLAGS_chassis_topic, config.mode(),
                      config.message_history_limit());
        break;
      case AdapterConfig::LOCALIZATION:
        EnableLocalization(FLAGS_localization_topic, config.mode(),
                           config.message_history_limit());
        break;
      case AdapterConfig::PERCEPTION_OBSTACLES:
        EnablePerceptionObstacles(FLAGS_perception_obstacle_topic,
                                  config.mode(),
                                  config.message_history_limit());
        break;
      case AdapterConfig::TRAFFIC_LIGHT_DETECTION:
        EnableTrafficLightDetection(FLAGS_traffic_light_detection_topic,
                                    config.mode(),
                                    config.message_history_limit());
      case AdapterConfig::PAD:
        EnablePad(FLAGS_pad_topic, config.mode(),
                  config.message_history_limit());
        break;
      case AdapterConfig::CONTROL_COMMAND:
        EnableControlCommand(FLAGS_control_command_topic, config.mode(),
                             config.message_history_limit());
        break;
      case AdapterConfig::ROUTING_REQUEST:
        EnableRoutingRequest(FLAGS_routing_request_topic, config.mode(),
                             config.message_history_limit());
        break;
      case AdapterConfig::ROUTING_RESPONSE:
        EnableRoutingResponse(FLAGS_routing_response_topic, config.mode(),
                              config.message_history_limit());
        break;
      case AdapterConfig::PLANNING_TRAJECTORY:
        EnablePlanning(FLAGS_planning_trajectory_topic, config.mode(),
                       config.message_history_limit());
        break;
      case AdapterConfig::PREDICTION:
        EnablePrediction(FLAGS_prediction_topic, config.mode(),
                         config.message_history_limit());
        break;
      case AdapterConfig::MONITOR:
        EnableMonitor(FLAGS_monitor_topic, config.mode(),
                      config.message_history_limit());
        break;
      case AdapterConfig::CHASSIS_DETAIL:
        EnableChassisDetail(FLAGS_chassis_detail_topic, config.mode(),
                            config.message_history_limit());
        break;
      case AdapterConfig::RELATIVE_ODOMETRY:
        EnableRelativeOdometry(FLAGS_relative_odometry_topic, config.mode(),
                               config.message_history_limit());
        break;
      case AdapterConfig::INS_STAT:
        EnableInsStat(FLAGS_ins_stat_topic, config.mode(),
                      config.message_history_limit());
        break;
      case AdapterConfig::HMI_COMMAND:
        EnableHMICommand(FLAGS_hmi_command_topic, config.mode(),
                         config.message_history_limit());
        break;
      case AdapterConfig::MOBILEYE:
        EnableMobileye(FLAGS_mobileye_topic, config.mode(),
                       config.message_history_limit());
        break;
      case AdapterConfig::DELPHIESR:
        EnableDelphiESR(FLAGS_delphi_esr_topic, config.mode(),
                        config.message_history_limit());
        break;
      case AdapterConfig::COMPRESSED_IMAGE:
        EnableCompressedImage(FLAGS_compressed_image_topic, config.mode(),
                              config.message_history_limit());
        break;
      case AdapterConfig::HMI_STATUS:
        EnableHMIStatus(FLAGS_hmi_status_topic, config.mode(),
                        config.message_history_limit());
        break;
      default:
        AERROR << "Unknown adapter config type!";
        break;
    }
  }
}

}  // namespace adapter
}  // namespace common
}  // namespace apollo
<commit_msg>Common: Fix reset (#920)<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/common/adapters/adapter_manager.h"

#include "modules/common/adapters/adapter_gflags.h"
#include "modules/common/util/util.h"

namespace apollo {
namespace common {
namespace adapter {

AdapterManager::AdapterManager() {}

void AdapterManager::Observe() {
  for (const auto observe : instance()->observers_) {
    observe();
  }
}

bool AdapterManager::Initialized() {
  return instance()->initialized_;
}

void AdapterManager::Reset() {
  instance()->initialized_ = false;
  instance()->observers_.clear();
}

void AdapterManager::Init(const std::string &adapter_config_filename) {
  // Parse config file
  AdapterManagerConfig configs;
  CHECK(util::GetProtoFromFile(adapter_config_filename, &configs))
      << "Unable to parse adapter config file " << adapter_config_filename;
  AINFO << "Init AdapterManger config:" << configs.DebugString();
  Init(configs);
}

void AdapterManager::Init(const AdapterManagerConfig &configs) {
  if (Initialized()) {
    return;
  }

  instance()->initialized_ = true;
  if (configs.is_ros()) {
    instance()->node_handle_.reset(new ros::NodeHandle());
  }

  for (const auto &config : configs.config()) {
    switch (config.type()) {
      case AdapterConfig::POINT_CLOUD:
        EnablePointCloud(FLAGS_pointcloud_topic, config.mode(),
                         config.message_history_limit());
        break;
      case AdapterConfig::GPS:
        EnableGps(FLAGS_gps_topic, config.mode(),
                  config.message_history_limit());
        break;
      case AdapterConfig::IMU:
        EnableImu(FLAGS_imu_topic, config.mode(),
                  config.message_history_limit());
        break;
      case AdapterConfig::CHASSIS:
        EnableChassis(FLAGS_chassis_topic, config.mode(),
                      config.message_history_limit());
        break;
      case AdapterConfig::LOCALIZATION:
        EnableLocalization(FLAGS_localization_topic, config.mode(),
                           config.message_history_limit());
        break;
      case AdapterConfig::PERCEPTION_OBSTACLES:
        EnablePerceptionObstacles(FLAGS_perception_obstacle_topic,
                                  config.mode(),
                                  config.message_history_limit());
        break;
      case AdapterConfig::TRAFFIC_LIGHT_DETECTION:
        EnableTrafficLightDetection(FLAGS_traffic_light_detection_topic,
                                    config.mode(),
                                    config.message_history_limit());
      case AdapterConfig::PAD:
        EnablePad(FLAGS_pad_topic, config.mode(),
                  config.message_history_limit());
        break;
      case AdapterConfig::CONTROL_COMMAND:
        EnableControlCommand(FLAGS_control_command_topic, config.mode(),
                             config.message_history_limit());
        break;
      case AdapterConfig::ROUTING_REQUEST:
        EnableRoutingRequest(FLAGS_routing_request_topic, config.mode(),
                             config.message_history_limit());
        break;
      case AdapterConfig::ROUTING_RESPONSE:
        EnableRoutingResponse(FLAGS_routing_response_topic, config.mode(),
                              config.message_history_limit());
        break;
      case AdapterConfig::PLANNING_TRAJECTORY:
        EnablePlanning(FLAGS_planning_trajectory_topic, config.mode(),
                       config.message_history_limit());
        break;
      case AdapterConfig::PREDICTION:
        EnablePrediction(FLAGS_prediction_topic, config.mode(),
                         config.message_history_limit());
        break;
      case AdapterConfig::MONITOR:
        EnableMonitor(FLAGS_monitor_topic, config.mode(),
                      config.message_history_limit());
        break;
      case AdapterConfig::CHASSIS_DETAIL:
        EnableChassisDetail(FLAGS_chassis_detail_topic, config.mode(),
                            config.message_history_limit());
        break;
      case AdapterConfig::RELATIVE_ODOMETRY:
        EnableRelativeOdometry(FLAGS_relative_odometry_topic, config.mode(),
                               config.message_history_limit());
        break;
      case AdapterConfig::INS_STAT:
        EnableInsStat(FLAGS_ins_stat_topic, config.mode(),
                      config.message_history_limit());
        break;
      case AdapterConfig::HMI_COMMAND:
        EnableHMICommand(FLAGS_hmi_command_topic, config.mode(),
                         config.message_history_limit());
        break;
      case AdapterConfig::MOBILEYE:
        EnableMobileye(FLAGS_mobileye_topic, config.mode(),
                       config.message_history_limit());
        break;
      case AdapterConfig::DELPHIESR:
        EnableDelphiESR(FLAGS_delphi_esr_topic, config.mode(),
                        config.message_history_limit());
        break;
      case AdapterConfig::COMPRESSED_IMAGE:
        EnableCompressedImage(FLAGS_compressed_image_topic, config.mode(),
                              config.message_history_limit());
        break;
      case AdapterConfig::HMI_STATUS:
        EnableHMIStatus(FLAGS_hmi_status_topic, config.mode(),
                        config.message_history_limit());
        break;
      default:
        AERROR << "Unknown adapter config type!";
        break;
    }
  }
}

}  // namespace adapter
}  // namespace common
}  // namespace apollo
<|endoftext|>


<commit_before>/* <x0/mod_accesslog.cpp>
 *
 * This file is part of the x0 web server, released under GPLv3.
 * (c) 2009 Chrisitan Parpart <trapni@gentoo.org>
 */

#include <x0/server.hpp>
#include <x0/request.hpp>
#include <x0/response.hpp>
#include <x0/header.hpp>
#include <x0/strutils.hpp>
#include <x0/types.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <cstring>
#include <cerrno>

/**
 * \ingroup modules
 * \brief implements an accesslog log facility - in spirit of "combined" mode of apache's accesslog logs.
 */
class accesslog_plugin :
	public x0::plugin
{
private:
	boost::signals::connection c;
	std::string filename;
	int fd;

public:
	accesslog_plugin(x0::server& srv, const std::string& name) :
		x0::plugin(srv, name),
		filename(), fd(-1)
	{
		c = srv.request_done.connect(boost::bind(&accesslog_plugin::request_done, this, _1, _2));
	}

	~accesslog_plugin()
	{
		server_.request_done.disconnect(c);

		if (fd != -1)
		{
			::close(fd);
		}
	}

	virtual void configure()
	{
		// TODO retrieve file to store accesslog log to.
		filename = server_.get_config().get("service", "accesslog-filename");

		if (!filename.empty())
		{
			fd = ::open(filename.c_str(), O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644);
			if (fd == -1)
			{
				LOG(server_, x0::severity::error, "Could not open access log file.");
			}
		}
	}

private:
	void request_done(x0::request& in, x0::response& out)
	{
		if (fd != -1)
		{
			std::stringstream sstr;
			sstr << hostname(in);
			sstr << " - "; // identity as of identd
			sstr << username(in) << ' ';
			sstr << now() << " \"";
			sstr << request_line(in) << "\" ";
			sstr << out.status << ' ';
			sstr << out.content.length() << ' ';
			sstr << '"' << get_header(in, "Referer") << "\" ";
			sstr << '"' << get_header(in, "User-Agent") << '"';
			sstr << std::endl;

			std::string line(sstr.str());

			::write(fd, line.c_str(), line.size());
		}
	}

	inline std::string hostname(x0::request& in)
	{
		std::string name = in.connection->socket().remote_endpoint().address().to_string();
		return !name.empty() ? name : "-";
	}

	inline std::string username(x0::request& in)
	{
		return !in.username.empty() ? in.username : "-";
	}

	inline std::string request_line(x0::request& in)
	{
		std::stringstream str;

		str << in.method << ' ' << in.uri
			<< " HTTP/" << in.http_version_major << '.' << in.http_version_minor;

		return str.str();
	}

	inline std::string now()
	{
		char buf[26];
		std::time_t ts = time(0);

		if (struct tm *tm = localtime(&ts))
		{
			if (strftime(buf, sizeof(buf), "[%m/%d/%y:%T %z]", tm) != 0)
			{
				return buf;
			}
		}
		return "-";
	}

	inline std::string get_header(const x0::request& in, const std::string& name)
	{
		std::string value(in.get_header(name));
		return !value.empty() ? value : "-";
	}
};

extern "C" x0::plugin *accesslog_init(x0::server& srv, const std::string& name) {
	return new accesslog_plugin(srv, name);
}
<commit_msg>typo fix in timestamp format<commit_after>/* <x0/mod_accesslog.cpp>
 *
 * This file is part of the x0 web server, released under GPLv3.
 * (c) 2009 Chrisitan Parpart <trapni@gentoo.org>
 */

#include <x0/server.hpp>
#include <x0/request.hpp>
#include <x0/response.hpp>
#include <x0/header.hpp>
#include <x0/strutils.hpp>
#include <x0/types.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <cstring>
#include <cerrno>

/**
 * \ingroup modules
 * \brief implements an accesslog log facility - in spirit of "combined" mode of apache's accesslog logs.
 */
class accesslog_plugin :
	public x0::plugin
{
private:
	boost::signals::connection c;
	std::string filename;
	int fd;

public:
	accesslog_plugin(x0::server& srv, const std::string& name) :
		x0::plugin(srv, name),
		filename(), fd(-1)
	{
		c = srv.request_done.connect(boost::bind(&accesslog_plugin::request_done, this, _1, _2));
	}

	~accesslog_plugin()
	{
		server_.request_done.disconnect(c);

		if (fd != -1)
		{
			::close(fd);
		}
	}

	virtual void configure()
	{
		// TODO retrieve file to store accesslog log to.
		filename = server_.get_config().get("service", "accesslog-filename");

		if (!filename.empty())
		{
			fd = ::open(filename.c_str(), O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644);
			if (fd == -1)
			{
				LOG(server_, x0::severity::error, "Could not open access log file.");
			}
		}
	}

private:
	void request_done(x0::request& in, x0::response& out)
	{
		if (fd != -1)
		{
			std::stringstream sstr;
			sstr << hostname(in);
			sstr << " - "; // identity as of identd
			sstr << username(in) << ' ';
			sstr << now() << " \"";
			sstr << request_line(in) << "\" ";
			sstr << out.status << ' ';
			sstr << out.content.length() << ' ';
			sstr << '"' << get_header(in, "Referer") << "\" ";
			sstr << '"' << get_header(in, "User-Agent") << '"';
			sstr << std::endl;

			std::string line(sstr.str());

			::write(fd, line.c_str(), line.size());
		}
	}

	inline std::string hostname(x0::request& in)
	{
		std::string name = in.connection->socket().remote_endpoint().address().to_string();
		return !name.empty() ? name : "-";
	}

	inline std::string username(x0::request& in)
	{
		return !in.username.empty() ? in.username : "-";
	}

	inline std::string request_line(x0::request& in)
	{
		std::stringstream str;

		str << in.method << ' ' << in.uri
			<< " HTTP/" << in.http_version_major << '.' << in.http_version_minor;

		return str.str();
	}

	inline std::string now()
	{
		char buf[26];
		std::time_t ts = time(0);

		if (struct tm *tm = localtime(&ts))
		{
			if (strftime(buf, sizeof(buf), "[%m/%d/%Y:%T %z]", tm) != 0)
			{
				return buf;
			}
		}
		return "-";
	}

	inline std::string get_header(const x0::request& in, const std::string& name)
	{
		std::string value(in.get_header(name));
		return !value.empty() ? value : "-";
	}
};

extern "C" x0::plugin *accesslog_init(x0::server& srv, const std::string& name) {
	return new accesslog_plugin(srv, name);
}
<|endoftext|>


<commit_before>#include <limits>
#include <string>
#include <utility>

// Algorithm to be tested

template <class Type> constexpr Type to_base(char c, unsigned base)
{
  return base <= 10
      ? c - '0'
      : (c > '9' ? static_cast<Type>(c-'a'+10) : static_cast<Type>(c-'0'));
}

template <class OutType> constexpr OutType _atox(const char* expression, unsigned base, OutType prev = OutType())
{
  return *expression == '\0'
      ? prev
      : (*expression == '-'
        ? -_atox(expression +1, base, prev)
        : _atox(expression +1, base, prev * base + to_base<OutType>(*expression, base)));
}

constexpr auto string_to_int(const char* expression, unsigned base=10) { return _atox<int>(expression, base); }
auto string_to_int(std::string const& expression, unsigned base=10) { return string_to_int(expression.c_str(), base); }

constexpr auto string_to_long(const char* expression, unsigned base=10) { return _atox<long>(expression, base); }
auto string_to_long(std::string const& expression, unsigned base=10) { return string_to_long(expression.c_str(), base); }

constexpr auto string_to_longlong(const char* expression, unsigned base=10) { return _atox<long long>(expression, base); }
auto string_to_longlong(std::string const& expression, unsigned base=10) { return string_to_longlong(expression.c_str(), base); }
<commit_msg>[visual studio][string-to-int] Bad template instanciation<commit_after>#include <limits>
#include <string>
#include <utility>

// Algorithm to be tested

template <class Type> constexpr Type to_base(char c, unsigned base)
{
  return base <= 10
      ? c - '0'
      : (c > '9' ? static_cast<Type>(c-'a'+10) : static_cast<Type>(c-'0'));
}

template <class OutType> constexpr OutType _atox(const char* expression, unsigned base, OutType prev = OutType())
{
  return *expression == '\0'
      ? prev
      : (*expression == '-'
        ? -_atox(expression +1, base, prev)
        : _atox(expression +1, base, static_cast<OutType>(prev * base + to_base<OutType>(*expression, base))));
}

constexpr auto string_to_int(const char* expression, unsigned base=10) { return _atox<int>(expression, base); }
auto string_to_int(std::string const& expression, unsigned base=10) { return string_to_int(expression.c_str(), base); }

constexpr auto string_to_long(const char* expression, unsigned base=10) { return _atox<long>(expression, base); }
auto string_to_long(std::string const& expression, unsigned base=10) { return string_to_long(expression.c_str(), base); }

constexpr auto string_to_longlong(const char* expression, unsigned base=10) { return _atox<long long>(expression, base); }
auto string_to_longlong(std::string const& expression, unsigned base=10) { return string_to_longlong(expression.c_str(), base); }
<|endoftext|>


<commit_before>#ifndef VOLE_VALUE
#define VOLE_VALUE

#include "slice.hpp"

namespace Vole {

  struct Value;
  using String = Slice<char>;
  using Vector = Slice<Value>;

  struct Value {
    enum Type {
      BOOLEAN,
      NUMBER,
      // SYMBOL,
      STRING,
      // REGEXP,
      VECTOR,
      // MAPPING
    } type;

    // for garbage collection
    enum Color {
      BLACK,
      GRAY,
      WHITE
    } color;

    union Content {
      bool    boolean;
      double  number;
      // wrapper around a String, every symbol with a name is unique
      // Symbol  symbol;
      String  string;
      // Regexp regexp;
      Vector  vector;
      // Mapping mapping;

      Content(bool b)    : boolean(b) { }
      Content(double d)  : number(d)  { }
      // Content(Symbol s) { new (&symbol) Symbol(s); }
      Content(String s)  { new (&string) String(s); }
      Content(Vector v)  { new (&vector) Vector(v); }
      // Content(Mapping m) { new (&mapping) Mapping(m); }
    } content;

    template <typename T>
    Value(T thing, Color c = BLACK)
    : type(BOOLEAN), color(c), content(true)
    { }

    operator std::string() {
      std::stringstream ss;
      switch (type) {
        case BOOLEAN: {
          ss << content.boolean;
        } break;
        case NUMBER: {
          ss << content.number;
        } break;
        case STRING: {
          ss << content.string;
        } break;
        case VECTOR: {
          ss << content.vector;
        } break;
      }
      return ss.str();
    }
  };

  template <>
  Value::Value(bool b, Color c)
  : type(BOOLEAN), color(c), content(b)
  { }

  template <>
  Value::Value(double d, Color c)
  : type(NUMBER), color(c), content(d)
  { }

  template <>
  Value::Value(String s, Color c)
  : type(STRING), color(c), content(s)
  { }

  template <>
  Value::Value(Vector v, Color c)
  : type(VECTOR), color(c), content(v)
  { }

  template <typename IOS>
  IOS& operator<<(IOS& ios, Value val) {
    switch (val.type) {
      case Value::BOOLEAN: {
        ios << val.content.boolean;
      } break;
      case Value::NUMBER: {
        ios << val.content.number;
      } break;
      case Value::STRING: {
        ios << val.content.string;
      } break;
      case Value::VECTOR: {
        ios << val.content.vector;
      } break;
    }
    return ios;
  }

}

#endif<commit_msg>making bools look more traditional<commit_after>#ifndef VOLE_VALUE
#define VOLE_VALUE

#include "slice.hpp"

namespace Vole {

  struct Value;
  using String = Slice<char>;
  using Vector = Slice<Value>;

  struct Value {
    enum Type {
      BOOLEAN,
      NUMBER,
      // SYMBOL,
      STRING,
      // REGEXP,
      VECTOR,
      // MAPPING
    } type;

    // for garbage collection
    enum Color {
      BLACK,
      GRAY,
      WHITE
    } color;

    union Content {
      bool    boolean;
      double  number;
      // wrapper around a String, every symbol with a name is unique
      // Symbol  symbol;
      String  string;
      // Regexp regexp;
      Vector  vector;
      // Mapping mapping;

      Content(bool b)    : boolean(b) { }
      Content(double d)  : number(d)  { }
      // Content(Symbol s) { new (&symbol) Symbol(s); }
      Content(String s)  { new (&string) String(s); }
      Content(Vector v)  { new (&vector) Vector(v); }
      // Content(Mapping m) { new (&mapping) Mapping(m); }
    } content;

    template <typename T>
    Value(T thing, Color c = BLACK)
    : type(BOOLEAN), color(c), content(true)
    { }

    operator std::string() {
      std::stringstream ss;
      switch (type) {
        case BOOLEAN: {
          ss << (content.boolean ? "#t" : "#f");
        } break;
        case NUMBER: {
          ss << content.number;
        } break;
        case STRING: {
          ss << content.string;
        } break;
        case VECTOR: {
          ss << content.vector;
        } break;
      }
      return ss.str();
    }
  };

  template <>
  Value::Value(bool b, Color c)
  : type(BOOLEAN), color(c), content(b)
  { }

  template <>
  Value::Value(double d, Color c)
  : type(NUMBER), color(c), content(d)
  { }

  template <>
  Value::Value(String s, Color c)
  : type(STRING), color(c), content(s)
  { }

  template <>
  Value::Value(Vector v, Color c)
  : type(VECTOR), color(c), content(v)
  { }

  template <typename IOS>
  IOS& operator<<(IOS& ios, Value val) {
    switch (val.type) {
      case Value::BOOLEAN: {
        ios << (val.content.boolean ? "#t" : "#f");
      } break;
      case Value::NUMBER: {
        ios << val.content.number;
      } break;
      case Value::STRING: {
        ios << val.content.string;
      } break;
      case Value::VECTOR: {
        ios << val.content.vector;
      } break;
    }
    return ios;
  }

}

#endif<|endoftext|>


<commit_before>/*
 *  adcalendar.cpp  -  configuration file access
 *  Program:  KAlarm's alarm daemon (kalarmd)
 *  Copyright (c) 2001, 2004, 2005 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarmd.h"

#include <qregexp.h>
#include <qstringlist.h>

#include <kconfig.h>
#include <kstandarddirs.h>
#include <kdebug.h>

#include "adcalendar.h"
#include "adconfigdata.h"

// Config file key strings
const QString CLIENT_GROUP(QLatin1String("Client "));
const QRegExp CLIENT_GROUP_SEARCH("^Client ");
// Client data file key strings
const QString CALENDAR_KEY(QLatin1String("Calendar"));
const QString TITLE_KEY(QLatin1String("Title"));
const QString DCOP_OBJECT_KEY(QLatin1String("DCOP object"));
const QString START_CLIENT_KEY(QLatin1String("Start"));

/******************************************************************************
* Read the configuration file.
* Create the client list and open all calendar files.
*/
void ADConfigData::readConfig()
{
	kdDebug(5900) << "ADConfigData::readConfig()" << endl;
	ClientInfo::clear();
	KConfig* config = KGlobal::config();
	QStringList clients = config->groupList().filter(CLIENT_GROUP_SEARCH);
	for (QStringList::Iterator cl = clients.begin();  cl != clients.end();  ++cl)
	{
		// Read this client's configuration
		config->setGroup(*cl);
		QString client = *cl;
		client.remove(CLIENT_GROUP_SEARCH);
		QString  title       = config->readEntry(TITLE_KEY, client);   // read app title (default = app name)
		QByteArray dcopObject  = config->readEntry(DCOP_OBJECT_KEY, QString()).toLocal8Bit();
		bool       startClient = config->readEntry(START_CLIENT_KEY, QVariant(false)).toBool();
		QString    calendar    = config->readPathEntry(CALENDAR_KEY);

		// Verify the configuration
		bool ok = false;
		if (client.isEmpty()  ||  KStandardDirs::findExe(client).isNull())
			kdError(5900) << "ADConfigData::readConfig(): group '" << *cl << "' deleted (client app not found)\n";
		else if (calendar.isEmpty())
			kdError(5900) << "ADConfigData::readConfig(): no calendar specified for '" << client << "'\n";
		else if (dcopObject.isEmpty())
			kdError(5900) << "ADConfigData::readConfig(): no DCOP object specified for '" << client << "'\n";
		else
		{
			ADCalendar* cal = ADCalendar::calendar(calendar);
			if (cal)
				kdError(5900) << "ADConfigData::readConfig(): calendar registered by multiple clients: " << calendar << endl;
			else
				ok = true;
		}
		if (!ok)
		{
			config->deleteGroup(*cl, KConfig::NLS);
			continue;
		}

		// Create the client and calendar objects
		new ClientInfo(client.toLocal8Bit(), title, dcopObject, calendar, startClient);
		kdDebug(5900) << "ADConfigData::readConfig(): client " << client << " : calendar " << calendar << endl;
	}

	// Remove obsolete CheckInterval entry (if it exists)
        config->setGroup("General");
	config->deleteEntry("CheckInterval");

	// Save any updates
	config->sync();
}

/******************************************************************************
* Write a client application's details to the config file.
*/
void ADConfigData::writeClient(const QByteArray& appName, const ClientInfo* cinfo)
{
	KConfig* config = KGlobal::config();
	config->setGroup(CLIENT_GROUP + QString::fromLocal8Bit(appName));
	config->writeEntry(TITLE_KEY, cinfo->title());
	config->writeEntry(DCOP_OBJECT_KEY, QString::fromLocal8Bit(cinfo->dcopObject()));
	config->writeEntry(START_CLIENT_KEY, cinfo->startClient());
	config->writePathEntry(CALENDAR_KEY, cinfo->calendar()->urlString());
	config->sync();
}

/******************************************************************************
* Remove a client application's details from the config file.
*/
void ADConfigData::removeClient(const QByteArray& appName)
{
	KConfig* config = KGlobal::config();
	config->deleteGroup(CLIENT_GROUP + QString::fromLocal8Bit(appName));
	config->sync();
}

/******************************************************************************
* Set the calendar file URL for a specified application.
*/
void ADConfigData::setCalendar(const QByteArray& appName, ADCalendar* cal)
{
	KConfig* config = KGlobal::config();
	config->setGroup(CLIENT_GROUP + QString::fromLocal8Bit(appName));
	config->writePathEntry(CALENDAR_KEY, cal->urlString());
        config->sync();
}

/******************************************************************************
* DCOP call to set autostart at login on or off.
*/
void ADConfigData::enableAutoStart(bool on)
{
        kdDebug(5900) << "ADConfigData::enableAutoStart(" << on << ")\n";
        KConfig* config = KGlobal::config();
	config->reparseConfiguration();
        config->setGroup(QLatin1String(DAEMON_AUTOSTART_SECTION));
        config->writeEntry(QLatin1String(DAEMON_AUTOSTART_KEY), on);
        config->sync();
}

<commit_msg>Fix compilation errors<commit_after>/*
 *  adcalendar.cpp  -  configuration file access
 *  Program:  KAlarm's alarm daemon (kalarmd)
 *  Copyright (c) 2001, 2004, 2005 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarmd.h"

#include <qregexp.h>
#include <qstringlist.h>

#include <kconfig.h>
#include <kstandarddirs.h>
#include <kdebug.h>

#include "adcalendar.h"
#include "adconfigdata.h"

// Config file key strings
const QString CLIENT_GROUP(QLatin1String("Client "));
const QRegExp CLIENT_GROUP_SEARCH("^Client ");
// Client data file key strings
const char* CALENDAR_KEY     = "Calendar";
const char* TITLE_KEY        = "Title";
const char* DCOP_OBJECT_KEY  = "DCOP object";
const char* START_CLIENT_KEY = "Start";

/******************************************************************************
* Read the configuration file.
* Create the client list and open all calendar files.
*/
void ADConfigData::readConfig()
{
	kdDebug(5900) << "ADConfigData::readConfig()" << endl;
	ClientInfo::clear();
	KConfig* config = KGlobal::config();
	QStringList clients = config->groupList().filter(CLIENT_GROUP_SEARCH);
	for (QStringList::Iterator cl = clients.begin();  cl != clients.end();  ++cl)
	{
		// Read this client's configuration
		config->setGroup(*cl);
		QString client = *cl;
		client.remove(CLIENT_GROUP_SEARCH);
		QString  title       = config->readEntry(TITLE_KEY, client);   // read app title (default = app name)
		QByteArray dcopObject  = config->readEntry(DCOP_OBJECT_KEY, QString()).toLocal8Bit();
		bool       startClient = config->readEntry(START_CLIENT_KEY, QVariant(false)).toBool();
		QString    calendar    = config->readPathEntry(CALENDAR_KEY);

		// Verify the configuration
		bool ok = false;
		if (client.isEmpty()  ||  KStandardDirs::findExe(client).isNull())
			kdError(5900) << "ADConfigData::readConfig(): group '" << *cl << "' deleted (client app not found)\n";
		else if (calendar.isEmpty())
			kdError(5900) << "ADConfigData::readConfig(): no calendar specified for '" << client << "'\n";
		else if (dcopObject.isEmpty())
			kdError(5900) << "ADConfigData::readConfig(): no DCOP object specified for '" << client << "'\n";
		else
		{
			ADCalendar* cal = ADCalendar::calendar(calendar);
			if (cal)
				kdError(5900) << "ADConfigData::readConfig(): calendar registered by multiple clients: " << calendar << endl;
			else
				ok = true;
		}
		if (!ok)
		{
			config->deleteGroup(*cl, KConfig::NLS);
			continue;
		}

		// Create the client and calendar objects
		new ClientInfo(client.toLocal8Bit(), title, dcopObject, calendar, startClient);
		kdDebug(5900) << "ADConfigData::readConfig(): client " << client << " : calendar " << calendar << endl;
	}

	// Remove obsolete CheckInterval entry (if it exists)
        config->setGroup("General");
	config->deleteEntry("CheckInterval");

	// Save any updates
	config->sync();
}

/******************************************************************************
* Write a client application's details to the config file.
*/
void ADConfigData::writeClient(const QByteArray& appName, const ClientInfo* cinfo)
{
	KConfig* config = KGlobal::config();
	config->setGroup(CLIENT_GROUP + QString::fromLocal8Bit(appName));
	config->writeEntry(TITLE_KEY, cinfo->title());
	config->writeEntry(DCOP_OBJECT_KEY, QString::fromLocal8Bit(cinfo->dcopObject()));
	config->writeEntry(START_CLIENT_KEY, cinfo->startClient());
	config->writePathEntry(CALENDAR_KEY, cinfo->calendar()->urlString());
	config->sync();
}

/******************************************************************************
* Remove a client application's details from the config file.
*/
void ADConfigData::removeClient(const QByteArray& appName)
{
	KConfig* config = KGlobal::config();
	config->deleteGroup(CLIENT_GROUP + QString::fromLocal8Bit(appName));
	config->sync();
}

/******************************************************************************
* Set the calendar file URL for a specified application.
*/
void ADConfigData::setCalendar(const QByteArray& appName, ADCalendar* cal)
{
	KConfig* config = KGlobal::config();
	config->setGroup(CLIENT_GROUP + QString::fromLocal8Bit(appName));
	config->writePathEntry(CALENDAR_KEY, cal->urlString());
        config->sync();
}

/******************************************************************************
* DCOP call to set autostart at login on or off.
*/
void ADConfigData::enableAutoStart(bool on)
{
        kdDebug(5900) << "ADConfigData::enableAutoStart(" << on << ")\n";
        KConfig* config = KGlobal::config();
	config->reparseConfiguration();
        config->setGroup(QLatin1String(DAEMON_AUTOSTART_SECTION));
        config->writeEntry(QLatin1String(DAEMON_AUTOSTART_KEY), on);
        config->sync();
}

<|endoftext|>


<commit_before><commit_msg>Correction in Prefix Function<commit_after><|endoftext|>