<commit_before>/*     Copyright 2015-2018 Egor Yusov
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include "AndroidAppBase.hpp"
#include "Timer.hpp"

#include <android/sensor.h>
//#include <android/log.h>
//#include <android_native_app_glue.h>
#include <android/native_window_jni.h>
//#include <cpu-features.h>

namespace Diligent
{

int AndroidAppBase::InitDisplay()
{
    if (!initialized_resources_)
    {
        Initialize();

        LoadResources();
        initialized_resources_ = true;
    }
    else
    {
        // initialize OpenGL ES and EGL
        if (EGL_SUCCESS != Resume(app_->window))
        {
            UnloadResources();
            LoadResources();
        }
    }

    ShowUI();

    //tap_camera_.SetFlip( 1.f, -1.f, -1.f );
    //tap_camera_.SetPinchTransformFactor( 2.f, 2.f, 8.f );

    return 0;
}

void AndroidAppBase::InitSensors()
{
    sensor_manager_       = ASensorManager_getInstance();
    accelerometer_sensor_ = ASensorManager_getDefaultSensor(sensor_manager_, ASENSOR_TYPE_ACCELEROMETER);
    sensor_event_queue_   = ASensorManager_createEventQueue(sensor_manager_, app_->looper, LOOPER_ID_USER, NULL, NULL);
}

//
// Just the current frame in the display.
//
void AndroidAppBase::DrawFrame()
{
    float fFPS;
    if (monitor_.Update(fFPS))
    {
        UpdateFPS(fFPS);
    }

    static Diligent::Timer Timer;

    static double PrevTime    = Timer.GetElapsedTime();
    auto          CurrTime    = Timer.GetElapsedTime();
    auto          ElapsedTime = CurrTime - PrevTime;

    PrevTime = CurrTime;

    Update(CurrTime, ElapsedTime);

    Render();

    Present();
    //if( EGL_SUCCESS != pRenderDevice_->Present() )
    //{
    //    UnloadResources();
    //    LoadResources();
    //}
}

//
// Process the next input event.
//
int32_t AndroidAppBase::HandleInput(android_app* app, AInputEvent* event)
{
    AndroidAppBase* eng = (AndroidAppBase*)app->userData;
    return eng->HandleInput(event);
}

//
// Process the next main command.
//
void AndroidAppBase::HandleCmd(struct android_app* app, int32_t cmd)
{
    AndroidAppBase* eng = (AndroidAppBase*)app->userData;
    switch (cmd)
    {
        case APP_CMD_SAVE_STATE:
            break;

        case APP_CMD_INIT_WINDOW:
            // The window is being shown, get it ready.
            if (app->window != NULL)
            {
                eng->InitDisplay();
                eng->DrawFrame();
            }
            break;

        case APP_CMD_CONFIG_CHANGED:
        {
            // This callback is not reliable for handling orientation changes. Depending on the
            // device, it may be called before or after the surface has been actually resized.
            break;
        }

        // Note that as of NDK r21b (21.1.6352462), APP_CMD_WINDOW_RESIZED event is never generated
        // by android_native_app_glue.
        // Also note that modifying android_native_app_glue to handle onNativeWindowResized
        // callback (as suggested in https://android-developers.googleblog.com/2020/02/handling-device-orientation-efficiently.html)
        // does not work either - the callback is only called once after the window has been created.
        case APP_CMD_WINDOW_RESIZED:
        {
            auto new_window_width  = ANativeWindow_getWidth(app->window);
            auto new_window_height = ANativeWindow_getHeight(app->window);
            eng->WindowResize(new_window_width, new_window_height);
            break;
        }

        // Note that as of NDK r21b (21.1.6352462), APP_CMD_CONTENT_RECT_CHANGED event is never
        // generated by android_native_app_glue
        case APP_CMD_CONTENT_RECT_CHANGED:
        {
            auto new_window_width  = app->contentRect.right - app->contentRect.left;
            auto new_window_height = app->contentRect.bottom - app->contentRect.top;
            eng->WindowResize(new_window_width, new_window_height);
            break;
        }

        case APP_CMD_TERM_WINDOW:
            // The window is being hidden or closed, clean it up.
            eng->TermDisplay();
            eng->has_focus_ = false;
            break;

        case APP_CMD_STOP:
            break;

        case APP_CMD_GAINED_FOCUS:
            eng->ResumeSensors();
            //Start animation
            eng->has_focus_ = true;
            break;

        case APP_CMD_LOST_FOCUS:
            eng->SuspendSensors();
            // Also stop animating.
            eng->has_focus_ = false;
            break;

        case APP_CMD_LOW_MEMORY:
            //Free up GL resources
            eng->TrimMemory();
            break;
    }
}

//-------------------------------------------------------------------------
//Sensor handlers
//-------------------------------------------------------------------------
void AndroidAppBase::ProcessSensors(int32_t id)
{
    // If a sensor has data, process it now.
    if (id == LOOPER_ID_USER)
    {
        if (accelerometer_sensor_ != NULL)
        {
            ASensorEvent event;
            while (ASensorEventQueue_getEvents(sensor_event_queue_, &event, 1) > 0)
            {
            }
        }
    }
}

void AndroidAppBase::ResumeSensors()
{
    // When our app gains focus, we start monitoring the accelerometer.
    if (accelerometer_sensor_ != NULL)
    {
        ASensorEventQueue_enableSensor(sensor_event_queue_, accelerometer_sensor_);
        // We'd like to get 60 events per second (in us).
        ASensorEventQueue_setEventRate(sensor_event_queue_, accelerometer_sensor_,
                                       (1000L / 60) * 1000);
    }
}

void AndroidAppBase::SuspendSensors()
{
    // When our app loses focus, we stop monitoring the accelerometer.
    // This is to avoid consuming battery while not being used.
    if (accelerometer_sensor_ != NULL)
    {
        ASensorEventQueue_disableSensor(sensor_event_queue_, accelerometer_sensor_);
    }
}

//-------------------------------------------------------------------------
//Misc
//-------------------------------------------------------------------------
void AndroidAppBase::SetState(android_app* state, const char* native_activity_class_name)
{
    app_ = state;

    native_activity_class_name_ = native_activity_class_name;
    doubletap_detector_.SetConfiguration(app_->config);
    drag_detector_.SetConfiguration(app_->config);
    pinch_detector_.SetConfiguration(app_->config);
}

bool AndroidAppBase::IsReady()
{
    if (has_focus_)
        return true;

    return false;
}

//void Engine::TransformPosition( ndk_helper::Vec2& vec )
//{
//    vec = ndk_helper::Vec2( 2.0f, 2.0f ) * vec
//        / ndk_helper::Vec2( pDeviceContext_->GetMainBackBufferDesc().Width, pDeviceContext_->GetMainBackBufferDesc().Height )
//        - ndk_helper::Vec2( 1.f, 1.f );
//}

void AndroidAppBase::ShowUI()
{
    JNIEnv* jni;
    app_->activity->vm->AttachCurrentThread(&jni, NULL);

    //Default class retrieval
    jclass    clazz    = jni->GetObjectClass(app_->activity->clazz);
    jmethodID methodID = jni->GetMethodID(clazz, "showUI", "()V");
    jni->CallVoidMethod(app_->activity->clazz, methodID);

    app_->activity->vm->DetachCurrentThread();
    return;
}

void AndroidAppBase::UpdateFPS(float fFPS)
{
    JNIEnv* jni;
    app_->activity->vm->AttachCurrentThread(&jni, NULL);

    //Default class retrieval
    jclass    clazz    = jni->GetObjectClass(app_->activity->clazz);
    jmethodID methodID = jni->GetMethodID(clazz, "updateFPS", "(F)V");
    jni->CallVoidMethod(app_->activity->clazz, methodID, fFPS);

    app_->activity->vm->DetachCurrentThread();
    return;
}

} // namespace Diligent
<commit_msg>Fixed crash on Android/Vulkan<commit_after>/*     Copyright 2015-2018 Egor Yusov
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include "AndroidAppBase.hpp"
#include "Timer.hpp"

#include <android/sensor.h>
//#include <android/log.h>
//#include <android_native_app_glue.h>
#include <android/native_window_jni.h>
//#include <cpu-features.h>

namespace Diligent
{

int AndroidAppBase::InitDisplay()
{
    if (!initialized_resources_)
    {
        Initialize();

        LoadResources();
        initialized_resources_ = true;
    }
    else
    {
        // initialize OpenGL ES and EGL
        if (EGL_SUCCESS != Resume(app_->window))
        {
            UnloadResources();
            LoadResources();
        }
    }

    ShowUI();

    //tap_camera_.SetFlip( 1.f, -1.f, -1.f );
    //tap_camera_.SetPinchTransformFactor( 2.f, 2.f, 8.f );

    return 0;
}

void AndroidAppBase::InitSensors()
{
    sensor_manager_       = ASensorManager_getInstance();
    accelerometer_sensor_ = ASensorManager_getDefaultSensor(sensor_manager_, ASENSOR_TYPE_ACCELEROMETER);
    sensor_event_queue_   = ASensorManager_createEventQueue(sensor_manager_, app_->looper, LOOPER_ID_USER, NULL, NULL);
}

//
// Just the current frame in the display.
//
void AndroidAppBase::DrawFrame()
{
    float fFPS;
    if (monitor_.Update(fFPS))
    {
        UpdateFPS(fFPS);
    }

    static Diligent::Timer Timer;

    static double PrevTime    = Timer.GetElapsedTime();
    auto          CurrTime    = Timer.GetElapsedTime();
    auto          ElapsedTime = CurrTime - PrevTime;

    PrevTime = CurrTime;

    Update(CurrTime, ElapsedTime);

    Render();

    Present();
    //if( EGL_SUCCESS != pRenderDevice_->Present() )
    //{
    //    UnloadResources();
    //    LoadResources();
    //}
}

//
// Process the next input event.
//
int32_t AndroidAppBase::HandleInput(android_app* app, AInputEvent* event)
{
    AndroidAppBase* eng = (AndroidAppBase*)app->userData;
    return eng->HandleInput(event);
}

//
// Process the next main command.
//
void AndroidAppBase::HandleCmd(struct android_app* app, int32_t cmd)
{
    AndroidAppBase* eng = (AndroidAppBase*)app->userData;
    switch (cmd)
    {
        case APP_CMD_SAVE_STATE:
            break;

        case APP_CMD_INIT_WINDOW:
            // The window is being shown, get it ready.
            if (app->window != NULL)
            {
                eng->InitDisplay();
                eng->DrawFrame();
            }
            break;

        case APP_CMD_CONFIG_CHANGED:
        {
            // This callback is not reliable for handling orientation changes. Depending on the
            // device, it may be called before or after the surface has been actually resized.
            break;
        }

        // Note that as of NDK r21b (21.1.6352462), APP_CMD_WINDOW_RESIZED event is never generated
        // by android_native_app_glue.
        // Also note that modifying android_native_app_glue to handle onNativeWindowResized
        // callback (as suggested in https://android-developers.googleblog.com/2020/02/handling-device-orientation-efficiently.html)
        // does not work either - the callback is only called once after the window has been created.
        case APP_CMD_WINDOW_RESIZED:
        {
            auto new_window_width  = ANativeWindow_getWidth(app->window);
            auto new_window_height = ANativeWindow_getHeight(app->window);
            eng->WindowResize(new_window_width, new_window_height);
            break;
        }

        // Note that as of NDK r21b (21.1.6352462), APP_CMD_CONTENT_RECT_CHANGED event is never
        // generated by android_native_app_glue
        case APP_CMD_CONTENT_RECT_CHANGED:
        {
            auto new_window_width  = app->contentRect.right - app->contentRect.left;
            auto new_window_height = app->contentRect.bottom - app->contentRect.top;
            eng->WindowResize(new_window_width, new_window_height);
            break;
        }

        case APP_CMD_TERM_WINDOW:
        case APP_CMD_PAUSE:
            // The window is being hidden or closed, clean it up.
            eng->TermDisplay();
            eng->has_focus_ = false;
            break;

        case APP_CMD_STOP:
            break;

        case APP_CMD_GAINED_FOCUS:
            eng->ResumeSensors();
            //Start animation
            eng->has_focus_ = true;
            break;

        case APP_CMD_LOST_FOCUS:
            eng->SuspendSensors();
            // Also stop animating.
            eng->has_focus_ = false;
            break;

        case APP_CMD_LOW_MEMORY:
            //Free up GL resources
            eng->TrimMemory();
            break;
    }
}

//-------------------------------------------------------------------------
//Sensor handlers
//-------------------------------------------------------------------------
void AndroidAppBase::ProcessSensors(int32_t id)
{
    // If a sensor has data, process it now.
    if (id == LOOPER_ID_USER)
    {
        if (accelerometer_sensor_ != NULL)
        {
            ASensorEvent event;
            while (ASensorEventQueue_getEvents(sensor_event_queue_, &event, 1) > 0)
            {
            }
        }
    }
}

void AndroidAppBase::ResumeSensors()
{
    // When our app gains focus, we start monitoring the accelerometer.
    if (accelerometer_sensor_ != NULL)
    {
        ASensorEventQueue_enableSensor(sensor_event_queue_, accelerometer_sensor_);
        // We'd like to get 60 events per second (in us).
        ASensorEventQueue_setEventRate(sensor_event_queue_, accelerometer_sensor_,
                                       (1000L / 60) * 1000);
    }
}

void AndroidAppBase::SuspendSensors()
{
    // When our app loses focus, we stop monitoring the accelerometer.
    // This is to avoid consuming battery while not being used.
    if (accelerometer_sensor_ != NULL)
    {
        ASensorEventQueue_disableSensor(sensor_event_queue_, accelerometer_sensor_);
    }
}

//-------------------------------------------------------------------------
//Misc
//-------------------------------------------------------------------------
void AndroidAppBase::SetState(android_app* state, const char* native_activity_class_name)
{
    app_ = state;

    native_activity_class_name_ = native_activity_class_name;
    doubletap_detector_.SetConfiguration(app_->config);
    drag_detector_.SetConfiguration(app_->config);
    pinch_detector_.SetConfiguration(app_->config);
}

bool AndroidAppBase::IsReady()
{
    if (has_focus_)
        return true;

    return false;
}

//void Engine::TransformPosition( ndk_helper::Vec2& vec )
//{
//    vec = ndk_helper::Vec2( 2.0f, 2.0f ) * vec
//        / ndk_helper::Vec2( pDeviceContext_->GetMainBackBufferDesc().Width, pDeviceContext_->GetMainBackBufferDesc().Height )
//        - ndk_helper::Vec2( 1.f, 1.f );
//}

void AndroidAppBase::ShowUI()
{
    JNIEnv* jni;
    app_->activity->vm->AttachCurrentThread(&jni, NULL);

    //Default class retrieval
    jclass    clazz    = jni->GetObjectClass(app_->activity->clazz);
    jmethodID methodID = jni->GetMethodID(clazz, "showUI", "()V");
    jni->CallVoidMethod(app_->activity->clazz, methodID);

    app_->activity->vm->DetachCurrentThread();
    return;
}

void AndroidAppBase::UpdateFPS(float fFPS)
{
    JNIEnv* jni;
    app_->activity->vm->AttachCurrentThread(&jni, NULL);

    //Default class retrieval
    jclass    clazz    = jni->GetObjectClass(app_->activity->clazz);
    jmethodID methodID = jni->GetMethodID(clazz, "updateFPS", "(F)V");
    jni->CallVoidMethod(app_->activity->clazz, methodID, fFPS);

    app_->activity->vm->DetachCurrentThread();
    return;
}

} // namespace Diligent
<|endoftext|>


<commit_before>/*
 * ======================================================================
 * Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
 * Licensed under the MIT License.
 * See LICENSE.md in the project root for license information.
 * ======================================================================
*/

#ifdef QTFRAMEWORK
#include "LocalSettingsQt.h"

namespace rmscore {
namespace platform {
namespace settings {

std::shared_ptr<ILocalSettings> ILocalSettings::Create(const std::string& filename)
{
    return std::make_shared<LocalSettingsQt>(filename.c_str());
}

LocalSettingsQt::LocalSettingsQt(const QString& filename) :
  impl_(filename)
{}

std::string LocalSettingsQt::GetString(const std::string& container,
                                            const std::string& name,
                                            const std::string& defaultValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.value(key.c_str(),
                           defaultValue.c_str()).toString().toStdString();
}

bool LocalSettingsQt::GetBool(const std::string& container,
                                   const std::string& name,
                                   bool               bDefaultValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.value(key.c_str(), bDefaultValue).toBool();
}

void LocalSettingsQt::SetBool(const std::string& container,
                                   const std::string& name,
                                   bool               bValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.setValue(key.c_str(), bValue);
}

int LocalSettingsQt::GetInt(const std::string& container,
                                 const std::string& name,
                                 int                nDefaultValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.value(key.c_str(), nDefaultValue).toInt();
}

void LocalSettingsQt::SetInt(const std::string& container,
                                  const std::string& name,
                                  int                nValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.setValue(key.c_str(), nValue);
}
}
}
} // namespace rmscore { namespace platform { namespace settings {

#endif
<commit_msg>#84 fix config format to INI<commit_after>/*
 * ======================================================================
 * Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
 * Licensed under the MIT License.
 * See LICENSE.md in the project root for license information.
 * ======================================================================
*/

#ifdef QTFRAMEWORK
#include <QDebug>
#include "LocalSettingsQt.h"

namespace rmscore {
namespace platform {
namespace settings {

std::shared_ptr<ILocalSettings> ILocalSettings::Create(const std::string& filename)
{
    return std::make_shared<LocalSettingsQt>(filename.c_str());
}

LocalSettingsQt::LocalSettingsQt(const QString& filename) :
  impl_(filename, QSettings::IniFormat) {}

std::string LocalSettingsQt::GetString(const std::string& container,
                                            const std::string& name,
                                            const std::string& defaultValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.value(key.c_str(),
                           defaultValue.c_str()).toString().toStdString();
}

bool LocalSettingsQt::GetBool(const std::string& container,
                                   const std::string& name,
                                   bool               bDefaultValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.value(key.c_str(), bDefaultValue).toBool();
}

void LocalSettingsQt::SetBool(const std::string& container,
                                   const std::string& name,
                                   bool               bValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.setValue(key.c_str(), bValue);
}

int LocalSettingsQt::GetInt(const std::string& container,
                                 const std::string& name,
                                 int                nDefaultValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.value(key.c_str(), nDefaultValue).toInt();
}

void LocalSettingsQt::SetInt(const std::string& container,
                                  const std::string& name,
                                  int                nValue)
{
  std::string key(container.empty() ? name : container + "/" + name);

  return this->impl_.setValue(key.c_str(), nValue);
}
}
}
} // namespace rmscore { namespace platform { namespace settings {

#endif
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "bucketid.h"
#include <iomanip>
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <vespa/vespalib/stllike/hash_set.hpp>
#include <vespa/vespalib/util/stringfmt.h>
#include <limits>

using vespalib::nbostream;
using vespalib::asciistream;

namespace document {

const unsigned char reverseBitTable[256] =
{
  0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
  0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
  0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
  0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
  0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
  0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
  0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
  0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
  0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
  0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
  0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
  0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
  0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
  0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
  0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
  0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};

BucketId::Type BucketId::_usedMasks[BucketId::maxNumBits+1];
BucketId::Type BucketId::_stripMasks[BucketId::maxNumBits+1];

namespace {

void fillUsedMasks(BucketId::Type * masks, uint8_t maxBits)
{
    typedef BucketId::Type Type;
    for (uint32_t usedBits = 0; usedBits <= maxBits; ++usedBits) {
        uint8_t notused = 8 * sizeof(Type) - usedBits;
        masks[usedBits] = (std::numeric_limits<Type>::max() << notused) >> notused;
    }
}

void fillStripMasks(BucketId::Type * masks, uint8_t maxBits)
{
    typedef BucketId::Type Type;
    for (uint32_t usedBits = 0; usedBits <= maxBits; ++usedBits) {
        uint8_t notused = 8 * sizeof(Type) - usedBits;
        Type usedMask = (std::numeric_limits<Type>::max() << notused) >> notused;
        Type countMask = (std::numeric_limits<Type>::max() >> maxBits) << maxBits;
        masks[usedBits] = usedMask | countMask;
    }
}

struct Initialize {
    Initialize() {
        BucketId::initialize();
    }
};

Initialize _initializeUsedMasks;

}

void BucketId::initialize() {
    fillUsedMasks(BucketId::_usedMasks, BucketId::maxNumBits);
    fillStripMasks(BucketId::_stripMasks, BucketId::maxNumBits);
}

vespalib::string
BucketId::toString() const
{
    vespalib::asciistream stream;
    stream << *this;
    return stream.str();
}

void BucketId::throwFailedSetUsedBits(uint32_t used, uint32_t availBits) {
    throw vespalib::IllegalArgumentException(vespalib::make_string(
            "Failed to set used bits to %u, max is %u.",
            used, availBits), VESPA_STRLOC);
}

BucketId::Type
BucketId::reverse(Type id)
{
    Type retVal;
    int bytes = sizeof(Type);

    for (int i = 0; i < bytes; i++) {
        ((unsigned char*)&retVal)[bytes - i - 1] = reverseBitTable[((const unsigned char*)&id)[i]];
    }

    return retVal;
}

BucketId::Type
BucketId::keyToBucketId(Type key)
{
    Type retVal = reverse(key);

    Type usedCountMSB = key << maxNumBits;
    retVal <<= CountBits;
    retVal >>= CountBits;
    retVal |= usedCountMSB;

    return retVal;
}

bool
BucketId::contains(const BucketId& id) const
{
    if (id.getUsedBits() < getUsedBits()) {
        return false;
    }
    BucketId copy(getUsedBits(), id.getRawId());
    return (copy.getId() == getId());
}

vespalib::asciistream& operator<<(asciistream& os, const BucketId& id)
{
    asciistream::StateSaver stateSaver(os);
    return os << "BucketId(0x"
              << vespalib::hex << vespalib::setw(sizeof(BucketId::Type)*2) << vespalib::setfill('0')
              << id.getId() << ")";
}

std::ostream& operator<<(std::ostream& os, const BucketId& id)
{
    return os << id.toString();
}

nbostream &
operator<<(nbostream &os, const BucketId &bucketId)
{
    os << bucketId._id;
    return os;
}

nbostream &
operator>>(nbostream &is, BucketId &bucketId)
{
    is >> bucketId._id;
    return is;
}

} // document

template class vespalib::Array<document::BucketId>;
VESPALIB_HASH_SET_INSTANTIATE_H(document::BucketId, document::BucketId::hash);
<commit_msg>Optimize bucketId::reverse<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "bucketid.h"
#include <iomanip>
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <vespa/vespalib/stllike/hash_set.hpp>
#include <vespa/vespalib/util/stringfmt.h>
#include <limits>

using vespalib::nbostream;
using vespalib::asciistream;

namespace document {

const unsigned char reverseBitTable[256] =
{
  0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
  0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
  0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
  0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
  0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
  0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
  0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
  0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
  0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
  0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
  0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
  0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
  0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
  0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
  0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
  0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};

BucketId::Type BucketId::_usedMasks[BucketId::maxNumBits+1];
BucketId::Type BucketId::_stripMasks[BucketId::maxNumBits+1];

namespace {

void fillUsedMasks(BucketId::Type * masks, uint8_t maxBits)
{
    typedef BucketId::Type Type;
    for (uint32_t usedBits = 0; usedBits <= maxBits; ++usedBits) {
        uint8_t notused = 8 * sizeof(Type) - usedBits;
        masks[usedBits] = (std::numeric_limits<Type>::max() << notused) >> notused;
    }
}

void fillStripMasks(BucketId::Type * masks, uint8_t maxBits)
{
    typedef BucketId::Type Type;
    for (uint32_t usedBits = 0; usedBits <= maxBits; ++usedBits) {
        uint8_t notused = 8 * sizeof(Type) - usedBits;
        Type usedMask = (std::numeric_limits<Type>::max() << notused) >> notused;
        Type countMask = (std::numeric_limits<Type>::max() >> maxBits) << maxBits;
        masks[usedBits] = usedMask | countMask;
    }
}

struct Initialize {
    Initialize() {
        BucketId::initialize();
    }
};

Initialize _initializeUsedMasks;

}

void BucketId::initialize() {
    fillUsedMasks(BucketId::_usedMasks, BucketId::maxNumBits);
    fillStripMasks(BucketId::_stripMasks, BucketId::maxNumBits);
}

vespalib::string
BucketId::toString() const
{
    vespalib::asciistream stream;
    stream << *this;
    return stream.str();
}

void BucketId::throwFailedSetUsedBits(uint32_t used, uint32_t availBits) {
    throw vespalib::IllegalArgumentException(vespalib::make_string(
            "Failed to set used bits to %u, max is %u.",
            used, availBits), VESPA_STRLOC);
}

BucketId::Type
BucketId::reverse(Type id)
{
    id = ((id & 0x5555555555555555l) << 1) | ((id & 0xaaaaaaaaaaaaaaaal) >> 1);
    id = ((id & 0x3333333333333333l) << 2) | ((id & 0xccccccccccccccccl) >> 2);
    id = ((id & 0x0f0f0f0f0f0f0f0fl) << 4) | ((id & 0xf0f0f0f0f0f0f0f0l) >> 4);
    return __builtin_bswap64(id);
}

BucketId::Type
BucketId::keyToBucketId(Type key)
{
    Type retVal = reverse(key);

    Type usedCountMSB = key << maxNumBits;
    retVal <<= CountBits;
    retVal >>= CountBits;
    retVal |= usedCountMSB;

    return retVal;
}

bool
BucketId::contains(const BucketId& id) const
{
    if (id.getUsedBits() < getUsedBits()) {
        return false;
    }
    BucketId copy(getUsedBits(), id.getRawId());
    return (copy.getId() == getId());
}

vespalib::asciistream& operator<<(asciistream& os, const BucketId& id)
{
    asciistream::StateSaver stateSaver(os);
    return os << "BucketId(0x"
              << vespalib::hex << vespalib::setw(sizeof(BucketId::Type)*2) << vespalib::setfill('0')
              << id.getId() << ")";
}

std::ostream& operator<<(std::ostream& os, const BucketId& id)
{
    return os << id.toString();
}

nbostream &
operator<<(nbostream &os, const BucketId &bucketId)
{
    os << bucketId._id;
    return os;
}

nbostream &
operator>>(nbostream &is, BucketId &bucketId)
{
    is >> bucketId._id;
    return is;
}

} // document

template class vespalib::Array<document::BucketId>;
VESPALIB_HASH_SET_INSTANTIATE_H(document::BucketId, document::BucketId::hash);
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
   @author Thomas F. Gundersen, �ystein Fledsberg
   @version $Id$
   @date 2004-03-15
*/

#include "bytebuffer.h"
#include "bufferexceptions.h"
#include "stringutil.h"
#include <vespa/vespalib/stllike/asciistream.h>
#include <sstream>
#include <arpa/inet.h>

using vespalib::alloc::Alloc;
using vespalib::make_string;

namespace document {

namespace {

static void throwOutOfBounds(size_t want, size_t has) __attribute__((noinline, noreturn));

void throwOutOfBounds(size_t want, size_t has)
{
    throw BufferOutOfBoundsException(want, has, VESPA_STRLOC);
}

}

#if defined(__i386__) || defined(__x86_64__)

template<typename T>
void
ByteBuffer::getDoubleLongNetwork(T &val) {
    //TODO: Change this if we move to big-endian hardware
    if (__builtin_expect(getRemaining() < (int)sizeof(T), 0)) {
        throwOutOfBounds(sizeof(T), getRemaining());
    }

    auto * data = reinterpret_cast<unsigned char*>(&val);
    for (int i=sizeof(T)-1; i>=0; --i) {
        getByte(data[i]);
    }
}

#else
#error "getDoubleLongNetwork is undefined for this arcitecture"
#endif

VESPA_IMPLEMENT_EXCEPTION_SPINE(BufferOutOfBoundsException);

vespalib::string BufferOutOfBoundsException::createMessage(size_t pos, size_t len) {
    vespalib::asciistream ost;
    ost << pos << " > " << len;
    return ost.str();
}

BufferOutOfBoundsException::BufferOutOfBoundsException(size_t pos, size_t len, const vespalib::string& location)
    : IoException(createMessage(pos, len), IoException::NO_SPACE, location, 1)
{
}

ByteBuffer::ByteBuffer(const char* buffer, uint32_t len) :
      _buffer(const_cast<char *>(buffer)),
      _len(len),
      _pos(0),
      _ownedBuffer()
{
}

ByteBuffer::ByteBuffer(Alloc buffer, uint32_t len) :
      _buffer(static_cast<char *>(buffer.get())),
      _len(len),
      _pos(0),
      _ownedBuffer(std::move(buffer))
{
}

ByteBuffer::ByteBuffer(const ByteBuffer& rhs) :
      _buffer(nullptr),
      _len(rhs._len),
      _pos(rhs._pos),
      _ownedBuffer()
{
    if (rhs._len > 0 && rhs._buffer) {
        Alloc buf = Alloc::alloc(rhs._len + 1);
        memcpy(buf.get(), rhs._buffer, rhs._len);
        static_cast<char *>(buf.get())[rhs._len] = 0;
        _ownedBuffer = std::move(buf);
        _buffer = static_cast<const char *>(_ownedBuffer.get());
    }
}

ByteBuffer::~ByteBuffer() = default;

ByteBuffer* ByteBuffer::copyBuffer(const char* buffer, uint32_t len)
{
    if (buffer && len) {
        Alloc newBuf = Alloc::alloc(len + 1);
        memcpy(newBuf.get(), buffer, len);
        static_cast<char *>(newBuf.get())[len] = 0;
        return new ByteBuffer(std::move(newBuf), len);
    } else {
        return nullptr;
    }
}

void ByteBuffer::incPos(uint32_t pos)
{
    if (_pos + pos > _len) {
        throwOutOfBounds(_pos + pos, _len);
    } else {
        _pos+=pos;
    }
}

void ByteBuffer::getNumeric(uint8_t & v) {
    if (__builtin_expect(getRemaining() < sizeof(v), 0)) {
        throwOutOfBounds(getRemaining(), sizeof(v));
    } else {
        v = *reinterpret_cast<const uint8_t *>(getBufferAtPos());
        incPosNoCheck(sizeof(v));
    }
}

void ByteBuffer::getNumericNetwork(int16_t & v) {
    if (__builtin_expect(getRemaining() < sizeof(v), 0)) {
        throwOutOfBounds(getRemaining(), sizeof(v));
    } else {
        uint16_t val;
        memcpy(&val, getBufferAtPos(), sizeof(val));
        v = ntohs(val);
        incPosNoCheck(sizeof(v));
    }
}

void ByteBuffer::getNumericNetwork(int32_t & v) {
    if (__builtin_expect(getRemaining() < sizeof(v), 0)) {
        throwOutOfBounds(getRemaining(), sizeof(v));
    } else {
        uint32_t val;
        memcpy(&val, getBufferAtPos(), sizeof(val));
        v = ntohl(val);
        incPosNoCheck(sizeof(v));
    }
}

void ByteBuffer::getNumeric(int64_t& v) {
    if (__builtin_expect(getRemaining() < sizeof(v), 0)) {
        throwOutOfBounds(getRemaining(), sizeof(v));
    } else {
        memcpy(&v, getBufferAtPos(), sizeof(v));
        incPosNoCheck(sizeof(v));
    }
}

void ByteBuffer::getNumericNetwork(double & v) {
    getDoubleLongNetwork(v);
}

void ByteBuffer::getNumericNetwork(int64_t & v) {
    getDoubleLongNetwork(v);
}

void ByteBuffer::getBytes(void *buffer, uint32_t count)
{
    const char *v = getBufferAtPos();
    incPos(count);
    memcpy(buffer, v, count);
}

} // document
<commit_msg>Remove zero termination.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
   @author Thomas F. Gundersen, �ystein Fledsberg
   @version $Id$
   @date 2004-03-15
*/

#include "bytebuffer.h"
#include "bufferexceptions.h"
#include "stringutil.h"
#include <vespa/vespalib/stllike/asciistream.h>
#include <sstream>
#include <arpa/inet.h>

using vespalib::alloc::Alloc;
using vespalib::make_string;

namespace document {

namespace {

static void throwOutOfBounds(size_t want, size_t has) __attribute__((noinline, noreturn));

void throwOutOfBounds(size_t want, size_t has)
{
    throw BufferOutOfBoundsException(want, has, VESPA_STRLOC);
}

}

#if defined(__i386__) || defined(__x86_64__)

template<typename T>
void
ByteBuffer::getDoubleLongNetwork(T &val) {
    //TODO: Change this if we move to big-endian hardware
    if (__builtin_expect(getRemaining() < (int)sizeof(T), 0)) {
        throwOutOfBounds(sizeof(T), getRemaining());
    }

    auto * data = reinterpret_cast<unsigned char*>(&val);
    for (int i=sizeof(T)-1; i>=0; --i) {
        getByte(data[i]);
    }
}

#else
#error "getDoubleLongNetwork is undefined for this arcitecture"
#endif

VESPA_IMPLEMENT_EXCEPTION_SPINE(BufferOutOfBoundsException);

vespalib::string BufferOutOfBoundsException::createMessage(size_t pos, size_t len) {
    vespalib::asciistream ost;
    ost << pos << " > " << len;
    return ost.str();
}

BufferOutOfBoundsException::BufferOutOfBoundsException(size_t pos, size_t len, const vespalib::string& location)
    : IoException(createMessage(pos, len), IoException::NO_SPACE, location, 1)
{
}

ByteBuffer::ByteBuffer(const char* buffer, uint32_t len) :
      _buffer(const_cast<char *>(buffer)),
      _len(len),
      _pos(0),
      _ownedBuffer()
{
}

ByteBuffer::ByteBuffer(Alloc buffer, uint32_t len) :
      _buffer(static_cast<char *>(buffer.get())),
      _len(len),
      _pos(0),
      _ownedBuffer(std::move(buffer))
{
}

ByteBuffer::ByteBuffer(const ByteBuffer& rhs) :
      _buffer(nullptr),
      _len(rhs._len),
      _pos(rhs._pos),
      _ownedBuffer()
{
    if (rhs._len > 0 && rhs._buffer) {
        Alloc buf = Alloc::alloc(rhs._len);
        memcpy(buf.get(), rhs._buffer, rhs._len);
        _ownedBuffer = std::move(buf);
        _buffer = static_cast<const char *>(_ownedBuffer.get());
    }
}

ByteBuffer::~ByteBuffer() = default;

ByteBuffer* ByteBuffer::copyBuffer(const char* buffer, uint32_t len)
{
    if (buffer && len) {
        Alloc newBuf = Alloc::alloc(len);
        memcpy(newBuf.get(), buffer, len);
        return new ByteBuffer(std::move(newBuf), len);
    } else {
        return nullptr;
    }
}

void ByteBuffer::incPos(uint32_t pos)
{
    if (_pos + pos > _len) {
        throwOutOfBounds(_pos + pos, _len);
    } else {
        _pos+=pos;
    }
}

void ByteBuffer::getNumeric(uint8_t & v) {
    if (__builtin_expect(getRemaining() < sizeof(v), 0)) {
        throwOutOfBounds(getRemaining(), sizeof(v));
    } else {
        v = *reinterpret_cast<const uint8_t *>(getBufferAtPos());
        incPosNoCheck(sizeof(v));
    }
}

void ByteBuffer::getNumericNetwork(int16_t & v) {
    if (__builtin_expect(getRemaining() < sizeof(v), 0)) {
        throwOutOfBounds(getRemaining(), sizeof(v));
    } else {
        uint16_t val;
        memcpy(&val, getBufferAtPos(), sizeof(val));
        v = ntohs(val);
        incPosNoCheck(sizeof(v));
    }
}

void ByteBuffer::getNumericNetwork(int32_t & v) {
    if (__builtin_expect(getRemaining() < sizeof(v), 0)) {
        throwOutOfBounds(getRemaining(), sizeof(v));
    } else {
        uint32_t val;
        memcpy(&val, getBufferAtPos(), sizeof(val));
        v = ntohl(val);
        incPosNoCheck(sizeof(v));
    }
}

void ByteBuffer::getNumeric(int64_t& v) {
    if (__builtin_expect(getRemaining() < sizeof(v), 0)) {
        throwOutOfBounds(getRemaining(), sizeof(v));
    } else {
        memcpy(&v, getBufferAtPos(), sizeof(v));
        incPosNoCheck(sizeof(v));
    }
}

void ByteBuffer::getNumericNetwork(double & v) {
    getDoubleLongNetwork(v);
}

void ByteBuffer::getNumericNetwork(int64_t & v) {
    getDoubleLongNetwork(v);
}

void ByteBuffer::getBytes(void *buffer, uint32_t count)
{
    const char *v = getBufferAtPos();
    incPos(count);
    memcpy(buffer, v, count);
}

} // document
<|endoftext|>


<commit_before>/*!
\file
	\brief
		Om source file.
	\version
		0.1.2
	\date
		2012-2013
	\copyright
		Copyright (c) Sparist.  All rights reserved.  This program and the accompanying materials are made available under the terms of the Eclipse Public License, Version 1.0, which accompanies this distribution.
	\authors
		Jason Erb - Initial API, implementation, and documentation.
*/

#if !defined( Om_ )

	#include "om.hpp"

	#if defined( Om_Macros_Test_ )

		#define BOOST_TEST_MODULE \
		OmTest

		#include <boost/test/included/unit_test.hpp>

bool init_unit_test() {
	Om::System::Get().Initialize( "en_US.UTF-8" );
	return( true );
}

	#else

/*!
\param theArgumentCount
	The argument count; must be greater than 0.
\param theArgumentArray
	The argument array contains (in order):
	-	The program invocation.
	-	(Optional) A valid UTF-8 locale string; defaults to "en_US.UTF-8".
*/
int main(
	int const theArgumentCount,
	char const * const theArgumentArray[]
) {
	assert( 0 < theArgumentCount );
	assert( theArgumentArray );

	Om::System::Get().Initialize(
		( 1 < theArgumentCount )?
		theArgumentArray[ 1 ]:
		"en_US.UTF-8"
	);

	typedef Om::Sources::StreamSource<> CodeUnitSource;
	CodeUnitSource theCodeUnitSource( std::cin );
	Om::Sources::CodePointSource< CodeUnitSource > theCodePointSource(
		theCodeUnitSource,
		CodeUnitSource()
	);

	typedef Om::Sinks::StreamSink<> CodeUnitSink;
	CodeUnitSink theCodeUnitSink( std::cout );
	Om::Sinks::CodePointSink< CodeUnitSink > theCodePointSink( theCodeUnitSink );

	Om::System::Get().Evaluate(
		theCodePointSource,
		theCodePointSink
	);

	return( EXIT_SUCCESS );
}

	#endif

#endif
<commit_msg>Moved test initialization to global fixture.<commit_after>/*!
\file
	\brief
		Om source file.
	\version
		0.1.2
	\date
		2012-2013
	\copyright
		Copyright (c) Sparist.  All rights reserved.  This program and the accompanying materials are made available under the terms of the Eclipse Public License, Version 1.0, which accompanies this distribution.
	\authors
		Jason Erb - Initial API, implementation, and documentation.
*/

#if !defined( Om_ )

	#include "om.hpp"

	#if defined( Om_Macros_Test_ )

		#define BOOST_TEST_MODULE \
		OmTest

		#include "boost/test/included/unit_test.hpp"

class OmFixture {
public:

	OmFixture() {
		Om::System::Get().Initialize( "en_US.UTF-8" );
	}

};

BOOST_GLOBAL_FIXTURE( OmFixture );

bool init_unit_test() {
	return( true );
}

	#else

/*!
\param theArgumentCount
	The argument count; must be greater than 0.
\param theArgumentArray
	The argument array contains (in order):
	-	The program invocation.
	-	(Optional) A valid UTF-8 locale string; defaults to "en_US.UTF-8".
*/
int main(
	int const theArgumentCount,
	char const * const theArgumentArray[]
) {
	assert( 0 < theArgumentCount );
	assert( theArgumentArray );

	Om::System::Get().Initialize(
		( 1 < theArgumentCount )?
		theArgumentArray[ 1 ]:
		"en_US.UTF-8"
	);

	typedef Om::Sources::StreamSource<> CodeUnitSource;
	CodeUnitSource theCodeUnitSource( std::cin );
	Om::Sources::CodePointSource< CodeUnitSource > theCodePointSource(
		theCodeUnitSource,
		CodeUnitSource()
	);

	typedef Om::Sinks::StreamSink<> CodeUnitSink;
	CodeUnitSink theCodeUnitSink( std::cout );
	Om::Sinks::CodePointSink< CodeUnitSink > theCodePointSink( theCodeUnitSink );

	Om::System::Get().Evaluate(
		theCodePointSource,
		theCodePointSink
	);

	return( EXIT_SUCCESS );
}

	#endif

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008, 2009, 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 "config.h"
#include "platform/fonts/SimpleFontData.h"

#include <unicode/normlzr.h>
#include "SkPaint.h"
#include "SkPath.h"
#include "SkTypeface.h"
#include "SkTypes.h"
#include "SkUtils.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/GlyphPage.h"
#include "platform/fonts/VDMXParser.h"
#include "platform/geometry/FloatRect.h"
#include "wtf/unicode/Unicode.h"

namespace blink {

// This is the largest VDMX table which we'll try to load and parse.
static const size_t maxVDMXTableSize = 1024 * 1024; // 1 MB

void SimpleFontData::platformInit()
{
    if (!m_platformData.size()) {
        m_fontMetrics.reset();
        m_avgCharWidth = 0;
        m_maxCharWidth = 0;
        return;
    }

    SkPaint paint;
    SkPaint::FontMetrics metrics;

    m_platformData.setupPaint(&paint);
    paint.getFontMetrics(&metrics);
    SkTypeface* face = paint.getTypeface();
    ASSERT(face);

    int vdmxAscent = 0, vdmxDescent = 0;
    bool isVDMXValid = false;

#if OS(LINUX) || OS(ANDROID)
    // Manually digging up VDMX metrics is only applicable when bytecode hinting using FreeType.
    // With GDI, the metrics will already have taken this into account (as needed).
    // With DirectWrite or CoreText, no bytecode hinting is ever done.
    // This code should be pushed into FreeType (hinted font metrics).
    static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
    int pixelSize = m_platformData.size() + 0.5;
    if (!paint.isAutohinted()
        &&    (paint.getHinting() == SkPaint::kFull_Hinting
            || paint.getHinting() == SkPaint::kNormal_Hinting))
    {
        size_t vdmxSize = face->getTableSize(vdmxTag);
        if (vdmxSize && vdmxSize < maxVDMXTableSize) {
            uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
            if (vdmxTable
                && face->getTableData(vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
                && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
                isVDMXValid = true;
            fastFree(vdmxTable);
        }
    }
#endif

    float ascent;
    float descent;

    // Beware those who step here: This code is designed to match Win32 font
    // metrics *exactly* (except the adjustment of ascent/descent on Linux/Android).
    if (isVDMXValid) {
        ascent = vdmxAscent;
        descent = -vdmxDescent;
    } else {
        ascent = SkScalarRoundToInt(-metrics.fAscent);
        descent = SkScalarRoundToInt(metrics.fDescent);
#if OS(LINUX) || OS(ANDROID)
        // When subpixel positioning is enabled, if the descent is rounded down, the descent part
        // of the glyph may be truncated when displayed in a 'overflow: hidden' container.
        // To avoid that, borrow 1 unit from the ascent when possible.
        // FIXME: This can be removed if sub-pixel ascent/descent is supported.
        if (platformData().fontRenderStyle().useSubpixelPositioning && descent < SkScalarToFloat(metrics.fDescent) && ascent >= 1) {
            ++descent;
            --ascent;
        }
#endif
    }

    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);

    float xHeight;
    if (metrics.fXHeight) {
        xHeight = metrics.fXHeight;
        m_fontMetrics.setXHeight(xHeight);
    } else {
        xHeight = ascent * 0.56; // Best guess from Windows font metrics.
        m_fontMetrics.setXHeight(xHeight);
        m_fontMetrics.setHasXHeight(false);
    }

    float lineGap = SkScalarToFloat(metrics.fLeading);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));

    SkScalar underlineThickness, underlinePosition;
    if (metrics.hasUnderlineThickness(&underlineThickness)
        && metrics.hasUnderlinePosition(&underlinePosition)) {
        m_fontMetrics.setUnderlineThickness(SkScalarToFloat(underlineThickness));
        m_fontMetrics.setUnderlinePosition(SkScalarToFloat(-underlinePosition));
    }

    if (platformData().orientation() == Vertical && !isTextOrientationFallback()) {
        static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
        static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
        size_t vheaSize = face->getTableSize(vheaTag);
        size_t vorgSize = face->getTableSize(vorgTag);
        if ((vheaSize > 0) || (vorgSize > 0))
            m_hasVerticalGlyphs = true;
    }

    // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
    // calculated for us, but we need to calculate m_maxCharWidth and
    // m_avgCharWidth in order for text entry widgets to be sized correctly.
#if OS(WIN)
    m_maxCharWidth = SkScalarRoundToInt(metrics.fMaxCharWidth);
#else
    // FIXME: This seems incorrect and should probably use fMaxCharWidth as
    // the code path above.
    SkScalar xRange = metrics.fXMax - metrics.fXMin;
    m_maxCharWidth = SkScalarRoundToInt(xRange * SkScalarRoundToInt(m_platformData.size()));
#endif

    if (metrics.fAvgCharWidth)
        m_avgCharWidth = SkScalarRoundToInt(metrics.fAvgCharWidth);
    else {
        m_avgCharWidth = xHeight;

        GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();

        if (glyphPageZero) {
            static const UChar32 xChar = 'x';
            const Glyph xGlyph = glyphPageZero->glyphForCharacter(xChar);

            if (xGlyph) {
                // In widthForGlyph(), xGlyph will be compared with
                // m_zeroWidthSpaceGlyph, which isn't initialized yet here.
                // Initialize it with zero to make sure widthForGlyph() returns
                // the right width.
                m_zeroWidthSpaceGlyph = 0;
                m_avgCharWidth = widthForGlyph(xGlyph);
            }
        }
    }

    if (int unitsPerEm = face->getUnitsPerEm())
        m_fontMetrics.setUnitsPerEm(unitsPerEm);
}

void SimpleFontData::platformCharWidthInit()
{
    // charwidths are set in platformInit.
}

void SimpleFontData::platformDestroy()
{
}

PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor);
    return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont() ? CustomFontData::create() : nullptr);
}

void SimpleFontData::determinePitch()
{
    m_treatAsFixedPitch = platformData().isFixedPitch();
}

static inline void getSkiaBoundsForGlyph(SkPaint& paint, Glyph glyph, SkRect& bounds)
{
    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);

    SkPath path;
    paint.getTextPath(&glyph, sizeof(glyph), 0, 0, &path);
    bounds = path.getBounds();

    if (!paint.isSubpixelText()) {
        SkIRect ir;
        bounds.round(&ir);
        bounds.set(ir);
    }
}

FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
{
    if (!m_platformData.size())
        return FloatRect();

    SkASSERT(sizeof(glyph) == 2); // compile-time assert

    SkPaint paint;
    m_platformData.setupPaint(&paint);

    SkRect bounds;
    getSkiaBoundsForGlyph(paint, glyph, bounds);
    return FloatRect(bounds);
}

float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
    if (!m_platformData.size())
        return 0;

    SkASSERT(sizeof(glyph) == 2); // compile-time assert

    SkPaint paint;

    m_platformData.setupPaint(&paint);

    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    SkScalar width = paint.measureText(&glyph, 2);
    if (!paint.isSubpixelText())
        width = SkScalarRoundToInt(width);
    return SkScalarToFloat(width);
}

#if USE(HARFBUZZ)
bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters, size_t length) const
{
    if (!m_combiningCharacterSequenceSupport)
        m_combiningCharacterSequenceSupport = adoptPtr(new HashMap<String, bool>);

    WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false);
    if (!addResult.isNewEntry)
        return addResult.storedValue->value;

    UErrorCode error = U_ZERO_ERROR;
    Vector<UChar, 4> normalizedCharacters(length);
    int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error);
    // Can't render if we have an error or no composition occurred.
    if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length))
        return false;

    SkPaint paint;
    m_platformData.setupPaint(&paint);
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    if (paint.textToGlyphs(&normalizedCharacters[0], normalizedLength * 2, 0)) {
        addResult.storedValue->value = true;
        return true;
    }
    return false;
}
#endif

bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const
{
    if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
        SkDebugf("%s last char is high-surrogate", __FUNCTION__);
        return false;
    }

    SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length);

    uint16_t* glyphs = glyphStorage.get();
    SkTypeface* typeface = platformData().typeface();
    typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length);

    bool haveGlyphs = false;
    for (unsigned i = 0; i < length; i++) {
        if (glyphs[i]) {
            pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
            haveGlyphs = true;
        }
    }

    return haveGlyphs;
}

} // namespace blink
<commit_msg>[Windows] Fall back on 2 x ascent if no max width is present <commit_after>/*
 * Copyright (c) 2008, 2009, 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 "config.h"
#include "platform/fonts/SimpleFontData.h"

#include <unicode/normlzr.h>
#include "SkPaint.h"
#include "SkPath.h"
#include "SkTypeface.h"
#include "SkTypes.h"
#include "SkUtils.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/GlyphPage.h"
#include "platform/fonts/VDMXParser.h"
#include "platform/geometry/FloatRect.h"
#include "wtf/unicode/Unicode.h"

namespace blink {

// This is the largest VDMX table which we'll try to load and parse.
static const size_t maxVDMXTableSize = 1024 * 1024; // 1 MB

void SimpleFontData::platformInit()
{
    if (!m_platformData.size()) {
        m_fontMetrics.reset();
        m_avgCharWidth = 0;
        m_maxCharWidth = 0;
        return;
    }

    SkPaint paint;
    SkPaint::FontMetrics metrics;

    m_platformData.setupPaint(&paint);
    paint.getFontMetrics(&metrics);
    SkTypeface* face = paint.getTypeface();
    ASSERT(face);

    int vdmxAscent = 0, vdmxDescent = 0;
    bool isVDMXValid = false;

#if OS(LINUX) || OS(ANDROID)
    // Manually digging up VDMX metrics is only applicable when bytecode hinting using FreeType.
    // With GDI, the metrics will already have taken this into account (as needed).
    // With DirectWrite or CoreText, no bytecode hinting is ever done.
    // This code should be pushed into FreeType (hinted font metrics).
    static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
    int pixelSize = m_platformData.size() + 0.5;
    if (!paint.isAutohinted()
        &&    (paint.getHinting() == SkPaint::kFull_Hinting
            || paint.getHinting() == SkPaint::kNormal_Hinting))
    {
        size_t vdmxSize = face->getTableSize(vdmxTag);
        if (vdmxSize && vdmxSize < maxVDMXTableSize) {
            uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
            if (vdmxTable
                && face->getTableData(vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
                && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
                isVDMXValid = true;
            fastFree(vdmxTable);
        }
    }
#endif

    float ascent;
    float descent;

    // Beware those who step here: This code is designed to match Win32 font
    // metrics *exactly* (except the adjustment of ascent/descent on Linux/Android).
    if (isVDMXValid) {
        ascent = vdmxAscent;
        descent = -vdmxDescent;
    } else {
        ascent = SkScalarRoundToInt(-metrics.fAscent);
        descent = SkScalarRoundToInt(metrics.fDescent);
#if OS(LINUX) || OS(ANDROID)
        // When subpixel positioning is enabled, if the descent is rounded down, the descent part
        // of the glyph may be truncated when displayed in a 'overflow: hidden' container.
        // To avoid that, borrow 1 unit from the ascent when possible.
        // FIXME: This can be removed if sub-pixel ascent/descent is supported.
        if (platformData().fontRenderStyle().useSubpixelPositioning && descent < SkScalarToFloat(metrics.fDescent) && ascent >= 1) {
            ++descent;
            --ascent;
        }
#endif
    }

    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);

    float xHeight;
    if (metrics.fXHeight) {
        xHeight = metrics.fXHeight;
        m_fontMetrics.setXHeight(xHeight);
    } else {
        xHeight = ascent * 0.56; // Best guess from Windows font metrics.
        m_fontMetrics.setXHeight(xHeight);
        m_fontMetrics.setHasXHeight(false);
    }

    float lineGap = SkScalarToFloat(metrics.fLeading);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));

    SkScalar underlineThickness, underlinePosition;
    if (metrics.hasUnderlineThickness(&underlineThickness)
        && metrics.hasUnderlinePosition(&underlinePosition)) {
        m_fontMetrics.setUnderlineThickness(SkScalarToFloat(underlineThickness));
        m_fontMetrics.setUnderlinePosition(SkScalarToFloat(-underlinePosition));
    }

    if (platformData().orientation() == Vertical && !isTextOrientationFallback()) {
        static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
        static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
        size_t vheaSize = face->getTableSize(vheaTag);
        size_t vorgSize = face->getTableSize(vorgTag);
        if ((vheaSize > 0) || (vorgSize > 0))
            m_hasVerticalGlyphs = true;
    }

    // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
    // calculated for us, but we need to calculate m_maxCharWidth and
    // m_avgCharWidth in order for text entry widgets to be sized correctly.
#if OS(WIN)
    m_maxCharWidth = SkScalarRoundToInt(metrics.fMaxCharWidth);

    // Older version of the DirectWrite API doesn't implement support for max
    // char width. Fall back on a multiple of the ascent. This is entirely
    // arbitrary but comes pretty close to the expected value in most cases.
    if (m_maxCharWidth < 1)
        m_maxCharWidth = ascent * 2;
#else
    // FIXME: This seems incorrect and should probably use fMaxCharWidth as
    // the code path above.
    SkScalar xRange = metrics.fXMax - metrics.fXMin;
    m_maxCharWidth = SkScalarRoundToInt(xRange * SkScalarRoundToInt(m_platformData.size()));
#endif

    if (metrics.fAvgCharWidth)
        m_avgCharWidth = SkScalarRoundToInt(metrics.fAvgCharWidth);
    else {
        m_avgCharWidth = xHeight;

        GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();

        if (glyphPageZero) {
            static const UChar32 xChar = 'x';
            const Glyph xGlyph = glyphPageZero->glyphForCharacter(xChar);

            if (xGlyph) {
                // In widthForGlyph(), xGlyph will be compared with
                // m_zeroWidthSpaceGlyph, which isn't initialized yet here.
                // Initialize it with zero to make sure widthForGlyph() returns
                // the right width.
                m_zeroWidthSpaceGlyph = 0;
                m_avgCharWidth = widthForGlyph(xGlyph);
            }
        }
    }

    if (int unitsPerEm = face->getUnitsPerEm())
        m_fontMetrics.setUnitsPerEm(unitsPerEm);
}

void SimpleFontData::platformCharWidthInit()
{
    // charwidths are set in platformInit.
}

void SimpleFontData::platformDestroy()
{
}

PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor);
    return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont() ? CustomFontData::create() : nullptr);
}

void SimpleFontData::determinePitch()
{
    m_treatAsFixedPitch = platformData().isFixedPitch();
}

static inline void getSkiaBoundsForGlyph(SkPaint& paint, Glyph glyph, SkRect& bounds)
{
    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);

    SkPath path;
    paint.getTextPath(&glyph, sizeof(glyph), 0, 0, &path);
    bounds = path.getBounds();

    if (!paint.isSubpixelText()) {
        SkIRect ir;
        bounds.round(&ir);
        bounds.set(ir);
    }
}

FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
{
    if (!m_platformData.size())
        return FloatRect();

    SkASSERT(sizeof(glyph) == 2); // compile-time assert

    SkPaint paint;
    m_platformData.setupPaint(&paint);

    SkRect bounds;
    getSkiaBoundsForGlyph(paint, glyph, bounds);
    return FloatRect(bounds);
}

float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
    if (!m_platformData.size())
        return 0;

    SkASSERT(sizeof(glyph) == 2); // compile-time assert

    SkPaint paint;

    m_platformData.setupPaint(&paint);

    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    SkScalar width = paint.measureText(&glyph, 2);
    if (!paint.isSubpixelText())
        width = SkScalarRoundToInt(width);
    return SkScalarToFloat(width);
}

#if USE(HARFBUZZ)
bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters, size_t length) const
{
    if (!m_combiningCharacterSequenceSupport)
        m_combiningCharacterSequenceSupport = adoptPtr(new HashMap<String, bool>);

    WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false);
    if (!addResult.isNewEntry)
        return addResult.storedValue->value;

    UErrorCode error = U_ZERO_ERROR;
    Vector<UChar, 4> normalizedCharacters(length);
    int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error);
    // Can't render if we have an error or no composition occurred.
    if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length))
        return false;

    SkPaint paint;
    m_platformData.setupPaint(&paint);
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    if (paint.textToGlyphs(&normalizedCharacters[0], normalizedLength * 2, 0)) {
        addResult.storedValue->value = true;
        return true;
    }
    return false;
}
#endif

bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const
{
    if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
        SkDebugf("%s last char is high-surrogate", __FUNCTION__);
        return false;
    }

    SkAutoSTMalloc<GlyphPage::size, uint16_t> glyphStorage(length);

    uint16_t* glyphs = glyphStorage.get();
    SkTypeface* typeface = platformData().typeface();
    typeface->charsToGlyphs(buffer, SkTypeface::kUTF16_Encoding, glyphs, length);

    bool haveGlyphs = false;
    for (unsigned i = 0; i < length; i++) {
        if (glyphs[i]) {
            pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
            haveGlyphs = true;
        }
    }

    return haveGlyphs;
}

} // namespace blink
<|endoftext|>


<commit_before>// This code is based on Sabberstone project.
// Copyright (c) 2017-2018 SabberStone Team, darkfriend77 & rnilva
// Hearthstone++ is hearthstone simulator using C++ with reinforcement learning.
// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

#include <hspp/Tasks/SimpleTasks/ModifyManaTask.hpp>

namespace Hearthstonepp::SimpleTasks
{
ModifyManaTask::ModifyManaTask(ManaOperator numMode, ManaType manaMode,
                               BYTE num)
    : m_numMode(numMode), m_manaMode(manaMode), m_num(num)
{
    // Do nothing
}

TaskID ModifyManaTask::GetTaskID() const
{
    return TaskID::MODIFY_MANA;
}

TaskStatus ModifyManaTask::Impl(Player& player)
{
    const auto getMana = [](Player& p, ManaType mode) -> BYTE {
        if (mode == ManaType::AVAILABLE)
        {
            return p.GetAvailableMana();
        }

        if (mode == ManaType::MAXIMUM)
        {
            return p.GetMaximumMana();
        }

        throw std::runtime_error("ModifyMana: Invalid mana mode");
    };

    BYTE mana = getMana(player, m_manaMode);
    switch (m_numMode)
    {
        case ManaOperator::ADD:
            mana += m_num;
            break;
        case ManaOperator::SUB:
            mana = (mana <= m_num) ? 0 : (mana - m_num);
            break;
        case ManaOperator::SET:
            mana = m_num;
            break;
    }

    // Clamps a mana cost to a given range (min:0 ~ max:10)
    mana = std::clamp(mana, static_cast<BYTE>(0), static_cast<BYTE>(10));

    if (m_manaMode == ManaType::AVAILABLE)
    {
        player.SetAvailableMana(mana);
    }

    if (m_manaMode == ManaType::MAXIMUM)
    {
        player.SetMaximumMana(mana);
    }

    return TaskStatus::MODIFY_MANA_SUCCESS;
}
}  // namespace Hearthstonepp::SimpleTasks<commit_msg>fix: Add missing <algorithm> header for std::clamp<commit_after>// This code is based on Sabberstone project.
// Copyright (c) 2017-2018 SabberStone Team, darkfriend77 & rnilva
// Hearthstone++ is hearthstone simulator using C++ with reinforcement learning.
// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

#include <hspp/Tasks/SimpleTasks/ModifyManaTask.hpp>

#include <algorithm>

namespace Hearthstonepp::SimpleTasks
{
ModifyManaTask::ModifyManaTask(ManaOperator numMode, ManaType manaMode,
                               BYTE num)
    : m_numMode(numMode), m_manaMode(manaMode), m_num(num)
{
    // Do nothing
}

TaskID ModifyManaTask::GetTaskID() const
{
    return TaskID::MODIFY_MANA;
}

TaskStatus ModifyManaTask::Impl(Player& player)
{
    const auto getMana = [](Player& p, ManaType mode) -> BYTE {
        if (mode == ManaType::AVAILABLE)
        {
            return p.GetAvailableMana();
        }

        if (mode == ManaType::MAXIMUM)
        {
            return p.GetMaximumMana();
        }

        throw std::runtime_error("ModifyMana: Invalid mana mode");
    };

    BYTE mana = getMana(player, m_manaMode);
    switch (m_numMode)
    {
        case ManaOperator::ADD:
            mana += m_num;
            break;
        case ManaOperator::SUB:
            mana = (mana <= m_num) ? 0 : (mana - m_num);
            break;
        case ManaOperator::SET:
            mana = m_num;
            break;
    }

    // Clamps a mana cost to a given range (min:0 ~ max:10)
    mana = std::clamp(mana, static_cast<BYTE>(0), static_cast<BYTE>(10));

    if (m_manaMode == ManaType::AVAILABLE)
    {
        player.SetAvailableMana(mana);
    }

    if (m_manaMode == ManaType::MAXIMUM)
    {
        player.SetMaximumMana(mana);
    }

    return TaskStatus::MODIFY_MANA_SUCCESS;
}
}  // namespace Hearthstonepp::SimpleTasks<|endoftext|>


<commit_before>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2001, 2002, 2003, 2004, 2005 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <lac/compressed_sparsity_pattern.h>

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <numeric>
#include <functional>

const unsigned int CompressedSparsityPattern::Line::cache_size;

// This function was originally inlined, because it was called very
// often without any need, because cache_entries==0. Onn the other
// hand, it is very long and causes linker warnings on certain
// systems.

// Therefore, we require now, that the caller checks if this function
// is necessary and only calls it, if it is actually used. Since it is
// it called less often, it ies removed from the inlined section.
void
CompressedSparsityPattern::Line::flush_cache () const
{
                                   // Make sure the caller checked
                                   // necessity of this function.
  Assert(cache_entries != 0, ExcInternalError());

                                   // first sort the entries in the cache, so
                                   // that it is easier to merge it with the
                                   // main array. note that due to the way
                                   // add() inserts elements, there can be no
                                   // duplicates in the cache
                                   //
                                   // do the sorting in a way that is fast for
                                   // the small cache sizes we have
                                   // here. basically, use bubble sort
  switch (cache_entries)
    {
      case 1:
      {
        break;
      }

      case 2:
      {
        if (cache[1] < cache[0])
          std::swap (cache[0], cache[1]);
        break;
      }

      case 3:
      {
        if (cache[1] < cache[0])
          std::swap (cache[0], cache[1]);
        if (cache[2] < cache[1])
          std::swap (cache[1], cache[2]);
        if (cache[1] < cache[0])
          std::swap (cache[0], cache[1]);
        break;
      }

      case 4:
      case 5:
      case 6:
      case 7:
      {
        for (unsigned int i=0; i<cache_entries; ++i)
          for (unsigned int j=i+1; j<cache_entries; ++j)
            if (cache[j] < cache[i])
              std::swap (cache[i], cache[j]);
        break;
      }

      default:
      {
        std::sort (&cache[0], &cache[cache_entries]);
        break;
      }
    }

                                   // next job is to merge the two
                                   // arrays. special case the case that the
                                   // original array is empty.
  if (entries.size() == 0)
    {
      entries.resize (cache_entries);
      for (unsigned int i=0; i<cache_entries; ++i)
        entries[i] = cache[i];
    }
  else
    {
                                       // first count how many of the cache
                                       // entries are already in the main
                                       // array, so that we can efficiently
                                       // allocate memory
      unsigned int n_new_entries = 0;
      {
        unsigned int cache_position = 0;
        unsigned int entry_position = 0;
        while ((entry_position<entries.size()) &&
               (cache_position<cache_entries))
          {
            ++n_new_entries;
            if (entries[entry_position] < cache[cache_position])
              ++entry_position;
            else if (entries[entry_position] == cache[cache_position])
              {
                ++entry_position;
                ++cache_position;
              }
            else
              ++cache_position;
          }

                                         // scoop up leftovers in arrays
        n_new_entries += (entries.size() - entry_position) +
                         (cache_entries - cache_position);
      }

                                       // then allocate new memory and merge
                                       // arrays
      std::vector<unsigned int> new_entries;
      new_entries.reserve (n_new_entries);
      unsigned int cache_position = 0;
      unsigned int entry_position = 0;
      while ((entry_position<entries.size()) && (cache_position<cache_entries))
        if (entries[entry_position] < cache[cache_position])
          {
            new_entries.push_back (entries[entry_position]);
            ++entry_position;
          }
        else if (entries[entry_position] == cache[cache_position])
          {
            new_entries.push_back (entries[entry_position]);
            ++entry_position;
            ++cache_position;
          }
        else
          {
            new_entries.push_back (cache[cache_position]);
            ++cache_position;
          }

                                       // copy remaining elements from the
                                       // array that we haven't finished. note
                                       // that at most one of the following
                                       // loops will run at all
      for (; entry_position < entries.size(); ++entry_position)
        new_entries.push_back (entries[entry_position]);
      for (; cache_position < cache_entries; ++cache_position)
        new_entries.push_back (cache[cache_position]);

      Assert (new_entries.size() == n_new_entries,
              ExcInternalError());

                                       // finally swap old and new array, and
                                       // set cache size to zero
      new_entries.swap (entries);
    }

  cache_entries = 0;
}

CompressedSparsityPattern::CompressedSparsityPattern ()
                :
		rows(0),
		cols(0)
{}

CompressedSparsityPattern::
CompressedSparsityPattern (const CompressedSparsityPattern &s)
                :
		Subscriptor(),
		rows(0),
		cols(0)
{
  Assert (s.rows == 0, ExcInvalidConstructorCall());
  Assert (s.cols == 0, ExcInvalidConstructorCall());
}

CompressedSparsityPattern::CompressedSparsityPattern (const unsigned int m,
						      const unsigned int n)
		:
                rows(0),
                cols(0)
{
  reinit (m,n);
}

CompressedSparsityPattern::CompressedSparsityPattern (const unsigned int n)
		:
                rows(0),
                cols(0)
{
  reinit (n,n);
}

CompressedSparsityPattern &
CompressedSparsityPattern::operator = (const CompressedSparsityPattern &s)
{
  Assert (s.rows == 0, ExcInvalidConstructorCall());
  Assert (s.cols == 0, ExcInvalidConstructorCall());

  Assert (rows == 0, ExcInvalidConstructorCall());
  Assert (cols == 0, ExcInvalidConstructorCall());

  return *this;
}

void
CompressedSparsityPattern::reinit (const unsigned int m,
				   const unsigned int n)
{
  rows = m;
  cols = n;

  std::vector<Line> new_lines (rows);
  lines.swap (new_lines);
}

void
CompressedSparsityPattern::compress ()
{}

bool
CompressedSparsityPattern::empty () const
{
  return ((rows==0) && (cols==0));
}

unsigned int
CompressedSparsityPattern::max_entries_per_row () const
{
  unsigned int m = 0;
  for (unsigned int i=0; i<rows; ++i)
    {
      lines[i].flush_cache ();
      m = std::max (m, static_cast<unsigned int>(lines[i].entries.size()));
    }

  return m;
}

bool
CompressedSparsityPattern::exists (const unsigned int i,
				   const unsigned int j) const
{
  Assert (i<rows, ExcIndexRange(i, 0, rows));
  Assert (j<cols, ExcIndexRange(j, 0, cols));

  lines[i].flush_cache();
  return std::binary_search (lines[i].entries.begin(),
                             lines[i].entries.end(),
                             j);
}

void
CompressedSparsityPattern::symmetrize ()
{
  Assert (rows==cols, ExcNotQuadratic());

				   // loop over all elements presently
				   // in the sparsity pattern and add
				   // the transpose element. note:
				   //
				   // 1. that the sparsity pattern
				   // changes which we work on, but
				   // not the present row
				   //
				   // 2. that the @p{add} function can
				   // be called on elements that
				   // already exist without any harm
  for (unsigned int row=0; row<rows; ++row)
    {
      lines[row].flush_cache ();
      for (std::vector<unsigned int>::const_iterator
             j=lines[row].entries.begin();
           j != lines[row].entries.end();
           ++j)
				       // add the transpose entry if
				       // this is not the diagonal
        if (row != *j)
          add (*j, row);
    }
}

void
CompressedSparsityPattern::print_gnuplot (std::ostream &out) const
{
  for (unsigned int row=0; row<rows; ++row)
    {
      lines[row].flush_cache ();
      for (std::vector<unsigned int>::const_iterator
             j=lines[row].entries.begin();
           j != lines[row].entries.end(); ++j)
                                         // while matrix entries are usually
                                         // written (i,j), with i vertical and
                                         // j horizontal, gnuplot output is
                                         // x-y, that is we have to exchange
                                         // the order of output
        out << *j << " " << -static_cast<signed int>(row) << std::endl;
    }

  AssertThrow (out, ExcIO());
}

unsigned int
CompressedSparsityPattern::bandwidth () const
{
  unsigned int b=0;
  for (unsigned int row=0; row<rows; ++row)
    {
      lines[row].flush_cache ();

      for (std::vector<unsigned int>::const_iterator
             j=lines[row].entries.begin();
           j != lines[row].entries.end(); ++j)
        if (static_cast<unsigned int>(std::abs(static_cast<int>(row-*j))) > b)
          b = std::abs(static_cast<signed int>(row-*j));
    }

  return b;
}

unsigned int
CompressedSparsityPattern::n_nonzero_elements () const
{
  unsigned int n=0;
  for (unsigned int i=0; i<rows; ++i)
    {
      lines[i].flush_cache ();
      n += lines[i].entries.size();
    }

  return n;
}
<commit_msg>add missing checks for empty cache<commit_after>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2001, 2002, 2003, 2004, 2005 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <lac/compressed_sparsity_pattern.h>

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <numeric>
#include <functional>

const unsigned int CompressedSparsityPattern::Line::cache_size;

// This function was originally inlined, because it was called very
// often without any need, because cache_entries==0. Onn the other
// hand, it is very long and causes linker warnings on certain
// systems.

// Therefore, we require now, that the caller checks if this function
// is necessary and only calls it, if it is actually used. Since it is
// it called less often, it ies removed from the inlined section.
void
CompressedSparsityPattern::Line::flush_cache () const
{
                                   // Make sure the caller checked
                                   // necessity of this function.
  Assert(cache_entries != 0, ExcInternalError());

                                   // first sort the entries in the cache, so
                                   // that it is easier to merge it with the
                                   // main array. note that due to the way
                                   // add() inserts elements, there can be no
                                   // duplicates in the cache
                                   //
                                   // do the sorting in a way that is fast for
                                   // the small cache sizes we have
                                   // here. basically, use bubble sort
  switch (cache_entries)
    {
      case 1:
      {
        break;
      }

      case 2:
      {
        if (cache[1] < cache[0])
          std::swap (cache[0], cache[1]);
        break;
      }

      case 3:
      {
        if (cache[1] < cache[0])
          std::swap (cache[0], cache[1]);
        if (cache[2] < cache[1])
          std::swap (cache[1], cache[2]);
        if (cache[1] < cache[0])
          std::swap (cache[0], cache[1]);
        break;
      }

      case 4:
      case 5:
      case 6:
      case 7:
      {
        for (unsigned int i=0; i<cache_entries; ++i)
          for (unsigned int j=i+1; j<cache_entries; ++j)
            if (cache[j] < cache[i])
              std::swap (cache[i], cache[j]);
        break;
      }

      default:
      {
        std::sort (&cache[0], &cache[cache_entries]);
        break;
      }
    }

                                   // next job is to merge the two
                                   // arrays. special case the case that the
                                   // original array is empty.
  if (entries.size() == 0)
    {
      entries.resize (cache_entries);
      for (unsigned int i=0; i<cache_entries; ++i)
        entries[i] = cache[i];
    }
  else
    {
                                       // first count how many of the cache
                                       // entries are already in the main
                                       // array, so that we can efficiently
                                       // allocate memory
      unsigned int n_new_entries = 0;
      {
        unsigned int cache_position = 0;
        unsigned int entry_position = 0;
        while ((entry_position<entries.size()) &&
               (cache_position<cache_entries))
          {
            ++n_new_entries;
            if (entries[entry_position] < cache[cache_position])
              ++entry_position;
            else if (entries[entry_position] == cache[cache_position])
              {
                ++entry_position;
                ++cache_position;
              }
            else
              ++cache_position;
          }

                                         // scoop up leftovers in arrays
        n_new_entries += (entries.size() - entry_position) +
                         (cache_entries - cache_position);
      }

                                       // then allocate new memory and merge
                                       // arrays
      std::vector<unsigned int> new_entries;
      new_entries.reserve (n_new_entries);
      unsigned int cache_position = 0;
      unsigned int entry_position = 0;
      while ((entry_position<entries.size()) && (cache_position<cache_entries))
        if (entries[entry_position] < cache[cache_position])
          {
            new_entries.push_back (entries[entry_position]);
            ++entry_position;
          }
        else if (entries[entry_position] == cache[cache_position])
          {
            new_entries.push_back (entries[entry_position]);
            ++entry_position;
            ++cache_position;
          }
        else
          {
            new_entries.push_back (cache[cache_position]);
            ++cache_position;
          }

                                       // copy remaining elements from the
                                       // array that we haven't finished. note
                                       // that at most one of the following
                                       // loops will run at all
      for (; entry_position < entries.size(); ++entry_position)
        new_entries.push_back (entries[entry_position]);
      for (; cache_position < cache_entries; ++cache_position)
        new_entries.push_back (cache[cache_position]);

      Assert (new_entries.size() == n_new_entries,
              ExcInternalError());

                                       // finally swap old and new array, and
                                       // set cache size to zero
      new_entries.swap (entries);
    }

  cache_entries = 0;
}

CompressedSparsityPattern::CompressedSparsityPattern ()
                :
		rows(0),
		cols(0)
{}

CompressedSparsityPattern::
CompressedSparsityPattern (const CompressedSparsityPattern &s)
                :
		Subscriptor(),
		rows(0),
		cols(0)
{
  Assert (s.rows == 0, ExcInvalidConstructorCall());
  Assert (s.cols == 0, ExcInvalidConstructorCall());
}

CompressedSparsityPattern::CompressedSparsityPattern (const unsigned int m,
						      const unsigned int n)
		:
                rows(0),
                cols(0)
{
  reinit (m,n);
}

CompressedSparsityPattern::CompressedSparsityPattern (const unsigned int n)
		:
                rows(0),
                cols(0)
{
  reinit (n,n);
}

CompressedSparsityPattern &
CompressedSparsityPattern::operator = (const CompressedSparsityPattern &s)
{
  Assert (s.rows == 0, ExcInvalidConstructorCall());
  Assert (s.cols == 0, ExcInvalidConstructorCall());

  Assert (rows == 0, ExcInvalidConstructorCall());
  Assert (cols == 0, ExcInvalidConstructorCall());

  return *this;
}

void
CompressedSparsityPattern::reinit (const unsigned int m,
				   const unsigned int n)
{
  rows = m;
  cols = n;

  std::vector<Line> new_lines (rows);
  lines.swap (new_lines);
}

void
CompressedSparsityPattern::compress ()
{}

bool
CompressedSparsityPattern::empty () const
{
  return ((rows==0) && (cols==0));
}

unsigned int
CompressedSparsityPattern::max_entries_per_row () const
{
  unsigned int m = 0;
  for (unsigned int i=0; i<rows; ++i)
    {
      if (lines[i].cache_entries != 0)
	lines[i].flush_cache ();
      m = std::max (m, static_cast<unsigned int>(lines[i].entries.size()));
    }

  return m;
}

bool
CompressedSparsityPattern::exists (const unsigned int i,
				   const unsigned int j) const
{
  Assert (i<rows, ExcIndexRange(i, 0, rows));
  Assert (j<cols, ExcIndexRange(j, 0, cols));

  if (lines[i].cache_entries != 0)
    lines[i].flush_cache();
  return std::binary_search (lines[i].entries.begin(),
                             lines[i].entries.end(),
                             j);
}

void
CompressedSparsityPattern::symmetrize ()
{
  Assert (rows==cols, ExcNotQuadratic());

				   // loop over all elements presently
				   // in the sparsity pattern and add
				   // the transpose element. note:
				   //
				   // 1. that the sparsity pattern
				   // changes which we work on, but
				   // not the present row
				   //
				   // 2. that the @p{add} function can
				   // be called on elements that
				   // already exist without any harm
  for (unsigned int row=0; row<rows; ++row)
    {
      if (lines[row].cache_entries != 0)
	lines[row].flush_cache ();
      for (std::vector<unsigned int>::const_iterator
             j=lines[row].entries.begin();
           j != lines[row].entries.end();
           ++j)
				       // add the transpose entry if
				       // this is not the diagonal
        if (row != *j)
          add (*j, row);
    }
}

void
CompressedSparsityPattern::print_gnuplot (std::ostream &out) const
{
  for (unsigned int row=0; row<rows; ++row)
    {
      if (lines[row].cache_entries != 0)
	lines[row].flush_cache ();
      for (std::vector<unsigned int>::const_iterator
             j=lines[row].entries.begin();
           j != lines[row].entries.end(); ++j)
                                         // while matrix entries are usually
                                         // written (i,j), with i vertical and
                                         // j horizontal, gnuplot output is
                                         // x-y, that is we have to exchange
                                         // the order of output
        out << *j << " " << -static_cast<signed int>(row) << std::endl;
    }

  AssertThrow (out, ExcIO());
}

unsigned int
CompressedSparsityPattern::bandwidth () const
{
  unsigned int b=0;
  for (unsigned int row=0; row<rows; ++row)
    {
      if (lines[row].cache_entries != 0)
	lines[row].flush_cache ();

      for (std::vector<unsigned int>::const_iterator
             j=lines[row].entries.begin();
           j != lines[row].entries.end(); ++j)
        if (static_cast<unsigned int>(std::abs(static_cast<int>(row-*j))) > b)
          b = std::abs(static_cast<signed int>(row-*j));
    }

  return b;
}

unsigned int
CompressedSparsityPattern::n_nonzero_elements () const
{
  unsigned int n=0;
  for (unsigned int i=0; i<rows; ++i)
    {
      if (lines[i].cache_entries != 0)
	lines[i].flush_cache ();
      n += lines[i].entries.size();
    }

  return n;
}
<|endoftext|>