<commit_before>#include <iostream>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>
#include <vector>

#include "metadatastorage.h"
#include "storage2.h"

#include "akumuli.h"
#include "log_iface.h"
#include "status_util.h"

// To initialize apr and sqlite properly
#include <apr.h>
#include <sqlite3.h>

using namespace Akumuli;
using namespace StorageEngine;

void test_logger(aku_LogLevel tag, const char* msg) {
    AKU_UNUSED(tag);
    BOOST_MESSAGE(msg);
}

struct AkumuliInitializer {
    AkumuliInitializer() {
        sqlite3_initialize();
        apr_initialize();

        apr_pool_t *pool = nullptr;
        auto status = apr_pool_create(&pool, NULL);
        if (status != APR_SUCCESS) {
            AKU_PANIC("Can't create memory pool");
        }
        apr_dbd_init(pool);

        Akumuli::Logger::set_logger(&test_logger);
    }
};

static AkumuliInitializer initializer;

std::shared_ptr<MetadataStorage> create_metadatastorage() {
    // Create in-memory sqlite database.
    std::shared_ptr<MetadataStorage> meta;
    meta.reset(new MetadataStorage(":memory:"));
    return std::move(meta);
}

std::shared_ptr<ColumnStore> create_cstore() {
    std::shared_ptr<BlockStore> bstore = BlockStoreBuilder::create_memstore();
    std::shared_ptr<ColumnStore> cstore;
    cstore.reset(new ColumnStore(bstore));
    return cstore;
}

std::shared_ptr<Storage> create_storage() {
    auto meta = create_metadatastorage();
    auto bstore = BlockStoreBuilder::create_memstore();
    auto cstore = create_cstore();
    auto store = std::make_shared<Storage>(meta, bstore, cstore, false);
    return store;
}

BOOST_AUTO_TEST_CASE(Test_metadata_storage_volumes_config) {

    MetadataStorage db(":memory:");
    std::vector<MetadataStorage::VolumeDesc> volumes = {
        std::make_pair(0, "first"),
        std::make_pair(1, "second"),
        std::make_pair(2, "third"),
    };
    db.init_volumes(volumes);
    auto actual = db.get_volumes();
    for (int i = 0; i < 3; i++) {
        BOOST_REQUIRE_EQUAL(volumes.at(i).first, actual.at(i).first);
        BOOST_REQUIRE_EQUAL(volumes.at(i).second, actual.at(i).second);
    }
}

BOOST_AUTO_TEST_CASE(Test_metadata_storage_numeric_config) {

    MetadataStorage db(":memory:");
    const char* creation_datetime = "2015-02-03 00:00:00";  // Formatting not required
    db.init_config(creation_datetime);
    std::string actual_dt;
    db.get_configs(&actual_dt);
    BOOST_REQUIRE_EQUAL(creation_datetime, actual_dt);
}

BOOST_AUTO_TEST_CASE(Test_storage_add_series_1) {
    aku_Status status;
    const char* sname = "hello world=1";
    const char* end = sname + strlen(sname);

    auto store = create_storage();
    auto sessiona = store->create_write_session();
    auto sessionb = store->create_write_session();

    aku_Sample samplea;
    status = sessiona->init_series_id(sname, end, &samplea);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    aku_Sample sampleb;
    // Should initialize from global data
    status = sessionb->init_series_id(sname, end, &sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    BOOST_REQUIRE_EQUAL(samplea.paramid, sampleb.paramid);

    // Should read local data
    status = sessionb->init_series_id(sname, end, &sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    BOOST_REQUIRE_EQUAL(samplea.paramid, sampleb.paramid);
}

BOOST_AUTO_TEST_CASE(Test_storage_add_values_1) {
    aku_Status status;
    const char* sname = "hello world=1";
    const char* end = sname + strlen(sname);

    auto store = create_storage();
    auto sessiona = store->create_write_session();
    auto sessionb = store->create_write_session();

    aku_Sample samplea;
    samplea.payload.type = AKU_PAYLOAD_FLOAT;
    samplea.timestamp = 111;
    samplea.payload.float64 = 111;
    status = sessiona->init_series_id(sname, end, &samplea);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
    status = sessiona->write(samplea);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    aku_Sample sampleb;
    sampleb.payload.type = AKU_PAYLOAD_FLOAT;
    sampleb.timestamp = 222;
    sampleb.payload.float64 = 222;
    // Should initialize from global data
    status = sessionb->init_series_id(sname, end, &sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
    status = sessionb->write(sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    BOOST_REQUIRE_EQUAL(samplea.paramid, sampleb.paramid);

    // Should read local data
    sampleb.timestamp = 333;
    sampleb.payload.float64 = 333;
    status = sessiona->init_series_id(sname, end, &sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
    status = sessiona->write(sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
}

BOOST_AUTO_TEST_CASE(Test_storage_add_values_2) {
    aku_Status status;
    const char* sname = "hello world=1";
    const char* end = sname + strlen(sname);

    auto store = create_storage();
    auto sessiona = store->create_write_session();
    {
        auto sessionb = store->create_write_session();

        aku_Sample sample;
        sample.payload.type = AKU_PAYLOAD_FLOAT;
        sample.timestamp = 111;
        sample.payload.float64 = 111;
        status = sessionb->init_series_id(sname, end, &sample);
        BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
        status = sessionb->write(sample);
        BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

        // disatcher should be freed and registry entry should be returned
    }
    aku_Sample sample;
    sample.payload.type = AKU_PAYLOAD_FLOAT;
    sample.timestamp = 222;
    sample.payload.float64 = 222;

    status = sessiona->init_series_id(sname, end, &sample);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
    status = sessiona->write(sample);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    BOOST_REQUIRE_EQUAL(sample.paramid, sample.paramid);
}

// Test read queries

void fill_data(std::shared_ptr<StorageSession> session, aku_Timestamp begin, aku_Timestamp end, std::vector<std::string> const& names) {
    for (aku_Timestamp ts = begin; ts < end; ts++) {
        for (auto it: names) {
            aku_Sample sample;
            sample.timestamp = ts;
            sample.payload.type = AKU_PAYLOAD_FLOAT;
            sample.payload.float64 = double(ts)/10.0;
            auto status = session->init_series_id(it.data(), it.data() + it.size(), &sample);
            if (status != AKU_SUCCESS) {
                BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
            }
            status = session->write(sample);
            if (status != AKU_SUCCESS) {
                BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
            }
        }
    }
}

struct CursorMock : InternalCursor {
    bool done;
    std::vector<aku_Sample> samples;
    aku_Status error;

    CursorMock() {
        done = false;
        error = AKU_SUCCESS;
    }

    virtual bool put(Caller&, const aku_Sample &val) override {
        if (done) {
            BOOST_FAIL("Cursor invariant broken");
        }
        samples.push_back(val);
        return true;
    }

    virtual void complete(Caller&) override {
        if (done) {
            BOOST_FAIL("Cursor invariant broken");
        }
        done = true;
    }

    virtual void set_error(Caller &, aku_Status error_code) override {
        if (done) {
            BOOST_FAIL("Cursor invariant broken");
        }
        done = true;
        error = error_code;
    }
};

std::string make_scan_query(aku_Timestamp begin, aku_Timestamp end) {
    std::stringstream str;
    str << "{ \"range\": { \"from\": " << begin << ", \"to\": " << end << "}}";
    return str.str();
}

void test_storage_read_query(aku_Timestamp begin, aku_Timestamp end/*, StorageEngine::OrderBy order*/) {
    std::vector<std::string> series_names = {
        "test key=0",
        "test key=1",
        "test key=2",
        "test key=3",
        "test key=4",
        "test key=5",
        "test key=6",
        "test key=7",
        "test key=8",
        "test key=9",
    };
    auto storage = create_storage();
    auto session = storage->create_write_session();
    fill_data(session, std::min(begin, end), std::max(begin, end), series_names);
    Caller caller;
    CursorMock cursor;
    auto query = make_scan_query(begin, end);
    session->query(caller, &cursor, query.c_str());
    BOOST_REQUIRE(cursor.done);
    BOOST_REQUIRE_EQUAL(cursor.error, AKU_SUCCESS);
    size_t expected_size;
    if (begin < end) {
        expected_size = (end - begin)*series_names.size();
    } else {
        // because we will read data in (end, begin] range but
        // fill data in [end, begin) range
        expected_size = (begin - end - 1)*series_names.size();
    }
    BOOST_REQUIRE_EQUAL(cursor.samples.size(), expected_size);
}

BOOST_AUTO_TEST_CASE(Test_storage_query) {
    std::vector<std::tuple<aku_Timestamp, aku_Timestamp>> input = {
        std::make_tuple(100ul, 200ul),
        std::make_tuple(200ul, 100ul),
        std::make_tuple(1000ul, 2000ul),
        std::make_tuple(2000ul, 1000ul),
    };
    for (auto tup: input) {
        aku_Timestamp begin;
        aku_Timestamp end;
        std::tie(begin, end) = tup;
        test_storage_read_query(begin, end);
    }
}

// Test reopen

<commit_msg>Storage integration test now checks order-by clause #118<commit_after>#include <iostream>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>
#include <vector>

#include "metadatastorage.h"
#include "storage2.h"

#include "akumuli.h"
#include "log_iface.h"
#include "status_util.h"

// To initialize apr and sqlite properly
#include <apr.h>
#include <sqlite3.h>

using namespace Akumuli;
using namespace StorageEngine;

void test_logger(aku_LogLevel tag, const char* msg) {
    AKU_UNUSED(tag);
    BOOST_MESSAGE(msg);
}

struct AkumuliInitializer {
    AkumuliInitializer() {
        sqlite3_initialize();
        apr_initialize();

        apr_pool_t *pool = nullptr;
        auto status = apr_pool_create(&pool, NULL);
        if (status != APR_SUCCESS) {
            AKU_PANIC("Can't create memory pool");
        }
        apr_dbd_init(pool);

        Akumuli::Logger::set_logger(&test_logger);
    }
};

static AkumuliInitializer initializer;

std::shared_ptr<MetadataStorage> create_metadatastorage() {
    // Create in-memory sqlite database.
    std::shared_ptr<MetadataStorage> meta;
    meta.reset(new MetadataStorage(":memory:"));
    return std::move(meta);
}

std::shared_ptr<ColumnStore> create_cstore() {
    std::shared_ptr<BlockStore> bstore = BlockStoreBuilder::create_memstore();
    std::shared_ptr<ColumnStore> cstore;
    cstore.reset(new ColumnStore(bstore));
    return cstore;
}

std::shared_ptr<Storage> create_storage() {
    auto meta = create_metadatastorage();
    auto bstore = BlockStoreBuilder::create_memstore();
    auto cstore = create_cstore();
    auto store = std::make_shared<Storage>(meta, bstore, cstore, false);
    return store;
}

BOOST_AUTO_TEST_CASE(Test_metadata_storage_volumes_config) {

    MetadataStorage db(":memory:");
    std::vector<MetadataStorage::VolumeDesc> volumes = {
        std::make_pair(0, "first"),
        std::make_pair(1, "second"),
        std::make_pair(2, "third"),
    };
    db.init_volumes(volumes);
    auto actual = db.get_volumes();
    for (int i = 0; i < 3; i++) {
        BOOST_REQUIRE_EQUAL(volumes.at(i).first, actual.at(i).first);
        BOOST_REQUIRE_EQUAL(volumes.at(i).second, actual.at(i).second);
    }
}

BOOST_AUTO_TEST_CASE(Test_metadata_storage_numeric_config) {

    MetadataStorage db(":memory:");
    const char* creation_datetime = "2015-02-03 00:00:00";  // Formatting not required
    db.init_config(creation_datetime);
    std::string actual_dt;
    db.get_configs(&actual_dt);
    BOOST_REQUIRE_EQUAL(creation_datetime, actual_dt);
}

BOOST_AUTO_TEST_CASE(Test_storage_add_series_1) {
    aku_Status status;
    const char* sname = "hello world=1";
    const char* end = sname + strlen(sname);

    auto store = create_storage();
    auto sessiona = store->create_write_session();
    auto sessionb = store->create_write_session();

    aku_Sample samplea;
    status = sessiona->init_series_id(sname, end, &samplea);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    aku_Sample sampleb;
    // Should initialize from global data
    status = sessionb->init_series_id(sname, end, &sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    BOOST_REQUIRE_EQUAL(samplea.paramid, sampleb.paramid);

    // Should read local data
    status = sessionb->init_series_id(sname, end, &sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    BOOST_REQUIRE_EQUAL(samplea.paramid, sampleb.paramid);
}

BOOST_AUTO_TEST_CASE(Test_storage_add_values_1) {
    aku_Status status;
    const char* sname = "hello world=1";
    const char* end = sname + strlen(sname);

    auto store = create_storage();
    auto sessiona = store->create_write_session();
    auto sessionb = store->create_write_session();

    aku_Sample samplea;
    samplea.payload.type = AKU_PAYLOAD_FLOAT;
    samplea.timestamp = 111;
    samplea.payload.float64 = 111;
    status = sessiona->init_series_id(sname, end, &samplea);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
    status = sessiona->write(samplea);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    aku_Sample sampleb;
    sampleb.payload.type = AKU_PAYLOAD_FLOAT;
    sampleb.timestamp = 222;
    sampleb.payload.float64 = 222;
    // Should initialize from global data
    status = sessionb->init_series_id(sname, end, &sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
    status = sessionb->write(sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    BOOST_REQUIRE_EQUAL(samplea.paramid, sampleb.paramid);

    // Should read local data
    sampleb.timestamp = 333;
    sampleb.payload.float64 = 333;
    status = sessiona->init_series_id(sname, end, &sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
    status = sessiona->write(sampleb);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
}

BOOST_AUTO_TEST_CASE(Test_storage_add_values_2) {
    aku_Status status;
    const char* sname = "hello world=1";
    const char* end = sname + strlen(sname);

    auto store = create_storage();
    auto sessiona = store->create_write_session();
    {
        auto sessionb = store->create_write_session();

        aku_Sample sample;
        sample.payload.type = AKU_PAYLOAD_FLOAT;
        sample.timestamp = 111;
        sample.payload.float64 = 111;
        status = sessionb->init_series_id(sname, end, &sample);
        BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
        status = sessionb->write(sample);
        BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

        // disatcher should be freed and registry entry should be returned
    }
    aku_Sample sample;
    sample.payload.type = AKU_PAYLOAD_FLOAT;
    sample.timestamp = 222;
    sample.payload.float64 = 222;

    status = sessiona->init_series_id(sname, end, &sample);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
    status = sessiona->write(sample);
    BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);

    BOOST_REQUIRE_EQUAL(sample.paramid, sample.paramid);
}

// Test read queries

void fill_data(std::shared_ptr<StorageSession> session, aku_Timestamp begin, aku_Timestamp end, std::vector<std::string> const& names) {
    for (aku_Timestamp ts = begin; ts < end; ts++) {
        for (auto it: names) {
            aku_Sample sample;
            sample.timestamp = ts;
            sample.payload.type = AKU_PAYLOAD_FLOAT;
            sample.payload.float64 = double(ts)/10.0;
            auto status = session->init_series_id(it.data(), it.data() + it.size(), &sample);
            if (status != AKU_SUCCESS) {
                BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
            }
            status = session->write(sample);
            if (status != AKU_SUCCESS) {
                BOOST_REQUIRE_EQUAL(status, AKU_SUCCESS);
            }
        }
    }
}

struct CursorMock : InternalCursor {
    bool done;
    std::vector<aku_Sample> samples;
    aku_Status error;

    CursorMock() {
        done = false;
        error = AKU_SUCCESS;
    }

    virtual bool put(Caller&, const aku_Sample &val) override {
        if (done) {
            BOOST_FAIL("Cursor invariant broken");
        }
        samples.push_back(val);
        return true;
    }

    virtual void complete(Caller&) override {
        if (done) {
            BOOST_FAIL("Cursor invariant broken");
        }
        done = true;
    }

    virtual void set_error(Caller &, aku_Status error_code) override {
        if (done) {
            BOOST_FAIL("Cursor invariant broken");
        }
        done = true;
        error = error_code;
    }
};

std::string make_scan_query(aku_Timestamp begin, aku_Timestamp end, OrderBy order) {
    std::stringstream str;
    str << "{ \"range\": { \"from\": " << begin << ", \"to\": " << end << "},";
    str << "  \"order-by\": " << (order == OrderBy::SERIES ? "\"series\"" : "\"time\"");
    str << "}";
    return str.str();
}

void check_timestamps(CursorMock const& mock, aku_Timestamp begin, aku_Timestamp end, OrderBy order, size_t nseries) {
    std::vector<aku_Timestamp> expected;
    if (begin < end) {
        for (aku_Timestamp ts = begin; ts < end; ts++) {
            expected.push_back(ts);
        }
    } else {
        for (aku_Timestamp ts = begin-1; ts > end; ts--) {
            expected.push_back(ts);
        }
    }
    size_t tsix = 0;
    if (order == OrderBy::SERIES) {
        for (size_t s = 0; s < nseries; s++) {
            for (auto expts: expected) {
                BOOST_REQUIRE_EQUAL(expts, mock.samples.at(tsix++).timestamp);
            }
        }
        BOOST_REQUIRE_EQUAL(tsix, mock.samples.size());
    } else {
        for (auto expts: expected) {
            for (size_t s = 0; s < nseries; s++) {
                BOOST_REQUIRE_EQUAL(expts, mock.samples.at(tsix++).timestamp);
            }
        }
        BOOST_REQUIRE_EQUAL(tsix, mock.samples.size());
    }
}

void test_storage_read_query(aku_Timestamp begin, aku_Timestamp end, OrderBy order) {
    std::vector<std::string> series_names = {
        "test key=0",
        "test key=1",
        "test key=2",
        "test key=3",
        "test key=4",
        "test key=5",
        "test key=6",
        "test key=7",
        "test key=8",
        "test key=9",
    };
    auto storage = create_storage();
    auto session = storage->create_write_session();
    fill_data(session, std::min(begin, end), std::max(begin, end), series_names);
    Caller caller;
    CursorMock cursor;
    auto query = make_scan_query(begin, end, order);
    session->query(caller, &cursor, query.c_str());
    BOOST_REQUIRE(cursor.done);
    BOOST_REQUIRE_EQUAL(cursor.error, AKU_SUCCESS);
    size_t expected_size;
    if (begin < end) {
        expected_size = (end - begin)*series_names.size();
    } else {
        // because we will read data in (end, begin] range but
        // fill data in [end, begin) range
        expected_size = (begin - end - 1)*series_names.size();
    }
    BOOST_REQUIRE_EQUAL(cursor.samples.size(), expected_size);
    check_timestamps(cursor, begin, end, order, series_names.size());
}

BOOST_AUTO_TEST_CASE(Test_storage_query) {
    std::vector<std::tuple<aku_Timestamp, aku_Timestamp, OrderBy>> input = {
        std::make_tuple( 100ul,  200ul, OrderBy::TIME),
        std::make_tuple( 200ul,  100ul, OrderBy::TIME),
        std::make_tuple(1000ul, 2000ul, OrderBy::TIME),
        std::make_tuple(2000ul, 1000ul, OrderBy::TIME),
        std::make_tuple( 100ul,  200ul, OrderBy::SERIES),
        std::make_tuple( 200ul,  100ul, OrderBy::SERIES),
        std::make_tuple(1000ul, 2000ul, OrderBy::SERIES),
        std::make_tuple(2000ul, 1000ul, OrderBy::SERIES),
    };
    for (auto tup: input) {
        OrderBy order;
        aku_Timestamp begin;
        aku_Timestamp end;
        std::tie(begin, end, order) = tup;
        test_storage_read_query(begin, end, order);
    }
}

// Test reopen

<|endoftext|>


<commit_before>/* This file is part of the KDE libraries
   Copyright (C) 2003-2005 Hamish Rodda <rodda@kde.org>
   Copyright (C) 2002 Christian Couder <christian@kdevelop.org>
   Copyright (C) 2001, 2003 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include "range.h"

using namespace KTextEditor;

Range::Range()
  : m_start(new Cursor())
  , m_end(new Cursor())
{
  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(const Cursor& start, const Cursor& end)
{
  if (start <= end) {
    m_start = new Cursor(start);
    m_end = new Cursor(end);

  } else {
    m_start = new Cursor(end);
    m_end = new Cursor(start);
  }

  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(const Cursor& start, int width)
  : m_start(new Cursor(start))
  , m_end(new Cursor(start.line(), start.column() + width))
{
  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(const Cursor& start, int endLine, int endColumn)
  : m_start(new Cursor(start))
  , m_end(new Cursor(endLine, endColumn))
{
  if (*m_end < *m_start) {
    Cursor* temp = m_end;
    m_end = m_start;
    m_start = temp;
  }

  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(int startLine, int startColumn, int endLine, int endColumn)
  : m_start(new Cursor(startLine, startColumn))
  , m_end(new Cursor(endLine, endColumn))
{
  if (*m_end < *m_start) {
    Cursor* temp = m_end;
    m_end = m_start;
    m_start = temp;
  }

  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(Cursor* start, Cursor* end)
  : m_start(start)
  , m_end(end)
{
  if (*m_end < *m_start) {
    Cursor temp = *m_end;
    *m_end = *m_start;
    *m_start = temp;
  }

  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(const Range& copy)
  : m_start(new Cursor(copy.start()))
  , m_end(new Cursor(copy.end()))
{
  m_start->setRange(this);
  m_end->setRange(this);
}

Range::~Range()
{
  delete m_start;
  delete m_end;
}

bool Range::isValid( ) const
{
  return start().isValid() && end().isValid();
}

const Range& Range::invalid()
{
  static Range r;
  if (r.start().line() != -1)
    r.setRange(Cursor(-1,-1),Cursor(-1,-1));
  return r;
}

void Range::setRange(const Range& range)
{
  *m_start = range.start();
  *m_end = range.end();
}

void Range::setRange( const Cursor & start, const Cursor & end )
{
  if (start > end)
    setRange(Range(end, start));
  else
    setRange(Range(start, end));
}

bool Range::containsLine(int line) const
{
  return (line > start().line() || line == start().line() && !start().column()) && line < end().line();
}

bool Range::overlapsLine(int line) const
{
  return line >= start().line() && line <= end().line();
}

bool Range::overlapsColumn( int col ) const
{
  return start().column() <= col && end().column() > col;
}

bool Range::contains( const Cursor& cursor ) const
{
  return cursor >= start() && cursor < end();
}

bool Range::contains( const Range& range ) const
{
  return range.start() >= start() && range.end() <= end();
}

bool Range::overlaps( const Range& range ) const
{
  if (range.start() <= start())
    return range.end() > start();

  else if (range.end() >= end())
    return range.start() < end();

  else
    return contains(range);
}

bool Range::boundaryAtCursor(const Cursor& cursor) const
{
  return cursor == start() || cursor == end();
}

bool Range::boundaryOnLine(int line) const
{
  return start().line() == line || end().line() == line;
}

bool Range::confineToRange(const Range& range)
{
  if (start() < range.start())
    if (end() > range.end())
      setRange(range);
    else
      start() = range.start();
  else if (end() > range.end())
    end() = range.end();
  else
    return false;

  return true;
}

bool Range::expandToRange(const Range& range)
{
  if (start() > range.start())
    if (end() < range.end())
      setRange(range);
    else
      start() = range.start();
  else if (end() < range.end())
    end() = range.end();
  else
    return false;

  return true;
}

void Range::rangeChanged( Cursor * c, const Range& )
{
  if (c == m_start) {
    if (*c > *m_end)
      *m_end = *c;

  } else if (c == m_end) {
    if (*c < *m_start)
      *m_start = *c;
  }
}

void Range::setBothLines( int line )
{
  setRange(Range(line, start().column(), line, end().column()));
}

bool KTextEditor::Range::onSingleLine( ) const
{
  return start().line() == end().line();
}

int KTextEditor::Range::columnWidth( ) const
{
  return end().column() - start().column();
}

int KTextEditor::Range::numberOfLines( ) const
{
  return end().line() - start().line();
}

bool KTextEditor::Range::isEmpty( ) const
{
  return start() == end();
}

int Range::positionRelativeToCursor( const Cursor & cursor ) const
{
  if (cursor < start())
    return -1;

  if (cursor > end())
    return +1;

  return 0;
}

int Range::positionRelativeToLine( int line ) const
{
  if (line < start().line())
    return -1;

  if (line > end().line())
    return +1;

  return 0;
}

void KTextEditor::Range::setBothColumns( int column )
{
  setRange(Range(start().line(), column, end().line(), column));
}

bool KTextEditor::Range::isSmartRange( ) const
{
  return false;
}

SmartRange* KTextEditor::Range::toSmartRange( ) const
{
  return 0L;
}

Range KTextEditor::Range::intersect( const Range & range ) const
{
  if (!isValid() || !range.isValid() || *this > range || *this < range)
    return invalid();

  return Range(qMax(start(), range.start()), qMin(end(), range.end()));
}

Range KTextEditor::Range::encompass( const Range & range ) const
{
  if (!isValid())
    if (range.isValid())
      return range;
    else
      return invalid();
  else if (range.isValid())
    return *this;
  else
    return Range(qMin(start(), range.start()), qMax(end(), range.end()));
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>Fix bug in Range::encompass()<commit_after>/* This file is part of the KDE libraries
   Copyright (C) 2003-2005 Hamish Rodda <rodda@kde.org>
   Copyright (C) 2002 Christian Couder <christian@kdevelop.org>
   Copyright (C) 2001, 2003 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include "range.h"

using namespace KTextEditor;

Range::Range()
  : m_start(new Cursor())
  , m_end(new Cursor())
{
  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(const Cursor& start, const Cursor& end)
{
  if (start <= end) {
    m_start = new Cursor(start);
    m_end = new Cursor(end);

  } else {
    m_start = new Cursor(end);
    m_end = new Cursor(start);
  }

  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(const Cursor& start, int width)
  : m_start(new Cursor(start))
  , m_end(new Cursor(start.line(), start.column() + width))
{
  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(const Cursor& start, int endLine, int endColumn)
  : m_start(new Cursor(start))
  , m_end(new Cursor(endLine, endColumn))
{
  if (*m_end < *m_start) {
    Cursor* temp = m_end;
    m_end = m_start;
    m_start = temp;
  }

  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(int startLine, int startColumn, int endLine, int endColumn)
  : m_start(new Cursor(startLine, startColumn))
  , m_end(new Cursor(endLine, endColumn))
{
  if (*m_end < *m_start) {
    Cursor* temp = m_end;
    m_end = m_start;
    m_start = temp;
  }

  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(Cursor* start, Cursor* end)
  : m_start(start)
  , m_end(end)
{
  if (*m_end < *m_start) {
    Cursor temp = *m_end;
    *m_end = *m_start;
    *m_start = temp;
  }

  m_start->setRange(this);
  m_end->setRange(this);
}

Range::Range(const Range& copy)
  : m_start(new Cursor(copy.start()))
  , m_end(new Cursor(copy.end()))
{
  m_start->setRange(this);
  m_end->setRange(this);
}

Range::~Range()
{
  delete m_start;
  delete m_end;
}

bool Range::isValid( ) const
{
  return start().isValid() && end().isValid();
}

const Range& Range::invalid()
{
  static Range r;
  if (r.start().line() != -1)
    r.setRange(Cursor(-1,-1),Cursor(-1,-1));
  return r;
}

void Range::setRange(const Range& range)
{
  *m_start = range.start();
  *m_end = range.end();
}

void Range::setRange( const Cursor & start, const Cursor & end )
{
  if (start > end)
    setRange(Range(end, start));
  else
    setRange(Range(start, end));
}

bool Range::containsLine(int line) const
{
  return (line > start().line() || line == start().line() && !start().column()) && line < end().line();
}

bool Range::overlapsLine(int line) const
{
  return line >= start().line() && line <= end().line();
}

bool Range::overlapsColumn( int col ) const
{
  return start().column() <= col && end().column() > col;
}

bool Range::contains( const Cursor& cursor ) const
{
  return cursor >= start() && cursor < end();
}

bool Range::contains( const Range& range ) const
{
  return range.start() >= start() && range.end() <= end();
}

bool Range::overlaps( const Range& range ) const
{
  if (range.start() <= start())
    return range.end() > start();

  else if (range.end() >= end())
    return range.start() < end();

  else
    return contains(range);
}

bool Range::boundaryAtCursor(const Cursor& cursor) const
{
  return cursor == start() || cursor == end();
}

bool Range::boundaryOnLine(int line) const
{
  return start().line() == line || end().line() == line;
}

bool Range::confineToRange(const Range& range)
{
  if (start() < range.start())
    if (end() > range.end())
      setRange(range);
    else
      start() = range.start();
  else if (end() > range.end())
    end() = range.end();
  else
    return false;

  return true;
}

bool Range::expandToRange(const Range& range)
{
  if (start() > range.start())
    if (end() < range.end())
      setRange(range);
    else
      start() = range.start();
  else if (end() < range.end())
    end() = range.end();
  else
    return false;

  return true;
}

void Range::rangeChanged( Cursor * c, const Range& )
{
  if (c == m_start) {
    if (*c > *m_end)
      *m_end = *c;

  } else if (c == m_end) {
    if (*c < *m_start)
      *m_start = *c;
  }
}

void Range::setBothLines( int line )
{
  setRange(Range(line, start().column(), line, end().column()));
}

bool KTextEditor::Range::onSingleLine( ) const
{
  return start().line() == end().line();
}

int KTextEditor::Range::columnWidth( ) const
{
  return end().column() - start().column();
}

int KTextEditor::Range::numberOfLines( ) const
{
  return end().line() - start().line();
}

bool KTextEditor::Range::isEmpty( ) const
{
  return start() == end();
}

int Range::positionRelativeToCursor( const Cursor & cursor ) const
{
  if (cursor < start())
    return -1;

  if (cursor > end())
    return +1;

  return 0;
}

int Range::positionRelativeToLine( int line ) const
{
  if (line < start().line())
    return -1;

  if (line > end().line())
    return +1;

  return 0;
}

void KTextEditor::Range::setBothColumns( int column )
{
  setRange(Range(start().line(), column, end().line(), column));
}

bool KTextEditor::Range::isSmartRange( ) const
{
  return false;
}

SmartRange* KTextEditor::Range::toSmartRange( ) const
{
  return 0L;
}

Range KTextEditor::Range::intersect( const Range & range ) const
{
  if (!isValid() || !range.isValid() || *this > range || *this < range)
    return invalid();

  return Range(qMax(start(), range.start()), qMin(end(), range.end()));
}

Range KTextEditor::Range::encompass( const Range & range ) const
{
  if (!isValid())
    if (range.isValid())
      return range;
    else
      return invalid();
  else if (!range.isValid())
    return *this;
  else
    return Range(qMin(start(), range.start()), qMax(end(), range.end()));
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>


<commit_before>// Copyright 2014 Toggl Desktop developers.

#include "./timeentrycellwidget.h"
#include "./ui_timeentrycellwidget.h"

#include "./toggl.h"

TimeEntryCellWidget::TimeEntryCellWidget() : QWidget(0),
ui(new Ui::TimeEntryCellWidget),
guid("") {
    ui->setupUi(this);
}

void TimeEntryCellWidget::display(TimeEntryView *view) {
    guid = view->GUID;
    QString description =
        (view->Description.length() > 0) ?
        view->Description : "(no description)";
    ui->description->setText(description);
    ui->project->setText(view->ProjectAndTaskLabel);
    ui->project->setStyleSheet("color: '" + getProjectColor(view->Color) + "'");
    ui->duration->setText(view->Duration);

    ui->billable->setVisible(view->Billable);
    ui->tags->setVisible(!view->Tags.isEmpty());

    ui->headerFrame->setVisible(view->IsHeader);
    ui->date->setText(view->DateHeader);
    ui->dateDuration->setText(view->DateDuration);

    if (view->StartTimeString.length() > 0 &&
            view->EndTimeString.length() > 0) {
        ui->duration->setToolTip(
            QString("
" +
                    view->StartTimeString + " - " + view->EndTimeString+"
"));
    }

    ui->tags->setToolTip(
        QString("
" +
                (view->Tags).replace(QString("\t"), QString(", ")) + "
"));
    if (view->Description.length() > 0) {
        ui->description->setToolTip(
            QString("
" +
                    view->Description + "
"));
    }
    if (view->ProjectAndTaskLabel.length() > 0) {
        ui->project->setToolTip(
            QString("
" +
                    view->ProjectAndTaskLabel + "
"));
    }
}

void TimeEntryCellWidget::labelClicked(QString field_name) {
    TogglApi::instance->editTimeEntry(guid, field_name);
}

TimeEntryCellWidget::~TimeEntryCellWidget() {
    delete ui;
}

QSize TimeEntryCellWidget::getSizeHint(bool is_header) {
    if (is_header) {
        return QSize(minimumWidth(), sizeHint().height());
    }
    return QSize(minimumWidth(), ui->dataFrame->height());
}

void TimeEntryCellWidget::mousePressEvent(QMouseEvent *event) {
    TogglApi::instance->editTimeEntry(guid, "");
    QWidget::mousePressEvent(event);
}

void TimeEntryCellWidget::on_continueButton_clicked() {
    TogglApi::instance->continueTimeEntry(guid);
}

QString TimeEntryCellWidget::getProjectColor(QString color) {
    if (color.length() == 0) {
        return QString("#9d9d9d");
    }
    return color;
}
<commit_msg>fix lint issue (linux)<commit_after>// Copyright 2014 Toggl Desktop developers.

#include "./timeentrycellwidget.h"
#include "./ui_timeentrycellwidget.h"

#include "./toggl.h"

TimeEntryCellWidget::TimeEntryCellWidget() : QWidget(0),
ui(new Ui::TimeEntryCellWidget),
guid("") {
    ui->setupUi(this);
}

void TimeEntryCellWidget::display(TimeEntryView *view) {
    guid = view->GUID;
    QString description =
        (view->Description.length() > 0) ?
        view->Description : "(no description)";
    ui->description->setText(description);
    ui->project->setText(view->ProjectAndTaskLabel);
    ui->project->setStyleSheet("color: '" + getProjectColor(view->Color) + "'");
    ui->duration->setText(view->Duration);

    ui->billable->setVisible(view->Billable);
    ui->tags->setVisible(!view->Tags.isEmpty());

    ui->headerFrame->setVisible(view->IsHeader);
    ui->date->setText(view->DateHeader);
    ui->dateDuration->setText(view->DateDuration);

    if (view->StartTimeString.length() > 0 &&
            view->EndTimeString.length() > 0) {
        ui->duration->setToolTip(
            QString("
" +
                    view->StartTimeString + " - " +
                    view->EndTimeString+"
"));
    }

    ui->tags->setToolTip(
        QString("
" +
                (view->Tags).replace(QString("\t"), QString(", ")) + "
"));
    if (view->Description.length() > 0) {
        ui->description->setToolTip(
            QString("
" +
                    view->Description + "
"));
    }
    if (view->ProjectAndTaskLabel.length() > 0) {
        ui->project->setToolTip(
            QString("
" +
                    view->ProjectAndTaskLabel + "
"));
    }
}

void TimeEntryCellWidget::labelClicked(QString field_name) {
    TogglApi::instance->editTimeEntry(guid, field_name);
}

TimeEntryCellWidget::~TimeEntryCellWidget() {
    delete ui;
}

QSize TimeEntryCellWidget::getSizeHint(bool is_header) {
    if (is_header) {
        return QSize(minimumWidth(), sizeHint().height());
    }
    return QSize(minimumWidth(), ui->dataFrame->height());
}

void TimeEntryCellWidget::mousePressEvent(QMouseEvent *event) {
    TogglApi::instance->editTimeEntry(guid, "");
    QWidget::mousePressEvent(event);
}

void TimeEntryCellWidget::on_continueButton_clicked() {
    TogglApi::instance->continueTimeEntry(guid);
}

QString TimeEntryCellWidget::getProjectColor(QString color) {
    if (color.length() == 0) {
        return QString("#9d9d9d");
    }
    return color;
}
<|endoftext|>


<commit_before>// This file is part of Parsito <http://github.com/ufal/parsito/>.
//
// Copyright 2015 Institute of Formal and Applied Linguistics, Faculty of
// Mathematics and Physics, Charles University in Prague, Czech Republic.
//
// 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 <cmath>

#include "parse_double.h"

namespace ufal {
namespace parsito {

bool parse_double(string_piece str, const char* value_name, double& value, string& error) {
  string_piece original = str;

  // Skip spaces
  while (str.len && (str.str[0] == ' ' || str.str[0] == '\f' || str.str[0] == '\n' || str.str[0] == '\r' || str.str[0] == '\t' || str.str[0] == '\v'))
    str.str++, str.len--;

  // Allow minus
  bool negative = false;
  if (str.len && str.str[0] == '-') {
    negative = true;
    str.str++, str.len--;
  }

  // Parse value, checking for overflow/underflow
  if (!str.len) return error.assign("No non-space character found when parsing ").append(value_name).append(" double value!"), false;
  if (!(str.str[0] >= '0' || str.str[0] <= '9')) return error.assign("Non-digit character found when parsing ").append(value_name).append(" double value '").append(original.str, original.len).append("'!"), false;

  value = 0;
  while (str.len && str.str[0] >= '0' && str.str[0] <= '9') {
    value = 10 * value + (str.str[0] - '0');
    str.str++, str.len--;
  }

  // If there is a decimal point, parse the rest of the
  if (str.len && str.str[0] == '.') {
    double divider = 1;

    str.str++, str.len--;
    while (str.len && str.str[0] >= '0' && str.str[0] <= '9') {
      value = 10 * value + (str.str[0] - '0');
      divider *= 10.;
      str.str++, str.len--;
    }

    value = (value + 0.5) / divider;
  }

  // Apply initial minus
  if (negative) value *= -1;

  // Skip spaces
  while (str.len && (str.str[0] == ' ' || str.str[0] == '\f' || str.str[0] == '\n' || str.str[0] == '\r' || str.str[0] == '\t' || str.str[0] == '\v'))
    str.str++, str.len--;

  // Check for remaining characters
  if (str.len) return error.assign("Non-digit character found when parsing ").append(value_name).append(" double value '").append(original.str, original.len).append("'!"), false;

  return true;
}

double parse_double(string_piece str, const char* value_name) {
  double result;
  string error;

  if (!parse_double(str, value_name, result, error))
    runtime_failure(error);

  return result;
}

} // namespace parsito
} // namespace ufal
<commit_msg>Parse the exact value, not "+0.5" one.<commit_after>// This file is part of Parsito <http://github.com/ufal/parsito/>.
//
// Copyright 2015 Institute of Formal and Applied Linguistics, Faculty of
// Mathematics and Physics, Charles University in Prague, Czech Republic.
//
// 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 <cmath>

#include "parse_double.h"

namespace ufal {
namespace parsito {

bool parse_double(string_piece str, const char* value_name, double& value, string& error) {
  string_piece original = str;

  // Skip spaces
  while (str.len && (str.str[0] == ' ' || str.str[0] == '\f' || str.str[0] == '\n' || str.str[0] == '\r' || str.str[0] == '\t' || str.str[0] == '\v'))
    str.str++, str.len--;

  // Allow minus
  bool negative = false;
  if (str.len && str.str[0] == '-') {
    negative = true;
    str.str++, str.len--;
  }

  // Parse value, checking for overflow/underflow
  if (!str.len) return error.assign("No non-space character found when parsing ").append(value_name).append(" double value!"), false;
  if (!(str.str[0] >= '0' || str.str[0] <= '9')) return error.assign("Non-digit character found when parsing ").append(value_name).append(" double value '").append(original.str, original.len).append("'!"), false;

  value = 0;
  while (str.len && str.str[0] >= '0' && str.str[0] <= '9') {
    value = 10 * value + (str.str[0] - '0');
    str.str++, str.len--;
  }

  // If there is a decimal point, parse the rest of the
  if (str.len && str.str[0] == '.') {
    double divider = 1;

    str.str++, str.len--;
    while (str.len && str.str[0] >= '0' && str.str[0] <= '9') {
      value = 10 * value + (str.str[0] - '0');
      divider *= 10.;
      str.str++, str.len--;
    }

    value /= divider;
  }

  // Apply initial minus
  if (negative) value *= -1;

  // Skip spaces
  while (str.len && (str.str[0] == ' ' || str.str[0] == '\f' || str.str[0] == '\n' || str.str[0] == '\r' || str.str[0] == '\t' || str.str[0] == '\v'))
    str.str++, str.len--;

  // Check for remaining characters
  if (str.len) return error.assign("Non-digit character found when parsing ").append(value_name).append(" double value '").append(original.str, original.len).append("'!"), false;

  return true;
}

double parse_double(string_piece str, const char* value_name) {
  double result;
  string error;

  if (!parse_double(str, value_name, result, error))
    runtime_failure(error);

  return result;
}

} // namespace parsito
} // namespace ufal
<|endoftext|>


<commit_before>// $Id: string_to_enum.C,v 1.3 2005-06-22 14:04:47 benkirk Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

// This library 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 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// 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

// C++ includes
#include <map>

// Local includes
#include "libmesh_common.h"
#include "string_to_enum.h"
#include "enum_elem_type.h"
#include "enum_order.h"
#include "enum_fe_family.h"
#include "enum_inf_map_type.h"

// ------------------------------------------------------------
// Anonymous namespace to hold local data & methods
namespace {

  //----------------------------------------------------
  std::map<std::string, ElemType> elem_type_to_enum;

  // Initialize elem_type_to_enum on first call
  void init_elem_type_to_enum ()
  {
    if (elem_type_to_enum.empty())
      {
	elem_type_to_enum["EDGE2"     ]=EDGE2;
	elem_type_to_enum["EDGE3"     ]=EDGE3;
	elem_type_to_enum["EDGE4"     ]=EDGE4;

	elem_type_to_enum["TRI3"      ]=TRI3;
	elem_type_to_enum["TRI6"      ]=TRI6;

	elem_type_to_enum["QUAD4"     ]=QUAD4;
	elem_type_to_enum["QUAD8"     ]=QUAD8;
	elem_type_to_enum["QUAD9"     ]=QUAD9;

	elem_type_to_enum["TET4"      ]=TET4;
	elem_type_to_enum["TET10"     ]=TET10;

	elem_type_to_enum["HEX8"      ]=HEX8;
	elem_type_to_enum["HEX20"     ]=HEX20;
	elem_type_to_enum["HEX27"     ]=HEX27;

	elem_type_to_enum["PRISM6"    ]=PRISM6;
	elem_type_to_enum["PRISM15"   ]=PRISM15;
	elem_type_to_enum["PRISM18"   ]=PRISM18;

	elem_type_to_enum["PYRAMID5"  ]=PYRAMID5;

	elem_type_to_enum["INFEDGE2"  ]=INFEDGE2;

	elem_type_to_enum["INFQUAD4"  ]=INFQUAD4;
	elem_type_to_enum["INFQUAD6"  ]=INFQUAD6;

	elem_type_to_enum["INFHEX8"   ]=INFHEX8;
	elem_type_to_enum["INFHEX16"  ]=INFHEX16;
	elem_type_to_enum["INFHEX18"  ]=INFHEX18;

	elem_type_to_enum["INFPRISM6" ]=INFPRISM6;
	elem_type_to_enum["INFPRISM12"]=INFPRISM12;
      }
  }

  std::map<ElemType, std::string> enum_to_elem_type;

  // Initialize the enum_to_elem_type on first call
  void init_enum_to_elem_type ()
  {
    // Build reverse map
    if (enum_to_elem_type.empty())
      {
	// Initialize elem_type_to_enum on first call
	init_elem_type_to_enum();

	std::map<std::string, ElemType>::iterator it =
	  elem_type_to_enum.begin();

	for  (; it != elem_type_to_enum.end(); ++it)
	  enum_to_elem_type.insert (std::make_pair(it->second, it->first));

	assert (elem_type_to_enum.size() ==
		enum_to_elem_type.size());
      }
  }

  //---------------------------------------------
  std::map<std::string, Order> order_to_enum;

  // Initialize order_to_enum on first call
  void init_order_to_enum ()
  {
    if (order_to_enum.empty())
      {
	order_to_enum["CONSTANT"     ]=CONSTANT;
	order_to_enum["FIRST"        ]=FIRST;
	order_to_enum["SECOND"       ]=SECOND;
	order_to_enum["THIRD"        ]=THIRD;
	order_to_enum["FOURTH"       ]=FOURTH;
	order_to_enum["FIFTH"        ]=FIFTH;
	order_to_enum["SIXTH"        ]=SIXTH;
	order_to_enum["SEVENTH"      ]=SEVENTH;
	order_to_enum["EIGHTH"       ]=EIGHTH;
	order_to_enum["NINTH"        ]=NINTH;
	order_to_enum["TENTH"        ]=TENTH;

	order_to_enum["ELEVENTH"     ]=ELEVENTH;
	order_to_enum["TWELFTH"      ]=TWELFTH;
	order_to_enum["THIRTEENTH"   ]=THIRTEENTH;
	order_to_enum["FOURTEENTH"   ]=FOURTEENTH;
	order_to_enum["FIFTEENTH"    ]=FIFTEENTH;
	order_to_enum["SIXTEENTH"    ]=SIXTEENTH;
	order_to_enum["SEVENTEENTH"  ]=SEVENTEENTH;
	order_to_enum["EIGHTTEENTH"  ]=EIGHTTEENTH;
	order_to_enum["NINTEENTH"    ]=NINTEENTH;
	order_to_enum["TWENTIETH"    ]=TWENTIETH;

	order_to_enum["TWENTYFIRST"  ]=TWENTYFIRST;
	order_to_enum["TWENTYSECOND" ]=TWENTYSECOND;
	order_to_enum["TWENTYTHIRD"  ]=TWENTYTHIRD;
	order_to_enum["TWENTYFOURTH" ]=TWENTYFOURTH;
	order_to_enum["TWENTYFIFTH"  ]=TWENTYFIFTH;
	order_to_enum["TWENTYSIXTH"  ]=TWENTYSIXTH;
	order_to_enum["TWENTYSEVENTH"]=TWENTYSEVENTH;
	order_to_enum["TWENTYEIGHTH" ]=TWENTYEIGHTH;
	order_to_enum["TWENTYNINTH"  ]=TWENTYNINTH;
	order_to_enum["THIRTIETH"    ]=THIRTIETH;

	order_to_enum["THIRTYFIRST"  ]=THIRTYFIRST;
	order_to_enum["THIRTYSECOND" ]=THIRTYSECOND;
	order_to_enum["THIRTYTHIRD"  ]=THIRTYTHIRD;
	order_to_enum["THIRTYFOURTH" ]=THIRTYFOURTH;
	order_to_enum["THIRTYFIFTH"  ]=THIRTYFIFTH;
	order_to_enum["THIRTYSIXTH"  ]=THIRTYSIXTH;
	order_to_enum["THIRTYSEVENTH"]=THIRTYSEVENTH;
	order_to_enum["THIRTYEIGHTH" ]=THIRTYEIGHTH;
	order_to_enum["THIRTYNINTH"  ]=THIRTYNINTH;
	order_to_enum["FOURTIETH"    ]=FOURTIETH;

	order_to_enum["FOURTYFIRST"  ]=FOURTYFIRST;
	order_to_enum["FOURTYSECOND" ]=FOURTYSECOND;
	order_to_enum["FOURTYTHIRD"  ]=FOURTYTHIRD;
      }
  }

  std::map<Order, std::string> enum_to_order;

  // Initialize the enum_to_order on first call
  void init_enum_to_order ()
  {
    // Build reverse map
    if (enum_to_order.empty())
      {
	// Initialize order_to_enum on first call
	init_order_to_enum();

	std::map<std::string, Order>::iterator it =
	  order_to_enum.begin();

	for  (; it != order_to_enum.end(); ++it)
	  enum_to_order.insert (std::make_pair(it->second, it->first));

	assert (order_to_enum.size() ==
		enum_to_order.size());
      }
  }

  //---------------------------------------------------
  std::map<std::string, FEFamily> fefamily_to_enum;

  // Initialize fefamily_to_enum on first call
  void init_fefamily_to_enum ()
  {
    if (fefamily_to_enum.empty())
      {
	fefamily_to_enum["LAGRANGE"    ]=LAGRANGE;
	fefamily_to_enum["HIERARCHIC"  ]=HIERARCHIC;
	fefamily_to_enum["MONOMIAL"    ]=MONOMIAL;
	fefamily_to_enum["XYZ"         ]=XYZ;
	fefamily_to_enum["BERNSTEIN"   ]=BERNSTEIN;
	fefamily_to_enum["SZABAB"      ]=SZABAB;
	fefamily_to_enum["INFINITE_MAP"]=INFINITE_MAP;
	fefamily_to_enum["JACOBI_20_00"]=JACOBI_20_00;
	fefamily_to_enum["JACOBI_30_00"]=JACOBI_30_00;
	fefamily_to_enum["LEGENDRE"    ]=LEGENDRE;
	fefamily_to_enum["CLOUGH"      ]=CLOUGH;
      }

  }

  std::map<FEFamily, std::string> enum_to_fefamily;

  // Initialize the enum_to_fefamily on first call
  void init_enum_to_fefamily ()
  {
    // Build reverse map
    if (enum_to_fefamily.empty())
      {
	// Initialize fefamily_to_enum on first call
	init_fefamily_to_enum();

	std::map<std::string, FEFamily>::iterator it =
	  fefamily_to_enum.begin();

	for  (; it != fefamily_to_enum.end(); ++it)
	  enum_to_fefamily.insert (std::make_pair(it->second, it->first));

	assert (fefamily_to_enum.size() ==
		enum_to_fefamily.size());
      }
  }

  //---------------------------------------------------
  std::map<std::string, InfMapType> inf_map_type_to_enum;

  // Initialize inf_map_type_to_enum on first call
  void init_inf_map_type_to_enum ()
  {
    if (inf_map_type_to_enum.empty())
      {
	inf_map_type_to_enum["CARTESIAN"  ]=CARTESIAN;
	inf_map_type_to_enum["SPHERICAL"  ]=SPHERICAL;
	inf_map_type_to_enum["ELLIPSOIDAL"]=ELLIPSOIDAL;
      }
  }

  std::map<InfMapType, std::string> enum_to_inf_map_type;

  // Initialize the enum_to_inf_map_type on first call
  void init_enum_to_inf_map_type ()
  {
    // Build reverse map
    if (enum_to_inf_map_type.empty())
      {
	// Initialize inf_map_type_to_enum on first call
	init_inf_map_type_to_enum();

	std::map<std::string, InfMapType>::iterator it =
	  inf_map_type_to_enum.begin();

	for  (; it != inf_map_type_to_enum.end(); ++it)
	  enum_to_inf_map_type.insert (std::make_pair(it->second, it->first));

	assert (inf_map_type_to_enum.size() ==
		enum_to_inf_map_type.size());
      }
  }
} // end anonymous namespace

// ------------------------------------------------------
// Utility::string_to_enum<> & Utility::enum_to_string<>
// full specializations
namespace Utility {

  //------------------------------------------------------
  // ElemType specialization
  template <>
  ElemType string_to_enum<ElemType> (const std::string& s)
  {
    init_elem_type_to_enum();

    if (!elem_type_to_enum.count(s))
      error();

    return elem_type_to_enum[s];
  }

  template <>
  std::string enum_to_string<ElemType> (const ElemType e)
  {
    init_enum_to_elem_type();

    if (!enum_to_elem_type.count(e))
      error();

    return enum_to_elem_type[e];
  }

  //------------------------------------------------
  // Order specialization
  template <>
  Order string_to_enum<Order> (const std::string& s)
  {
    init_order_to_enum();

    if (!order_to_enum.count(s))
      error();

    return order_to_enum[s];
  }

  template <>
  std::string enum_to_string<Order> (const Order o)
  {
    init_enum_to_order();

    if (!enum_to_order.count(o))
      error();

    return enum_to_order[o];
  }

  //------------------------------------------------------
  // FEFamily specialization
  template <>
  FEFamily string_to_enum<FEFamily> (const std::string& s)
  {
    init_fefamily_to_enum();

    if (!fefamily_to_enum.count(s))
      error();

    return fefamily_to_enum[s];
  }

  template <>
  std::string enum_to_string<FEFamily> (const FEFamily f)
  {
    init_enum_to_fefamily();

    if (!enum_to_fefamily.count(f))
      error();

    return enum_to_fefamily[f];
  }

  //------------------------------------------------------
  // InfMapType specialization
  template <>
  InfMapType string_to_enum<InfMapType> (const std::string& s)
  {
    init_inf_map_type_to_enum();

    if (!inf_map_type_to_enum.count(s))
      error();

    return inf_map_type_to_enum[s];
  }

  template <>
  std::string enum_to_string<InfMapType> (const InfMapType i)
  {
    init_enum_to_inf_map_type();

    if (!enum_to_inf_map_type.count(i))
      error();

    return enum_to_inf_map_type[i];
  }
}

<commit_msg>added string conversion for QuadratureType enumeration<commit_after>// $Id: string_to_enum.C,v 1.4 2005-06-28 20:54:14 benkirk Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

// This library 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 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// 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

// C++ includes
#include <map>

// Local includes
#include "libmesh_common.h"
#include "string_to_enum.h"
#include "enum_elem_type.h"
#include "enum_order.h"
#include "enum_fe_family.h"
#include "enum_inf_map_type.h"
#include "enum_quadrature_type.h"

// ------------------------------------------------------------
// Anonymous namespace to hold local data & methods
namespace {

  // Reverse a map
  template <typename MapIter, class MapType>
  inline
  void build_reverse_map (MapIter it, MapIter end, MapType& reverse)
  {
    reverse.clear();

    for (; it != end; ++it)
      reverse.insert (std::make_pair(it->second, it->first));
  }

  //----------------------------------------------------
  std::map<std::string, ElemType> elem_type_to_enum;

  // Initialize elem_type_to_enum on first call
  void init_elem_type_to_enum ()
  {
    if (elem_type_to_enum.empty())
      {
	elem_type_to_enum["EDGE2"     ]=EDGE2;
	elem_type_to_enum["EDGE3"     ]=EDGE3;
	elem_type_to_enum["EDGE4"     ]=EDGE4;

	elem_type_to_enum["TRI3"      ]=TRI3;
	elem_type_to_enum["TRI6"      ]=TRI6;

	elem_type_to_enum["QUAD4"     ]=QUAD4;
	elem_type_to_enum["QUAD8"     ]=QUAD8;
	elem_type_to_enum["QUAD9"     ]=QUAD9;

	elem_type_to_enum["TET4"      ]=TET4;
	elem_type_to_enum["TET10"     ]=TET10;

	elem_type_to_enum["HEX8"      ]=HEX8;
	elem_type_to_enum["HEX20"     ]=HEX20;
	elem_type_to_enum["HEX27"     ]=HEX27;

	elem_type_to_enum["PRISM6"    ]=PRISM6;
	elem_type_to_enum["PRISM15"   ]=PRISM15;
	elem_type_to_enum["PRISM18"   ]=PRISM18;

	elem_type_to_enum["PYRAMID5"  ]=PYRAMID5;

	elem_type_to_enum["INFEDGE2"  ]=INFEDGE2;

	elem_type_to_enum["INFQUAD4"  ]=INFQUAD4;
	elem_type_to_enum["INFQUAD6"  ]=INFQUAD6;

	elem_type_to_enum["INFHEX8"   ]=INFHEX8;
	elem_type_to_enum["INFHEX16"  ]=INFHEX16;
	elem_type_to_enum["INFHEX18"  ]=INFHEX18;

	elem_type_to_enum["INFPRISM6" ]=INFPRISM6;
	elem_type_to_enum["INFPRISM12"]=INFPRISM12;
      }
  }

  std::map<ElemType, std::string> enum_to_elem_type;

  // Initialize the enum_to_elem_type on first call
  void init_enum_to_elem_type ()
  {
    // Build reverse map
    if (enum_to_elem_type.empty())
      {
	// Initialize elem_type_to_enum on first call
	init_elem_type_to_enum();

	build_reverse_map (elem_type_to_enum.begin(),
			   elem_type_to_enum.end(),
			   enum_to_elem_type);
      }
  }

  //---------------------------------------------
  std::map<std::string, Order> order_to_enum;

  // Initialize order_to_enum on first call
  void init_order_to_enum ()
  {
    if (order_to_enum.empty())
      {
	order_to_enum["CONSTANT"     ]=CONSTANT;
	order_to_enum["FIRST"        ]=FIRST;
	order_to_enum["SECOND"       ]=SECOND;
	order_to_enum["THIRD"        ]=THIRD;
	order_to_enum["FOURTH"       ]=FOURTH;
	order_to_enum["FIFTH"        ]=FIFTH;
	order_to_enum["SIXTH"        ]=SIXTH;
	order_to_enum["SEVENTH"      ]=SEVENTH;
	order_to_enum["EIGHTH"       ]=EIGHTH;
	order_to_enum["NINTH"        ]=NINTH;
	order_to_enum["TENTH"        ]=TENTH;

	order_to_enum["ELEVENTH"     ]=ELEVENTH;
	order_to_enum["TWELFTH"      ]=TWELFTH;
	order_to_enum["THIRTEENTH"   ]=THIRTEENTH;
	order_to_enum["FOURTEENTH"   ]=FOURTEENTH;
	order_to_enum["FIFTEENTH"    ]=FIFTEENTH;
	order_to_enum["SIXTEENTH"    ]=SIXTEENTH;
	order_to_enum["SEVENTEENTH"  ]=SEVENTEENTH;
	order_to_enum["EIGHTTEENTH"  ]=EIGHTTEENTH;
	order_to_enum["NINTEENTH"    ]=NINTEENTH;
	order_to_enum["TWENTIETH"    ]=TWENTIETH;

	order_to_enum["TWENTYFIRST"  ]=TWENTYFIRST;
	order_to_enum["TWENTYSECOND" ]=TWENTYSECOND;
	order_to_enum["TWENTYTHIRD"  ]=TWENTYTHIRD;
	order_to_enum["TWENTYFOURTH" ]=TWENTYFOURTH;
	order_to_enum["TWENTYFIFTH"  ]=TWENTYFIFTH;
	order_to_enum["TWENTYSIXTH"  ]=TWENTYSIXTH;
	order_to_enum["TWENTYSEVENTH"]=TWENTYSEVENTH;
	order_to_enum["TWENTYEIGHTH" ]=TWENTYEIGHTH;
	order_to_enum["TWENTYNINTH"  ]=TWENTYNINTH;
	order_to_enum["THIRTIETH"    ]=THIRTIETH;

	order_to_enum["THIRTYFIRST"  ]=THIRTYFIRST;
	order_to_enum["THIRTYSECOND" ]=THIRTYSECOND;
	order_to_enum["THIRTYTHIRD"  ]=THIRTYTHIRD;
	order_to_enum["THIRTYFOURTH" ]=THIRTYFOURTH;
	order_to_enum["THIRTYFIFTH"  ]=THIRTYFIFTH;
	order_to_enum["THIRTYSIXTH"  ]=THIRTYSIXTH;
	order_to_enum["THIRTYSEVENTH"]=THIRTYSEVENTH;
	order_to_enum["THIRTYEIGHTH" ]=THIRTYEIGHTH;
	order_to_enum["THIRTYNINTH"  ]=THIRTYNINTH;
	order_to_enum["FOURTIETH"    ]=FOURTIETH;

	order_to_enum["FOURTYFIRST"  ]=FOURTYFIRST;
	order_to_enum["FOURTYSECOND" ]=FOURTYSECOND;
	order_to_enum["FOURTYTHIRD"  ]=FOURTYTHIRD;
      }
  }

  std::map<Order, std::string> enum_to_order;

  // Initialize the enum_to_order on first call
  void init_enum_to_order ()
  {
    // Build reverse map
    if (enum_to_order.empty())
      {
	// Initialize order_to_enum on first call
	init_order_to_enum();

	build_reverse_map (order_to_enum.begin(),
			   order_to_enum.end(),
			   enum_to_order);
      }
  }

  //---------------------------------------------------
  std::map<std::string, FEFamily> fefamily_to_enum;

  // Initialize fefamily_to_enum on first call
  void init_fefamily_to_enum ()
  {
    if (fefamily_to_enum.empty())
      {
	fefamily_to_enum["LAGRANGE"    ]=LAGRANGE;
	fefamily_to_enum["HIERARCHIC"  ]=HIERARCHIC;
	fefamily_to_enum["MONOMIAL"    ]=MONOMIAL;
	fefamily_to_enum["XYZ"         ]=XYZ;
	fefamily_to_enum["BERNSTEIN"   ]=BERNSTEIN;
	fefamily_to_enum["SZABAB"      ]=SZABAB;
	fefamily_to_enum["INFINITE_MAP"]=INFINITE_MAP;
	fefamily_to_enum["JACOBI_20_00"]=JACOBI_20_00;
	fefamily_to_enum["JACOBI_30_00"]=JACOBI_30_00;
	fefamily_to_enum["LEGENDRE"    ]=LEGENDRE;
	fefamily_to_enum["CLOUGH"      ]=CLOUGH;
      }

  }

  std::map<FEFamily, std::string> enum_to_fefamily;

  // Initialize the enum_to_fefamily on first call
  void init_enum_to_fefamily ()
  {
    // Build reverse map
    if (enum_to_fefamily.empty())
      {
	// Initialize fefamily_to_enum on first call
	init_fefamily_to_enum();

	build_reverse_map (fefamily_to_enum.begin(),
			   fefamily_to_enum.end(),
			   enum_to_fefamily);
      }
  }

  //---------------------------------------------------
  std::map<std::string, InfMapType> inf_map_type_to_enum;

  // Initialize inf_map_type_to_enum on first call
  void init_inf_map_type_to_enum ()
  {
    if (inf_map_type_to_enum.empty())
      {
	inf_map_type_to_enum["CARTESIAN"  ]=CARTESIAN;
	inf_map_type_to_enum["SPHERICAL"  ]=SPHERICAL;
	inf_map_type_to_enum["ELLIPSOIDAL"]=ELLIPSOIDAL;
      }
  }

  std::map<InfMapType, std::string> enum_to_inf_map_type;

  // Initialize the enum_to_inf_map_type on first call
  void init_enum_to_inf_map_type ()
  {
    // Build reverse map
    if (enum_to_inf_map_type.empty())
      {
	// Initialize inf_map_type_to_enum on first call
	init_inf_map_type_to_enum();

	build_reverse_map (inf_map_type_to_enum.begin(),
			   inf_map_type_to_enum.end(),
			   enum_to_inf_map_type);
      }
  }

  //---------------------------------------------------
  std::map<std::string, QuadratureType> quadrature_type_to_enum;

  // Initialize quadrature_type_to_enum on first call
  void init_quadrature_type_to_enum ()
  {
    if (quadrature_type_to_enum.empty())
      {
	quadrature_type_to_enum["QGAUSS"     ]=QGAUSS;
	quadrature_type_to_enum["QJACOBI_1_0"]=QJACOBI_1_0;
	quadrature_type_to_enum["QJACOBI_2_0"]=QJACOBI_2_0;
	quadrature_type_to_enum["QSIMPSON"   ]=QSIMPSON;
	quadrature_type_to_enum["QTRAP"      ]=QTRAP;
	quadrature_type_to_enum["QGRID"      ]=QGRID;
	quadrature_type_to_enum["QCLOUGH"    ]=QCLOUGH;
      }
  }

  std::map<QuadratureType, std::string> enum_to_quadrature_type;

  // Initialize the enum_to_quadrature_type on first call
  void init_enum_to_quadrature_type ()
  {
    // Build reverse map
    if (enum_to_quadrature_type.empty())
      {
	// Initialize inf_map_type_to_enum on first call
	init_quadrature_type_to_enum();

	build_reverse_map (quadrature_type_to_enum.begin(),
			   quadrature_type_to_enum.end(),
			   enum_to_quadrature_type);
      }
  }
} // end anonymous namespace

// ------------------------------------------------------
// Utility::string_to_enum<> & Utility::enum_to_string<>
// full specializations
namespace Utility {

  //------------------------------------------------------
  // ElemType specialization
  template <>
  ElemType string_to_enum<ElemType> (const std::string& s)
  {
    init_elem_type_to_enum();

    if (!elem_type_to_enum.count(s))
      error();

    return elem_type_to_enum[s];
  }

  template <>
  std::string enum_to_string<ElemType> (const ElemType e)
  {
    init_enum_to_elem_type();

    if (!enum_to_elem_type.count(e))
      error();

    return enum_to_elem_type[e];
  }

  //------------------------------------------------
  // Order specialization
  template <>
  Order string_to_enum<Order> (const std::string& s)
  {
    init_order_to_enum();

    if (!order_to_enum.count(s))
      error();

    return order_to_enum[s];
  }

  template <>
  std::string enum_to_string<Order> (const Order o)
  {
    init_enum_to_order();

    if (!enum_to_order.count(o))
      error();

    return enum_to_order[o];
  }

  //------------------------------------------------------
  // FEFamily specialization
  template <>
  FEFamily string_to_enum<FEFamily> (const std::string& s)
  {
    init_fefamily_to_enum();

    if (!fefamily_to_enum.count(s))
      error();

    return fefamily_to_enum[s];
  }

  template <>
  std::string enum_to_string<FEFamily> (const FEFamily f)
  {
    init_enum_to_fefamily();

    if (!enum_to_fefamily.count(f))
      error();

    return enum_to_fefamily[f];
  }

  //------------------------------------------------------
  // InfMapType specialization
  template <>
  InfMapType string_to_enum<InfMapType> (const std::string& s)
  {
    init_inf_map_type_to_enum();

    if (!inf_map_type_to_enum.count(s))
      error();

    return inf_map_type_to_enum[s];
  }

  template <>
  std::string enum_to_string<InfMapType> (const InfMapType i)
  {
    init_enum_to_inf_map_type();

    if (!enum_to_inf_map_type.count(i))
      error();

    return enum_to_inf_map_type[i];
  }

  //------------------------------------------------------
  // QuadratureType specialization
  template <>
  QuadratureType string_to_enum<QuadratureType> (const std::string& s)
  {
    init_quadrature_type_to_enum();

    if (!quadrature_type_to_enum.count(s))
      error();

    return quadrature_type_to_enum[s];
  }

  template <>
  std::string enum_to_string<QuadratureType> (const QuadratureType i)
  {
    init_enum_to_quadrature_type();

    if (!enum_to_quadrature_type.count(i))
      error();

    return enum_to_quadrature_type[i];
  }
}

<|endoftext|>


<commit_before>// -- -x cuda -include inputs/cuda_support_header.h
#include <string>

#include "clang/AST/AST.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::driver;
using namespace clang::tooling;

static llvm::cl::OptionCategory ToolingSampleCategory("Tooling Sample");

class CallExprHandler : public MatchFinder::MatchCallback {
public:
  CallExprHandler(Replacements *Replace) : Replace(Replace) {}

  virtual void run(const MatchFinder::MatchResult &Result) {
    if (const CallExpr *Call =
            Result.Nodes.getNodeAs<clang::CallExpr>("callExpr")) {
      if (const CUDAKernelCallExpr *KernelCall =
              llvm::dyn_cast<CUDAKernelCallExpr>(Call)) {
        KernelCall->dump();
        auto *callee = KernelCall->getCallee();
        llvm::errs() << "@@@@ Callee:\n";
        callee->dump();
        llvm::errs() << "  Location:\n";
        // Note: a SourceLocation points to a token
        callee->getLocStart().dump(*(Result.SourceManager));
        llvm::errs() << "  token length at location: "
                     << Lexer::MeasureTokenLength(
                            callee->getLocStart(), *(Result.SourceManager),
                            Result.Context->getLangOpts()) << "\n";
      }
    }
  }

private:
  Replacements *Replace;
};

int main(int argc, const char **argv) {
  CommonOptionsParser op(argc, argv, ToolingSampleCategory);
  RefactoringTool Tool(op.getCompilations(), op.getSourcePathList());

  // Set up AST matcher callbacks.
  CallExprHandler HandlerForCall(&Tool.getReplacements());

  MatchFinder Finder;
  Finder.addMatcher(callExpr().bind("callExpr"), &HandlerForCall);
  if (int Result = Tool.run(newFrontendActionFactory(&Finder).get())) {
    return Result;
  }

  return 0;
}
<commit_msg>Obtain locs of arguments<commit_after>// -- -x cuda -include inputs/cuda_support_header.h
#include <string>

#include "clang/AST/AST.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::driver;
using namespace clang::tooling;

static llvm::cl::OptionCategory ToolingSampleCategory("Tooling Sample");

class CallExprHandler : public MatchFinder::MatchCallback {
public:
  CallExprHandler(Replacements *Replace) : Replace(Replace) {}

  virtual void run(const MatchFinder::MatchResult &Result) {
    if (const CallExpr *Call =
            Result.Nodes.getNodeAs<clang::CallExpr>("callExpr")) {
      if (const CUDAKernelCallExpr *KernelCall =
              llvm::dyn_cast<CUDAKernelCallExpr>(Call)) {
        KernelCall->dump();
        auto *callee = KernelCall->getCallee();
        llvm::errs() << "@@@@ Callee:\n";
        callee->dump();

        const SourceManager *SM = Result.SourceManager;
        const LangOptions &LOpts = Result.Context->getLangOpts();

        // Note: a SourceLocation points to a token
        llvm::errs() << "  Callee location:\n";
        callee->getLocStart().dump(*SM);
        llvm::errs() << "  token length at location: "
                     << Lexer::MeasureTokenLength(callee->getLocStart(), *SM,
                                                  LOpts) << "\n";

        for (const auto *Arg : KernelCall->arguments()) {
          llvm::errs() << "  argument location:\n";
          llvm::errs() << "    start: ";
          Arg->getLocStart().dump(*SM);
          llvm::errs() << "\n";
          llvm::errs() << "    end: ";
          Arg->getLocEnd().dump(*SM);
          llvm::errs() << "\n";
        }
      }
    }
  }

private:
  Replacements *Replace;
};

int main(int argc, const char **argv) {
  CommonOptionsParser op(argc, argv, ToolingSampleCategory);
  RefactoringTool Tool(op.getCompilations(), op.getSourcePathList());

  // Set up AST matcher callbacks.
  CallExprHandler HandlerForCall(&Tool.getReplacements());

  MatchFinder Finder;
  Finder.addMatcher(callExpr().bind("callExpr"), &HandlerForCall);
  if (int Result = Tool.run(newFrontendActionFactory(&Finder).get())) {
    return Result;
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Adplug - Replayer for many OPL2/OPL3 audio file formats.
 * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al.
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * crctest.cpp - Test AdPlug CRC calculation, by Stas'M <binarymaster@mail.ru>
 */

#include <stdlib.h>
#include <stdio.h>
#include <binfile.h>

#include "../src/fprovide.h"
#include "../src/database.h"

/***** Local variables *****/

// String holding the relative path to the source directory
static char *srcdir;

/***** Local variables *****/

struct crcEntry
{
	const char *filename;
	unsigned short crc16;
	unsigned long  crc32;
};

static const crcEntry testlist[] = {
	{"2001.MKJ", 0x5138, 0xFA44E548},
	{"ADAGIO.DFM", 0x0021, 0xFC217809},
	{"adlibsp.s3m", 0x40A8, 0xC3A4D5BF},
	{NULL, 0, 0}
};

/***** Main program *****/

int main(int argc, char *argv[])
{
	bool retval = true;

	// Set path to source directory
	srcdir = getenv("srcdir");
	if (!srcdir) srcdir = ".";
	{
		const CFileProvider &fp = CProvider_Filesystem();
		for (int i = 0; testlist[i].filename != NULL; i++)
		{
			binistream *f = fp.open(testlist[i].filename);
			if (!f)
			{
				std::cerr << "Error opening for reading: " << testlist[i].filename << "\n";
				retval = false;
				continue;
			}

			f->seek(0);
			CAdPlugDatabase::CKey key(*f);
			fp.close(f);
			std::cout << "Checking CRC16: " << testlist[i].filename;
			if (testlist[i].crc16 != key.crc16)
			{
				std::cout << " [FAIL: " << std::hex << key.crc16 << "]\n";
				retval = false;
			}
			else
				std::cout << " [OK]\n";
			std::cout << "Checking CRC32: " << testlist[i].filename;
			if (testlist[i].crc32 != key.crc32)
			{
				std::cout << " [FAIL: " << std::hex << key.crc32 << "]\n";
				retval = false;
			}
			else
				std::cout << " [OK]\n";
		}
	}

	return retval ? EXIT_SUCCESS : EXIT_FAILURE;
}
<commit_msg>test/crctest.cpp: Fix out-of-source building<commit_after>/*
 * Adplug - Replayer for many OPL2/OPL3 audio file formats.
 * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al.
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * crctest.cpp - Test AdPlug CRC calculation, by Stas'M <binarymaster@mail.ru>
 */

#include <stdlib.h>
#include <stdio.h>
#include <binfile.h>

#include "../src/fprovide.h"
#include "../src/database.h"

#ifdef MSDOS
#	define DIR_DELIM	"\\"
#else
#	define DIR_DELIM	"/"
#endif

/***** Local variables *****/

// String holding the relative path to the source directory
static const char *srcdir;

/***** Local variables *****/

struct crcEntry
{
	const char *filename;
	unsigned short crc16;
	unsigned long  crc32;
};

static const crcEntry testlist[] = {
	{"2001.MKJ", 0x5138, 0xFA44E548},
	{"ADAGIO.DFM", 0x0021, 0xFC217809},
	{"adlibsp.s3m", 0x40A8, 0xC3A4D5BF},
	{NULL, 0, 0}
};

/***** Main program *****/

int main(int argc, char *argv[])
{
	bool retval = true;

	// Set path to source directory
	srcdir = getenv("srcdir");
	if (!srcdir) srcdir = ".";
	{
		const CFileProvider &fp = CProvider_Filesystem();
		for (int i = 0; testlist[i].filename != NULL; i++)
		{
			binistream *f = fp.open(std::string(srcdir) + DIR_DELIM + testlist[i].filename);
			if (!f)
			{
				std::cerr << "Error opening for reading: " << testlist[i].filename << "\n";
				retval = false;
				continue;
			}

			f->seek(0);
			CAdPlugDatabase::CKey key(*f);
			fp.close(f);
			std::cout << "Checking CRC16: " << testlist[i].filename;
			if (testlist[i].crc16 != key.crc16)
			{
				std::cout << " [FAIL: " << std::hex << key.crc16 << "]\n";
				retval = false;
			}
			else
				std::cout << " [OK]\n";
			std::cout << "Checking CRC32: " << testlist[i].filename;
			if (testlist[i].crc32 != key.crc32)
			{
				std::cout << " [FAIL: " << std::hex << key.crc32 << "]\n";
				retval = false;
			}
			else
				std::cout << " [OK]\n";
		}
	}

	return retval ? EXIT_SUCCESS : EXIT_FAILURE;
}
<|endoftext|>


<commit_before>// Copyright 2008, Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  1. Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//  3. Neither the name of Google Inc. 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 AUTHOR ``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 AUTHOR 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.

// This file contains the unit tests for the GpxTrkPtHandler class.

#include "kml/convenience/gpx_trk_pt_handler.h"
#include <vector>
#include "kml/base/expat_parser.h"
#include "kml/base/file.h"
#include "gtest/gtest.h"

// The following define is a convenience for testing inside Google.
#ifdef GOOGLE_INTERNAL
#include "kml/base/google_internal_test.h"
#endif

#ifndef DATADIR
#error *** DATADIR must be defined! ***
#endif

namespace kmlconvenience {

class GpxTrkPtHandlerTest : public testing::Test {
};

typedef std::pair<kmlbase::Vec3, string> WhereWhenPair;
typedef std::vector<WhereWhenPair> PointVector;

// This test class implements a GpxTrkPtHandler which simply saves everything
// passed to HandlePoint into a vector.
class TestGpxTrkPtHandler : public GpxTrkPtHandler {
 public:
  TestGpxTrkPtHandler(PointVector* point_vector)
    : point_vector_(point_vector) {
  }
  void HandlePoint(const kmlbase::Vec3& where, const string& when) {
    point_vector_->push_back(std::make_pair(where, when));
  }
 private:
  PointVector* point_vector_;
};

// By simply compiling this verifies that the HandlePoint method has a default
// implementation.
TEST_F(GpxTrkPtHandlerTest, TestEmpty) {
  GpxTrkPtHandler gpx_trk_pt_handler;
}

// This tests parsing of the <trkpt> element using the StartElement() and
// EndElement() methods.
TEST_F(GpxTrkPtHandlerTest, TestTrkPt) {
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);
  kmlbase::StringVector trk_pt_atts;
  trk_pt_atts.push_back("lat");
  trk_pt_atts.push_back("-123.456");
  trk_pt_atts.push_back("lon");
  trk_pt_atts.push_back("37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trk_pt_atts);
  test_gpx_trk_pt_handler.EndElement("trkpt");
  ASSERT_EQ(static_cast<size_t>(1), point_vector.size());
  const kmlbase::Vec3& vec3 = point_vector[0].first;
  ASSERT_EQ(-123.456, vec3.get_latitude());
  ASSERT_EQ(37.37, vec3.get_longitude());
  ASSERT_TRUE(point_vector[0].second.empty());
}

// This tests parsing of the <ele> element using the StartElement(),
// EndElement(), and CharData() methods.
TEST_F(GpxTrkPtHandlerTest, TestEle) {
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);
  // <ele> is only parsed within a <trkpt> with both lat and lon.
  kmlbase::StringVector trk_pt_atts;
  trk_pt_atts.push_back("lat");
  trk_pt_atts.push_back("-123.456");
  trk_pt_atts.push_back("lon");
  trk_pt_atts.push_back("37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trk_pt_atts);
  //test_gpx_trk_pt_handler.StartElement("ele", NULL);
  const char* kEle("12356.789");
  test_gpx_trk_pt_handler.CharData(kEle);
  test_gpx_trk_pt_handler.EndElement("ele");
  test_gpx_trk_pt_handler.EndElement("trkpt");
  ASSERT_EQ(static_cast<size_t>(1), point_vector.size());
  const kmlbase::Vec3& vec3 = point_vector[0].first;
  ASSERT_EQ(-123.456, vec3.get_latitude());
  ASSERT_EQ(37.37, vec3.get_longitude());
  ASSERT_EQ(12356.789, vec3.get_altitude());
}

// This tests parsing of the <ele> element using the StartElement(),
// EndElement(), and CharData() methods.
TEST_F(GpxTrkPtHandlerTest, TestTime) {
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);
  // <time> is only parsed within a <trkpt> with both lat and lon.
  kmlbase::StringVector trk_pt_atts;
  trk_pt_atts.push_back("lat");
  trk_pt_atts.push_back("-123.456");
  trk_pt_atts.push_back("lon");
  trk_pt_atts.push_back("37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trk_pt_atts);
  // <time>2008-10-03T11:10:01Z</time>
  test_gpx_trk_pt_handler.StartElement("time", kmlbase::StringVector());
  const string kTime("2008-10-03T11:10:01Z");
  test_gpx_trk_pt_handler.CharData(kTime);
  test_gpx_trk_pt_handler.EndElement("time");
  test_gpx_trk_pt_handler.EndElement("trkpt");
  ASSERT_EQ(static_cast<size_t>(1), point_vector.size());
  const kmlbase::Vec3& vec3 = point_vector[0].first;
  ASSERT_EQ(-123.456, vec3.get_latitude());
  ASSERT_EQ(37.37, vec3.get_longitude());
  ASSERT_EQ(kTime, point_vector[0].second);
}

// This verifies that a <trkpt> with no <time> child preceded by one with time
// does not cause that first point's time to be repeated.
TEST_F(GpxTrkPtHandlerTest, TestMissingTime) {
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);

  // Send down one <trkpt> with a <time> child.
  kmlbase::StringVector trkpt0;
  trkpt0.push_back("lat");
  trkpt0.push_back("-123.456");
  trkpt0.push_back("lon");
  trkpt0.push_back("37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trkpt0);
  // <time>2008-10-03T11:10:01Z</time>
  test_gpx_trk_pt_handler.StartElement("time", kmlbase::StringVector());
  const string kTime("2008-10-03T11:10:01Z");
  test_gpx_trk_pt_handler.CharData(kTime);
  test_gpx_trk_pt_handler.EndElement("time");
  test_gpx_trk_pt_handler.EndElement("trkpt");

  // Send down another <trkpt> with no <time> child.
  kmlbase::StringVector trkpt1;
  trkpt1.push_back("lat");
  trkpt1.push_back("123.456");
  trkpt1.push_back("lon");
  trkpt1.push_back("-37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trkpt1);
  test_gpx_trk_pt_handler.EndElement("trkpt");

  ASSERT_EQ(static_cast<size_t>(2), point_vector.size());
  ASSERT_EQ(-123.456, point_vector[0].first.get_latitude());
  ASSERT_EQ(37.37, point_vector[0].first.get_longitude());
  ASSERT_EQ(kTime, point_vector[0].second);

  ASSERT_EQ(123.456, point_vector[1].first.get_latitude());
  ASSERT_EQ(-37.37, point_vector[1].first.get_longitude());
  // This is the key assertion of this test.
  ASSERT_TRUE(point_vector[1].second.empty());
}

// These are some expected values from testdata/gpx/trkpts.gpx.
static const struct {
  const size_t index;
  const double latitude;
  const double longitude;
  const double altitude;
  const char* time;
} kTrkPtsFileData[] = {
  { 0, 39.235658487, -106.315917922, 3012.428223, "2007-09-16T19:22:00Z" },
  { 1, 39.235505015, -106.316187400, 3011.467285, "2007-09-16T19:22:03Z" },
  { 141, 39.251128044, -106.287899902, 3125.864258, "2007-09-16T19:50:18Z" },
  { 142, 39.251178671, -106.287928736, 3125.864258, "2007-09-16T19:50:35Z" }
};

// Verify overall usage of GpxTrkPtHandler on a real-world GPX file.
TEST_F(GpxTrkPtHandlerTest, TestTrkPtFile) {
  // Read the GPX file contents.
  string gpx_data;
  ASSERT_TRUE(kmlbase::File::ReadFileToString(
      string(DATADIR) + "/gpx/trkpts.gpx", &gpx_data));
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);
  string errors;
  ASSERT_TRUE(kmlbase::ExpatParser::ParseString(
        gpx_data, &test_gpx_trk_pt_handler, &errors, false));
  ASSERT_TRUE(errors.empty());
  ASSERT_EQ(static_cast<size_t>(143), point_vector.size());
  size_t size = sizeof(kTrkPtsFileData)/sizeof(kTrkPtsFileData[0]);
  for (size_t i = 0; i < size; ++i) {
    size_t index = kTrkPtsFileData[i].index;
    ASSERT_EQ(kTrkPtsFileData[i].latitude,
                         point_vector[index].first.get_latitude());
    ASSERT_EQ(kTrkPtsFileData[i].longitude,
                         point_vector[index].first.get_longitude());
    ASSERT_EQ(kTrkPtsFileData[i].altitude,
                         point_vector[index].first.get_altitude());
    ASSERT_EQ(string(kTrkPtsFileData[i].time),
                         point_vector[index].second);
  }
}

}  // namespace kmlconvenience

int main(int argc, char** argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>fix failing test<commit_after>// Copyright 2008, Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  1. Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//  3. Neither the name of Google Inc. 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 AUTHOR ``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 AUTHOR 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.

// This file contains the unit tests for the GpxTrkPtHandler class.

#include "kml/convenience/gpx_trk_pt_handler.h"
#include <vector>
#include "kml/base/expat_parser.h"
#include "kml/base/file.h"
#include "gtest/gtest.h"

// The following define is a convenience for testing inside Google.
#ifdef GOOGLE_INTERNAL
#include "kml/base/google_internal_test.h"
#endif

#ifndef DATADIR
#error *** DATADIR must be defined! ***
#endif

namespace kmlconvenience {

class GpxTrkPtHandlerTest : public testing::Test {
 protected:
  kmlbase::StringVector atts_;
};

typedef std::pair<kmlbase::Vec3, string> WhereWhenPair;
typedef std::vector<WhereWhenPair> PointVector;

// This test class implements a GpxTrkPtHandler which simply saves everything
// passed to HandlePoint into a vector.
class TestGpxTrkPtHandler : public GpxTrkPtHandler {
 public:
  TestGpxTrkPtHandler(PointVector* point_vector)
    : point_vector_(point_vector) {
  }
  void HandlePoint(const kmlbase::Vec3& where, const string& when) {
    point_vector_->push_back(std::make_pair(where, when));
  }
 private:
  PointVector* point_vector_;
};

// By simply compiling this verifies that the HandlePoint method has a default
// implementation.
TEST_F(GpxTrkPtHandlerTest, TestEmpty) {
  GpxTrkPtHandler gpx_trk_pt_handler;
}

// This tests parsing of the <trkpt> element using the StartElement() and
// EndElement() methods.
TEST_F(GpxTrkPtHandlerTest, TestTrkPt) {
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);
  kmlbase::StringVector trk_pt_atts;
  trk_pt_atts.push_back("lat");
  trk_pt_atts.push_back("-123.456");
  trk_pt_atts.push_back("lon");
  trk_pt_atts.push_back("37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trk_pt_atts);
  test_gpx_trk_pt_handler.EndElement("trkpt");
  ASSERT_EQ(static_cast<size_t>(1), point_vector.size());
  const kmlbase::Vec3& vec3 = point_vector[0].first;
  ASSERT_EQ(-123.456, vec3.get_latitude());
  ASSERT_EQ(37.37, vec3.get_longitude());
  ASSERT_TRUE(point_vector[0].second.empty());
}

// This tests parsing of the <ele> element using the StartElement(),
// EndElement(), and CharData() methods.
TEST_F(GpxTrkPtHandlerTest, TestEle) {
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);
  // <ele> is only parsed within a <trkpt> with both lat and lon.
  kmlbase::StringVector trk_pt_atts;
  trk_pt_atts.push_back("lat");
  trk_pt_atts.push_back("-123.456");
  trk_pt_atts.push_back("lon");
  trk_pt_atts.push_back("37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trk_pt_atts);
  test_gpx_trk_pt_handler.StartElement("ele", atts_);
  const char* kEle("12356.789");
  test_gpx_trk_pt_handler.CharData(kEle);
  test_gpx_trk_pt_handler.EndElement("ele");
  test_gpx_trk_pt_handler.EndElement("trkpt");
  ASSERT_EQ(static_cast<size_t>(1), point_vector.size());
  const kmlbase::Vec3& vec3 = point_vector[0].first;
  ASSERT_EQ(-123.456, vec3.get_latitude());
  ASSERT_EQ(37.37, vec3.get_longitude());
  ASSERT_EQ(12356.789, vec3.get_altitude());
}

// This tests parsing of the <ele> element using the StartElement(),
// EndElement(), and CharData() methods.
TEST_F(GpxTrkPtHandlerTest, TestTime) {
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);
  // <time> is only parsed within a <trkpt> with both lat and lon.
  kmlbase::StringVector trk_pt_atts;
  trk_pt_atts.push_back("lat");
  trk_pt_atts.push_back("-123.456");
  trk_pt_atts.push_back("lon");
  trk_pt_atts.push_back("37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trk_pt_atts);
  // <time>2008-10-03T11:10:01Z</time>
  test_gpx_trk_pt_handler.StartElement("time", kmlbase::StringVector());
  const string kTime("2008-10-03T11:10:01Z");
  test_gpx_trk_pt_handler.CharData(kTime);
  test_gpx_trk_pt_handler.EndElement("time");
  test_gpx_trk_pt_handler.EndElement("trkpt");
  ASSERT_EQ(static_cast<size_t>(1), point_vector.size());
  const kmlbase::Vec3& vec3 = point_vector[0].first;
  ASSERT_EQ(-123.456, vec3.get_latitude());
  ASSERT_EQ(37.37, vec3.get_longitude());
  ASSERT_EQ(kTime, point_vector[0].second);
}

// This verifies that a <trkpt> with no <time> child preceded by one with time
// does not cause that first point's time to be repeated.
TEST_F(GpxTrkPtHandlerTest, TestMissingTime) {
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);

  // Send down one <trkpt> with a <time> child.
  kmlbase::StringVector trkpt0;
  trkpt0.push_back("lat");
  trkpt0.push_back("-123.456");
  trkpt0.push_back("lon");
  trkpt0.push_back("37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trkpt0);
  // <time>2008-10-03T11:10:01Z</time>
  test_gpx_trk_pt_handler.StartElement("time", kmlbase::StringVector());
  const string kTime("2008-10-03T11:10:01Z");
  test_gpx_trk_pt_handler.CharData(kTime);
  test_gpx_trk_pt_handler.EndElement("time");
  test_gpx_trk_pt_handler.EndElement("trkpt");

  // Send down another <trkpt> with no <time> child.
  kmlbase::StringVector trkpt1;
  trkpt1.push_back("lat");
  trkpt1.push_back("123.456");
  trkpt1.push_back("lon");
  trkpt1.push_back("-37.37");
  test_gpx_trk_pt_handler.StartElement("trkpt", trkpt1);
  test_gpx_trk_pt_handler.EndElement("trkpt");

  ASSERT_EQ(static_cast<size_t>(2), point_vector.size());
  ASSERT_EQ(-123.456, point_vector[0].first.get_latitude());
  ASSERT_EQ(37.37, point_vector[0].first.get_longitude());
  ASSERT_EQ(kTime, point_vector[0].second);

  ASSERT_EQ(123.456, point_vector[1].first.get_latitude());
  ASSERT_EQ(-37.37, point_vector[1].first.get_longitude());
  // This is the key assertion of this test.
  ASSERT_TRUE(point_vector[1].second.empty());
}

// These are some expected values from testdata/gpx/trkpts.gpx.
static const struct {
  const size_t index;
  const double latitude;
  const double longitude;
  const double altitude;
  const char* time;
} kTrkPtsFileData[] = {
  { 0, 39.235658487, -106.315917922, 3012.428223, "2007-09-16T19:22:00Z" },
  { 1, 39.235505015, -106.316187400, 3011.467285, "2007-09-16T19:22:03Z" },
  { 141, 39.251128044, -106.287899902, 3125.864258, "2007-09-16T19:50:18Z" },
  { 142, 39.251178671, -106.287928736, 3125.864258, "2007-09-16T19:50:35Z" }
};

// Verify overall usage of GpxTrkPtHandler on a real-world GPX file.
TEST_F(GpxTrkPtHandlerTest, TestTrkPtFile) {
  // Read the GPX file contents.
  string gpx_data;
  ASSERT_TRUE(kmlbase::File::ReadFileToString(
      string(DATADIR) + "/gpx/trkpts.gpx", &gpx_data));
  PointVector point_vector;
  TestGpxTrkPtHandler test_gpx_trk_pt_handler(&point_vector);
  string errors;
  ASSERT_TRUE(kmlbase::ExpatParser::ParseString(
        gpx_data, &test_gpx_trk_pt_handler, &errors, false));
  ASSERT_TRUE(errors.empty());
  ASSERT_EQ(static_cast<size_t>(143), point_vector.size());
  size_t size = sizeof(kTrkPtsFileData)/sizeof(kTrkPtsFileData[0]);
  for (size_t i = 0; i < size; ++i) {
    size_t index = kTrkPtsFileData[i].index;
    ASSERT_EQ(kTrkPtsFileData[i].latitude,
                         point_vector[index].first.get_latitude());
    ASSERT_EQ(kTrkPtsFileData[i].longitude,
                         point_vector[index].first.get_longitude());
    ASSERT_EQ(kTrkPtsFileData[i].altitude,
                         point_vector[index].first.get_altitude());
    ASSERT_EQ(string(kTrkPtsFileData[i].time),
                         point_vector[index].second);
  }
}

}  // namespace kmlconvenience

int main(int argc, char** argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>