<commit_before>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "ConfigParser.hxx"
#include "LineParser.hxx"
#include "system/Error.hxx"
#include "util/ScopeExit.hxx"

#include <inline/compiler.h>

#include <assert.h>
#include <errno.h>

bool
ConfigParser::PreParseLine(gcc_unused LineParser &line)
{
    return false;
}

bool
NestedConfigParser::PreParseLine(LineParser &line)
{
    if (child) {
        if (child->PreParseLine(line))
            return true;

        if (line.SkipSymbol('}')) {
            line.ExpectEnd();
            child->Finish();
            child.reset();
            return true;
        }
    }

    return ConfigParser::PreParseLine(line);
}

void
NestedConfigParser::ParseLine(LineParser &line)
{
    if (child)
        child->ParseLine(line);
    else
        ParseLine2(line);
}

void
NestedConfigParser::Finish()
{
    if (child)
        throw LineParser::Error("Block not closed at end of file");

    ConfigParser::Finish();
}

void
NestedConfigParser::SetChild(std::unique_ptr<ConfigParser> &&_child)
{
    assert(!child);

    child = std::move(_child);
}

bool
CommentConfigParser::PreParseLine(LineParser &line)
{
    if (child.PreParseLine(line))
        return true;

    if (line.front() == '#' || line.IsEnd())
        /* ignore empty lines and comments */
        return true;

    return ConfigParser::PreParseLine(line);
}

void
CommentConfigParser::ParseLine(LineParser &line)
{
    child.ParseLine(line);
}

void
CommentConfigParser::Finish()
{
    child.Finish();
    ConfigParser::Finish();
}

bool
IncludeConfigParser::PreParseLine(LineParser &line)
{
    return child.PreParseLine(line);
}

void
IncludeConfigParser::ParseLine(LineParser &line)
{
    if (line.SkipWord("include")) {
        const char *p = line.NextUnescape();
        if (p == nullptr)
            throw LineParser::Error("Quoted path expected");

        line.ExpectEnd();

        IncludePath(p);
    } else if (line.SkipWord("include_optional")) {
        const char *p = line.NextUnescape();
        if (p == nullptr)
            throw LineParser::Error("Quoted path expected");

        line.ExpectEnd();

        IncludeOptionalPath(p);
    } else
        child.ParseLine(line);
}

void
IncludeConfigParser::Finish()
{
    child.Finish();
}

static std::string
ApplyPath(const char *base, const char *p)
{
    if (*p == '/')
        /* is already absolute */
        return p;

    const char *slash = strrchr(base, '/');
    if (slash == nullptr)
        return p;

    return std::string(base, slash + 1) + p;
}

inline void
IncludeConfigParser::IncludePath(const char *p)
{
    IncludeConfigParser sub(ApplyPath(path.c_str(), p), child);
    ParseConfigFile(sub.path.c_str(), sub);
}

static void
ParseConfigFile(const char *path, FILE *file, ConfigParser &parser)
{
    char buffer[4096], *line;
    unsigned i = 1;
    while ((line = fgets(buffer, sizeof(buffer), file)) != nullptr) {
        LineParser line_parser(line);

        try {
            if (!parser.PreParseLine(line_parser))
                parser.ParseLine(line_parser);
        } catch (...) {
            std::throw_with_nested(LineParser::Error(std::string(path) + ':' + std::to_string(i)));
        }

        ++i;
    }
}

inline void
IncludeConfigParser::IncludeOptionalPath(const char *p)
{
    IncludeConfigParser sub(ApplyPath(path.c_str(), p), child);

    FILE *file = fopen(sub.path.c_str(), "r");
    if (file == nullptr) {
        int e = errno;
        switch (e) {
        case ENOENT:
        case ENOTDIR:
            /* silently ignore this error */
            return;

        default:
            throw FormatErrno(e, "Failed to open %s", path);
        }
    }

    AtScopeExit(file) { fclose(file); };

    ParseConfigFile(sub.path.c_str(), file, sub);
    sub.Finish();
}

void
ParseConfigFile(const char *path, ConfigParser &parser)
{
    FILE *file = fopen(path, "r");
    if (file == nullptr)
        throw FormatErrno("Failed to open %s", path);

    AtScopeExit(file) { fclose(file); };

    ParseConfigFile(path, file, parser);
    parser.Finish();
}
<commit_msg>ConfigParser: fix FormatErrno() call<commit_after>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "ConfigParser.hxx"
#include "LineParser.hxx"
#include "system/Error.hxx"
#include "util/ScopeExit.hxx"

#include <inline/compiler.h>

#include <assert.h>
#include <errno.h>

bool
ConfigParser::PreParseLine(gcc_unused LineParser &line)
{
    return false;
}

bool
NestedConfigParser::PreParseLine(LineParser &line)
{
    if (child) {
        if (child->PreParseLine(line))
            return true;

        if (line.SkipSymbol('}')) {
            line.ExpectEnd();
            child->Finish();
            child.reset();
            return true;
        }
    }

    return ConfigParser::PreParseLine(line);
}

void
NestedConfigParser::ParseLine(LineParser &line)
{
    if (child)
        child->ParseLine(line);
    else
        ParseLine2(line);
}

void
NestedConfigParser::Finish()
{
    if (child)
        throw LineParser::Error("Block not closed at end of file");

    ConfigParser::Finish();
}

void
NestedConfigParser::SetChild(std::unique_ptr<ConfigParser> &&_child)
{
    assert(!child);

    child = std::move(_child);
}

bool
CommentConfigParser::PreParseLine(LineParser &line)
{
    if (child.PreParseLine(line))
        return true;

    if (line.front() == '#' || line.IsEnd())
        /* ignore empty lines and comments */
        return true;

    return ConfigParser::PreParseLine(line);
}

void
CommentConfigParser::ParseLine(LineParser &line)
{
    child.ParseLine(line);
}

void
CommentConfigParser::Finish()
{
    child.Finish();
    ConfigParser::Finish();
}

bool
IncludeConfigParser::PreParseLine(LineParser &line)
{
    return child.PreParseLine(line);
}

void
IncludeConfigParser::ParseLine(LineParser &line)
{
    if (line.SkipWord("include")) {
        const char *p = line.NextUnescape();
        if (p == nullptr)
            throw LineParser::Error("Quoted path expected");

        line.ExpectEnd();

        IncludePath(p);
    } else if (line.SkipWord("include_optional")) {
        const char *p = line.NextUnescape();
        if (p == nullptr)
            throw LineParser::Error("Quoted path expected");

        line.ExpectEnd();

        IncludeOptionalPath(p);
    } else
        child.ParseLine(line);
}

void
IncludeConfigParser::Finish()
{
    child.Finish();
}

static std::string
ApplyPath(const char *base, const char *p)
{
    if (*p == '/')
        /* is already absolute */
        return p;

    const char *slash = strrchr(base, '/');
    if (slash == nullptr)
        return p;

    return std::string(base, slash + 1) + p;
}

inline void
IncludeConfigParser::IncludePath(const char *p)
{
    IncludeConfigParser sub(ApplyPath(path.c_str(), p), child);
    ParseConfigFile(sub.path.c_str(), sub);
}

static void
ParseConfigFile(const char *path, FILE *file, ConfigParser &parser)
{
    char buffer[4096], *line;
    unsigned i = 1;
    while ((line = fgets(buffer, sizeof(buffer), file)) != nullptr) {
        LineParser line_parser(line);

        try {
            if (!parser.PreParseLine(line_parser))
                parser.ParseLine(line_parser);
        } catch (...) {
            std::throw_with_nested(LineParser::Error(std::string(path) + ':' + std::to_string(i)));
        }

        ++i;
    }
}

inline void
IncludeConfigParser::IncludeOptionalPath(const char *p)
{
    IncludeConfigParser sub(ApplyPath(path.c_str(), p), child);

    FILE *file = fopen(sub.path.c_str(), "r");
    if (file == nullptr) {
        int e = errno;
        switch (e) {
        case ENOENT:
        case ENOTDIR:
            /* silently ignore this error */
            return;

        default:
            throw FormatErrno(e, "Failed to open %s", sub.path.c_str());
        }
    }

    AtScopeExit(file) { fclose(file); };

    ParseConfigFile(sub.path.c_str(), file, sub);
    sub.Finish();
}

void
ParseConfigFile(const char *path, ConfigParser &parser)
{
    FILE *file = fopen(path, "r");
    if (file == nullptr)
        throw FormatErrno("Failed to open %s", path);

    AtScopeExit(file) { fclose(file); };

    ParseConfigFile(path, file, parser);
    parser.Finish();
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %built_cling -fno-rtti 2>&1 | FileCheck %s
// Test Lookup::Named and Namespace, used in quick simple lookups.

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/LookupHelper.h"
#include "cling/Utils/AST.h"

#include "clang/AST/Decl.h"
#include "clang/AST/Tag.h"

#include <cstdio>

using namespace cling;
using namespace llvm;

.rawInput 1

enum class E {};
class C {};

namespace N {
enum class Inside_E {};
class C {};
}

.rawInput 0

clang::Sema& S = gCling->getSema();
const LookupHelper& lookup = gCling->getLookupHelper();
LookupHelper::DiagSetting diags = LookupHelper::WithDiagnostics;

const clang::TagDecl *tagdecl{nullptr};

tagdecl = utils::Lookup::Tag(&S, "E", nullptr);
tagdecl
//CHECK: (const clang::TagDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
tagdecl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "N"

tagdecl = utils::Lookup::Tag(&S, "C", nullptr);
tagdecl
//CHECK: (const clang::TagDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
tagdecl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "C"

const clang::NamedDeck *nameddecl{nullptr};

nameddecl = utils::Lookup::Named(&S, "N", nullptr);
nameddecl
//CHECK: (const clang::NamedDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
decl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "N"

const clang::DeclContext *context = dyn_cast<clang::DeclContext>(decl);
context
//CHECK: (const clang::DeclContext *) 0x{{[1-9a-f][0-9a-f]*$}}

decl = utils::Lookup::Tag(&S, "E", context);
decl
//CHECK: (const clang::TagDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
decl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "N::E"

decl = utils::Lookup::Tag(&S, "C", context);
decl
//CHECK: (const clang::TagDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
decl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "N::C"
<commit_msg>[Cling] Fix Tag test: the test failed because of a typo<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %built_cling -fno-rtti 2>&1 | FileCheck %s
// Test Lookup::Named and Namespace, used in quick simple lookups.

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/LookupHelper.h"
#include "cling/Utils/AST.h"

#include "clang/AST/Decl.h"
#include "clang/AST/Tag.h"

#include <cstdio>

using namespace cling;
using namespace llvm;

.rawInput 1

enum class E {};
class C {};

namespace N {
enum class Inside_E {};
class C {};
}

.rawInput 0

clang::Sema& S = gCling->getSema();
const LookupHelper& lookup = gCling->getLookupHelper();
LookupHelper::DiagSetting diags = LookupHelper::WithDiagnostics;

const clang::TagDecl *tagdecl{nullptr};

tagdecl = utils::Lookup::Tag(&S, "E", nullptr);
tagdecl
//CHECK: (const clang::TagDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
tagdecl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "E"

tagdecl = utils::Lookup::Tag(&S, "C", nullptr);
tagdecl
//CHECK: (const clang::TagDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
tagdecl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "C"

const clang::NamedDeck *nameddecl{nullptr};

nameddecl = utils::Lookup::Named(&S, "N", nullptr);
nameddecl
//CHECK: (const clang::NamedDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
decl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "N"

const clang::DeclContext *context = dyn_cast<clang::DeclContext>(decl);
context
//CHECK: (const clang::DeclContext *) 0x{{[1-9a-f][0-9a-f]*$}}

decl = utils::Lookup::Tag(&S, "E", context);
decl
//CHECK: (const clang::TagDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
decl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "N::E"

decl = utils::Lookup::Tag(&S, "C", context);
decl
//CHECK: (const clang::TagDecl *) 0x{{[1-9a-f][0-9a-f]*$}}
decl->getQualifiedNameAsString().c_str()
//CHECK-NEXT: ({{[^)]+}}) "N::C"
<|endoftext|>


<commit_before><commit_msg>Update Main.cpp<commit_after><|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "breakwindow.h"

#include "debuggeractions.h"
#include "debuggermanager.h"
#include "ui_breakcondition.h"
#include "ui_breakbyfunction.h"

#include <utils/qtcassert.h>
#include <utils/savedaction.h>

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QFileInfoList>

#include <QtGui/QAction>
#include <QtGui/QHeaderView>
#include <QtGui/QKeyEvent>
#include <QtGui/QMenu>
#include <QtGui/QResizeEvent>
#include <QtGui/QItemSelectionModel>
#include <QtGui/QToolButton>
#include <QtGui/QTreeView>

using Debugger::Internal::BreakWindow;

///////////////////////////////////////////////////////////////////////
//
// BreakByFunctionDialog
//
///////////////////////////////////////////////////////////////////////

class BreakByFunctionDialog : public QDialog, Ui::BreakByFunctionDialog
{
public:
    explicit BreakByFunctionDialog(QWidget *parent)
      : QDialog(parent)
    {
        setupUi(this);
        connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
        connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
    }
    QString functionName() const { return functionLineEdit->text(); }
};

///////////////////////////////////////////////////////////////////////
//
// BreakWindow
//
///////////////////////////////////////////////////////////////////////

BreakWindow::BreakWindow(Debugger::DebuggerManager *manager)
  : m_manager(manager), m_alwaysResizeColumnsToContents(false)
{
    QAction *act = theDebuggerAction(UseAlternatingRowColors);
    setFrameStyle(QFrame::NoFrame);
    setWindowTitle(tr("Breakpoints"));
    setWindowIcon(QIcon(":/debugger/images/debugger_breakpoints.png"));
    setAlternatingRowColors(act->isChecked());
    setRootIsDecorated(false);
    setIconSize(QSize(10, 10));
    setSelectionMode(QAbstractItemView::ExtendedSelection);

    connect(this, SIGNAL(activated(QModelIndex)),
        this, SLOT(rowActivated(QModelIndex)));
    connect(act, SIGNAL(toggled(bool)),
        this, SLOT(setAlternatingRowColorsHelper(bool)));
    connect(theDebuggerAction(UseAddressInBreakpointsView), SIGNAL(toggled(bool)),
        this, SLOT(showAddressColumn(bool)));
}

void BreakWindow::showAddressColumn(bool on)
{
    setColumnHidden(6, !on);
}

static QModelIndexList normalizeIndexes(const QModelIndexList &list)
{
    QModelIndexList res;
    foreach (const QModelIndex &idx, list)
        if (idx.column() == 0)
            res.append(idx);
    return res;
}

void BreakWindow::keyPressEvent(QKeyEvent *ev)
{
    if (ev->key() == Qt::Key_Delete) {
        QItemSelectionModel *sm = selectionModel();
        QTC_ASSERT(sm, return);
        QModelIndexList si = sm->selectedIndexes();
        if (si.isEmpty())
            si.append(currentIndex().sibling(currentIndex().row(), 0));
        deleteBreakpoints(normalizeIndexes(si));
    }
    QTreeView::keyPressEvent(ev);
}

void BreakWindow::resizeEvent(QResizeEvent *ev)
{
    QTreeView::resizeEvent(ev);
}

void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
{
    QMenu menu;
    const QAbstractItemModel *itemModel = model();
    QItemSelectionModel *sm = selectionModel();
    QTC_ASSERT(sm, return);
    QModelIndexList si = sm->selectedIndexes();
    QModelIndex indexUnderMouse = indexAt(ev->pos());
    if (si.isEmpty() && indexUnderMouse.isValid())
        si.append(indexUnderMouse.sibling(indexUnderMouse.row(), 0));
    si = normalizeIndexes(si);

    const int rowCount = itemModel->rowCount();
    const unsigned engineCapabilities = m_manager->debuggerCapabilities();

    QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu);
    deleteAction->setEnabled(si.size() > 0);

    QAction *deleteAllAction = new QAction(tr("Delete All Breakpoints"), &menu);
    deleteAllAction->setEnabled(si.size() > 0);

    // Delete by file: Find indices of breakpoints of the same file.
    QAction *deleteByFileAction = 0;
    QList<int> breakPointsOfFile;
    if (indexUnderMouse.isValid()) {
        const QModelIndex index = indexUnderMouse.sibling(indexUnderMouse.row(), 2);
        const QString file = itemModel->data(index).toString();
        if (!file.isEmpty()) {
            for (int i = 0; i < rowCount; i++)
                if (itemModel->data(itemModel->index(i, 2)).toString() == file)
                    breakPointsOfFile.push_back(i);
            if (breakPointsOfFile.size() > 1) {
                deleteByFileAction =
                    new QAction(tr("Delete Breakpoints of \"%1\"").arg(file), &menu);
                deleteByFileAction->setEnabled(true);
            }
        }
    }
    if (!deleteByFileAction) {
        deleteByFileAction = new QAction(tr("Delete Breakpoints of File"), &menu);
        deleteByFileAction->setEnabled(false);
    }

    QAction *adjustColumnAction =
        new QAction(tr("Adjust Column Widths to Contents"), &menu);

    QAction *alwaysAdjustAction =
        new QAction(tr("Always Adjust Column Widths to Contents"), &menu);

    alwaysAdjustAction->setCheckable(true);
    alwaysAdjustAction->setChecked(m_alwaysResizeColumnsToContents);

    QAction *editConditionAction =
        new QAction(tr("Edit Condition..."), &menu);
    editConditionAction->setEnabled(si.size() > 0);

    QAction *synchronizeAction =
        new QAction(tr("Synchronize Breakpoints"), &menu);
    synchronizeAction->setEnabled(
        Debugger::DebuggerManager::instance()->debuggerActionsEnabled());

    QModelIndex idx0 = (si.size() ? si.front() : QModelIndex());
    QModelIndex idx2 = idx0.sibling(idx0.row(), 2);
    bool enabled = si.isEmpty() || itemModel->data(idx0, Qt::UserRole).toBool();
    const QString str5 = enabled ? tr("Disable Breakpoint") : tr("Enable Breakpoint");
    QAction *toggleEnabledAction = new QAction(str5, &menu);
    toggleEnabledAction->setEnabled(si.size() > 0);

    const bool fullpath = si.isEmpty() || itemModel->data(idx2, Qt::UserRole).toBool();
    const QString str6 = fullpath ? tr("Use Short Path") : tr("Use Full Path");
    QAction *pathAction = new QAction(str6, &menu);
    pathAction->setEnabled(si.size() > 0);

    QAction *breakAtFunctionAction =
        new QAction(tr("Set Breakpoint at Function..."), this);
    QAction *breakAtMainAction =
        new QAction(tr("Set Breakpoint at Function \"main\""), this);
    QAction *breakAtThrowAction =
        new QAction(tr("Set Breakpoint at \"throw\""), this);
    QAction *breakAtCatchAction =
        new QAction(tr("Set Breakpoint at \"catch\""), this);

    menu.addAction(deleteAction);
    menu.addAction(editConditionAction);
    menu.addAction(toggleEnabledAction);
    menu.addAction(pathAction);
    menu.addSeparator();
    menu.addAction(deleteAllAction);
    menu.addAction(deleteByFileAction);
    menu.addSeparator();
    menu.addAction(synchronizeAction);
    menu.addSeparator();
    menu.addAction(breakAtFunctionAction);
    menu.addAction(breakAtMainAction);
    if (engineCapabilities & BreakOnThrowAndCatchCapability) {
        menu.addAction(breakAtThrowAction);
        menu.addAction(breakAtCatchAction);
    }
    menu.addSeparator();
    menu.addAction(theDebuggerAction(UseToolTipsInBreakpointsView));
    menu.addAction(theDebuggerAction(UseAddressInBreakpointsView));
    menu.addAction(adjustColumnAction);
    menu.addAction(alwaysAdjustAction);
    menu.addSeparator();
    menu.addAction(theDebuggerAction(SettingsDialog));

    QAction *act = menu.exec(ev->globalPos());

    if (act == deleteAction) {
        deleteBreakpoints(si);
    } else if (act == deleteAllAction) {
        QList<int> allRows;
        for (int i = 0; i < rowCount; i++)
            allRows.push_back(i);
        deleteBreakpoints(allRows);
    }  else if (act == deleteByFileAction)
        deleteBreakpoints(breakPointsOfFile);
    else if (act == adjustColumnAction)
        resizeColumnsToContents();
    else if (act == alwaysAdjustAction)
        setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
    else if (act == editConditionAction)
        editConditions(si);
    else if (act == synchronizeAction)
        emit breakpointSynchronizationRequested();
    else if (act == toggleEnabledAction)
        setBreakpointsEnabled(si, !enabled);
    else if (act == pathAction)
        setBreakpointsFullPath(si, !fullpath);
    else if (act == breakAtFunctionAction) {
        BreakByFunctionDialog dlg(this);
        if (dlg.exec())
            emit breakByFunctionRequested(dlg.functionName());
    } else if (act == breakAtMainAction)
        emit breakByFunctionMainRequested();
     else if (act == breakAtThrowAction)
        emit breakByFunctionRequested("__cxa_throw");
     else if (act == breakAtCatchAction)
        emit breakByFunctionRequested("__cxa_begin_catch");
}

void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled)
{
    foreach (const QModelIndex &idx, list)
        model()->setData(idx, enabled);
    emit breakpointSynchronizationRequested();
}

void BreakWindow::setBreakpointsFullPath(const QModelIndexList &list, bool fullpath)
{
    foreach (const QModelIndex &idx, list) {
        QModelIndex idx2 = idx.sibling(idx.row(), 2);
        model()->setData(idx2, fullpath);
    }
    emit breakpointSynchronizationRequested();
}

void BreakWindow::deleteBreakpoints(const QModelIndexList &indexes)
{
    QTC_ASSERT(!indexes.isEmpty(), return);
    QList<int> list;
    foreach (const QModelIndex &idx, indexes)
        list.append(idx.row());
    deleteBreakpoints(list);
}

void BreakWindow::deleteBreakpoints(QList<int> list)
{
    if (list.empty())
        return;
    const int firstRow = list.front();
    qSort(list.begin(), list.end());
    for (int i = list.size(); --i >= 0; )
        emit breakpointDeleted(list.at(i));

    const int row = qMin(firstRow, model()->rowCount() - 1);
    if (row >= 0)
        setCurrentIndex(model()->index(row, 0));
}

void BreakWindow::editConditions(const QModelIndexList &list)
{
    QDialog dlg(this);
    Ui::BreakCondition ui;
    ui.setupUi(&dlg);

    QTC_ASSERT(!list.isEmpty(), return);
    QModelIndex idx = list.front();
    int row = idx.row();
    dlg.setWindowTitle(tr("Conditions on Breakpoint %1").arg(row));
    ui.lineEditCondition->setText(model()->data(idx.sibling(row, 4)).toString());
    ui.spinBoxIgnoreCount->setValue(model()->data(idx.sibling(row, 5)).toInt());

    if (dlg.exec() == QDialog::Rejected)
        return;

    foreach (const QModelIndex &idx, list) {
        model()->setData(idx.sibling(idx.row(), 4), ui.lineEditCondition->text());
        model()->setData(idx.sibling(idx.row(), 5), ui.spinBoxIgnoreCount->value());
    }
}

void BreakWindow::resizeColumnsToContents()
{
    for (int i = model()->columnCount(); --i >= 0; )
        resizeColumnToContents(i);
}

void BreakWindow::setAlwaysResizeColumnsToContents(bool on)
{
    m_alwaysResizeColumnsToContents = on;
    QHeaderView::ResizeMode mode = on
        ? QHeaderView::ResizeToContents : QHeaderView::Interactive;
    for (int i = model()->columnCount(); --i >= 0; )
        header()->setResizeMode(i, mode);
}

void BreakWindow::rowActivated(const QModelIndex &idx)
{
    emit breakpointActivated(idx.row());
}

<commit_msg>debugger: better tell gdb about changed breakpoint attributes.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "breakwindow.h"

#include "debuggeractions.h"
#include "debuggermanager.h"
#include "ui_breakcondition.h"
#include "ui_breakbyfunction.h"

#include <utils/qtcassert.h>
#include <utils/savedaction.h>

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QFileInfoList>

#include <QtGui/QAction>
#include <QtGui/QHeaderView>
#include <QtGui/QKeyEvent>
#include <QtGui/QMenu>
#include <QtGui/QResizeEvent>
#include <QtGui/QItemSelectionModel>
#include <QtGui/QToolButton>
#include <QtGui/QTreeView>

using Debugger::Internal::BreakWindow;

///////////////////////////////////////////////////////////////////////
//
// BreakByFunctionDialog
//
///////////////////////////////////////////////////////////////////////

class BreakByFunctionDialog : public QDialog, Ui::BreakByFunctionDialog
{
public:
    explicit BreakByFunctionDialog(QWidget *parent)
      : QDialog(parent)
    {
        setupUi(this);
        connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
        connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
    }
    QString functionName() const { return functionLineEdit->text(); }
};

///////////////////////////////////////////////////////////////////////
//
// BreakWindow
//
///////////////////////////////////////////////////////////////////////

BreakWindow::BreakWindow(Debugger::DebuggerManager *manager)
  : m_manager(manager), m_alwaysResizeColumnsToContents(false)
{
    QAction *act = theDebuggerAction(UseAlternatingRowColors);
    setFrameStyle(QFrame::NoFrame);
    setWindowTitle(tr("Breakpoints"));
    setWindowIcon(QIcon(":/debugger/images/debugger_breakpoints.png"));
    setAlternatingRowColors(act->isChecked());
    setRootIsDecorated(false);
    setIconSize(QSize(10, 10));
    setSelectionMode(QAbstractItemView::ExtendedSelection);

    connect(this, SIGNAL(activated(QModelIndex)),
        this, SLOT(rowActivated(QModelIndex)));
    connect(act, SIGNAL(toggled(bool)),
        this, SLOT(setAlternatingRowColorsHelper(bool)));
    connect(theDebuggerAction(UseAddressInBreakpointsView), SIGNAL(toggled(bool)),
        this, SLOT(showAddressColumn(bool)));
}

void BreakWindow::showAddressColumn(bool on)
{
    setColumnHidden(6, !on);
}

static QModelIndexList normalizeIndexes(const QModelIndexList &list)
{
    QModelIndexList res;
    foreach (const QModelIndex &idx, list)
        if (idx.column() == 0)
            res.append(idx);
    return res;
}

void BreakWindow::keyPressEvent(QKeyEvent *ev)
{
    if (ev->key() == Qt::Key_Delete) {
        QItemSelectionModel *sm = selectionModel();
        QTC_ASSERT(sm, return);
        QModelIndexList si = sm->selectedIndexes();
        if (si.isEmpty())
            si.append(currentIndex().sibling(currentIndex().row(), 0));
        deleteBreakpoints(normalizeIndexes(si));
    }
    QTreeView::keyPressEvent(ev);
}

void BreakWindow::resizeEvent(QResizeEvent *ev)
{
    QTreeView::resizeEvent(ev);
}

void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
{
    QMenu menu;
    const QAbstractItemModel *itemModel = model();
    QItemSelectionModel *sm = selectionModel();
    QTC_ASSERT(sm, return);
    QModelIndexList si = sm->selectedIndexes();
    QModelIndex indexUnderMouse = indexAt(ev->pos());
    if (si.isEmpty() && indexUnderMouse.isValid())
        si.append(indexUnderMouse.sibling(indexUnderMouse.row(), 0));
    si = normalizeIndexes(si);

    const int rowCount = itemModel->rowCount();
    const unsigned engineCapabilities = m_manager->debuggerCapabilities();

    QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu);
    deleteAction->setEnabled(si.size() > 0);

    QAction *deleteAllAction = new QAction(tr("Delete All Breakpoints"), &menu);
    deleteAllAction->setEnabled(si.size() > 0);

    // Delete by file: Find indices of breakpoints of the same file.
    QAction *deleteByFileAction = 0;
    QList<int> breakPointsOfFile;
    if (indexUnderMouse.isValid()) {
        const QModelIndex index = indexUnderMouse.sibling(indexUnderMouse.row(), 2);
        const QString file = itemModel->data(index).toString();
        if (!file.isEmpty()) {
            for (int i = 0; i < rowCount; i++)
                if (itemModel->data(itemModel->index(i, 2)).toString() == file)
                    breakPointsOfFile.push_back(i);
            if (breakPointsOfFile.size() > 1) {
                deleteByFileAction =
                    new QAction(tr("Delete Breakpoints of \"%1\"").arg(file), &menu);
                deleteByFileAction->setEnabled(true);
            }
        }
    }
    if (!deleteByFileAction) {
        deleteByFileAction = new QAction(tr("Delete Breakpoints of File"), &menu);
        deleteByFileAction->setEnabled(false);
    }

    QAction *adjustColumnAction =
        new QAction(tr("Adjust Column Widths to Contents"), &menu);

    QAction *alwaysAdjustAction =
        new QAction(tr("Always Adjust Column Widths to Contents"), &menu);

    alwaysAdjustAction->setCheckable(true);
    alwaysAdjustAction->setChecked(m_alwaysResizeColumnsToContents);

    QAction *editConditionAction =
        new QAction(tr("Edit Condition..."), &menu);
    editConditionAction->setEnabled(si.size() > 0);

    QAction *synchronizeAction =
        new QAction(tr("Synchronize Breakpoints"), &menu);
    synchronizeAction->setEnabled(
        Debugger::DebuggerManager::instance()->debuggerActionsEnabled());

    QModelIndex idx0 = (si.size() ? si.front() : QModelIndex());
    QModelIndex idx2 = idx0.sibling(idx0.row(), 2);
    bool enabled = si.isEmpty() || itemModel->data(idx0, Qt::UserRole).toBool();
    const QString str5 = enabled ? tr("Disable Breakpoint") : tr("Enable Breakpoint");
    QAction *toggleEnabledAction = new QAction(str5, &menu);
    toggleEnabledAction->setEnabled(si.size() > 0);

    const bool fullpath = si.isEmpty() || itemModel->data(idx2, Qt::UserRole).toBool();
    const QString str6 = fullpath ? tr("Use Short Path") : tr("Use Full Path");
    QAction *pathAction = new QAction(str6, &menu);
    pathAction->setEnabled(si.size() > 0);

    QAction *breakAtFunctionAction =
        new QAction(tr("Set Breakpoint at Function..."), this);
    QAction *breakAtMainAction =
        new QAction(tr("Set Breakpoint at Function \"main\""), this);
    QAction *breakAtThrowAction =
        new QAction(tr("Set Breakpoint at \"throw\""), this);
    QAction *breakAtCatchAction =
        new QAction(tr("Set Breakpoint at \"catch\""), this);

    menu.addAction(deleteAction);
    menu.addAction(editConditionAction);
    menu.addAction(toggleEnabledAction);
    menu.addAction(pathAction);
    menu.addSeparator();
    menu.addAction(deleteAllAction);
    menu.addAction(deleteByFileAction);
    menu.addSeparator();
    menu.addAction(synchronizeAction);
    menu.addSeparator();
    menu.addAction(breakAtFunctionAction);
    menu.addAction(breakAtMainAction);
    if (engineCapabilities & BreakOnThrowAndCatchCapability) {
        menu.addAction(breakAtThrowAction);
        menu.addAction(breakAtCatchAction);
    }
    menu.addSeparator();
    menu.addAction(theDebuggerAction(UseToolTipsInBreakpointsView));
    menu.addAction(theDebuggerAction(UseAddressInBreakpointsView));
    menu.addAction(adjustColumnAction);
    menu.addAction(alwaysAdjustAction);
    menu.addSeparator();
    menu.addAction(theDebuggerAction(SettingsDialog));

    QAction *act = menu.exec(ev->globalPos());

    if (act == deleteAction) {
        deleteBreakpoints(si);
    } else if (act == deleteAllAction) {
        QList<int> allRows;
        for (int i = 0; i < rowCount; i++)
            allRows.push_back(i);
        deleteBreakpoints(allRows);
    }  else if (act == deleteByFileAction)
        deleteBreakpoints(breakPointsOfFile);
    else if (act == adjustColumnAction)
        resizeColumnsToContents();
    else if (act == alwaysAdjustAction)
        setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
    else if (act == editConditionAction)
        editConditions(si);
    else if (act == synchronizeAction)
        emit breakpointSynchronizationRequested();
    else if (act == toggleEnabledAction)
        setBreakpointsEnabled(si, !enabled);
    else if (act == pathAction)
        setBreakpointsFullPath(si, !fullpath);
    else if (act == breakAtFunctionAction) {
        BreakByFunctionDialog dlg(this);
        if (dlg.exec())
            emit breakByFunctionRequested(dlg.functionName());
    } else if (act == breakAtMainAction)
        emit breakByFunctionMainRequested();
     else if (act == breakAtThrowAction)
        emit breakByFunctionRequested("__cxa_throw");
     else if (act == breakAtCatchAction)
        emit breakByFunctionRequested("__cxa_begin_catch");
}

void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled)
{
    foreach (const QModelIndex &idx, list)
        model()->setData(idx, enabled);
    emit breakpointSynchronizationRequested();
}

void BreakWindow::setBreakpointsFullPath(const QModelIndexList &list, bool fullpath)
{
    foreach (const QModelIndex &idx, list) {
        QModelIndex idx2 = idx.sibling(idx.row(), 2);
        model()->setData(idx2, fullpath);
    }
    emit breakpointSynchronizationRequested();
}

void BreakWindow::deleteBreakpoints(const QModelIndexList &indexes)
{
    QTC_ASSERT(!indexes.isEmpty(), return);
    QList<int> list;
    foreach (const QModelIndex &idx, indexes)
        list.append(idx.row());
    deleteBreakpoints(list);
}

void BreakWindow::deleteBreakpoints(QList<int> list)
{
    if (list.empty())
        return;
    const int firstRow = list.front();
    qSort(list.begin(), list.end());
    for (int i = list.size(); --i >= 0; )
        emit breakpointDeleted(list.at(i));

    const int row = qMin(firstRow, model()->rowCount() - 1);
    if (row >= 0)
        setCurrentIndex(model()->index(row, 0));
}

void BreakWindow::editConditions(const QModelIndexList &list)
{
    QDialog dlg(this);
    Ui::BreakCondition ui;
    ui.setupUi(&dlg);

    QTC_ASSERT(!list.isEmpty(), return);
    QModelIndex idx = list.front();
    int row = idx.row();
    dlg.setWindowTitle(tr("Conditions on Breakpoint %1").arg(row));
    ui.lineEditCondition->setText(model()->data(idx.sibling(row, 4)).toString());
    ui.spinBoxIgnoreCount->setValue(model()->data(idx.sibling(row, 5)).toInt());

    if (dlg.exec() == QDialog::Rejected)
        return;

    foreach (const QModelIndex &idx, list) {
        model()->setData(idx.sibling(idx.row(), 4), ui.lineEditCondition->text());
        model()->setData(idx.sibling(idx.row(), 5), ui.spinBoxIgnoreCount->value());
    }
    emit breakpointSynchronizationRequested();
}

void BreakWindow::resizeColumnsToContents()
{
    for (int i = model()->columnCount(); --i >= 0; )
        resizeColumnToContents(i);
}

void BreakWindow::setAlwaysResizeColumnsToContents(bool on)
{
    m_alwaysResizeColumnsToContents = on;
    QHeaderView::ResizeMode mode = on
        ? QHeaderView::ResizeToContents : QHeaderView::Interactive;
    for (int i = model()->columnCount(); --i >= 0; )
        header()->setResizeMode(i, mode);
}

void BreakWindow::rowActivated(const QModelIndex &idx)
{
    emit breakpointActivated(idx.row());
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * Copyright (c) 2012 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_MULTI_TYPE_MATRIX_HPP__
#define __MDDS_MULTI_TYPE_MATRIX_HPP__

#include "multi_type_vector.hpp"
#include "multi_type_matrix_block_func.hpp"

namespace mdds {

template<typename _String>
class multi_type_matrix
{
public:
    enum element_t { element_empty, element_boolean, element_string, element_numeric };
    typedef _String     string_type;
    typedef size_t      size_type;

    struct size_pair_type
    {
        size_type row;
        size_type column;
        size_pair_type() : row(0), column(0) {}
        size_pair_type(size_type _row, size_type _column) : row(_row), column(_column) {}
    };

    /**
     * Default constructor.
     */
    multi_type_matrix();

    /**
     * Construct a matrix of specified size with specified density type.
     */
    multi_type_matrix(size_type rows, size_type cols);

    template<typename _T>
    multi_type_matrix(size_type rows, size_type cols, const _T& value);

    multi_type_matrix(const multi_type_matrix& r);
    ~multi_type_matrix();

    multi_type_matrix& operator= (const multi_type_matrix& r);

    /**
     * Get the type of element specified by its position.  The type can be one
     * of empty, string, numeric, or boolean.
     *
     * @return element type.
     */
    element_t get_type(size_type row, size_type col) const;

    /**
     * Get a numeric representation of the element.  If the element is of
     * numeric type, its value is returned.  If it's of boolean type, either 1
     * or 0 is returned depending on whether it's true or false.  If it's of
     * empty or string type, 0 is returned.
     *
     * @param row row position of the element.
     * @param col column position of the element.
     *
     * @return numeric representation of the element.
     */
    double get_numeric(size_type row, size_type col) const;

    /**
     * Get a boolean representation of the element.  If the element is of
     * numeric type, true is returned if it's non-zero, otherwise false is
     * returned. If it's of boolean type, its value is returned.  If it's of
     * empty or string type, false is returned.
     *
     * @param row row position of the element.
     * @param col column position of the element.
     *
     * @return boolean representation of the element.
     */
    bool get_boolean(size_type row, size_type col) const;

    /**
     * Get the value of a string element.  If the element is not of string
     * type, it throws an exception.
     *
     * @param row row position of the element.
     * @param col column position of the element.
     *
     * @return value of the element.
     */
    string_type get_string(size_type row, size_type col) const;

    /**
     * Get the value of element at specified position.  The caller must
     * explicitly specify the return type.  If the element is not of the
     * specified type, it throws an exception.
     *
     * @param row row position of the element.
     * @param col column position of the element.
     *
     * @return value of the element.
     */
    template<typename _T>
    _T get(size_type row, size_type col) const;

    void set_empty(size_type row, size_type col);
    void set_column_empty(size_type col);
    void set_row_empty(size_type row);

    void set(size_type row, size_type col, double val);
    void set(size_type row, size_type col, bool val);
    void set(size_type row, size_type col, const string_type& str);

    /**
     * Set values of multiple elements at once, starting at specified element
     * position following the direction of columns.  When the new value series
     * does not fit in the column of the start element, it gets wrapped into
     * the next column(s).
     *
     *
The method will throw an std::out_of_range exception
     * if the specified position is outside the current container range.

     *
     * @param row row position of the start element.
     * @param col column position of the start element.
     * @param it_begin iterator that points to the begin position of the
     *                 values being set.
     * @param it_end iterator that points to the end position of the values
     *               being set.
     */
    template<typename _T>
    void set(size_type row, size_type col, const _T& it_begin, const _T& it_end);

    /**
     * Set values of multiple elements at once in a single column.  When the
     * length of passed elements exceeds that of the column, it gets truncated
     * to the column size.
     *
     * @param col column position
     * @param it_begin iterator that points to the begin position of the
     *                 values being set.
     * @param it_end iterator that points to the end position of the values
     *               being set.
     */
    template<typename _T>
    void set_column(size_type col, const _T& it_begin, const _T& it_end);

    /**
     * Return the size of matrix as a pair.  The first value is the row size,
     * while the second value is the column size.
     *
     * @return matrix size as a value pair.
     */
    size_pair_type size() const;

    /**
     * Transpose the stored matrix data.
     *
     * @return reference to this matrix instance.
     */
    multi_type_matrix& transpose();

    /**
     * Assign values from the passed matrix instance.  If the size of the
     * passed matrix is smaller, then the element values are assigned by their
     * positions, while the rest of the elements that fall outside the size of
     * the passed matrix instance will remain unmodified.  If the size of the
     * passed matrix instance is larger, then only the elements within the
     * size of this matrix instance will get assigned.
     *
     * @param r passed matrix object to assign element values from.
     */
    void assign(const multi_type_matrix& r);

    /**
     * Resize the matrix to specified size.  This method supports resizing to
     * zero-sized matrix; however, either specifying the row or column size to
     * zero will resize the matrix to 0 x 0.
     *
     * @param row new row size
     * @param col new column size
     */
    void resize(size_type row, size_type col);

    /**
     * Empty the matrix.
     */
    void clear();

    /**
     * Check whether or not this matrix is numeric.  A numeric matrix contains
     * only numeric or boolean elements.
     *
     * @return true if the matrix contains only numeric or boolean elements,
     *         or false otherwise.
     */
    bool numeric() const;

    /**
     * Check whether or not this matrix is empty.
     *
     * @return true if this matrix is empty, or false otherwise.
     */
    bool empty() const;

    /**
     * Swap the content of the matrix with another instance.
     */
    void swap(multi_type_matrix& r);

private:

    /**
     * Get an array position of the data referenced by the row and column
     * indices.  The array consists of multiple columns, the content of column
     * 0 followded by the content of column 1, and so on.  Note that no
     * boundary check is performed in this method.
     *
     * @param row 0-based row index.
     * @param col 0-based column index.
     * @return position in the data array.
     */
    inline size_type get_pos(size_type row, size_type col) const
    {
        return m_size.row * col + row;
    }

private:
    typedef __mtm::trait<string_type> string_trait;
    typedef mdds::multi_type_vector<typename string_trait::elem_block_func> store_type;

    store_type m_store;
    size_pair_type m_size;
};

}

#include "multi_type_matrix_def.inl"

#endif
<commit_msg>Let's call this copy().  assign() has a different expectation per STL.<commit_after>/*************************************************************************
 *
 * Copyright (c) 2012 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_MULTI_TYPE_MATRIX_HPP__
#define __MDDS_MULTI_TYPE_MATRIX_HPP__

#include "multi_type_vector.hpp"
#include "multi_type_matrix_block_func.hpp"

namespace mdds {

template<typename _String>
class multi_type_matrix
{
public:
    enum element_t { element_empty, element_boolean, element_string, element_numeric };
    typedef _String     string_type;
    typedef size_t      size_type;

    struct size_pair_type
    {
        size_type row;
        size_type column;
        size_pair_type() : row(0), column(0) {}
        size_pair_type(size_type _row, size_type _column) : row(_row), column(_column) {}
    };

    /**
     * Default constructor.
     */
    multi_type_matrix();

    /**
     * Construct a matrix of specified size with specified density type.
     */
    multi_type_matrix(size_type rows, size_type cols);

    template<typename _T>
    multi_type_matrix(size_type rows, size_type cols, const _T& value);

    multi_type_matrix(const multi_type_matrix& r);
    ~multi_type_matrix();

    multi_type_matrix& operator= (const multi_type_matrix& r);

    /**
     * Get the type of element specified by its position.  The type can be one
     * of empty, string, numeric, or boolean.
     *
     * @return element type.
     */
    element_t get_type(size_type row, size_type col) const;

    /**
     * Get a numeric representation of the element.  If the element is of
     * numeric type, its value is returned.  If it's of boolean type, either 1
     * or 0 is returned depending on whether it's true or false.  If it's of
     * empty or string type, 0 is returned.
     *
     * @param row row position of the element.
     * @param col column position of the element.
     *
     * @return numeric representation of the element.
     */
    double get_numeric(size_type row, size_type col) const;

    /**
     * Get a boolean representation of the element.  If the element is of
     * numeric type, true is returned if it's non-zero, otherwise false is
     * returned. If it's of boolean type, its value is returned.  If it's of
     * empty or string type, false is returned.
     *
     * @param row row position of the element.
     * @param col column position of the element.
     *
     * @return boolean representation of the element.
     */
    bool get_boolean(size_type row, size_type col) const;

    /**
     * Get the value of a string element.  If the element is not of string
     * type, it throws an exception.
     *
     * @param row row position of the element.
     * @param col column position of the element.
     *
     * @return value of the element.
     */
    string_type get_string(size_type row, size_type col) const;

    /**
     * Get the value of element at specified position.  The caller must
     * explicitly specify the return type.  If the element is not of the
     * specified type, it throws an exception.
     *
     * @param row row position of the element.
     * @param col column position of the element.
     *
     * @return value of the element.
     */
    template<typename _T>
    _T get(size_type row, size_type col) const;

    void set_empty(size_type row, size_type col);
    void set_column_empty(size_type col);
    void set_row_empty(size_type row);

    void set(size_type row, size_type col, double val);
    void set(size_type row, size_type col, bool val);
    void set(size_type row, size_type col, const string_type& str);

    /**
     * Set values of multiple elements at once, starting at specified element
     * position following the direction of columns.  When the new value series
     * does not fit in the column of the start element, it gets wrapped into
     * the next column(s).
     *
     *
The method will throw an std::out_of_range exception
     * if the specified position is outside the current container range.

     *
     * @param row row position of the start element.
     * @param col column position of the start element.
     * @param it_begin iterator that points to the begin position of the
     *                 values being set.
     * @param it_end iterator that points to the end position of the values
     *               being set.
     */
    template<typename _T>
    void set(size_type row, size_type col, const _T& it_begin, const _T& it_end);

    /**
     * Set values of multiple elements at once in a single column.  When the
     * length of passed elements exceeds that of the column, it gets truncated
     * to the column size.
     *
     * @param col column position
     * @param it_begin iterator that points to the begin position of the
     *                 values being set.
     * @param it_end iterator that points to the end position of the values
     *               being set.
     */
    template<typename _T>
    void set_column(size_type col, const _T& it_begin, const _T& it_end);

    /**
     * Return the size of matrix as a pair.  The first value is the row size,
     * while the second value is the column size.
     *
     * @return matrix size as a value pair.
     */
    size_pair_type size() const;

    /**
     * Transpose the stored matrix data.
     *
     * @return reference to this matrix instance.
     */
    multi_type_matrix& transpose();

    /**
     * Copy values from the passed matrix instance.  If the size of the passed
     * matrix is smaller, then the element values are assigned by their
     * positions, while the rest of the elements that fall outside the size of
     * the passed matrix instance will remain unmodified.  If the size of the
     * passed matrix instance is larger, then only the elements within the
     * size of this matrix instance will get assigned.
     *
     * @param r passed matrix object to assign element values from.
     */
    void copy(const multi_type_matrix& r);

    /**
     * Resize the matrix to specified size.  This method supports resizing to
     * zero-sized matrix; however, either specifying the row or column size to
     * zero will resize the matrix to 0 x 0.
     *
     * @param row new row size
     * @param col new column size
     */
    void resize(size_type row, size_type col);

    /**
     * Empty the matrix.
     */
    void clear();

    /**
     * Check whether or not this matrix is numeric.  A numeric matrix contains
     * only numeric or boolean elements.
     *
     * @return true if the matrix contains only numeric or boolean elements,
     *         or false otherwise.
     */
    bool numeric() const;

    /**
     * Check whether or not this matrix is empty.
     *
     * @return true if this matrix is empty, or false otherwise.
     */
    bool empty() const;

    /**
     * Swap the content of the matrix with another instance.
     */
    void swap(multi_type_matrix& r);

private:

    /**
     * Get an array position of the data referenced by the row and column
     * indices.  The array consists of multiple columns, the content of column
     * 0 followded by the content of column 1, and so on.  Note that no
     * boundary check is performed in this method.
     *
     * @param row 0-based row index.
     * @param col 0-based column index.
     * @return position in the data array.
     */
    inline size_type get_pos(size_type row, size_type col) const
    {
        return m_size.row * col + row;
    }

private:
    typedef __mtm::trait<string_type> string_trait;
    typedef mdds::multi_type_vector<typename string_trait::elem_block_func> store_type;

    store_type m_store;
    size_pair_type m_size;
};

}

#include "multi_type_matrix_def.inl"

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * Copyright (c) 2011-2012 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_MULTI_TYPE_VECTOR_HPP__
#define __MDDS_MULTI_TYPE_VECTOR_HPP__

#include "default_deleter.hpp"
#include "compat/unique_ptr.hpp"
#include "global.hpp"
#include "multi_type_vector_types.hpp"
#include "multi_type_vector_itr.hpp"

#include <vector>
#include <algorithm>
#include <cassert>

namespace mdds {

/**
 * Multi-type vector consists of a series of blocks, and each block stores a
 * series of non-empty elements of identical type.  In this container,
 * elements are represented simply as values that they store; there are no
 * separate element objects that the user of this container needs to deal
 * with.  The user accesses directly with the raw values.
 */
template<typename _ElemBlockFunc>
class multi_type_vector
{
public:
    typedef size_t size_type;

    typedef typename mdds::mtv::base_element_block element_block_type;
    typedef typename mdds::mtv::element_t element_category_type;

private:
    typedef _ElemBlockFunc element_block_func;

    struct block
    {
        size_type m_size;
        element_block_type* mp_data;

        block();
        block(size_type _size);
        block(const block& other);
        ~block();
    };

    typedef std::vector<block*> blocks_type;

public:

    typedef __mtv::iterator_base<multi_type_vector, blocks_type, typename blocks_type::const_iterator> const_iterator;
    typedef __mtv::iterator_base<multi_type_vector, blocks_type, typename blocks_type::const_reverse_iterator> const_reverse_iterator;

    const_iterator begin() const;
    const_iterator end() const;

    const_reverse_iterator rbegin() const;
    const_reverse_iterator rend() const;

    /**
     * Default constructor.  It initializes the container with empty size.
     */
    multi_type_vector();

    /**
     * Constructor that takes initial size of the container.  When the size
     * specified is greater than 0, it initializes the container with empty
     * elements.
     *
     * @param init_row_size initial container size
     */
    multi_type_vector(size_type init_size);

    template<typename _T>
    multi_type_vector(size_type init_size, const _T& value);

    /**
     * Copy constructor.
     *
     * @param other other column instance to copy values from.
     */
    multi_type_vector(const multi_type_vector& other);

    /**
     * Destructor.  It deletes all allocated data blocks.
     */
    ~multi_type_vector();

    /**
     * Set a value of an arbitrary type to a specified position.  The type of
     * the value is inferred from the value passed to this method.  The new
     * value will overwrite an existing value at the specified position
     * position if any.
     *
     *
The method will throw an std::out_of_range exception
     * if the specified position is outside the current container range.

     *
     *
Calling this method will not change the size of the container.

     *
     * @param pos position to insert the value to.
     * @param value value to insert.
     */
    template<typename _T>
    void set(size_type pos, const _T& value);

    /**
     * Set multiple values of identical type to a range of elements starting
     * at specified position.  Any existing values will be overwritten by the
     * new values.
     *
     *
The method will throw an std::out_of_range exception if
     * the range of new values would fall outside the current container
     * range.

     *
     *
Calling this method will not change the size of the container.

     *
     * @param pos position of the first value of the series of new values
     *            being inserted.
     * @param it_begin iterator that points to the begin position of the
     *                 values being set.
     * @param it_end iterator that points to the end position of the values
     *               being set.
     */
    template<typename _T>
    void set(size_type pos, const _T& it_begin, const _T& it_end);

    /**
     * Insert multiple values of identical type to a specified position.
     * Existing values that occur at or below the specified position will get
     * shifted after the insertion.  No existing values will be overwritten by
     * the inserted values.
     *
     *
The method will throw an std::out_of_range exception
     * if the specified position is outside the current container range.

     *
     *
Calling this method will increase the size of the container by
     * the length of the new values inserted.

     *
     * @param pos position at which the new values are to be inserted.
     * @param it_begin iterator that points to the begin position of the
     *                 values being inserted.
     * @param it_end iterator that points to the end position of the values
     *               being inserted.
     */
    template<typename _T>
    void insert(size_type pos, const _T& it_begin, const _T& it_end);

    /**
     * Get the value of an element at specified position.  The caller must
     * pass a variable of the correct type to store the value.
     *
     *
The method will throw an std::out_of_range exception if
     * the specified position is outside the current container range.

     *
     * @param pos position of the element value to retrieve.
     * @param value (out) variable to store the retrieved value.
     */
    template<typename _T>
    void get(size_type pos, _T& value) const;

    /**
     * Get the value of an element at specified position.  The caller must
     * specify the type of the element as the template parameter e.g.
     * get<double>(1).
     *
     *
The method will throw an std::out_of_range exception if
     * the specified position is outside the current container range.

     *
     * @param position position of the element value to retrieve.
     * @return element value.
     */
    template<typename _T>
    _T get(size_type pos) const;

    mtv::element_t get_type(size_type pos) const;

    /**
     * Check if element at specified position is empty of not.
     *
     *
The method will throw an std::out_of_range exception if
     * the specified position is outside the current container range.

     *
     * @param pos position of the element to check.
     *
     * @return true if the element is empty, false otherwise.
     */
    bool is_empty(size_type pos) const;

    /**
     * Set specified range of elements to be empty.  Any existing values will
     * be overwritten.
     *
     *
The method will throw an std::out_of_range exception if
     * either the starting or the ending position is outside the current
     * container size.

     *
     * @param start_pos starting position
     * @param end_pos ending position, inclusive.
     */
    void set_empty(size_type start_pos, size_type end_pos);

    /**
     * Erase elements located between specified start and end positions. The
     * end positions are both inclusive.
     *
     *
The method will throw an std::out_of_range exception if
     * either the starting or the ending position is outside the current
     * container range.

     *
     *
Calling this method will decrease the size of the container by
     * the length of the erased range.

     *
     * @param start_pos starting position
     * @param end_pos ending position, inclusive.
     */
    void erase(size_type start_pos, size_type end_pos);

    /**
     * Insert a range of empty elements at specified position.
     *
     *
The method will throw an std::out_of_range exception if
     * either the specified position is outside the current container
     * range.

     *
     *
Calling this method will increase the size of the container by
     * the length of the inserted empty elements.

     *
     * @param pos position at which to insert a range of empty elements.
     * @param length number of empty elements to insert.
     */
    void insert_empty(size_type pos, size_type length);

    /**
     * Clear the content of the container.  The size of the container will
     * become zero after calling this method.
     */
    void clear();

    /**
     * Return the current container size.
     *
     * @return current container size.
     */
    size_type size() const;

    /**
     * Return the current number of data blocks.  Each data block stores a
     * series of contiguous elements of identical type.  A series of empty
     * elements is also represented by a separate data block.
     *
     *
For instance, if the container stores values of double-precision
     * type at rows 0 to 2, values of std::string type at 3 to 7, and empty
     * values at 8 to 10, it consists of 3 data blocks: one that stores double
     * values, one that stores std::string values, and one that represents the
     * empty value range. In this specific scenario, block_size()
     * returns 3, and size() returns 11.

     *
     * @return current number of data blocks.
     */
    size_type block_size() const;

    /**
     * Return whether or not the container is empty.
     *
     * @return true if the container is empty, false otherwise.
     */
    bool empty() const;

    /**
     * Extend or shrink the container.  When extending the container, it
     * appends a series of empty elements to the end.  When shrinking, the
     * elements at the end of the container get stripped off.
     *
     * @param new_size size of the container after the resize.
     */
    void resize(size_type new_size);

    /**
     * Swap the content with another container.
     *
     * @param other another container to swap content with.
     */
    void swap(multi_type_vector& other);

    bool operator== (const multi_type_vector& other) const;
    bool operator!= (const multi_type_vector& other) const;

    multi_type_vector& operator= (const multi_type_vector& other);

    /**
     * Return the numerical identifier that represents passed element.
     *
     * @param elem element value.
     *
     * @return numerical identifier representing the element.
     */
    template<typename _T>
    static mtv::element_t get_element_type(const _T& elem);

private:

    void get_block_position(
        size_type row, size_type& start_pos, size_type& block_index, size_type start_block=0, size_type start_block_row=0) const;

    template<typename _T>
    void create_new_block_with_new_cell(element_block_type*& data, const _T& cell);

    template<typename _T>
    void set_cell_to_middle_of_block(
        size_type block_index, size_type pos_in_block, const _T& cell);

    template<typename _T>
    void append_cell_to_block(size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_impl(size_type row, const _T& cell);

    template<typename _T>
    void set_cell_to_empty_block(
        size_type block_index, size_type pos_in_block, const _T& cell);

    template<typename _T>
    void set_cell_to_block_of_size_one(
        size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_to_top_of_data_block(
        size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_to_bottom_of_data_block(
        size_type block_index, const _T& cell);

    void set_empty_in_single_block(
        size_type start_pos, size_type end_pos, size_type block_index, size_type start_pos_in_block);

    void set_empty_in_multi_blocks(
        size_type start_pos, size_type end_pos,
        size_type block_index1, size_type start_pos_in_block1,
        size_type block_index2, size_type start_pos_in_block2);

    void erase_impl(size_type start_pos, size_type end_pos);

    void insert_empty_impl(size_type row, size_type length);

    template<typename _T>
    void set_cells_impl(size_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void insert_cells_impl(size_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_single_block(
        size_type start_pos, size_type end_pos, size_type block_index,
        size_type start_pos_in_block, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks(
        size_type start_pos, size_type end_pos,
        size_type block_index1, size_type start_pos_in_block1,
        size_type block_index2, size_type start_pos_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks_block1_non_equal(
        size_type start_pos, size_type end_pos,
        size_type block_index1, size_type start_pos_in_block1,
        size_type block_index2, size_type start_pos_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks_block1_non_empty(
        size_type start_pos, size_type end_pos,
        size_type block_index1, size_type start_pos_in_block1,
        size_type block_index2, size_type start_pos_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    bool append_to_prev_block(
        size_type block_index, element_category_type cat, size_type length,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void insert_cells_to_middle(
        size_type row, size_type block_index, size_type start_pos,
        const _T& it_begin, const _T& it_end);

private:
    blocks_type m_blocks;
    size_type m_cur_size;
};

}

#include "multi_type_vector_def.inl"

#endif
<commit_msg>This method can be static.<commit_after>/*************************************************************************
 *
 * Copyright (c) 2011-2012 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_MULTI_TYPE_VECTOR_HPP__
#define __MDDS_MULTI_TYPE_VECTOR_HPP__

#include "default_deleter.hpp"
#include "compat/unique_ptr.hpp"
#include "global.hpp"
#include "multi_type_vector_types.hpp"
#include "multi_type_vector_itr.hpp"

#include <vector>
#include <algorithm>
#include <cassert>

namespace mdds {

/**
 * Multi-type vector consists of a series of blocks, and each block stores a
 * series of non-empty elements of identical type.  In this container,
 * elements are represented simply as values that they store; there are no
 * separate element objects that the user of this container needs to deal
 * with.  The user accesses directly with the raw values.
 */
template<typename _ElemBlockFunc>
class multi_type_vector
{
public:
    typedef size_t size_type;

    typedef typename mdds::mtv::base_element_block element_block_type;
    typedef typename mdds::mtv::element_t element_category_type;

private:
    typedef _ElemBlockFunc element_block_func;

    struct block
    {
        size_type m_size;
        element_block_type* mp_data;

        block();
        block(size_type _size);
        block(const block& other);
        ~block();
    };

    typedef std::vector<block*> blocks_type;

public:

    typedef __mtv::iterator_base<multi_type_vector, blocks_type, typename blocks_type::const_iterator> const_iterator;
    typedef __mtv::iterator_base<multi_type_vector, blocks_type, typename blocks_type::const_reverse_iterator> const_reverse_iterator;

    const_iterator begin() const;
    const_iterator end() const;

    const_reverse_iterator rbegin() const;
    const_reverse_iterator rend() const;

    /**
     * Default constructor.  It initializes the container with empty size.
     */
    multi_type_vector();

    /**
     * Constructor that takes initial size of the container.  When the size
     * specified is greater than 0, it initializes the container with empty
     * elements.
     *
     * @param init_row_size initial container size
     */
    multi_type_vector(size_type init_size);

    template<typename _T>
    multi_type_vector(size_type init_size, const _T& value);

    /**
     * Copy constructor.
     *
     * @param other other column instance to copy values from.
     */
    multi_type_vector(const multi_type_vector& other);

    /**
     * Destructor.  It deletes all allocated data blocks.
     */
    ~multi_type_vector();

    /**
     * Set a value of an arbitrary type to a specified position.  The type of
     * the value is inferred from the value passed to this method.  The new
     * value will overwrite an existing value at the specified position
     * position if any.
     *
     *
The method will throw an std::out_of_range exception
     * if the specified position is outside the current container range.

     *
     *
Calling this method will not change the size of the container.

     *
     * @param pos position to insert the value to.
     * @param value value to insert.
     */
    template<typename _T>
    void set(size_type pos, const _T& value);

    /**
     * Set multiple values of identical type to a range of elements starting
     * at specified position.  Any existing values will be overwritten by the
     * new values.
     *
     *
The method will throw an std::out_of_range exception if
     * the range of new values would fall outside the current container
     * range.

     *
     *
Calling this method will not change the size of the container.

     *
     * @param pos position of the first value of the series of new values
     *            being inserted.
     * @param it_begin iterator that points to the begin position of the
     *                 values being set.
     * @param it_end iterator that points to the end position of the values
     *               being set.
     */
    template<typename _T>
    void set(size_type pos, const _T& it_begin, const _T& it_end);

    /**
     * Insert multiple values of identical type to a specified position.
     * Existing values that occur at or below the specified position will get
     * shifted after the insertion.  No existing values will be overwritten by
     * the inserted values.
     *
     *
The method will throw an std::out_of_range exception
     * if the specified position is outside the current container range.

     *
     *
Calling this method will increase the size of the container by
     * the length of the new values inserted.

     *
     * @param pos position at which the new values are to be inserted.
     * @param it_begin iterator that points to the begin position of the
     *                 values being inserted.
     * @param it_end iterator that points to the end position of the values
     *               being inserted.
     */
    template<typename _T>
    void insert(size_type pos, const _T& it_begin, const _T& it_end);

    /**
     * Get the value of an element at specified position.  The caller must
     * pass a variable of the correct type to store the value.
     *
     *
The method will throw an std::out_of_range exception if
     * the specified position is outside the current container range.

     *
     * @param pos position of the element value to retrieve.
     * @param value (out) variable to store the retrieved value.
     */
    template<typename _T>
    void get(size_type pos, _T& value) const;

    /**
     * Get the value of an element at specified position.  The caller must
     * specify the type of the element as the template parameter e.g.
     * get<double>(1).
     *
     *
The method will throw an std::out_of_range exception if
     * the specified position is outside the current container range.

     *
     * @param position position of the element value to retrieve.
     * @return element value.
     */
    template<typename _T>
    _T get(size_type pos) const;

    mtv::element_t get_type(size_type pos) const;

    /**
     * Check if element at specified position is empty of not.
     *
     *
The method will throw an std::out_of_range exception if
     * the specified position is outside the current container range.

     *
     * @param pos position of the element to check.
     *
     * @return true if the element is empty, false otherwise.
     */
    bool is_empty(size_type pos) const;

    /**
     * Set specified range of elements to be empty.  Any existing values will
     * be overwritten.
     *
     *
The method will throw an std::out_of_range exception if
     * either the starting or the ending position is outside the current
     * container size.

     *
     * @param start_pos starting position
     * @param end_pos ending position, inclusive.
     */
    void set_empty(size_type start_pos, size_type end_pos);

    /**
     * Erase elements located between specified start and end positions. The
     * end positions are both inclusive.
     *
     *
The method will throw an std::out_of_range exception if
     * either the starting or the ending position is outside the current
     * container range.

     *
     *
Calling this method will decrease the size of the container by
     * the length of the erased range.

     *
     * @param start_pos starting position
     * @param end_pos ending position, inclusive.
     */
    void erase(size_type start_pos, size_type end_pos);

    /**
     * Insert a range of empty elements at specified position.
     *
     *
The method will throw an std::out_of_range exception if
     * either the specified position is outside the current container
     * range.

     *
     *
Calling this method will increase the size of the container by
     * the length of the inserted empty elements.

     *
     * @param pos position at which to insert a range of empty elements.
     * @param length number of empty elements to insert.
     */
    void insert_empty(size_type pos, size_type length);

    /**
     * Clear the content of the container.  The size of the container will
     * become zero after calling this method.
     */
    void clear();

    /**
     * Return the current container size.
     *
     * @return current container size.
     */
    size_type size() const;

    /**
     * Return the current number of data blocks.  Each data block stores a
     * series of contiguous elements of identical type.  A series of empty
     * elements is also represented by a separate data block.
     *
     *
For instance, if the container stores values of double-precision
     * type at rows 0 to 2, values of std::string type at 3 to 7, and empty
     * values at 8 to 10, it consists of 3 data blocks: one that stores double
     * values, one that stores std::string values, and one that represents the
     * empty value range. In this specific scenario, block_size()
     * returns 3, and size() returns 11.

     *
     * @return current number of data blocks.
     */
    size_type block_size() const;

    /**
     * Return whether or not the container is empty.
     *
     * @return true if the container is empty, false otherwise.
     */
    bool empty() const;

    /**
     * Extend or shrink the container.  When extending the container, it
     * appends a series of empty elements to the end.  When shrinking, the
     * elements at the end of the container get stripped off.
     *
     * @param new_size size of the container after the resize.
     */
    void resize(size_type new_size);

    /**
     * Swap the content with another container.
     *
     * @param other another container to swap content with.
     */
    void swap(multi_type_vector& other);

    bool operator== (const multi_type_vector& other) const;
    bool operator!= (const multi_type_vector& other) const;

    multi_type_vector& operator= (const multi_type_vector& other);

    /**
     * Return the numerical identifier that represents passed element.
     *
     * @param elem element value.
     *
     * @return numerical identifier representing the element.
     */
    template<typename _T>
    static mtv::element_t get_element_type(const _T& elem);

private:

    void get_block_position(
        size_type row, size_type& start_pos, size_type& block_index, size_type start_block=0, size_type start_block_row=0) const;

    template<typename _T>
    static void create_new_block_with_new_cell(element_block_type*& data, const _T& cell);

    template<typename _T>
    void set_cell_to_middle_of_block(
        size_type block_index, size_type pos_in_block, const _T& cell);

    template<typename _T>
    void append_cell_to_block(size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_impl(size_type row, const _T& cell);

    template<typename _T>
    void set_cell_to_empty_block(
        size_type block_index, size_type pos_in_block, const _T& cell);

    template<typename _T>
    void set_cell_to_block_of_size_one(
        size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_to_top_of_data_block(
        size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_to_bottom_of_data_block(
        size_type block_index, const _T& cell);

    void set_empty_in_single_block(
        size_type start_pos, size_type end_pos, size_type block_index, size_type start_pos_in_block);

    void set_empty_in_multi_blocks(
        size_type start_pos, size_type end_pos,
        size_type block_index1, size_type start_pos_in_block1,
        size_type block_index2, size_type start_pos_in_block2);

    void erase_impl(size_type start_pos, size_type end_pos);

    void insert_empty_impl(size_type row, size_type length);

    template<typename _T>
    void set_cells_impl(size_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void insert_cells_impl(size_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_single_block(
        size_type start_pos, size_type end_pos, size_type block_index,
        size_type start_pos_in_block, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks(
        size_type start_pos, size_type end_pos,
        size_type block_index1, size_type start_pos_in_block1,
        size_type block_index2, size_type start_pos_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks_block1_non_equal(
        size_type start_pos, size_type end_pos,
        size_type block_index1, size_type start_pos_in_block1,
        size_type block_index2, size_type start_pos_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks_block1_non_empty(
        size_type start_pos, size_type end_pos,
        size_type block_index1, size_type start_pos_in_block1,
        size_type block_index2, size_type start_pos_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    bool append_to_prev_block(
        size_type block_index, element_category_type cat, size_type length,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void insert_cells_to_middle(
        size_type row, size_type block_index, size_type start_pos,
        const _T& it_begin, const _T& it_end);

private:
    blocks_type m_blocks;
    size_type m_cur_size;
};

}

#include "multi_type_vector_def.inl"

#endif
<|endoftext|>


<commit_before><commit_msg>hiscore again<commit_after><|endoftext|>


<commit_before><commit_msg>Missing data type in OpenCL code.<commit_after><|endoftext|>