<commit_before>#include "parser.hpp"

#include <iostream>
#include <sstream>

#include <tuple>
#include <map>

#include "error.hpp"

std::tuple<int64_t, bool> get_int(std::stringstream &ss, const std::string &sn, const int &ln) {
	int64_t integer_token;
	ss >> integer_token;
	if (ss.fail()) {
		std::cerr << Error() << "Invalid integer literal in " << sn << '.' << ln << std::endl;
		return std::make_tuple(0, true);
	}
	return std::make_tuple(integer_token, false);
}

std::tuple<int64_t, bool> get_reg(std::stringstream &ss, const std::string &sn, const int &ln) {
	// @TODO Check if integer value is actually valid
	int64_t integer_token;
	ss >> integer_token;
	if (ss.fail()) {
		std::cerr << Error() << "Invalid register literal in " << sn << '.' << ln << std::endl;
		return std::make_tuple(0, true);
	}
	return std::make_tuple(integer_token, false);
}

bool check_empty(std::stringstream &ss, const std::string &sn, const int &ln)
{
	std::string token;
	if (ss >> token) {
		// Allow comments
		if (token[0] == ';')
			return false;

		std::cerr << Error() << "Expected newline but found '" << token << "' in " <<
			sn << '.' << ln << std::endl;
		return true;
	}
	return false;
}

Code parse(std::ifstream& src, std::string& src_name)
{
	// Rely that src is opened and at the proper point

	Code code;
	int line_num = 0;
	std::string line;

	std::map<std::string, int64_t> label_dict;
	std::map<int64_t, std::string> label_refs;

	while (std::getline(src, line)) {
		line_num++;

		if (line.empty())
			continue;

		std::stringstream line_stream(line);

		std::string token;
		line_stream >> token;

		// Check if line is a comment
		if (token[0] == ';')
			continue;

		// Check if line is a label
		if (token[0] == '@') {
			// @TODO Check if label is already defined and don't allow
			// substitutions.
			label_dict[token] = code.curr_index;
			continue;
		}

		if (token == "halt") {
			code.push_op(op::halt);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "noop") {
			code.push_op(op::noop);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "add") {
			code.push_op(op::add);

			auto tmp1 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			auto tmp2 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp2))
				return Code();
			code.push_int(std::get<0>(tmp2));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "cil") {
			code.push_op(op::cil);

			auto tmp1 = get_int(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			auto tmp2 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp2))
				return Code();
			code.push_int(std::get<0>(tmp2));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "ofv") {
			code.push_op(op::ofv);

			auto tmp1 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "onl") {
			code.push_op(op::onl);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jmp") {
			code.push_op(op::jmp);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jgt") {
			code.push_op(op::jgt);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jeq") {
			code.push_op(op::jeq);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jlt") {
			code.push_op(op::jlt);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else {
			std::cerr << Error() << "Unkown instruction '" << token << "' in " <<
				src_name << '.' << line_num << std::endl;
			return Code();
		}
	}

	// Push a halt at the end
	code.push_op(op::halt);

	for (auto &ref : label_refs) {
		const auto index_to_change = ref.first;
		const auto referenced_label = ref.second;
		const auto find_result = label_dict.find(referenced_label);
		if (find_result == label_dict.end()) {
			// @TODO Add information about where this label was used
			std::cerr << Error() << "Unknown label " << referenced_label << std::endl;
			return Code();
		}
		const auto referenced_index = find_result->second;
		code.change(index_to_change, var(referenced_index));
	}

	return code;
}
<commit_msg>Support parsing floats<commit_after>#include "parser.hpp"

#include <iostream>
#include <sstream>

#include <tuple>
#include <map>

#include "error.hpp"

std::tuple<int64_t, bool> get_int(std::stringstream &ss, const std::string &sn, const int &ln) {
	int64_t integer_token;
	ss >> integer_token;
	if (ss.fail()) {
		std::cerr << Error() << "Invalid integer literal in " << sn << '.' << ln << std::endl;
		return std::make_tuple(0, true);
	}
	return std::make_tuple(integer_token, false);
}

std::tuple<int64_t, bool> get_reg(std::stringstream &ss, const std::string &sn, const int &ln) {
	// @TODO Check if integer value is actually valid
	int64_t integer_token;
	ss >> integer_token;
	if (ss.fail()) {
		std::cerr << Error() << "Invalid register literal in " << sn << '.' << ln << std::endl;
		return std::make_tuple(0, true);
	}
	return std::make_tuple(integer_token, false);
}

std::tuple<double, bool> get_float(std::stringstream &ss, const std::string &sn, const int &ln) {
	double float_token;
	ss >> float_token;
	if (ss.fail()) {
		std::cerr << Error() << "Invalid register literal in " << sn << '.' << ln << std::endl;
		return std::make_tuple(0., true);
	}
	return std::make_tuple(float_token, false);
}

bool check_empty(std::stringstream &ss, const std::string &sn, const int &ln)
{
	std::string token;
	if (ss >> token) {
		// Allow comments
		if (token[0] == ';')
			return false;

		std::cerr << Error() << "Expected newline but found '" << token << "' in " <<
			sn << '.' << ln << std::endl;
		return true;
	}
	return false;
}

Code parse(std::ifstream& src, std::string& src_name)
{
	// Rely that src is opened and at the proper point

	Code code;
	int line_num = 0;
	std::string line;

	std::map<std::string, int64_t> label_dict;
	std::map<int64_t, std::string> label_refs;

	while (std::getline(src, line)) {
		line_num++;

		if (line.empty())
			continue;

		std::stringstream line_stream(line);

		std::string token;
		line_stream >> token;

		// Check if line is a comment
		if (token[0] == ';')
			continue;

		// Check if line is a label
		if (token[0] == '@') {
			// @TODO Check if label is already defined and don't allow
			// substitutions.
			label_dict[token] = code.curr_index;
			continue;
		}

		if (token == "halt") {
			code.push_op(op::halt);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "noop") {
			code.push_op(op::noop);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "add") {
			code.push_op(op::add);

			auto tmp1 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			auto tmp2 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp2))
				return Code();
			code.push_int(std::get<0>(tmp2));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "cil") {
			code.push_op(op::cil);

			auto tmp1 = get_int(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			auto tmp2 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp2))
				return Code();
			code.push_int(std::get<0>(tmp2));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "cfl") {
			code.push_op(op::cfl);

			auto tmp1 = get_float(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			auto tmp2 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp2))
				return Code();
			code.push_int(std::get<0>(tmp2));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "ofv") {
			code.push_op(op::ofv);

			auto tmp1 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "onl") {
			code.push_op(op::onl);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jmp") {
			code.push_op(op::jmp);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jgt") {
			code.push_op(op::jgt);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jeq") {
			code.push_op(op::jeq);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jlt") {
			code.push_op(op::jlt);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else {
			std::cerr << Error() << "Unkown instruction '" << token << "' in " <<
				src_name << '.' << line_num << std::endl;
			return Code();
		}
	}

	// Push a halt at the end
	code.push_op(op::halt);

	for (auto &ref : label_refs) {
		const auto index_to_change = ref.first;
		const auto referenced_label = ref.second;
		const auto find_result = label_dict.find(referenced_label);
		if (find_result == label_dict.end()) {
			// @TODO Add information about where this label was used
			std::cerr << Error() << "Unknown label " << referenced_label << std::endl;
			return Code();
		}
		const auto referenced_index = find_result->second;
		code.change(index_to_change, var(referenced_index));
	}

	return code;
}
<|endoftext|>


<commit_before>/* This file is part of the Nepomuk query parser
   Copyright (c) 2013 Denis Steckelmacher <steckdenis@yahoo.fr>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2.1 as published by the Free Software Foundation,
   or any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "parser.h"

#include "pass_splitunits.h"
#include "pass_numbers.h"
#include "pass_filesize.h"
#include "pass_typehints.h"
#include "pass_properties.h"
#include "pass_comparators.h"

#include <nepomuk2/andterm.h>
#include <nepomuk2/orterm.h>
#include <nepomuk2/literalterm.h>
#include <nepomuk2/property.h>
#include <nepomuk2/nfo.h>
#include <nepomuk2/nmo.h>
#include <soprano/literalvalue.h>
#include <soprano/nao.h>
#include <klocalizedstring.h>

#include <QList>
#include <QRegExp>
#include <QtDebug>

struct Parser::Private
{
    QStringList split(const QString &query, bool split_separators);

    template<typename T>
    bool runPass(const T &pass, const QString &pattern, int match_count);
    bool match(const Nepomuk2::Query::Term &term, const QString &pattern, int &index);
    Nepomuk2::Query::Term fuseTerms(int first_term_index, int &end_term_index) const;

    // Terms on which the parser works
    QList<Nepomuk2::Query::Term> terms;

    // Parsing passes (they cache translations, queries, etc)
    PassSplitUnits pass_splitunits;
    PassNumbers pass_numbers;
    PassFileSize pass_filesize;
    PassTypeHints pass_typehints;
    PassComparators pass_comparators;
    PassProperties pass_properties;
};

Parser::Parser()
: d(new Private)
{
}

Parser::Parser(const Parser &other)
: d(new Private(*other.d))
{
}

Parser::~Parser()
{
    delete d;
}

void Parser::reset()
{
    d->terms.clear();
}

Nepomuk2::Query::Query Parser::parse(const QString &query)
{
    reset();

    // Split the query into terms
    QStringList parts = d->split(query, true);

    Q_FOREACH(const QString &part, parts) {
        d->terms.append(Nepomuk2::Query::LiteralTerm(part));
    }

    // Parse passes
    bool progress = true;

    while (progress) {
        progress = false;

        progress |= d->runPass(d->pass_splitunits, "%1", 1);
        progress |= d->runPass(d->pass_numbers, "%1", 1);
        progress |= d->runPass(d->pass_filesize, "%1 %2", 2);
        progress |= d->runPass(d->pass_typehints, "%1", 1);

        // Comparators
        d->pass_comparators.setComparator(Nepomuk2::Query::ComparisonTerm::Contains);
        progress |= d->runPass(d->pass_comparators,
            i18nc("Equality", "(contains|containing) %1"), 1);
        d->pass_comparators.setComparator(Nepomuk2::Query::ComparisonTerm::Greater);
        progress |= d->runPass(d->pass_comparators,
            i18nc("Strictly greater", "(greater|bigger|more) than %1;at least %1;\\> %1"), 1);
        d->pass_comparators.setComparator(Nepomuk2::Query::ComparisonTerm::Smaller);
        progress |= d->runPass(d->pass_comparators,
            i18nc("Strictly smaller", "(smaller|less|lesser) than %1;at most %1;\\< %1"), 1);
        d->pass_comparators.setComparator(Nepomuk2::Query::ComparisonTerm::Equal);
        progress |= d->runPass(d->pass_comparators,
            i18nc("Equality", "(equal|equals|=) %1;equal to %1"), 1);

        // Email-related properties
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NMO::messageFrom());
        progress |= d->runPass(d->pass_properties,
            i18nc("Sender of an e-mail", "sent by %1;from %1;sender is %1;sender %1"), 1);
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NMO::messageSubject());
        progress |= d->runPass(d->pass_properties,
            i18nc("Title of an e-mail", "title %1"), 1);
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NMO::messageRecipient());
        progress |= d->runPass(d->pass_properties,
            i18nc("Recipient of an e-mail", "sent to %1;to %1;recipient is %1;recipient %1"), 1);

        // File-related properties
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NFO::fileSize());
        progress |= d->runPass(d->pass_properties,
            i18nc("Size of a file", "size is %1;size %1;being %1 large;%1 large"), 1);
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NFO::fileName());
        progress |= d->runPass(d->pass_properties,
            i18nc("Name of a file", "name %1;named %1"), 1);
    }

    // Fuse the terms into a big AND term and produce the query
    int end_index;
    Nepomuk2::Query::Term final_term = d->fuseTerms(0, end_index);

    qDebug() << final_term;

    return Nepomuk2::Query::Query(final_term);
}

QStringList Parser::Private::split(const QString &query, bool split_separators)
{
    QString separators;
    QStringList parts;
    QString part;
    int size = query.size();
    bool between_quotes = false;

    if (split_separators) {
        separators = i18nc("Characters that are kept in the query for further processing but are considered word boundaries", ".,;:!?()[]{}<>=");
    }

    for (int i=0; i<size; ++i) {
        QChar c = query.at(i);

        if (!between_quotes && (c.isSpace() || (split_separators && separators.contains(c)))) {
            // A part may be empty if more than one space are found in block in the input
            if (part.size() > 0) {
                parts.append(part);
                part.clear();
            }

            // Add a separator, if any
            if (split_separators && separators.contains(c)) {
                parts.append(QString(c));
            }
        } else if (c == '"') {
            between_quotes = !between_quotes;
        } else {
            part.append(c);
        }
    }

    if (part.size() > 0) {
        parts.append(part);
    }

    return parts;
}

template<typename T>
bool Parser::Private::runPass(const T &pass, const QString &pattern, int match_count)
{
    QList<Nepomuk2::Query::Term> matched_terms;
    bool progress = false;

    for (int i=0; i<match_count; ++i) {
        matched_terms.append(Nepomuk2::Query::Term());
    }

    // Split the pattern at ";" characters, as a locale can have more than one
    // pattern that can be used for a given rule
    QStringList rules = pattern.split(QLatin1Char(';'));

    Q_FOREACH(const QString &rule, rules) {
        // Split the rule into parts that have to be matched
        QStringList parts = split(rule, false);
        int part_index = 0;
        int first_match_index = -1;

        // Try to match the rule into the list of terms
        for (int i=0; i<terms.size(); ++i) {
            const Nepomuk2::Query::Term &term = terms.at(i);
            int index = -1;

            if (match(term, parts.at(part_index), index)) {
                if (index != -1) {
                    matched_terms[index] = term;
                }

                if (first_match_index == -1) {
                    first_match_index = i;
                }

                if (++part_index == parts.size()) {
                    // Match complete, run the pass on it
                    QList<Nepomuk2::Query::Term> replacement = pass.run(matched_terms);

                    if (replacement.count() > 0) {
                        // Replace terms first_match_index..i with replacement
                        QList<Nepomuk2::Query::Term>::iterator first_remove =
                            terms.begin() + first_match_index;
                        QList<Nepomuk2::Query::Term>::iterator last_remove =
                            terms.begin() + (i + 1);

                        terms.erase(first_remove, last_remove);

                        for (int j=replacement.count()-1; j>=0; --j) {
                            terms.insert(first_match_index, replacement.at(j));
                        }

                        // Re-explore the terms vector as indexes have changed
                        progress = true;
                        i = -1;
                    }

                    // Reinitialize the matching machinery
                    first_match_index = -1;
                    part_index = 0;
                }
            } else {
                // The begin of the pattern matched but not the end
                first_match_index = -1;
                part_index = 0;
            }
        }
    }

    return progress;
}

bool Parser::Private::match(const Nepomuk2::Query::Term &term, const QString &pattern, int &index)
{
    if (pattern.at(0) == QLatin1Char('%')) {
        // Placeholder
        index = pattern.mid(1).toInt() - 1;

        return true;
    } else {
        // Literal value that has to be matched against a regular expression
        if (!term.isLiteralTerm()) {
            return false;
        }

        QString value = term.toLiteralTerm().value().toString();
        QRegExp regexp(pattern, Qt::CaseInsensitive, QRegExp::RegExp2);

        return regexp.exactMatch(value);
    }
}

Nepomuk2::Query::Term Parser::Private::fuseTerms(int first_term_index, int &end_term_index) const
{
    Nepomuk2::Query::Term fused_term;
    bool build_and = true;

    // Fuse terms in nested AND and OR terms. "a AND b OR c" is fused as
    // "(a AND b) OR c"
    for (end_term_index=first_term_index; end_term_index<terms.size(); ++end_term_index) {
        Nepomuk2::Query::Term term = terms.at(end_term_index);

        if (term.isLiteralTerm()) {
            Soprano::LiteralValue value = term.toLiteralTerm().value();

            if (value.isString()) {
                QString content = value.toString();

                if (content == QLatin1String("OR")) {
                    // Consume the OR term, the next term will be ORed with the previous
                    build_and = false;
                    continue;
                } else if (content == QLatin1String("AND")) {
                    // Consume the AND term
                    build_and = true;
                    continue;
                } else if (content == QLatin1String("(")) {
                    // Fuse the nested query
                    term = fuseTerms(end_term_index + 1, end_term_index);
                } else if (content == QLatin1String(")")) {
                    // Done
                    return fused_term;
                }
            }
        }

        // Add term to the fused term
        if (!fused_term.isValid()) {
            fused_term = term;
        } else if (build_and) {
            if (fused_term.isAndTerm()) {
                fused_term.toAndTerm().addSubTerm(term);
            } else {
                fused_term = Nepomuk2::Query::AndTerm(fused_term, term);
            }
        } else {
            if (fused_term.isOrTerm()) {
                fused_term.toOrTerm().addSubTerm(term);
            } else {
                fused_term = Nepomuk2::Query::OrTerm(fused_term, term);
            }
        }

        // If there is no logical operator in the query, the default one is AND
        build_and = true;
    }

    return fused_term;
}
<commit_msg>Support negation of terms or nested queries<commit_after>/* This file is part of the Nepomuk query parser
   Copyright (c) 2013 Denis Steckelmacher <steckdenis@yahoo.fr>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2.1 as published by the Free Software Foundation,
   or any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "parser.h"

#include "pass_splitunits.h"
#include "pass_numbers.h"
#include "pass_filesize.h"
#include "pass_typehints.h"
#include "pass_properties.h"
#include "pass_comparators.h"

#include <nepomuk2/andterm.h>
#include <nepomuk2/orterm.h>
#include <nepomuk2/negationterm.h>
#include <nepomuk2/literalterm.h>
#include <nepomuk2/property.h>
#include <nepomuk2/nfo.h>
#include <nepomuk2/nmo.h>
#include <soprano/literalvalue.h>
#include <soprano/nao.h>
#include <klocalizedstring.h>

#include <QList>
#include <QRegExp>
#include <QtDebug>

struct Parser::Private
{
    QStringList split(const QString &query, bool split_separators);

    template<typename T>
    bool runPass(const T &pass, const QString &pattern, int match_count);
    bool match(const Nepomuk2::Query::Term &term, const QString &pattern, int &index);
    Nepomuk2::Query::Term fuseTerms(int first_term_index, int &end_term_index) const;

    // Terms on which the parser works
    QList<Nepomuk2::Query::Term> terms;

    // Parsing passes (they cache translations, queries, etc)
    PassSplitUnits pass_splitunits;
    PassNumbers pass_numbers;
    PassFileSize pass_filesize;
    PassTypeHints pass_typehints;
    PassComparators pass_comparators;
    PassProperties pass_properties;
};

Parser::Parser()
: d(new Private)
{
}

Parser::Parser(const Parser &other)
: d(new Private(*other.d))
{
}

Parser::~Parser()
{
    delete d;
}

void Parser::reset()
{
    d->terms.clear();
}

Nepomuk2::Query::Query Parser::parse(const QString &query)
{
    reset();

    // Split the query into terms
    QStringList parts = d->split(query, true);

    Q_FOREACH(const QString &part, parts) {
        d->terms.append(Nepomuk2::Query::LiteralTerm(part));
    }

    // Parse passes
    bool progress = true;

    while (progress) {
        progress = false;

        progress |= d->runPass(d->pass_splitunits, "%1", 1);
        progress |= d->runPass(d->pass_numbers, "%1", 1);
        progress |= d->runPass(d->pass_filesize, "%1 %2", 2);
        progress |= d->runPass(d->pass_typehints, "%1", 1);

        // Comparators
        d->pass_comparators.setComparator(Nepomuk2::Query::ComparisonTerm::Contains);
        progress |= d->runPass(d->pass_comparators,
            i18nc("Equality", "(contains|containing) %1"), 1);
        d->pass_comparators.setComparator(Nepomuk2::Query::ComparisonTerm::Greater);
        progress |= d->runPass(d->pass_comparators,
            i18nc("Strictly greater", "(greater|bigger|more) than %1;at least %1;\\> %1"), 1);
        d->pass_comparators.setComparator(Nepomuk2::Query::ComparisonTerm::Smaller);
        progress |= d->runPass(d->pass_comparators,
            i18nc("Strictly smaller", "(smaller|less|lesser) than %1;at most %1;\\< %1"), 1);
        d->pass_comparators.setComparator(Nepomuk2::Query::ComparisonTerm::Equal);
        progress |= d->runPass(d->pass_comparators,
            i18nc("Equality", "(equal|equals|=) %1;equal to %1"), 1);

        // Email-related properties
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NMO::messageFrom());
        progress |= d->runPass(d->pass_properties,
            i18nc("Sender of an e-mail", "sent by %1;from %1;sender is %1;sender %1"), 1);
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NMO::messageSubject());
        progress |= d->runPass(d->pass_properties,
            i18nc("Title of an e-mail", "title %1"), 1);
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NMO::messageRecipient());
        progress |= d->runPass(d->pass_properties,
            i18nc("Recipient of an e-mail", "sent to %1;to %1;recipient is %1;recipient %1"), 1);

        // File-related properties
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NFO::fileSize());
        progress |= d->runPass(d->pass_properties,
            i18nc("Size of a file", "size is %1;size %1;being %1 large;%1 large"), 1);
        d->pass_properties.setProperty(Nepomuk2::Vocabulary::NFO::fileName());
        progress |= d->runPass(d->pass_properties,
            i18nc("Name of a file", "name %1;named %1"), 1);
    }

    // Fuse the terms into a big AND term and produce the query
    int end_index;
    Nepomuk2::Query::Term final_term = d->fuseTerms(0, end_index);

    qDebug() << final_term;

    return Nepomuk2::Query::Query(final_term);
}

QStringList Parser::Private::split(const QString &query, bool split_separators)
{
    QString separators;
    QStringList parts;
    QString part;
    int size = query.size();
    bool between_quotes = false;

    if (split_separators) {
        separators = i18nc("Characters that are kept in the query for further processing but are considered word boundaries", ".,;:!?()[]{}<>=");
    }

    for (int i=0; i<size; ++i) {
        QChar c = query.at(i);

        if (!between_quotes && (c.isSpace() || (split_separators && separators.contains(c)))) {
            // A part may be empty if more than one space are found in block in the input
            if (part.size() > 0) {
                parts.append(part);
                part.clear();
            }

            // Add a separator, if any
            if (split_separators && separators.contains(c)) {
                parts.append(QString(c));
            }
        } else if (c == '"') {
            between_quotes = !between_quotes;
        } else {
            part.append(c);
        }
    }

    if (part.size() > 0) {
        parts.append(part);
    }

    return parts;
}

template<typename T>
bool Parser::Private::runPass(const T &pass, const QString &pattern, int match_count)
{
    QList<Nepomuk2::Query::Term> matched_terms;
    bool progress = false;

    for (int i=0; i<match_count; ++i) {
        matched_terms.append(Nepomuk2::Query::Term());
    }

    // Split the pattern at ";" characters, as a locale can have more than one
    // pattern that can be used for a given rule
    QStringList rules = pattern.split(QLatin1Char(';'));

    Q_FOREACH(const QString &rule, rules) {
        // Split the rule into parts that have to be matched
        QStringList parts = split(rule, false);
        int part_index = 0;
        int first_match_index = -1;

        // Try to match the rule into the list of terms
        for (int i=0; i<terms.size(); ++i) {
            const Nepomuk2::Query::Term &term = terms.at(i);
            int index = -1;

            if (match(term, parts.at(part_index), index)) {
                if (index != -1) {
                    matched_terms[index] = term;
                }

                if (first_match_index == -1) {
                    first_match_index = i;
                }

                if (++part_index == parts.size()) {
                    // Match complete, run the pass on it
                    QList<Nepomuk2::Query::Term> replacement = pass.run(matched_terms);

                    if (replacement.count() > 0) {
                        // Replace terms first_match_index..i with replacement
                        QList<Nepomuk2::Query::Term>::iterator first_remove =
                            terms.begin() + first_match_index;
                        QList<Nepomuk2::Query::Term>::iterator last_remove =
                            terms.begin() + (i + 1);

                        terms.erase(first_remove, last_remove);

                        for (int j=replacement.count()-1; j>=0; --j) {
                            terms.insert(first_match_index, replacement.at(j));
                        }

                        // Re-explore the terms vector as indexes have changed
                        progress = true;
                        i = -1;
                    }

                    // Reinitialize the matching machinery
                    first_match_index = -1;
                    part_index = 0;
                }
            } else {
                // The begin of the pattern matched but not the end
                first_match_index = -1;
                part_index = 0;
            }
        }
    }

    return progress;
}

bool Parser::Private::match(const Nepomuk2::Query::Term &term, const QString &pattern, int &index)
{
    if (pattern.at(0) == QLatin1Char('%')) {
        // Placeholder
        index = pattern.mid(1).toInt() - 1;

        return true;
    } else {
        // Literal value that has to be matched against a regular expression
        if (!term.isLiteralTerm()) {
            return false;
        }

        QString value = term.toLiteralTerm().value().toString();
        QRegExp regexp(pattern, Qt::CaseInsensitive, QRegExp::RegExp2);

        return regexp.exactMatch(value);
    }
}

Nepomuk2::Query::Term Parser::Private::fuseTerms(int first_term_index, int &end_term_index) const
{
    Nepomuk2::Query::Term fused_term;
    bool build_and = true;
    bool build_not = false;

    // Fuse terms in nested AND and OR terms. "a AND b OR c" is fused as
    // "(a AND b) OR c"
    for (end_term_index=first_term_index; end_term_index<terms.size(); ++end_term_index) {
        Nepomuk2::Query::Term term = terms.at(end_term_index);

        if (term.isLiteralTerm()) {
            Soprano::LiteralValue value = term.toLiteralTerm().value();

            if (value.isString()) {
                QString content = value.toString();

                if (content == QLatin1String("OR")) {
                    // Consume the OR term, the next term will be ORed with the previous
                    build_and = false;
                    continue;
                } else if (content == QLatin1String("AND")) {
                    // Consume the AND term
                    build_and = true;
                    continue;
                } else if (content == QLatin1String("!")) {
                    // Consume the negation
                    build_not = true;
                    continue;
                } else if (content == QLatin1String("(")) {
                    // Fuse the nested query
                    term = fuseTerms(end_term_index + 1, end_term_index);
                } else if (content == QLatin1String(")")) {
                    // Done
                    return fused_term;
                }
            }
        }

        // Negate the term if needed
        if (build_not) {
            term = Nepomuk2::Query::NegationTerm::negateTerm(term);
        }

        // Add term to the fused term
        if (!fused_term.isValid()) {
            fused_term = term;
        } else if (build_and) {
            if (fused_term.isAndTerm()) {
                fused_term.toAndTerm().addSubTerm(term);
            } else {
                fused_term = Nepomuk2::Query::AndTerm(fused_term, term);
            }
        } else {
            if (fused_term.isOrTerm()) {
                fused_term.toOrTerm().addSubTerm(term);
            } else {
                fused_term = Nepomuk2::Query::OrTerm(fused_term, term);
            }
        }

        // Default to AND, and don't invert terms
        build_and = true;
        build_not = false;
    }

    return fused_term;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 NovaCoin Developers

#include <string.h>
#include "pbkdf2.h"

static inline uint32_t
be32dec(const void *pp)
{
    const uint8_t *p = (uint8_t const *)pp;

    return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
        ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
}

static inline void
be32enc(void *pp, uint32_t x)
{
    uint8_t * p = (uint8_t *)pp;

    p[3] = x & 0xff;
    p[2] = (x >> 8) & 0xff;
    p[1] = (x >> 16) & 0xff;
    p[0] = (x >> 24) & 0xff;
}

/* Initialize an HMAC-SHA256 operation with the given key. */
void
HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
{
    unsigned char pad[64];
    unsigned char khash[32];
    const unsigned char * K = (const unsigned char *)_K;
    size_t i;

    /* If Klen > 64, the key is really SHA256(K). */
    if (Klen > 64) {
        SHA256_Init(&ctx->ictx);
        SHA256_Update(&ctx->ictx, K, Klen);
        SHA256_Final(khash, &ctx->ictx);
        K = khash;
        Klen = 32;
    }

    /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
    SHA256_Init(&ctx->ictx);
    memset(pad, 0x36, 64);
    for (i = 0; i < Klen; i++)
        pad[i] ^= K[i];
    SHA256_Update(&ctx->ictx, pad, 64);

    /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
    SHA256_Init(&ctx->octx);
    memset(pad, 0x5c, 64);
    for (i = 0; i < Klen; i++)
        pad[i] ^= K[i];
    SHA256_Update(&ctx->octx, pad, 64);

    /* Clean the stack. */
    memset(khash, 0, 32);
}

/* Add bytes to the HMAC-SHA256 operation. */
void
HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len)
{

    /* Feed data to the inner SHA256 operation. */
    SHA256_Update(&ctx->ictx, in, len);
}

/* Finish an HMAC-SHA256 operation. */
void
HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx)
{
    unsigned char ihash[32];

    /* Finish the inner SHA256 operation. */
    SHA256_Final(ihash, &ctx->ictx);

    /* Feed the inner hash to the outer SHA256 operation. */
    SHA256_Update(&ctx->octx, ihash, 32);

    /* Finish the outer SHA256 operation. */
    SHA256_Final(digest, &ctx->octx);

    /* Clean the stack. */
    memset(ihash, 0, 32);
}

/**
 * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
 * write the output to buf.  The value dkLen must be at most 32 * (2^32 - 1).
 */
void
PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
    size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
{
    HMAC_SHA256_CTX PShctx, hctx;
    size_t i;
    uint8_t ivec[4];
    uint8_t U[32];
    uint8_t T[32];
    uint64_t j;
    int k;
    size_t clen;

    /* Compute HMAC state after processing P and S. */
    HMAC_SHA256_Init(&PShctx, passwd, passwdlen);
    HMAC_SHA256_Update(&PShctx, salt, saltlen);

    /* Iterate through the blocks. */
    for (i = 0; i * 32 < dkLen; i++) {
        /* Generate INT(i + 1). */
        be32enc(ivec, (uint32_t)(i + 1));

        /* Compute U_1 = PRF(P, S || INT(i)). */
        memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
        HMAC_SHA256_Update(&hctx, ivec, 4);
        HMAC_SHA256_Final(U, &hctx);

        /* T_i = U_1 ... */
        memcpy(T, U, 32);

        for (j = 2; j <= c; j++) {
            /* Compute U_j. */
            HMAC_SHA256_Init(&hctx, passwd, passwdlen);
            HMAC_SHA256_Update(&hctx, U, 32);
            HMAC_SHA256_Final(U, &hctx);

            /* ... xor U_j ... */
            for (k = 0; k < 32; k++)
                T[k] ^= U[k];
        }

        /* Copy as many bytes as necessary into buf. */
        clen = dkLen - i * 32;
        if (clen > 32)
            clen = 32;
        memcpy(&buf[i * 32], T, clen);
    }

    /* Clean PShctx, since we never called _Final on it. */
    memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX));
}

<commit_msg>Delete pbkdf2.cpp<commit_after><|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "CoupledPotential.h"

template<>
InputParameters validParams<CoupledPotential>()
{
  InputParameters params = validParams<Kernel>();
  params.addParam<std::string>("mob_name", "mobtemp", "The mobility used with the kernel");
  params.addRequiredCoupledVar("potential", "The variable representing the electrical potential.");
  return params;
}

CoupledPotential::CoupledPotential(const std::string & name, InputParameters parameters) :
    Kernel(name, parameters),

    // Couple to the gradient of the potential
    _potential_gradient(coupledGradient("potential")),

    // Save off the coupled variable identifier for use in computeQpOffDiagJacobian
    //_potential_var(coupled("potential")),

    // Grab necessary material properties
    _conductivity(getParam<Real>("conductivity"))

    // Get the mobility parameters
    _mob_name(getParam<std::string>("mob_name")),
    _mob(getMaterialProperty<Real>(_mob_name))
{
}

Real
CoupledPotential::computeQpResidual()
{
   return _mob[_qp] * _conductivity[_qp] * _potential_gradient[_qp] * _u[_qp] * _test[_i][_qp];
}

Real
CoupledPotential::computeQpJacobian()
{
  return _mob[_qp] *  _conductivity[_qp] * _potential_gradient[_qp] *_phi[_j][_qp] * _test[_i][_qp];
}
<commit_msg>Update CoupledPotential.C<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "CoupledPotential.h"

template<>
InputParameters validParams<CoupledPotential>()
{
  InputParameters params = validParams<Kernel>();
  params.addParam<std::string>("mob_name", "mobtemp", "The mobility used with the kernel");
  params.addRequiredCoupledVar("potential", "The variable representing the electrical potential.");
  return params;
}

CoupledPotential::CoupledPotential(const std::string & name, InputParameters parameters) :
    Kernel(name, parameters),

    // Couple to the gradient of the potential
    _potential_gradient(coupledGradient("potential")),

    // Save off the coupled variable identifier for use in computeQpOffDiagJacobian
    _potential_var(coupled("potential")),

    // Grab necessary material properties
    _conductivity(getParam<Real>("conductivity"))

    // Get the mobility parameters
    _mob_name(getParam<std::string>("mob_name")),
    _mob(getMaterialProperty<Real>(_mob_name))
{
}

Real
CoupledPotential::computeQpResidual()
{
   return _mob[_qp] * _conductivity[_qp] * _potential_gradient[_qp] * _u[_qp] * _test[_i][_qp];
}

Real
CoupledPotential::computeQpJacobian()
{
  return _mob[_qp] *  _conductivity[_qp] * _potential_gradient[_qp] *_phi[_j][_qp] * _test[_i][_qp];
}

Real
CoupledPotential::computeQpOffDiagJacobian(unsigned int jvar)
{
  if (jvar == _potential_var)
  {
    return _conductivity[_qp]*_phi[_j][_qp] * _u[_qp] * _test[_i][_qp];
  }

  return 0.0;
}
<|endoftext|>


<commit_before>//
//#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <ctime>
#include <algorithm>
#include <cmath>
#include "GPIOClass.h"

using namespace std;

void Pulse(GPIOClass* pin, double cycles);
void Wait(double seconds);
clock_t timer;
double time_to_complete;
double resolution = CLOCKS_PER_SEC/10;

#define PI 4*atan(1)

int main (int argc, char *argv[]) {
	string type = argv[1];
	transform(type.begin(), type.end(), type.begin(), :: tolower);
	// lets assume that the way to run this is
	// pwm.exe [rising/falling/sine/constant]
	if (argc != 2) {
		cout << "Usage: pwm [rising/falling/sine/constant/blink]" << endl;
		return -1;
	}

	while (time_to_complete <= 0) {
		cout << "Input How Long To Run (in seconds)" << endl;
		cin >> time_to_complete;
	}

	GPIOClass* out1 = new GPIOClass("4");
	GPIOClass* in2 = new GPIOClass("17");

	out1->export_gpio();
	in2->export_gpio();

	out1->setdir_gpio("out");
	in2->setdir_gpio("in");

	cout << "Pins are setup." << endl;
	cout << "resolution of cpu" << CLOCKS_PER_SEC << endl;
	// avoiding flickering will be at 100hz
	// aka turn on and off 100 times a sec
	// a cycle of 0 is off
	// a cycle of 100 is on

	if (type == "rising") {
		clock_t finish = clock() + time_to_complete * CLOCKS_PER_SEC;
		double t = time_to_complete;
		while (clock() < finish) {
			// pulse for however long we need to to achieve brightness.
			if(t == 0){
				t = time_to_complete;
			}
			else{
				t -=;
			}
			//Pulse(out1, sin((2PI/2) * abs(1/t)));
			//Wait(sin((PI/2) * abs(1/t)));
			cout << sin((2*PI)/t) << endl;
			cout << "this is t" << t << endl;
			Pulse(out1, 1/resolution);
			Wait(sin((2*PI)/t));
		}
	}
	if (type == "falling") {

	}
	if (type == "sine") {
		clock_t finish = clock() + time_to_complete * CLOCKS_PER_SEC;
		while (clock() < finish) {
			// pulse for however long we need to to achieve brightness.
			for (double i = 0; i < 1; i += resolution) {
				Pulse(out1, 1/resolution);
				cout << sin(i)/resolution << endl;
				Wait(sin(i)/resolution);
			}
		}
	}
	if (type == "constant") {
		out1->setval_gpio("1"); // turn the pin on
		Wait(time_to_complete); // sleep for number of cycles / 1/100 sec
		//cout << "Waiting during pulse" << endl;
		out1->setval_gpio("0"); // turn the pin off
	}
	if (type == "blink") { // aka. TESTR
		clock_t finish = clock() + time_to_complete * CLOCKS_PER_SEC;
		while (clock() < finish) {
			// pulse for however long we need to to achieve brightness.
			Pulse(out1, 1/resolution);
			Wait(4/resolution);
		}
	}
	cout << "Done." << endl;
}

//1 cycle is 1/100th of a second
//100 cycles is 1 sec
void Pulse(GPIOClass* pin, double cycles) {
	bool running = true;
	while (running) {
		pin->setval_gpio("1"); // turn the pin on
		Wait(cycles / resolution); // sleep for number of cycles / 1/100 sec
		//cout << "Waiting during pulse" << endl;
		pin->setval_gpio("0"); // turn the pin off
		running = false; // this is unnessesary but could be useful if modified a bit.
	}
}

void Wait ( double seconds )
{
	clock_t endwait;
	endwait = clock () + seconds * CLOCKS_PER_SEC ;
	while (clock() < endwait) {}
}
<commit_msg>Update pwm.cpp<commit_after>//
//#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <ctime>
#include <algorithm>
#include <cmath>
#include "GPIOClass.h"

using namespace std;

void Pulse(GPIOClass* pin, double cycles);
void Wait(double seconds);
clock_t timer;
double time_to_complete;
double resolution = CLOCKS_PER_SEC/10;

#define PI 4*atan(1)

int main (int argc, char *argv[]) {
	string type = argv[1];
	transform(type.begin(), type.end(), type.begin(), :: tolower);
	// lets assume that the way to run this is
	// pwm.exe [rising/falling/sine/constant]
	if (argc != 2) {
		cout << "Usage: pwm [rising/falling/sine/constant/blink]" << endl;
		return -1;
	}

	while (time_to_complete <= 0) {
		cout << "Input How Long To Run (in seconds)" << endl;
		cin >> time_to_complete;
	}

	GPIOClass* out1 = new GPIOClass("4");
	GPIOClass* in2 = new GPIOClass("17");

	out1->export_gpio();
	in2->export_gpio();

	out1->setdir_gpio("out");
	in2->setdir_gpio("in");

	cout << "Pins are setup." << endl;
	cout << "resolution of cpu" << CLOCKS_PER_SEC << endl;
	// avoiding flickering will be at 100hz
	// aka turn on and off 100 times a sec
	// a cycle of 0 is off
	// a cycle of 100 is on

	if (type == "rising") {
		clock_t finish = clock() + time_to_complete * CLOCKS_PER_SEC;
		double t = time_to_complete;
		while (clock() < finish) {
			// pulse for however long we need to to achieve brightness.
			if(t == 0){
				t = time_to_complete;
			}
			else{
				t -=1;
			}
			//Pulse(out1, sin((2PI/2) * abs(1/t)));
			//Wait(sin((PI/2) * abs(1/t)));
			cout << sin((2*PI)/t) << endl;
			cout << "this is t" << t << endl;
			Pulse(out1, 1/resolution);
			Wait(sin((2*PI)/t));
		}
	}
	if (type == "falling") {

	}
	if (type == "sine") {
		clock_t finish = clock() + time_to_complete * CLOCKS_PER_SEC;
		while (clock() < finish) {
			// pulse for however long we need to to achieve brightness.
			for (double i = 0; i < 1; i += resolution) {
				Pulse(out1, 1/resolution);
				cout << sin(i)/resolution << endl;
				Wait(sin(i)/resolution);
			}
		}
	}
	if (type == "constant") {
		out1->setval_gpio("1"); // turn the pin on
		Wait(time_to_complete); // sleep for number of cycles / 1/100 sec
		//cout << "Waiting during pulse" << endl;
		out1->setval_gpio("0"); // turn the pin off
	}
	if (type == "blink") { // aka. TESTR
		clock_t finish = clock() + time_to_complete * CLOCKS_PER_SEC;
		while (clock() < finish) {
			// pulse for however long we need to to achieve brightness.
			Pulse(out1, 1/resolution);
			Wait(4/resolution);
		}
	}
	cout << "Done." << endl;
}

//1 cycle is 1/100th of a second
//100 cycles is 1 sec
void Pulse(GPIOClass* pin, double cycles) {
	bool running = true;
	while (running) {
		pin->setval_gpio("1"); // turn the pin on
		Wait(cycles / resolution); // sleep for number of cycles / 1/100 sec
		//cout << "Waiting during pulse" << endl;
		pin->setval_gpio("0"); // turn the pin off
		running = false; // this is unnessesary but could be useful if modified a bit.
	}
}

void Wait ( double seconds )
{
	clock_t endwait;
	endwait = clock () + seconds * CLOCKS_PER_SEC ;
	while (clock() < endwait) {}
}
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "../archivereader.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

using namespace std;
using namespace Strigi;

int errors;

void
test1(const char* path) {
    FileStreamOpener opener;
    ArchiveReader r;
    r.addStreamOpener(&opener);
    StreamBase<char>* s = r.openStream(path);
    if (s == 0) {
        fprintf(stderr, "cannot open stream to %s\n", path);
        errors++;
    }
    r.closeStream(s);
}
void
test2(const char* path) {
    FileStreamOpener opener;
    ArchiveReader r;
    r.addStreamOpener(&opener);
    ArchiveReader::DirLister dl = r.dirEntries(path);
    EntryInfo e;
    while (dl.nextEntry(e)) {
        string filepath(path);
        filepath += "/";
        filepath += e.filename;
        if (e.type == EntryInfo::File) {
            test1(filepath.c_str());
        }
        test2(filepath.c_str());
    }
}

void
walkdirectories(const char* path, void (*callback)(const char*)) {
    DIR* dir = opendir(path);
    if (dir == 0) return;
    string p(path);
    struct dirent* subdir = readdir(dir);
    struct stat dirstat;
    while (subdir) {
        if (subdir->d_name[0] == '.') {
            subdir = readdir(dir);
            continue;
        }
        string name = subdir->d_name;
        string filepath = p + name;
        if (lstat(filepath.c_str(), &dirstat) == 0) {
            if (S_ISREG(dirstat.st_mode)) {
                callback(filepath.c_str());
            } else if (S_ISDIR(dirstat.st_mode)) {
                filepath += "/";
                walkdirectories(filepath.c_str(), callback);
            }
        }
        subdir = readdir(dir);
    }
    closedir(dir);
}

/**
 * Test the class ArchiveReader by analyzing all files in the given
 * directory.
 **/
int
ArchiveReaderTest(int argc, char** argv) {
    if (argc < 2) return 1;
    errors = 0;
    walkdirectories(argv[1], test1);
    walkdirectories(argv[1], test2);
    if (errors) {
        fprintf(stderr, "%i errors\n", errors);
    }
    return errors;
}
<commit_msg>Make the unit test more robust for path formatting.<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "../archivereader.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

using namespace std;
using namespace Strigi;

int errors;

void
test1(const char* path) {
    FileStreamOpener opener;
    ArchiveReader r;
    r.addStreamOpener(&opener);
    StreamBase<char>* s = r.openStream(path);
    if (s == 0) {
        fprintf(stderr, "cannot open stream to %s\n", path);
        errors++;
    }
    r.closeStream(s);
}
void
test2(const char* path) {
    FileStreamOpener opener;
    ArchiveReader r;
    r.addStreamOpener(&opener);
    ArchiveReader::DirLister dl = r.dirEntries(path);
    EntryInfo e;
    while (dl.nextEntry(e)) {
        string filepath(path);
        filepath += "/";
        filepath += e.filename;
        if (e.type == EntryInfo::File) {
            test1(filepath.c_str());
        }
        test2(filepath.c_str());
    }
}

void
walkdirectories(const char* path, void (*callback)(const char*)) {
    DIR* dir = opendir(path);
    if (dir == 0) {
        callback(path);
        return;
    }
    string p(path);
    if (p.size() > 0 && p[p.size()-1] != '/') {
        p.append("/");
    }
    struct dirent* subdir = readdir(dir);
    struct stat dirstat;
    while (subdir) {
        if (subdir->d_name[0] == '.') {
            subdir = readdir(dir);
            continue;
        }
        string name = subdir->d_name;
        string filepath = p + name;
        if (lstat(filepath.c_str(), &dirstat) == 0) {
            if (S_ISREG(dirstat.st_mode)) {
                callback(filepath.c_str());
            } else if (S_ISDIR(dirstat.st_mode)) {
                filepath += "/";
                walkdirectories(filepath.c_str(), callback);
            }
        }
        subdir = readdir(dir);
    }
    closedir(dir);
}

/**
 * Test the class ArchiveReader by analyzing all files in the given
 * directory.
 **/
int
ArchiveReaderTest(int argc, char** argv) {
    if (argc < 2) return 1;
    errors = 0;
    walkdirectories(argv[1], test1);
    walkdirectories(argv[1], test2);
    if (errors) {
        fprintf(stderr, "%i errors\n", errors);
    }
    return errors;
}
<|endoftext|>


<commit_before>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2016 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  hugh/render/stage/base.cpp                                                      */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// include i/f header

#include "hugh/render/stage/base.hpp"

// includes, system

#include <stdexcept> // std::logic_error

// includes, project

//#include <>

#define HUGH_USE_TRACE
#undef HUGH_USE_TRACE
#include <hugh/support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  // variables, internal

  // functions, internal

} // namespace {

namespace hugh {

  namespace render {

    namespace stage {

      // variables, exported

      // functions, exported

      /* virtual */
      base::~base()
      {
        TRACE("hugh::render::stage::base::~base");
      }

      void
      base::execute(context::swap& a)
      {
        TRACE("hugh::render::stage::base::execute");

        if (active_) {
          do_execute(a);
        }
      }

      bool const&
      base::active() const
      {
        TRACE("hugh::render::stage::base::active(get)");

        return active_;
      }

      bool
      base::active(bool a)
      {
        TRACE("hugh::render::stage::base::active(set)");

        bool const result(active_);

        active_ = a;

        return result;
      }

      /* virtual */ void
      base::invalidate()
      {
        TRACE("hugh::render::stage::base::invalidate");

        throw std::logic_error("pure virtual function "
                               "'hugh::render::stage::base::invalidate'"
                               " called");
      }

      /* virtual */ void
      base::resize(glm::uvec2 const&)
      {
        TRACE("hugh::render::stage::base::resize");

        throw std::logic_error("pure virtual function "
                               "'hugh::render::stage::base::resize'"
                               " called");
      }

      /* virtual */ void
      base::print_on(std::ostream& os) const
      {
        TRACE_NEVER("hugh::render::stage::base::print_on");

        os << '[' << ctx_ << ',' << ((active_) ? "" : "!") << "active" << ']';
      }

      /* explicit */
      base::base(context::device& a)
        : support::printable       (),
          support::refcounted<base>(),
          ctx_                     (a),
          active_                  ()
      {
        TRACE("hugh::render::stage::base::base");
      }

      /* virtual */ void
      base::do_execute(context::swap&)
      {
        TRACE("hugh::render::stage::base::do_execute");

        throw std::logic_error("pure virtual function "
                               "'hugh::render::stage::base::do_execute'"
                               " called");
      }

    } // namespace stage {

  } // namespace render {

} // namespace hugh {
<commit_msg>fixed: missing attribute initialization<commit_after>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2016 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  hugh/render/stage/base.cpp                                                      */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// include i/f header

#include "hugh/render/stage/base.hpp"

// includes, system

#include <stdexcept> // std::logic_error

// includes, project

//#include <>

#define HUGH_USE_TRACE
#undef HUGH_USE_TRACE
#include <hugh/support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  // variables, internal

  // functions, internal

} // namespace {

namespace hugh {

  namespace render {

    namespace stage {

      // variables, exported

      // functions, exported

      /* virtual */
      base::~base()
      {
        TRACE("hugh::render::stage::base::~base");
      }

      void
      base::execute(context::swap& a)
      {
        TRACE("hugh::render::stage::base::execute");

        if (active_) {
          do_execute(a);
        }
      }

      bool const&
      base::active() const
      {
        TRACE("hugh::render::stage::base::active(get)");

        return active_;
      }

      bool
      base::active(bool a)
      {
        TRACE("hugh::render::stage::base::active(set)");

        bool const result(active_);

        active_ = a;

        return result;
      }

      /* virtual */ void
      base::invalidate()
      {
        TRACE("hugh::render::stage::base::invalidate");

        throw std::logic_error("pure virtual function "
                               "'hugh::render::stage::base::invalidate'"
                               " called");
      }

      /* virtual */ void
      base::resize(glm::uvec2 const&)
      {
        TRACE("hugh::render::stage::base::resize");

        throw std::logic_error("pure virtual function "
                               "'hugh::render::stage::base::resize'"
                               " called");
      }

      /* virtual */ void
      base::print_on(std::ostream& os) const
      {
        TRACE_NEVER("hugh::render::stage::base::print_on");

        os << '[' << ctx_ << ',' << ((active_) ? "" : "!") << "active" << ']';
      }

      /* explicit */
      base::base(context::device& a)
        : support::printable       (),
          support::refcounted<base>(),
          ctx_                     (a),
          active_                  (true)
      {
        TRACE("hugh::render::stage::base::base");
      }

      /* virtual */ void
      base::do_execute(context::swap&)
      {
        TRACE("hugh::render::stage::base::do_execute");

        throw std::logic_error("pure virtual function "
                               "'hugh::render::stage::base::do_execute'"
                               " called");
      }

    } // namespace stage {

  } // namespace render {

} // namespace hugh {
<|endoftext|>


<commit_before>/*
    Copyright 2012 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    EVENT SHALL JOE HERMASZEWSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "type_properties.hpp"

#include <map>
#include <string>
#include <vector>

#include <llvm/Type.h>
#include <llvm/DerivedTypes.h>

#include <compiler/tokens/expression.hpp>
#include <engine/types.hpp>

namespace JoeLang
{

Type GetCommonType( Type t1, Type t2 )
{
    const static std::vector<Type> promotion_ordering =
    {
        Type::DOUBLE,
        Type::FLOAT,
        Type::U64,
        Type::I64,
        Type::U32,
        Type::I32,
        Type::U16,
        Type::I16,
        Type::U8,
        Type::I8,
        Type::BOOL
    };

    if( t1 == Type::STRING )
    {
        if( t2 == Type::STRING )
            return Type::STRING;
        else
            return Type::UNKNOWN;
    }

    if( t1 == Type::ARRAY )
    {
        return Type::UNKNOWN;
    }

    for( Type t : promotion_ordering )
        if( t1 == t || t2 == t )
            return t;

    assert( false && "Trying to get the common type of unknown types" );
    return Type::UNKNOWN;
}

bool IsIntegral( Type t )
{
    return t == Type::BOOL ||
           t == Type::I8   ||
           t == Type::I16  ||
           t == Type::I32  ||
           t == Type::I64  ||
           t == Type::U8   ||
           t == Type::U16  ||
           t == Type::U32  ||
           t == Type::U64;
}

bool IsFloatingPoint( Type t )
{
    return t == Type::DOUBLE ||
           t == Type::FLOAT;
}

bool IsSigned( Type t )
{
    return t == Type::I64 ||
           t == Type::I32 ||
           t == Type::I16 ||
           t == Type::I8;
}

bool IsVectorType( Type t )
{
    return t == Type::FLOAT4;
}

unsigned GetVectorSize( Type t )
{
    switch( t )
    {
    case Type::FLOAT4:
        return 4;
    default:
        assert( false && "Trying to get the vector size of a non-vector type" );
    }
    return 0;
}

Type GetVectorBaseType( Type t )
{
    switch( t )
    {
    case Type::FLOAT4:
        return Type::FLOAT;
    default:
        assert( false && "Trying to get the vector base of a non-vector type" );
    }
    return Type::UNKNOWN;
}

std::size_t SizeOf( Type t )
{
    if( t == Type::DOUBLE ||
        t == Type::U64 ||
        t == Type::I64 )
        return 8;

    if( t == Type::FLOAT ||
        t == Type::U32 ||
        t == Type::I32 )
        return 4;

    if( t == Type::U16 ||
        t == Type::I16 )
        return 2;

    if( t == Type::U8 ||
        t == Type::I8 ||
        t == Type::BOOL )
        return 1;

    return 0;
}

Type MakeUnsigned( Type t )
{
    assert( IsIntegral( t ) && t != Type::BOOL &&
            "Trying to make an invalid type unsigned" );
    switch( t )
    {
    case Type::I8:
        return Type::U8;
    case Type::I16:
        return Type::U16;
    case Type::I32:
        return Type::U32;
    case Type::I64:
        return Type::U64;
    default:
        // t is already unsigned;
        return t;
    }
}

const std::string& GetTypeString( Type t )
{
    const static std::map<Type, std::string> string_map =
    {
        { Type::UNKNOWN, "unknown type" },
        { Type::DOUBLE,       "double" },
        { Type::FLOAT,        "float" },
        { Type::U64,          "u64" },
        { Type::I64,          "i64" },
        { Type::U32,          "u32" },
        { Type::I32,          "i32" },
        { Type::U16,          "u16" },
        { Type::I16,          "i16" },
        { Type::U8,           "u8" },
        { Type::I8,           "i8" },
        { Type::BOOL,         "bool" },
        { Type::STRING,       "string" },
        { Type::ARRAY,        "array" },
    };

    return string_map.at(t);
}

} // namespace JoeLang
<commit_msg>[~] Clean up<commit_after>/*
    Copyright 2012 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    EVENT SHALL JOE HERMASZEWSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "type_properties.hpp"

#include <map>
#include <string>
#include <vector>

#include <llvm/Type.h>
#include <llvm/DerivedTypes.h>

#include <compiler/tokens/expression.hpp>
#include <engine/types.hpp>

namespace JoeLang
{

Type GetCommonType( Type t1, Type t2 )
{
    const static std::vector<Type> promotion_ordering =
    {
        Type::DOUBLE,
        Type::FLOAT,
        Type::U64,
        Type::I64,
        Type::U32,
        Type::I32,
        Type::U16,
        Type::I16,
        Type::U8,
        Type::I8,
        Type::BOOL
    };

    if( t1 == Type::STRING )
    {
        if( t2 == Type::STRING )
            return Type::STRING;
        else
            return Type::UNKNOWN;
    }

    if( t1 == Type::ARRAY )
    {
        return Type::UNKNOWN;
    }

    for( Type t : promotion_ordering )
        if( t1 == t || t2 == t )
            return t;

    assert( false && "Trying to get the common type of unknown types" );
    return Type::UNKNOWN;
}

bool IsIntegral( Type t )
{
    return t == Type::BOOL ||
           t == Type::I8   ||
           t == Type::I16  ||
           t == Type::I32  ||
           t == Type::I64  ||
           t == Type::U8   ||
           t == Type::U16  ||
           t == Type::U32  ||
           t == Type::U64;
}

bool IsFloatingPoint( Type t )
{
    return t == Type::DOUBLE ||
           t == Type::FLOAT ||
           t == Type::FLOAT4;
}

bool IsSigned( Type t )
{
    return t == Type::I64 ||
           t == Type::I32 ||
           t == Type::I16 ||
           t == Type::I8;
}

bool IsVectorType( Type t )
{
    return t == Type::FLOAT4;
}

unsigned GetVectorSize( Type t )
{
    switch( t )
    {
    case Type::FLOAT4:
        return 4;
    default:
        assert( false && "Trying to get the vector size of a non-vector type" );
    }
    return 0;
}

Type GetVectorBaseType( Type t )
{
    switch( t )
    {
    case Type::FLOAT4:
        return Type::FLOAT;
    default:
        assert( false && "Trying to get the vector base of a non-vector type" );
    }
    return Type::UNKNOWN;
}

std::size_t SizeOf( Type t )
{
    switch( t )
    {
    case Type::FLOAT4:
        return 16;
    case Type::DOUBLE:
    case Type::U64:
    case Type::I64:
        return 8;
    case Type::FLOAT:
    case Type::U32:
    case Type::I32:
        return 4;
    case Type::U16:
    case Type::I16:
        return 2;
    case Type::U8:
    case Type::I8:
    case Type::BOOL:
        return 1;
    default:
        assert( false && "Trying to get the size of an unhandled type" );
    }
    return 0;
}

Type MakeUnsigned( Type t )
{
    assert( IsIntegral( t ) && t != Type::BOOL &&
            "Trying to make an invalid type unsigned" );
    switch( t )
    {
    case Type::I8:
        return Type::U8;
    case Type::I16:
        return Type::U16;
    case Type::I32:
        return Type::U32;
    case Type::I64:
        return Type::U64;
    default:
        // t is already unsigned;
        return t;
    }
}

const std::string& GetTypeString( Type t )
{
    const static std::map<Type, std::string> string_map =
    {
        { Type::UNKNOWN, "unknown type" },
        { Type::DOUBLE,       "double" },
        { Type::FLOAT,        "float" },
        { Type::U64,          "u64" },
        { Type::I64,          "i64" },
        { Type::U32,          "u32" },
        { Type::I32,          "i32" },
        { Type::U16,          "u16" },
        { Type::I16,          "i16" },
        { Type::U8,           "u8" },
        { Type::I8,           "i8" },
        { Type::BOOL,         "bool" },
        { Type::STRING,       "string" },
        { Type::ARRAY,        "array" },
    };

    return string_map.at(t);
}

} // namespace JoeLang
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of the Qt Build Suite
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file.
** Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**************************************************************************/

#include "persistence.h"
#include "fileinfo.h"
#include <QtCore/QDir>
#include <stdio.h>

namespace qbs {

static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE0_0_1__4";

PersistentPool::PersistentPool()
{
}

PersistentPool::~PersistentPool()
{
}

bool PersistentPool::load(const QString &filePath, const LoadMode loadMode)
{
    QFile file(filePath);
    if (!file.open(QFile::ReadOnly))
        return false;
    QDataStream s(&file);

    QByteArray magic;
    s >> magic;
    if (magic != QBS_PERSISTENCE_MAGIC) {
        file.close();
        file.remove();
        return false;
    }

    s >> m_headData.projectConfig;
    if (loadMode == LoadHeadData)
        return true;

    s >> m_stringStorage;
    m_inverseStringStorage.reserve(m_stringStorage.count());
    for (int i = m_stringStorage.count(); --i >= 0;)
        m_inverseStringStorage.insert(m_stringStorage.at(i), i);

    s >> m_storage;
    m_loadedRaw.reserve(m_storage.count());
    m_loaded.reserve(m_storage.count());
    return true;
}

bool PersistentPool::store(const QString &filePath)
{
    QString dirPath = FileInfo::path(filePath);
    if (!FileInfo::exists(dirPath))
        if (!QDir().mkpath(dirPath))
            return false;

    if (QFile::exists(filePath) && !QFile::remove(filePath))
        return false;
    Q_ASSERT(!QFile::exists(filePath));
    QFile file(filePath);
    if (!file.open(QFile::WriteOnly))
        return false;

    QDataStream s(&file);
    s << QByteArray(QBS_PERSISTENCE_MAGIC);
    s << m_headData.projectConfig;
    s << m_stringStorage;
    s << m_storage;
    return true;
}

PersistentObjectId PersistentPool::store(PersistentObject *object)
{
    if (!object)
        return 0;
    PersistentObjectId id = m_storageIndices.value(object, -1);
    if (id < 0) {
        PersistentObjectData data;
        id = qMax(m_storage.count(), m_maxReservedId + 1);
        m_storageIndices.insert(object, id);
        m_storage.resize(id + 1);
        m_storage[id] = data;
        object->store(*this, data);
        m_storage[id] = data;
    }
    return id;
}

void PersistentPool::clear()
{
    m_loaded.clear();
    m_storage.clear();
    m_storageIndices.clear();
    m_stringStorage.clear();
    m_inverseStringStorage.clear();
}

PersistentObjectData PersistentPool::getData(PersistentObjectId id) const
{
    return m_storage.at(id);
}

void PersistentPool::setData(PersistentObjectId id, PersistentObjectData data)
{
    Q_ASSERT(id <= m_maxReservedId);
    if (id >= m_storage.count())
        m_storage.resize(id + 1);
    m_storage[id] = data;
}

int PersistentPool::storeString(const QString &t)
{
    if (t.isEmpty())
        return 0;
    int id = m_inverseStringStorage.value(t, -1);
    if (id < 0) {
        id = m_stringStorage.count();
        m_inverseStringStorage.insert(t, id);
        m_stringStorage.append(t);
    }
    return id;
}

QString PersistentPool::loadString(int id)
{
    if (id == 0)
        return QString();

    if (id < 0 || id >= m_stringStorage.count())
        throw Error(QString("storage error: no string id %1 stored.").arg(id));

    return m_stringStorage.at(id);
}

QString PersistentPool::idLoadString(QDataStream &s)
{
    int id;
    s >> id;
    return loadString(id);
}

QList<int> PersistentPool::storeStringSet(const QSet<QString> &t)
{
    QList<int> r;
    r.reserve(t.count());
    foreach (const QString &s, t)
        r += storeString(s);
    return r;
}

QSet<QString> PersistentPool::loadStringSet(const QList<int> &ids)
{
    QSet<QString> r;
    r.reserve(ids.count());
    foreach (int id, ids)
        r.insert(loadString(id));
    return r;
}

QSet<QString> PersistentPool::idLoadStringSet(QDataStream &s)
{
    QList<int> list;
    s >> list;
    return loadStringSet(list);
}

QList<int> PersistentPool::storeStringList(const QStringList &t)
{
    QList<int> r;
    r.reserve(t.count());
    foreach (const QString &s, t)
        r += storeString(s);
    return r;
}

QStringList PersistentPool::loadStringList(const QList<int> &ids)
{
    QStringList result;
    result.reserve(ids.count());
    foreach (const int &id, ids)
        result.append(loadString(id));
    return result;
}

QStringList PersistentPool::idLoadStringList(QDataStream &s)
{
    QList<int> list;
    s >> list;
    return loadStringList(list);
}

} // namespace qbs
<commit_msg>fix string serialization in stored BG<commit_after>/**************************************************************************
**
** This file is part of the Qt Build Suite
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file.
** Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**************************************************************************/

#include "persistence.h"
#include "fileinfo.h"
#include <QtCore/QDir>
#include <stdio.h>

namespace qbs {

static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE0_0_1__4";

PersistentPool::PersistentPool()
{
}

PersistentPool::~PersistentPool()
{
}

bool PersistentPool::load(const QString &filePath, const LoadMode loadMode)
{
    QFile file(filePath);
    if (!file.open(QFile::ReadOnly))
        return false;
    QDataStream s(&file);

    QByteArray magic;
    s >> magic;
    if (magic != QBS_PERSISTENCE_MAGIC) {
        file.close();
        file.remove();
        return false;
    }

    s >> m_headData.projectConfig;
    if (loadMode == LoadHeadData)
        return true;

    s >> m_stringStorage;
    m_inverseStringStorage.reserve(m_stringStorage.count());
    for (int i = m_stringStorage.count(); --i >= 0;)
        m_inverseStringStorage.insert(m_stringStorage.at(i), i);

    s >> m_storage;
    m_loadedRaw.reserve(m_storage.count());
    m_loaded.reserve(m_storage.count());
    return true;
}

bool PersistentPool::store(const QString &filePath)
{
    QString dirPath = FileInfo::path(filePath);
    if (!FileInfo::exists(dirPath))
        if (!QDir().mkpath(dirPath))
            return false;

    if (QFile::exists(filePath) && !QFile::remove(filePath))
        return false;
    Q_ASSERT(!QFile::exists(filePath));
    QFile file(filePath);
    if (!file.open(QFile::WriteOnly))
        return false;

    QDataStream s(&file);
    s << QByteArray(QBS_PERSISTENCE_MAGIC);
    s << m_headData.projectConfig;
    s << m_stringStorage;
    s << m_storage;
    return true;
}

PersistentObjectId PersistentPool::store(PersistentObject *object)
{
    if (!object)
        return 0;
    PersistentObjectId id = m_storageIndices.value(object, -1);
    if (id < 0) {
        PersistentObjectData data;
        id = qMax(m_storage.count(), m_maxReservedId + 1);
        m_storageIndices.insert(object, id);
        m_storage.resize(id + 1);
        m_storage[id] = data;
        object->store(*this, data);
        m_storage[id] = data;
    }
    return id;
}

void PersistentPool::clear()
{
    m_loaded.clear();
    m_storage.clear();
    m_storageIndices.clear();
    m_stringStorage.clear();
    m_inverseStringStorage.clear();
}

PersistentObjectData PersistentPool::getData(PersistentObjectId id) const
{
    return m_storage.at(id);
}

void PersistentPool::setData(PersistentObjectId id, PersistentObjectData data)
{
    Q_ASSERT(id <= m_maxReservedId);
    if (id >= m_storage.count())
        m_storage.resize(id + 1);
    m_storage[id] = data;
}

int PersistentPool::storeString(const QString &t)
{
    int id = m_inverseStringStorage.value(t, -1);
    if (id < 0) {
        id = m_stringStorage.count();
        m_inverseStringStorage.insert(t, id);
        m_stringStorage.append(t);
    }
    return id;
}

QString PersistentPool::loadString(int id)
{
    if (id < 0 || id >= m_stringStorage.count())
        throw Error(QString("storage error: no string id %1 stored.").arg(id));

    return m_stringStorage.at(id);
}

QString PersistentPool::idLoadString(QDataStream &s)
{
    int id;
    s >> id;
    return loadString(id);
}

QList<int> PersistentPool::storeStringSet(const QSet<QString> &t)
{
    QList<int> r;
    r.reserve(t.count());
    foreach (const QString &s, t)
        r += storeString(s);
    return r;
}

QSet<QString> PersistentPool::loadStringSet(const QList<int> &ids)
{
    QSet<QString> r;
    r.reserve(ids.count());
    foreach (int id, ids)
        r.insert(loadString(id));
    return r;
}

QSet<QString> PersistentPool::idLoadStringSet(QDataStream &s)
{
    QList<int> list;
    s >> list;
    return loadStringSet(list);
}

QList<int> PersistentPool::storeStringList(const QStringList &t)
{
    QList<int> r;
    r.reserve(t.count());
    foreach (const QString &s, t)
        r += storeString(s);
    return r;
}

QStringList PersistentPool::loadStringList(const QList<int> &ids)
{
    QStringList result;
    result.reserve(ids.count());
    foreach (const int &id, ids)
        result.append(loadString(id));
    return result;
}

QStringList PersistentPool::idLoadStringList(QDataStream &s)
{
    QList<int> list;
    s >> list;
    return loadStringList(list);
}

} // namespace qbs
<|endoftext|>