Logo Search packages:      
Sourcecode: cb2bib version File versions

coreBibParser.h

/***************************************************************************
 *   Copyright (C) 2004-2009 by Pere Constans
 *   constans@molspaces.com
 *   cb2Bib version 1.3.0. Licensed under the GNU GPL version 3.
 *   See the LICENSE file that comes with this distribution.
 ***************************************************************************/
#ifndef COREBIBPARSER_H
#define COREBIBPARSER_H

#include "authorString.h"
#include "bibReference.h"
#include "cb2bib_utilities.h"
#include "settings.h"

#include <QDir>
#include <QObject>


/**
    Class for bibliographic reference parsing

    @author Pere Constans
*/
00024 class coreBibParser : public QObject
{

    Q_OBJECT

public:
    coreBibParser(QObject* parento = 0);
    virtual ~coreBibParser();

    QString referenceToBibTeX(const bibReference& ref) const;
    QString referenceToFomattedBibTeX(const bibReference& ref) const;
    bibReference wholeReference(const QString& str);
    void initReferenceParsing(const QString& dir, const QStringList& fields, bibReference* ref);

    inline const QStringList& bibliographicFields() const
    {
        return _bibliographic_fields;
    }
    inline const QStringList& sortedBibliographicFields() const
    {
        return _sorted_bibliographic_fields;
    }
    inline const QStringList& bibliographicTypes() const
    {
        return _bibliographic_types;
    }
    inline void setReferenceParsingDir(const QString& dir)
    {
        // Set base dir for cases of relative 'file'
        // Terminate dirname with separator to avoid adding it to each reference
        _bib_file_dir = QDir::toNativeSeparators(QFileInfo(dir).absolutePath() + QDir::separator());
    }
    inline bool hasBibTeX(const QString& str) const
    {
        if (_bib_begin0_re.indexIn(str) > -1)
            return true;
        else
            return _bib_begin1_re.indexIn(str) > -1;
    }
    inline bool referencesIn(const QString& str, bibReference* ref)
    {
        // File parsing for given fields in ref
        ref->clearReference();
        int pos = referenceStarts(str, ref->pos);
        if (pos < 0)
            return false;
        referenceContents(str, ref, pos);
        return true;
    }
    inline bool referenceAtKey(const QString& key, const QString& str, bibReference* ref)
    {
        // File parsing for given fields in ref
        ref->clearReference();
        int pos = referenceStarts(key, str);
        if (pos < 0)
            return false;
        referenceContents(str, ref, pos);
        return true;
    }
    inline int fieldCount(const bibReference& ref) const
    {
        // Counting Non Empty Fields
        int n = 0;
        bibReferenceIterator i;
        for (i = ref.constBegin(); i != ref.constEnd(); ++i)
            if (!i.value().isEmpty())
                ++n;
        return n;
    }
    inline QString& authorFromBibTeX(QString& as)
    {
        // Avoid BibTeX reverse names
        if (as.contains(','))
            as = _authorString.toBibTeX(as, _settingsP->value("cb2Bib/UseFullNames").toBool());
        return as;
    }


protected:
    QRegExp _field_re;
    QString adjacentNumbers(const QString& numbers) const;
    QStringList _bibliographic_fields;
    QStringList _bibliographic_types;
    QStringList _sorted_bibliographic_fields;
    authorString _authorString;
    settings* _settingsP;


private:
    QList<QRegExp> _bib_fields_nb_re;
    QList<QRegExp> _bib_fields_re;
    QRegExp _bib_begin0_re;
    QRegExp _bib_begin1_re;
    QRegExp _bib_begin_re;
    QRegExp _bib_key_re;
    QRegExp _bib_type_re;
    QString _bib_file_dir;
    void setFields();
    void setRegularExpressions();
    void setTypes();

    inline int referenceStarts(const QString& str, int pos = 0) const
    {
        int i;
        if (pos == 0)
        {
            i = _bib_begin0_re.indexIn(str);
            if (i < 0)
                i = _bib_begin1_re.indexIn(str, pos);
        }
        else
            i = _bib_begin1_re.indexIn(str, pos);
        if (i < 0)
            return i;
        return _bib_begin_re.indexIn(str, i);
    }

    inline int referenceStarts(const QString& key, const QString& str) const
    {
        if (!str.contains(key))
            return -1;
        int i = str.indexOf(QRegExp("^\\s*@\\w+\\s*\\{" + key + ","));
        if (i < 0)
            i = str.indexOf(QRegExp("[\\r\\n]\\s*@\\w+\\s*\\{" + key + ","));
        if (i < 0)
            return i;
        return str.indexOf(QRegExp("@\\w+\\s*\\{" + key + ","), i);
    }

    inline int referenceEnds(const QString& str, int pos = 0) const
    {
        // If referenceStarts call is successful, we know for sure
        // that there is an opening { right after pos.
        // Do not check again here.
        // Checking for brace closure is the safest way for parsing.
        // It will fail, though, for references incorrectly written.
        // Avoid overextending in these cases by checking the
        // start of the next reference.
        int ref_length = referenceStarts(str, pos + 2) - 1;
        if (ref_length < 0)
            ref_length = str.length();
        const int brace_pos = str.indexOf('{', pos);
        int open_braces = 1;
        for (int i = brace_pos + 1; i < ref_length; ++i)
        {
            const QChar& si = str[i];
            if (si == '{')
                open_braces++;
            else if (si == '}')
                open_braces--;
            if (open_braces == 0)
                return i;
        }
        return ref_length - 1;
    }

    inline QString referenceAt(const QString& str, int* pos) const
    {
        // String str contains one or multiple references (file contents)
        const int _pos = referenceEnds(str, *pos) + 1;
        const QString str_ref = str.mid(*pos, _pos - (*pos));
        *pos = _pos;
        return str_ref;
    }

    inline void referenceContents(const QString& str, bibReference* ref, int pos)
    {
        // File parsing for given fields in ref
        ref->positionValue = pos;
        QString str_ref = referenceAt(str, &pos);
        ref->pos = pos;
        ref->rawReference = str_ref;
        c2bUtils::bibToC2b(str_ref);
        str_ref = str_ref.simplified();
        ref->unicodeReference = str_ref;
        _bib_key_re.indexIn(str_ref);
        ref->citeidName = _bib_key_re.cap(1);
        _bib_type_re.indexIn(str_ref);
        ref->typeName = _bib_type_re.cap(1).toLower();
        str_ref.replace(str_ref.length() - 1, 1, ",}");
        QString fvalue;
        for (int i = 0; i < ref->_bib_fields_re.count(); ++i)
        {
            QRegExp* bf = &ref->_bib_fields_re[i];
            pos = bf->indexIn(str_ref);
            if (pos > 0)
            {
                if (c2bUtils::inBraces(pos + bf->matchedLength(), str_ref, &fvalue))
                    (*ref)[ref->bib_fieldList.at(i)] = fvalue.trimmed();
            }
            else
            {
                bf = &ref->_bib_fields_nb_re[i];
                if (bf->indexIn(str_ref) > -1)
                    (*ref)[ref->bib_fieldList.at(i)] = bf->cap(1).trimmed();
            }
        }
        if (ref->contains("file"))
            if (!QDir::isAbsolutePath(ref->value("file")))
                (*ref)["file"] = _bib_file_dir + ref->value("file");
    }

};

#endif

Generated by  Doxygen 1.6.0   Back to index