<commit_before>#include "indexer.h"

#include <gflags/gflags.h>

#include <stdarg.h>

DEFINE_bool(debug_index, false, "Debug the index query generator.");

static void debug(const char *format, ...) {
    if (!FLAGS_debug_index)
        return;
    va_list ap;

    va_start(ap, format);
    vprintf(format, ap);
    va_end(ap);
}

using namespace re2;
using namespace std;

const unsigned kMinWeight = 16;
const int kMaxFilters     = 32;

double IndexKey::selectivity() {
    if (keys.size() == 0)
        return 1.0;

    double s = 0.0;
    for (vector<string>::const_iterator it = keys.begin();
         it != keys.end(); ++it)
        s += pow(1./64, min(it->size(), size_t(4)));

    return s;
}

unsigned IndexKey::weight() {
    return 1/selectivity();
}

string IndexKey::ToString() {
    string out;
    for (vector<string>::const_iterator it = keys.begin();
         it != keys.end(); ++it) {
        out += *it;
        out += ",";
    }
    out += "|";
    if (anchor & kAnchorLeft)
        out += "<";
    if (anchor & kAnchorRight)
        out += ">";
    return out;
}

class IndexWalker : public Regexp::Walker<IndexKey*> {
public:
    IndexWalker() { }
    virtual IndexKey *
    PostVisit(Regexp* re, IndexKey *parent_arg,
              IndexKey *pre_arg,
              IndexKey **child_args, int nchild_args);

    virtual IndexKey *
    ShortVisit(Regexp* re,
               IndexKey *parent_arg);

private:
    IndexWalker(const IndexWalker&);
    void operator=(const IndexWalker&);
};

namespace {
    string RuneToString(Rune r) {
        char buf[UTFmax];
        int n = runetochar(buf, &r);
        return string(buf, n);
    }

    IndexKey *Any() {
        return new IndexKey(kAnchorNone);
    }

    IndexKey *Empty() {
        return new IndexKey(kAnchorBoth);
    }

    IndexKey *Literal(Rune r) {
        IndexKey *k = new IndexKey;
        k->keys.push_back(RuneToString(r));
        k->anchor = kAnchorBoth;
        return k;
    }

    IndexKey *Literal(Rune *runes, int nrunes) {
        IndexKey *k = new IndexKey;
        string lit;

        for (int i = 0; i < nrunes; i++) {
            lit.append(RuneToString(runes[i]));
        }

        k->keys.push_back(lit);
        k->anchor = kAnchorBoth;

        return k;
    }

    IndexKey *CClass(CharClass *cc) {
        if (cc->size() > kMaxFilters)
            return Any();

        IndexKey *k = new IndexKey();

        for (CharClass::iterator i = cc->begin(); i != cc->end(); ++i)
            for (Rune r = i->lo; r <= i->hi; r++)
                k->keys.push_back(RuneToString(r));

        k->anchor = kAnchorBoth;

        return k;
    }

    IndexKey *Concat(IndexKey *lhs, IndexKey *rhs) {
        IndexKey *out = 0;

        debug("Concat([%s](%d), [%s](%d)) = ",
               lhs->ToString().c_str(),
               lhs->weight(),
               rhs->ToString().c_str(),
               rhs->weight());

        if ((lhs->anchor & kAnchorRight) &&
            (rhs->anchor & kAnchorLeft) &&
            lhs->keys.size() && rhs->keys.size() &&
            lhs->keys.size() * rhs->keys.size() <= kMaxFilters) {
            out = new IndexKey;
            for (vector<string>::iterator lit = lhs->keys.begin();
                 lit != lhs->keys.end(); ++lit)
                for (vector<string>::iterator rit = rhs->keys.begin();
                     rit != rhs->keys.end(); ++rit)
                    out->keys.push_back(*lit + *rit);
            out->anchor = (lhs->anchor & kAnchorLeft) | (rhs->anchor & kAnchorRight);
        }

        if (!out || lhs->weight() > out->weight()) {
            delete out;
            out = lhs;
            out->anchor &= ~kAnchorRight;
        } else {
            delete lhs;
        }

        if (rhs->weight() > out->weight()) {
            delete out;
            out = rhs;
            out->anchor &= ~kAnchorLeft;
        } else {
            delete rhs;
        }

        debug("[%s]\n", out->ToString().c_str());

        return out;
    }

    IndexKey *Alternate(IndexKey *lhs, IndexKey *rhs) {
        if (lhs->keys.size() + rhs->keys.size() < kMaxFilters) {
            lhs->keys.insert(lhs->keys.end(), rhs->keys.begin(), rhs->keys.end());
            lhs->anchor &= rhs->anchor;

            delete rhs;
            return lhs;
        }
        delete lhs;
        delete rhs;

        return Any();
    }

};

unique_ptr<IndexKey> indexRE(const re2::RE2 &re) {
    IndexWalker walk;

    unique_ptr<IndexKey> key(walk.Walk(re.Regexp(), 0));

    if (key->weight() < kMinWeight)
        key->keys.clear();
    return key;
}

IndexKey *IndexWalker::PostVisit(Regexp* re, IndexKey *parent_arg,
                                 IndexKey *pre_arg,
                                 IndexKey **child_args, int nchild_args) {
    IndexKey *key;

    switch (re->op()) {
    case kRegexpNoMatch:
    case kRegexpEmptyMatch:      // anywhere
    case kRegexpBeginLine:       // at beginning of line
    case kRegexpEndLine:         // at end of line
    case kRegexpBeginText:       // at beginning of text
    case kRegexpEndText:         // at end of text
    case kRegexpWordBoundary:    // at word boundary
    case kRegexpNoWordBoundary:  // not at word boundary
        key = Empty();
        break;

    case kRegexpAnyChar:
    case kRegexpAnyByte:
        key = Any();
        break;

    case kRegexpLiteral:
        key = Literal(re->rune());
        break;

    case kRegexpCharClass:
        key = CClass(re->cc());
        break;

    case kRegexpLiteralString:
        key = Literal(re->runes(), re->nrunes());
        break;

    case kRegexpConcat:
        key = Empty();
        for (int i = 0; i < nchild_args; i++)
            key = Concat(key, child_args[i]);
        break;

    case kRegexpAlternate:
        key = child_args[0];
        for (int i = 1; i < nchild_args; i++)
            key = Alternate(key, child_args[i]);
        break;

    case kRegexpStar:
    case kRegexpQuest:
        delete child_args[0];
        key = Any();
        break;

    case kRegexpCapture:
        key = child_args[0];
        break;

    case kRegexpRepeat:
    case kRegexpPlus:
        key = child_args[0];
        if (key->anchor == kAnchorBoth)
            key->anchor &= ~kAnchorRight;
        break;

    default:
        assert(false);
    }

    debug(" %s -> [%s](%d)\n",
          re->ToString().c_str(),
          key->ToString().c_str(),
          key->weight());

    return key;
}

IndexKey *IndexWalker::ShortVisit(Regexp* re, IndexKey *parent_arg) {
    return Any();
}
<commit_msg>Tweak the selectivity heuristic for the indexer.<commit_after>#include "indexer.h"

#include <gflags/gflags.h>

#include <stdarg.h>

DEFINE_bool(debug_index, false, "Debug the index query generator.");

static void debug(const char *format, ...) {
    if (!FLAGS_debug_index)
        return;
    va_list ap;

    va_start(ap, format);
    vprintf(format, ap);
    va_end(ap);
}

using namespace re2;
using namespace std;

const unsigned kMinWeight = 16;
const int kMaxFilters     = 32;

double IndexKey::selectivity() {
    if (keys.size() == 0)
        return 1.0;

    double s = 0.0;
    for (vector<string>::const_iterator it = keys.begin();
         it != keys.end(); ++it)
        s += pow(1./(it->size() + 1), 8);

    return s;
}

unsigned IndexKey::weight() {
    return 1/selectivity();
}

string IndexKey::ToString() {
    string out;
    for (vector<string>::const_iterator it = keys.begin();
         it != keys.end(); ++it) {
        out += *it;
        out += ",";
    }
    out += "|";
    if (anchor & kAnchorLeft)
        out += "<";
    if (anchor & kAnchorRight)
        out += ">";
    return out;
}

class IndexWalker : public Regexp::Walker<IndexKey*> {
public:
    IndexWalker() { }
    virtual IndexKey *
    PostVisit(Regexp* re, IndexKey *parent_arg,
              IndexKey *pre_arg,
              IndexKey **child_args, int nchild_args);

    virtual IndexKey *
    ShortVisit(Regexp* re,
               IndexKey *parent_arg);

private:
    IndexWalker(const IndexWalker&);
    void operator=(const IndexWalker&);
};

namespace {
    string RuneToString(Rune r) {
        char buf[UTFmax];
        int n = runetochar(buf, &r);
        return string(buf, n);
    }

    IndexKey *Any() {
        return new IndexKey(kAnchorNone);
    }

    IndexKey *Empty() {
        return new IndexKey(kAnchorBoth);
    }

    IndexKey *Literal(Rune r) {
        IndexKey *k = new IndexKey;
        k->keys.push_back(RuneToString(r));
        k->anchor = kAnchorBoth;
        return k;
    }

    IndexKey *Literal(Rune *runes, int nrunes) {
        IndexKey *k = new IndexKey;
        string lit;

        for (int i = 0; i < nrunes; i++) {
            lit.append(RuneToString(runes[i]));
        }

        k->keys.push_back(lit);
        k->anchor = kAnchorBoth;

        return k;
    }

    IndexKey *CClass(CharClass *cc) {
        if (cc->size() > kMaxFilters)
            return Any();

        IndexKey *k = new IndexKey();

        for (CharClass::iterator i = cc->begin(); i != cc->end(); ++i)
            for (Rune r = i->lo; r <= i->hi; r++)
                k->keys.push_back(RuneToString(r));

        k->anchor = kAnchorBoth;

        return k;
    }

    IndexKey *Concat(IndexKey *lhs, IndexKey *rhs) {
        IndexKey *out = 0;

        debug("Concat([%s](%d), [%s](%d)) = ",
               lhs->ToString().c_str(),
               lhs->weight(),
               rhs->ToString().c_str(),
               rhs->weight());

        if ((lhs->anchor & kAnchorRight) &&
            (rhs->anchor & kAnchorLeft) &&
            lhs->keys.size() && rhs->keys.size() &&
            lhs->keys.size() * rhs->keys.size() <= kMaxFilters) {
            out = new IndexKey;
            for (vector<string>::iterator lit = lhs->keys.begin();
                 lit != lhs->keys.end(); ++lit)
                for (vector<string>::iterator rit = rhs->keys.begin();
                     rit != rhs->keys.end(); ++rit)
                    out->keys.push_back(*lit + *rit);
            out->anchor = (lhs->anchor & kAnchorLeft) | (rhs->anchor & kAnchorRight);
        }

        if (!out || lhs->weight() > out->weight()) {
            delete out;
            out = lhs;
            out->anchor &= ~kAnchorRight;
        } else {
            delete lhs;
        }

        if (rhs->weight() > out->weight()) {
            delete out;
            out = rhs;
            out->anchor &= ~kAnchorLeft;
        } else {
            delete rhs;
        }

        debug("[%s]\n", out->ToString().c_str());

        return out;
    }

    IndexKey *Alternate(IndexKey *lhs, IndexKey *rhs) {
        if (lhs->keys.size() + rhs->keys.size() < kMaxFilters) {
            lhs->keys.insert(lhs->keys.end(), rhs->keys.begin(), rhs->keys.end());
            lhs->anchor &= rhs->anchor;

            delete rhs;
            return lhs;
        }
        delete lhs;
        delete rhs;

        return Any();
    }

};

unique_ptr<IndexKey> indexRE(const re2::RE2 &re) {
    IndexWalker walk;

    unique_ptr<IndexKey> key(walk.Walk(re.Regexp(), 0));

    if (key->weight() < kMinWeight)
        key->keys.clear();
    return key;
}

IndexKey *IndexWalker::PostVisit(Regexp* re, IndexKey *parent_arg,
                                 IndexKey *pre_arg,
                                 IndexKey **child_args, int nchild_args) {
    IndexKey *key;

    switch (re->op()) {
    case kRegexpNoMatch:
    case kRegexpEmptyMatch:      // anywhere
    case kRegexpBeginLine:       // at beginning of line
    case kRegexpEndLine:         // at end of line
    case kRegexpBeginText:       // at beginning of text
    case kRegexpEndText:         // at end of text
    case kRegexpWordBoundary:    // at word boundary
    case kRegexpNoWordBoundary:  // not at word boundary
        key = Empty();
        break;

    case kRegexpAnyChar:
    case kRegexpAnyByte:
        key = Any();
        break;

    case kRegexpLiteral:
        key = Literal(re->rune());
        break;

    case kRegexpCharClass:
        key = CClass(re->cc());
        break;

    case kRegexpLiteralString:
        key = Literal(re->runes(), re->nrunes());
        break;

    case kRegexpConcat:
        key = Empty();
        for (int i = 0; i < nchild_args; i++)
            key = Concat(key, child_args[i]);
        break;

    case kRegexpAlternate:
        key = child_args[0];
        for (int i = 1; i < nchild_args; i++)
            key = Alternate(key, child_args[i]);
        break;

    case kRegexpStar:
    case kRegexpQuest:
        delete child_args[0];
        key = Any();
        break;

    case kRegexpCapture:
        key = child_args[0];
        break;

    case kRegexpRepeat:
    case kRegexpPlus:
        key = child_args[0];
        if (key->anchor == kAnchorBoth)
            key->anchor &= ~kAnchorRight;
        break;

    default:
        assert(false);
    }

    debug(" %s -> [%s](%d)\n",
          re->ToString().c_str(),
          key->ToString().c_str(),
          key->weight());

    return key;
}

IndexKey *IndexWalker::ShortVisit(Regexp* re, IndexKey *parent_arg) {
    return Any();
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Jolla Ltd.
** Contact: Raine Makelainen <raine.makelainen@jolla.com>
**
****************************************************************************/

/* 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 "webpages.h"
#include "declarativewebcontainer.h"
#include "declarativewebpage.h"
#include "qmozcontext.h"

#include <QDateTime>
#include <QDBusConnection>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQmlContext>
#include <QMapIterator>
#include <QRectF>
#include <qqmlinfo.h>

#ifndef DEBUG_LOGS
#define DEBUG_LOGS 0
#endif

#if DEBUG_LOGS
#include <QDebug>
#endif

static const qint64 gMemoryPressureTimeout = 600 * 1000; // 600 sec
// In normal cases gLowMemoryEnabled is true. Can be disabled e.g. for test runs.
static const bool gLowMemoryEnabled = qgetenv("LOW_MEMORY_DISABLED").isEmpty();

WebPages::WebPages(QObject *parent)
    : QObject(parent)
    , m_backgroundTimestamp(0)
{
    if (gLowMemoryEnabled) {
        QDBusConnection::systemBus().connect("com.nokia.mce", "/com/nokia/mce/signal",
                                             "com.nokia.mce.signal", "sig_memory_level_ind",
                                             this, SLOT(handleMemNotify(QString)));
    }
}

WebPages::~WebPages()
{
}

void WebPages::initialize(DeclarativeWebContainer *webContainer, QQmlComponent *webPageComponent)
{
    if (!m_webContainer || !m_webPageComponent) {
        m_webContainer = webContainer;
        m_webPageComponent = webPageComponent;
    }

    connect(webContainer, SIGNAL(foregroundChanged()), this, SLOT(updateBackgroundTimestamp()));
}

void WebPages::updateBackgroundTimestamp()
{
    if (!m_webContainer->foreground()) {
        m_backgroundTimestamp = QDateTime::currentMSecsSinceEpoch();
    }
}

bool WebPages::initialized() const
{
    return m_webContainer && m_webPageComponent;
}

int WebPages::count() const
{
    return m_activePages.count();
}

bool WebPages::setMaxLivePages(int count)
{
    return m_activePages.setMaxLivePages(count);
}

int WebPages::maxLivePages() const
{
    return m_activePages.maxLivePages();
}

bool WebPages::alive(int tabId) const
{
    return m_activePages.alive(tabId);
}

WebPageActivationData WebPages::page(int tabId, int parentId)
{
    if (!m_webPageComponent) {
        qWarning() << "TabModel not initialized!";
        return WebPageActivationData(0, false);
    }

    if (m_activePages.active(tabId)) {
        DeclarativeWebPage *activePage = m_activePages.activeWebPage();
        activePage->resumeView();
        return WebPageActivationData(activePage, false);
    }

#if DEBUG_LOGS
    qDebug() << "about to create a new tab or activate old:" << tabId;
#endif

    DeclarativeWebPage *webPage = 0;
    DeclarativeWebPage *oldActiveWebPage = m_activePages.activeWebPage();
    if (!m_activePages.alive(tabId)) {
        QQmlContext *creationContext = m_webPageComponent->creationContext();
        QQmlContext *context = new QQmlContext(creationContext ? creationContext : QQmlEngine::contextForObject(m_webContainer));
        QObject *object = m_webPageComponent->beginCreate(context);
        if (object) {
            context->setParent(object);
            object->setParent(m_webContainer);
            webPage = qobject_cast<DeclarativeWebPage *>(object);
            if (webPage) {
//                webPage->setParentItem(m_webContainer);
                webPage->setParentID(parentId);
                webPage->setPrivateMode(m_webContainer->privateMode());
                webPage->setTabId(tabId);
                webPage->setContainer(m_webContainer);
                m_webPageComponent->completeCreate();
#if DEBUG_LOGS
                qDebug() << "New view id:" << webPage->uniqueID() << "parentId:" << webPage->parentId() << "tab id:" << webPage->tabId();
#endif
                m_activePages.prepend(tabId, webPage);
                QQmlEngine::setObjectOwnership(webPage, QQmlEngine::CppOwnership);
            } else {
                qmlInfo(m_webContainer) << "webPage component must be a WebPage component";
            }
        } else {
            qmlInfo(m_webContainer) << "Creation of the web page failed. Error: " << m_webPageComponent->errorString();
            delete object;
            object = 0;
        }
    }

    DeclarativeWebPage *newActiveWebPage = m_activePages.activate(tabId);
    updateStates(oldActiveWebPage, newActiveWebPage);

#if DEBUG_LOGS
    dumpPages();
#endif

    return WebPageActivationData(newActiveWebPage, true);
}

void WebPages::release(int tabId, bool virtualize)
{
    m_activePages.release(tabId, virtualize);
}

void WebPages::clear()
{
    m_activePages.clear();
}

int WebPages::parentTabId(int tabId) const
{
    return m_activePages.parentTabId(tabId);
}

void WebPages::updateStates(DeclarativeWebPage *oldActivePage, DeclarativeWebPage *newActivePage)
{
    if (oldActivePage) {
        // Allow suspending only the current active page if it is not the creator (parent).
        if (newActivePage->parentId() != (int)oldActivePage->uniqueID()) {
            if (oldActivePage->loading()) {
                oldActivePage->stop();
            }
            oldActivePage->suspendView();
        }
    }

    if (newActivePage) {
        newActivePage->resumeView();
    }
}

void WebPages::dumpPages() const
{
    m_activePages.dumpPages();
}

void WebPages::handleMemNotify(const QString &memoryLevel)
{
    if (!m_webContainer || !m_webContainer->completed()) {
        return;
    }

    if (memoryLevel == QString("warning") || memoryLevel == QString("critical")) {
        m_activePages.virtualizeInactive();

        if (!m_webContainer->foreground() &&
                (QDateTime::currentMSecsSinceEpoch() - m_backgroundTimestamp) > gMemoryPressureTimeout) {
            m_backgroundTimestamp = QDateTime::currentMSecsSinceEpoch();
            QMozContext::GetInstance()->sendObserve(QString("memory-pressure"), QString("heap-minimize"));
        }
    }
}
<commit_msg>[sailfish-browser] Call initialize to complete instantiation. Contributes JB#27557<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Jolla Ltd.
** Contact: Raine Makelainen <raine.makelainen@jolla.com>
**
****************************************************************************/

/* 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 "webpages.h"
#include "declarativewebcontainer.h"
#include "declarativewebpage.h"
#include "qmozcontext.h"

#include <QDateTime>
#include <QDBusConnection>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQmlContext>
#include <QMapIterator>
#include <QRectF>
#include <qqmlinfo.h>

#ifndef DEBUG_LOGS
#define DEBUG_LOGS 0
#endif

#if DEBUG_LOGS
#include <QDebug>
#endif

static const qint64 gMemoryPressureTimeout = 600 * 1000; // 600 sec
// In normal cases gLowMemoryEnabled is true. Can be disabled e.g. for test runs.
static const bool gLowMemoryEnabled = qgetenv("LOW_MEMORY_DISABLED").isEmpty();

WebPages::WebPages(QObject *parent)
    : QObject(parent)
    , m_backgroundTimestamp(0)
{
    if (gLowMemoryEnabled) {
        QDBusConnection::systemBus().connect("com.nokia.mce", "/com/nokia/mce/signal",
                                             "com.nokia.mce.signal", "sig_memory_level_ind",
                                             this, SLOT(handleMemNotify(QString)));
    }
}

WebPages::~WebPages()
{
}

void WebPages::initialize(DeclarativeWebContainer *webContainer, QQmlComponent *webPageComponent)
{
    if (!m_webContainer || !m_webPageComponent) {
        m_webContainer = webContainer;
        m_webPageComponent = webPageComponent;
    }

    connect(webContainer, SIGNAL(foregroundChanged()), this, SLOT(updateBackgroundTimestamp()));
}

void WebPages::updateBackgroundTimestamp()
{
    if (!m_webContainer->foreground()) {
        m_backgroundTimestamp = QDateTime::currentMSecsSinceEpoch();
    }
}

bool WebPages::initialized() const
{
    return m_webContainer && m_webPageComponent;
}

int WebPages::count() const
{
    return m_activePages.count();
}

bool WebPages::setMaxLivePages(int count)
{
    return m_activePages.setMaxLivePages(count);
}

int WebPages::maxLivePages() const
{
    return m_activePages.maxLivePages();
}

bool WebPages::alive(int tabId) const
{
    return m_activePages.alive(tabId);
}

WebPageActivationData WebPages::page(int tabId, int parentId)
{
    if (!m_webPageComponent) {
        qWarning() << "TabModel not initialized!";
        return WebPageActivationData(0, false);
    }

    if (m_activePages.active(tabId)) {
        DeclarativeWebPage *activePage = m_activePages.activeWebPage();
        activePage->resumeView();
        return WebPageActivationData(activePage, false);
    }

#if DEBUG_LOGS
    qDebug() << "about to create a new tab or activate old:" << tabId;
#endif

    DeclarativeWebPage *webPage = 0;
    DeclarativeWebPage *oldActiveWebPage = m_activePages.activeWebPage();
    if (!m_activePages.alive(tabId)) {
        QQmlContext *creationContext = m_webPageComponent->creationContext();
        QQmlContext *context = new QQmlContext(creationContext ? creationContext : QQmlEngine::contextForObject(m_webContainer));
        QObject *object = m_webPageComponent->beginCreate(context);
        if (object) {
            context->setParent(object);
            object->setParent(m_webContainer);
            webPage = qobject_cast<DeclarativeWebPage *>(object);
            if (webPage) {
                webPage->setParentID(parentId);
                webPage->setPrivateMode(m_webContainer->privateMode());
                webPage->setTabId(tabId);
                webPage->setContainer(m_webContainer);
                webPage->initialize();
                m_webPageComponent->completeCreate();
#if DEBUG_LOGS
                qDebug() << "New view id:" << webPage->uniqueID() << "parentId:" << webPage->parentId() << "tab id:" << webPage->tabId();
#endif
                m_activePages.prepend(tabId, webPage);
                QQmlEngine::setObjectOwnership(webPage, QQmlEngine::CppOwnership);
            } else {
                qmlInfo(m_webContainer) << "webPage component must be a WebPage component";
            }
        } else {
            qmlInfo(m_webContainer) << "Creation of the web page failed. Error: " << m_webPageComponent->errorString();
            delete object;
            object = 0;
        }
    }

    DeclarativeWebPage *newActiveWebPage = m_activePages.activate(tabId);
    updateStates(oldActiveWebPage, newActiveWebPage);

#if DEBUG_LOGS
    dumpPages();
#endif

    return WebPageActivationData(newActiveWebPage, true);
}

void WebPages::release(int tabId, bool virtualize)
{
    m_activePages.release(tabId, virtualize);
}

void WebPages::clear()
{
    m_activePages.clear();
}

int WebPages::parentTabId(int tabId) const
{
    return m_activePages.parentTabId(tabId);
}

void WebPages::updateStates(DeclarativeWebPage *oldActivePage, DeclarativeWebPage *newActivePage)
{
    if (oldActivePage) {
        // Allow suspending only the current active page if it is not the creator (parent).
        if (newActivePage->parentId() != (int)oldActivePage->uniqueID()) {
            if (oldActivePage->loading()) {
                oldActivePage->stop();
            }
            oldActivePage->suspendView();
        }
    }

    if (newActivePage) {
        newActivePage->resumeView();
    }
}

void WebPages::dumpPages() const
{
    m_activePages.dumpPages();
}

void WebPages::handleMemNotify(const QString &memoryLevel)
{
    if (!m_webContainer || !m_webContainer->completed()) {
        return;
    }

    if (memoryLevel == QString("warning") || memoryLevel == QString("critical")) {
        m_activePages.virtualizeInactive();

        if (!m_webContainer->foreground() &&
                (QDateTime::currentMSecsSinceEpoch() - m_backgroundTimestamp) > gMemoryPressureTimeout) {
            m_backgroundTimestamp = QDateTime::currentMSecsSinceEpoch();
            QMozContext::GetInstance()->sendObserve(QString("memory-pressure"), QString("heap-minimize"));
        }
    }
}
<|endoftext|>


<commit_before>#pragma once

#include <new>
#include <utility>
#include "_types.hh"

namespace zbs {

template <typename T> class func;

template <typename R, typename ...Args>
class func<R (Args...)> {
	static R _invoke_func(void *data, Args &&...args) {
		auto fp = reinterpret_cast<R (*)(Args...)>(data);
		return (*fp)(std::forward<Args>(args)...);
	}

	template <typename T>
	static R _invoke_obj(void *data, Args &&...args) {
		auto obj = reinterpret_cast<T*>(data);
		return (*obj)(std::forward<Args>(args)...);
	}

	template <typename T>
	static R _invoke_const_obj(void *data, Args &&...args) {
		auto obj = reinterpret_cast<const T*>(data);
		return (*obj)(std::forward<Args>(args)...);
	}

	R (*_invoker)(void*, Args&&...);
	void *_data;

public:
	template <typename T>
	func(T &obj): _invoker(_invoke_obj<T>),
		_data(reinterpret_cast<void*>(&obj)) {}
	template <typename T>
	func(const T &obj): _invoker(_invoke_const_obj<T>),
		_data(reinterpret_cast<void*>(const_cast<T*>(&obj))) {}
	func(R (*fp)(Args...)): _invoker(_invoke_func),
		_data(reinterpret_cast<void*>(fp)) {}
	func(const func&) = default;
	func(func&&) = default;
	func &operator=(const func&) = default;
	func &operator=(func&&) = default;
	R operator()(Args ...args) const {
		return (*_invoker)(_data, std::forward<Args>(args)...);
	}
};

} // namespace zbs
<commit_msg>Remove two unused headers from _func.hh.<commit_after>#pragma once

#include <utility>

namespace zbs {

template <typename T> class func;

template <typename R, typename ...Args>
class func<R (Args...)> {
	static R _invoke_func(void *data, Args &&...args) {
		auto fp = reinterpret_cast<R (*)(Args...)>(data);
		return (*fp)(std::forward<Args>(args)...);
	}

	template <typename T>
	static R _invoke_obj(void *data, Args &&...args) {
		auto obj = reinterpret_cast<T*>(data);
		return (*obj)(std::forward<Args>(args)...);
	}

	template <typename T>
	static R _invoke_const_obj(void *data, Args &&...args) {
		auto obj = reinterpret_cast<const T*>(data);
		return (*obj)(std::forward<Args>(args)...);
	}

	R (*_invoker)(void*, Args&&...);
	void *_data;

public:
	template <typename T>
	func(T &obj): _invoker(_invoke_obj<T>),
		_data(reinterpret_cast<void*>(&obj)) {}
	template <typename T>
	func(const T &obj): _invoker(_invoke_const_obj<T>),
		_data(reinterpret_cast<void*>(const_cast<T*>(&obj))) {}
	func(R (*fp)(Args...)): _invoker(_invoke_func),
		_data(reinterpret_cast<void*>(fp)) {}
	func(const func&) = default;
	func(func&&) = default;
	func &operator=(const func&) = default;
	func &operator=(func&&) = default;
	R operator()(Args ...args) const {
		return (*_invoker)(_data, std::forward<Args>(args)...);
	}
};

} // namespace zbs
<|endoftext|>


<commit_before>/****************************************************************
 *                                                              *
 * zpar.lib.cpp - a library that can be used by python          *
 *                                                              *
 * Author: Nitin Madnani                                        *
 * Educational Testing Service, Princeton, NJ                   *
 *                                                              *
 ****************************************************************/

#define SIMPLE_HASH

#include "definitions.h"
#include "options.h"
#include "tagger.h"
#include "conparser.h"
#include "depparser.h"
#include "reader.h"
#include "writer.h"
#include "stdlib.h"
#include <iterator>
#include <sstream>

using namespace english;

#define MAX_SENTENCE_SIZE 512

// define a container structure with a container and a destructor
struct zparModel_t
{
    void *tagger;
    void *conparser;
    void *depparser;
    char *output_buffer;

    zparModel_t() {
        tagger = NULL;
        conparser = NULL;
        depparser = NULL;
        output_buffer = NULL;
    };

    ~zparModel_t() {
        if (tagger)
            delete (CTagger *)tagger;
        if (conparser)
            delete (CConParser *)conparser;
        if (depparser)
            delete (CDepParser *)depparser;
        if (output_buffer) {
            free(output_buffer);
        }
    };
};

// instantiate the container
zparModel_t *zpm = new zparModel_t();

// a utility function to output tagged data in the usual
// "WORD/TAG" format as expected
const char *format_tagged_vector(CTwoStringVector *tagged_sent)
{

    CTwoStringVector::const_iterator it;
    CStringVector formatted_tagged_sent[1];
    for (it = tagged_sent->begin(); it != tagged_sent->end(); ++it)
    {
        std::stringstream tmpss;
        tmpss << it->first << "/" << it->second;
        std::string tmpstr(tmpss.str());
        formatted_tagged_sent->push_back(tmpstr);
    }

    int i;
    std::stringstream oss;
    for (i = 0; i < formatted_tagged_sent->size(); ++i)
    {
        oss << formatted_tagged_sent->at(i);
        if (i != formatted_tagged_sent->size() - 1)
        {
            oss << " ";
        }
    }

    std::string outstr(oss.str());
    return outstr.c_str();

}

// A utility function to format the dependncy output
// in CoNLL format
const char *format_dependency_tree(CDependencyParse *parsed_sent)
{

    int i;
    std::stringstream oss;
    std::copy(parsed_sent->begin(), parsed_sent->end(), std::ostream_iterator<CLabeledDependencyTreeNode>(oss, "\n"));

    std::string outstr(oss.str());
    return outstr.c_str();

}

// The function to load the tagger model
extern "C" int load_tagger(const char *sFeaturePath) {

    CTagger *tagger;
    std::string sTaggerFeatureFile = std::string(sFeaturePath) + "/tagger";
    std::cerr << "Loading tagger from " << sTaggerFeatureFile << std::endl;
    if (!FileExists(sTaggerFeatureFile)) {
        return 1;
    }
    tagger = new CTagger(sTaggerFeatureFile, false);
    zpm->tagger = (void *)tagger;
    return 0;

}

// The function to load the constituency parser model
extern "C" int load_parser(const char *sFeaturePath) {

    // If the tagger is not already loaded, then we need to load
    // it since the parser requires the tagger
    if (!zpm->tagger) {
        if (load_tagger(sFeaturePath)) {
            return 1;
        }
    }

    CConParser *conparser;
    std::string sConParserFeatureFile = std::string(sFeaturePath) + "/conparser";
    std::cerr << "Loading constituency parser from " << sConParserFeatureFile << std::endl;
    if (!FileExists(sConParserFeatureFile)) {
        return 1;
    }
    conparser = new CConParser(sConParserFeatureFile, false);
    zpm->conparser = (void *)conparser;
    return 0;
}

// The function to load the dependency parser model
extern "C" int load_depparser(const char *sFeaturePath) {

    CDepParser *depparser;
    std::string sDepParserFeatureFile = std::string(sFeaturePath) + "/depparser";
    std::cerr << "Loading dependency parser from " << sDepParserFeatureFile << std::endl;
    if (!FileExists(sDepParserFeatureFile)) {
        return 1;
    }
    depparser = new CDepParser(sDepParserFeatureFile, false);
    zpm->depparser = (void *)depparser;
    return 0;
}

// The function to load all three models
extern "C" int load_models(const char *sFeaturePath) {
    if (load_tagger(sFeaturePath)) {
        return 1;
    }
    if (load_parser(sFeaturePath)) {
        return 1;
    }
    if (load_depparser(sFeaturePath)) {
        return 1;
    }
    return 0;
}

// Function to tag a sentence
extern "C" const char* tag_sentence(const char *input_sentence)
{

    // create a temporary string stream from the input char *
    CSentenceReader input_reader(std::string(input_sentence), false);

    // tokenize the sentence
    CStringVector input_sent[1];
    input_reader.readSegmentedSentenceAndTokenize(input_sent);

    // initialize the variable that will hold the tagged sentence
    CTwoStringVector tagged_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger that was stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;

    // tag the sentence
    tagger->tag(input_sent, tagged_sent);

    // format the tagged sentence properly and return
    return format_tagged_vector(tagged_sent);
}

// Function to constituency parse a sentence
extern "C" char* parse_sentence(const char *input_sentence)
{

    // create a temporary string stream from the input char *
    CSentenceReader input_reader(std::string(input_sentence), false);

    // tokenize the sentence
    CStringVector input_sent[1];
    input_reader.readSegmentedSentenceAndTokenize(input_sent);

    // initialize the variable that will hold the tagged sentence
    CTwoStringVector tagged_sent[1];
    english::CCFGTree parsed_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger that was stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;
    CConParser *conparser = (CConParser *)zpm->conparser;

    // tag the sentence
    tagger->tag(input_sent, tagged_sent);
    conparser->parse(*tagged_sent, parsed_sent);

    // now put the tagged_sent into a string stream
    const char * parse;
    parse = parsed_sent->str_unbinarized().c_str();
    if (zpm->output_buffer != NULL) {
        free(zpm->output_buffer);
    }
    zpm->output_buffer = new char[strlen(parse)+1];
    strcpy(zpm->output_buffer, parse);
    return zpm->output_buffer;
}

// Function to dependency parse a sentence
extern "C" const char* dep_parse_sentence(const char *input_sentence)
{

    // create a temporary string stream from the input char *
    CSentenceReader input_reader(std::string(input_sentence), false);

    // tokenize the sentence
    CStringVector input_sent[1];
    input_reader.readSegmentedSentenceAndTokenize(input_sent);

    // initialize the variable that will hold the tagged sentence
    CTwoStringVector tagged_sent[1];
    CDependencyParse parsed_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger that was stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;
    CDepParser *depparser = (CDepParser *)zpm->depparser;

    // tag the sentence
    tagger->tag(input_sent, tagged_sent);
    depparser->parse(*tagged_sent, parsed_sent);

    // now output the formatted dependency tree
    return format_dependency_tree(parsed_sent);

}

// Function to tag all sentence in the given input file
// and write tagged sentences to the given output file
extern "C" void tag_file(const char *sInputFile, const char *sOutputFile)
{

    std::cerr << "Processing file " <<  sInputFile << std::endl;

    // initialize the input reader
    CSentenceReader input_reader(sInputFile);

    // open the output file
    FILE *outfp = NULL;
    outfp = fopen(sOutputFile, "w");

    // initialize the temporary sentence variables
    CStringVector input_sent[1];
    CTwoStringVector tagged_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger and the parser that were stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;

    // read in and tokenize the given input file
    while ( input_reader.readSegmentedSentenceAndTokenize(input_sent) )
    {
        if ( input_sent->back() == "\n" )
        {
            input_sent->pop_back();
        }

        // tag the sentence
        tagger->tag(input_sent, tagged_sent);

        // write the formatted sentence to the output file
        fprintf(outfp, "%s\n", format_tagged_vector(tagged_sent));
    }

    // close the output file
    std::cerr << "Wrote output to " << sOutputFile << std::endl;
    fclose(outfp);
}

// Function to constituency parse all sentence in the given input file
// and write parsed sentences to the given output file
extern "C" void parse_file(const char *sInputFile, const char *sOutputFile)
{

    std::cerr << "Processing file " <<  sInputFile << std::endl;

    // initialize the input reader
    CSentenceReader input_reader(sInputFile);

    // open the output file
    FILE *outfp = NULL;
    outfp = fopen(sOutputFile, "w");

    // initialize the temporary sentence variables
    CStringVector input_sent[1];
    CTwoStringVector tagged_sent[1];
    english::CCFGTree parsed_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger and the parser that were stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;
    CConParser *conparser = (CConParser *)zpm->conparser;

    // read in and tokenize the given input file
    while ( input_reader.readSegmentedSentenceAndTokenize(input_sent) )
    {
        if ( input_sent->back() == "\n" )
        {
            input_sent->pop_back();
        }

        tagger->tag(input_sent, tagged_sent);
        conparser->parse(*tagged_sent, parsed_sent);

        fprintf(outfp, "%s\n", parsed_sent->str_unbinarized().c_str());
    }

    // close the output file
    std::cerr << "Wrote output to " << sOutputFile << std::endl;
    fclose(outfp);
}

// Function to dependency parse all sentence in the given input file
// and write parsed sentences to the given output file
extern "C" void dep_parse_file(const char *sInputFile, const char *sOutputFile)
{

    std::cerr << "Processing file " <<  sInputFile << std::endl;

    // initialize the input reader
    CSentenceReader input_reader(sInputFile);

    // open the output file
    FILE *outfp = NULL;
    outfp = fopen(sOutputFile, "w");

    // initialize the temporary sentence variables
    CStringVector input_sent[1];
    CTwoStringVector tagged_sent[1];
    CDependencyParse parsed_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger and the parser that were stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;
    CDepParser *depparser = (CDepParser *)zpm->depparser;

    // read in and tokenize the given input file
    while ( input_reader.readSegmentedSentenceAndTokenize(input_sent) )
    {
        if ( input_sent->back() == "\n" )
        {
            input_sent->pop_back();
        }

        tagger->tag(input_sent, tagged_sent);
        depparser->parse(*tagged_sent, parsed_sent);

        fprintf(outfp, "%s\n", format_dependency_tree(parsed_sent));
    }

    // close the output file
    std::cerr << "Wrote output to " << sOutputFile << std::endl;
    fclose(outfp);
}

// Function to unload all the models
extern "C" void unload_models()
{

    // just delete the container itself and its destructor
    // will take care of everything else
    delete zpm;
}

// A main function for testing
// extern "C" int main(int argc, char *argv[])
// {
//     load_tagger("/scratch/nmadnani/zpar/english");
//     load_depparser("/scratch/nmadnani/zpar/english");
//     std::cout << std::string(dep_parse_sentence("I am going to the market.\n")) << std::endl;
//     dep_parse_file("/scratch/nmadnani/zpar/test.txt", "/scratch/nmadnani/zpar/test.dep");
//     unload_models();

//     return 0;
// }
<commit_msg>Some more fixes<commit_after>/****************************************************************
 *                                                              *
 * zpar.lib.cpp - a library that can be used by python          *
 *                                                              *
 * Author: Nitin Madnani                                        *
 * Educational Testing Service, Princeton, NJ                   *
 *                                                              *
 ****************************************************************/

#define SIMPLE_HASH

#include "definitions.h"
#include "options.h"
#include "tagger.h"
#include "conparser.h"
#include "depparser.h"
#include "reader.h"
#include "writer.h"
#include "stdlib.h"
#include <cstring>
#include <iterator>
#include <sstream>

using namespace english;

#define MAX_SENTENCE_SIZE 512

// define a container structure with a container and a destructor
struct zparModel_t
{
    void *tagger;
    void *conparser;
    void *depparser;
    char *output_buffer;

    zparModel_t() {
        tagger = NULL;
        conparser = NULL;
        depparser = NULL;
        output_buffer = NULL;
    };

    ~zparModel_t() {
        if (tagger)
            delete (CTagger *)tagger;
        if (conparser)
            delete (CConParser *)conparser;
        if (depparser)
            delete (CDepParser *)depparser;
        if (output_buffer) {
            free(output_buffer);
        }
    };
};

// instantiate the container
zparModel_t *zpm = new zparModel_t();

// a utility function to output tagged data in the usual
// "WORD/TAG" format as expected
const char *format_tagged_vector(CTwoStringVector *tagged_sent)
{

    CTwoStringVector::const_iterator it;
    CStringVector formatted_tagged_sent[1];
    for (it = tagged_sent->begin(); it != tagged_sent->end(); ++it)
    {
        std::stringstream tmpss;
        tmpss << it->first << "/" << it->second;
        std::string tmpstr(tmpss.str());
        formatted_tagged_sent->push_back(tmpstr);
    }

    int i;
    std::stringstream oss;
    for (i = 0; i < formatted_tagged_sent->size(); ++i)
    {
        oss << formatted_tagged_sent->at(i);
        if (i != formatted_tagged_sent->size() - 1)
        {
            oss << " ";
        }
    }

    std::string outstr(oss.str());
    return outstr.c_str();

}

// A utility function to format the dependncy output
// in CoNLL format
const char *format_dependency_tree(CDependencyParse *parsed_sent)
{

    int i;
    std::stringstream oss;
    std::copy(parsed_sent->begin(), parsed_sent->end(), std::ostream_iterator<CLabeledDependencyTreeNode>(oss, "\n"));

    std::string outstr(oss.str());
    return outstr.c_str();

}

// The function to load the tagger model
extern "C" int load_tagger(const char *sFeaturePath) {

    CTagger *tagger;
    std::string sTaggerFeatureFile = std::string(sFeaturePath) + "/tagger";
    std::cerr << "Loading tagger from " << sTaggerFeatureFile << std::endl;
    if (!FileExists(sTaggerFeatureFile)) {
        return 1;
    }
    tagger = new CTagger(sTaggerFeatureFile, false);
    zpm->tagger = (void *)tagger;
    return 0;

}

// The function to load the constituency parser model
extern "C" int load_parser(const char *sFeaturePath) {

    // If the tagger is not already loaded, then we need to load
    // it since the parser requires the tagger
    if (!zpm->tagger) {
        if (load_tagger(sFeaturePath)) {
            return 1;
        }
    }

    CConParser *conparser;
    std::string sConParserFeatureFile = std::string(sFeaturePath) + "/conparser";
    std::cerr << "Loading constituency parser from " << sConParserFeatureFile << std::endl;
    if (!FileExists(sConParserFeatureFile)) {
        return 1;
    }
    conparser = new CConParser(sConParserFeatureFile, false);
    zpm->conparser = (void *)conparser;
    return 0;
}

// The function to load the dependency parser model
extern "C" int load_depparser(const char *sFeaturePath) {

    CDepParser *depparser;
    std::string sDepParserFeatureFile = std::string(sFeaturePath) + "/depparser";
    std::cerr << "Loading dependency parser from " << sDepParserFeatureFile << std::endl;
    if (!FileExists(sDepParserFeatureFile)) {
        return 1;
    }
    depparser = new CDepParser(sDepParserFeatureFile, false);
    zpm->depparser = (void *)depparser;
    return 0;
}

// The function to load all three models
extern "C" int load_models(const char *sFeaturePath) {
    if (load_tagger(sFeaturePath)) {
        return 1;
    }
    if (load_parser(sFeaturePath)) {
        return 1;
    }
    if (load_depparser(sFeaturePath)) {
        return 1;
    }
    return 0;
}

// Function to tag a sentence
extern "C" const char* tag_sentence(const char *input_sentence)
{

    // create a temporary string stream from the input char *
    CSentenceReader input_reader(std::string(input_sentence), false);

    // tokenize the sentence
    CStringVector input_sent[1];
    input_reader.readSegmentedSentenceAndTokenize(input_sent);

    // initialize the variable that will hold the tagged sentence
    CTwoStringVector tagged_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger that was stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;

    // tag the sentence
    tagger->tag(input_sent, tagged_sent);

    // format the tagged sentence properly and return
    return format_tagged_vector(tagged_sent);
}

// Function to constituency parse a sentence
extern "C" char* parse_sentence(const char *input_sentence)
{

    // create a temporary string stream from the input char *
    CSentenceReader input_reader(std::string(input_sentence), false);

    // tokenize the sentence
    CStringVector input_sent[1];
    input_reader.readSegmentedSentenceAndTokenize(input_sent);

    // initialize the variable that will hold the tagged sentence
    CTwoStringVector tagged_sent[1];
    english::CCFGTree parsed_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger that was stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;
    CConParser *conparser = (CConParser *)zpm->conparser;

    // tag the sentence
    tagger->tag(input_sent, tagged_sent);
    conparser->parse(*tagged_sent, parsed_sent);

    // now put the tagged_sent into a string stream
    const char * parse;
    parse = parsed_sent->str_unbinarized().c_str();
    if (zpm->output_buffer != NULL) {
        free(zpm->output_buffer);
        zpm->output_buffer = NULL;
    }
    zpm->output_buffer = new char[strlen(parse) + 1];
    strcpy(zpm->output_buffer, parse);
    return zpm->output_buffer;
}

// Function to dependency parse a sentence
extern "C" const char* dep_parse_sentence(const char *input_sentence)
{

    // create a temporary string stream from the input char *
    CSentenceReader input_reader(std::string(input_sentence), false);

    // tokenize the sentence
    CStringVector input_sent[1];
    input_reader.readSegmentedSentenceAndTokenize(input_sent);

    // initialize the variable that will hold the tagged sentence
    CTwoStringVector tagged_sent[1];
    CDependencyParse parsed_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger that was stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;
    CDepParser *depparser = (CDepParser *)zpm->depparser;

    // tag the sentence
    tagger->tag(input_sent, tagged_sent);
    depparser->parse(*tagged_sent, parsed_sent);

    // now output the formatted dependency tree
    return format_dependency_tree(parsed_sent);

}

// Function to tag all sentence in the given input file
// and write tagged sentences to the given output file
extern "C" void tag_file(const char *sInputFile, const char *sOutputFile)
{

    std::cerr << "Processing file " <<  sInputFile << std::endl;

    // initialize the input reader
    CSentenceReader input_reader(sInputFile);

    // open the output file
    FILE *outfp = NULL;
    outfp = fopen(sOutputFile, "w");

    // initialize the temporary sentence variables
    CStringVector input_sent[1];
    CTwoStringVector tagged_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger and the parser that were stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;

    // read in and tokenize the given input file
    while ( input_reader.readSegmentedSentenceAndTokenize(input_sent) )
    {
        if ( input_sent->back() == "\n" )
        {
            input_sent->pop_back();
        }

        // tag the sentence
        tagger->tag(input_sent, tagged_sent);

        // write the formatted sentence to the output file
        fprintf(outfp, "%s\n", format_tagged_vector(tagged_sent));
    }

    // close the output file
    std::cerr << "Wrote output to " << sOutputFile << std::endl;
    fclose(outfp);
}

// Function to constituency parse all sentence in the given input file
// and write parsed sentences to the given output file
extern "C" void parse_file(const char *sInputFile, const char *sOutputFile)
{

    std::cerr << "Processing file " <<  sInputFile << std::endl;

    // initialize the input reader
    CSentenceReader input_reader(sInputFile);

    // open the output file
    FILE *outfp = NULL;
    outfp = fopen(sOutputFile, "w");

    // initialize the temporary sentence variables
    CStringVector input_sent[1];
    CTwoStringVector tagged_sent[1];
    english::CCFGTree parsed_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger and the parser that were stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;
    CConParser *conparser = (CConParser *)zpm->conparser;

    // read in and tokenize the given input file
    while ( input_reader.readSegmentedSentenceAndTokenize(input_sent) )
    {
        if ( input_sent->back() == "\n" )
        {
            input_sent->pop_back();
        }

        tagger->tag(input_sent, tagged_sent);
        conparser->parse(*tagged_sent, parsed_sent);

        fprintf(outfp, "%s\n", parsed_sent->str_unbinarized().c_str());
    }

    // close the output file
    std::cerr << "Wrote output to " << sOutputFile << std::endl;
    fclose(outfp);
}

// Function to dependency parse all sentence in the given input file
// and write parsed sentences to the given output file
extern "C" void dep_parse_file(const char *sInputFile, const char *sOutputFile)
{

    std::cerr << "Processing file " <<  sInputFile << std::endl;

    // initialize the input reader
    CSentenceReader input_reader(sInputFile);

    // open the output file
    FILE *outfp = NULL;
    outfp = fopen(sOutputFile, "w");

    // initialize the temporary sentence variables
    CStringVector input_sent[1];
    CTwoStringVector tagged_sent[1];
    CDependencyParse parsed_sent[1];

    CBitArray prunes(MAX_SENTENCE_SIZE);

    // get the tagger and the parser that were stored earlier
    CTagger *tagger = (CTagger *)zpm->tagger;
    CDepParser *depparser = (CDepParser *)zpm->depparser;

    // read in and tokenize the given input file
    while ( input_reader.readSegmentedSentenceAndTokenize(input_sent) )
    {
        if ( input_sent->back() == "\n" )
        {
            input_sent->pop_back();
        }

        tagger->tag(input_sent, tagged_sent);
        depparser->parse(*tagged_sent, parsed_sent);

        fprintf(outfp, "%s\n", format_dependency_tree(parsed_sent));
    }

    // close the output file
    std::cerr << "Wrote output to " << sOutputFile << std::endl;
    fclose(outfp);
}

// Function to unload all the models
extern "C" void unload_models()
{

    // just delete the container itself and its destructor
    // will take care of everything else
    delete zpm;
}

// A main function for testing
// extern "C" int main(int argc, char *argv[])
// {
//     load_tagger("/scratch/nmadnani/zpar/english");
//     load_depparser("/scratch/nmadnani/zpar/english");
//     std::cout << std::string(dep_parse_sentence("I am going to the market.\n")) << std::endl;
//     dep_parse_file("/scratch/nmadnani/zpar/test.txt", "/scratch/nmadnani/zpar/test.dep");
//     unload_models();

//     return 0;
// }
<|endoftext|>


<commit_before>#ifndef ZSTD_WRAP_H
#define ZSTD_WRAP_H

#include <nan.h>
#include <zstd.h>

class ZSTDWrap : public Nan::ObjectWrap {
 public:
  static NAN_MODULE_INIT(Init) {
    v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
    tpl->SetClassName(Nan::New("ZSTD").ToLocalChecked());
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    SetPrototypeMethod(tpl, "compress", Compress);
    SetPrototypeMethod(tpl, "decompress", Decompress);

    constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
    Nan::Set(target, Nan::New("ZSTD").ToLocalChecked(),
             Nan::GetFunction(tpl).ToLocalChecked());
  }

 private:
  static NAN_METHOD(New) {
    if (info.IsConstructCall()) {
      ZSTDWrap *obj = new ZSTDWrap();
      obj->Wrap(info.This());
      info.GetReturnValue().Set(info.This());
    } else {
      v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
      info.GetReturnValue().Set(cons->NewInstance(0, NULL));
    }
  }

  static NAN_METHOD(Compress) {
    ZSTDWrap *obj = ObjectWrap::Unwrap<ZSTDWrap>(info.Holder());

    if (info.Length() < 1 || !node::Buffer::HasInstance(info[0])) {
      return Nan::ThrowError("First argument should be a buffer");
    }

    v8::Local<v8::Object> buf = info[0]->ToObject();
    char *src = node::Buffer::Data(buf);
    size_t srcSize = node::Buffer::Length(buf);

    size_t dstCapacity = ZSTD_compressBound(srcSize);
    char *dst = (char*)malloc(dstCapacity);
    if (NULL == dst) {
      return Nan::ThrowError("Too large, Out of memory!");
    }

    int compressionLevel = 1;
    if (info.Length() == 2) {
      compressionLevel = info[1]->IsUndefined() ? 0 : info[1]->NumberValue();
    }

    size_t cSize = ZSTD_compress(dst, dstCapacity, src, srcSize, compressionLevel);
    if (ZSTD_isError(cSize)) {
      return Nan::ThrowError("Compress failed!");
    }

    v8::Local<v8::Object> dstBuf = Nan::NewBuffer(dst, cSize);
    free(dst);

    return info.GetReturnValue().Set(dstBuf);
  }

  static NAN_METHOD(Decompress) {
    ZSTDWrap *obj = ObjectWrap::Unwrap<ZSTDWrap>(info.Holder());

    if (info.Length() < 1 || !node::Buffer::HasInstance(info[0])) {
      return Nan::ThrowError("First argument should be a buffer");
    }

    v8::Local<v8::Object> buf = info[0]->ToObject();
    char *src = node::Buffer::Data(buf);
    size_t srcSize = node::Buffer::Length(buf);

    size_t dstCapacity = ZSTD_getDecompressedSize(src, srcSize);
    if (0 == dstCapacity) {
      return Nan::ThrowError("Compressed size unknown");
    }

    char *dst = (char*)malloc(dstCapacity);
    if (NULL == dst) {
      return Nan::ThrowError("Too large, Out of memory!");
    }

    size_t dSize = ZSTD_decompress(dst, dstCapacity, src, srcSize);
    if (ZSTD_isError(dSize))  {
      return Nan::ThrowError("Decompress failed!");
    }

    v8::Local<v8::Object> dstBuf = Nan::NewBuffer(dst, dSize);
    free(dst);

    return info.GetReturnValue().Set(dstBuf);
  }

  static inline Nan::Persistent<v8::Function> & constructor() {
    static Nan::Persistent<v8::Function> _constructor;
    return _constructor;
  }
};

NODE_MODULE(node_zstd, ZSTDWrap::Init)

#endif
<commit_msg>refactor<zstd_wrap>: remove class<commit_after>#include <nan.h>
#include <zstd.h>

static NAN_METHOD(Compress) {

  if (info.Length() < 1 || !node::Buffer::HasInstance(info[0])) {
    return Nan::ThrowError("First argument should be a buffer");
  }

  v8::Local<v8::Object> buf = info[0]->ToObject();
  char *src = node::Buffer::Data(buf);
  size_t srcSize = node::Buffer::Length(buf);

  size_t dstCapacity = ZSTD_compressBound(srcSize);
  char *dst = (char*)malloc(dstCapacity);
  if (NULL == dst) {
    return Nan::ThrowError("Too large, Out of memory!");
  }

  int compressionLevel = 1;
  if (info.Length() == 2) {
    compressionLevel = info[1]->IsUndefined() ? 0 : info[1]->NumberValue();
  }

  size_t cSize = ZSTD_compress(dst, dstCapacity, src, srcSize, compressionLevel);
  if (ZSTD_isError(cSize)) {
    return Nan::ThrowError("Compress failed!");
  }

  Nan::MaybeLocal<v8::Object> dstBuf = Nan::NewBuffer(dst, cSize);
  free(dst);

  return info.GetReturnValue().Set(dstBuf.ToLocalChecked());
}

static NAN_METHOD(Decompress) {

  if (info.Length() < 1 || !node::Buffer::HasInstance(info[0])) {
    return Nan::ThrowError("First argument should be a buffer");
  }

  v8::Local<v8::Object> buf = info[0]->ToObject();
  char *src = node::Buffer::Data(buf);
  size_t srcSize = node::Buffer::Length(buf);

  size_t dstCapacity = ZSTD_getDecompressedSize(src, srcSize);
  if (0 == dstCapacity) {
    return Nan::ThrowError("Compressed size unknown");
  }

  char *dst = (char*)malloc(dstCapacity);
  if (NULL == dst) {
    return Nan::ThrowError("Too large, Out of memory!");
  }

  size_t dSize = ZSTD_decompress(dst, dstCapacity, src, srcSize);
  if (ZSTD_isError(dSize))  {
    return Nan::ThrowError("Decompress failed!");
  }

  Nan::MaybeLocal<v8::Object> dstBuf = Nan::NewBuffer(dst, dSize);
  free(dst);

  return info.GetReturnValue().Set(dstBuf.ToLocalChecked());
}

NAN_MODULE_INIT(Init) {
  NAN_EXPORT(target, Compress);
  NAN_EXPORT(target, Decompress);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <functional>
#include <cassert>

#include "calc\calculator.h"

const float DELTA = 0.001f;

bool equal(float a, float b) {
	return (a + DELTA > b) && (a - DELTA < b);
}

float addTwo(float a, float notUsed) {
	return a + 2;
}

float multiply(float a, float b) {
	return a * b;
}

int main() {
	// Test 1.
	// Expression is evaluated.
	{
		calc::Calculator calculator;
		std::string expression = "2.1+~3.2*5^(3-1)/(2*3.14 - 1)";
		const float answer = -13.0515151515151515f;
		float value = calculator.excecute(expression);
		std::cout << expression << "=" << value << "\n";
		// Test expression!
		assert(equal(answer, value));
	}

	// Test 2.
	// Expression is evaluated with added constants.
	{
		calc::Calculator calculator;
		calculator.addVariable("PI", 3.14f);
		calculator.addVariable("TWO", 2);
		calculator.addVariable("FIVE", 5);
		std::string expression = "2.1+~3.2*FIVE^(3-1)/(TWO*PI - 1)";
		const float answer = -13.0515151515151515f;
		float value = calculator.excecute(expression);
		std::cout << expression << "=" << value << "\n";
		// Test expression!
		assert(equal(answer, value));
	}

	// Test 2.
	// Expression is evaluated with added constants and functions.
	{
		calc::Calculator calculator;
		calculator.addVariable("PI", 3.14f);
		calculator.addVariable("TWO", 2);
		calculator.addVariable("FIVE", 5);
		calculator.addFunction("addTwo", 1, std::bind(addTwo, std::placeholders::_1, std::placeholders::_2));
		calculator.addFunction("multiply", 2, std::bind(multiply, std::placeholders::_1, std::placeholders::_2));

		std::string expression = "multiply(addTwo(2.1+~3.2*FIVE^(3-1)/(TWO*PI - 1)), 8.1)";
		const float answer = (-13.0515151515151515f + 2)*8.1f;
		float value = calculator.excecute(expression);
		std::cout << expression << "=" << value << "\n";
		// Test expression!
		assert(equal(answer, value));
	}

	std::cout << "\nAll tests succeeded!\n";

	return 0;
}<commit_msg>Added some tests.<commit_after>#include <iostream>
#include <string>
#include <functional>
#include <cassert>

#include "calc\calculator.h"

const float DELTA = 0.001f;

bool equal(float a, float b) {
	return (a + DELTA > b) && (a - DELTA < b);
}

float addTwo(float a, float notUsed) {
	return a + 2;
}

float multiply(float a, float b) {
	return a * b;
}

int main() {
	// Test 1.
	// Expression is evaluated.
	{
		calc::Calculator calculator;
		std::string expression = "2.1+~3.2*5^(3-1)/(2*3.14 - 1)";
		const float answer = -13.0515151515151515f;
		float value = calculator.excecute(expression);
		std::cout << expression << "=" << value << "\n";
		// Test expression!
		assert(equal(answer, value));
	}

	// Test 2.
	// Expression is evaluated with added constants.
	{
		calc::Calculator calculator;
		calculator.addVariable("PI", 3.14f);
		calculator.addVariable("TWO", 2);
		calculator.addVariable("FIVE", 5);
		std::string expression = "2.1+~3.2*FIVE^(3-1)/(TWO*PI - 1)";
		const float answer = -13.0515151515151515f;
		float value = calculator.excecute(expression);
		std::cout << expression << "=" << value << "\n";
		// Test expression!
		assert(equal(answer, value));
	}

	// Test 2.
	// Expression is evaluated with added constants and functions.
	{
		calc::Calculator calculator;
		calculator.addVariable("PI", 3.14f);
		calculator.addVariable("TWO", 2);
		calculator.addVariable("FIVE", 5);
		calculator.addFunction("addTwo", 1, std::bind(addTwo, std::placeholders::_1, std::placeholders::_2));
		calculator.addFunction("multiply", 2, std::bind(multiply, std::placeholders::_1, std::placeholders::_2));

		std::string expression = "multiply(addTwo(2.1+~3.2*FIVE^(3-1)/(TWO*PI - 1)), 8.1)";
		const float answer = (-13.0515151515151515f + 2)*8.1f;
		float value = calculator.excecute(expression);
		std::cout << expression << "=" << value << "\n";
		// Test expression!
		assert(equal(answer, value));
	}

	// Test 2.
	// Expression is evaluated with added constants and functions.
	{
		calc::Calculator calculator;
		calculator.addVariable("pi", 3.14159265359f);
		calculator.addFunction("exp", 1, [](float a, float b) {
			return std::exp(a);
		});
		calculator.addFunction("sin", 1, [](float a, float b) {
			return std::sin(a);
		});
		calculator.addFunction("cos", 1, [](float a, float b) {
			return std::cos(a);
		});
		calculator.addFunction("ln", 1, [](float a, float b) {
			return std::log(a);
		});
		calculator.addFunction("log", 1, [](float a, float b) {
			return std::log10(a);
		});
		calculator.addFunction("pow", 2, [](float a, float b) {
			return std::pow(a,b);
		});

		assert(equal(calculator.excecute("exp(1.11)"), 3.034358f));

		assert(equal(calculator.excecute("sin( cos(90*pi / 180))"), 0.000001f));
		assert(equal(calculator.excecute("34.5*(23+1.5)/2"), 422.625000f));

		assert(equal(calculator.excecute("5 + ((1 + 2) * 4) - 3"), 14));
		assert(equal(calculator.excecute("( 1 + 2 ) * ( 3 / 4 ) ^ ( 5 + 6 )"), 0.126705f));
		assert(equal(calculator.excecute("3/2 + 4*(12+3)"), 61.5f));

		assert(equal(calculator.excecute("pi*pow(9/2,2)"), 63.617197f));
		assert(equal(calculator.excecute("((2*(6-1))/2)*4"), 20));

		assert(equal(calculator.excecute("ln(2)+3^5"), 243.693147f));

		assert(equal(calculator.excecute("11 ^ -7"), 5.13158f*std::pow(10.f, -8.f)));
		assert(equal(calculator.excecute("cos ( ( 1.3 + 1 ) ^ ( 1 / 3 ) ) - log ( ~2 * 3 / ~14 )"), 0.616143f));
		assert(equal(calculator.excecute("1 * ~sin( pi / 2) "), -1));
		assert(equal(calculator.excecute("~8 + 5"), -3));
		assert(equal(calculator.excecute("1 - (~(2^2)) - 1"), 4));
	}

	std::cout << "\nAll tests succeeded!\n";

	return 0;
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/minimodel.hh>

using namespace Gecode;

//
// g++ -g simple_dependency.cpp -lgecodesupport -lgecodekernel -lgecodeint -lgecodesearch -lgecodedriver -lpthread -ldl   -lstdc++ -o simple_dependency
//

class SimpleDependency : public MinimizeScript {
protected:
  static const int PKG_COUNT = 11;

  IntVarArray package_versions;
  IntArgs disabled_package_weights;
  BoolVarArray disabled_package_variables;
  IntVar total_disabled;
public:
  /// Actual model
  SimpleDependency(const Options& opt) :
    package_versions(*this, PKG_COUNT, -1, 10),
    disabled_package_variables(*this, PKG_COUNT, 0, 1),
    total_disabled(*this, 0, 10*PKG_COUNT)
  {
    Problem2();

    branch(*this, package_versions, INT_VAR_SIZE_MIN, INT_VAL_MAX);
    branch(*this, disabled_package_variables, INT_VAR_SIZE_MIN, INT_VAL_MIN);
    branch(*this, total_disabled, INT_VAL_MIN);
  }

  void Problem1() {
    // Add version constraints for pkg 0
    dom(*this, package_versions[0], -1, 0);
    dom(*this, package_versions[1], -1, 0);
    dom(*this, package_versions[2], -1, 0);
    dom(*this, package_versions[3], -1, 1);
    dom(*this, package_versions[4], -1, 0);
    dom(*this, package_versions[5], -1, 0);
    dom(*this, package_versions[6], -1, 2);
    dom(*this, package_versions[7], -1, 0);
    dom(*this, package_versions[8], -1, 0);
    dom(*this, package_versions[9], -1, -1);
    dom(*this, package_versions[10], 0, 0);

    AddVersionConstraint(0, 0, 1, 0, 1);
    AddVersionConstraint(2, 0, 1, 0, 0);
    AddVersionConstraint(1, 0, 3, 0, 1);
    AddVersionConstraint(1, 0, 4, 0, 0);
    AddVersionConstraint(1, 1, 3, 1, 1);
    AddVersionConstraint(1, 1, 5, 0, 0);
    AddVersionConstraint(7, 0, 3, -2, -2);
    AddVersionConstraint(8, 0, 9, -2, -2);
    AddVersionConstraint(10, 0, 7, 0, 0);

    IntArgs package_weights(PKG_COUNT, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10 );

    std::cout << "Package versions:           " << package_versions << std::endl;
    std::cout << "Disabled package variables: " << disabled_package_variables << std::endl;
    std::cout << "Package weights             " << package_weights << std::endl;
    std::cout << "Total disabled:             " << total_disabled << std::endl;

    linear(*this, disabled_package_variables, IRT_EQ, total_disabled);
  }

  void Problem2() {
    // Add version constraints for pkg 0
    dom(*this, package_versions[0], -1, 0);
    dom(*this, package_versions[1], -1, 0);
    dom(*this, package_versions[2], -1, 0);
    dom(*this, package_versions[3], -1, 1);
    dom(*this, package_versions[4], -1, 0);
    dom(*this, package_versions[5], -1, 0);
    dom(*this, package_versions[6], -1, 2);
    dom(*this, package_versions[7], -1, 0);
    dom(*this, package_versions[8], -1, 0);
    dom(*this, package_versions[9], -1, -1);
    dom(*this, package_versions[10], 0, 0);

    AddVersionConstraint(0, 0, 1, 0, 1);
    AddVersionConstraint(2, 0, 1, 0, 0);
    AddVersionConstraint(1, 0, 3, 0, 1);
    AddVersionConstraint(1, 0, 4, 0, 0);
    AddVersionConstraint(1, 1, 3, 1, 1);
    AddVersionConstraint(1, 1, 5, 0, 0);
    AddVersionConstraint(7, 0, 3, -2, -2);
    AddVersionConstraint(8, 0, 9, -2, -2);
    AddVersionConstraint(10, 0, 7, 0, 0);

    IntArgs package_weights(PKG_COUNT, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10 );

    std::cout << "Package versions:           " << package_versions << std::endl;
    std::cout << "Disabled package variables: " << disabled_package_variables << std::endl;
    std::cout << "Package weights             " << package_weights << std::endl;
    std::cout << "Total disabled:             " << total_disabled << std::endl;

    linear(*this, package_weights, disabled_package_variables, IRT_EQ, total_disabled);
  }

  bool AddVersionConstraint(int packageId, int version,
			    int dependentPackageId, int minDependentVersion, int maxDependentVersion)
  {
    BoolVar version_match(*this, 0, 1);
    BoolVar depend_match(*this, 0, 1);
    BoolVar predicated_depend_match(*this, 0, 1);

    std::cout << "Add VC for " << packageId << " @ " << version << " depPkg " << dependentPackageId;
    std::cout << " [ " << minDependentVersion << ", " << maxDependentVersion << " ]" << std::endl;
    std::cout.flush();

    //version_flags << version_match;
    // Constrain pred to reify package @ version
    rel(*this, package_versions[packageId], IRT_EQ, version, version_match);
    // Add the predicated version constraints imposed on dependent package
    dom(*this, package_versions[dependentPackageId], minDependentVersion, maxDependentVersion, depend_match);
    // disabled_package_variables[dependentPackageId] OR depend_match <=> version_match

    rel(*this, disabled_package_variables[dependentPackageId], BOT_OR, depend_match, predicated_depend_match);
    rel(*this, version_match, BOT_IMP, predicated_depend_match, 1);
  }

  /// Print solution
  virtual void
  print(std::ostream& os) const {
    os << "\t" << package_versions << std::endl;
    os << "\t" << disabled_package_variables << std::endl;
    os << "\t" << total_disabled << std::endl;
  }
  virtual IntVar cost() const {
    return total_disabled;
  }

  /// Constructor for cloning \a s
  SimpleDependency(bool share, SimpleDependency& s) :
    MinimizeScript(share,s),
    package_versions(s.package_versions),
    disabled_package_variables(s.disabled_package_variables),
    total_disabled(s.total_disabled)
  {
    package_versions.update(*this, share, s.package_versions);
    disabled_package_variables.update(*this, share, s.disabled_package_variables);
    total_disabled.update(*this, share, s.total_disabled);
  }
  /// Copy during cloning
  virtual Space*
  copy(bool share) {
    return new SimpleDependency(share,*this);
  }
};

/** \brief Main-function
 *  \relates Money
 */
int
main(int argc, char* argv[]) {
  Options opt("Solve dependency");
  opt.solutions(0);
  opt.iterations(20000);
  opt.parse(argc,argv);
  MaximizeScript::run<SimpleDependency,Restart,Options>(opt);
  return 0;
}

// STATISTICS: example-any

<commit_msg>Make weights work. <commit_after>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/minimodel.hh>

using namespace Gecode;

//
// g++ -g simple_dependency.cpp -lgecodesupport -lgecodekernel -lgecodeint -lgecodesearch -lgecodedriver -lpthread -ldl   -lstdc++ -o simple_dependency
//

class SimpleDependency : public MinimizeScript {
protected:
  static const int PKG_COUNT = 11;

  IntVarArray package_versions;
  IntArgs disabled_package_weights;
  BoolVarArray disabled_package_variables;
  IntVar total_disabled;
public:
  /// Actual model
  SimpleDependency(const Options& opt) :
    package_versions(*this, PKG_COUNT, -1, 10),
    disabled_package_variables(*this, PKG_COUNT, 0, 1),
    total_disabled(*this, 0, 10*PKG_COUNT)
  {
    Problem2();

    branch(*this, package_versions, INT_VAR_SIZE_MIN, INT_VAL_MAX);
    branch(*this, disabled_package_variables, INT_VAR_SIZE_MIN, INT_VAL_MIN);
    branch(*this, total_disabled, INT_VAL_MIN);
  }

  void Problem1() {
    // Add version constraints for pkg 0
    dom(*this, package_versions[0], -1, 0);
    dom(*this, package_versions[1], -1, 0);
    dom(*this, package_versions[2], -1, 0);
    dom(*this, package_versions[3], -1, 1);
    dom(*this, package_versions[4], -1, 0);
    dom(*this, package_versions[5], -1, 0);
    dom(*this, package_versions[6], -1, 2);
    dom(*this, package_versions[7], -1, 0);
    dom(*this, package_versions[8], -1, 0);
    dom(*this, package_versions[9], -1, -1);
    dom(*this, package_versions[10], 0, 0);

    AddVersionConstraint(0, 0, 1, 0, 1);
    AddVersionConstraint(2, 0, 1, 0, 0);
    AddVersionConstraint(1, 0, 3, 0, 1);
    AddVersionConstraint(1, 0, 4, 0, 0);
    AddVersionConstraint(1, 1, 3, 1, 1);
    AddVersionConstraint(1, 1, 5, 0, 0);
    AddVersionConstraint(7, 0, 3, -2, -2);
    AddVersionConstraint(8, 0, 9, -2, -2);
    AddVersionConstraint(10, 0, 7, 0, 0);

    IntArgs package_weights(PKG_COUNT, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10 );

    std::cout << "Package versions:           " << package_versions << std::endl;
    std::cout << "Disabled package variables: " << disabled_package_variables << std::endl;
    std::cout << "Package weights             " << package_weights << std::endl;
    std::cout << "Total disabled:             " << total_disabled << std::endl;

    linear(*this, package_weights, disabled_package_variables, IRT_EQ, total_disabled);
  }

  void Problem2() {
    // Add version constraints for pkg 0
    dom(*this, package_versions[0], -1, 0);
    dom(*this, package_versions[1], -1, 0);
    dom(*this, package_versions[2], -1, 0);
    dom(*this, package_versions[3], -1, 1);
    dom(*this, package_versions[4], -1, 0);
    dom(*this, package_versions[5], -1, 0);
    dom(*this, package_versions[6], -1, 2);
    dom(*this, package_versions[7], -1, 0);
    dom(*this, package_versions[8], -1, 0);
    dom(*this, package_versions[9], -1, -1);
    dom(*this, package_versions[10], 0, 0);

    AddVersionConstraint(0, 0, 1, 0, 1);
    AddVersionConstraint(2, 0, 1, 0, 0);
    AddVersionConstraint(1, 0, 3, 0, 1);
    AddVersionConstraint(1, 0, 4, 0, 0);
    AddVersionConstraint(1, 1, 3, 1, 1);
    AddVersionConstraint(1, 1, 5, 0, 0);
    AddVersionConstraint(7, 0, 3, -2, -2);
    AddVersionConstraint(8, 0, 9, -2, -2);
    AddVersionConstraint(10, 0, 7, 0, 0);

    IntArgs package_weights(PKG_COUNT, 10, 10, 10, 10, 10,  10, 10, 5, 10, 10 );

    std::cout << "Package versions:           " << package_versions << std::endl;
    std::cout << "Disabled package variables: " << disabled_package_variables << std::endl;
    std::cout << "Package weights             " << package_weights << std::endl;
    std::cout << "Total disabled:             " << total_disabled << std::endl;

    linear(*this, package_weights, disabled_package_variables, IRT_EQ, total_disabled);
  }

  bool AddVersionConstraint(int packageId, int version,
			    int dependentPackageId, int minDependentVersion, int maxDependentVersion)
  {
    BoolVar version_match(*this, 0, 1);
    BoolVar depend_match(*this, 0, 1);
    BoolVar predicated_depend_match(*this, 0, 1);

    std::cout << "Add VC for " << packageId << " @ " << version << " depPkg " << dependentPackageId;
    std::cout << " [ " << minDependentVersion << ", " << maxDependentVersion << " ]" << std::endl;
    std::cout.flush();

    //version_flags << version_match;
    // Constrain pred to reify package @ version
    rel(*this, package_versions[packageId], IRT_EQ, version, version_match);
    // Add the predicated version constraints imposed on dependent package
    dom(*this, package_versions[dependentPackageId], minDependentVersion, maxDependentVersion, depend_match);
    // disabled_package_variables[dependentPackageId] OR depend_match <=> version_match

    rel(*this, disabled_package_variables[dependentPackageId], BOT_OR, depend_match, predicated_depend_match);
    rel(*this, version_match, BOT_IMP, predicated_depend_match, 1);
  }

  /// Print solution
  virtual void
  print(std::ostream& os) const {
    os << "\t" << package_versions << std::endl;
    os << "\t" << disabled_package_variables << std::endl;
    os << "\t" << total_disabled << std::endl;
  }
  virtual IntVar cost() const {
    return total_disabled;
  }

  /// Constructor for cloning \a s
  SimpleDependency(bool share, SimpleDependency& s) :
    MinimizeScript(share,s),
    package_versions(s.package_versions),
    disabled_package_variables(s.disabled_package_variables),
    total_disabled(s.total_disabled)
  {
    package_versions.update(*this, share, s.package_versions);
    disabled_package_variables.update(*this, share, s.disabled_package_variables);
    total_disabled.update(*this, share, s.total_disabled);
  }
  /// Copy during cloning
  virtual Space*
  copy(bool share) {
    return new SimpleDependency(share,*this);
  }
};

/** \brief Main-function
 *  \relates Money
 */
int
main(int argc, char* argv[]) {
  Options opt("Solve dependency");
  opt.solutions(0);
  opt.iterations(20000);
  opt.parse(argc,argv);
  MaximizeScript::run<SimpleDependency,Restart,Options>(opt);
  return 0;
}

// STATISTICS: example-any

<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/x509_certificate.h"

#include <CommonCrypto/CommonDigest.h>
#include <time.h>

#include "base/histogram.h"
#include "base/logging.h"
#include "base/pickle.h"
#include "net/base/cert_status_flags.h"
#include "net/base/ev_root_ca_metadata.h"

namespace net {

namespace {

// Calculates the SHA-1 fingerprint of the certificate.  Returns an empty
// (all zero) fingerprint on failure.
X509Certificate::Fingerprint CalculateFingerprint(
    X509Certificate::OSCertHandle cert) {
  X509Certificate::Fingerprint sha1;
  memset(sha1.data, 0, sizeof(sha1.data));

  CSSM_DATA cert_data;
  OSStatus status = SecCertificateGetData(cert, &cert_data);
  if (status)
    return sha1;

  DCHECK(NULL != cert_data.Data);
  DCHECK(0 != cert_data.Length);

  CC_SHA1(cert_data.Data, cert_data.Length, sha1.data);

  return sha1;
}

inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) {
  return oid1->Length == oid2->Length &&
      (memcmp(oid1->Data, oid2->Data, oid1->Length) == 0);
}

void ParsePrincipal(const CSSM_X509_NAME* name,
                    X509Certificate::Principal* principal) {
  std::vector<std::string> common_names, locality_names, state_names,
      country_names;

  // TODO(jcampan): add business_category and serial_number.
  const CSSM_OID* kOIDs[] = { &CSSMOID_CommonName,
                              &CSSMOID_LocalityName,
                              &CSSMOID_StateProvinceName,
                              &CSSMOID_CountryName,
                              &CSSMOID_StreetAddress,
                              &CSSMOID_OrganizationName,
                              &CSSMOID_OrganizationalUnitName,
                              &CSSMOID_DNQualifier };  // This should be "DC"
                                                       // but is undoubtedly
                                                       // wrong. TODO(avi):
                                                       // Find the right OID.

  std::vector<std::string>* values[] = {
      &common_names, &locality_names,
      &state_names, &country_names,
      &(principal->street_addresses),
      &(principal->organization_names),
      &(principal->organization_unit_names),
      &(principal->domain_components) };
  DCHECK(arraysize(kOIDs) == arraysize(values));

  for (size_t rdn = 0; rdn < name->numberOfRDNs; ++rdn) {
    CSSM_X509_RDN rdn_struct = name->RelativeDistinguishedName[rdn];
    for (size_t pair = 0; pair < rdn_struct.numberOfPairs; ++pair) {
      CSSM_X509_TYPE_VALUE_PAIR pair_struct =
          rdn_struct.AttributeTypeAndValue[pair];
      for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
        if (CSSMOIDEqual(&pair_struct.type, kOIDs[oid])) {
          std::string value =
              std::string(reinterpret_cast<std::string::value_type*>
                              (pair_struct.value.Data),
                          pair_struct.value.Length);
          values[oid]->push_back(value);
          break;
        }
      }
    }
  }

  // We don't expect to have more than one CN, L, S, and C.
  std::vector<std::string>* single_value_lists[4] = {
      &common_names, &locality_names, &state_names, &country_names };
  std::string* single_values[4] = {
      &principal->common_name, &principal->locality_name,
      &principal->state_or_province_name, &principal->country_name };
  for (size_t i = 0; i < arraysize(single_value_lists); ++i) {
    DCHECK(single_value_lists[i]->size() <= 1);
    if (single_value_lists[i]->size() > 0)
      *(single_values[i]) = (*(single_value_lists[i]))[0];
  }
}

OSStatus GetCertFieldsForOID(X509Certificate::OSCertHandle cert_handle,
                             CSSM_OID oid, uint32* num_of_fields,
                             CSSM_FIELD_PTR* fields) {
  *num_of_fields = 0;
  *fields = NULL;

  CSSM_DATA cert_data;
  OSStatus status = SecCertificateGetData(cert_handle, &cert_data);
  if (status)
    return status;

  CSSM_CL_HANDLE cl_handle;
  status = SecCertificateGetCLHandle(cert_handle, &cl_handle);
  if (status)
    return status;

  status = CSSM_CL_CertGetAllFields(cl_handle, &cert_data, num_of_fields,
                                    fields);
  return status;
}

void GetCertGeneralNamesForOID(X509Certificate::OSCertHandle cert_handle,
                               CSSM_OID oid, CE_GeneralNameType name_type,
                               std::vector<std::string>* result) {
  uint32 num_of_fields;
  CSSM_FIELD_PTR fields;
  OSStatus status = GetCertFieldsForOID(cert_handle, oid, &num_of_fields,
                                        &fields);
  if (status)
    return;

  for (size_t field = 0; field < num_of_fields; ++field) {
    if (CSSMOIDEqual(&fields[field].FieldOid, &oid)) {
      CSSM_X509_EXTENSION_PTR cssm_ext =
          (CSSM_X509_EXTENSION_PTR)fields[field].FieldValue.Data;
      CE_GeneralNames* alt_name =
          (CE_GeneralNames*) cssm_ext->value.parsedValue;

      for (size_t name = 0; name < alt_name->numNames; ++name) {
        const CE_GeneralName& name_struct = alt_name->generalName[name];
        // For future extension: We're assuming that these values are of types
        // GNT_RFC822Name, GNT_DNSName or GNT_URI, all of which are encoded as
        // IA5String. In general, we should be switching off
        // |name_struct.nameType| and doing type-appropriate conversions. See
        // certextensions.h and the comment immediately preceding
        // CE_GeneralNameType for more information.
        if (name_struct.nameType == name_type) {
          const CSSM_DATA& name_data = name_struct.name;
          std::string value =
          std::string(reinterpret_cast<std::string::value_type*>
                      (name_data.Data),
                      name_data.Length);
          result->push_back(value);
        }
      }
    }
  }
}

void GetCertDateForOID(X509Certificate::OSCertHandle cert_handle,
                       CSSM_OID oid, Time* result) {
  uint32 num_of_fields;
  CSSM_FIELD_PTR fields;
  OSStatus status = GetCertFieldsForOID(cert_handle, oid, &num_of_fields,
                                        &fields);
  if (status)
    return;

  for (size_t field = 0; field < num_of_fields; ++field) {
    if (CSSMOIDEqual(&fields[field].FieldOid, &oid)) {
      CSSM_X509_TIME* x509_time =
          reinterpret_cast<CSSM_X509_TIME *>(fields[field].FieldValue.Data);
      std::string time_string =
          std::string(reinterpret_cast<std::string::value_type*>
                      (x509_time->time.Data),
                      x509_time->time.Length);

      struct tm time;
      const char* parse_string;
      if (x509_time->timeType == BER_TAG_UTC_TIME)
        parse_string = "%y%m%d%H%M%SZ";
      else if (x509_time->timeType == BER_TAG_GENERALIZED_TIME)
        parse_string = "%y%m%d%H%M%SZ";
      // else log?

      strptime(time_string.c_str(), parse_string, &time);

      Time::Exploded exploded;
      exploded.year         = time.tm_year + 1900;
      exploded.month        = time.tm_mon + 1;
      exploded.day_of_week  = time.tm_wday;
      exploded.day_of_month = time.tm_mday;
      exploded.hour         = time.tm_hour;
      exploded.minute       = time.tm_min;
      exploded.second       = time.tm_sec;
      exploded.millisecond  = 0;

      *result = Time::FromUTCExploded(exploded);
    }
  }
}

}  // namespace

void X509Certificate::Initialize() {
  const CSSM_X509_NAME* name;
  OSStatus status = SecCertificateGetSubject(cert_handle_, &name);
  if (!status) {
    ParsePrincipal(name, &subject_);
  }
  status = SecCertificateGetIssuer(cert_handle_, &name);
  if (!status) {
    ParsePrincipal(name, &issuer_);
  }

  GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore,
                    &valid_start_);
  GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter,
                    &valid_expiry_);

  fingerprint_ = CalculateFingerprint(cert_handle_);

  // Store the certificate in the cache in case we need it later.
  X509Certificate::Cache::GetInstance()->Insert(this);
}

// static
X509Certificate* X509Certificate::CreateFromHandle(OSCertHandle cert_handle) {
  DCHECK(cert_handle);

  // Check if we already have this certificate in memory.
  X509Certificate::Cache* cache = X509Certificate::Cache::GetInstance();
  X509Certificate* cert = cache->Find(CalculateFingerprint(cert_handle));
  if (cert) {
    // We've found a certificate with the same fingerprint in our cache.  We own
    // the |cert_handle|, which makes it our job to free it.
    CFRelease(cert_handle);
    DHISTOGRAM_COUNTS(L"X509CertificateReuseCount", 1);
    return cert;
  }
  // Otherwise, allocate a new object.
  return new X509Certificate(cert_handle);
}

// static
X509Certificate* X509Certificate::CreateFromBytes(const char* data,
                                                  int length) {
  CSSM_DATA cert_data;
  cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data));
  cert_data.Length = length;

  OSCertHandle cert_handle = NULL;
  OSStatus status = SecCertificateCreateFromData(&cert_data,
                                                 CSSM_CERT_X_509v3,
                                                 CSSM_CERT_ENCODING_BER,
                                                 &cert_handle);
  if (status)
    return NULL;

  return CreateFromHandle(cert_handle);
}

// static
X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
                                                   void** pickle_iter) {
  const char* data;
  int length;
  if (!pickle.ReadData(pickle_iter, &data, &length))
    return NULL;

  return CreateFromBytes(data, length);
}

X509Certificate::X509Certificate(OSCertHandle cert_handle)
    : cert_handle_(cert_handle) {
  Initialize();
}

X509Certificate::X509Certificate(std::string subject, std::string issuer,
                                 Time start_date, Time expiration_date)
    : subject_(subject),
      issuer_(issuer),
      valid_start_(start_date),
      valid_expiry_(expiration_date),
      cert_handle_(NULL) {
  memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
}

void X509Certificate::Persist(Pickle* pickle) {
  CSSM_DATA cert_data;
  OSStatus status = SecCertificateGetData(cert_handle_, &cert_data);
  if (status) {
    NOTREACHED();
    return;
  }

  pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), cert_data.Length);
}

X509Certificate::~X509Certificate() {
  // We might not be in the cache, but it is safe to remove ourselves anyway.
  X509Certificate::Cache::GetInstance()->Remove(this);
  if (cert_handle_)
    CFRelease(cert_handle_);
}

void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
  dns_names->clear();

  GetCertGeneralNamesForOID(cert_handle_, CSSMOID_SubjectAltName, GNT_DNSName,
                            dns_names);

  if (dns_names->empty())
    dns_names->push_back(subject_.common_name);
}

// Returns true if the certificate is an extended-validation certificate.
//
// The certificate has already been verified by the HTTP library.  cert_status
// represents the result of that verification.  This function performs
// additional checks of the certificatePolicies extensions of the certificates
// in the certificate chain according to Section 7 (pp. 11-12) of the EV
// Certificate Guidelines Version 1.0 at
// http://cabforum.org/EV_Certificate_Guidelines.pdf.
bool X509Certificate::IsEV(int cert_status) const {
  // TODO(avi): implement this
  NOTIMPLEMENTED();
  return false;
}

}  // namespace net
<commit_msg>Some quick changes suggested by wtc in review.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/x509_certificate.h"

#include <CommonCrypto/CommonDigest.h>
#include <time.h>

#include "base/histogram.h"
#include "base/logging.h"
#include "base/pickle.h"
#include "net/base/cert_status_flags.h"
#include "net/base/ev_root_ca_metadata.h"

namespace net {

namespace {

// Calculates the SHA-1 fingerprint of the certificate.  Returns an empty
// (all zero) fingerprint on failure.
X509Certificate::Fingerprint CalculateFingerprint(
    X509Certificate::OSCertHandle cert) {
  X509Certificate::Fingerprint sha1;
  memset(sha1.data, 0, sizeof(sha1.data));

  CSSM_DATA cert_data;
  OSStatus status = SecCertificateGetData(cert, &cert_data);
  if (status)
    return sha1;

  DCHECK(NULL != cert_data.Data);
  DCHECK(0 != cert_data.Length);

  CC_SHA1(cert_data.Data, cert_data.Length, sha1.data);

  return sha1;
}

inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) {
  return oid1->Length == oid2->Length &&
      (memcmp(oid1->Data, oid2->Data, oid1->Length) == 0);
}

void ParsePrincipal(const CSSM_X509_NAME* name,
                    X509Certificate::Principal* principal) {
  std::vector<std::string> common_names, locality_names, state_names,
      country_names;

  // TODO(jcampan): add business_category and serial_number.
  const CSSM_OID* kOIDs[] = { &CSSMOID_CommonName,
                              &CSSMOID_LocalityName,
                              &CSSMOID_StateProvinceName,
                              &CSSMOID_CountryName,
                              &CSSMOID_StreetAddress,
                              &CSSMOID_OrganizationName,
                              &CSSMOID_OrganizationalUnitName,
                              &CSSMOID_DNQualifier };  // This should be "DC"
                                                       // but is undoubtedly
                                                       // wrong. TODO(avi):
                                                       // Find the right OID.

  std::vector<std::string>* values[] = {
      &common_names, &locality_names,
      &state_names, &country_names,
      &(principal->street_addresses),
      &(principal->organization_names),
      &(principal->organization_unit_names),
      &(principal->domain_components) };
  DCHECK(arraysize(kOIDs) == arraysize(values));

  for (size_t rdn = 0; rdn < name->numberOfRDNs; ++rdn) {
    CSSM_X509_RDN rdn_struct = name->RelativeDistinguishedName[rdn];
    for (size_t pair = 0; pair < rdn_struct.numberOfPairs; ++pair) {
      CSSM_X509_TYPE_VALUE_PAIR pair_struct =
          rdn_struct.AttributeTypeAndValue[pair];
      for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
        if (CSSMOIDEqual(&pair_struct.type, kOIDs[oid])) {
          std::string value =
              std::string(reinterpret_cast<std::string::value_type*>
                              (pair_struct.value.Data),
                          pair_struct.value.Length);
          values[oid]->push_back(value);
          break;
        }
      }
    }
  }

  // We don't expect to have more than one CN, L, S, and C.
  std::vector<std::string>* single_value_lists[4] = {
      &common_names, &locality_names, &state_names, &country_names };
  std::string* single_values[4] = {
      &principal->common_name, &principal->locality_name,
      &principal->state_or_province_name, &principal->country_name };
  for (size_t i = 0; i < arraysize(single_value_lists); ++i) {
    DCHECK(single_value_lists[i]->size() <= 1);
    if (single_value_lists[i]->size() > 0)
      *(single_values[i]) = (*(single_value_lists[i]))[0];
  }
}

OSStatus GetCertFieldsForOID(X509Certificate::OSCertHandle cert_handle,
                             CSSM_OID oid, uint32* num_of_fields,
                             CSSM_FIELD_PTR* fields) {
  *num_of_fields = 0;
  *fields = NULL;

  CSSM_DATA cert_data;
  OSStatus status = SecCertificateGetData(cert_handle, &cert_data);
  if (status)
    return status;

  CSSM_CL_HANDLE cl_handle;
  status = SecCertificateGetCLHandle(cert_handle, &cl_handle);
  if (status)
    return status;

  status = CSSM_CL_CertGetAllFields(cl_handle, &cert_data, num_of_fields,
                                    fields);
  return status;
}

void GetCertGeneralNamesForOID(X509Certificate::OSCertHandle cert_handle,
                               CSSM_OID oid, CE_GeneralNameType name_type,
                               std::vector<std::string>* result) {
  uint32 num_of_fields;
  CSSM_FIELD_PTR fields;
  OSStatus status = GetCertFieldsForOID(cert_handle, oid, &num_of_fields,
                                        &fields);
  if (status)
    return;

  for (size_t field = 0; field < num_of_fields; ++field) {
    if (CSSMOIDEqual(&fields[field].FieldOid, &oid)) {
      CSSM_X509_EXTENSION_PTR cssm_ext =
          (CSSM_X509_EXTENSION_PTR)fields[field].FieldValue.Data;
      CE_GeneralNames* alt_name =
          (CE_GeneralNames*) cssm_ext->value.parsedValue;

      for (size_t name = 0; name < alt_name->numNames; ++name) {
        const CE_GeneralName& name_struct = alt_name->generalName[name];
        // For future extension: We're assuming that these values are of types
        // GNT_RFC822Name, GNT_DNSName or GNT_URI, all of which are encoded as
        // IA5String. In general, we should be switching off
        // |name_struct.nameType| and doing type-appropriate conversions. See
        // certextensions.h and the comment immediately preceding
        // CE_GeneralNameType for more information.
        DCHECK(name_struct.nameType == GNT_RFC822Name ||
               name_struct.nameType == GNT_DNSName ||
               name_struct.nameType == GNT_URI);
        if (name_struct.nameType == name_type) {
          const CSSM_DATA& name_data = name_struct.name;
          std::string value =
          std::string(reinterpret_cast<std::string::value_type*>
                      (name_data.Data),
                      name_data.Length);
          result->push_back(value);
        }
      }
    }
  }
}

void GetCertDateForOID(X509Certificate::OSCertHandle cert_handle,
                       CSSM_OID oid, Time* result) {
  *result = Time::Time();

  uint32 num_of_fields;
  CSSM_FIELD_PTR fields;
  OSStatus status = GetCertFieldsForOID(cert_handle, oid, &num_of_fields,
                                        &fields);
  if (status)
    return;

  for (size_t field = 0; field < num_of_fields; ++field) {
    if (CSSMOIDEqual(&fields[field].FieldOid, &oid)) {
      CSSM_X509_TIME* x509_time =
          reinterpret_cast<CSSM_X509_TIME *>(fields[field].FieldValue.Data);
      std::string time_string =
          std::string(reinterpret_cast<std::string::value_type*>
                      (x509_time->time.Data),
                      x509_time->time.Length);

      DCHECK(x509_time->timeType == BER_TAG_UTC_TIME ||
             x509_time->timeType == BER_TAG_GENERALIZED_TIME);

      struct tm time;
      const char* parse_string;
      if (x509_time->timeType == BER_TAG_UTC_TIME)
        parse_string = "%y%m%d%H%M%SZ";
      else if (x509_time->timeType == BER_TAG_GENERALIZED_TIME)
        parse_string = "%y%m%d%H%M%SZ";
      else {
        // Those are the only two BER tags for time; if neither are used then
        // this is a rather broken cert.
        return;
      }

      strptime(time_string.c_str(), parse_string, &time);

      Time::Exploded exploded;
      exploded.year         = time.tm_year + 1900;
      exploded.month        = time.tm_mon + 1;
      exploded.day_of_week  = time.tm_wday;
      exploded.day_of_month = time.tm_mday;
      exploded.hour         = time.tm_hour;
      exploded.minute       = time.tm_min;
      exploded.second       = time.tm_sec;
      exploded.millisecond  = 0;

      *result = Time::FromUTCExploded(exploded);
      break;
    }
  }
}

}  // namespace

void X509Certificate::Initialize() {
  const CSSM_X509_NAME* name;
  OSStatus status = SecCertificateGetSubject(cert_handle_, &name);
  if (!status) {
    ParsePrincipal(name, &subject_);
  }
  status = SecCertificateGetIssuer(cert_handle_, &name);
  if (!status) {
    ParsePrincipal(name, &issuer_);
  }

  GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore,
                    &valid_start_);
  GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter,
                    &valid_expiry_);

  fingerprint_ = CalculateFingerprint(cert_handle_);

  // Store the certificate in the cache in case we need it later.
  X509Certificate::Cache::GetInstance()->Insert(this);
}

// static
X509Certificate* X509Certificate::CreateFromHandle(OSCertHandle cert_handle) {
  DCHECK(cert_handle);

  // Check if we already have this certificate in memory.
  X509Certificate::Cache* cache = X509Certificate::Cache::GetInstance();
  X509Certificate* cert = cache->Find(CalculateFingerprint(cert_handle));
  if (cert) {
    // We've found a certificate with the same fingerprint in our cache.  We own
    // the |cert_handle|, which makes it our job to free it.
    CFRelease(cert_handle);
    DHISTOGRAM_COUNTS(L"X509CertificateReuseCount", 1);
    return cert;
  }
  // Otherwise, allocate a new object.
  return new X509Certificate(cert_handle);
}

// static
X509Certificate* X509Certificate::CreateFromBytes(const char* data,
                                                  int length) {
  CSSM_DATA cert_data;
  cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data));
  cert_data.Length = length;

  OSCertHandle cert_handle = NULL;
  OSStatus status = SecCertificateCreateFromData(&cert_data,
                                                 CSSM_CERT_X_509v3,
                                                 CSSM_CERT_ENCODING_BER,
                                                 &cert_handle);
  if (status)
    return NULL;

  return CreateFromHandle(cert_handle);
}

// static
X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
                                                   void** pickle_iter) {
  const char* data;
  int length;
  if (!pickle.ReadData(pickle_iter, &data, &length))
    return NULL;

  return CreateFromBytes(data, length);
}

X509Certificate::X509Certificate(OSCertHandle cert_handle)
    : cert_handle_(cert_handle) {
  Initialize();
}

X509Certificate::X509Certificate(std::string subject, std::string issuer,
                                 Time start_date, Time expiration_date)
    : subject_(subject),
      issuer_(issuer),
      valid_start_(start_date),
      valid_expiry_(expiration_date),
      cert_handle_(NULL) {
  memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
}

void X509Certificate::Persist(Pickle* pickle) {
  CSSM_DATA cert_data;
  OSStatus status = SecCertificateGetData(cert_handle_, &cert_data);
  if (status) {
    NOTREACHED();
    return;
  }

  pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), cert_data.Length);
}

X509Certificate::~X509Certificate() {
  // We might not be in the cache, but it is safe to remove ourselves anyway.
  X509Certificate::Cache::GetInstance()->Remove(this);
  if (cert_handle_)
    CFRelease(cert_handle_);
}

void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
  dns_names->clear();

  GetCertGeneralNamesForOID(cert_handle_, CSSMOID_SubjectAltName, GNT_DNSName,
                            dns_names);

  if (dns_names->empty())
    dns_names->push_back(subject_.common_name);
}

// Returns true if the certificate is an extended-validation certificate.
//
// The certificate has already been verified by the HTTP library.  cert_status
// represents the result of that verification.  This function performs
// additional checks of the certificatePolicies extensions of the certificates
// in the certificate chain according to Section 7 (pp. 11-12) of the EV
// Certificate Guidelines Version 1.0 at
// http://cabforum.org/EV_Certificate_Guidelines.pdf.
bool X509Certificate::IsEV(int cert_status) const {
  // TODO(avi): implement this
  NOTIMPLEMENTED();
  return false;
}

}  // namespace net
<|endoftext|>