Program Listing for File IfcParse.h

Return to documentation for file (src/ifcparse/IfcParse.h)

/********************************************************************************
*                                                                              *
* This file is part of IfcOpenShell.                                           *
*                                                                              *
* IfcOpenShell is free software: you can redistribute it and/or modify         *
* it under the terms of the Lesser GNU General Public License as published by  *
* the Free Software Foundation, either version 3.0 of the License, or          *
* (at your option) any later version.                                          *
*                                                                              *
* IfcOpenShell 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                 *
* Lesser GNU General Public License for more details.                          *
*                                                                              *
* You should have received a copy of the Lesser GNU General Public License     *
* along with this program. If not, see <http://www.gnu.org/licenses/>.         *
*                                                                              *
********************************************************************************/

/********************************************************************************
 *                                                                              *
 * This file provides functions for loading an IFC file into memory and access  *
 * its entities either by ID, by an IfcSchema::Type or by reference             *
 *                                                                              *
 ********************************************************************************/

#ifndef IFCPARSE_H
#define IFCPARSE_H

#define IFCOPENSHELL_VERSION "0.6.0b0"

#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <fstream>
#include <cstring>
#include <map>

#include <boost/shared_ptr.hpp>
#include <boost/dynamic_bitset.hpp>

#include "ifc_parse_api.h"

#include "../ifcparse/IfcCharacterDecoder.h"
#include "../ifcparse/IfcBaseClass.h"
#include "../ifcparse/IfcLogger.h"
#include "../ifcparse/Argument.h"

#include "../ifcparse/IfcSpfStream.h"

#if defined(__clang__)
# define my_thread_local thread_local
#elif defined(__GNUC__)
# define my_thread_local __thread
#elif __STDC_VERSION__ >= 201112L
# define my_thread_local _Thread_local
#elif defined(_MSC_VER)
# define my_thread_local __declspec(thread)
#else
# error Cannot define thread_local
#endif

namespace IfcParse {

    class IfcFile;
    class IfcSpfLexer;

    enum TokenType {
        Token_NONE,
        Token_STRING,
        Token_IDENTIFIER,
        Token_OPERATOR,
        Token_ENUMERATION,
        Token_KEYWORD,
        Token_INT,
        Token_BOOL,
        Token_FLOAT,
        Token_BINARY
    };

    struct Token {
        IfcSpfLexer* lexer; //TODO: remove it from here
        unsigned startPos;
        TokenType type;
        union {
            bool value_bool;      //types: BOOL
            char value_char;      //types: OPERATOR
            int value_int;        //types: INT, IDENTIFIER
            double value_double;  //types: FLOAT
        };

        Token() : lexer(0), startPos(0), type(Token_NONE) {}
        Token(IfcSpfLexer* _lexer, unsigned _startPos, unsigned /*_endPos*/, TokenType _type)
            : lexer(_lexer), startPos(_startPos), type(_type) {}
    };

    class IFC_PARSE_API TokenFunc {
    private:
        static bool startsWith(const Token& t, char c);
    public:
        // static unsigned int Offset(const Token& t);
        static bool isString(const Token& t);
        static bool isIdentifier(const Token& t);
        static bool isOperator(const Token& t);
        static bool isOperator(const Token& t, char op);
        static bool isEnumeration(const Token& t);
        static bool isKeyword(const Token& t);
        static bool isInt(const Token& t);
        static bool isBool(const Token& t);
        static bool isFloat(const Token& t);
        static bool isBinary(const Token& t);
        static int asInt(const Token& t);
        static int asIdentifier(const Token& t);
        static bool asBool(const Token& t);
        static double asFloat(const Token& t);
        static std::string asString(const Token& t);
        static const std::string &asStringRef(const Token& t);
        static boost::dynamic_bitset<> asBinary(const Token& t);
        static std::string toString(const Token& t);
    };

    //
    // Functions for creating Tokens from an arbitary file offset
    // The first 4 bits are reserved for Tokens of type ()=,;$*
    //
    Token OperatorTokenPtr(IfcSpfLexer* tokens, unsigned start, unsigned end);
    Token GeneralTokenPtr(IfcSpfLexer* tokens, unsigned start, unsigned end);
    Token NoneTokenPtr();

    class IFC_PARSE_API IfcSpfLexer {
    private:
        IfcCharacterDecoder* decoder;
        unsigned int skipWhitespace();
        unsigned int skipComment();
    public:
        std::string &GetTempString() const {
            static my_thread_local std::string s;
            return s;
        }
        IfcSpfStream* stream;
        IfcFile* file;
        IfcSpfLexer(IfcSpfStream* s, IfcFile* f);
        Token Next();
        ~IfcSpfLexer();
        void TokenString(unsigned int offset, std::string &result);
    };

    class IFC_PARSE_API ArgumentList: public Argument {
    private:
        size_t size_;
        Argument** list_;

    public:
        ArgumentList() : size_(0), list_(0) {}
        ArgumentList(size_t n) : size_(n), list_(new Argument*[size_]) {}
        ~ArgumentList();

        void read(IfcSpfLexer* t, std::vector<unsigned int>& ids);

        IfcUtil::ArgumentType type() const;

        operator std::vector<int>() const;
        operator std::vector<double>() const;
        operator std::vector<std::string>() const;
        operator std::vector<boost::dynamic_bitset<> >() const;
        operator IfcEntityList::ptr() const;

        operator std::vector< std::vector<int> >() const;
        operator std::vector< std::vector<double> >() const;
        operator IfcEntityListList::ptr() const;

        bool isNull() const;
        unsigned int size() const;

        Argument* operator [] (unsigned int i) const;

        std::string toString(bool upper=false) const;

        Argument**& arguments() { return list_; }
        size_t& size() { return size_; }
    };


    class IFC_PARSE_API NullArgument : public Argument {
    public:
        NullArgument() {}
        IfcUtil::ArgumentType type() const { return IfcUtil::Argument_NULL; }
        bool isNull() const { return true; }
        unsigned int size() const { return 1; }
        Argument* operator [] (unsigned int /*i*/) const { throw IfcException("Argument is not a list of attributes"); }
        std::string toString(bool /*upper=false*/) const { return "$"; }
    };

    class IFC_PARSE_API TokenArgument : public Argument {
    private:

    public:
        Token token;
        TokenArgument(const Token& t);

        IfcUtil::ArgumentType type() const;

        operator int() const;
        operator bool() const;
        operator double() const;
        operator std::string() const;
        operator boost::dynamic_bitset<>() const;
        operator IfcUtil::IfcBaseClass*() const;

        bool isNull() const;
        unsigned int size() const;

        Argument* operator [] (unsigned int i) const;
        std::string toString(bool upper=false) const;
    };

    class IFC_PARSE_API EntityArgument : public Argument {
    private:
        IfcUtil::IfcBaseClass* entity;
    public:
        EntityArgument(const Token& t);
        ~EntityArgument();

        IfcUtil::ArgumentType type() const;

        operator IfcUtil::IfcBaseClass*() const;

        bool isNull() const;
        unsigned int size() const;

        Argument* operator [] (unsigned int i) const;
        std::string toString(bool upper=false) const;
    };

    IFC_PARSE_API IfcEntityInstanceData* read(unsigned int i, IfcFile* t, boost::optional<unsigned> offset = boost::none);

    IFC_PARSE_API IfcEntityList::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level = -1);
}

IFC_PARSE_API std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f);

#endif