<commit_before>/****************************************************************************
 **
 ** Copyright (C) 2013 Jolla Ltd.
 ** Contact: Chris Adams <chris.adams@jollamobile.com>
 **
 ****************************************************************************/

#include "twitterhometimelinesyncadaptor.h"
#include "syncservice.h"
#include "trace.h"
#include "constants_p.h"

#include <QtCore/QPair>
#include <QtCore/QJsonValue>
#include <QtCore/QUrlQuery>

TwitterHomeTimelineSyncAdaptor::TwitterHomeTimelineSyncAdaptor(SyncService *syncService, QObject *parent)
    : TwitterDataTypeSyncAdaptor(syncService, SyncService::Posts, parent)
{
    m_db.initDatabase();
    setInitialActive(m_db.isValid());
}

TwitterHomeTimelineSyncAdaptor::~TwitterHomeTimelineSyncAdaptor()
{
}

void TwitterHomeTimelineSyncAdaptor::purgeDataForOldAccounts(const QList<int> &purgeIds)
{
    if (purgeIds.size()) {
        foreach (int accountIdentifier, purgeIds) {
            m_db.removePosts(accountIdentifier);
        }
        m_db.write();
    }
}

void TwitterHomeTimelineSyncAdaptor::beginSync(int accountId, const QString &oauthToken, const QString &oauthTokenSecret)
{
    m_db.removePosts(accountId); // always purge all tweets for the account, prior to syncing most recent.
    requestMe(accountId, oauthToken, oauthTokenSecret);
}

void TwitterHomeTimelineSyncAdaptor::finalize(int accountId)
{
    Q_UNUSED(accountId)
    m_db.write();
}

void TwitterHomeTimelineSyncAdaptor::requestMe(int accountId, const QString &oauthToken, const QString &oauthTokenSecret)
{
    QList<QPair<QString, QString> > queryItems;
    queryItems.append(QPair<QString, QString>(QString(QLatin1String("skip_status")), QString(QLatin1String("true"))));
    QString baseUrl = QLatin1String("https://api.twitter.com/1.1/account/verify_credentials.json");
    QUrl url(baseUrl);
    QUrlQuery query(url);
    query.setQueryItems(queryItems);
    url.setQuery(query);

    QNetworkRequest nreq(url);
    nreq.setRawHeader("Authorization", authorizationHeader(
            accountId, oauthToken, oauthTokenSecret,
            QLatin1String("GET"), baseUrl, queryItems).toLatin1());
    QNetworkReply *reply = networkAccessManager->get(nreq);

    if (reply) {
        reply->setProperty("accountId", accountId);
        reply->setProperty("oauthToken", oauthToken);
        reply->setProperty("oauthTokenSecret", oauthTokenSecret);
        connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(errorHandler(QNetworkReply::NetworkError)));
        connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrorsHandler(QList<QSslError>)));
        connect(reply, SIGNAL(finished()), this, SLOT(finishedMeHandler()));

        // we're requesting data.  Increment the semaphore so that we know we're still busy.
        incrementSemaphore(accountId);
    } else {
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: unable to request user verification from Twitter account with id %1"))
                .arg(accountId));
    }
}

void TwitterHomeTimelineSyncAdaptor::requestPosts(int accountId, const QString &oauthToken,
                                                  const QString &oauthTokenSecret,
                                                  const QString &sinceTweetId, const QString &fromUserId)
{
    QList<QPair<QString, QString> > queryItems;
    queryItems.append(QPair<QString, QString>(QString(QLatin1String("count")), QString(QLatin1String("10")))); // limit to 10 Tweets.
    if (!sinceTweetId.isEmpty()) {
        queryItems.append(QPair<QString, QString>(QString(QLatin1String("since_id")), sinceTweetId));
    }
    if (!fromUserId.isEmpty()) {
        queryItems.append(QPair<QString, QString>(QString(QLatin1String("user_id")), fromUserId));
    }
    QString baseUrl = QLatin1String("https://api.twitter.com/1.1/statuses/home_timeline.json");
    QUrl url(baseUrl);
    QUrlQuery query(url);
    query.setQueryItems(queryItems);
    url.setQuery(query);

    QNetworkRequest nreq(url);
    nreq.setRawHeader("Authorization", authorizationHeader(
            accountId, oauthToken, oauthTokenSecret,
            QLatin1String("GET"), baseUrl, queryItems).toLatin1());
    QNetworkReply *reply = networkAccessManager->get(nreq);

    if (reply) {
        reply->setProperty("accountId", accountId);
        reply->setProperty("oauthToken", oauthToken);
        reply->setProperty("oauthTokenSecret", oauthTokenSecret);
        reply->setProperty("selfUserId", fromUserId);
        connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(errorHandler(QNetworkReply::NetworkError)));
        connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrorsHandler(QList<QSslError>)));
        connect(reply, SIGNAL(finished()), this, SLOT(finishedPostsHandler()));

        // we're requesting data.  Increment the semaphore so that we know we're still busy.
        incrementSemaphore(accountId);
    } else {
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: unable to request user timeline posts from Twitter account with id %1"))
                .arg(accountId));
    }
}

void TwitterHomeTimelineSyncAdaptor::finishedMeHandler()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) {
        // shouldn't happen, but just in case.
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: invalid reply in finished me - unable to decrement semaphore!")));
        return;
    }
    int accountId = reply->property("accountId").toInt();
    QString oauthToken = reply->property("oauthToken").toString();
    QString oauthTokenSecret = reply->property("oauthTokenSecret").toString();
    QByteArray replyData = reply->readAll();
    disconnect(reply);
    reply->deleteLater();

    bool ok = false;
    QJsonObject parsed = parseJsonObjectReplyData(replyData, &ok);
    if (ok && parsed.contains(QLatin1String("id_str"))) {
        QString selfUserId = parsed.value(QLatin1String("id_str")).toString();
        QString selfScreenName = parsed.value(QLatin1String("screen_name")).toString();
        QString profileImage = parsed.value(QLatin1String("profile_image_url")).toString();
        if (!m_selfTuids.contains(selfUserId)) {
            m_selfTuids.append(selfUserId);
            m_selfTScreenNames.insert(selfUserId, selfScreenName);
            m_accountProfileImage.insert(accountId, profileImage);
        }

        requestPosts(accountId, oauthToken, oauthTokenSecret, QString(), QString());
    } else {
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: unable to parse self user id from me request for account %1, got:"))
                .arg(accountId) << replyData);
    }

    decrementSemaphore(accountId);
}

void TwitterHomeTimelineSyncAdaptor::finishedPostsHandler()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) {
        // shouldn't happen, but just in case
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: invalid reply in finished posts - unable to decrement semaphore!")));
        return;
    }

    int accountId = reply->property("accountId").toInt();
    QDateTime lastSync = lastSyncTimestamp(QLatin1String("twitter"),
                                           SyncService::dataType(SyncService::Posts),
                                           accountId);
    QByteArray replyData = reply->readAll();
    disconnect(reply);
    reply->deleteLater();

    bool ok = false;
    QJsonArray tweets = parseJsonArrayReplyData(replyData, &ok);
    if (ok) {
        if (!tweets.size()) {
            TRACE(SOCIALD_DEBUG,
                    QString(QLatin1String("no feed posts received for account %1"))
                    .arg(accountId));
            decrementSemaphore(accountId);
            return;
        }

        foreach (const QJsonValue &tweetValue, tweets) {
            // these are the fields we eventually need to fill out:
            QList<QPair<QString, SocialPostImage::ImageType> > imageList;
            QString retweeter;

            // grab the data from the current post
            QJsonObject tweet = tweetValue.toObject();

            // Just to be sure to get the time of the current (re)tweet
            QDateTime eventTimestamp = parseTwitterDateTime(tweet.value(QLatin1String("created_at")).toString());

            // We should get data for the retweeted tweet instead of
            // getting the (often partial) retweeted tweet.
            if (tweet.contains(QLatin1String("retweeted_status"))) {
                retweeter = tweet.value(QLatin1String("user")).toObject().value("name").toString();
                tweet = tweet.value(QLatin1String("retweeted_status")).toObject();
            }

            QString postId = tweet.value(QLatin1String("id_str")).toString();
            QString body = tweet.value(QLatin1String("text")).toString();
            QJsonObject user = tweet.value(QLatin1String("user")).toObject();
            QString name = user.value("name").toString();
            QString screenName = user.value("screen_name").toString();
            QString icon = user.value(QLatin1String("profile_image_url")).toString();

            // Twitter does some HTML substitutions in their content
            // in JSON feeds, to prevent issues with JSONP formatting.
            body.replace(QStringLiteral("<"), QStringLiteral("<"));
            body.replace(QStringLiteral(">"), QStringLiteral(">"));
            body.replace(QStringLiteral("&"), QStringLiteral("&"));

            QJsonObject entities = tweet.value(QLatin1String("entities")).toObject();
            QJsonArray mediaList = entities.value(QLatin1String("media")).toArray();
            if (!mediaList.isEmpty()) {
                foreach (const QJsonValue &mediaValue, mediaList) {
                    QJsonObject mediaObject = mediaValue.toObject();
                    if (mediaObject.contains(QLatin1String("media_url_https"))) {
                        QString imageUrl = mediaObject.value(QLatin1String("media_url_https")).toString();
                        imageList.append(qMakePair<QString, SocialPostImage::ImageType>(imageUrl, SocialPostImage::Photo));
                    }
                }
            }

            QJsonArray urlList = entities.value(QLatin1String("urls")).toArray();
            foreach (const QJsonValue &urlValue, urlList) {
                // Right now, we use a slightly inefficient algorithm, that is error-proof
                // we just replace the old URL by the new one
                QJsonObject urlObject = urlValue.toObject();
                QString shortUrl = urlObject.value(QLatin1String("url")).toString();
                QString expandedUrl = urlObject.value(QLatin1String("expanded_url")).toString();
                body.replace(shortUrl, expandedUrl);
            }

            // We always purge, so even if we've synced it in the past, we need it.
            // Check to see if we need to post it to the events feed
            //if (lastSync.isValid() && eventTimestamp < lastSync) {
            //    TRACE(SOCIALD_DEBUG,
            //            QString(QLatin1String("event for account %1 came after last sync:"))
            //            .arg(accountId) << "    " << eventTimestamp << ":" << body);
            //    break;                 // all subsequent events will be even older.
            //} else if (eventTimestamp.daysTo(QDateTime::currentDateTime()) > 7) {
            //    TRACE(SOCIALD_DEBUG,
            //            QString(QLatin1String("event for account %1 is more than a week old:\n"))
            //            .arg(accountId) << "    " << eventTimestamp << ":" << body);
            //    break;                 // all subsequent events will be even older.
            //} else {
                m_db.addTwitterPost(postId, name, body, eventTimestamp, icon, imageList,
                                    screenName, retweeter, consumerKey(), consumerSecret(), accountId);
            //}
        }
    } else {
        // error occurred during request.
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: unable to parse event feed data from request with account %1; got: %2"))
                .arg(accountId).arg(QString::fromLatin1(replyData.constData())));
    }

    // we're finished this request.  Decrement our busy semaphore.
    decrementSemaphore(accountId);
}
<commit_msg>[sociald] Purge old tweets only after successful update. Fixes JB#13723<commit_after>/****************************************************************************
 **
 ** Copyright (C) 2013 Jolla Ltd.
 ** Contact: Chris Adams <chris.adams@jollamobile.com>
 **
 ****************************************************************************/

#include "twitterhometimelinesyncadaptor.h"
#include "syncservice.h"
#include "trace.h"
#include "constants_p.h"

#include <QtCore/QPair>
#include <QtCore/QJsonValue>
#include <QtCore/QUrlQuery>

TwitterHomeTimelineSyncAdaptor::TwitterHomeTimelineSyncAdaptor(SyncService *syncService, QObject *parent)
    : TwitterDataTypeSyncAdaptor(syncService, SyncService::Posts, parent)
{
    m_db.initDatabase();
    setInitialActive(m_db.isValid());
}

TwitterHomeTimelineSyncAdaptor::~TwitterHomeTimelineSyncAdaptor()
{
}

void TwitterHomeTimelineSyncAdaptor::purgeDataForOldAccounts(const QList<int> &purgeIds)
{
    if (purgeIds.size()) {
        foreach (int accountIdentifier, purgeIds) {
            m_db.removePosts(accountIdentifier);
        }
        m_db.write();
    }
}

void TwitterHomeTimelineSyncAdaptor::beginSync(int accountId, const QString &oauthToken, const QString &oauthTokenSecret)
{
    requestMe(accountId, oauthToken, oauthTokenSecret);
}

void TwitterHomeTimelineSyncAdaptor::finalize(int accountId)
{
    Q_UNUSED(accountId)
    m_db.write();
}

void TwitterHomeTimelineSyncAdaptor::requestMe(int accountId, const QString &oauthToken, const QString &oauthTokenSecret)
{
    QList<QPair<QString, QString> > queryItems;
    queryItems.append(QPair<QString, QString>(QString(QLatin1String("skip_status")), QString(QLatin1String("true"))));
    QString baseUrl = QLatin1String("https://api.twitter.com/1.1/account/verify_credentials.json");
    QUrl url(baseUrl);
    QUrlQuery query(url);
    query.setQueryItems(queryItems);
    url.setQuery(query);

    QNetworkRequest nreq(url);
    nreq.setRawHeader("Authorization", authorizationHeader(
            accountId, oauthToken, oauthTokenSecret,
            QLatin1String("GET"), baseUrl, queryItems).toLatin1());
    QNetworkReply *reply = networkAccessManager->get(nreq);

    if (reply) {
        reply->setProperty("accountId", accountId);
        reply->setProperty("oauthToken", oauthToken);
        reply->setProperty("oauthTokenSecret", oauthTokenSecret);
        connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(errorHandler(QNetworkReply::NetworkError)));
        connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrorsHandler(QList<QSslError>)));
        connect(reply, SIGNAL(finished()), this, SLOT(finishedMeHandler()));

        // we're requesting data.  Increment the semaphore so that we know we're still busy.
        incrementSemaphore(accountId);
    } else {
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: unable to request user verification from Twitter account with id %1"))
                .arg(accountId));
    }
}

void TwitterHomeTimelineSyncAdaptor::requestPosts(int accountId, const QString &oauthToken,
                                                  const QString &oauthTokenSecret,
                                                  const QString &sinceTweetId, const QString &fromUserId)
{
    QList<QPair<QString, QString> > queryItems;
    queryItems.append(QPair<QString, QString>(QString(QLatin1String("count")), QString(QLatin1String("10")))); // limit to 10 Tweets.
    if (!sinceTweetId.isEmpty()) {
        queryItems.append(QPair<QString, QString>(QString(QLatin1String("since_id")), sinceTweetId));
    }
    if (!fromUserId.isEmpty()) {
        queryItems.append(QPair<QString, QString>(QString(QLatin1String("user_id")), fromUserId));
    }
    QString baseUrl = QLatin1String("https://api.twitter.com/1.1/statuses/home_timeline.json");
    QUrl url(baseUrl);
    QUrlQuery query(url);
    query.setQueryItems(queryItems);
    url.setQuery(query);

    QNetworkRequest nreq(url);
    nreq.setRawHeader("Authorization", authorizationHeader(
            accountId, oauthToken, oauthTokenSecret,
            QLatin1String("GET"), baseUrl, queryItems).toLatin1());
    QNetworkReply *reply = networkAccessManager->get(nreq);

    if (reply) {
        reply->setProperty("accountId", accountId);
        reply->setProperty("oauthToken", oauthToken);
        reply->setProperty("oauthTokenSecret", oauthTokenSecret);
        reply->setProperty("selfUserId", fromUserId);
        connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(errorHandler(QNetworkReply::NetworkError)));
        connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrorsHandler(QList<QSslError>)));
        connect(reply, SIGNAL(finished()), this, SLOT(finishedPostsHandler()));

        // we're requesting data.  Increment the semaphore so that we know we're still busy.
        incrementSemaphore(accountId);
    } else {
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: unable to request user timeline posts from Twitter account with id %1"))
                .arg(accountId));
    }
}

void TwitterHomeTimelineSyncAdaptor::finishedMeHandler()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) {
        // shouldn't happen, but just in case.
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: invalid reply in finished me - unable to decrement semaphore!")));
        return;
    }
    int accountId = reply->property("accountId").toInt();
    QString oauthToken = reply->property("oauthToken").toString();
    QString oauthTokenSecret = reply->property("oauthTokenSecret").toString();
    QByteArray replyData = reply->readAll();
    disconnect(reply);
    reply->deleteLater();

    bool ok = false;
    QJsonObject parsed = parseJsonObjectReplyData(replyData, &ok);
    if (ok && parsed.contains(QLatin1String("id_str"))) {
        QString selfUserId = parsed.value(QLatin1String("id_str")).toString();
        QString selfScreenName = parsed.value(QLatin1String("screen_name")).toString();
        QString profileImage = parsed.value(QLatin1String("profile_image_url")).toString();
        if (!m_selfTuids.contains(selfUserId)) {
            m_selfTuids.append(selfUserId);
            m_selfTScreenNames.insert(selfUserId, selfScreenName);
            m_accountProfileImage.insert(accountId, profileImage);
        }

        requestPosts(accountId, oauthToken, oauthTokenSecret, QString(), QString());
    } else {
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: unable to parse self user id from me request for account %1, got:"))
                .arg(accountId) << replyData);
    }

    decrementSemaphore(accountId);
}

void TwitterHomeTimelineSyncAdaptor::finishedPostsHandler()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) {
        // shouldn't happen, but just in case
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: invalid reply in finished posts - unable to decrement semaphore!")));
        return;
    }

    int accountId = reply->property("accountId").toInt();
    QDateTime lastSync = lastSyncTimestamp(QLatin1String("twitter"),
                                           SyncService::dataType(SyncService::Posts),
                                           accountId);
    QByteArray replyData = reply->readAll();
    disconnect(reply);
    reply->deleteLater();

    bool ok = false;
    QJsonArray tweets = parseJsonArrayReplyData(replyData, &ok);
    if (ok) {
        if (!tweets.size()) {
            TRACE(SOCIALD_DEBUG,
                    QString(QLatin1String("no feed posts received for account %1"))
                    .arg(accountId));
            decrementSemaphore(accountId);
            return;
        }

        m_db.removePosts(accountId); // purge old tweets.

        foreach (const QJsonValue &tweetValue, tweets) {
            // these are the fields we eventually need to fill out:
            QList<QPair<QString, SocialPostImage::ImageType> > imageList;
            QString retweeter;

            // grab the data from the current post
            QJsonObject tweet = tweetValue.toObject();

            // Just to be sure to get the time of the current (re)tweet
            QDateTime eventTimestamp = parseTwitterDateTime(tweet.value(QLatin1String("created_at")).toString());

            // We should get data for the retweeted tweet instead of
            // getting the (often partial) retweeted tweet.
            if (tweet.contains(QLatin1String("retweeted_status"))) {
                retweeter = tweet.value(QLatin1String("user")).toObject().value("name").toString();
                tweet = tweet.value(QLatin1String("retweeted_status")).toObject();
            }

            QString postId = tweet.value(QLatin1String("id_str")).toString();
            QString body = tweet.value(QLatin1String("text")).toString();
            QJsonObject user = tweet.value(QLatin1String("user")).toObject();
            QString name = user.value("name").toString();
            QString screenName = user.value("screen_name").toString();
            QString icon = user.value(QLatin1String("profile_image_url")).toString();

            // Twitter does some HTML substitutions in their content
            // in JSON feeds, to prevent issues with JSONP formatting.
            body.replace(QStringLiteral("<"), QStringLiteral("<"));
            body.replace(QStringLiteral(">"), QStringLiteral(">"));
            body.replace(QStringLiteral("&"), QStringLiteral("&"));

            QJsonObject entities = tweet.value(QLatin1String("entities")).toObject();
            QJsonArray mediaList = entities.value(QLatin1String("media")).toArray();
            if (!mediaList.isEmpty()) {
                foreach (const QJsonValue &mediaValue, mediaList) {
                    QJsonObject mediaObject = mediaValue.toObject();
                    if (mediaObject.contains(QLatin1String("media_url_https"))) {
                        QString imageUrl = mediaObject.value(QLatin1String("media_url_https")).toString();
                        imageList.append(qMakePair<QString, SocialPostImage::ImageType>(imageUrl, SocialPostImage::Photo));
                    }
                }
            }

            QJsonArray urlList = entities.value(QLatin1String("urls")).toArray();
            foreach (const QJsonValue &urlValue, urlList) {
                // Right now, we use a slightly inefficient algorithm, that is error-proof
                // we just replace the old URL by the new one
                QJsonObject urlObject = urlValue.toObject();
                QString shortUrl = urlObject.value(QLatin1String("url")).toString();
                QString expandedUrl = urlObject.value(QLatin1String("expanded_url")).toString();
                body.replace(shortUrl, expandedUrl);
            }

            // We always purge, so even if we've synced it in the past, we need it.
            // Check to see if we need to post it to the events feed
            //if (lastSync.isValid() && eventTimestamp < lastSync) {
            //    TRACE(SOCIALD_DEBUG,
            //            QString(QLatin1String("event for account %1 came after last sync:"))
            //            .arg(accountId) << "    " << eventTimestamp << ":" << body);
            //    break;                 // all subsequent events will be even older.
            //} else if (eventTimestamp.daysTo(QDateTime::currentDateTime()) > 7) {
            //    TRACE(SOCIALD_DEBUG,
            //            QString(QLatin1String("event for account %1 is more than a week old:\n"))
            //            .arg(accountId) << "    " << eventTimestamp << ":" << body);
            //    break;                 // all subsequent events will be even older.
            //} else {
                m_db.addTwitterPost(postId, name, body, eventTimestamp, icon, imageList,
                                    screenName, retweeter, consumerKey(), consumerSecret(), accountId);
            //}
        }
    } else {
        // error occurred during request.
        TRACE(SOCIALD_ERROR,
                QString(QLatin1String("error: unable to parse event feed data from request with account %1; got: %2"))
                .arg(accountId).arg(QString::fromLatin1(replyData.constData())));
    }

    // we're finished this request.  Decrement our busy semaphore.
    decrementSemaphore(accountId);
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

#if !defined(CODEWARRIORDEFS_HPP)
#define CODEWARRIORDEFS_HPP

// ---------------------------------------------------------------------------
//  Include some runtime files that will be needed product wide
// ---------------------------------------------------------------------------
//#include <sys/types.h>  	// for size_t and ssize_t
//#include <limits.h>		// for MAX of size_t and ssize_t
//#include <extras.h>

#if defined(_WIN32) || defined(WIN32)
#include <wchar.h>
#include <wctype.h>
#endif

// ---------------------------------------------------------------------------
//  A define in the build for each project is also used to control whether
//  the export keyword is from the project's viewpoint or the client's.
//  These defines provide the platform specific keywords that they need
//  to do this.
// ---------------------------------------------------------------------------
#if defined(macintosh)
#define PLATFORM_EXPORT		__declspec(export)
#define PLATFORM_IMPORT		__declspec(import)
#elif defined(_WIN32) || defined(WIN32)
#define PLATFORM_EXPORT     __declspec(dllexport)
#define PLATFORM_IMPORT     __declspec(dllimport)
#endif

// ---------------------------------------------------------------------------
//  Indicate that we do not support native bools
//  If the compiler can handle boolean itself, do not define it
// ---------------------------------------------------------------------------
// #define NO_NATIVE_BOOL

// ---------------------------------------------------------------------------
//  Each compiler might support L"" prefixed constants. There are places
//  where it is advantageous to use the L"" where it supported, to avoid
//  unnecessary transcoding.
//  If your compiler does not support it, don't define this.
// ---------------------------------------------------------------------------
// #define XML_LSTRSUPPORT

// ---------------------------------------------------------------------------
//  Indicate that we support C++ namespace
//  Do not define it if the compile cannot handle C++ namespace
// ---------------------------------------------------------------------------
// #define XERCES_HAS_CPP_NAMESPACE

// ---------------------------------------------------------------------------
//  Define our version of the XML character
// ---------------------------------------------------------------------------
#if defined(macintosh)
typedef unsigned short  XMLCh;
#elif defined(_WIN32) || defined(WIN32)
typedef wchar_t			XMLCh;
#endif

// ---------------------------------------------------------------------------
//  Define unsigned 16 and 32 bits integers
// ---------------------------------------------------------------------------
typedef unsigned short  XMLUInt16;
typedef unsigned int    XMLUInt32;

// ---------------------------------------------------------------------------
//  Define signed 32 bits integers
// ---------------------------------------------------------------------------
typedef int             XMLInt32;

// ---------------------------------------------------------------------------
//  XMLSize_t is the unsigned integral type.
// ---------------------------------------------------------------------------
#if defined(_SIZE_T) && defined(SIZE_MAX) && defined(_SSIZE_T) && defined(SSIZE_MAX)
    typedef size_t              XMLSize_t;
    #define XML_SIZE_MAX        SIZE_MAX
    typedef ssize_t             XMLSSize_t;
    #define XML_SSIZE_MAX       SSIZE_MAX
#else
    typedef unsigned long       XMLSize_t;
    #define XML_SIZE_MAX        ULONG_MAX
    typedef long                XMLSSize_t;
    #define XML_SSIZE_MAX       LONG_MAX
#endif

// ---------------------------------------------------------------------------
//  Force on the Xerces debug token if it was on in the build environment
// ---------------------------------------------------------------------------
#ifdef _DEBUG
#define XERCES_DEBUG
#endif

// ---------------------------------------------------------------------------
//  Provide some common string ops that are different/notavail for CodeWarrior.
//	(these routines are defined in CW 8 by extras.h, but there is no MachO
//	library for extras).
// ---------------------------------------------------------------------------
#if __MACH__
int stricmp(const char* const str1, const char* const  str2);
int strnicmp(const char* const str1, const char* const  str2, const unsigned int count);
#endif

#if defined(_WIN32) || defined(WIN32)
/* used in place of calling mbstowcs or wcstombs with a NULL destination */
int mbswcslen(const char * s, const unsigned int n);
int wcsmbslen(const wchar_t * pwcs, const unsigned int n);
#endif

// ---------------------------------------------------------------------------
//  The name of the DLL that is built by the Codewarrior version of the
//  system. We append a previously defined token which holds the DLL
//  versioning string. This is defined in XercesDefs.hpp which is what this
//  file is included into.
// ---------------------------------------------------------------------------
const char* const Xerces_DLLName = "xerces-c" Xerces_DLLVersionStr;

#endif //CODEWARRIORDEFS_HPP
<commit_msg>Restore support for CodeWarrior MachO framework build<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

#if !defined(CODEWARRIORDEFS_HPP)
#define CODEWARRIORDEFS_HPP

// ---------------------------------------------------------------------------
//  Include some runtime files that will be needed product wide
// ---------------------------------------------------------------------------
//#include <sys/types.h>  	// for size_t and ssize_t
//#include <limits.h>		// for MAX of size_t and ssize_t
//#include <extras.h>

#if defined(_WIN32) || defined(WIN32)
#include <wchar.h>
#include <wctype.h>
#endif

// ---------------------------------------------------------------------------
//  A define in the build for each project is also used to control whether
//  the export keyword is from the project's viewpoint or the client's.
//  These defines provide the platform specific keywords that they need
//  to do this.
// ---------------------------------------------------------------------------
#if defined(XML_MACOS)
#define PLATFORM_EXPORT		__declspec(export)
#define PLATFORM_IMPORT		__declspec(import)
#elif defined(_WIN32) || defined(WIN32)
#define PLATFORM_EXPORT     __declspec(dllexport)
#define PLATFORM_IMPORT     __declspec(dllimport)
#endif

// ---------------------------------------------------------------------------
//  Indicate that we do not support native bools
//  If the compiler can handle boolean itself, do not define it
// ---------------------------------------------------------------------------
// #define NO_NATIVE_BOOL

// ---------------------------------------------------------------------------
//  Each compiler might support L"" prefixed constants. There are places
//  where it is advantageous to use the L"" where it supported, to avoid
//  unnecessary transcoding.
//  If your compiler does not support it, don't define this.
// ---------------------------------------------------------------------------
// #define XML_LSTRSUPPORT

// ---------------------------------------------------------------------------
//  Indicate that we support C++ namespace
//  Do not define it if the compile cannot handle C++ namespace
// ---------------------------------------------------------------------------
// #define XERCES_HAS_CPP_NAMESPACE

// ---------------------------------------------------------------------------
//  Define our version of the XML character
// ---------------------------------------------------------------------------
#if defined(XML_MACOS)
typedef unsigned short  XMLCh;
#elif defined(_WIN32) || defined(WIN32)
typedef wchar_t			XMLCh;
#endif

// ---------------------------------------------------------------------------
//  Define unsigned 16 and 32 bits integers
// ---------------------------------------------------------------------------
typedef unsigned short  XMLUInt16;
typedef unsigned int    XMLUInt32;

// ---------------------------------------------------------------------------
//  Define signed 32 bits integers
// ---------------------------------------------------------------------------
typedef int             XMLInt32;

// ---------------------------------------------------------------------------
//  XMLSize_t is the unsigned integral type.
// ---------------------------------------------------------------------------
#if defined(_SIZE_T) && defined(SIZE_MAX) && defined(_SSIZE_T) && defined(SSIZE_MAX)
    typedef size_t              XMLSize_t;
    #define XML_SIZE_MAX        SIZE_MAX
    typedef ssize_t             XMLSSize_t;
    #define XML_SSIZE_MAX       SSIZE_MAX
#else
    typedef unsigned long       XMLSize_t;
    #define XML_SIZE_MAX        ULONG_MAX
    typedef long                XMLSSize_t;
    #define XML_SSIZE_MAX       LONG_MAX
#endif

// ---------------------------------------------------------------------------
//  Force on the Xerces debug token if it was on in the build environment
// ---------------------------------------------------------------------------
#ifdef _DEBUG
#define XERCES_DEBUG
#endif

// ---------------------------------------------------------------------------
//  Provide some common string ops that are different/notavail for CodeWarrior.
//	(these routines are defined in CW 8 by extras.h, but there is no MachO
//	library for extras).
// ---------------------------------------------------------------------------
#if __MACH__
int stricmp(const char* const str1, const char* const  str2);
int strnicmp(const char* const str1, const char* const  str2, const unsigned int count);
#endif

#if defined(_WIN32) || defined(WIN32)
/* used in place of calling mbstowcs or wcstombs with a NULL destination */
int mbswcslen(const char * s, const unsigned int n);
int wcsmbslen(const wchar_t * pwcs, const unsigned int n);
#endif

// ---------------------------------------------------------------------------
//  The name of the DLL that is built by the Codewarrior version of the
//  system. We append a previously defined token which holds the DLL
//  versioning string. This is defined in XercesDefs.hpp which is what this
//  file is included into.
// ---------------------------------------------------------------------------
const char* const Xerces_DLLName = "xerces-c" Xerces_DLLVersionStr;

#endif //CODEWARRIORDEFS_HPP
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/**
  * $Id$
  */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/schema/XSDDOMParser.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/internal/XMLScanner.hpp>

// ---------------------------------------------------------------------------
//  XSDDOMParser: Constructors and Destructor
// ---------------------------------------------------------------------------
XSDDOMParser::XSDDOMParser(XMLValidator* const valToAdopt) :
    XercesDOMParser(valToAdopt)
    , fSawFatal(false)
    , fUserErrorReporter(0)
{

}

XSDDOMParser::~XSDDOMParser()
{
}

// ---------------------------------------------------------------------------
//  XSDDOMParser: Helper methods
// ---------------------------------------------------------------------------
DOMElement* XSDDOMParser::createElementNSNode(const XMLCh *namespaceURI,
                                              const XMLCh *qualifiedName)
{
    ReaderMgr::LastExtEntityInfo lastInfo;
    ((ReaderMgr*) getScanner()->getLocator())->getLastExtEntityInfo(lastInfo);

    return getDocument()->createElementNS(namespaceURI, qualifiedName,
                                          lastInfo.lineNumber, lastInfo.colNumber);
}

// ---------------------------------------------------------------------------
//  XSDDOMParser: Setter methods
// ---------------------------------------------------------------------------
void XSDDOMParser::setUserErrorReporter(XMLErrorReporter* const errorReporter)
{
    fUserErrorReporter = errorReporter;
    getScanner()->setErrorReporter(this);
}

void XSDDOMParser::setUserEntityHandler(XMLEntityHandler* const entityHandler)
{
    fUserEntityHandler = entityHandler;
    getScanner()->setEntityHandler(this);
}

// ---------------------------------------------------------------------------
//  XSDDOMParser: Implementation of the XMLErrorReporter interface
// ---------------------------------------------------------------------------
void XSDDOMParser::error(const   unsigned int                code
                         , const XMLCh* const                msgDomain
                         , const XMLErrorReporter::ErrTypes  errType
                         , const XMLCh* const                errorText
                         , const XMLCh* const                systemId
                         , const XMLCh* const                publicId
                         , const XMLSSize_t                  lineNum
                         , const XMLSSize_t                  colNum)
{
    if (errType >= XMLErrorReporter::ErrType_Fatal)
        fSawFatal = true;

    if (fUserErrorReporter)
        fUserErrorReporter->error(code, msgDomain, errType, errorText,
                                  systemId, publicId, lineNum, colNum);
}

InputSource* XSDDOMParser::resolveEntity(const XMLCh* const publicId,
                                         const XMLCh* const systemId,
                                         const XMLCh* const baseURI)
{
    if (fUserEntityHandler)
        return fUserEntityHandler->resolveEntity(publicId, systemId, baseURI);

    return 0;
}<commit_msg>[Bug 128484] newline warning whist building.  By Gareth Reakes.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/**
  * $Id$
  */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/schema/XSDDOMParser.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/internal/XMLScanner.hpp>

// ---------------------------------------------------------------------------
//  XSDDOMParser: Constructors and Destructor
// ---------------------------------------------------------------------------
XSDDOMParser::XSDDOMParser(XMLValidator* const valToAdopt) :
    XercesDOMParser(valToAdopt)
    , fSawFatal(false)
    , fUserErrorReporter(0)
{

}

XSDDOMParser::~XSDDOMParser()
{
}

// ---------------------------------------------------------------------------
//  XSDDOMParser: Helper methods
// ---------------------------------------------------------------------------
DOMElement* XSDDOMParser::createElementNSNode(const XMLCh *namespaceURI,
                                              const XMLCh *qualifiedName)
{
    ReaderMgr::LastExtEntityInfo lastInfo;
    ((ReaderMgr*) getScanner()->getLocator())->getLastExtEntityInfo(lastInfo);

    return getDocument()->createElementNS(namespaceURI, qualifiedName,
                                          lastInfo.lineNumber, lastInfo.colNumber);
}

// ---------------------------------------------------------------------------
//  XSDDOMParser: Setter methods
// ---------------------------------------------------------------------------
void XSDDOMParser::setUserErrorReporter(XMLErrorReporter* const errorReporter)
{
    fUserErrorReporter = errorReporter;
    getScanner()->setErrorReporter(this);
}

void XSDDOMParser::setUserEntityHandler(XMLEntityHandler* const entityHandler)
{
    fUserEntityHandler = entityHandler;
    getScanner()->setEntityHandler(this);
}

// ---------------------------------------------------------------------------
//  XSDDOMParser: Implementation of the XMLErrorReporter interface
// ---------------------------------------------------------------------------
void XSDDOMParser::error(const   unsigned int                code
                         , const XMLCh* const                msgDomain
                         , const XMLErrorReporter::ErrTypes  errType
                         , const XMLCh* const                errorText
                         , const XMLCh* const                systemId
                         , const XMLCh* const                publicId
                         , const XMLSSize_t                  lineNum
                         , const XMLSSize_t                  colNum)
{
    if (errType >= XMLErrorReporter::ErrType_Fatal)
        fSawFatal = true;

    if (fUserErrorReporter)
        fUserErrorReporter->error(code, msgDomain, errType, errorText,
                                  systemId, publicId, lineNum, colNum);
}

InputSource* XSDDOMParser::resolveEntity(const XMLCh* const publicId,
                                         const XMLCh* const systemId,
                                         const XMLCh* const baseURI)
{
    if (fUserEntityHandler)
        return fUserEntityHandler->resolveEntity(publicId, systemId, baseURI);

    return 0;
}

<|endoftext|>


<commit_before>#pragma once
//=============================================================================//
/*! @file
    @brief  mpfr クラス @n
			GNU gmp, mpfr の C++ ラッパー
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=============================================================================//
#include <cmath>
#include <mpfr.h>

namespace mpfr {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  mpfr オブジェクト
		@param[in]	num		有効桁数
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t num>
	class value {

		mpfr_t		t_;
		mpfr_rnd_t	rnd_;

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		value(mpfr_rnd_t rnd = MPFR_RNDN) noexcept : t_(), rnd_(rnd) {
			mpfr_init2(t_, num);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		value(const value& t, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd)
		{
			mpfr_init2(t_, num);
			mpfr_set(t_, t.t_, rnd_);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター(int)
			@param[in]	iv	初期値
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		explicit value(int iv, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd) {
			mpfr_init2(t_, num);
			mpfr_set_si(t_, iv, rnd);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター(float)
			@param[in]	iv	初期値
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		explicit value(float iv, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd) {
			mpfr_init2(t_, num);
			mpfr_set_flt(t_, iv, rnd);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター(double)
			@param[in]	iv	初期値
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		explicit value(double iv, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd) {
			mpfr_init2(t_, num);
			mpfr_set_d(t_, iv, rnd);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター(文字列)
			@param[in]	iv	初期値
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		explicit value(const char* iv, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd) {
			mpfr_init2(t_, num);
			mpfr_set_str(t_, iv, 10, rnd);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  デストラクター
		*/
		//-----------------------------------------------------------------//
		~value() { mpfr_clear(t_); }

		//-----------------------------------------------------------------//
		/*!
			@brief  mpfr_ptr を取得
			@return mpfr_ptr
		*/
		//-----------------------------------------------------------------//
		mpfr_ptr get() noexcept { return t_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  mpfr_rnd_t を取得
			@return mpfr_rnd_t
		*/
		//-----------------------------------------------------------------//
		auto get_rnd() const noexcept { return rnd_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  円周率を取得
			@return 円周率
		*/
		//-----------------------------------------------------------------//
		static const auto get_pi() {
			value tmp;
			mpfr_const_pi(tmp.t_, tmp.get_rnd());
			return tmp;
		}

		void assign(const char* str) noexcept
		{
			mpfr_set_str(t_, str, 10, rnd_);
		}

		void pow(const value& n) noexcept
		{
			mpfr_pow(t_, t_, n.t_, rnd_);
		}

		bool operator == (int v) const noexcept
		{
			return mpfr_cmp_si(t_, v) == 0;
		}
		bool operator == (long v) const noexcept
		{
			return mpfr_cmp_si(t_, v) == 0;
		}
		bool operator == (double v) const noexcept
		{
			return mpfr_cmp_d(t_, v) == 0;
		}

		value& operator = (const value& th) noexcept {
			mpfr_set(t_, th.t_, rnd_);
			return *this;
		}
		value& operator = (long v) noexcept {
			mpfr_set_si(t_, v, rnd_);
			return *this;
		}
		value& operator = (double v) noexcept {
			mpfr_set_d(t_, v, rnd_);
			return *this;
		}

		const value operator - () noexcept
		{
			value tmp(*this);
			mpfr_neg(tmp.t_, tmp.t_, rnd_);
			return tmp;
		}

		value& operator += (const value& th) noexcept
		{
			mpfr_add(t_, t_, th.t_, rnd_);
			return *this;
		}

		value& operator -= (const value& th) noexcept
		{
			mpfr_sub(t_, t_, th.t_, rnd_);
			return *this;
		}

		value& operator *= (const value& th) noexcept
		{
			mpfr_mul(t_, t_, th.t_, rnd_);
			return *this;
		}

		value& operator /= (const value& th) noexcept
		{
			mpfr_div(t_, t_, th.t_, rnd_);
			return *this;
		}

		value operator + (const value& th) const noexcept { return value(*this) += th; }
		value operator - (const value& th) const noexcept { return value(*this) -= th; }
		value operator * (const value& th) const noexcept { return value(*this) *= th; }
		value operator / (const value& th) const noexcept { return value(*this) /= th; }

		void operator() (int upn, char* out, uint32_t len) noexcept
		{
			char form[16];
			utils::sformat("%%.%dRNf", form, sizeof(form)) % upn;
			mpfr_snprintf(out, len, form, t_);
//			mpfr_snprintf(out, len, "%.50RNf", t_);
//			mpfr_snprintf(out, len, "%10.5RNE", t_);
		}

		static value sin(const value& in)
		{
			value out;
			mpfr_sin(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value asin(const value& in)
		{
			value out;
			mpfr_asin(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value cos(const value& in)
		{
			value out;
			mpfr_cos(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value acos(const value& in)
		{
			value out;
			mpfr_acos(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value tan(const value& in)
		{
			value out;
			mpfr_tan(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value atan(const value& in)
		{
			value out;
			mpfr_atan(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value log10(const value& in)
		{
			value out;
			mpfr_log10(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value log(const value& in)
		{
			value out;
			mpfr_log(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value sqrt(const value& in)
		{
			value out;
			mpfr_sqrt(out.t_, in.t_, out.get_rnd());
			return out;
		}
	};
}
<commit_msg>Update: add func, func manage<commit_after>#pragma once
//=============================================================================//
/*! @file
    @brief  mpfr ラッパークラス @n
			GNU gmp, mpfr の C++ ラッパー
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=============================================================================//
#include <cmath>
#include <mpfr.h>

namespace mpfr {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  mpfr オブジェクト
		@param[in]	num		有効桁数
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t num>
	class value {

		mpfr_t		t_;
		mpfr_rnd_t	rnd_;

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		value(mpfr_rnd_t rnd = MPFR_RNDN) noexcept : t_(), rnd_(rnd) {
			mpfr_init2(t_, num);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		value(const value& t, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd)
		{
			mpfr_init2(t_, num);
			mpfr_set(t_, t.t_, rnd_);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター(int)
			@param[in]	iv	初期値
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		explicit value(int iv, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd) {
			mpfr_init2(t_, num);
			mpfr_set_si(t_, iv, rnd);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター(float)
			@param[in]	iv	初期値
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		explicit value(float iv, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd) {
			mpfr_init2(t_, num);
			mpfr_set_flt(t_, iv, rnd);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター(double)
			@param[in]	iv	初期値
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		explicit value(double iv, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd) {
			mpfr_init2(t_, num);
			mpfr_set_d(t_, iv, rnd);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター(文字列)
			@param[in]	iv	初期値
			@param[in]	rnd	丸めパラメータ
		*/
		//-----------------------------------------------------------------//
		explicit value(const char* iv, mpfr_rnd_t rnd = MPFR_RNDN) noexcept : rnd_(rnd) {
			mpfr_init2(t_, num);
			mpfr_set_str(t_, iv, 10, rnd);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  デストラクター
		*/
		//-----------------------------------------------------------------//
		~value() { mpfr_clear(t_); }

		//-----------------------------------------------------------------//
		/*!
			@brief  mpfr_ptr を取得
			@return mpfr_ptr
		*/
		//-----------------------------------------------------------------//
		mpfr_ptr get() noexcept { return t_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  mpfr_rnd_t を取得
			@return mpfr_rnd_t
		*/
		//-----------------------------------------------------------------//
		auto get_rnd() const noexcept { return rnd_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  円周率を取得
			@return 円周率
		*/
		//-----------------------------------------------------------------//
		static const auto get_pi() {
			value tmp;
			mpfr_const_pi(tmp.t_, tmp.get_rnd());
			return tmp;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ２の自然対数を取得
			@return ２の自然対数
		*/
		//-----------------------------------------------------------------//
		static const auto get_log2() {
			value tmp;
			mpfr_const_log2(tmp.t_, tmp.get_rnd());
			return tmp;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  Euler数を取得
			@return Euler数
		*/
		//-----------------------------------------------------------------//
		static const auto get_euler() {
			value tmp;
			mpfr_const_euler(tmp.t_, tmp.get_rnd());
			return tmp;
		}

		void assign(const char* str) noexcept
		{
			mpfr_set_str(t_, str, 10, rnd_);
		}

		// べき乗
		void pow(const value& n) noexcept
		{
			mpfr_pow(t_, t_, n.t_, rnd_);
		}

		bool operator == (int v) const noexcept { return mpfr_cmp_si(t_, v) == 0; }
		bool operator != (int v) const noexcept { return mpfr_cmp_si(t_, v) != 0; }
		bool operator == (long v) const noexcept { return mpfr_cmp_si(t_, v) == 0; }
		bool operator != (long v) const noexcept { return mpfr_cmp_si(t_, v) != 0; }
		bool operator == (double v) const noexcept { return mpfr_cmp_d(t_, v) == 0; }
		bool operator != (double v) const noexcept { return mpfr_cmp_d(t_, v) != 0; }

		value& operator = (const value& th) noexcept {
			mpfr_set(t_, th.t_, rnd_);
			return *this;
		}
		value& operator = (long v) noexcept {
			mpfr_set_si(t_, v, rnd_);
			return *this;
		}
		value& operator = (double v) noexcept {
			mpfr_set_d(t_, v, rnd_);
			return *this;
		}

		const value operator - () noexcept
		{
			value tmp(*this);
			mpfr_neg(tmp.t_, tmp.t_, rnd_);
			return tmp;
		}

		value& operator += (const value& th) noexcept
		{
			mpfr_add(t_, t_, th.t_, rnd_);
			return *this;
		}

		value& operator -= (const value& th) noexcept
		{
			mpfr_sub(t_, t_, th.t_, rnd_);
			return *this;
		}

		value& operator *= (const value& th) noexcept
		{
			mpfr_mul(t_, t_, th.t_, rnd_);
			return *this;
		}

		value& operator /= (const value& th) noexcept
		{
			mpfr_div(t_, t_, th.t_, rnd_);
			return *this;
		}

		value operator + (const value& th) const noexcept { return value(*this) += th; }
		value operator - (const value& th) const noexcept { return value(*this) -= th; }
		value operator * (const value& th) const noexcept { return value(*this) *= th; }
		value operator / (const value& th) const noexcept { return value(*this) /= th; }

		//-----------------------------------------------------------------//
		/*!
			@brief  数値文字列を取得
			@param[in]	upn		小数点以下の文字数
			@param[out]	out		格納文字列ポインター
			@param[in]	len		格納文字列最大数
		*/
		//-----------------------------------------------------------------//
		void operator() (int upn, char* out, uint32_t len) noexcept
		{
			char form[16];
			utils::sformat("%%.%dRNf", form, sizeof(form)) % upn;
			mpfr_snprintf(out, len, form, t_);
//			mpfr_snprintf(out, len, "%.50RNf", t_);
//			mpfr_snprintf(out, len, "%10.5RNE", t_);
		}

		static value sin(const value& in)
		{
			value out;
			mpfr_sin(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value asin(const value& in)
		{
			value out;
			mpfr_asin(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value cos(const value& in)
		{
			value out;
			mpfr_cos(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value acos(const value& in)
		{
			value out;
			mpfr_acos(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value tan(const value& in)
		{
			value out;
			mpfr_tan(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value atan(const value& in)
		{
			value out;
			mpfr_atan(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value log10(const value& in)
		{
			value out;
			mpfr_log10(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value log(const value& in)
		{
			value out;
			mpfr_log(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value sqrt(const value& in)
		{
			value out;
			mpfr_sqrt(out.t_, in.t_, out.get_rnd());
			return out;
		}

		static value exp10(const value& in)
		{
			value out;
			mpfr_exp10(out.t_, in.t_, out.get_rnd());
			return out;
		}
	};
}
<|endoftext|>


<commit_before>// Ignore unused parameter warnings coming from cppunit headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/libmesh.h>
#include <libmesh/elem.h>

#include "test_comm.h"

using namespace libMesh;

class ContainsPointTest : public CppUnit::TestCase
{
  /**
   * The goal of this test is to verify proper operation of the contains_point
   * method that is used extensively in the point locator. This test focusses on
   * the specializes contains_point implementaion in TRI3.
   */
public:
  CPPUNIT_TEST_SUITE( ContainsPointTest );

  CPPUNIT_TEST( testContainsPointTri3 );

  CPPUNIT_TEST( testContainsPointTet4 );

  CPPUNIT_TEST_SUITE_END();

public:
  void setUp() {}

  void tearDown() {}

  // TRI3 test
  void testContainsPointTri3() {
    // tri corner nodes
    Node a(3,1,2, 0);
    Node b(1,2,3, 1);
    Node c(2,3,1, 2);

    // helper vectors to span the tri and point out of plane
    Point va(a-c);
    Point vb(b-c);
    Point oop(va.cross(vb));

    UniquePtr<Elem> elem = Elem::build(TRI3);

    elem->set_node(0) = &a;
    elem->set_node(1) = &b;
    elem->set_node(2) = &c;

    // midpoint
    Point mid = (a + b + c) / 3;
    CPPUNIT_ASSERT (elem->contains_point(mid));

    // out of plane from the mid point
    CPPUNIT_ASSERT (!elem->contains_point(mid + oop/10));

    // check all corners
    CPPUNIT_ASSERT (elem->contains_point(a));
    CPPUNIT_ASSERT (elem->contains_point(b));
    CPPUNIT_ASSERT (elem->contains_point(c));

    // check outside
    CPPUNIT_ASSERT (!elem->contains_point(a + va * TOLERANCE * 10));
    CPPUNIT_ASSERT (!elem->contains_point(b + vb * TOLERANCE * 10));
    CPPUNIT_ASSERT (!elem->contains_point(c - (va + vb) * TOLERANCE * 10));
  }

  // TET4 test
  void testContainsPointTet4()
  {
    // Construct unit Tet.
    {
      Node zero  (0., 0., 0., 0);
      Node one   (1., 0., 0., 1);
      Node two   (0., 1., 0., 2);
      Node three (0., 0., 1., 3);

      UniquePtr<Elem> elem = Elem::build(TET4);
      elem->set_node(0) = &zero;
      elem->set_node(1) = &one;
      elem->set_node(2) = &two;
      elem->set_node(3) = &three;

      // The centroid must be inside the element.
      CPPUNIT_ASSERT (elem->contains_point(elem->centroid()));

      // The vertices must be contained in the element.
      CPPUNIT_ASSERT (elem->contains_point(zero));
      CPPUNIT_ASSERT (elem->contains_point(one));
      CPPUNIT_ASSERT (elem->contains_point(two));
      CPPUNIT_ASSERT (elem->contains_point(three));

      // Make sure that outside points are not contained.
      CPPUNIT_ASSERT (!elem->contains_point(Point(.34, .34, .34)));
      CPPUNIT_ASSERT (!elem->contains_point(Point(.33, .33, -.1)));
      CPPUNIT_ASSERT (!elem->contains_point(Point(0., -.1, .5)));
    }

    // Construct a nearly degenerate (sliver) tet.  A unit tet with
    // nodes "one" and "two" moved to within a distance of epsilon
    // from the origin.
    {
      Real epsilon = 1.e-4;

      Node zero  (0., 0., 0., 0);
      Node one   (epsilon, 0., 0., 1);
      Node two   (0., epsilon, 0., 2);
      Node three (0., 0., 1., 3);

      UniquePtr<Elem> elem = Elem::build(TET4);
      elem->set_node(0) = &zero;
      elem->set_node(1) = &one;
      elem->set_node(2) = &two;
      elem->set_node(3) = &three;

      // The centroid must be inside the element.
      CPPUNIT_ASSERT (elem->contains_point(elem->centroid()));

      // The vertices must be contained in the element.
      CPPUNIT_ASSERT (elem->contains_point(zero));
      CPPUNIT_ASSERT (elem->contains_point(one));
      CPPUNIT_ASSERT (elem->contains_point(two));
      CPPUNIT_ASSERT (elem->contains_point(three));

      // Verify that a point which is on a mid-edge is contained in the element.
      CPPUNIT_ASSERT (elem->contains_point(Point(epsilon/2, 0, 0.5)));

      // Make sure that "just barely" outside points are outside.
      CPPUNIT_ASSERT (!elem->contains_point(Point(epsilon, epsilon, epsilon/2)));
      CPPUNIT_ASSERT (!elem->contains_point(Point(epsilon/10, epsilon/10, 1.0)));
      CPPUNIT_ASSERT (!elem->contains_point(Point(epsilon/2, -epsilon/10, 0.5)));
    }
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION( ContainsPointTest );
<commit_msg>Call elem->centroid() instead of computing it manually.<commit_after>// Ignore unused parameter warnings coming from cppunit headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/libmesh.h>
#include <libmesh/elem.h>

#include "test_comm.h"

using namespace libMesh;

class ContainsPointTest : public CppUnit::TestCase
{
  /**
   * The goal of this test is to verify proper operation of the contains_point
   * method that is used extensively in the point locator. This test focusses on
   * the specializes contains_point implementaion in TRI3.
   */
public:
  CPPUNIT_TEST_SUITE( ContainsPointTest );

  CPPUNIT_TEST( testContainsPointTri3 );

  CPPUNIT_TEST( testContainsPointTet4 );

  CPPUNIT_TEST_SUITE_END();

public:
  void setUp() {}

  void tearDown() {}

  // TRI3 test
  void testContainsPointTri3()
  {
    // tri corner nodes
    Node a(3,1,2, 0);
    Node b(1,2,3, 1);
    Node c(2,3,1, 2);

    // helper vectors to span the tri and point out of plane
    Point va(a-c);
    Point vb(b-c);
    Point oop(va.cross(vb));

    UniquePtr<Elem> elem = Elem::build(TRI3);

    elem->set_node(0) = &a;
    elem->set_node(1) = &b;
    elem->set_node(2) = &c;

    // centroid
    CPPUNIT_ASSERT (elem->contains_point(elem->centroid()));

    // out of plane from the centroid
    CPPUNIT_ASSERT (!elem->contains_point(elem->centroid() + oop/10));

    // check all corners
    CPPUNIT_ASSERT (elem->contains_point(a));
    CPPUNIT_ASSERT (elem->contains_point(b));
    CPPUNIT_ASSERT (elem->contains_point(c));

    // check outside
    CPPUNIT_ASSERT (!elem->contains_point(a + va * TOLERANCE * 10));
    CPPUNIT_ASSERT (!elem->contains_point(b + vb * TOLERANCE * 10));
    CPPUNIT_ASSERT (!elem->contains_point(c - (va + vb) * TOLERANCE * 10));
  }

  // TET4 test
  void testContainsPointTet4()
  {
    // Construct unit Tet.
    {
      Node zero  (0., 0., 0., 0);
      Node one   (1., 0., 0., 1);
      Node two   (0., 1., 0., 2);
      Node three (0., 0., 1., 3);

      UniquePtr<Elem> elem = Elem::build(TET4);
      elem->set_node(0) = &zero;
      elem->set_node(1) = &one;
      elem->set_node(2) = &two;
      elem->set_node(3) = &three;

      // The centroid must be inside the element.
      CPPUNIT_ASSERT (elem->contains_point(elem->centroid()));

      // The vertices must be contained in the element.
      CPPUNIT_ASSERT (elem->contains_point(zero));
      CPPUNIT_ASSERT (elem->contains_point(one));
      CPPUNIT_ASSERT (elem->contains_point(two));
      CPPUNIT_ASSERT (elem->contains_point(three));

      // Make sure that outside points are not contained.
      CPPUNIT_ASSERT (!elem->contains_point(Point(.34, .34, .34)));
      CPPUNIT_ASSERT (!elem->contains_point(Point(.33, .33, -.1)));
      CPPUNIT_ASSERT (!elem->contains_point(Point(0., -.1, .5)));
    }

    // Construct a nearly degenerate (sliver) tet.  A unit tet with
    // nodes "one" and "two" moved to within a distance of epsilon
    // from the origin.
    {
      Real epsilon = 1.e-4;

      Node zero  (0., 0., 0., 0);
      Node one   (epsilon, 0., 0., 1);
      Node two   (0., epsilon, 0., 2);
      Node three (0., 0., 1., 3);

      UniquePtr<Elem> elem = Elem::build(TET4);
      elem->set_node(0) = &zero;
      elem->set_node(1) = &one;
      elem->set_node(2) = &two;
      elem->set_node(3) = &three;

      // The centroid must be inside the element.
      CPPUNIT_ASSERT (elem->contains_point(elem->centroid()));

      // The vertices must be contained in the element.
      CPPUNIT_ASSERT (elem->contains_point(zero));
      CPPUNIT_ASSERT (elem->contains_point(one));
      CPPUNIT_ASSERT (elem->contains_point(two));
      CPPUNIT_ASSERT (elem->contains_point(three));

      // Verify that a point which is on a mid-edge is contained in the element.
      CPPUNIT_ASSERT (elem->contains_point(Point(epsilon/2, 0, 0.5)));

      // Make sure that "just barely" outside points are outside.
      CPPUNIT_ASSERT (!elem->contains_point(Point(epsilon, epsilon, epsilon/2)));
      CPPUNIT_ASSERT (!elem->contains_point(Point(epsilon/10, epsilon/10, 1.0)));
      CPPUNIT_ASSERT (!elem->contains_point(Point(epsilon/2, -epsilon/10, 0.5)));
    }
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION( ContainsPointTest );
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "mocca/base/Endian.h"
#include "mocca/net/NetworkError.h"
#include "mocca/net/framing/FramingUtils.h"
#include "mocca/net/framing/WebSocketProtocol.h"
#include "mocca/net/message/FramingConnectionFactory.h"
#include "mocca/net/stream/QueueConnectionFactory.h"

#include <array>

using namespace mocca;
using namespace mocca::net;

class WebsocketTest : public ::testing::Test {
protected:
    WebsocketTest()
        : mask({{0x11, 0x22, 0x33, 0x44}}) {
        factory.reset(new FramingConnectionFactory(std::unique_ptr<IStreamConnectionFactory>(new QueueConnectionFactory()),
                                                   std::unique_ptr<FramingStrategy>(new WebSocketProtocol())));
    }

    virtual ~WebsocketTest() {
        // You can do clean-up work that doesn't throw exceptions here.
    }

    std::string clientHandshakeStr =
        "GET / HTTP/1.1\r\n"
        "Host: localhost\r\n"
        "Connection: Upgrade\r\n"
        "Pragma: no-cache\r\n"
        "Cache-Control: no-cache\r\n"
        "Upgrade: websocket\r\n"
        "Origin: chrome-extension://pfdhoblngboilpfeibdedpjgfnlcodoo\r\n"
        "Sec-WebSocket-Version: 13\r\n"
        "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36\r\n"
        "Accept-Encoding: gzip, deflate, sdch\r\n"
        "Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4\r\n"
        "Sec-WebSocket-Key: cdsNUQEVKJWSMNeiLaaCbw==\r\n"
        "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n";

    ByteArray createPayloadData(uint32_t size) {
        ByteArray payload(size);
        payload.setSize(size);
        for (uint32_t i = 0; i < size; ++i) {
            payload.data()[i] = ('a' + (i % ('z' - 'a')));
        }
        return payload;
    }

    const unsigned char mediumPayload = 126;
    const unsigned char bigPayload = 127;
    const unsigned char flags = 0x81;
    std::array<unsigned char, 4> mask;

    ByteArray maskData(const ByteArray& data) {
        ByteArray result(data.size());
        result.setSize(data.size());
        for (uint32_t i = 0; i < data.size(); ++i) {
            result[i] = data[i] ^ mask[i % 4];
        }
        return result;
    }

    std::unique_ptr<FramingConnectionFactory> factory;
};

TEST_F(WebsocketTest, ReceiveSmallPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();

    unsigned char payloadSize = 125;
    ByteArray data(payloadSize + 6); // 6 bytes header
    data.append(&flags, 1);
    data.append(&payloadSize, 1);
    data.append(&mask, 4);
    auto payload = createPayloadData(payloadSize);
    data.append(maskData(payload));
    lbClientConnection->send(std::move(data));
    auto receivedData = wsServerConnection->receive();
    ASSERT_EQ(payloadSize, receivedData.size());
    ASSERT_TRUE(std::memcmp(payload.data(), receivedData.data(), payloadSize) == 0);
}

TEST_F(WebsocketTest, ReceiveMediumPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();

    uint16_t payloadSize = 40000;
    uint16_t payloadSizeBE = swap_uint16(payloadSize);
    ByteArray data(payloadSize + 8); // 8 bytes header
    data.append(&flags, 1);
    data.append(&mediumPayload, 1);
    data.append(&payloadSizeBE, 2);
    data.append(&mask, 4);
    auto payload = createPayloadData(payloadSize);
    data.append(maskData(payload));
    lbClientConnection->send(std::move(data));
    auto receivedData = wsServerConnection->receive();
    ASSERT_EQ(payloadSize, receivedData.size());
    ASSERT_TRUE(std::memcmp(payload.data(), receivedData.data(), payloadSize) == 0);
}

TEST_F(WebsocketTest, ReceiveBigPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();

    uint64_t payloadSize = 70000;
    uint64_t payloadSizeBE = swap_uint64(payloadSize);
    ByteArray data(static_cast<uint32_t>(payloadSize + 14)); // 14 bytes header
    data.append(&flags, 1);
    data.append(&bigPayload, 1);
    data.append(&payloadSizeBE, 8);
    data.append(&mask, 4);
    auto payload = createPayloadData(static_cast<uint32_t>(payloadSize));
    data.append(maskData(payload));
    lbClientConnection->send(std::move(data));
    auto receivedData = wsServerConnection->receive();
    ASSERT_EQ(payloadSize, receivedData.size());
    ASSERT_TRUE(std::memcmp(payload.data(), receivedData.data(), static_cast<uint32_t>(payloadSize)) == 0);
}

TEST_F(WebsocketTest, SendSmallPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();
    readUntil(*lbClientConnection, ByteArray(), "\r\n\r\n"); // remove hanshake response from client buffer

    unsigned char payloadSize = 125;
    auto payload = createPayloadData(payloadSize);
    wsServerConnection->send(payload.clone());

    ByteArray expectedData(payloadSize + 2); // 2 bytes header
    expectedData.append(&flags, 1);
    expectedData.append(&payloadSize, 1);
    expectedData.append(payload);

    auto receivedData = lbClientConnection->receive(200);
    ASSERT_EQ(expectedData.size(), receivedData.size());
    ASSERT_TRUE(std::memcmp(expectedData.data(), receivedData.data(), expectedData.size()) == 0);
}

TEST_F(WebsocketTest, SendMediumPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();
    readUntil(*lbClientConnection, ByteArray(), "\r\n\r\n"); // remove hanshake response from client buffer

    uint16_t payloadSize = 40000;
    uint16_t payloadSizeBE = swap_uint16(payloadSize);
    auto payload = createPayloadData(payloadSize);
    wsServerConnection->send(payload.clone());

    ByteArray expectedData(payloadSize + 4); // 4 bytes header
    expectedData.append(&flags, 1);
    expectedData.append(&mediumPayload, 1);
    expectedData.append(&payloadSizeBE, 2);
    expectedData.append(payload);

    auto receivedData = lbClientConnection->receive(41000);
    ASSERT_EQ(expectedData.size(), receivedData.size());
    ASSERT_TRUE(std::memcmp(expectedData.data(), receivedData.data(), expectedData.size()) == 0);
}

TEST_F(WebsocketTest, SendBigPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();
    readUntil(*lbClientConnection, ByteArray(), "\r\n\r\n"); // remove hanshake response from client buffer

    uint64_t payloadSize = 70000;
    uint64_t payloadSizeBE = swap_uint64(payloadSize);
    auto payload = createPayloadData(static_cast<uint32_t>(payloadSize));
    wsServerConnection->send(payload.clone());

    ByteArray expectedData(static_cast<uint32_t>(payloadSize) + 12); // 12 bytes header
    expectedData.append(&flags, 1);
    expectedData.append(&bigPayload, 1);
    expectedData.append(&payloadSizeBE, 8);
    expectedData.append(payload);

    auto receivedData = lbClientConnection->receive(71000);
    ASSERT_EQ(expectedData.size(), receivedData.size());
    ASSERT_TRUE(std::memcmp(expectedData.data(), receivedData.data(), expectedData.size()) == 0);
}

TEST_F(WebsocketTest, CloseConnection) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();
    const unsigned char closeData[] = {0x88};
    lbClientConnection->send(ByteArray::createFromRaw(&closeData, 1));
    ASSERT_THROW(wsServerConnection->receive(), ConnectionClosedError);
}<commit_msg>fixed test<commit_after>#include "gtest/gtest.h"

#include "mocca/base/Endian.h"
#include "mocca/net/NetworkError.h"
#include "mocca/net/framing/FramingUtils.h"
#include "mocca/net/framing/WebSocketProtocol.h"
#include "mocca/net/message/FramingConnectionFactory.h"
#include "mocca/net/stream/QueueConnectionFactory.h"

#include <array>

using namespace mocca;
using namespace mocca::net;

class WebsocketTest : public ::testing::Test {
protected:
    WebsocketTest()
        : mask({{0x11, 0x22, 0x33, 0x44}}) {
        factory.reset(new FramingConnectionFactory(std::unique_ptr<IStreamConnectionFactory>(new QueueConnectionFactory()),
                                                   std::unique_ptr<FramingStrategy>(new WebSocketProtocol())));
    }

    virtual ~WebsocketTest() {
        // You can do clean-up work that doesn't throw exceptions here.
    }

    std::string clientHandshakeStr =
        "GET / HTTP/1.1\r\n"
        "Host: localhost\r\n"
        "Connection: Upgrade\r\n"
        "Pragma: no-cache\r\n"
        "Cache-Control: no-cache\r\n"
        "Upgrade: websocket\r\n"
        "Origin: chrome-extension://pfdhoblngboilpfeibdedpjgfnlcodoo\r\n"
        "Sec-WebSocket-Version: 13\r\n"
        "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36\r\n"
        "Accept-Encoding: gzip, deflate, sdch\r\n"
        "Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4\r\n"
        "Sec-WebSocket-Key: cdsNUQEVKJWSMNeiLaaCbw==\r\n"
        "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n";

    ByteArray createPayloadData(uint32_t size) {
        ByteArray payload(size);
        payload.setSize(size);
        for (uint32_t i = 0; i < size; ++i) {
            payload.data()[i] = ('a' + (i % ('z' - 'a')));
        }
        return payload;
    }

    const unsigned char mediumPayload = 126;
    const unsigned char bigPayload = 127;
    const unsigned char flags = 0x81;
    std::array<unsigned char, 4> mask;

    ByteArray maskData(const ByteArray& data) {
        ByteArray result(data.size());
        result.setSize(data.size());
        for (uint32_t i = 0; i < data.size(); ++i) {
            result[i] = data[i] ^ mask[i % 4];
        }
        return result;
    }

    std::unique_ptr<FramingConnectionFactory> factory;
};

TEST_F(WebsocketTest, ReceiveSmallPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();

    unsigned char payloadSize = 125;
    ByteArray data(payloadSize + 6); // 6 bytes header
    data.append(&flags, 1);
    data.append(&payloadSize, 1);
    data.append(&mask, 4);
    auto payload = createPayloadData(payloadSize);
    data.append(maskData(payload));
    lbClientConnection->send(std::move(data));
    auto receivedData = wsServerConnection->receive();
    ASSERT_EQ(payloadSize, receivedData.size());
    ASSERT_TRUE(std::memcmp(payload.data(), receivedData.data(), payloadSize) == 0);
}

TEST_F(WebsocketTest, ReceiveMediumPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();

    uint16_t payloadSize = 40000;
    uint16_t payloadSizeBE = swap_uint16(payloadSize);
    ByteArray data(payloadSize + 8); // 8 bytes header
    data.append(&flags, 1);
    data.append(&mediumPayload, 1);
    data.append(&payloadSizeBE, 2);
    data.append(&mask, 4);
    auto payload = createPayloadData(payloadSize);
    data.append(maskData(payload));
    lbClientConnection->send(std::move(data));
    auto receivedData = wsServerConnection->receive();
    ASSERT_EQ(payloadSize, receivedData.size());
    ASSERT_TRUE(std::memcmp(payload.data(), receivedData.data(), payloadSize) == 0);
}

TEST_F(WebsocketTest, ReceiveBigPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();

    uint64_t payloadSize = 70000;
    uint64_t payloadSizeBE = swap_uint64(payloadSize);
    ByteArray data(static_cast<uint32_t>(payloadSize + 14)); // 14 bytes header
    data.append(&flags, 1);
    data.append(&bigPayload, 1);
    data.append(&payloadSizeBE, 8);
    data.append(&mask, 4);
    auto payload = createPayloadData(static_cast<uint32_t>(payloadSize));
    data.append(maskData(payload));
    lbClientConnection->send(std::move(data));
    auto receivedData = wsServerConnection->receive();
    ASSERT_EQ(payloadSize, receivedData.size());
    ASSERT_TRUE(std::memcmp(payload.data(), receivedData.data(), static_cast<uint32_t>(payloadSize)) == 0);
}

TEST_F(WebsocketTest, SendSmallPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();
    ByteArray tmp;
    readUntil(*lbClientConnection, tmp, "\r\n\r\n"); // remove hanshake response from client buffer

    unsigned char payloadSize = 125;
    auto payload = createPayloadData(payloadSize);
    wsServerConnection->send(payload.clone());

    ByteArray expectedData(payloadSize + 2); // 2 bytes header
    expectedData.append(&flags, 1);
    expectedData.append(&payloadSize, 1);
    expectedData.append(payload);

    auto receivedData = lbClientConnection->receive(200);
    ASSERT_EQ(expectedData.size(), receivedData.size());
    ASSERT_TRUE(std::memcmp(expectedData.data(), receivedData.data(), expectedData.size()) == 0);
}

TEST_F(WebsocketTest, SendMediumPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();
    ByteArray tmp;
    readUntil(*lbClientConnection, tmp, "\r\n\r\n"); // remove hanshake response from client buffer

    uint16_t payloadSize = 40000;
    uint16_t payloadSizeBE = swap_uint16(payloadSize);
    auto payload = createPayloadData(payloadSize);
    wsServerConnection->send(payload.clone());

    ByteArray expectedData(payloadSize + 4); // 4 bytes header
    expectedData.append(&flags, 1);
    expectedData.append(&mediumPayload, 1);
    expectedData.append(&payloadSizeBE, 2);
    expectedData.append(payload);

    auto receivedData = lbClientConnection->receive(41000);
    ASSERT_EQ(expectedData.size(), receivedData.size());
    ASSERT_TRUE(std::memcmp(expectedData.data(), receivedData.data(), expectedData.size()) == 0);
}

TEST_F(WebsocketTest, SendBigPayload) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();
    ByteArray tmp;
    readUntil(*lbClientConnection, tmp, "\r\n\r\n"); // remove hanshake response from client buffer

    uint64_t payloadSize = 70000;
    uint64_t payloadSizeBE = swap_uint64(payloadSize);
    auto payload = createPayloadData(static_cast<uint32_t>(payloadSize));
    wsServerConnection->send(payload.clone());

    ByteArray expectedData(static_cast<uint32_t>(payloadSize) + 12); // 12 bytes header
    expectedData.append(&flags, 1);
    expectedData.append(&bigPayload, 1);
    expectedData.append(&payloadSizeBE, 8);
    expectedData.append(payload);

    auto receivedData = lbClientConnection->receive(71000);
    ASSERT_EQ(expectedData.size(), receivedData.size());
    ASSERT_TRUE(std::memcmp(expectedData.data(), receivedData.data(), expectedData.size()) == 0);
}

TEST_F(WebsocketTest, CloseConnection) {
    auto wsAcceptor = factory->bind("mq");
    auto& lbService = factory->streamConnectionFactory();
    auto lbClientConnection = lbService.connect("mq");
    lbClientConnection->send(ByteArray::createFromRaw((unsigned char*)clientHandshakeStr.c_str(), clientHandshakeStr.size()));
    auto wsServerConnection = wsAcceptor->accept();
    const unsigned char closeData[] = {0x88};
    lbClientConnection->send(ByteArray::createFromRaw(&closeData, 1));
    ASSERT_THROW(wsServerConnection->receive(), ConnectionClosedError);
}<|endoftext|>


<commit_before>// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "base/lock_impl.h"

LockImpl::LockImpl() {
  ::InitializeCriticalSection(&os_lock_);
}

LockImpl::~LockImpl() {
  ::DeleteCriticalSection(&os_lock_);
}

bool LockImpl::Try() {
  return ::TryEnterCriticalSection(&os_lock_) != FALSE;
}

void LockImpl::Lock() {
  ::EnterCriticalSection(&os_lock_);
}

void LockImpl::Unlock() {
  ::LeaveCriticalSection(&os_lock_);
}
<commit_msg>Add a spinlock wait to the dearly beloved crititcal section - the 2000 is a guess, I think the right number is between 1000 and 4000 - lets look at perf, if hurts then we remove it<commit_after>// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "base/lock_impl.h"

LockImpl::LockImpl() {
  // The second parameter is the spin count, for short-held locks it avoid the
  // contending thread from going to sleep which helps performance greatly.
  ::InitializeCriticalSectionAndSpinCount(&os_lock_, 2000);
}

LockImpl::~LockImpl() {
  ::DeleteCriticalSection(&os_lock_);
}

bool LockImpl::Try() {
  return ::TryEnterCriticalSection(&os_lock_) != FALSE;
}

void LockImpl::Lock() {
  ::EnterCriticalSection(&os_lock_);
}

void LockImpl::Unlock() {
  ::LeaveCriticalSection(&os_lock_);
}
<|endoftext|>