<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tk_docw2.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2007-09-18 14:25:53 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <precomp.h>
#include <s2_dsapi/tk_docw2.hxx>

// NOT FULLY DEFINED SERVICES
#include <s2_dsapi/tokintpr.hxx>

namespace csi
{
namespace dsapi
{

void
Tok_Word::Trigger( TokenInterpreter &   io_rInterpreter ) const
{
    io_rInterpreter.Process_Word(*this);
}

const char *
Tok_Word::Text() const
{
    return sText;
}

void
Tok_Comma::Trigger( TokenInterpreter &  io_rInterpreter ) const
{
    io_rInterpreter.Process_Comma();
}

const char *
Tok_Comma::Text() const
{
    return ",";
}

void
Tok_DocuEnd::Trigger( TokenInterpreter &    io_rInterpreter ) const
{
    io_rInterpreter.Process_DocuEnd();
}

const char *
Tok_DocuEnd::Text() const
{
    return "*/";
}

void
Tok_EOL::Trigger( TokenInterpreter &    io_rInterpreter ) const
{
    io_rInterpreter.Process_EOL();
}

const char *
Tok_EOL::Text() const
{
    return "\r\n";
}

void
Tok_EOF::Trigger( TokenInterpreter & ) const
{
    csv_assert(false);
}

const char *
Tok_EOF::Text() const
{
    return "";
}

void
Tok_White::Trigger( TokenInterpreter &  io_rInterpreter ) const
{
    io_rInterpreter.Process_White();
}

const char *
Tok_White::Text() const
{
    return " ";
}

}   // namespace dsapi
}   // namespace csi

<commit_msg>INTEGRATION: CWS changefileheader (1.5.26); FILE MERGED 2008/03/28 16:02:49 rt 1.5.26.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: tk_docw2.cxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <precomp.h>
#include <s2_dsapi/tk_docw2.hxx>

// NOT FULLY DEFINED SERVICES
#include <s2_dsapi/tokintpr.hxx>

namespace csi
{
namespace dsapi
{

void
Tok_Word::Trigger( TokenInterpreter &   io_rInterpreter ) const
{
    io_rInterpreter.Process_Word(*this);
}

const char *
Tok_Word::Text() const
{
    return sText;
}

void
Tok_Comma::Trigger( TokenInterpreter &  io_rInterpreter ) const
{
    io_rInterpreter.Process_Comma();
}

const char *
Tok_Comma::Text() const
{
    return ",";
}

void
Tok_DocuEnd::Trigger( TokenInterpreter &    io_rInterpreter ) const
{
    io_rInterpreter.Process_DocuEnd();
}

const char *
Tok_DocuEnd::Text() const
{
    return "*/";
}

void
Tok_EOL::Trigger( TokenInterpreter &    io_rInterpreter ) const
{
    io_rInterpreter.Process_EOL();
}

const char *
Tok_EOL::Text() const
{
    return "\r\n";
}

void
Tok_EOF::Trigger( TokenInterpreter & ) const
{
    csv_assert(false);
}

const char *
Tok_EOF::Text() const
{
    return "";
}

void
Tok_White::Trigger( TokenInterpreter &  io_rInterpreter ) const
{
    io_rInterpreter.Process_White();
}

const char *
Tok_White::Text() const
{
    return " ";
}

}   // namespace dsapi
}   // namespace csi

<|endoftext|>


<commit_before>939b67d7-ad5b-11e7-8efc-ac87a332f658<commit_msg>Bug fixes and performance improvements<commit_after>94121457-ad5b-11e7-83ae-ac87a332f658<|endoftext|>


<commit_before>
#include <iostream>
#include <cstring>
#include <cassert>

#include "csprot.hpp"

using csprot::operator"" _S;
using csprot::operator"" _XS;

#define TEST(...) \
	static_assert(__VA_ARGS__, #__VA_ARGS__)

/**************************************************************************/

void test_prop() {
	TEST("1"_S.is_plain() == true);
	TEST("1"_S.is_xored() == false);
	TEST("1"_XS.is_plain() == false);
	TEST("1"_XS.is_xored() == true);
}

void test_size() {
	TEST(""_S.size() == 0 && ""_S.length() == 0 && ""_S.empty() == true);
	TEST("1"_S.size() == 1 && "1"_S.length() == 1 && "1"_S.empty() == false);
}

void test_cat() {
	struct {
		constexpr int operator()(const char *a, const char *b) const {
			return
				*a == 0 && *b == 0 ? 0 :
				*a == 0 ? -1 :
				*b == 0 ? 1 :
				*a < *b ? -1 :
				*a > *b ? 1 :
				*a == *b ? operator()(a+1, b+1) : throw "compare::operator(a, b) error";
		}
	} compare{};

	auto s0 = "1"_S + "2"_S;
	TEST(compare(s0.c_str(), "12") == 0);
}

void test_compare() {
	TEST("1"_S == "1"_S);
	TEST("1"_XS == "1"_XS);
	TEST("1"_S != "1"_XS);
	TEST("1"_S == "1"_S);
	TEST("1"_S != "2"_S);
	TEST(""_S == ""_S);
}

void test_xored_string() {
	TEST("1"_S.data()[0] == '1');
	TEST("1"_XS.data()[0] != '1');
}

/**************************************************************************/

template<typename>
struct impl;

using posix_type = decltype("posix implementation"_XS);
using win32_type = decltype("win32 implementation"_XS);

template<>
struct impl<posix_type> {
	static constexpr auto name = posix_type();
};
template<>
struct impl<win32_type> {
	static constexpr auto name = win32_type();
};

void test_templspec() {
	impl<win32_type> impl;
	TEST(impl.name == "win32 implementation"_XS);
}

/**************************************************************************/

int main() {
	test_prop();
	test_size();
	test_cat();
	test_compare();
	test_xored_string();
	test_templspec();

	auto s0 = "some xor`ed string 0"_XS;
	assert(std::strcmp(s0.data (), "some xor`ed string 0") != 0);
	assert(std::strcmp(s0.c_str(), "some xor`ed string 0") == 0);
	std::cout << "s0.data()=" << s0.data() << std::endl;
	std::cout << "s0.c_str()=" << s0.c_str() << std::endl;

	auto s1 = "some plain string 0"_S;
	assert(std::strcmp(s1.data (), "some plain string 0") == 0);
	assert(std::strcmp(s1.c_str(), "some plain string 0") == 0);
	std::cout << "s1.data()=" << s1.data() << std::endl;
	std::cout << "s1.c_str()=" << s1.c_str() << std::endl;
}

/**************************************************************************/
<commit_msg>fixes<commit_after>
#include <iostream>
#include <cstring>
#include <cassert>

#include "csprot.hpp"

using csprot::operator"" _S;
using csprot::operator"" _XS;

#define TEST(...) \
	static_assert(__VA_ARGS__, #__VA_ARGS__)

/**************************************************************************/

void test_prop() {
	TEST("1"_S.is_plain() == true);
	TEST("1"_S.is_xored() == false);
	TEST("1"_XS.is_plain() == false);
	TEST("1"_XS.is_xored() == true);
}

void test_size() {
	TEST(""_S.size() == 0 && ""_S.length() == 0 && ""_S.empty() == true);
	TEST("1"_S.size() == 1 && "1"_S.length() == 1 && "1"_S.empty() == false);
}

void test_cat() {
	struct {
		constexpr int operator()(const char *a, const char *b) const {
			return
				*a == 0 && *b == 0 ? 0 :
				*a == 0 ? -1 :
				*b == 0 ? 1 :
				*a < *b ? -1 :
				*a > *b ? 1 :
				*a == *b ? operator()(a+1, b+1) : throw "compare::operator(a, b) error";
		}
	} compare{};

	auto s0 = "1"_S + "2"_S;
	TEST(compare(s0.c_str(), "12") == 0);
}

void test_compare() {
	TEST("1"_S == "1"_S);
	TEST("1"_XS == "1"_XS);
	TEST("1"_S != "1"_XS);
	TEST("1"_S == "1"_S);
	TEST("1"_S != "2"_S);
	TEST(""_S == ""_S);
}

void test_xored_string() {
	TEST("1"_S.data()[0] == '1');
	TEST("1"_XS.data()[0] != '1');
}

/**************************************************************************/

#define _CAT2(x, y) x##y
#define _CAT(x, y) _CAT2(x, y)
#define CSPROT_TAG(x) decltype(_CAT(x, _XS))

template<typename>
struct impl;

using posix_tag = CSPROT_TAG("posix implementation");
using win32_tag = CSPROT_TAG("win32 implementation");

template<>
struct impl<posix_tag> {
	static constexpr auto name = posix_tag();
};
template<>
struct impl<win32_tag> {
	static constexpr auto name = win32_tag();
};

void test_templspec() {
	impl<win32_tag> impl;
	TEST(impl.name == win32_tag());
}

/**************************************************************************/

int main() {
	test_prop();
	test_size();
	test_cat();
	test_compare();
	test_xored_string();
	test_templspec();

	auto s0 = "some xor`ed string 0"_XS;
	assert(std::strcmp(s0.data (), "some xor`ed string 0") != 0);
	assert(std::strcmp(s0.c_str(), "some xor`ed string 0") == 0);
	std::cout << "s0.data()=" << s0.data() << std::endl;
	std::cout << "s0.c_str()=" << s0.c_str() << std::endl;

	auto s1 = "some plain string 0"_S;
	assert(std::strcmp(s1.data (), "some plain string 0") == 0);
	assert(std::strcmp(s1.c_str(), "some plain string 0") == 0);
	std::cout << "s1.data()=" << s1.data() << std::endl;
	std::cout << "s1.c_str()=" << s1.c_str() << std::endl;
}

/**************************************************************************/
<|endoftext|>


<commit_before>6ffba466-4b02-11e5-8b65-28cfe9171a43<commit_msg>That didn't fix it<commit_after>70089e14-4b02-11e5-a7fc-28cfe9171a43<|endoftext|>


<commit_before>#include <iostream>
#include <memory>
#include "include/Logger.hpp"
#include "include/LoggingPolicyFile.hpp"
#include "include/ConfigurationManager.hpp"
#include "include/GlobalFileLogger.hpp"

using namespace clc;
using namespace clb;

int main()
{

    std::unique_ptr<LoggingPolicyFile> uPtr(new LoggingPolicyFile("./", "test"));
    Logger<LoggingPolicyFile> logger(std::move(uPtr), SeverityLevel::ALL);
    GlobalFileLogger::init();

    for (size_t i = 0; i < 100; i++)
    {
        logger.log(SeverityType::INFO, "Info: ", i);
        GlobalFileLogger::instance()->log(SeverityType::DEBUG, "test", i);
    }

    logger.log(SeverityType::WARNING, "File: ", __FILE__);
    logger.log(SeverityType::WARNING, "Definition Exe Version: ", (CLUSTERER_VERSION));
    logger.log(SeverityType::WARNING, "Definition Exe Version FUll: ", CLUSTERER_VERSION_FULL);

    logger.log(SeverityType::WARNING, "Definition Lib Version: ", CLUSTERER_LIB_VERSION);
    logger.log(SeverityType::WARNING, "Definition Lib Version FUll: ", CLUSTERER_LIB_VERSION_FULL);

    ConfigurationManager cfg;
    cfg.saveClusteringParams("config1.txt");
    cfg.setMaxFitness(11235467889.000);
    cfg.saveClusteringParams("config2.txt");
    cfg.loadClusteringParams("config2.txt");

    return 0;
}<commit_msg>Added main file that shows a bit more of the implemented functionality.<commit_after>#include <iostream>
#include <cstdlib>
#include <iostream>
#include <memory>
#include "include/Vertex.hpp"
#include "include/AbstractGraph.hpp"
#include "include/Graph.hpp"
#include "include/GraphReader.hpp"
#include "include/Logger.hpp"
#include "include/LoggingPolicyFile.hpp"
#include "include/ConfigurationManager.hpp"
#include "include/GlobalFileLogger.hpp"

using namespace clc;
using namespace clb;

int main()
{

    std::unique_ptr<LoggingPolicyFile> uPtr(new LoggingPolicyFile("./", "test"));
    Logger<LoggingPolicyFile> logger(std::move(uPtr), SeverityLevel::ALL);
    GlobalFileLogger::init();

    for (size_t i = 0; i < 100; i++)
    {
        logger.log(SeverityType::INFO, "Info: ", i);
        GlobalFileLogger::instance()->log(SeverityType::DEBUG, "test", i);
    }

    Graph g;
    GraphReader gr(&g);
    gr.readFile("../test_files/out.ucidata-zachary");
    // can be replaced with "test_files/out.ucidata-zachary"

    std::cout << "number of edges: " << g.getNoEdges() << "\n";
    std::cout << "number of vertices: " << g.getNoVertices() << "\n";

    std::vector<std::pair<VertexId, VertexId>> edges = g.getEdges();

    std::cout << "edges: \n";
    std::vector<std::pair<VertexId, VertexId>>::iterator it;
    for (it = edges.begin(); it != edges.end(); ++it)
    {
        std::cout << (*it).first << " " << (*it).second << "\n";
    }

    std::cout << "vertices: \n";
    std::vector<VertexId> vec = g.getVertices();

    std::vector<VertexId>::iterator it2;
    for (auto t : vec)
    {
        std::cout << t << " ";
    }
    std::cout << "\n";

    std::vector<std::pair<std::pair<VertexId, VertexId>, double>> wedges = g.getEdgesAndWeights();

    std::cout << "edges: \n";
    std::vector<std::pair<std::pair<VertexId, VertexId>, double>>::iterator wit;
    for (wit = wedges.begin(); wit != wedges.end(); ++wit)
    {
        std::cout << (*wit).first.first << " " << (*wit).first.second;
        std::cout << " with weight: " << (*wit).second << "\n";
    }

    logger.log(SeverityType::WARNING, "File: ", __FILE__);
    logger.log(SeverityType::WARNING, "Definition Exe Version: ", (CLUSTERER_VERSION));
    logger.log(SeverityType::WARNING, "Definition Exe Version FUll: ", CLUSTERER_VERSION_FULL);

    logger.log(SeverityType::WARNING, "Definition Lib Version: ", CLUSTERER_LIB_VERSION);
    logger.log(SeverityType::WARNING, "Definition Lib Version FUll: ", CLUSTERER_LIB_VERSION_FULL);

    ConfigurationManager cfg;
    cfg.saveClusteringParams("config1.txt");
    cfg.setMaxFitness(11235467889.000);
    cfg.saveClusteringParams("config2.txt");
    cfg.loadClusteringParams("config2.txt");

    return 0;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <thread>
#include <mutex>

// TODO: test if a thread has an infinite cycle

constexpr int ASSIGNMENT_SCALE = 1000000;

using namespace std;

/**
 * Our big number type
 */
typedef unsigned long long int BigInt;

/**
 * Split declaration from initialisation: supportedThreads not const enough
 * according to g++ (idk why it doesn't work)
 */
const unsigned supportedThreads = thread::hardware_concurrency();
thread *threads;

/**
 * This mutex ensures that the writes on stdout don't get mixed
 */
std::mutex output_mutex;

/**
 * This mutex ensures that assign functions are not called simultaneously
 */
std::mutex assign_mutex;

/**
 *  Stores what to assign next
 */
BigInt next_assignment_start = 0;
BigInt next_assignment_end;

/**
 * Already checked values
 */
BigInt lower_boundary = 0;

/**
 * Do Collatz algorithm on the number
 *
 * @param numberToTest Number to enumerate
 */
inline void enumerateNumber(BigInt numberToTest) {
    while (numberToTest != 1) {
        if (numberToTest % 2 == 0) {
            numberToTest = numberToTest >> 1;
        } else {
            numberToTest *= 3;
            numberToTest++;
        }

        if (numberToTest < lower_boundary)
            return;
    }
}

/**
 * Returns an assignment for a thread
 * The pointers must be initialized. The values pointed will be filled.
 * The assignment means that x must be tested if start <= x < end
 */
void getAssignment(BigInt *start, BigInt *end) {
    std::lock_guard<std::mutex> lock(assign_mutex);
    lower_boundary = *end;

    if (next_assignment_start == -1) {
        next_assignment_start = 2;
        next_assignment_end = ASSIGNMENT_SCALE;
    } else {
        next_assignment_start = next_assignment_end;
        next_assignment_end += ASSIGNMENT_SCALE;
    }
    *start = next_assignment_start;
    *end = next_assignment_end;
}

/**
 * A thread worker. This should never ends.
 */
void launchThread() {
    BigInt start, end;
    while (true) {
        getAssignment(&start, &end);
        for (BigInt i = start; i < end; i++) {
            enumerateNumber(i);
        }
        std::lock_guard<std::mutex> lock(output_mutex);
        cout << "Assignment " << start << "-" << end << " complete!" << endl;
    }
}

/**
 * Entry point
 *
 * @return 0 or noting, in better case ;)
 */
int main() {
    ios::sync_with_stdio(false);

    cout << "Supported threads: " << supportedThreads << endl;
    cout << "Start program" << endl;

    threads = new thread[supportedThreads];
    for (int i = 0; i < supportedThreads; i++) {
        threads[i] = thread(launchThread);
    }

    for (int i = 0; i < supportedThreads; i++) {
        threads[i].join();
        cerr << "Thread #" << i << " joined." << endl;
    }

    cerr << "END" << endl;

    delete[] threads;

    return 0;
}
<commit_msg>Minor optimisations<commit_after>#include <iostream>
#include <thread>
#include <mutex>

// TODO: test if a thread has an infinite cycle

constexpr int ASSIGNMENT_SCALE = 1000000;

using namespace std;

/**
 * Our big number type
 */
typedef unsigned long long int BigInt;

/**
 * Split declaration from initialisation: supportedThreads not const enough
 * according to g++ (idk why it doesn't work)
 */
const unsigned supportedThreads = thread::hardware_concurrency();
thread *threads;

/**
 * This mutex ensures that the writes on stdout don't get mixed
 */
std::mutex output_mutex;

/**
 * This mutex ensures that assign functions are not called simultaneously
 */
std::mutex assign_mutex;

/**
 *  Stores what to assign next
 */
BigInt next_assignment_start = 0;
BigInt next_assignment_end;

/**
 * Already checked values
 * initially 2 for minor optimisation (see enumerateNumber)
 */
BigInt lower_boundary = 2;

/**
 * Do Collatz algorithm on the number
 *
 * @param numberToTest Number to enumerate
 */
inline void enumerateNumber(BigInt numberToTest) {
    /**
     * Lower_boundary is 2, so it always stops if the numberToTest is 1
     */
    while (numberToTest >= lower_boundary) {
        if (numberToTest % 2 == 0) {
            numberToTest = numberToTest >> 1;
        } else {
            numberToTest *= 3;
            numberToTest++;
            /**
             * Minor optimisation: numberToTest is always even here and does
             * not change stopping condition
             */
            numberToTest = numberToTest >> 1;
        }
    }
}

/**
 * Returns an assignment for a thread
 * The pointers must be initialized. The values pointed will be filled.
 * The assignment means that x must be tested if start <= x < end
 */
void getAssignment(BigInt *start, BigInt *end) {
    std::lock_guard<std::mutex> lock(assign_mutex);
    lower_boundary = *end;

    if (next_assignment_start == -1) {
        next_assignment_start = 2;
        next_assignment_end = ASSIGNMENT_SCALE;
    } else {
        next_assignment_start = next_assignment_end;
        next_assignment_end += ASSIGNMENT_SCALE;
    }
    *start = next_assignment_start;
    *end = next_assignment_end;
}

/**
 * A thread worker. This should never ends.
 */
void launchThread() {
    BigInt start, end;
    while (true) {
        getAssignment(&start, &end);
        for (BigInt i = start; i < end; i++) {
            enumerateNumber(i);
        }
        std::lock_guard<std::mutex> lock(output_mutex);
        cout << "Assignment " << start << "-" << end << " complete!" << endl;
    }
}

/**
 * Entry point
 *
 * @return 0 or noting, in better case ;)
 */
int main() {
    ios::sync_with_stdio(false);

    cout << "Supported threads: " << supportedThreads << endl;
    cout << "Start program" << endl;

    threads = new thread[supportedThreads];
    for (int i = 0; i < supportedThreads; i++) {
        threads[i] = thread(launchThread);
    }

    for (int i = 0; i < supportedThreads; i++) {
        threads[i].join();
        cerr << "Thread #" << i << " joined." << endl;
    }

    cerr << "END" << endl;

    delete[] threads;

    return 0;
}
<|endoftext|>


<commit_before>c12df81c-2747-11e6-81d8-e0f84713e7b8<commit_msg>lets try again<commit_after>c13fe085-2747-11e6-9c10-e0f84713e7b8<|endoftext|>


<commit_before>/**
 * KQOAuth - An OAuth authentication library for Qt.
 *
 * Author: Johan Paul (johan.paul@d-pointer.com)
 *         http://www.d-pointer.com
 *
 *  KQOAuth is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  KQOAuth 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 Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with KQOAuth.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <QString>
#include <QCryptographicHash>
#include <QByteArray>

#include <QtDebug>
#include "kqoauthutils.h"

QString KQOAuthUtils::hmac_sha1(const QString &message, const QString &key)
{
    QByteArray keyBytes = key.toAscii();
    int keyLength;              // Lenght of key word
    const int blockSize = 64;   // Both MD5 and SHA-1 have a block size of 64.

    keyLength = keyBytes.size();
    // If key is longer than block size, we need to hash the key
    if (keyLength > blockSize) {
        QCryptographicHash hash(QCryptographicHash::Sha1);
        hash.addData(keyBytes);
        keyBytes = hash.result();
        keyLength = keyBytes.size();
    }

    /* http://tools.ietf.org/html/rfc2104  - (1) */
    // Create the opad and ipad for the hash function.
    QByteArray ipad;
    QByteArray opad;
    ipad.clear();
    ipad.clear();

    ipad.fill( 0, blockSize+1);
    opad.fill( 0, blockSize+1);

    ipad.replace(0, keyBytes.length(), keyBytes.constData());
    opad.replace(0, keyBytes.length(), keyBytes.constData());

    /* http://tools.ietf.org/html/rfc2104 - (2) & (5) */
    for (int i=0; i<64; i++) {
        ipad[i] = ipad[i] ^ 0x36;
        opad[i] = opad[i] ^ 0x5c;
    }

    QByteArray workArray;
    workArray.clear();

    workArray.append(ipad, 64);
    /* http://tools.ietf.org/html/rfc2104 - (3) */
    workArray.append(message.toAscii());

    /* http://tools.ietf.org/html/rfc2104 - (4) */
    QByteArray sha1 = QCryptographicHash::hash(workArray, QCryptographicHash::Sha1);

    /* http://tools.ietf.org/html/rfc2104 - (6) */
    workArray.clear();
    workArray.append(opad, 64);
    workArray.append(sha1);

    sha1.clear();

    /* http://tools.ietf.org/html/rfc2104 - (7) */
    sha1 = QCryptographicHash::hash(workArray, QCryptographicHash::Sha1);
    return QString(sha1.toBase64());
}
<commit_msg>Removed unnecessary code based on review by Ivan Kuznetsov.<commit_after>/**
 * KQOAuth - An OAuth authentication library for Qt.
 *
 * Author: Johan Paul (johan.paul@d-pointer.com)
 *         http://www.d-pointer.com
 *
 *  KQOAuth is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  KQOAuth 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 Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with KQOAuth.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <QString>
#include <QCryptographicHash>
#include <QByteArray>

#include <QtDebug>
#include "kqoauthutils.h"

QString KQOAuthUtils::hmac_sha1(const QString &message, const QString &key)
{
    QByteArray keyBytes = key.toAscii();
    int keyLength;              // Lenght of key word
    const int blockSize = 64;   // Both MD5 and SHA-1 have a block size of 64.

    keyLength = keyBytes.size();
    // If key is longer than block size, we need to hash the key
    if (keyLength > blockSize) {
        QCryptographicHash hash(QCryptographicHash::Sha1);
        hash.addData(keyBytes);
        keyBytes = hash.result();
    }

    /* http://tools.ietf.org/html/rfc2104  - (1) */
    // Create the opad and ipad for the hash function.
    QByteArray ipad;
    QByteArray opad;

    ipad.fill( 0, blockSize);
    opad.fill( 0, blockSize);

    ipad.replace(0, keyBytes.length(), keyBytes.constData());
    opad.replace(0, keyBytes.length(), keyBytes.constData());

    /* http://tools.ietf.org/html/rfc2104 - (2) & (5) */
    for (int i=0; i<64; i++) {
        ipad[i] = ipad[i] ^ 0x36;
        opad[i] = opad[i] ^ 0x5c;
    }

    QByteArray workArray;
    workArray.clear();

    workArray.append(ipad, 64);
    /* http://tools.ietf.org/html/rfc2104 - (3) */
    workArray.append(message.toAscii());

    /* http://tools.ietf.org/html/rfc2104 - (4) */
    QByteArray sha1 = QCryptographicHash::hash(workArray, QCryptographicHash::Sha1);

    /* http://tools.ietf.org/html/rfc2104 - (6) */
    workArray.clear();
    workArray.append(opad, 64);
    workArray.append(sha1);

    sha1.clear();

    /* http://tools.ietf.org/html/rfc2104 - (7) */
    sha1 = QCryptographicHash::hash(workArray, QCryptographicHash::Sha1);
    return QString(sha1.toBase64());
}
<|endoftext|>


<commit_before>8497a840-ad5a-11e7-981d-ac87a332f658<commit_msg>Introduced random NullPointerException bug<commit_after>8512a3eb-ad5a-11e7-bbe0-ac87a332f658<|endoftext|>


<commit_before>caa253de-2747-11e6-8f45-e0f84713e7b8<commit_msg>Fixed that one bug<commit_after>cac883e1-2747-11e6-b0cb-e0f84713e7b8<|endoftext|>


<commit_before>/*
 * Movie.cpp
 *
 *  Created on: Sep 25, 2009
 *      Author: travel
 */

#include "Movie.hpp"
#include "../io/imageio.hpp"
#include "../utils/pv_random.h"

#include <assert.h>
#include <stdio.h>
#include <string.h>

namespace PV {

Movie::Movie(const char * name, HyPerCol * hc, const char * fileOfFileNames, float displayPeriod)
     : Image(name, hc)
{
   PVLayerLoc * loc = &clayer->loc;

   this->displayPeriod = displayPeriod;
   this->nextDisplayTime = hc->simulationTime() + displayPeriod;

   fp = fopen(fileOfFileNames, "r");
   assert(fp != NULL);

   filename = strdup(getNextFileName());
   assert(filename != NULL);

   // get size info from image so that data buffer can be allocated
   int status = getImageInfo(filename, parent->icCommunicator(), &imageLoc);
   assert(status == 0);

   // create mpi_datatypes for border transfer
   mpi_datatypes = Communicator::newDatatypes(loc);

//   int N = imageLoc.nx * imageLoc.ny * imageLoc.nBands;
//   imageData = new float [N];
//   for (int i = 0; i < N; ++i) {
//      imageData[i] = 0;
//   }
   imageData = NULL;

   // need all image bands until converted to gray scale
   loc->nBands = imageLoc.nBands;

#ifdef OBSOLETE
   initialize_data(loc);

//   N = loc.nx * loc.ny * loc.nBands;
//   imageData = new float [N];
//   for (int i = 0; i < N; ++i) {
//      imageData[i] = 0;
//   }
//
#endif

   this->offsetX = imageLoc.nx / 2;
   this->offsetY = imageLoc.ny / 2;

   read(filename, offsetX, offsetY);

   // for now convert images to grayscale
   if (loc->nBands > 1) {
      toGrayScale();
   }

   // exchange border information
   exchange();
}

Movie::~Movie()
{
   if (imageData != NULL) {
      delete imageData;
      imageData = NULL;
   }
}

pvdata_t * Movie::getImageBuffer()
{
//   return imageData;
   return data;
}

PVLayerLoc Movie::getImageLoc()
{
//   return imageLoc;
   return clayer->loc;
}

int Movie::updateState(float time, float dt)
{
  updateImage(time, dt);
  return 0;
}

/**
 * update the image buffers
 *
 * return true if buffers have changed
 */
bool Movie::updateImage(float time, float dt)
{
   PVLayerLoc * loc = &clayer->loc;

   if (time >= nextDisplayTime) {
      if (filename != NULL) free(filename);
      filename = strdup(getNextFileName());
      assert(filename != NULL);
      nextDisplayTime += displayPeriod;
   }

   // need all image bands until converted to gray scale
   loc->nBands = imageLoc.nBands;

   int step = 2;
   offsetX = calcPosition(offsetX, step, imageLoc.nx - loc->nx);
   offsetY = calcPosition(offsetY, step, imageLoc.ny - loc->nx);

   read(filename, offsetX, offsetY);

   // for now convert images to grayscale
   if (loc->nBands > 1) {
      toGrayScale();
   }

   // exchange border information
   exchange();

   lastUpdateTime = time;

   return true;
}

int Movie::outputState(float time, bool last)
{
   if (writeImages) {
      char basicFilename[PV_PATH_MAX + 1];
      snprintf(basicFilename, PV_PATH_MAX, "./output/Movie_%f.tif", time);
      write(basicFilename);
   }
   return 0;
}

int Movie::copyReducedImagePortion()
{
   const PVLayerLoc * loc = getLayerLoc();

   const int nx = loc->nx;
   const int ny = loc->ny;

   const int nx0 = imageLoc.nx;
   const int ny0 = imageLoc.ny;

   assert(nx0 <= nx);
   assert(ny0 <= ny);

   const int i0 = nx/2 - nx0/2;
   const int j0 = ny/2 - ny0/2;

   int ii = 0;
   for (int j = j0; j < j0+ny0; j++) {
      for (int i = i0; i < i0+nx0; i++) {
         imageData[ii++] = data[i+nx*j];
      }
   }

   return 0;
}

const char * Movie::getNextFileName()
{
   int c;
   size_t len = PV_PATH_MAX;
   char * path;

   // if at end of file (EOF), rewind

   if ((c = fgetc(fp)) == EOF) {
      rewind(fp);
   }
   else {
      ungetc(c, fp);
   }

   path = fgets(this->inputfile, len, fp);

   if (path != NULL) {
      path[PV_PATH_MAX-1] = '\0';
      len = strlen(path);
      if (len > 1) {
         if (path[len-1] == '\n') {
             path[len-1] = '\0';
         }
      }
   }

   return path;
}

/**
 * Return an integer between 0 and (step-1)
 */
int Movie::calcPosition(int pos, int step, int sizeLength)
{
   const float dp = 1.0 / step;
   const double p = pv_random_prob();
   const int random_walk = 0;
   const int move_forward = 0;
   const int move_backward = 0;
   const int random_jump = 1;

   if (random_walk) {
      if (p < 0.5) {
         pos += step;
      } else {
         pos -= step;
      }
   } else if (move_forward) {
      pos += step;
   } else if (move_backward) {
      pos -= step;
   } else if (random_jump) {
      for (int i = 0; i < step; i++) {
         if ((i * dp < p) && (p < (i + 1) * dp)) {
            pos = (pv_random_prob() < 0.5) ? pos - i : pos + i;
         }
      }
   }

   pos = (pos < 0) ? -pos : pos;
   pos = (pos > sizeLength) ? sizeLength - (pos-sizeLength) : pos;

   return pos;
}

}
<commit_msg>Added resetPositionInBounds to ensure that offsets into image keep window on image within the image.<commit_after>/*
 * Movie.cpp
 *
 *  Created on: Sep 25, 2009
 *      Author: travel
 */

#include "Movie.hpp"
#include "../io/imageio.hpp"
#include "../utils/pv_random.h"

#include <assert.h>
#include <stdio.h>
#include <string.h>

namespace PV {

Movie::Movie(const char * name, HyPerCol * hc, const char * fileOfFileNames, float displayPeriod)
     : Image(name, hc)
{
   PVParams * params = parent->parameters();

   PVLayerLoc * loc = &clayer->loc;

   this->displayPeriod = displayPeriod;
   this->nextDisplayTime = hc->simulationTime() + displayPeriod;

   fp = fopen(fileOfFileNames, "r");
   assert(fp != NULL);

   filename = strdup(getNextFileName());
   assert(filename != NULL);

   // get size info from image so that data buffer can be allocated
   int status = getImageInfo(filename, parent->icCommunicator(), &imageLoc);
   assert(status == 0);

   // create mpi_datatypes for border transfer
   mpi_datatypes = Communicator::newDatatypes(loc);

//   int N = imageLoc.nx * imageLoc.ny * imageLoc.nBands;
//   imageData = new float [N];
//   for (int i = 0; i < N; ++i) {
//      imageData[i] = 0;
//   }
   imageData = NULL;

   // need all image bands until converted to gray scale
   loc->nBands = imageLoc.nBands;

#ifdef OBSOLETE
   initialize_data(loc);

//   N = loc.nx * loc.ny * loc.nBands;
//   imageData = new float [N];
//   for (int i = 0; i < N; ++i) {
//      imageData[i] = 0;
//   }
//
#endif

   offsetX = imageLoc.nx / 2;
   offsetY = imageLoc.ny / 2;

   offsetX = params->value(name, "offsetX", offsetX);
   offsetY = params->value(name, "offsetY", offsetY);
   resetPositionInBounds();  // ensure that offsets keep loc within image bounds

   read(filename, offsetX, offsetY);

   // for now convert images to grayscale
   if (loc->nBands > 1) {
      toGrayScale();
   }

   // exchange border information
   exchange();
}

Movie::~Movie()
{
   if (imageData != NULL) {
      delete imageData;
      imageData = NULL;
   }
}

pvdata_t * Movie::getImageBuffer()
{
//   return imageData;
   return data;
}

PVLayerLoc Movie::getImageLoc()
{
//   return imageLoc;
   return clayer->loc;
}

int Movie::updateState(float time, float dt)
{
  updateImage(time, dt);
  return 0;
}

/**
 * update the image buffers
 *
 * return true if buffers have changed
 */
bool Movie::updateImage(float time, float dt)
{
   PVLayerLoc * loc = &clayer->loc;

   if (time >= nextDisplayTime) {
      if (filename != NULL) free(filename);
      filename = strdup(getNextFileName());
      assert(filename != NULL);
      nextDisplayTime += displayPeriod;
   }

   // need all image bands until converted to gray scale
   loc->nBands = imageLoc.nBands;

   int step = 2;
   offsetX = calcPosition(offsetX, step, imageLoc.nx - loc->nx);
   offsetY = calcPosition(offsetY, step, imageLoc.ny - loc->ny);

   // ensure that offsets keep loc within image bounds
   resetPositionInBounds();

   read(filename, offsetX, offsetY);

   // for now convert images to grayscale
   if (loc->nBands > 1) {
      toGrayScale();
   }

   // exchange border information
   exchange();

   lastUpdateTime = time;

   return true;
}

int Movie::outputState(float time, bool last)
{
   if (writeImages) {
      char basicFilename[PV_PATH_MAX + 1];
      snprintf(basicFilename, PV_PATH_MAX, "./output/Movie_%f.tif", time);
      write(basicFilename);
   }
   return 0;
}

int Movie::copyReducedImagePortion()
{
   const PVLayerLoc * loc = getLayerLoc();

   const int nx = loc->nx;
   const int ny = loc->ny;

   const int nx0 = imageLoc.nx;
   const int ny0 = imageLoc.ny;

   assert(nx0 <= nx);
   assert(ny0 <= ny);

   const int i0 = nx/2 - nx0/2;
   const int j0 = ny/2 - ny0/2;

   int ii = 0;
   for (int j = j0; j < j0+ny0; j++) {
      for (int i = i0; i < i0+nx0; i++) {
         imageData[ii++] = data[i+nx*j];
      }
   }

   return 0;
}

const char * Movie::getNextFileName()
{
   int c;
   size_t len = PV_PATH_MAX;
   char * path;

   // if at end of file (EOF), rewind

   if ((c = fgetc(fp)) == EOF) {
      rewind(fp);
   }
   else {
      ungetc(c, fp);
   }

   path = fgets(this->inputfile, len, fp);

   if (path != NULL) {
      path[PV_PATH_MAX-1] = '\0';
      len = strlen(path);
      if (len > 1) {
         if (path[len-1] == '\n') {
             path[len-1] = '\0';
         }
      }
   }

   return path;
}

/**
 * Return an integer between 0 and (step-1)
 */
int Movie::calcPosition(int pos, int step, int sizeLength)
{
   const float dp = 1.0 / step;
   const double p = pv_random_prob();
   const int random_walk = 0;
   const int move_forward = 0;
   const int move_backward = 0;
   const int random_jump = 1;

   if (random_walk) {
      if (p < 0.5) {
         pos += step;
      } else {
         pos -= step;
      }
   } else if (move_forward) {
      pos += step;
   } else if (move_backward) {
      pos -= step;
   } else if (random_jump) {
      for (int i = 0; i < step; i++) {
         if ((i * dp < p) && (p < (i + 1) * dp)) {
            pos = (pv_random_prob() < 0.5) ? pos - i : pos + i;
         }
      }
   }

   pos = (pos < 0) ? -pos : pos;
   pos = (pos > sizeLength) ? sizeLength - (pos-sizeLength) : pos;

   return pos;
}

int Movie::resetPositionInBounds()
{
   PVLayerLoc * loc = &clayer->loc;

   // apply circular boundary conditions
   //
   if (offsetX < 0) offsetX += imageLoc.nx;
   if (offsetY < 0) offsetY += imageLoc.ny;
   offsetX = (imageLoc.nx < offsetX + loc->nx) ? imageLoc.nx - offsetX : offsetX;
   offsetY = (imageLoc.ny < offsetY + loc->ny) ? imageLoc.ny - offsetY : offsetY;

   // could still be out of bounds
   //
   offsetX = (offsetX < 0 || imageLoc.nx < offsetX + loc->nx) ? offsetX = 0 : offsetX;
   offsetY = (offsetY < 0 || imageLoc.ny < offsetY + loc->ny) ? offsetY = 0 : offsetY;

   return 0;
}

}
<|endoftext|>


<commit_before>638f439e-2749-11e6-bbaa-e0f84713e7b8<commit_msg>The previous fix has been fixed<commit_after>63a1764a-2749-11e6-85b2-e0f84713e7b8<|endoftext|>


<commit_before>8b4541fa-ad5a-11e7-9d26-ac87a332f658<commit_msg>Hey we can now do a thing<commit_after>8bd77b11-ad5a-11e7-8660-ac87a332f658<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libone project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <cstring>
#include <iostream>
#include <iomanip>
#include <libone/libone.h>

#include "libone_utils.h"

#include <bitset>

#include "FileNode.h"

namespace libone {

  void FileNode::parse(librevenge::RVNGInputStream *input) {
    m_offset = input->tell();

    parse_header(input);
    switch (FileNodeID) {
      case fnd_id::ObjectSpaceManifestListStartFND:
      case fnd_id::RevisionManifestListStartFND:
      case fnd_id::RevisionManifestStart4FND:
      case fnd_id::RevisionManifestStart6FND:
      case fnd_id::RevisionManifestStart7FND:
      case fnd_id::RevisionManifestListReferenceFND:
      case fnd_id::ObjectGroupListReferenceFND:
      case fnd_id::ObjectSpaceManifestListReferenceFND:
      case fnd_id::ObjectSpaceManifestRootFND:
      case fnd_id::FileDataStoreListReferenceFND:
      case fnd_id::ObjectGroupStartFND:
      case fnd_id::GlobalIdTableStart2FND:
      case fnd_id::GlobalIdTableEntryFNDX:
      case fnd_id::GlobalIdTableEndFNDX:
      case fnd_id::DataSignatureGroupDefinitionFND:
      case fnd_id::ObjectDeclaration2RefCountFND:
      case fnd_id::ObjectGroupEndFND:
      case fnd_id::ObjectInfoDependencyOverridesFND:
      case fnd_id::RootObjectReference3FND:
      case fnd_id::RevisionManifestEndFND:
      case fnd_id::ObjectDeclarationFileData3RefCountFND:
      case fnd_id::ReadOnlyObjectDeclaration2RefCountFND:
      case fnd_id::FileDataStoreObjectReferenceFND:
        break;
      case fnd_id::ChunkTerminatorFND:
        ONE_DEBUG_MSG(("ChunkTerminatorFND\n"));
        is_end = true;
        break;
      case fnd_id::fnd_invalid_id:
        ONE_DEBUG_MSG(("padding everywhere\n"));
//				while (readU16 (input) ==  0) {}
//				input->seek(-2, librevenge::RVNG_SEEK_CUR);
//        ref.parse(input, FileChunkReference::mode::Type64x32);
        is_end = true;
        break;
      default:
        ONE_DEBUG_MSG(("dunno but value is %x\n", FileNodeID));
//				input->seek(-4, librevenge::RVNG_SEEK_CUR);
//				skip(input, Size);
        is_end = true;
        break;
    }
  }

  std::string FileNode::to_string() {
    std::stringstream stream;
    stream << "FileNodeID " << std::hex << FileNodeID << " ";

    switch (FileNodeID) {
      case fnd_id::ObjectSpaceManifestListStartFND:
        ONE_DEBUG_MSG(("ObjectSpaceManifestListStartFND\n"));
        break;
      case fnd_id::ChunkTerminatorFND:
        ONE_DEBUG_MSG(("ChunkTerminatorFND\n"));
        break;
      case fnd_id::RevisionManifestListStartFND:
        ONE_DEBUG_MSG(("RevisionManifestListStart\n"));
        break;
      case fnd_id::RevisionManifestStart4FND:
        ONE_DEBUG_MSG(("RevisionManifestStart4FND\n"));
        break;
      case fnd_id::RevisionManifestStart6FND:
        ONE_DEBUG_MSG(("RevisionManifestStart6FND\n"));
        break;
      case fnd_id::RevisionManifestStart7FND:
        ONE_DEBUG_MSG(("RevisionManifestStart\n"));
        break;
      case fnd_id::RevisionManifestListReferenceFND:
          ONE_DEBUG_MSG(("RevisionManifestListReferenceFND\n"));
        break;
      case fnd_id::ObjectGroupListReferenceFND:
        ONE_DEBUG_MSG(("ObjectGroupListReferenceFND\n"));
        break;
      case fnd_id::ObjectSpaceManifestListReferenceFND:
        break;
      case fnd_id::ObjectSpaceManifestRootFND:
        ONE_DEBUG_MSG(("ObjectSpaceManifestListRootFND\n"));
        break;
      case fnd_id::FileDataStoreListReferenceFND:
        ONE_DEBUG_MSG(("FileDataStoreListReferenceFND\n"));
        break;
      case fnd_id::ObjectGroupStartFND:
        ONE_DEBUG_MSG(("ObjectGroupStartFND\n"));
        break;
      case fnd_id::GlobalIdTableStart2FND:
        ONE_DEBUG_MSG(("GlobalIdTableStart2FND\n"));
        break;
      case fnd_id::GlobalIdTableEntryFNDX:
        ONE_DEBUG_MSG(("GlobalIdTableEntryFNDX\n"));
        break;
      case fnd_id::GlobalIdTableEndFNDX:
        ONE_DEBUG_MSG(("GlobalIdTableEndFNDX\n"));
        break;
      case fnd_id::DataSignatureGroupDefinitionFND:
        ONE_DEBUG_MSG(("DataSignatureGroupDefinitionFND\n"));
        break;
      case fnd_id::ObjectDeclaration2RefCountFND:
        ONE_DEBUG_MSG(("ObjectDeclaration2RefCountFND\n"));
        break;
      case fnd_id::ObjectGroupEndFND:
        ONE_DEBUG_MSG(("ObjectGroupEndFND\n"));
        break;
      case fnd_id::fnd_invalid_id:
      default:
        ONE_DEBUG_MSG(("dunno but value is %x\n", FileNodeID));
        break;
    }
    stream << std::hex << "Size " << m_size_in_file << std::endl;
    stream << std::hex << m_base_type << std::endl;

    return stream.str();
  }

  void FileNode::parse_header(librevenge::RVNGInputStream *input) {
    uint32_t temp;
    enum stp_format format_stp;
    enum cb_format format_cb;
    int d;

    temp = readU32 (input, false);
    d = temp >> 31;
    format_stp = static_cast<stp_format>((temp >> 23) & 0x3);
    format_cb = static_cast<cb_format>((temp >> 25) & 0x3);
    m_base_type = static_cast<fnd_basetype> ((temp >> 27) & 0xF);
    m_size_in_file = (temp >> 10) & 0x1FFF;
    FileNodeID = temp & 0x3FF;
    if (d == 0) {
      std::bitset<13> z(m_size_in_file);
      ONE_DEBUG_MSG(("%s\n", z.to_string().c_str()));
      ONE_DEBUG_MSG(("warning: d is zero\n"));
    }
    assert (d == 1);
    FileNodeChunkReference reference(format_stp, format_cb, input->tell());

    std::bitset<32> y(temp);
    ONE_DEBUG_MSG((" filenode bits %s\n", y.to_string().c_str()));
    switch(m_base_type) {
      case fnd_ref_data:
      case fnd_ref_filenodelist:
        reference.parse(input);
        ONE_DEBUG_MSG(("\n"));
        break;
      case fnd_no_data:
      default:
        reference.set_zero();
        ONE_DEBUG_MSG(("\n"));
    }
    m_fnd = reference;
  }

  void FileNode::skip_node(librevenge::RVNGInputStream *input) {
    input->seek(m_offset + m_size_in_file, librevenge::RVNG_SEEK_CUR);
  }

  bool FileNode::isEnd() {
    return is_end;
  }

  uint32_t FileNode::get_FileNodeID() {
    return FileNodeID;
  }

  uint32_t FileNode::get_Size() {
    return m_size_in_file;
  }

  enum fnd_basetype FileNode::get_Basetype() {
    return m_base_type;
  }

  FileNodeChunkReference FileNode::get_fnd() {
    return m_fnd;
  }
}

<commit_msg>FileNode: clean up to_string() and some debug messages<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libone project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <cstring>
#include <iostream>
#include <iomanip>
#include <libone/libone.h>

#include "libone_utils.h"

#include <bitset>

#include "FileNode.h"

namespace libone {

  void FileNode::parse(librevenge::RVNGInputStream *input) {
    m_offset = input->tell();

    parse_header(input);
    switch (FileNodeID) {
      case fnd_id::ObjectSpaceManifestListStartFND:
      case fnd_id::RevisionManifestListStartFND:
      case fnd_id::RevisionManifestStart4FND:
      case fnd_id::RevisionManifestStart6FND:
      case fnd_id::RevisionManifestStart7FND:
      case fnd_id::RevisionManifestListReferenceFND:
      case fnd_id::ObjectGroupListReferenceFND:
      case fnd_id::ObjectSpaceManifestListReferenceFND:
      case fnd_id::ObjectSpaceManifestRootFND:
      case fnd_id::FileDataStoreListReferenceFND:
      case fnd_id::ObjectGroupStartFND:
      case fnd_id::GlobalIdTableStart2FND:
      case fnd_id::GlobalIdTableEntryFNDX:
      case fnd_id::GlobalIdTableEndFNDX:
      case fnd_id::DataSignatureGroupDefinitionFND:
      case fnd_id::ObjectDeclaration2RefCountFND:
      case fnd_id::ObjectGroupEndFND:
      case fnd_id::ObjectInfoDependencyOverridesFND:
      case fnd_id::RootObjectReference3FND:
      case fnd_id::RevisionManifestEndFND:
      case fnd_id::ObjectDeclarationFileData3RefCountFND:
      case fnd_id::ReadOnlyObjectDeclaration2RefCountFND:
      case fnd_id::FileDataStoreObjectReferenceFND:
        break;
      case fnd_id::ChunkTerminatorFND:
        ONE_DEBUG_MSG(("ChunkTerminatorFND\n"));
        is_end = true;
        break;
      case fnd_id::fnd_invalid_id:
        ONE_DEBUG_MSG(("padding everywhere\n"));
//				while (readU16 (input) ==  0) {}
//				input->seek(-2, librevenge::RVNG_SEEK_CUR);
//        ref.parse(input, FileChunkReference::mode::Type64x32);
        is_end = true;
        break;
      default:
        ONE_DEBUG_MSG(("dunno but value is %x\n", FileNodeID));
//				input->seek(-4, librevenge::RVNG_SEEK_CUR);
//				skip(input, Size);
        is_end = true;
        break;
    }
  }

  std::string FileNode::to_string() {
    std::stringstream stream;

    switch (FileNodeID) {
      case fnd_id::ObjectSpaceManifestListStartFND:
        stream << "ObjectSpaceManifestListStartFND";
        break;
      case fnd_id::ChunkTerminatorFND:
        stream << "ChunkTerminatorFND";
        break;
      case fnd_id::RevisionManifestListStartFND:
        stream << "RevisionManifestListStart";
        break;
      case fnd_id::RevisionManifestStart4FND:
        stream << "RevisionManifestStart4FND";
        break;
      case fnd_id::RevisionManifestStart6FND:
        stream << "RevisionManifestStart6FND";
        break;
      case fnd_id::RevisionManifestStart7FND:
        stream << "RevisionManifestStart";
        break;
      case fnd_id::RevisionManifestListReferenceFND:
          stream << "RevisionManifestListReferenceFND";
        break;
      case fnd_id::ObjectGroupListReferenceFND:
        stream << "ObjectGroupListReferenceFND";
        break;
      case fnd_id::ObjectSpaceManifestListReferenceFND:
        stream << "ObjectSpaceManifestListReferenceFND";
        break;
      case fnd_id::ObjectSpaceManifestRootFND:
        stream << "ObjectSpaceManifestListRootFND";
        break;
      case fnd_id::FileDataStoreListReferenceFND:
        stream << "FileDataStoreListReferenceFND";
        break;
      case fnd_id::ObjectGroupStartFND:
        stream << "ObjectGroupStartFND";
        break;
      case fnd_id::GlobalIdTableStart2FND:
        stream << "GlobalIdTableStart2FND";
        break;
      case fnd_id::GlobalIdTableEntryFNDX:
        stream << "GlobalIdTableEntryFNDX";
        break;
      case fnd_id::GlobalIdTableEndFNDX:
        stream << "GlobalIdTableEndFNDX";
        break;
      case fnd_id::DataSignatureGroupDefinitionFND:
        stream << "DataSignatureGroupDefinitionFND";
        break;
      case fnd_id::ObjectDeclaration2RefCountFND:
        stream << "ObjectDeclaration2RefCountFND";
        break;
      case fnd_id::ObjectGroupEndFND:
        stream << "ObjectGroupEndFND";
        break;
      case fnd_id::fnd_invalid_id:
      default:
        stream << "dunno but value is " << FileNodeID;
        break;
    }
    stream << "; ";
    stream << std::hex << "size " << m_size_in_file << "; ";

    stream << std::hex << "base_type ";
    switch (m_base_type) {
      case fnd_no_data:
        stream << "fnd_no_data";
        break;
      case fnd_ref_data:
        stream << "fnd_ref_data";
        break;
      case fnd_ref_filenodelist:
        stream << "fnd_ref_filenodelist";
        break;
      default:
        stream << "UNKNOWN BASETYPE";
        break;
    }

    return stream.str();
  }

  void FileNode::parse_header(librevenge::RVNGInputStream *input) {
    uint32_t temp;
    enum stp_format format_stp;
    enum cb_format format_cb;
    int d;

    temp = readU32 (input, false);
    d = temp >> 31;
    format_stp = static_cast<stp_format>((temp >> 23) & 0x3);
    format_cb = static_cast<cb_format>((temp >> 25) & 0x3);
    m_base_type = static_cast<fnd_basetype> ((temp >> 27) & 0xF);
    m_size_in_file = (temp >> 10) & 0x1FFF;
    FileNodeID = temp & 0x3FF;
    if (d == 0) {
      std::bitset<13> z(m_size_in_file);
      ONE_DEBUG_MSG(("%s\n", z.to_string().c_str()));
      ONE_DEBUG_MSG(("warning: d is zero\n"));
    }
    assert (d == 1);
    FileNodeChunkReference reference(format_stp, format_cb, input->tell());

    std::bitset<32> y(temp);
    ONE_DEBUG_MSG((" filenode bits %s\n", y.to_string().c_str()));
    switch(m_base_type) {
      case fnd_ref_data:
      case fnd_ref_filenodelist:
        reference.parse(input);
        ONE_DEBUG_MSG(("\n"));
        break;
      case fnd_no_data:
      default:
        reference.set_zero();
        ONE_DEBUG_MSG(("\n"));
    }
    m_fnd = reference;
  }

  void FileNode::skip_node(librevenge::RVNGInputStream *input) {
    input->seek(m_offset + m_size_in_file, librevenge::RVNG_SEEK_CUR);
  }

  bool FileNode::isEnd() {
    return is_end;
  }

  uint32_t FileNode::get_FileNodeID() {
    return FileNodeID;
  }

  uint32_t FileNode::get_Size() {
    return m_size_in_file;
  }

  enum fnd_basetype FileNode::get_Basetype() {
    return m_base_type;
  }

  FileNodeChunkReference FileNode::get_fnd() {
    return m_fnd;
  }
}

<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRWBuffer.h"

#include "SkAtomics.h"
#include "SkMalloc.h"
#include "SkMakeUnique.h"
#include "SkStream.h"

#include <atomic>

// Force small chunks to be a page's worth
static const size_t kMinAllocSize = 4096;

struct SkBufferBlock {
    SkBufferBlock*  fNext;      // updated by the writer
    size_t          fUsed;      // updated by the writer
    const size_t    fCapacity;

    SkBufferBlock(size_t capacity) : fNext(nullptr), fUsed(0), fCapacity(capacity) {}

    const void* startData() const { return this + 1; }

    size_t avail() const { return fCapacity - fUsed; }
    void* availData() { return (char*)this->startData() + fUsed; }

    static SkBufferBlock* Alloc(size_t length) {
        size_t capacity = LengthToCapacity(length);
        void* buffer = sk_malloc_throw(sizeof(SkBufferBlock) + capacity);
        return new (buffer) SkBufferBlock(capacity);
    }

    // Return number of bytes actually appended. Important that we always completely this block
    // before spilling into the next, since the reader uses fCapacity to know how many it can read.
    //
    size_t append(const void* src, size_t length) {
        this->validate();
        size_t amount = SkTMin(this->avail(), length);
        memcpy(this->availData(), src, amount);
        fUsed += amount;
        this->validate();
        return amount;
    }

    // Do not call in the reader thread, since the writer may be updating fUsed.
    // (The assertion is still true, but TSAN still may complain about its raciness.)
    void validate() const {
#ifdef SK_DEBUG
        SkASSERT(fCapacity > 0);
        SkASSERT(fUsed <= fCapacity);
#endif
    }

private:
    static size_t LengthToCapacity(size_t length) {
        const size_t minSize = kMinAllocSize - sizeof(SkBufferBlock);
        return SkTMax(length, minSize);
    }
};

struct SkBufferHead {
    mutable std::atomic<int32_t> fRefCnt;
    SkBufferBlock   fBlock;

    SkBufferHead(size_t capacity) : fRefCnt(1), fBlock(capacity) {}

    static size_t LengthToCapacity(size_t length) {
        const size_t minSize = kMinAllocSize - sizeof(SkBufferHead);
        return SkTMax(length, minSize);
    }

    static SkBufferHead* Alloc(size_t length) {
        size_t capacity = LengthToCapacity(length);
        size_t size = sizeof(SkBufferHead) + capacity;
        void* buffer = sk_malloc_throw(size);
        return new (buffer) SkBufferHead(capacity);
    }

    void ref() const {
        SkASSERT(fRefCnt.load(std::memory_order_relaxed) > 0);
        (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
    }

    void unref() const {
        SkASSERT(fRefCnt.load(std::memory_order_relaxed) > 0);
        // A release here acts in place of all releases we "should" have been doing in ref().
        if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
            // Like unique(), the acquire is only needed on success.
            SkBufferBlock* block = fBlock.fNext;
            sk_free((void*)this);
            while (block) {
                SkBufferBlock* next = block->fNext;
                sk_free(block);
                block = next;
            }
        }
    }

    void validate(size_t minUsed, const SkBufferBlock* tail = nullptr) const {
#ifdef SK_DEBUG
        SkASSERT(fRefCnt.load(std::memory_order_relaxed) > 0);
        size_t totalUsed = 0;
        const SkBufferBlock* block = &fBlock;
        const SkBufferBlock* lastBlock = block;
        while (block) {
            block->validate();
            totalUsed += block->fUsed;
            lastBlock = block;
            block = block->fNext;
        }
        SkASSERT(minUsed <= totalUsed);
        if (tail) {
            SkASSERT(tail == lastBlock);
        }
#endif
    }
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// The reader can only access block.fCapacity (which never changes), and cannot access
// block.fUsed, which may be updated by the writer.
//
SkROBuffer::SkROBuffer(const SkBufferHead* head, size_t available, const SkBufferBlock* tail)
    : fHead(head), fAvailable(available), fTail(tail)
{
    if (head) {
        fHead->ref();
        SkASSERT(available > 0);
        head->validate(available, tail);
    } else {
        SkASSERT(0 == available);
        SkASSERT(!tail);
    }
}

SkROBuffer::~SkROBuffer() {
    if (fHead) {
        fHead->unref();
    }
}

SkROBuffer::Iter::Iter(const SkROBuffer* buffer) {
    this->reset(buffer);
}

SkROBuffer::Iter::Iter(const sk_sp<SkROBuffer>& buffer) {
    this->reset(buffer.get());
}

void SkROBuffer::Iter::reset(const SkROBuffer* buffer) {
    fBuffer = buffer;
    if (buffer && buffer->fHead) {
        fBlock = &buffer->fHead->fBlock;
        fRemaining = buffer->fAvailable;
    } else {
        fBlock = nullptr;
        fRemaining = 0;
    }
}

const void* SkROBuffer::Iter::data() const {
    return fRemaining ? fBlock->startData() : nullptr;
}

size_t SkROBuffer::Iter::size() const {
    if (!fBlock) {
        return 0;
    }
    return SkTMin(fBlock->fCapacity, fRemaining);
}

bool SkROBuffer::Iter::next() {
    if (fRemaining) {
        fRemaining -= this->size();
        if (fBuffer->fTail == fBlock) {
            // There are more blocks, but fBuffer does not know about them.
            SkASSERT(0 == fRemaining);
            fBlock = nullptr;
        } else {
            fBlock = fBlock->fNext;
        }
    }
    return fRemaining != 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////

SkRWBuffer::SkRWBuffer(size_t initialCapacity) : fHead(nullptr), fTail(nullptr), fTotalUsed(0) {
    if (initialCapacity) {
        fHead = SkBufferHead::Alloc(initialCapacity);
        fTail = &fHead->fBlock;
    }
}

SkRWBuffer::~SkRWBuffer() {
    this->validate();
    if (fHead) {
        fHead->unref();
    }
}

// It is important that we always completely fill the current block before spilling over to the
// next, since our reader will be using fCapacity (min'd against its total available) to know how
// many bytes to read from a given block.
//
void SkRWBuffer::append(const void* src, size_t length, size_t reserve) {
    this->validate();
    if (0 == length) {
        return;
    }

    fTotalUsed += length;

    if (nullptr == fHead) {
        fHead = SkBufferHead::Alloc(length + reserve);
        fTail = &fHead->fBlock;
    }

    size_t written = fTail->append(src, length);
    SkASSERT(written <= length);
    src = (const char*)src + written;
    length -= written;

    if (length) {
        SkBufferBlock* block = SkBufferBlock::Alloc(length + reserve);
        fTail->fNext = block;
        fTail = block;
        written = fTail->append(src, length);
        SkASSERT(written == length);
    }
    this->validate();
}

#ifdef SK_DEBUG
void SkRWBuffer::validate() const {
    if (fHead) {
        fHead->validate(fTotalUsed, fTail);
    } else {
        SkASSERT(nullptr == fTail);
        SkASSERT(0 == fTotalUsed);
    }
}
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////

class SkROBufferStreamAsset : public SkStreamAsset {
    void validate() const {
#ifdef SK_DEBUG
        SkASSERT(fGlobalOffset <= fBuffer->size());
        SkASSERT(fLocalOffset <= fIter.size());
        SkASSERT(fLocalOffset <= fGlobalOffset);
#endif
    }

#ifdef SK_DEBUG
    class AutoValidate {
        SkROBufferStreamAsset* fStream;
    public:
        AutoValidate(SkROBufferStreamAsset* stream) : fStream(stream) { stream->validate(); }
        ~AutoValidate() { fStream->validate(); }
    };
    #define AUTO_VALIDATE   AutoValidate av(this);
#else
    #define AUTO_VALIDATE
#endif

public:
    SkROBufferStreamAsset(sk_sp<SkROBuffer> buffer) : fBuffer(std::move(buffer)), fIter(fBuffer) {
        fGlobalOffset = fLocalOffset = 0;
    }

    size_t getLength() const override { return fBuffer->size(); }

    bool rewind() override {
        AUTO_VALIDATE
        fIter.reset(fBuffer.get());
        fGlobalOffset = fLocalOffset = 0;
        return true;
    }

    size_t read(void* dst, size_t request) override {
        AUTO_VALIDATE
        size_t bytesRead = 0;
        for (;;) {
            size_t size = fIter.size();
            SkASSERT(fLocalOffset <= size);
            size_t avail = SkTMin(size - fLocalOffset, request - bytesRead);
            if (dst) {
                memcpy(dst, (const char*)fIter.data() + fLocalOffset, avail);
                dst = (char*)dst + avail;
            }
            bytesRead += avail;
            fLocalOffset += avail;
            SkASSERT(bytesRead <= request);
            if (bytesRead == request) {
                break;
            }
            // If we get here, we've exhausted the current iter
            SkASSERT(fLocalOffset == size);
            fLocalOffset = 0;
            if (!fIter.next()) {
                break;   // ran out of data
            }
        }
        fGlobalOffset += bytesRead;
        SkASSERT(fGlobalOffset <= fBuffer->size());
        return bytesRead;
    }

    bool isAtEnd() const override {
        return fBuffer->size() == fGlobalOffset;
    }

    size_t getPosition() const override {
        return fGlobalOffset;
    }

    bool seek(size_t position) override {
        AUTO_VALIDATE
        if (position < fGlobalOffset) {
            this->rewind();
        }
        (void)this->skip(position - fGlobalOffset);
        return true;
    }

    bool move(long offset)  override{
        AUTO_VALIDATE
        offset += fGlobalOffset;
        if (offset <= 0) {
            this->rewind();
        } else {
            (void)this->seek(SkToSizeT(offset));
        }
        return true;
    }

private:
    SkStreamAsset* onDuplicate() const override {
        return new SkROBufferStreamAsset(fBuffer);
    }

    SkStreamAsset* onFork() const override {
        auto clone = this->duplicate();
        clone->seek(this->getPosition());
        return clone.release();
    }

    sk_sp<SkROBuffer> fBuffer;
    SkROBuffer::Iter  fIter;
    size_t            fLocalOffset;
    size_t            fGlobalOffset;
};

std::unique_ptr<SkStreamAsset> SkRWBuffer::makeStreamSnapshot() const {
    return skstd::make_unique<SkROBufferStreamAsset>(this->makeROBufferSnapshot());
}
<commit_msg>Fewer atomic ops in debug with SkBufferHead.<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRWBuffer.h"

#include "SkAtomics.h"
#include "SkMalloc.h"
#include "SkMakeUnique.h"
#include "SkStream.h"

#include <atomic>

// Force small chunks to be a page's worth
static const size_t kMinAllocSize = 4096;

struct SkBufferBlock {
    SkBufferBlock*  fNext;      // updated by the writer
    size_t          fUsed;      // updated by the writer
    const size_t    fCapacity;

    SkBufferBlock(size_t capacity) : fNext(nullptr), fUsed(0), fCapacity(capacity) {}

    const void* startData() const { return this + 1; }

    size_t avail() const { return fCapacity - fUsed; }
    void* availData() { return (char*)this->startData() + fUsed; }

    static SkBufferBlock* Alloc(size_t length) {
        size_t capacity = LengthToCapacity(length);
        void* buffer = sk_malloc_throw(sizeof(SkBufferBlock) + capacity);
        return new (buffer) SkBufferBlock(capacity);
    }

    // Return number of bytes actually appended. Important that we always completely this block
    // before spilling into the next, since the reader uses fCapacity to know how many it can read.
    //
    size_t append(const void* src, size_t length) {
        this->validate();
        size_t amount = SkTMin(this->avail(), length);
        memcpy(this->availData(), src, amount);
        fUsed += amount;
        this->validate();
        return amount;
    }

    // Do not call in the reader thread, since the writer may be updating fUsed.
    // (The assertion is still true, but TSAN still may complain about its raciness.)
    void validate() const {
#ifdef SK_DEBUG
        SkASSERT(fCapacity > 0);
        SkASSERT(fUsed <= fCapacity);
#endif
    }

private:
    static size_t LengthToCapacity(size_t length) {
        const size_t minSize = kMinAllocSize - sizeof(SkBufferBlock);
        return SkTMax(length, minSize);
    }
};

struct SkBufferHead {
    mutable std::atomic<int32_t> fRefCnt;
    SkBufferBlock   fBlock;

    SkBufferHead(size_t capacity) : fRefCnt(1), fBlock(capacity) {}

    static size_t LengthToCapacity(size_t length) {
        const size_t minSize = kMinAllocSize - sizeof(SkBufferHead);
        return SkTMax(length, minSize);
    }

    static SkBufferHead* Alloc(size_t length) {
        size_t capacity = LengthToCapacity(length);
        size_t size = sizeof(SkBufferHead) + capacity;
        void* buffer = sk_malloc_throw(size);
        return new (buffer) SkBufferHead(capacity);
    }

    void ref() const {
        SkAssertResult(fRefCnt.fetch_add(+1, std::memory_order_relaxed));
    }

    void unref() const {
        // A release here acts in place of all releases we "should" have been doing in ref().
        int32_t oldRefCnt = fRefCnt.fetch_add(-1, std::memory_order_acq_rel);
        SkASSERT(oldRefCnt);
        if (1 == oldRefCnt) {
            // Like unique(), the acquire is only needed on success.
            SkBufferBlock* block = fBlock.fNext;
            sk_free((void*)this);
            while (block) {
                SkBufferBlock* next = block->fNext;
                sk_free(block);
                block = next;
            }
        }
    }

    void validate(size_t minUsed, const SkBufferBlock* tail = nullptr) const {
#ifdef SK_DEBUG
        SkASSERT(fRefCnt.load(std::memory_order_relaxed) > 0);
        size_t totalUsed = 0;
        const SkBufferBlock* block = &fBlock;
        const SkBufferBlock* lastBlock = block;
        while (block) {
            block->validate();
            totalUsed += block->fUsed;
            lastBlock = block;
            block = block->fNext;
        }
        SkASSERT(minUsed <= totalUsed);
        if (tail) {
            SkASSERT(tail == lastBlock);
        }
#endif
    }
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// The reader can only access block.fCapacity (which never changes), and cannot access
// block.fUsed, which may be updated by the writer.
//
SkROBuffer::SkROBuffer(const SkBufferHead* head, size_t available, const SkBufferBlock* tail)
    : fHead(head), fAvailable(available), fTail(tail)
{
    if (head) {
        fHead->ref();
        SkASSERT(available > 0);
        head->validate(available, tail);
    } else {
        SkASSERT(0 == available);
        SkASSERT(!tail);
    }
}

SkROBuffer::~SkROBuffer() {
    if (fHead) {
        fHead->unref();
    }
}

SkROBuffer::Iter::Iter(const SkROBuffer* buffer) {
    this->reset(buffer);
}

SkROBuffer::Iter::Iter(const sk_sp<SkROBuffer>& buffer) {
    this->reset(buffer.get());
}

void SkROBuffer::Iter::reset(const SkROBuffer* buffer) {
    fBuffer = buffer;
    if (buffer && buffer->fHead) {
        fBlock = &buffer->fHead->fBlock;
        fRemaining = buffer->fAvailable;
    } else {
        fBlock = nullptr;
        fRemaining = 0;
    }
}

const void* SkROBuffer::Iter::data() const {
    return fRemaining ? fBlock->startData() : nullptr;
}

size_t SkROBuffer::Iter::size() const {
    if (!fBlock) {
        return 0;
    }
    return SkTMin(fBlock->fCapacity, fRemaining);
}

bool SkROBuffer::Iter::next() {
    if (fRemaining) {
        fRemaining -= this->size();
        if (fBuffer->fTail == fBlock) {
            // There are more blocks, but fBuffer does not know about them.
            SkASSERT(0 == fRemaining);
            fBlock = nullptr;
        } else {
            fBlock = fBlock->fNext;
        }
    }
    return fRemaining != 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////

SkRWBuffer::SkRWBuffer(size_t initialCapacity) : fHead(nullptr), fTail(nullptr), fTotalUsed(0) {
    if (initialCapacity) {
        fHead = SkBufferHead::Alloc(initialCapacity);
        fTail = &fHead->fBlock;
    }
}

SkRWBuffer::~SkRWBuffer() {
    this->validate();
    if (fHead) {
        fHead->unref();
    }
}

// It is important that we always completely fill the current block before spilling over to the
// next, since our reader will be using fCapacity (min'd against its total available) to know how
// many bytes to read from a given block.
//
void SkRWBuffer::append(const void* src, size_t length, size_t reserve) {
    this->validate();
    if (0 == length) {
        return;
    }

    fTotalUsed += length;

    if (nullptr == fHead) {
        fHead = SkBufferHead::Alloc(length + reserve);
        fTail = &fHead->fBlock;
    }

    size_t written = fTail->append(src, length);
    SkASSERT(written <= length);
    src = (const char*)src + written;
    length -= written;

    if (length) {
        SkBufferBlock* block = SkBufferBlock::Alloc(length + reserve);
        fTail->fNext = block;
        fTail = block;
        written = fTail->append(src, length);
        SkASSERT(written == length);
    }
    this->validate();
}

#ifdef SK_DEBUG
void SkRWBuffer::validate() const {
    if (fHead) {
        fHead->validate(fTotalUsed, fTail);
    } else {
        SkASSERT(nullptr == fTail);
        SkASSERT(0 == fTotalUsed);
    }
}
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////

class SkROBufferStreamAsset : public SkStreamAsset {
    void validate() const {
#ifdef SK_DEBUG
        SkASSERT(fGlobalOffset <= fBuffer->size());
        SkASSERT(fLocalOffset <= fIter.size());
        SkASSERT(fLocalOffset <= fGlobalOffset);
#endif
    }

#ifdef SK_DEBUG
    class AutoValidate {
        SkROBufferStreamAsset* fStream;
    public:
        AutoValidate(SkROBufferStreamAsset* stream) : fStream(stream) { stream->validate(); }
        ~AutoValidate() { fStream->validate(); }
    };
    #define AUTO_VALIDATE   AutoValidate av(this);
#else
    #define AUTO_VALIDATE
#endif

public:
    SkROBufferStreamAsset(sk_sp<SkROBuffer> buffer) : fBuffer(std::move(buffer)), fIter(fBuffer) {
        fGlobalOffset = fLocalOffset = 0;
    }

    size_t getLength() const override { return fBuffer->size(); }

    bool rewind() override {
        AUTO_VALIDATE
        fIter.reset(fBuffer.get());
        fGlobalOffset = fLocalOffset = 0;
        return true;
    }

    size_t read(void* dst, size_t request) override {
        AUTO_VALIDATE
        size_t bytesRead = 0;
        for (;;) {
            size_t size = fIter.size();
            SkASSERT(fLocalOffset <= size);
            size_t avail = SkTMin(size - fLocalOffset, request - bytesRead);
            if (dst) {
                memcpy(dst, (const char*)fIter.data() + fLocalOffset, avail);
                dst = (char*)dst + avail;
            }
            bytesRead += avail;
            fLocalOffset += avail;
            SkASSERT(bytesRead <= request);
            if (bytesRead == request) {
                break;
            }
            // If we get here, we've exhausted the current iter
            SkASSERT(fLocalOffset == size);
            fLocalOffset = 0;
            if (!fIter.next()) {
                break;   // ran out of data
            }
        }
        fGlobalOffset += bytesRead;
        SkASSERT(fGlobalOffset <= fBuffer->size());
        return bytesRead;
    }

    bool isAtEnd() const override {
        return fBuffer->size() == fGlobalOffset;
    }

    size_t getPosition() const override {
        return fGlobalOffset;
    }

    bool seek(size_t position) override {
        AUTO_VALIDATE
        if (position < fGlobalOffset) {
            this->rewind();
        }
        (void)this->skip(position - fGlobalOffset);
        return true;
    }

    bool move(long offset)  override{
        AUTO_VALIDATE
        offset += fGlobalOffset;
        if (offset <= 0) {
            this->rewind();
        } else {
            (void)this->seek(SkToSizeT(offset));
        }
        return true;
    }

private:
    SkStreamAsset* onDuplicate() const override {
        return new SkROBufferStreamAsset(fBuffer);
    }

    SkStreamAsset* onFork() const override {
        auto clone = this->duplicate();
        clone->seek(this->getPosition());
        return clone.release();
    }

    sk_sp<SkROBuffer> fBuffer;
    SkROBuffer::Iter  fIter;
    size_t            fLocalOffset;
    size_t            fGlobalOffset;
};

std::unique_ptr<SkStreamAsset> SkRWBuffer::makeStreamSnapshot() const {
    return skstd::make_unique<SkROBufferStreamAsset>(this->makeROBufferSnapshot());
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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.
 *
 * Authors: Anthony Gutierrez
 */

/* @file
 * Implementation of a bi-mode branch predictor
 */

#include "base/bitfield.hh"
#include "base/intmath.hh"
#include "cpu/pred/bi_mode.hh"

BiModeBP::BiModeBP(const Params *params)
    : BPredUnit(params), instShiftAmt(params->instShiftAmt),
      globalHistoryReg(0),
      globalHistoryBits(ceilLog2(params->globalPredictorSize)),
      choicePredictorSize(params->choicePredictorSize),
      choiceCtrBits(params->choiceCtrBits),
      globalPredictorSize(params->globalPredictorSize),
      globalCtrBits(params->globalCtrBits)
{
    if (!isPowerOf2(choicePredictorSize))
        fatal("Invalid choice predictor size.\n");
    if (!isPowerOf2(globalPredictorSize))
        fatal("Invalid global history predictor size.\n");

    choiceCounters.resize(choicePredictorSize);
    takenCounters.resize(globalPredictorSize);
    notTakenCounters.resize(globalPredictorSize);

    for (int i = 0; i < choicePredictorSize; ++i) {
        choiceCounters[i].setBits(choiceCtrBits);
    }
    for (int i = 0; i < globalPredictorSize; ++i) {
        takenCounters[i].setBits(globalCtrBits);
        notTakenCounters[i].setBits(globalCtrBits);
    }

    historyRegisterMask = mask(globalHistoryBits);
    choiceHistoryMask = choicePredictorSize - 1;
    globalHistoryMask = globalPredictorSize - 1;

    choiceThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
    takenThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
    notTakenThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
}

/*
 * For an unconditional branch we set its history such that
 * everything is set to taken. I.e., its choice predictor
 * chooses the taken array and the taken array predicts taken.
 */
void
BiModeBP::uncondBranch(void * &bpHistory)
{
    BPHistory *history = new BPHistory;
    history->globalHistoryReg = globalHistoryReg;
    history->takenUsed = true;
    history->takenPred = true;
    history->notTakenPred = true;
    history->finalPred = true;
    bpHistory = static_cast<void*>(history);
    updateGlobalHistReg(true);
}

void
BiModeBP::squash(void *bpHistory)
{
    BPHistory *history = static_cast<BPHistory*>(bpHistory);
    globalHistoryReg = history->globalHistoryReg;

    delete history;
}

/*
 * Here we lookup the actual branch prediction. We use the PC to
 * identify the bias of a particular branch, which is based on the
 * prediction in the choice array. A hash of the global history
 * register and a branch's PC is used to index into both the taken
 * and not-taken predictors, which both present a prediction. The
 * choice array's prediction is used to select between the two
 * direction predictors for the final branch prediction.
 */
bool
BiModeBP::lookup(Addr branchAddr, void * &bpHistory)
{
    unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
                                & choiceHistoryMask);
    unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
                                ^ globalHistoryReg)
                                & globalHistoryMask);

    assert(choiceHistoryIdx < choicePredictorSize);
    assert(globalHistoryIdx < globalPredictorSize);

    bool choicePrediction = choiceCounters[choiceHistoryIdx].read()
                            > choiceThreshold;
    bool takenGHBPrediction = takenCounters[globalHistoryIdx].read()
                              > takenThreshold;
    bool notTakenGHBPrediction = notTakenCounters[globalHistoryIdx].read()
                                 > notTakenThreshold;
    bool finalPrediction;

    BPHistory *history = new BPHistory;
    history->globalHistoryReg = globalHistoryReg;
    history->takenUsed = choicePrediction;
    history->takenPred = takenGHBPrediction;
    history->notTakenPred = notTakenGHBPrediction;

    if (choicePrediction) {
        finalPrediction = takenGHBPrediction;
    } else {
        finalPrediction = notTakenGHBPrediction;
    }

    history->finalPred = finalPrediction;
    bpHistory = static_cast<void*>(history);
    updateGlobalHistReg(finalPrediction);

    return finalPrediction;
}

void
BiModeBP::btbUpdate(Addr branchAddr, void * &bpHistory)
{
    globalHistoryReg &= (historyRegisterMask & ~ULL(1));
}

/* Only the selected direction predictor will be updated with the final
 * outcome; the status of the unselected one will not be altered. The choice
 * predictor is always updated with the branch outcome, except when the
 * choice is opposite to the branch outcome but the selected counter of
 * the direction predictors makes a correct final prediction.
 */
void
BiModeBP::update(Addr branchAddr, bool taken, void *bpHistory, bool squashed)
{
    if (bpHistory) {
        BPHistory *history = static_cast<BPHistory*>(bpHistory);

        unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
                                    & choiceHistoryMask);
        unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
                                    ^ globalHistoryReg)
                                    & globalHistoryMask);

        assert(choiceHistoryIdx < choicePredictorSize);
        assert(globalHistoryIdx < globalPredictorSize);

        if (history->takenUsed) {
            // if the taken array's prediction was used, update it
            if (taken) {
                takenCounters[globalHistoryIdx].increment();
            } else {
                takenCounters[globalHistoryIdx].decrement();
            }
        } else {
            // if the not-taken array's prediction was used, update it
            if (taken) {
                notTakenCounters[globalHistoryIdx].increment();
            } else {
                notTakenCounters[globalHistoryIdx].decrement();
            }
        }

        if (history->finalPred == taken) {
            /* If the final prediction matches the actual branch's
             * outcome and the choice predictor matches the final
             * outcome, we update the choice predictor, otherwise it
             * is not updated. While the designers of the bi-mode
             * predictor don't explicity say why this is done, one
             * can infer that it is to preserve the choice predictor's
             * bias with respect to the branch being predicted; afterall,
             * the whole point of the bi-mode predictor is to identify the
             * atypical case when a branch deviates from its bias.
             */
            if (history->finalPred == history->takenUsed) {
                if (taken) {
                    choiceCounters[choiceHistoryIdx].increment();
                } else {
                    choiceCounters[choiceHistoryIdx].decrement();
                }
            }
        } else {
            // always update the choice predictor on an incorrect prediction
            if (taken) {
                choiceCounters[choiceHistoryIdx].increment();
            } else {
                choiceCounters[choiceHistoryIdx].decrement();
            }
        }

        if (squashed) {
            if (taken) {
                globalHistoryReg = (history->globalHistoryReg << 1) | 1;
            } else {
                globalHistoryReg = (history->globalHistoryReg << 1);
            }
            globalHistoryReg &= historyRegisterMask;
        } else {
            delete history;
        }
    }
}

void
BiModeBP::retireSquashed(void *bp_history)
{
    BPHistory *history = static_cast<BPHistory*>(bp_history);
    delete history;
}

void
BiModeBP::updateGlobalHistReg(bool taken)
{
    globalHistoryReg = taken ? (globalHistoryReg << 1) | 1 :
                               (globalHistoryReg << 1);
    globalHistoryReg &= historyRegisterMask;
}
<commit_msg>cpu: fix bimodal predictor to use correct global history reg<commit_after>/*
 * Copyright (c) 2014 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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.
 *
 * Authors: Anthony Gutierrez
 */

/* @file
 * Implementation of a bi-mode branch predictor
 */

#include "base/bitfield.hh"
#include "base/intmath.hh"
#include "cpu/pred/bi_mode.hh"

BiModeBP::BiModeBP(const Params *params)
    : BPredUnit(params), instShiftAmt(params->instShiftAmt),
      globalHistoryReg(0),
      globalHistoryBits(ceilLog2(params->globalPredictorSize)),
      choicePredictorSize(params->choicePredictorSize),
      choiceCtrBits(params->choiceCtrBits),
      globalPredictorSize(params->globalPredictorSize),
      globalCtrBits(params->globalCtrBits)
{
    if (!isPowerOf2(choicePredictorSize))
        fatal("Invalid choice predictor size.\n");
    if (!isPowerOf2(globalPredictorSize))
        fatal("Invalid global history predictor size.\n");

    choiceCounters.resize(choicePredictorSize);
    takenCounters.resize(globalPredictorSize);
    notTakenCounters.resize(globalPredictorSize);

    for (int i = 0; i < choicePredictorSize; ++i) {
        choiceCounters[i].setBits(choiceCtrBits);
    }
    for (int i = 0; i < globalPredictorSize; ++i) {
        takenCounters[i].setBits(globalCtrBits);
        notTakenCounters[i].setBits(globalCtrBits);
    }

    historyRegisterMask = mask(globalHistoryBits);
    choiceHistoryMask = choicePredictorSize - 1;
    globalHistoryMask = globalPredictorSize - 1;

    choiceThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
    takenThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
    notTakenThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
}

/*
 * For an unconditional branch we set its history such that
 * everything is set to taken. I.e., its choice predictor
 * chooses the taken array and the taken array predicts taken.
 */
void
BiModeBP::uncondBranch(void * &bpHistory)
{
    BPHistory *history = new BPHistory;
    history->globalHistoryReg = globalHistoryReg;
    history->takenUsed = true;
    history->takenPred = true;
    history->notTakenPred = true;
    history->finalPred = true;
    bpHistory = static_cast<void*>(history);
    updateGlobalHistReg(true);
}

void
BiModeBP::squash(void *bpHistory)
{
    BPHistory *history = static_cast<BPHistory*>(bpHistory);
    globalHistoryReg = history->globalHistoryReg;

    delete history;
}

/*
 * Here we lookup the actual branch prediction. We use the PC to
 * identify the bias of a particular branch, which is based on the
 * prediction in the choice array. A hash of the global history
 * register and a branch's PC is used to index into both the taken
 * and not-taken predictors, which both present a prediction. The
 * choice array's prediction is used to select between the two
 * direction predictors for the final branch prediction.
 */
bool
BiModeBP::lookup(Addr branchAddr, void * &bpHistory)
{
    unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
                                & choiceHistoryMask);
    unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
                                ^ globalHistoryReg)
                                & globalHistoryMask);

    assert(choiceHistoryIdx < choicePredictorSize);
    assert(globalHistoryIdx < globalPredictorSize);

    bool choicePrediction = choiceCounters[choiceHistoryIdx].read()
                            > choiceThreshold;
    bool takenGHBPrediction = takenCounters[globalHistoryIdx].read()
                              > takenThreshold;
    bool notTakenGHBPrediction = notTakenCounters[globalHistoryIdx].read()
                                 > notTakenThreshold;
    bool finalPrediction;

    BPHistory *history = new BPHistory;
    history->globalHistoryReg = globalHistoryReg;
    history->takenUsed = choicePrediction;
    history->takenPred = takenGHBPrediction;
    history->notTakenPred = notTakenGHBPrediction;

    if (choicePrediction) {
        finalPrediction = takenGHBPrediction;
    } else {
        finalPrediction = notTakenGHBPrediction;
    }

    history->finalPred = finalPrediction;
    bpHistory = static_cast<void*>(history);
    updateGlobalHistReg(finalPrediction);

    return finalPrediction;
}

void
BiModeBP::btbUpdate(Addr branchAddr, void * &bpHistory)
{
    globalHistoryReg &= (historyRegisterMask & ~ULL(1));
}

/* Only the selected direction predictor will be updated with the final
 * outcome; the status of the unselected one will not be altered. The choice
 * predictor is always updated with the branch outcome, except when the
 * choice is opposite to the branch outcome but the selected counter of
 * the direction predictors makes a correct final prediction.
 */
void
BiModeBP::update(Addr branchAddr, bool taken, void *bpHistory, bool squashed)
{
    if (bpHistory) {
        BPHistory *history = static_cast<BPHistory*>(bpHistory);

        unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
                                    & choiceHistoryMask);
        unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
                                    ^ history->globalHistoryReg)
                                    & globalHistoryMask);

        assert(choiceHistoryIdx < choicePredictorSize);
        assert(globalHistoryIdx < globalPredictorSize);

        if (history->takenUsed) {
            // if the taken array's prediction was used, update it
            if (taken) {
                takenCounters[globalHistoryIdx].increment();
            } else {
                takenCounters[globalHistoryIdx].decrement();
            }
        } else {
            // if the not-taken array's prediction was used, update it
            if (taken) {
                notTakenCounters[globalHistoryIdx].increment();
            } else {
                notTakenCounters[globalHistoryIdx].decrement();
            }
        }

        if (history->finalPred == taken) {
            /* If the final prediction matches the actual branch's
             * outcome and the choice predictor matches the final
             * outcome, we update the choice predictor, otherwise it
             * is not updated. While the designers of the bi-mode
             * predictor don't explicity say why this is done, one
             * can infer that it is to preserve the choice predictor's
             * bias with respect to the branch being predicted; afterall,
             * the whole point of the bi-mode predictor is to identify the
             * atypical case when a branch deviates from its bias.
             */
            if (history->finalPred == history->takenUsed) {
                if (taken) {
                    choiceCounters[choiceHistoryIdx].increment();
                } else {
                    choiceCounters[choiceHistoryIdx].decrement();
                }
            }
        } else {
            // always update the choice predictor on an incorrect prediction
            if (taken) {
                choiceCounters[choiceHistoryIdx].increment();
            } else {
                choiceCounters[choiceHistoryIdx].decrement();
            }
        }

        if (squashed) {
            if (taken) {
                globalHistoryReg = (history->globalHistoryReg << 1) | 1;
            } else {
                globalHistoryReg = (history->globalHistoryReg << 1);
            }
            globalHistoryReg &= historyRegisterMask;
        } else {
            delete history;
        }
    }
}

void
BiModeBP::retireSquashed(void *bp_history)
{
    BPHistory *history = static_cast<BPHistory*>(bp_history);
    delete history;
}

void
BiModeBP::updateGlobalHistReg(bool taken)
{
    globalHistoryReg = taken ? (globalHistoryReg << 1) | 1 :
                               (globalHistoryReg << 1);
    globalHistoryReg &= historyRegisterMask;
}
<|endoftext|>


<commit_before>#include <drivers/mpu6000.hpp>

#include <hal.h>

#include <hal_config.hpp>

MPU6000::MPU6000(SPIDriver *spid, const SPIConfig *spicfg) : spid(spid), spicfg(spicfg) {
}

void MPU6000::init() {
  uint8_t txbuf[8], rxbuf[8];

  // Start bus
  chMtxLock(&spi_mtx);
  spiAcquireBus(spid);      // Acquire bus ownership
  spiStart(spid, spicfg);   // Set up transfer parameters
  spiSelect(spid);          // Assert slave select

  // Reset device.
  txbuf[0] = MPU6000_PWR_MGMT_1;
  txbuf[1] = 0x80;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  chThdSleepMilliseconds(100);

  // Set sample rate to 1 kHz.
  txbuf[0] = MPU6000_SMPLRT_DIV;
  txbuf[1] = 0x00;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Set DLPF to 4 (20 Hz gyro bandwidth1 Hz accelerometer bandwidth)
  txbuf[0] = MPU6000_CONFIG;
  txbuf[1] = 0x04;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Wake up device and set clock source to Gyro Z.
  txbuf[0] = MPU6000_PWR_MGMT_1;
  txbuf[1] = 0x03;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Set gyro full range to 2000 dps. We first read in the current register
  // value so we can change what we need and leave everything else alone.
  txbuf[0] = MPU6000_GYRO_CONFIG | (1<<7);
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.
  txbuf[0] = MPU6000_GYRO_CONFIG;
  txbuf[1] = (rxbuf[1] & ~0x18) | 0x18;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Set accelerometer full range to 2 g.
  txbuf[0] = MPU6000_ACCEL_CONFIG | (1<<7);
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.
  txbuf[0] = MPU6000_ACCEL_CONFIG;
  txbuf[1] = (rxbuf[1] & ~0x18) | 0x00;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Stop bus
  spiUnselect(spid);     // Deassert slave select
  spiReleaseBus(spid);   // Release bus ownership
  chMtxUnlock();

  // Read once to clear out bad data?
  readGyro();
  readAccel();
}

gyroscope_reading_t MPU6000::readGyro() {
  uint8_t txbuf[8], rxbuf[8];
  gyroscope_reading_t reading;

  // Start bus
  chMtxLock(&spi_mtx);
  spiAcquireBus(spid);      // Acquire bus ownership
  spiStart(spid, spicfg);   // Set up transfer parameters
  spiSelect(spid);          // Assert slave select

  // Get data
  txbuf[0] = MPU6000_GYRO_XOUT_H | (1<<7);
  spiExchange(spid, 7, txbuf, rxbuf);   // Atomic transfer operations
  reading.axes[0] = ((int16_t) ((rxbuf[1]<<8) | rxbuf[2])) / 16.384 * 3.1415926535 / 180.0 + GYR_X_OFFSET;
  reading.axes[1] = ((int16_t) ((rxbuf[3]<<8) | rxbuf[4])) / 16.384 * 3.1415926535 / 180.0 + GYR_Y_OFFSET;
  reading.axes[2] = ((int16_t) ((rxbuf[5]<<8) | rxbuf[6])) / 16.384 * 3.1415926535 / 180.0 + GYR_Z_OFFSET;

  // TODO(yoos): correct for thermal bias.
  txbuf[0] = MPU6000_TEMP_OUT_H | (1<<7);
  spiExchange(spid, 3, txbuf, rxbuf);
  float temp = ((int16_t) ((rxbuf[1]<<8) | rxbuf[2])) / 340 + 36.53;

  // Stop bus
  spiUnselect(spid);     // Deassert slave select
  spiReleaseBus(spid);   // Release bus ownership
  chMtxUnlock();

  return reading;
}

accelerometer_reading_t MPU6000::readAccel() {
  uint8_t txbuf[8], rxbuf[8];
  accelerometer_reading_t reading;

  // Start bus
  chMtxLock(&spi_mtx);
  spiAcquireBus(spid);      // Acquire bus ownership
  spiStart(spid, spicfg);   // Set up transfer parameters
  spiSelect(spid);          // Assert slave select

  // Get data
  txbuf[0] = MPU6000_ACCEL_XOUT_H | (1<<7);
  spiExchange(spid, 7, txbuf, rxbuf);   // Atomic transfer operations
  reading.axes[0] = ((int16_t) ((rxbuf[1]<<8) | rxbuf[2])) / 16384.0 + ACC_X_OFFSET;
  reading.axes[1] = ((int16_t) ((rxbuf[3]<<8) | rxbuf[4])) / 16384.0 + ACC_Y_OFFSET;
  reading.axes[2] = ((int16_t) ((rxbuf[5]<<8) | rxbuf[6])) / 16384.0 + ACC_Z_OFFSET;

  // Stop bus
  spiUnselect(spid);     // Deassert slave select
  spiReleaseBus(spid);   // Release bus ownership
  chMtxUnlock();

  return reading;
}

//uint8_t MPU6000::readRegister(uint8_t reg) {
//  uint8_t txbuf[8];
//  uint8_t rxbuf[8];
//
//  txbuf[0] = reg;
//  txbuf[1] = 0xFF;
//
//  spiSelect(this->spid);
//  spiExchange(this->spid, 2, txbuf, rxbuf);
//  spiUnselect(this->spid);
//
//  return rxbuf[1];
//}
//
//void MPU6000::writeRegister(uint8_t reg, uint8_t val) {
//  uint8_t txbuf[8];
//  uint8_t rxbuf[8];
//
//  txbuf[0] = reg;
//  txbuf[1] = val;
//
//  spiSelect(this->spid);
//  spiExchange(this->spid, 2, txbuf, rxbuf);
//  spiUnselect(this->spid);
//}
<commit_msg>Disable SPI mutex lock for now.<commit_after>#include <drivers/mpu6000.hpp>

#include <hal.h>

#include <hal_config.hpp>

MPU6000::MPU6000(SPIDriver *spid, const SPIConfig *spicfg) : spid(spid), spicfg(spicfg) {
}

void MPU6000::init() {
  uint8_t txbuf[8], rxbuf[8];

  // Start bus
  //chMtxLock(&spi_mtx);
  spiAcquireBus(spid);      // Acquire bus ownership
  spiStart(spid, spicfg);   // Set up transfer parameters
  spiSelect(spid);          // Assert slave select

  // Reset device.
  txbuf[0] = MPU6000_PWR_MGMT_1;
  txbuf[1] = 0x80;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  chThdSleepMilliseconds(100);

  // Set sample rate to 1 kHz.
  txbuf[0] = MPU6000_SMPLRT_DIV;
  txbuf[1] = 0x00;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Set DLPF to 4 (20 Hz gyro bandwidth1 Hz accelerometer bandwidth)
  txbuf[0] = MPU6000_CONFIG;
  txbuf[1] = 0x04;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Wake up device and set clock source to Gyro Z.
  txbuf[0] = MPU6000_PWR_MGMT_1;
  txbuf[1] = 0x03;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Set gyro full range to 2000 dps. We first read in the current register
  // value so we can change what we need and leave everything else alone.
  txbuf[0] = MPU6000_GYRO_CONFIG | (1<<7);
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.
  txbuf[0] = MPU6000_GYRO_CONFIG;
  txbuf[1] = (rxbuf[1] & ~0x18) | 0x18;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Set accelerometer full range to 2 g.
  txbuf[0] = MPU6000_ACCEL_CONFIG | (1<<7);
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.
  txbuf[0] = MPU6000_ACCEL_CONFIG;
  txbuf[1] = (rxbuf[1] & ~0x18) | 0x00;
  spiExchange(spid, 2, txbuf, rxbuf);   // Exchange data.

  // Stop bus
  spiUnselect(spid);     // Deassert slave select
  spiReleaseBus(spid);   // Release bus ownership
  //chMtxUnlock();

  // Read once to clear out bad data?
  readGyro();
  readAccel();
}

gyroscope_reading_t MPU6000::readGyro() {
  uint8_t txbuf[8], rxbuf[8];
  gyroscope_reading_t reading;

  // Start bus
  //chMtxLock(&spi_mtx);
  spiAcquireBus(spid);      // Acquire bus ownership
  spiStart(spid, spicfg);   // Set up transfer parameters
  spiSelect(spid);          // Assert slave select

  // Get data
  txbuf[0] = MPU6000_GYRO_XOUT_H | (1<<7);
  spiExchange(spid, 7, txbuf, rxbuf);   // Atomic transfer operations
  reading.axes[0] = ((int16_t) ((rxbuf[1]<<8) | rxbuf[2])) / 16.384 * 3.1415926535 / 180.0 + GYR_X_OFFSET;
  reading.axes[1] = ((int16_t) ((rxbuf[3]<<8) | rxbuf[4])) / 16.384 * 3.1415926535 / 180.0 + GYR_Y_OFFSET;
  reading.axes[2] = ((int16_t) ((rxbuf[5]<<8) | rxbuf[6])) / 16.384 * 3.1415926535 / 180.0 + GYR_Z_OFFSET;

  // TODO(yoos): correct for thermal bias.
  txbuf[0] = MPU6000_TEMP_OUT_H | (1<<7);
  spiExchange(spid, 3, txbuf, rxbuf);
  float temp = ((int16_t) ((rxbuf[1]<<8) | rxbuf[2])) / 340 + 36.53;

  // Stop bus
  spiUnselect(spid);     // Deassert slave select
  spiReleaseBus(spid);   // Release bus ownership
  //chMtxUnlock();

  return reading;
}

accelerometer_reading_t MPU6000::readAccel() {
  uint8_t txbuf[8], rxbuf[8];
  accelerometer_reading_t reading;

  // Start bus
  //chMtxLock(&spi_mtx);
  spiAcquireBus(spid);      // Acquire bus ownership
  spiStart(spid, spicfg);   // Set up transfer parameters
  spiSelect(spid);          // Assert slave select

  // Get data
  txbuf[0] = MPU6000_ACCEL_XOUT_H | (1<<7);
  spiExchange(spid, 7, txbuf, rxbuf);   // Atomic transfer operations
  reading.axes[0] = ((int16_t) ((rxbuf[1]<<8) | rxbuf[2])) / 16384.0 + ACC_X_OFFSET;
  reading.axes[1] = ((int16_t) ((rxbuf[3]<<8) | rxbuf[4])) / 16384.0 + ACC_Y_OFFSET;
  reading.axes[2] = ((int16_t) ((rxbuf[5]<<8) | rxbuf[6])) / 16384.0 + ACC_Z_OFFSET;

  // Stop bus
  spiUnselect(spid);     // Deassert slave select
  spiReleaseBus(spid);   // Release bus ownership
  //chMtxUnlock();

  return reading;
}

//uint8_t MPU6000::readRegister(uint8_t reg) {
//  uint8_t txbuf[8];
//  uint8_t rxbuf[8];
//
//  txbuf[0] = reg;
//  txbuf[1] = 0xFF;
//
//  spiSelect(this->spid);
//  spiExchange(this->spid, 2, txbuf, rxbuf);
//  spiUnselect(this->spid);
//
//  return rxbuf[1];
//}
//
//void MPU6000::writeRegister(uint8_t reg, uint8_t val) {
//  uint8_t txbuf[8];
//  uint8_t rxbuf[8];
//
//  txbuf[0] = reg;
//  txbuf[1] = val;
//
//  spiSelect(this->spid);
//  spiExchange(this->spid, 2, txbuf, rxbuf);
//  spiUnselect(this->spid);
//}
<|endoftext|>