Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • release/202005
  • release/202001
  • release/201912
  • release/201911
  • release/releaseWindowsTestOne
  • release/windowsReleaseTest
  • release/releaseTest
  • release/releaseWindowsTest
  • release/201910
  • release/qt/201910
  • release/windows-test/201910
  • release/201908
  • release/201906
  • release/201905
  • release/201904
  • release/201903
  • release/201902
  • release/201901
  • release/201812
  • 4.0.0
  • 2.2.0
  • 2.1.0
  • 2.0.1
  • 2.0.0
  • 1.4.1
  • 1.4.0
  • 1.3.0
  • 1.2.0
  • 1.1.0
30 results

yamlparser.cpp

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    yamlparser.cpp 14.43 KiB
    /*
     *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
     *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
     *
     *  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 3 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., 675 Mass Ave, Cambridge, MA 02139, USA.
     *
     *  Additional permission under GNU GPL version 3 section 7:
     *
     *  If you modify this program, or any covered work, by linking or
     *  combining it with the OpenSSL project's OpenSSL library (or a
     *  modified version of that library), containing parts covered by the
     *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
     *  grants you additional permission to convey the resulting work.
     *  Corresponding Source for a non-source form of such a combination
     *  shall include the source code for the parts of OpenSSL used as well
     *  as that of the covered work.
     */
    
    #include "yamlparser.h"
    
    #include "../global.h"
    #include "config.h"
    #include "yamlnode.h"
    #include <stdio.h>
    
    namespace Conf
    {
    
    YamlParser::YamlParser (const char *file) : filename (file)
        , accountSequence (NULL)
        , preferenceSequence (NULL)
        , addressbookSequence (NULL)
        , audioSequence (NULL)
        , hooksSequence (NULL)
        , voiplinkSequence (NULL)
        , shortcutSequence (NULL)
    {
        memset (buffer, 0, PARSER_BUFFERSIZE);
    
        open();
    }
    
    YamlParser::~YamlParser()
    {
        close();
    }
    
    void YamlParser::open()
    {
    
        fd = fopen (filename.c_str(), "rb");
    
        if (!fd)
            throw YamlParserException ("Could not open file descriptor");
    
        if (!yaml_parser_initialize (&parser))
            throw YamlParserException ("Could not open file descriptor");
    
        yaml_parser_set_input_file (&parser, fd);
    }
    
    void YamlParser::close()
    {
        if (!fd)
            throw YamlParserException ("File descriptor not valid");
    
        // fclose (fd);
        if (fclose (fd))
            throw YamlParserException ("Error closing file descriptor");
    
        yaml_parser_delete (&parser);
    
        if (doc) {
            doc->deleteChildNodes();
            delete doc;
            doc = NULL;
        }
    }
    
    void YamlParser::serializeEvents()
    {
        bool done = false;
        yaml_event_t event;
    
        while (!done) {
    
            if (!yaml_parser_parse (&parser, &event))
                throw YamlParserException ("Error while parsing");
    
            done = (event.type == YAML_STREAM_END_EVENT);
    
            if (eventNumber > PARSER_MAXEVENT)
                throw YamlParserException ("Reached maximum of event");
    
            if (!copyEvent (& (events[eventNumber++]), &event))
                throw YamlParserException ("Error copying event");
    
        }
    }
    
    
    int YamlParser::copyEvent (yaml_event_t *event_to, yaml_event_t *event_from)
    {
    
        switch (event_from->type) {
            case YAML_STREAM_START_EVENT: {
                // _debug("YAML_STREAM_START_EVENT");
                return yaml_stream_start_event_initialize (event_to,
                        event_from->data.stream_start.encoding);
            }
    
            case YAML_STREAM_END_EVENT: {
                //_debug("YAML_STREAM_END_EVENT");
                return yaml_stream_end_event_initialize (event_to);
            }
    
            case YAML_DOCUMENT_START_EVENT: {
                // _debug("YAML_DOCUMENT_START_EVENT");
                return yaml_document_start_event_initialize (event_to,
                        event_from->data.document_start.version_directive,
                        event_from->data.document_start.tag_directives.start,
                        event_from->data.document_start.tag_directives.end,
                        event_from->data.document_start.implicit);
            }
    
            case YAML_DOCUMENT_END_EVENT: {
                // _debug("YAML_DOCUMENT_END_EVENT");
                return yaml_document_end_event_initialize (event_to,
                        event_from->data.document_end.implicit);
            }
            case YAML_ALIAS_EVENT: {
                // _debug("YAML_ALIAS_EVENT");
                return yaml_alias_event_initialize (event_to,
                                                    event_from->data.alias.anchor);
            }
            case YAML_SCALAR_EVENT: {
                // _debug("YAML_SCALAR_EVENT");
                return yaml_scalar_event_initialize (event_to,
                                                     event_from->data.scalar.anchor,
                                                     event_from->data.scalar.tag,
                                                     event_from->data.scalar.value,
                                                     event_from->data.scalar.length,
                                                     event_from->data.scalar.plain_implicit,
                                                     event_from->data.scalar.quoted_implicit,
                                                     event_from->data.scalar.style);
            }
            case YAML_SEQUENCE_START_EVENT: {
                // _debug("YAML_SEQUENCE_START_EVENT");
                return yaml_sequence_start_event_initialize (event_to,
                        event_from->data.sequence_start.anchor,
                        event_from->data.sequence_start.tag,
                        event_from->data.sequence_start.implicit,
                        event_from->data.sequence_start.style);
            }
            case YAML_SEQUENCE_END_EVENT: {
                // _debug("YAML_SEQUENCE_END_EVENT");
                return yaml_sequence_end_event_initialize (event_to);
            }
            case YAML_MAPPING_START_EVENT: {
                // _debug("YAML_MAPPING_START_EVENT");
                return yaml_mapping_start_event_initialize (event_to,
                        event_from->data.mapping_start.anchor,
                        event_from->data.mapping_start.tag,
                        event_from->data.mapping_start.implicit,
                        event_from->data.mapping_start.style);
            }
            case YAML_MAPPING_END_EVENT: {
                // _debug("YAML_MAPPING_END_EVENT");
                return yaml_mapping_end_event_initialize (event_to);
    
            }
            default:
                assert (1);
    
        }
    
        return 0;
    }
    
    
    YamlDocument *YamlParser::composeEvents()
    {
    
        // _debug("YamlParser: Compose Events");
    
        if (eventNumber == 0)
            throw YamlParserException ("No event available");
    
        if (events[0].type != YAML_STREAM_START_EVENT)
            throw YamlParserException ("Parsing does not start with stream start");
    
        eventIndex = 0;
    
        processStream();
    
        return doc;
    }
    
    void YamlParser::processStream ()
    {
    
        // _debug("YamlParser: process stream");
    
        while ( (eventIndex < eventNumber) && (events[eventIndex].type != YAML_STREAM_END_EVENT)) {
    
            if (events[eventIndex].type == YAML_DOCUMENT_START_EVENT)
                processDocument();
    
            eventIndex++;
        }
    
        if (events[eventIndex].type != YAML_STREAM_END_EVENT)
            throw YamlParserException ("Did not found end of stream");
    }
    
    
    void YamlParser::processDocument()
    {
        // _debug("YamlParser: process document");
    
        doc = new YamlDocument();
    
        if (!doc)
            throw YamlParserException ("Not able to create new document");
    
        while ( (eventIndex < eventNumber) && (events[eventIndex].type != YAML_DOCUMENT_END_EVENT)) {
    
            switch (events[eventIndex].type) {
                case YAML_SCALAR_EVENT:
                    processScalar ( (YamlNode *) doc);
                    break;
                case YAML_SEQUENCE_START_EVENT:
                    processSequence ( (YamlNode *) doc);
                    break;
                case YAML_MAPPING_START_EVENT:
                    processMapping ( (YamlNode *) doc);
                    break;
                default:
                    break;
            }
    
            eventIndex++;
        }
    
        if (events[eventIndex].type != YAML_DOCUMENT_END_EVENT)
            throw YamlParserException ("Did not found end of document");
    
    }
    
    
    void YamlParser::processScalar (YamlNode *topNode)
    {
    
        // _debug("YamlParser: process scalar");
    
        if (!topNode)
            throw YamlParserException ("No container for scalar");
    
        char buffer[1000];
        snprintf (buffer, 1000, "%s", events[eventIndex].data.scalar.value);
        // _debug("and the scalar is: %s", buffer);
    
        ScalarNode *sclr = new ScalarNode (buffer, topNode);
    
        switch (topNode->getType()) {
            case DOCUMENT:
                ( (YamlDocument *) (topNode))->addNode (sclr);
                break;
            case SEQUENCE:
                ( (SequenceNode *) (topNode))->addNode (sclr);
                break;
            case MAPPING:
                ( (MappingNode *) (topNode))->addNode (sclr);
            case SCALAR:
            default:
                break;
        }
    }
    
    
    void YamlParser::processSequence (YamlNode *topNode)
    {
        _debug ("YamlParser: process sequence");
    
        if (!topNode)
            throw YamlParserException ("No container for sequence");
    
        SequenceNode *seq = new SequenceNode (topNode);
    
        switch (topNode->getType()) {
            case DOCUMENT:
                ( (YamlDocument *) (topNode))->addNode (seq);
                break;
            case SEQUENCE:
                ( (SequenceNode *) (topNode))->addNode (seq);
                break;
            case MAPPING:
                ( (MappingNode *) (topNode))->addNode (seq);
            case SCALAR:
            default:
                break;
        }
    
        eventIndex++;
    
        while ( (eventIndex < eventNumber) && (events[eventIndex].type != YAML_SEQUENCE_END_EVENT)) {
    
            switch (events[eventIndex].type) {
                case YAML_SCALAR_EVENT:
                    processScalar (seq);
                    break;
                case YAML_SEQUENCE_START_EVENT:
                    processSequence (seq);
                    break;
                case YAML_MAPPING_START_EVENT:
                    processMapping (seq);
                    break;
                default:
                    break;
            }
    
            eventIndex++;
        }
    
        if (events[eventIndex].type != YAML_SEQUENCE_END_EVENT)
            throw YamlParserException ("Did not found end of sequence");
    }
    
    
    void YamlParser::processMapping (YamlNode *topNode)
    {
        // _debug("YamlParser: process mapping");
    
        if (!topNode)
            throw YamlParserException ("No container for mapping");
    
        MappingNode *map = new MappingNode (topNode);
    
        switch (topNode->getType()) {
            case DOCUMENT:
                ( (YamlDocument *) (topNode))->addNode (map);
                break;
            case SEQUENCE:
                ( (SequenceNode *) (topNode))->addNode (map);
                break;
            case MAPPING:
                ( (MappingNode *) (topNode))->addNode (map);
            case SCALAR:
            default:
                break;
        }
    
        eventIndex++;
    
        while ( (eventIndex < eventNumber) && (events[eventIndex].type != YAML_MAPPING_END_EVENT)) {
    
            if (events[eventIndex].type != YAML_SCALAR_EVENT)
                throw YamlParserException ("Mapping not followed by a key");
    
            char buffer[1000];
            snprintf (buffer, 1000, "%s", events[eventIndex].data.scalar.value);
            map->setTmpKey (Key (buffer));
            // _debug("KEY %s", buffer);
    
            eventIndex++;
    
            switch (events[eventIndex].type) {
                case YAML_SCALAR_EVENT:
                    processScalar (map);
                    break;
                case YAML_SEQUENCE_START_EVENT:
                    processSequence (map);
                    break;
                case YAML_MAPPING_START_EVENT:
                    processMapping (map);
                    break;
                default:
                    break;
            }
    
            eventIndex++;
        }
    
        if (events[eventIndex].type != YAML_MAPPING_END_EVENT)
            throw YamlParserException ("Did not found end of mapping");
    }
    
    void YamlParser::constructNativeData()
    {
    
        Sequence *seq;
    
        seq = doc->getSequence();
    
        Sequence::iterator iter = seq->begin();
    
        while (iter != seq->end()) {
    
            switch ( (*iter)->getType()) {
                case SCALAR:
                    // _debug("construct scalar");
                    throw YamlParserException ("No scalar allowed at document level, expect a mapping");
                    break;
                case SEQUENCE:
                    // _debug("construct sequence");
                    throw YamlParserException ("No sequence allowed at document level, expect a mapping");
                    break;
                case MAPPING: {
                    // _debug("construct mapping");
                    MappingNode *map = (MappingNode *) (*iter);
                    mainNativeDataMapping (map);
                    break;
                }
                default:
                    throw YamlParserException ("Unknown type in configuration file, expect a mapping");
                    break;
            }
    
            iter++;
    
        }
    
    }
    
    
    void YamlParser::mainNativeDataMapping (MappingNode *map)
    {
    
    
        Mapping::iterator iter = map->getMapping()->begin();
    
        Key accounts ("accounts");
        Key addressbook ("addressbook");
        Key audio ("audio");
        Key hooks ("hooks");
        Key preferences ("preferences");
        Key voiplink ("voipPreferences");
        Key shortcuts ("shortcuts");
    
        while (iter != map->getMapping()->end()) {
    
            _debug ("Iterating: %s", iter->first.c_str());
    
            if (accounts.compare (iter->first) == 0) {
                _debug ("YamlParser: Adding voip account preferences");
                accountSequence = (SequenceNode *) (iter->second);
            } else if (addressbook.compare (iter->first) == 0) {
                _debug ("YamlParser: Adding addressbook preference");
                addressbookSequence = (SequenceNode *) (iter->second);
            } else if (audio.compare (iter->first) == 0) {
                _debug ("YamlParser: Adding audio preference");
                audioSequence = (SequenceNode *) (iter->second);
            } else if (hooks.compare (iter->first) == 0) {
                _debug ("YamlParser: Adding hooks preference");
                hooksSequence = (SequenceNode *) (iter->second);
            } else if (preferences.compare (iter->first) == 0) {
                _debug ("YamlParser: Adding preference preference");
                preferenceSequence = (SequenceNode *) (iter->second);
            } else if (voiplink.compare (iter->first) == 0) {
                _debug ("YamlParser: Adding voip preference");
                voiplinkSequence = (SequenceNode *) (iter->second);
            } else if (shortcuts.compare (iter->first) == 0) {
                _debug ("YamlParser: Adding shortcut preference");
                shortcutSequence = (SequenceNode *) (iter->second);
            } else
                throw YamlParserException ("Unknow map key in configuration");
    
            iter++;
        }
    
        // _debug("Done");
    }
    
    }