<commit_before>
// This file is part of lipstick, a QML desktop library
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation
// and appearing in the file LICENSE.LGPL included in the packaging
// of this file.
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// Copyright (c) 2011, Robin Burchell
// Copyright (c) 2012, Timur Kristóf <venemo@fedoraproject.org>

#include <QDebug>
#include <QProcess>
#include <QFile>
#include <QDir>
#include <QSettings>
#include <mlite/mdesktopentry.h>

#ifdef HAS_CONTENTACTION
#include <contentaction.h>
#endif

#include "launcheritem.h"

static QString findIconHelper(const QString &pathName, const QString &icon)
{
    QStringList extensions;
    extensions << "";
    extensions << ".png";
    extensions << ".svg";
//    qDebug() << "Trying " << pathName << " for " << icon;

    foreach (const QString &extension, extensions) {
        if (QFile::exists(pathName + QDir::separator() + icon + extension))
            return pathName + QDir::separator() + icon + extension;
    }

    QStringList entryList = QDir(pathName).entryList(QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot);
    foreach (const QString &dir, entryList) {
        QString retval = findIconHelper(QDir(pathName).absoluteFilePath(dir), icon);
        if (!retval.isNull())
            return retval;
    }

    // all else failed
    return QString();
}

static QString getIconPath(const QString &name)
{
    if (QFile::exists(name)) {
        // fast path: file given
        return name;
    }

    QSettings settings("MeeGo", "IconCache");
    QString cachedPath = settings.value(name).toString();

    if (!QFile::exists(cachedPath)) {
        qDebug() << Q_FUNC_INFO << "Negative cache hit for " << name << " to " << cachedPath;
    } else {
        return cachedPath;
    }

    QStringList themes = QDir("/usr/share/themes").entryList(QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot);
    if (themes.isEmpty())
        return QString();

    // TODO: look up active theme in gconf and set it to the first search path, don't hardcode it.
    // TODO: would be nice to investigate if our fallback behaviour is actually correct, too, but meh.
    if (themes.contains("n900de") &&
        themes.at(0) != "n900de") {
        themes.removeAll("n900de");
        themes.insert(0, "n900de");
    }

    foreach (const QString &theme, themes) {
        QString retval = findIconHelper("/usr/share/themes/" + theme, name);
        if (!retval.isNull()) {
            settings.setValue(name, retval);
            return retval;
        }
    }

    // they also seem to get plonked here
    QString retval = findIconHelper("/usr/share/pixmaps/", name);
    if (!retval.isNull()) {
        settings.setValue(name, retval);
        return retval;
    }

    // I hate all application developers
    retval = findIconHelper("/usr/share/icons/hicolor/64x64/", name);
    if (!retval.isNull()) {
        settings.setValue(name, retval);
        return retval;
    }

    return QString();
}

LauncherItem::LauncherItem(const QString &path, QObject *parent)
    : QObject(parent),
      _desktopEntry(new MDesktopEntry(path))
{
    emit this->itemChanged();
}

LauncherItem::~LauncherItem()
{
    delete _desktopEntry;
}

QString LauncherItem::filePath() const
{
    return _desktopEntry->fileName();
}

QString LauncherItem::title() const
{
    return _desktopEntry->name();
}

QString LauncherItem::entryType() const
{
    return _desktopEntry->type();
}

QString LauncherItem::iconFilePath() const
{
    return "file://" + getIconPath(_desktopEntry->icon());
}

QStringList LauncherItem::desktopCategories() const
{
    return _desktopEntry->categories();
}

bool LauncherItem::shouldDisplay() const
{
    return !_desktopEntry->noDisplay();
}

bool LauncherItem::isValid() const
{
    return _desktopEntry->isValid();
}

void LauncherItem::launchApplication() const
{
#if defined(HAVE_CONTENTACTION)
    ContentAction::Action action = ContentAction::Action::launcherAction(m_entry, QStringList());
    action.trigger();
#else
    // Get the command text from the desktop entry
    QString commandText = _desktopEntry->exec();

    // Take care of the freedesktop standards things

    commandText.replace(QRegExp("%k"), filePath());
    commandText.replace(QRegExp("%c"), _desktopEntry->name());
    commandText.remove(QRegExp("%[fFuU]"));

    if (!_desktopEntry->icon().isEmpty())
        commandText.replace(QRegExp("%i"), QString("--icon ") + _desktopEntry->icon());

    // DETAILS: http://standards.freedesktop.org/desktop-entry-spec/latest/index.html
    // DETAILS: http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s06.html

    // Launch the application
    QProcess::startDetached(commandText);
#endif
}
<commit_msg>Icon path will not be returned unless it really exists.<commit_after>
// This file is part of lipstick, a QML desktop library
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation
// and appearing in the file LICENSE.LGPL included in the packaging
// of this file.
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// Copyright (c) 2011, Robin Burchell
// Copyright (c) 2012, Timur Kristóf <venemo@fedoraproject.org>

#include <QDebug>
#include <QProcess>
#include <QFile>
#include <QDir>
#include <QSettings>
#include <mlite/mdesktopentry.h>

#ifdef HAS_CONTENTACTION
#include <contentaction.h>
#endif

#include "launcheritem.h"

static QString findIconHelper(const QString &pathName, const QString &icon)
{
    QStringList extensions;
    extensions << "";
    extensions << ".png";
    extensions << ".svg";
    //    qDebug() << "Trying " << pathName << " for " << icon;

    foreach (const QString &extension, extensions) {
        if (QFile::exists(pathName + QDir::separator() + icon + extension))
            return pathName + QDir::separator() + icon + extension;
    }

    QStringList entryList = QDir(pathName).entryList(QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot);
    foreach (const QString &dir, entryList) {
        QString retval = findIconHelper(QDir(pathName).absoluteFilePath(dir), icon);
        if (!retval.isNull())
            return retval;
    }

    // all else failed
    return QString();
}

static QString getIconPath(const QString &name)
{
    if (QFile::exists(name)) {
        // fast path: file given
        return name;
    }

    QSettings settings("MeeGo", "IconCache");
    QString cachedPath = settings.value(name).toString();

    if (!QFile::exists(cachedPath))
    {
        qDebug() << Q_FUNC_INFO << "Negative cache hit for " << name << " to " << cachedPath;
    }
    else
    {
        return cachedPath;
    }

    QStringList themes = QDir("/usr/share/themes").entryList(QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot);
    if (!themes.isEmpty())
    {
        // TODO: look up active theme in gconf and set it to the first search path, don't hardcode it.
        // TODO: would be nice to investigate if our fallback behaviour is actually correct, too, but meh.

        if (themes.contains("n900de") && themes.at(0) != "n900de")
        {
            themes.removeAll("n900de");
            themes.insert(0, "n900de");
        }

        foreach (const QString &theme, themes)
        {
            QString retval = findIconHelper("/usr/share/themes/" + theme, name);

            if (!retval.isNull())
            {
                if (QFile::exists(retval))
                {
                    settings.setValue(name, retval);
                    return retval;
                }
            }
        }
    }

    // they also seem to get plonked here
    QString retval = findIconHelper("/usr/share/pixmaps/", name);

    if (!retval.isNull())
    {
        if (QFile::exists(retval))
        {
            settings.setValue(name, retval);
            return retval;
        }
    }

    // I hate all application developers
    retval = findIconHelper("/usr/share/icons/hicolor/64x64/", name);

    if (!retval.isNull())
    {
        if (QFile::exists(retval))
        {
            settings.setValue(name, retval);
            return retval;
        }
    }

    return QString();
}

LauncherItem::LauncherItem(const QString &path, QObject *parent)
    : QObject(parent),
      _desktopEntry(new MDesktopEntry(path))
{
    emit this->itemChanged();
}

LauncherItem::~LauncherItem()
{
    delete _desktopEntry;
}

QString LauncherItem::filePath() const
{
    return _desktopEntry->fileName();
}

QString LauncherItem::title() const
{
    return _desktopEntry->name();
}

QString LauncherItem::entryType() const
{
    return _desktopEntry->type();
}

QString LauncherItem::iconFilePath() const
{
    return "file://" + getIconPath(_desktopEntry->icon());
}

QStringList LauncherItem::desktopCategories() const
{
    return _desktopEntry->categories();
}

bool LauncherItem::shouldDisplay() const
{
    return !_desktopEntry->noDisplay();
}

bool LauncherItem::isValid() const
{
    return _desktopEntry->isValid();
}

void LauncherItem::launchApplication() const
{
#if defined(HAVE_CONTENTACTION)
    ContentAction::Action action = ContentAction::Action::launcherAction(m_entry, QStringList());
    action.trigger();
#else
    // Get the command text from the desktop entry
    QString commandText = _desktopEntry->exec();

    // Take care of the freedesktop standards things

    commandText.replace(QRegExp("%k"), filePath());
    commandText.replace(QRegExp("%c"), _desktopEntry->name());
    commandText.remove(QRegExp("%[fFuU]"));

    if (!_desktopEntry->icon().isEmpty())
        commandText.replace(QRegExp("%i"), QString("--icon ") + _desktopEntry->icon());

    // DETAILS: http://standards.freedesktop.org/desktop-entry-spec/latest/index.html
    // DETAILS: http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s06.html

    // Launch the application
    QProcess::startDetached(commandText);
#endif
}
<|endoftext|>


<commit_before>// Modified from chromium/src/webkit/glue/gl_bindings_skia_cmd_buffer.cc

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

#include "gl/GrGLInterface.h"

#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

const GrGLInterface* GrGLCreateNativeInterface() {
    static SkAutoTUnref<GrGLInterface> glInterface;
    if (!glInterface.get()) {
        GrGLInterface* interface = new GrGLInterface;
        glInterface.reset(interface);
        interface->fBindingsExported = kES2_GrGLBinding;
        interface->fActiveTexture = glActiveTexture;
        interface->fAttachShader = glAttachShader;
        interface->fBindAttribLocation = glBindAttribLocation;
        interface->fBindBuffer = glBindBuffer;
        interface->fBindTexture = glBindTexture;
        interface->fBlendColor = glBlendColor;
        interface->fBlendFunc = glBlendFunc;
        interface->fBufferData = glBufferData;
        interface->fBufferSubData = glBufferSubData;
        interface->fClear = glClear;
        interface->fClearColor = glClearColor;
        interface->fClearStencil = glClearStencil;
        interface->fColorMask = glColorMask;
        interface->fCompileShader = glCompileShader;
        interface->fCompressedTexImage2D = glCompressedTexImage2D;
        interface->fCreateProgram = glCreateProgram;
        interface->fCreateShader = glCreateShader;
        interface->fCullFace = glCullFace;
        interface->fDeleteBuffers = glDeleteBuffers;
        interface->fDeleteProgram = glDeleteProgram;
        interface->fDeleteShader = glDeleteShader;
        interface->fDeleteTextures = glDeleteTextures;
        interface->fDepthMask = glDepthMask;
        interface->fDisable = glDisable;
        interface->fDisableVertexAttribArray = glDisableVertexAttribArray;
        interface->fDrawArrays = glDrawArrays;
        interface->fDrawElements = glDrawElements;
        interface->fEnable = glEnable;
        interface->fEnableVertexAttribArray = glEnableVertexAttribArray;
        interface->fFinish = glFinish;
        interface->fFlush = glFlush;
        interface->fFrontFace = glFrontFace;
        interface->fGenBuffers = glGenBuffers;
        interface->fGenTextures = glGenTextures;
        interface->fGetBufferParameteriv = glGetBufferParameteriv;
        interface->fGetError = glGetError;
        interface->fGetIntegerv = glGetIntegerv;
        interface->fGetProgramInfoLog = glGetProgramInfoLog;
        interface->fGetProgramiv = glGetProgramiv;
        interface->fGetShaderInfoLog = glGetShaderInfoLog;
        interface->fGetShaderiv = glGetShaderiv;
        interface->fGetString = glGetString;
        interface->fGetUniformLocation = glGetUniformLocation;
        interface->fLineWidth = glLineWidth;
        interface->fLinkProgram = glLinkProgram;
        interface->fPixelStorei = glPixelStorei;
        interface->fReadPixels = glReadPixels;
        interface->fScissor = glScissor;
        interface->fShaderSource = glShaderSource;
        interface->fStencilFunc = glStencilFunc;
        interface->fStencilFuncSeparate = glStencilFuncSeparate;
        interface->fStencilMask = glStencilMask;
        interface->fStencilMaskSeparate = glStencilMaskSeparate;
        interface->fStencilOp = glStencilOp;
        interface->fStencilOpSeparate = glStencilOpSeparate;
        interface->fTexImage2D = glTexImage2D;
        interface->fTexParameteri = glTexParameteri;
        interface->fTexParameteriv = glTexParameteriv;
        interface->fTexSubImage2D = glTexSubImage2D;
#if GL_ARB_texture_storage
        interface->fTexStorage2D = glTexStorage2D;
#elif GL_EXT_texture_storage
        interface->fTexStorage2D = glTexStorage2DEXT;
#endif
        interface->fUniform1f = glUniform1f;
        interface->fUniform1i = glUniform1i;
        interface->fUniform1fv = glUniform1fv;
        interface->fUniform1iv = glUniform1iv;
        interface->fUniform2f = glUniform2f;
        interface->fUniform2i = glUniform2i;
        interface->fUniform2fv = glUniform2fv;
        interface->fUniform2iv = glUniform2iv;
        interface->fUniform3f = glUniform3f;
        interface->fUniform3i = glUniform3i;
        interface->fUniform3fv = glUniform3fv;
        interface->fUniform3iv = glUniform3iv;
        interface->fUniform4f = glUniform4f;
        interface->fUniform4i = glUniform4i;
        interface->fUniform4fv = glUniform4fv;
        interface->fUniform4iv = glUniform4iv;
        interface->fUniformMatrix2fv = glUniformMatrix2fv;
        interface->fUniformMatrix3fv = glUniformMatrix3fv;
        interface->fUniformMatrix4fv = glUniformMatrix4fv;
        interface->fUseProgram = glUseProgram;
        interface->fVertexAttrib4fv = glVertexAttrib4fv;
        interface->fVertexAttribPointer = glVertexAttribPointer;
        interface->fViewport = glViewport;
        interface->fBindFramebuffer = glBindFramebuffer;
        interface->fBindRenderbuffer = glBindRenderbuffer;
        interface->fCheckFramebufferStatus = glCheckFramebufferStatus;
        interface->fDeleteFramebuffers = glDeleteFramebuffers;
        interface->fDeleteRenderbuffers = glDeleteRenderbuffers;
        interface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
        interface->fFramebufferTexture2D = glFramebufferTexture2D;
        interface->fGenFramebuffers = glGenFramebuffers;
        interface->fGenRenderbuffers = glGenRenderbuffers;
        interface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
        interface->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
        interface->fRenderbufferStorage = glRenderbufferStorage;
    #if GL_OES_mapbuffer
        interface->fMapBuffer = glMapBufferOES;
        interface->fUnmapBuffer = glUnmapBufferOES;
    #endif
    }
    glInterface.get()->ref();
    return glInterface.get();
}
<commit_msg>Fix GrGLCreateNativeInterface_android Review URL: https://codereview.appspot.com/6503101<commit_after>// Modified from chromium/src/webkit/glue/gl_bindings_skia_cmd_buffer.cc

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

#include "gl/GrGLInterface.h"

#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <EGL/egl.h>

const GrGLInterface* GrGLCreateNativeInterface() {
    static SkAutoTUnref<GrGLInterface> glInterface;
    if (!glInterface.get()) {
        GrGLInterface* interface = new GrGLInterface;
        glInterface.reset(interface);
        interface->fBindingsExported = kES2_GrGLBinding;
        interface->fActiveTexture = glActiveTexture;
        interface->fAttachShader = glAttachShader;
        interface->fBindAttribLocation = glBindAttribLocation;
        interface->fBindBuffer = glBindBuffer;
        interface->fBindTexture = glBindTexture;
        interface->fBlendColor = glBlendColor;
        interface->fBlendFunc = glBlendFunc;
        interface->fBufferData = glBufferData;
        interface->fBufferSubData = glBufferSubData;
        interface->fClear = glClear;
        interface->fClearColor = glClearColor;
        interface->fClearStencil = glClearStencil;
        interface->fColorMask = glColorMask;
        interface->fCompileShader = glCompileShader;
        interface->fCompressedTexImage2D = glCompressedTexImage2D;
        interface->fCreateProgram = glCreateProgram;
        interface->fCreateShader = glCreateShader;
        interface->fCullFace = glCullFace;
        interface->fDeleteBuffers = glDeleteBuffers;
        interface->fDeleteProgram = glDeleteProgram;
        interface->fDeleteShader = glDeleteShader;
        interface->fDeleteTextures = glDeleteTextures;
        interface->fDepthMask = glDepthMask;
        interface->fDisable = glDisable;
        interface->fDisableVertexAttribArray = glDisableVertexAttribArray;
        interface->fDrawArrays = glDrawArrays;
        interface->fDrawElements = glDrawElements;
        interface->fEnable = glEnable;
        interface->fEnableVertexAttribArray = glEnableVertexAttribArray;
        interface->fFinish = glFinish;
        interface->fFlush = glFlush;
        interface->fFrontFace = glFrontFace;
        interface->fGenBuffers = glGenBuffers;
        interface->fGenTextures = glGenTextures;
        interface->fGetBufferParameteriv = glGetBufferParameteriv;
        interface->fGetError = glGetError;
        interface->fGetIntegerv = glGetIntegerv;
        interface->fGetProgramInfoLog = glGetProgramInfoLog;
        interface->fGetProgramiv = glGetProgramiv;
        interface->fGetShaderInfoLog = glGetShaderInfoLog;
        interface->fGetShaderiv = glGetShaderiv;
        interface->fGetString = glGetString;
        interface->fGetUniformLocation = glGetUniformLocation;
        interface->fLineWidth = glLineWidth;
        interface->fLinkProgram = glLinkProgram;
        interface->fPixelStorei = glPixelStorei;
        interface->fReadPixels = glReadPixels;
        interface->fScissor = glScissor;
        interface->fShaderSource = glShaderSource;
        interface->fStencilFunc = glStencilFunc;
        interface->fStencilFuncSeparate = glStencilFuncSeparate;
        interface->fStencilMask = glStencilMask;
        interface->fStencilMaskSeparate = glStencilMaskSeparate;
        interface->fStencilOp = glStencilOp;
        interface->fStencilOpSeparate = glStencilOpSeparate;
        interface->fTexImage2D = glTexImage2D;
        interface->fTexParameteri = glTexParameteri;
        interface->fTexParameteriv = glTexParameteriv;
        interface->fTexSubImage2D = glTexSubImage2D;
#if GL_ARB_texture_storage
        interface->fTexStorage2D = glTexStorage2D;
#elif GL_EXT_texture_storage
        interface->fTexStorage2D = glTexStorage2DEXT;
#else
        interface->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2DEXT");
#endif
        interface->fUniform1f = glUniform1f;
        interface->fUniform1i = glUniform1i;
        interface->fUniform1fv = glUniform1fv;
        interface->fUniform1iv = glUniform1iv;
        interface->fUniform2f = glUniform2f;
        interface->fUniform2i = glUniform2i;
        interface->fUniform2fv = glUniform2fv;
        interface->fUniform2iv = glUniform2iv;
        interface->fUniform3f = glUniform3f;
        interface->fUniform3i = glUniform3i;
        interface->fUniform3fv = glUniform3fv;
        interface->fUniform3iv = glUniform3iv;
        interface->fUniform4f = glUniform4f;
        interface->fUniform4i = glUniform4i;
        interface->fUniform4fv = glUniform4fv;
        interface->fUniform4iv = glUniform4iv;
        interface->fUniformMatrix2fv = glUniformMatrix2fv;
        interface->fUniformMatrix3fv = glUniformMatrix3fv;
        interface->fUniformMatrix4fv = glUniformMatrix4fv;
        interface->fUseProgram = glUseProgram;
        interface->fVertexAttrib4fv = glVertexAttrib4fv;
        interface->fVertexAttribPointer = glVertexAttribPointer;
        interface->fViewport = glViewport;
        interface->fBindFramebuffer = glBindFramebuffer;
        interface->fBindRenderbuffer = glBindRenderbuffer;
        interface->fCheckFramebufferStatus = glCheckFramebufferStatus;
        interface->fDeleteFramebuffers = glDeleteFramebuffers;
        interface->fDeleteRenderbuffers = glDeleteRenderbuffers;
        interface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
        interface->fFramebufferTexture2D = glFramebufferTexture2D;
        interface->fGenFramebuffers = glGenFramebuffers;
        interface->fGenRenderbuffers = glGenRenderbuffers;
        interface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
        interface->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
        interface->fRenderbufferStorage = glRenderbufferStorage;
#if GL_OES_mapbuffer
        interface->fMapBuffer = glMapBufferOES;
        interface->fUnmapBuffer = glUnmapBufferOES;
#else
        interface->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
        interface->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
#endif
    }
    glInterface.get()->ref();
    return glInterface.get();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "common/common.h"
#include <assert.h>
#include <time.h>
#include <sys/timeb.h>

#include "store/api/iterator.h"
#include "store/api/temp_seq.h"
#include "store/api/item_factory.h"
#include "store/api/store.h"

#include "system/globalenv.h"

#include "context/dynamic_context.h"
#include "context/static_context.h"

#include "compiler/expression/var_expr.h"

#include "types/root_typemanager.h"

#include "runtime/api/plan_wrapper.h"

#include "zorbautils/strutil.h"

#include "indexing/value_index.h"

using namespace std;
namespace zorba {

bool dynamic_context::static_init = false;

string dynamic_context::var_key (const void *var)
{
  if (var == NULL) return "";
  const var_expr *ve = static_cast<const var_expr *> (var);
  return xqpString::concat(to_string(var), ":", ve->get_varname ()->getStringValue ());
}

xqp_string dynamic_context::expand_varname(static_context	*sctx, xqp_string qname)
{
  if(!sctx)
  {
    ///actually the whole static context is missing
    ZORBA_ERROR_PARAM( XPST0001, "entire static context", "");
    return (const char*)NULL;
  }
  void *var = static_cast<void *> (sctx->lookup_var (qname));
  return var_key (var);
}

void dynamic_context::init()
{
	if (!dynamic_context::static_init) {
		dynamic_context::static_init = true;
	}
}

dynamic_context::dynamic_context(dynamic_context *parent)
{
  this->parent = parent;
  if(!parent)
  {
#if defined (WIN32)
    struct _timeb timebuffer;
    _ftime_s( &timebuffer );
    struct ::tm gmtm;
    localtime_s(&gmtm, &timebuffer.time); //thread safe localtime on Windows
#else
    struct timeb timebuffer;
    ftime( &timebuffer );
    struct ::tm gmtm;
    localtime_r(&timebuffer.time, &gmtm); //thread safe localtime on Linux
#endif

    set_implicit_timezone( -timebuffer.timezone * 60 );//in seconds

    GENV_ITEMFACTORY->createDateTime(current_date_time_item, gmtm.tm_year + 1900, gmtm.tm_mon + 1, gmtm.tm_mday,
		  gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec + timebuffer.millitm/1000.0, implicit_timezone/3600);

	  ctxt_position = 0;
	}
	else
	{
		current_date_time_item = parent->current_date_time_item;
		implicit_timezone = parent->implicit_timezone;
		default_collection_uri = parent->default_collection_uri;

		ctxt_item = parent->ctxt_item;
		ctxt_position = parent->ctxt_position;
	}
}

void dynamic_context::destroy_dctx_value (const dctx_value_t* val) {
  switch (val->type) {
  case dynamic_context::dctx_value_t::no_val:
    break;
  case dynamic_context::dctx_value_t::var_iterator_val:
    RCHelper::removeReference (val->val.var_iterator);
    break;
  case dynamic_context::dctx_value_t::temp_seq_val:
    RCHelper::removeReference (val->val.temp_seq);
    break;
  default:
    ZORBA_ASSERT (false);
  }
}

dynamic_context::~dynamic_context()
{
	///free the pointers from ctx_value_t from keymap
	checked_vector<hashmap<dctx_value_t>::entry>::const_iterator it;
	const char		*keybuff;//[50];

	for(it = keymap.begin(); it != keymap.end(); it++)
	{
		///it is an entry
		keybuff = (*it).key.c_str();
		if(strncmp(keybuff, "var:", 4) == 0)
		{
			destroy_dctx_value (&(*it).val);
		}
	}
}

void dynamic_context::set_context_item(
    const store::Item_t& context_item,
    unsigned long position)
{
	this->ctxt_item = context_item;
	this->ctxt_position = position;
}

store::Item_t dynamic_context::context_item() const
{
	return ctxt_item;
}

unsigned long dynamic_context::context_position()
{
	return ctxt_position;
}

xqtref_t dynamic_context::context_item_type() const
{
	return GENV_TYPESYSTEM.ITEM_TYPE_STAR;
}

void dynamic_context::set_context_item_type(xqtref_t v)
{
}

void	dynamic_context::set_current_date_time( const store::Item_t& aDateTimeItem )
{
  this->current_date_time_item = aDateTimeItem;
}

store::Item_t	dynamic_context::get_current_date_time()
{
	return current_date_time_item;
}

void  dynamic_context::set_implicit_timezone(int tzone_seconds)
{
	this->implicit_timezone = tzone_seconds;
}

int  dynamic_context::get_implicit_timezone()
{
  return implicit_timezone;
}

/*
var_name is expanded name localname:nsURI
constructed by static_context::qname_internal_key( .. )
*/
void dynamic_context::set_variable(
    const std::string& var_name,
    store::Iterator_t var_iterator)
{
  if (var_name.empty()) return;

  dctx_value_t v;
  string key = "var:" + var_name;
  hashmap<dctx_value_t> *map;
  if (! context_value (key, v, &map))
    ZORBA_ASSERT (false);

  var_iterator->open ();
  store::TempSeq_t seq = GENV_STORE.createTempSeq (var_iterator.getp());
  var_iterator->close ();
  RCHelper::addReference (seq);
  v.type = dynamic_context::dctx_value_t::temp_seq_val;
  v.in_progress = false;
  v.val.temp_seq = seq.getp();
  map->put (key, v);
}

void dynamic_context::declare_variable(const std::string& var_name)
{
  if (var_name.empty()) return;

  dctx_value_t v;
  string key = "var:" + var_name;
  if (keymap.get (key, v))
    destroy_dctx_value (&v);

  v.type = dynamic_context::dctx_value_t::no_val;
  v.in_progress = true;
  keymap.put (key, v);
}

void dynamic_context::add_variable(
    const std::string& varname,
    store::Iterator_t var_iterator)
{
  declare_variable (varname);
  set_variable (varname, var_iterator);
}

store::Iterator_t	dynamic_context::get_variable(const store::Item_t& varname)
{
	return lookup_var_iter("var:" + varname->getStringValue()->str());
}

store::Iterator_t dynamic_context::lookup_var_iter(const std::string& key)
{
  dctx_value_t val = {dctx_value_t::no_val, false, {0} };

  if(!keymap.get(key, val))
	{
    if(parent)
      return parent->lookup_var_iter(key);
    else
      return NULL;///variable not found
	}
  if (val.in_progress)
    ZORBA_ERROR (XQST0054);

  assert (val.type == dynamic_context::dctx_value_t::temp_seq_val);
  return val.val.temp_seq->getIterator ();
}

store::Item_t dynamic_context::get_default_collection()
{
	return default_collection_uri;
}

void dynamic_context::set_default_collection(const store::Item_t& default_collection_uri)
{
	this->default_collection_uri = default_collection_uri;
}

void dynamic_context::bind_index(
    const std::string& indexUri,
    store::Index* index)
{
  if (val_idx_ins_session_map.find(indexUri) != val_idx_ins_session_map.end()) {
    ZORBA_ERROR_PARAM(XQP0034_INDEX_ALREADY_EXISTS, indexUri.c_str(), "");
  }
  std::pair<store::Index_t, ValueIndexInsertSession_t> v;
  v.first = index;
  v.second = NULL;
  val_idx_ins_session_map[indexUri] = v;
}

void dynamic_context::unbind_index(
    const std::string& indexUri)
{
  IndexMap::iterator i = val_idx_ins_session_map.find(indexUri);
  if (i != val_idx_ins_session_map.end())
  {
    val_idx_ins_session_map.erase(i);
  }
  else if (parent != NULL)
  {
    return parent->unbind_index(indexUri);
  }
  else
  {
    ZORBA_ERROR_PARAM(XQP0033_INDEX_DOES_NOT_EXIST, indexUri.c_str(), "");
  }
}

store::Index* dynamic_context::lookup_index(const std::string& indexUri) const
{
  IndexMap::const_iterator i = val_idx_ins_session_map.find(indexUri);
  if (i != val_idx_ins_session_map.end())
  {
    return i->second.first.getp();
  }
  else if (parent != NULL)
  {
    return parent->lookup_index(indexUri);
  }
  else
  {
    ZORBA_ERROR_PARAM(XQP0033_INDEX_DOES_NOT_EXIST, indexUri.c_str(), "");
  }
}

ValueIndexInsertSession* dynamic_context::get_index_insert_session(
    const std::string& indexUri) const
{
  IndexMap::const_iterator i = val_idx_ins_session_map.find(indexUri);
  if (i != val_idx_ins_session_map.end())
  {
    return i->second.second.getp();
  }
  else if (parent != NULL)
  {
    return parent->get_index_insert_session(indexUri);
  }
  else
  {
    ZORBA_ASSERT(false);
  }
}

void dynamic_context::set_index_insert_session (
    const std::string& indexUri,
    ValueIndexInsertSession* s)
{
  IndexMap::iterator i = val_idx_ins_session_map.find(indexUri);
  if (i != val_idx_ins_session_map.end())
  {
    i->second.second = s;
  }
  else if (parent != NULL)
  {
    parent->set_index_insert_session(indexUri, s);
  }
  else
  {
    ZORBA_ASSERT(false);
  }
}

}	/* namespace zorba */

<commit_msg>added daylight saving time to current date time in the dynamic context<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "common/common.h"
#include <assert.h>
#include <time.h>
#include <sys/timeb.h>

#include "store/api/iterator.h"
#include "store/api/temp_seq.h"
#include "store/api/item_factory.h"
#include "store/api/store.h"

#include "system/globalenv.h"

#include "context/dynamic_context.h"
#include "context/static_context.h"

#include "compiler/expression/var_expr.h"

#include "types/root_typemanager.h"

#include "runtime/api/plan_wrapper.h"

#include "zorbautils/strutil.h"

#include "indexing/value_index.h"

using namespace std;
namespace zorba {

bool dynamic_context::static_init = false;

string dynamic_context::var_key (const void *var)
{
  if (var == NULL) return "";
  const var_expr *ve = static_cast<const var_expr *> (var);
  return xqpString::concat(to_string(var), ":", ve->get_varname ()->getStringValue ());
}

xqp_string dynamic_context::expand_varname(static_context	*sctx, xqp_string qname)
{
  if(!sctx)
  {
    ///actually the whole static context is missing
    ZORBA_ERROR_PARAM( XPST0001, "entire static context", "");
    return (const char*)NULL;
  }
  void *var = static_cast<void *> (sctx->lookup_var (qname));
  return var_key (var);
}

void dynamic_context::init()
{
	if (!dynamic_context::static_init) {
		dynamic_context::static_init = true;
	}
}

dynamic_context::dynamic_context(dynamic_context *parent)
{
  this->parent = parent;
  if(!parent)
  {
#if defined (WIN32)
    struct _timeb timebuffer;
    _ftime_s( &timebuffer );
    struct ::tm gmtm;
    localtime_s(&gmtm, &timebuffer.time); //thread safe localtime on Windows
#else
    struct timeb timebuffer;
    ftime( &timebuffer );
    struct ::tm gmtm;
    localtime_r(&timebuffer.time, &gmtm); //thread safe localtime on Linux
#endif

    {
      int lSummerTimeShift = 0;
      if (gmtm.tm_isdst != 0) {
        lSummerTimeShift = 3600;
      }
      set_implicit_timezone( -timebuffer.timezone * 60 + lSummerTimeShift );//in seconds
    }

    GENV_ITEMFACTORY->createDateTime(current_date_time_item, gmtm.tm_year + 1900, gmtm.tm_mon + 1, gmtm.tm_mday,
		  gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec + timebuffer.millitm/1000.0, implicit_timezone/3600);

	  ctxt_position = 0;
	}
	else
	{
		current_date_time_item = parent->current_date_time_item;
		implicit_timezone = parent->implicit_timezone;
		default_collection_uri = parent->default_collection_uri;

		ctxt_item = parent->ctxt_item;
		ctxt_position = parent->ctxt_position;
	}
}

void dynamic_context::destroy_dctx_value (const dctx_value_t* val) {
  switch (val->type) {
  case dynamic_context::dctx_value_t::no_val:
    break;
  case dynamic_context::dctx_value_t::var_iterator_val:
    RCHelper::removeReference (val->val.var_iterator);
    break;
  case dynamic_context::dctx_value_t::temp_seq_val:
    RCHelper::removeReference (val->val.temp_seq);
    break;
  default:
    ZORBA_ASSERT (false);
  }
}

dynamic_context::~dynamic_context()
{
	///free the pointers from ctx_value_t from keymap
	checked_vector<hashmap<dctx_value_t>::entry>::const_iterator it;
	const char		*keybuff;//[50];

	for(it = keymap.begin(); it != keymap.end(); it++)
	{
		///it is an entry
		keybuff = (*it).key.c_str();
		if(strncmp(keybuff, "var:", 4) == 0)
		{
			destroy_dctx_value (&(*it).val);
		}
	}
}

void dynamic_context::set_context_item(
    const store::Item_t& context_item,
    unsigned long position)
{
	this->ctxt_item = context_item;
	this->ctxt_position = position;
}

store::Item_t dynamic_context::context_item() const
{
	return ctxt_item;
}

unsigned long dynamic_context::context_position()
{
	return ctxt_position;
}

xqtref_t dynamic_context::context_item_type() const
{
	return GENV_TYPESYSTEM.ITEM_TYPE_STAR;
}

void dynamic_context::set_context_item_type(xqtref_t v)
{
}

void	dynamic_context::set_current_date_time( const store::Item_t& aDateTimeItem )
{
  this->current_date_time_item = aDateTimeItem;
}

store::Item_t	dynamic_context::get_current_date_time()
{
	return current_date_time_item;
}

void  dynamic_context::set_implicit_timezone(int tzone_seconds)
{
	this->implicit_timezone = tzone_seconds;
}

int  dynamic_context::get_implicit_timezone()
{
  return implicit_timezone;
}

/*
var_name is expanded name localname:nsURI
constructed by static_context::qname_internal_key( .. )
*/
void dynamic_context::set_variable(
    const std::string& var_name,
    store::Iterator_t var_iterator)
{
  if (var_name.empty()) return;

  dctx_value_t v;
  string key = "var:" + var_name;
  hashmap<dctx_value_t> *map;
  if (! context_value (key, v, &map))
    ZORBA_ASSERT (false);

  var_iterator->open ();
  store::TempSeq_t seq = GENV_STORE.createTempSeq (var_iterator.getp());
  var_iterator->close ();
  RCHelper::addReference (seq);
  v.type = dynamic_context::dctx_value_t::temp_seq_val;
  v.in_progress = false;
  v.val.temp_seq = seq.getp();
  map->put (key, v);
}

void dynamic_context::declare_variable(const std::string& var_name)
{
  if (var_name.empty()) return;

  dctx_value_t v;
  string key = "var:" + var_name;
  if (keymap.get (key, v))
    destroy_dctx_value (&v);

  v.type = dynamic_context::dctx_value_t::no_val;
  v.in_progress = true;
  keymap.put (key, v);
}

void dynamic_context::add_variable(
    const std::string& varname,
    store::Iterator_t var_iterator)
{
  declare_variable (varname);
  set_variable (varname, var_iterator);
}

store::Iterator_t	dynamic_context::get_variable(const store::Item_t& varname)
{
	return lookup_var_iter("var:" + varname->getStringValue()->str());
}

store::Iterator_t dynamic_context::lookup_var_iter(const std::string& key)
{
  dctx_value_t val = {dctx_value_t::no_val, false, {0} };

  if(!keymap.get(key, val))
	{
    if(parent)
      return parent->lookup_var_iter(key);
    else
      return NULL;///variable not found
	}
  if (val.in_progress)
    ZORBA_ERROR (XQST0054);

  assert (val.type == dynamic_context::dctx_value_t::temp_seq_val);
  return val.val.temp_seq->getIterator ();
}

store::Item_t dynamic_context::get_default_collection()
{
	return default_collection_uri;
}

void dynamic_context::set_default_collection(const store::Item_t& default_collection_uri)
{
	this->default_collection_uri = default_collection_uri;
}

void dynamic_context::bind_index(
    const std::string& indexUri,
    store::Index* index)
{
  if (val_idx_ins_session_map.find(indexUri) != val_idx_ins_session_map.end()) {
    ZORBA_ERROR_PARAM(XQP0034_INDEX_ALREADY_EXISTS, indexUri.c_str(), "");
  }
  std::pair<store::Index_t, ValueIndexInsertSession_t> v;
  v.first = index;
  v.second = NULL;
  val_idx_ins_session_map[indexUri] = v;
}

void dynamic_context::unbind_index(
    const std::string& indexUri)
{
  IndexMap::iterator i = val_idx_ins_session_map.find(indexUri);
  if (i != val_idx_ins_session_map.end())
  {
    val_idx_ins_session_map.erase(i);
  }
  else if (parent != NULL)
  {
    return parent->unbind_index(indexUri);
  }
  else
  {
    ZORBA_ERROR_PARAM(XQP0033_INDEX_DOES_NOT_EXIST, indexUri.c_str(), "");
  }
}

store::Index* dynamic_context::lookup_index(const std::string& indexUri) const
{
  IndexMap::const_iterator i = val_idx_ins_session_map.find(indexUri);
  if (i != val_idx_ins_session_map.end())
  {
    return i->second.first.getp();
  }
  else if (parent != NULL)
  {
    return parent->lookup_index(indexUri);
  }
  else
  {
    ZORBA_ERROR_PARAM(XQP0033_INDEX_DOES_NOT_EXIST, indexUri.c_str(), "");
  }
}

ValueIndexInsertSession* dynamic_context::get_index_insert_session(
    const std::string& indexUri) const
{
  IndexMap::const_iterator i = val_idx_ins_session_map.find(indexUri);
  if (i != val_idx_ins_session_map.end())
  {
    return i->second.second.getp();
  }
  else if (parent != NULL)
  {
    return parent->get_index_insert_session(indexUri);
  }
  else
  {
    ZORBA_ASSERT(false);
  }
}

void dynamic_context::set_index_insert_session (
    const std::string& indexUri,
    ValueIndexInsertSession* s)
{
  IndexMap::iterator i = val_idx_ins_session_map.find(indexUri);
  if (i != val_idx_ins_session_map.end())
  {
    i->second.second = s;
  }
  else if (parent != NULL)
  {
    parent->set_index_insert_session(indexUri, s);
  }
  else
  {
    ZORBA_ASSERT(false);
  }
}

}	/* namespace zorba */

<|endoftext|>


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

/*
 * Description:
 *     What is this file about?
 *
 * Revision history:
 *     xxxx-xx-xx, author, first version
 *     xxxx-xx-xx, author, fix bug about xxx
 */

# include <dsn/internal/perf_counters.h>
# include <dsn/service_api_c.h>
# include <dsn/internal/command.h>
# include <dsn/internal/task.h>
# include <dsn/cpp/json_helper.h>
# include "service_engine.h"

DSN_API dsn_handle_t dsn_perf_counter_create(const char* section, const char* name, dsn_perf_counter_type_t type, const char* description)
{
    auto cnode = dsn::task::get_current_node2();
    dassert(cnode != nullptr, "cannot get current service node!");
    auto c = dsn::perf_counters::instance().get_counter(cnode->name(), section, name, type, description, true);
    c->add_ref();
    return c.get();
}

DSN_API void dsn_perf_counter_remove(dsn_handle_t handle)
{
    auto sptr = reinterpret_cast<dsn::perf_counter*>(handle);
    if (dsn::perf_counters::instance().remove_counter(sptr->full_name()))
        sptr->release_ref();
    else
    {
        dwarn("cannot remove counter %s as it is not found in our repo", sptr->full_name());
    }
}

DSN_API void dsn_perf_counter_increment(dsn_handle_t handle)
{
    reinterpret_cast<dsn::perf_counter*>(handle)->increment();
}

DSN_API void dsn_perf_counter_decrement(dsn_handle_t handle)
{
    reinterpret_cast<dsn::perf_counter*>(handle)->decrement();
}
DSN_API void dsn_perf_counter_add(dsn_handle_t handle, uint64_t val)
{
    reinterpret_cast<dsn::perf_counter*>(handle)->add(val);
}
DSN_API void dsn_perf_counter_set(dsn_handle_t handle, uint64_t val)
{
    reinterpret_cast<dsn::perf_counter*>(handle)->set(val);
}
DSN_API double dsn_perf_counter_get_value(dsn_handle_t handle)
{
    return reinterpret_cast<dsn::perf_counter*>(handle)->get_value();
}
DSN_API uint64_t dsn_perf_counter_get_integer_value(dsn_handle_t handle)
{
    return reinterpret_cast<dsn::perf_counter*>(handle)->get_integer_value();
}
DSN_API double dsn_perf_counter_get_percentile(dsn_handle_t handle, dsn_perf_counter_percentile_type_t type)
{
    return reinterpret_cast<dsn::perf_counter*>(handle)->get_percentile(type);
}

namespace dsn {

perf_counters::perf_counters(void)
{
    _max_counter_count = dsn_config_get_value_uint64(
        "core",
        "perf_counter_max_count",
        10000,
        "maximum number of performance counters"
        );

    dassert(_max_counter_count > 0 && _max_counter_count < 1000000,
        "invalid given perf_counter_max_count value %" PRIu64,
        _max_counter_count
        );
    _quick_counters = new perf_counter*[_max_counter_count];
    memset((void*)_quick_counters, 0, sizeof(perf_counter*) * _max_counter_count);

    // index << 32 | version
    // zero is reserved for invalid
    for (uint64_t i = 1; i < _max_counter_count; i++)
    {
        _quick_counters_empty_slots.push((i << 32) | 0x0);
    }

    ::dsn::register_command("counter.list",
        "counter.list - get the list of all counters",
        "counter.list",
        &perf_counters::list_counter
        );

    ::dsn::register_command("counter.value",
        "counter.value - get current value of a specific counter",
        "counter.value app-name*section-name*counter-name",
        &perf_counters::get_counter_value
        );

    ::dsn::register_command("counter.sample",
        "counter.sample - get latest sample of a specific counter",
        "counter.sample app-name*section-name*counter-name",
        &perf_counters::get_counter_sample
        );

    ::dsn::register_command("counter.valuei",
        "counter.valuei - get current value of a specific counter",
        "counter.valuei counter-index",
        &perf_counters::get_counter_value_i
        );

    ::dsn::register_command("counter.samplei",
        "counter.samplei - get latest sample of a specific counter",
        "counter.samplei counter-index",
        &perf_counters::get_counter_sample_i
        );

    ::dsn::register_command("counter.getindex",
        "counter.getindex - get index of a list of counters by name",
        "counter.getindex app-name1*section-name1*counter-name1 app-name2*section-name2*counter-name2 ...",
        &perf_counters::get_counter_index
        );

}

perf_counters::~perf_counters(void)
{
    delete[] _quick_counters;
}

perf_counter_ptr perf_counters::get_counter(const char* app, const char *section, const char *name, dsn_perf_counter_type_t flags, const char *dsptr, bool create_if_not_exist /*= false*/)
{
    std::string full_name;
    perf_counter::build_full_name(app, section, name, full_name);

    if (create_if_not_exist)
    {
        utils::auto_write_lock l(_lock);

        auto it = _counters.find(full_name);
        if (it == _counters.end())
        {
            dassert(_quick_counters_empty_slots.size() > 0,
                "no more slots for perf counters, please increase [core] perf_counter_max_count"
                );

            uint64_t idx = _quick_counters_empty_slots.front();
            _quick_counters_empty_slots.pop();

            // increase version
            idx++;

            perf_counter_ptr counter = _factory(app, section, name, flags, dsptr);
            counter->_index = idx; // index << 32 | version

            _quick_counters[idx >> 32] = counter.get();
            _counters.emplace(std::piecewise_construct, std::forward_as_tuple(full_name), std::forward_as_tuple(counter));
            return counter;
        }
        else
        {
            dassert (it->second->type() == flags,
                "counters with the same name %s with differnt types",
                full_name.c_str()
                );
            return it->second;
        }
    }
    else
    {
        utils::auto_read_lock l(_lock);

        auto it = _counters.find(full_name);
        if (it == _counters.end())
            return nullptr;
        else
            return it->second;
    }
}

perf_counter_ptr perf_counters::get_counter(const char* full_name)
{
    utils::auto_read_lock l(_lock);

    auto it = _counters.find(full_name);
    if (it == _counters.end())
        return nullptr;
    else
        return it->second;
}
perf_counter_ptr perf_counters::get_counter(uint64_t index)
{
    utils::auto_read_lock l(_lock);

    auto slot = (index >> 32);
    if (slot >= _max_counter_count)
        return nullptr;

    if (_quick_counters[slot] && _quick_counters[slot]->index() == index)
    {
        return _quick_counters[slot];
    }
    else
    {
        return nullptr;
    }
}

bool perf_counters::remove_counter(const char* full_name)
{
    {
        utils::auto_write_lock l(_lock);

        auto it = _counters.find(full_name);
        if (it == _counters.end())
            return false;
        else
        {
            _quick_counters_empty_slots.push(it->second->index());
            auto& c = _quick_counters[it->second->index() >> 32];
            dassert(c == it->second.get(),
                "invalid perf counter pointer stored in quick access array");

            c = nullptr;
            _counters.erase(it);
        }
    }

    dinfo("performance counter %s is removed", full_name);
    return true;
}

void perf_counters::register_factory(perf_counter::factory factory)
{
    utils::auto_write_lock l(_lock);
    _factory = factory;
}

std::string perf_counters::list_counter(const std::vector<std::string>& args)
{
    return perf_counters::instance().list_counter_internal(args);
}

struct counter_info
{
    std::string name;
    uint64_t    index;

    DEFINE_JSON_SERIALIZATION(name, index)
};

struct value_resp {
    double val;
    uint64_t time;
    DEFINE_JSON_SERIALIZATION(val, time)
};

struct sample_resp {
    uint64_t val;
    uint64_t time;
    DEFINE_JSON_SERIALIZATION(time, val)
};

std::string perf_counters::list_counter_internal(const std::vector<std::string>& args)
{
    // <app, <section, counter_info[] > > counters
    std::map<std::string, std::map< std::string, std::vector<counter_info> > > counters;
    std::map< std::string, std::vector<counter_info> > empty_m;
    std::vector<counter_info> empty_v;

    std::map< std::string, std::vector<counter_info> >* pp;
    std::vector<counter_info>* pv;

    {
        utils::auto_read_lock l(_lock);
        for (auto& c : _counters)
        {
            pp = &counters.insert(
                std::map<std::string, std::map< std::string, std::vector<counter_info> > >::value_type(
                c.second->app(),
                empty_m
                )
                ).first->second;

            pv = &pp->insert(
                std::map< std::string, std::vector<counter_info> >::value_type(
                c.second->section(),
                empty_v
                )
                ).first->second;

            pv->push_back({ c.second->name(), c.second->index() });
        }
    }

    std::stringstream ss;
    std::json_encode(ss, counters);
    return ss.str();
}

std::string perf_counters::get_counter_value(const std::vector<std::string>& args)
{
    std::stringstream ss;

    uint64_t ts = dsn_now_ns();
    double value = 0;

    if (args.size() < 1)
    {
        value_resp{ value, ts }.json_state(ss);
        return ss.str();
    }

    perf_counters& c = perf_counters::instance();
    auto counter = c.get_counter(args[0].c_str());

    if (counter && counter->type() != COUNTER_TYPE_NUMBER_PERCENTILES)
        value =  counter->get_value();

    value_resp{ value, ts }.json_state(ss);
    return ss.str();
}

std::string perf_counters::get_counter_sample(const std::vector<std::string>& args)
{
    std::stringstream ss;

    uint64_t ts = dsn_now_ns();
    uint64_t sample = 0;

    if (args.size() < 1)
    {
        sample_resp{ sample, ts }.json_state(ss);
        return ss.str();
    }

    perf_counters& c = perf_counters::instance();
    auto counter = c.get_counter(args[0].c_str());

    if (counter)
        sample = counter->get_latest_sample();

    sample_resp{ sample, ts }.json_state(ss);
    return ss.str();
}

std::string perf_counters::get_counter_value_i(const std::vector<std::string>& args)
{
    std::stringstream ss;

    uint64_t ts = dsn_now_ns();
    double value = 0;

    if (args.size() < 1)
    {
        value_resp{ value, ts }.json_state(ss);
        return ss.str();
    }

    uint64_t idx = atoll(args[0].c_str());

    perf_counters& c = perf_counters::instance();
    auto counter = c.get_counter(idx);

    if (counter && counter->type() != COUNTER_TYPE_NUMBER_PERCENTILES)
        value = counter->get_value();

    value_resp{ value, ts }.json_state(ss);
    return ss.str();
}

std::string perf_counters::get_counter_sample_i(const std::vector<std::string>& args)
{
    std::stringstream ss;

    uint64_t ts = dsn_now_ns();
    uint64_t sample = 0;

    if (args.size() < 1)
    {
        sample_resp{ sample, ts }.json_state(ss);
        return ss.str();
    }

    uint64_t idx = atoll(args[0].c_str());

    perf_counters& c = perf_counters::instance();
    auto counter = c.get_counter(idx);

    if (counter)
        sample = counter->get_latest_sample();

    sample_resp{ sample, ts }.json_state(ss);
    return ss.str();
}

std::string perf_counters::get_counter_index(const std::vector<std::string>& args)
{
    std::stringstream ss;

    std::vector<uint64_t> counter_index_list;

    for (auto counter_name : args)
    {
        perf_counters& c = perf_counters::instance();
        auto counter = c.get_counter(counter_name.c_str());
        if (counter)
            counter_index_list.push_back(counter->index());
        else
            counter_index_list.push_back(0);
    }

    std::json_encode(ss, counter_index_list);
    return ss.str();
}

} // end namespace

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

/*
 * Description:
 *     What is this file about?
 *
 * Revision history:
 *     xxxx-xx-xx, author, first version
 *     xxxx-xx-xx, author, fix bug about xxx
 */

# include <dsn/internal/perf_counters.h>
# include <dsn/service_api_c.h>
# include <dsn/internal/command.h>
# include <dsn/internal/task.h>
# include <dsn/cpp/json_helper.h>
# include "service_engine.h"

DSN_API dsn_handle_t dsn_perf_counter_create(const char* section, const char* name, dsn_perf_counter_type_t type, const char* description)
{
    auto cnode = dsn::task::get_current_node2();
    dassert(cnode != nullptr, "cannot get current service node!");
    auto c = dsn::perf_counters::instance().get_counter(cnode->name(), section, name, type, description, true);
    c->add_ref();
    return c.get();
}

DSN_API void dsn_perf_counter_remove(dsn_handle_t handle)
{
    auto sptr = reinterpret_cast<dsn::perf_counter*>(handle);
    if (dsn::perf_counters::instance().remove_counter(sptr->full_name()))
        sptr->release_ref();
    else
    {
        dwarn("cannot remove counter %s as it is not found in our repo", sptr->full_name());
    }
}

DSN_API void dsn_perf_counter_increment(dsn_handle_t handle)
{
    reinterpret_cast<dsn::perf_counter*>(handle)->increment();
}

DSN_API void dsn_perf_counter_decrement(dsn_handle_t handle)
{
    reinterpret_cast<dsn::perf_counter*>(handle)->decrement();
}
DSN_API void dsn_perf_counter_add(dsn_handle_t handle, uint64_t val)
{
    reinterpret_cast<dsn::perf_counter*>(handle)->add(val);
}
DSN_API void dsn_perf_counter_set(dsn_handle_t handle, uint64_t val)
{
    reinterpret_cast<dsn::perf_counter*>(handle)->set(val);
}
DSN_API double dsn_perf_counter_get_value(dsn_handle_t handle)
{
    return reinterpret_cast<dsn::perf_counter*>(handle)->get_value();
}
DSN_API uint64_t dsn_perf_counter_get_integer_value(dsn_handle_t handle)
{
    return reinterpret_cast<dsn::perf_counter*>(handle)->get_integer_value();
}
DSN_API double dsn_perf_counter_get_percentile(dsn_handle_t handle, dsn_perf_counter_percentile_type_t type)
{
    return reinterpret_cast<dsn::perf_counter*>(handle)->get_percentile(type);
}

namespace dsn {

perf_counters::perf_counters(void)
{
    _max_counter_count = dsn_config_get_value_uint64(
        "core",
        "perf_counter_max_count",
        10000,
        "maximum number of performance counters"
        );

    dassert(_max_counter_count > 0 && _max_counter_count < 1000000,
        "invalid given perf_counter_max_count value %" PRIu64,
        _max_counter_count
        );
    _quick_counters = new perf_counter*[_max_counter_count];
    memset((void*)_quick_counters, 0, sizeof(perf_counter*) * _max_counter_count);

    // index << 32 | version
    // zero is reserved for invalid
    for (uint64_t i = 1; i < _max_counter_count; i++)
    {
        _quick_counters_empty_slots.push((i << 32) | 0x0);
    }

    ::dsn::register_command("counter.list",
        "counter.list - get the list of all counters",
        "counter.list",
        &perf_counters::list_counter
        );

    ::dsn::register_command("counter.value",
        "counter.value - get current value of a specific counter",
        "counter.value app-name*section-name*counter-name",
        &perf_counters::get_counter_value
        );

    ::dsn::register_command("counter.sample",
        "counter.sample - get latest sample of a specific counter",
        "counter.sample app-name*section-name*counter-name",
        &perf_counters::get_counter_sample
        );

    ::dsn::register_command("counter.valuei",
        "counter.valuei - get current value of a specific counter",
        "counter.valuei counter-index",
        &perf_counters::get_counter_value_i
        );

    ::dsn::register_command("counter.samplei",
        "counter.samplei - get latest sample of a specific counter",
        "counter.samplei counter-index",
        &perf_counters::get_counter_sample_i
        );

    ::dsn::register_command("counter.getindex",
        "counter.getindex - get index of a list of counters by name",
        "counter.getindex app-name1*section-name1*counter-name1 app-name2*section-name2*counter-name2 ...",
        &perf_counters::get_counter_index
        );

}

perf_counters::~perf_counters(void)
{
    delete[] _quick_counters;
}

perf_counter_ptr perf_counters::get_counter(const char* app, const char *section, const char *name, dsn_perf_counter_type_t flags, const char *dsptr, bool create_if_not_exist /*= false*/)
{
    std::string full_name;
    perf_counter::build_full_name(app, section, name, full_name);

    if (create_if_not_exist)
    {
        utils::auto_write_lock l(_lock);

        auto it = _counters.find(full_name);
        if (it == _counters.end())
        {
            dassert(_quick_counters_empty_slots.size() > 0,
                "no more slots for perf counters, please increase [core] perf_counter_max_count"
                );

            uint64_t idx = _quick_counters_empty_slots.front();
            _quick_counters_empty_slots.pop();

            // increase version
            idx++;

            perf_counter_ptr counter = _factory(app, section, name, flags, dsptr);
            counter->_index = idx; // index << 32 | version

            _quick_counters[idx >> 32] = counter.get();
            _counters.emplace(std::piecewise_construct, std::forward_as_tuple(full_name), std::forward_as_tuple(counter));
            return counter;
        }
        else
        {
            dassert (it->second->type() == flags,
                "counters with the same name %s with differnt types",
                full_name.c_str()
                );
            return it->second;
        }
    }
    else
    {
        utils::auto_read_lock l(_lock);

        auto it = _counters.find(full_name);
        if (it == _counters.end())
            return nullptr;
        else
            return it->second;
    }
}

perf_counter_ptr perf_counters::get_counter(const char* full_name)
{
    utils::auto_read_lock l(_lock);

    auto it = _counters.find(full_name);
    if (it == _counters.end())
        return nullptr;
    else
        return it->second;
}
perf_counter_ptr perf_counters::get_counter(uint64_t index)
{
    utils::auto_read_lock l(_lock);

    auto slot = (index >> 32);
    if (slot >= _max_counter_count)
        return nullptr;

    if (_quick_counters[slot] && _quick_counters[slot]->index() == index)
    {
        return _quick_counters[slot];
    }
    else
    {
        return nullptr;
    }
}

bool perf_counters::remove_counter(const char* full_name)
{
    {
        utils::auto_write_lock l(_lock);

        auto it = _counters.find(full_name);
        if (it == _counters.end())
            return false;
        else
        {
            _quick_counters_empty_slots.push(it->second->index());
            auto& c = _quick_counters[it->second->index() >> 32];
            dassert(c == it->second.get(),
                "invalid perf counter pointer stored in quick access array");

            c = nullptr;
            _counters.erase(it);
        }
    }

    dinfo("performance counter %s is removed", full_name);
    return true;
}

void perf_counters::register_factory(perf_counter::factory factory)
{
    utils::auto_write_lock l(_lock);
    _factory = factory;
}

std::string perf_counters::list_counter(const std::vector<std::string>& args)
{
    return perf_counters::instance().list_counter_internal(args);
}

struct counter_info
{
    std::string name;
    uint64_t    index;

    DEFINE_JSON_SERIALIZATION(name, index)
};

struct value_resp {
    double val;
    uint64_t time;
    std::string counter_name;
    uint64_t counter_index;
    DEFINE_JSON_SERIALIZATION(val, time, counter_name, counter_index)
};

struct sample_resp {
    uint64_t val;
    uint64_t time;
    std::string counter_name;
    uint64_t counter_index;
    DEFINE_JSON_SERIALIZATION(val, time, counter_name, counter_index)
};

std::string perf_counters::list_counter_internal(const std::vector<std::string>& args)
{
    // <app, <section, counter_info[] > > counters
    std::map<std::string, std::map< std::string, std::vector<counter_info> > > counters;
    std::map< std::string, std::vector<counter_info> > empty_m;
    std::vector<counter_info> empty_v;

    std::map< std::string, std::vector<counter_info> >* pp;
    std::vector<counter_info>* pv;

    {
        utils::auto_read_lock l(_lock);
        for (auto& c : _counters)
        {
            pp = &counters.insert(
                std::map<std::string, std::map< std::string, std::vector<counter_info> > >::value_type(
                c.second->app(),
                empty_m
                )
                ).first->second;

            pv = &pp->insert(
                std::map< std::string, std::vector<counter_info> >::value_type(
                c.second->section(),
                empty_v
                )
                ).first->second;

            pv->push_back({ c.second->name(), c.second->index() });
        }
    }

    std::stringstream ss;
    std::json_encode(ss, counters);
    return ss.str();
}

std::string perf_counters::get_counter_value(const std::vector<std::string>& args)
{
    std::stringstream ss;

    uint64_t ts = dsn_now_ns();
    double value = 0;
    uint64_t counter_index = 0;

    if (args.size() < 1)
    {
        value_resp{ value, ts, std::string(), 0 }.json_state(ss);
        return ss.str();
    }

    perf_counters& c = perf_counters::instance();
    auto counter = c.get_counter(args[0].c_str());

    if (counter)
    {
        counter_index = counter->index();
        if(counter->type() != COUNTER_TYPE_NUMBER_PERCENTILES)
            value = counter->get_value();
    }

    value_resp{ value, ts, args[0], counter_index }.json_state(ss);
    return ss.str();
}

std::string perf_counters::get_counter_sample(const std::vector<std::string>& args)
{
    std::stringstream ss;

    uint64_t ts = dsn_now_ns();
    uint64_t sample = 0;
    uint64_t counter_index = 0;

    if (args.size() < 1)
    {
        sample_resp{ sample, ts, std::string(), 0 }.json_state(ss);
        return ss.str();
    }

    perf_counters& c = perf_counters::instance();
    auto counter = c.get_counter(args[0].c_str());

    if (counter)
    {
        sample = counter->get_latest_sample();
        counter_index = counter->index();
    }
    sample_resp{ sample, ts, args[0], counter_index }.json_state(ss);
    return ss.str();
}

std::string perf_counters::get_counter_value_i(const std::vector<std::string>& args)
{
    std::stringstream ss;

    uint64_t ts = dsn_now_ns();
    double value = 0;
    std::string counter_name = std::string();

    if (args.size() < 1)
    {
        value_resp{ value, ts, std::string(), 0 }.json_state(ss);
        return ss.str();
    }

    uint64_t idx = atoll(args[0].c_str());

    perf_counters& c = perf_counters::instance();
    auto counter = c.get_counter(idx);

    if (counter)
    {
        counter_name = std::string(counter->full_name());
        if(counter->type() != COUNTER_TYPE_NUMBER_PERCENTILES)
            value = counter->get_value();
    }

    value_resp{ value, ts, counter_name, idx }.json_state(ss);
    return ss.str();
}

std::string perf_counters::get_counter_sample_i(const std::vector<std::string>& args)
{
    std::stringstream ss;

    uint64_t ts = dsn_now_ns();
    uint64_t sample = 0;
    std::string counter_name = std::string();

    if (args.size() < 1)
    {
        sample_resp{ sample, ts, std::string(), 0 }.json_state(ss);
        return ss.str();
    }

    uint64_t idx = atoll(args[0].c_str());

    perf_counters& c = perf_counters::instance();
    auto counter = c.get_counter(idx);

    if (counter)
    {
        sample = counter->get_latest_sample();
        counter_name = std::string(counter->full_name());
    }
    sample_resp{ sample, ts, counter_name, idx }.json_state(ss);
    return ss.str();
}

std::string perf_counters::get_counter_index(const std::vector<std::string>& args)
{
    std::stringstream ss;

    std::vector<uint64_t> counter_index_list;

    for (auto counter_name : args)
    {
        perf_counters& c = perf_counters::instance();
        auto counter = c.get_counter(counter_name.c_str());
        if (counter)
            counter_index_list.push_back(counter->index());
        else
            counter_index_list.push_back(0);
    }

    std::json_encode(ss, counter_index_list);
    return ss.str();
}

} // end namespace

<|endoftext|>


<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2014-2015 Pedro Côrte-Real
    Copyright (C) 2017 Roman Lebedev

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "decompressors/OlympusDecompressor.h"
#include "common/Common.h"                // for uint32, ushort16, uchar8
#include "common/Point.h"                 // for iPoint2D
#include "common/RawImage.h"              // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "io/BitPumpMSB.h"                // for BitPumpMSB
#include "io/ByteStream.h"                // for ByteStream
#include <algorithm>                      // for min
#include <array>                          // for array, array<>::value_type
#include <cassert>                        // for assert
#include <cmath>                          // for abs
#include <cstdlib>                        // for abs
#include <memory>                         // for unique_ptr
#include <type_traits>                    // for enable_if_t, is_integral

namespace {

// Normally, we'd just use std::signbit(int) here. But, some (non-conforming?)
// compilers do not provide that overload, so the code simply fails to compile.
// One could cast the int to the double, but at least right now that results
// in a horrible code. So let's just provide our own signbit(). It compiles to
// the exact same code as the std::signbit(int).
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
constexpr __attribute__((const)) bool SignBit(T x) {
  return x < 0;
}

} // namespace

namespace rawspeed {

OlympusDecompressor::OlympusDecompressor(const RawImage& img) : mRaw(img) {
  if (mRaw->getCpp() != 1 || mRaw->getDataType() != TYPE_USHORT16 ||
      mRaw->getBpp() != 2)
    ThrowRDE("Unexpected component count / data type");

  const uint32 w = mRaw->dim.x;
  const uint32 h = mRaw->dim.y;

  if (w == 0 || h == 0 || w % 2 != 0 || w > 10400 || h > 7792)
    ThrowRDE("Unexpected image dimensions found: (%u; %u)", w, h);
}

/* This is probably the slowest decoder of them all.
 * I cannot see any way to effectively speed up the prediction
 * phase, which is by far the slowest part of this algorithm.
 * Also there is no way to multithread this code, since prediction
 * is based on the output of all previous pixel (bar the first four)
 */

void OlympusDecompressor::decompress(ByteStream input) const {
  assert(mRaw->dim.y > 0);
  assert(mRaw->dim.x > 0);
  assert(mRaw->dim.x % 2 == 0);

  int nbits;
  int sign;
  int low;
  int high;
  int i;
  std::array<int, 2> left{{}};
  std::array<int, 2> nw{{}};
  int pred;
  int diff;

  uchar8* data = mRaw->getData();
  int pitch = mRaw->pitch;

  /* Build a table to quickly look up "high" value */
  std::unique_ptr<char[]> bittable(new char[4096]);

  for (i = 0; i < 4096; i++) {
    int b = i;
    for (high = 0; high < 12; high++)
      if ((b >> (11 - high)) & 1)
        break;
    bittable[i] = std::min(12, high);
  }

  input.skipBytes(7);
  BitPumpMSB bits(input);

  for (uint32 y = 0; y < static_cast<uint32>(mRaw->dim.y); y++) {
    std::array<std::array<int, 3>, 2> acarry{{}};

    auto* dest = reinterpret_cast<ushort16*>(&data[y * pitch]);
    bool y_border = y < 2;
    bool border = true;
    for (uint32 x = 0; x < static_cast<uint32>(mRaw->dim.x); x++) {
      int c = 0;

      bits.fill();
      i = 2 * (acarry[c][2] < 3);
      for (nbits = 2 + i; static_cast<ushort16>(acarry[c][0]) >> (nbits + i);
           nbits++)
        ;

      int b = bits.peekBitsNoFill(15);
      sign = (b >> 14) * -1;
      low = (b >> 12) & 3;
      high = bittable[b & 4095];

      // Skip bytes used above or read bits
      if (high == 12) {
        bits.skipBitsNoFill(15);
        high = bits.getBits(16 - nbits) >> 1;
      } else
        bits.skipBitsNoFill(high + 1 + 3);

      acarry[c][0] = (high << nbits) | bits.getBits(nbits);
      diff = (acarry[c][0] ^ sign) + acarry[c][1];
      acarry[c][1] = (diff * 3 + acarry[c][1]) >> 5;
      acarry[c][2] = acarry[c][0] > 16 ? 0 : acarry[c][2] + 1;

      if (border) {
        if (y_border && x < 2)
          pred = 0;
        else {
          if (y_border)
            pred = left[c];
          else {
            pred = dest[-pitch + (static_cast<int>(x))];
            nw[c] = pred;
          }
        }
        // Set predictor
        left[c] = pred + ((diff * 4) | low);
        // Set the pixel
        dest[x] = left[c];
      } else {
        // Have local variables for values used several tiles
        // (having a "ushort16 *dst_up" that caches dest[-pitch+((int)x)] is
        // actually slower, probably stack spill or aliasing)
        int up = dest[-pitch + (static_cast<int>(x))];
        int leftMinusNw = left[c] - nw[c];
        int upMinusNw = up - nw[c];
        // Check if sign is different, and they are both not zero
        if ((SignBit(leftMinusNw) ^ SignBit(upMinusNw)) &&
            (leftMinusNw != 0 && upMinusNw != 0)) {
          if (std::abs(leftMinusNw) > 32 || std::abs(upMinusNw) > 32)
            pred = left[c] + upMinusNw;
          else
            pred = (left[c] + up) >> 1;
        } else
          pred = std::abs(leftMinusNw) > std::abs(upMinusNw) ? left[c] : up;

        // Set predictors
        left[c] = pred + ((diff * 4) | low);
        nw[c] = up;
        // Set the pixel
        dest[x] = left[c];
      }

      // ODD PIXELS
      x += 1;
      c = 1;
      bits.fill();
      i = 2 * (acarry[c][2] < 3);
      for (nbits = 2 + i; static_cast<ushort16>(acarry[c][0]) >> (nbits + i);
           nbits++)
        ;
      b = bits.peekBitsNoFill(15);
      sign = (b >> 14) * -1;
      low = (b >> 12) & 3;
      high = bittable[b & 4095];

      // Skip bytes used above or read bits
      if (high == 12) {
        bits.skipBitsNoFill(15);
        high = bits.getBits(16 - nbits) >> 1;
      } else
        bits.skipBitsNoFill(high + 1 + 3);

      acarry[c][0] = (high << nbits) | bits.getBits(nbits);
      diff = (acarry[c][0] ^ sign) + acarry[c][1];
      acarry[c][1] = (diff * 3 + acarry[c][1]) >> 5;
      acarry[c][2] = acarry[c][0] > 16 ? 0 : acarry[c][2] + 1;

      if (border) {
        if (y_border && x < 2)
          pred = 0;
        else {
          if (y_border)
            pred = left[c];
          else {
            pred = dest[-pitch + (static_cast<int>(x))];
            nw[c] = pred;
          }
        }
        // Set predictor
        left[c] = pred + ((diff * 4) | low);
        // Set the pixel
        dest[x] = left[c];
      } else {
        int up = dest[-pitch + (static_cast<int>(x))];
        int leftMinusNw = left[c] - nw[c];
        int upMinusNw = up - nw[c];

        // Check if sign is different, and they are both not zero
        if ((SignBit(leftMinusNw) ^ SignBit(upMinusNw)) &&
            (leftMinusNw != 0 && upMinusNw != 0)) {
          if (std::abs(leftMinusNw) > 32 || std::abs(upMinusNw) > 32)
            pred = left[c] + upMinusNw;
          else
            pred = (left[c] + up) >> 1;
        } else
          pred = std::abs(leftMinusNw) > std::abs(upMinusNw) ? left[c] : up;

        // Set predictors
        left[c] = pred + ((diff * 4) | low);
        nw[c] = up;
        // Set the pixel
        dest[x] = left[c];
      }
      border = y_border;
    }
  }
}

} // namespace rawspeed
<commit_msg>Partially revert "OlympusDecompressor: address implicit-truncation issue #143"<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2014-2015 Pedro Côrte-Real
    Copyright (C) 2017 Roman Lebedev

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "decompressors/OlympusDecompressor.h"
#include "common/Common.h"                // for uint32, ushort16, uchar8
#include "common/Point.h"                 // for iPoint2D
#include "common/RawImage.h"              // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "io/BitPumpMSB.h"                // for BitPumpMSB
#include "io/ByteStream.h"                // for ByteStream
#include <algorithm>                      // for min
#include <array>                          // for array, array<>::value_type
#include <cassert>                        // for assert
#include <cmath>                          // for abs
#include <cstdlib>                        // for abs
#include <memory>                         // for unique_ptr
#include <type_traits>                    // for enable_if_t, is_integral

namespace {

// Normally, we'd just use std::signbit(int) here. But, some (non-conforming?)
// compilers do not provide that overload, so the code simply fails to compile.
// One could cast the int to the double, but at least right now that results
// in a horrible code. So let's just provide our own signbit(). It compiles to
// the exact same code as the std::signbit(int).
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
constexpr __attribute__((const)) bool SignBit(T x) {
  return x < 0;
}

} // namespace

namespace rawspeed {

OlympusDecompressor::OlympusDecompressor(const RawImage& img) : mRaw(img) {
  if (mRaw->getCpp() != 1 || mRaw->getDataType() != TYPE_USHORT16 ||
      mRaw->getBpp() != 2)
    ThrowRDE("Unexpected component count / data type");

  const uint32 w = mRaw->dim.x;
  const uint32 h = mRaw->dim.y;

  if (w == 0 || h == 0 || w % 2 != 0 || w > 10400 || h > 7792)
    ThrowRDE("Unexpected image dimensions found: (%u; %u)", w, h);
}

/* This is probably the slowest decoder of them all.
 * I cannot see any way to effectively speed up the prediction
 * phase, which is by far the slowest part of this algorithm.
 * Also there is no way to multithread this code, since prediction
 * is based on the output of all previous pixel (bar the first four)
 */

void OlympusDecompressor::decompress(ByteStream input) const {
  assert(mRaw->dim.y > 0);
  assert(mRaw->dim.x > 0);
  assert(mRaw->dim.x % 2 == 0);

  int nbits;
  int sign;
  int low;
  int high;
  int i;
  std::array<int, 2> left{{}};
  std::array<int, 2> nw{{}};
  int pred;
  int diff;

  uchar8* data = mRaw->getData();
  int pitch = mRaw->pitch;

  /* Build a table to quickly look up "high" value */
  std::unique_ptr<char[]> bittable(new char[4096]);

  for (i = 0; i < 4096; i++) {
    int b = i;
    for (high = 0; high < 12; high++)
      if ((b >> (11 - high)) & 1)
        break;
    bittable[i] = std::min(12, high);
  }

  input.skipBytes(7);
  BitPumpMSB bits(input);

  for (uint32 y = 0; y < static_cast<uint32>(mRaw->dim.y); y++) {
    std::array<std::array<int, 3>, 2> acarry{{}};

    auto* dest = reinterpret_cast<ushort16*>(&data[y * pitch]);
    bool y_border = y < 2;
    bool border = true;
    for (uint32 x = 0; x < static_cast<uint32>(mRaw->dim.x); x++) {
      int c = 0;

      bits.fill();
      i = 2 * (acarry[c][2] < 3);
      for (nbits = 2 + i; static_cast<ushort16>(acarry[c][0]) >> (nbits + i);
           nbits++)
        ;

      int b = bits.peekBitsNoFill(15);
      sign = (b >> 14) * -1;
      low = (b >> 12) & 3;
      high = bittable[b & 4095];

      // Skip bytes used above or read bits
      if (high == 12) {
        bits.skipBitsNoFill(15);
        high = bits.getBits(16 - nbits) >> 1;
      } else
        bits.skipBitsNoFill(high + 1 + 3);

      acarry[c][0] = (high << nbits) | bits.getBits(nbits);
      diff = (acarry[c][0] ^ sign) + acarry[c][1];
      acarry[c][1] = (diff * 3 + acarry[c][1]) >> 5;
      acarry[c][2] = acarry[c][0] > 16 ? 0 : acarry[c][2] + 1;

      if (border) {
        if (y_border && x < 2)
          pred = 0;
        else {
          if (y_border)
            pred = left[c];
          else {
            pred = dest[-pitch + (static_cast<int>(x))];
            nw[c] = pred;
          }
        }
        // Set predictor
        left[c] = pred + ((diff * 4) | low);
        // Set the pixel
        dest[x] = ushort16(left[c]);
      } else {
        // Have local variables for values used several tiles
        // (having a "ushort16 *dst_up" that caches dest[-pitch+((int)x)] is
        // actually slower, probably stack spill or aliasing)
        int up = dest[-pitch + (static_cast<int>(x))];
        int leftMinusNw = left[c] - nw[c];
        int upMinusNw = up - nw[c];
        // Check if sign is different, and they are both not zero
        if ((SignBit(leftMinusNw) ^ SignBit(upMinusNw)) &&
            (leftMinusNw != 0 && upMinusNw != 0)) {
          if (std::abs(leftMinusNw) > 32 || std::abs(upMinusNw) > 32)
            pred = left[c] + upMinusNw;
          else
            pred = (left[c] + up) >> 1;
        } else
          pred = std::abs(leftMinusNw) > std::abs(upMinusNw) ? left[c] : up;

        // Set predictors
        left[c] = pred + ((diff * 4) | low);
        nw[c] = up;
        // Set the pixel
        dest[x] = ushort16(left[c]);
      }

      // ODD PIXELS
      x += 1;
      c = 1;
      bits.fill();
      i = 2 * (acarry[c][2] < 3);
      for (nbits = 2 + i; static_cast<ushort16>(acarry[c][0]) >> (nbits + i);
           nbits++)
        ;
      b = bits.peekBitsNoFill(15);
      sign = (b >> 14) * -1;
      low = (b >> 12) & 3;
      high = bittable[b & 4095];

      // Skip bytes used above or read bits
      if (high == 12) {
        bits.skipBitsNoFill(15);
        high = bits.getBits(16 - nbits) >> 1;
      } else
        bits.skipBitsNoFill(high + 1 + 3);

      acarry[c][0] = (high << nbits) | bits.getBits(nbits);
      diff = (acarry[c][0] ^ sign) + acarry[c][1];
      acarry[c][1] = (diff * 3 + acarry[c][1]) >> 5;
      acarry[c][2] = acarry[c][0] > 16 ? 0 : acarry[c][2] + 1;

      if (border) {
        if (y_border && x < 2)
          pred = 0;
        else {
          if (y_border)
            pred = left[c];
          else {
            pred = dest[-pitch + (static_cast<int>(x))];
            nw[c] = pred;
          }
        }
        // Set predictor
        left[c] = pred + ((diff * 4) | low);
        // Set the pixel
        dest[x] = ushort16(left[c]);
      } else {
        int up = dest[-pitch + (static_cast<int>(x))];
        int leftMinusNw = left[c] - nw[c];
        int upMinusNw = up - nw[c];

        // Check if sign is different, and they are both not zero
        if ((SignBit(leftMinusNw) ^ SignBit(upMinusNw)) &&
            (leftMinusNw != 0 && upMinusNw != 0)) {
          if (std::abs(leftMinusNw) > 32 || std::abs(upMinusNw) > 32)
            pred = left[c] + upMinusNw;
          else
            pred = (left[c] + up) >> 1;
        } else
          pred = std::abs(leftMinusNw) > std::abs(upMinusNw) ? left[c] : up;

        // Set predictors
        left[c] = pred + ((diff * 4) | low);
        nw[c] = up;
        // Set the pixel
        dest[x] = ushort16(left[c]);
      }
      border = y_border;
    }
  }
}

} // namespace rawspeed
<|endoftext|>


<commit_before>//
// Copyright (c) 2017 Michael W Powell <mwpowellhtx@gmail.com>
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include <catch.hpp>
#include <nngcpp.h>

#include <string>
#include <memory>
#include <thread>

#ifndef _WIN32

    #include <poll.h>
    #include <unistd.h>
    #define INVALID_SOCKET -1

#else // _WIN32

    #define poll WSAPoll

    #ifndef WIN32_LEAN_AND_MEAN
        #define WIN32_LEAN_AND_MEAN
    #endif // WIN32_LEAN_AND_MEAN

    #include <Windows.h>
    #include <WinSock2.h>

    #include <MSWSock.h>
    #include <WS2tcpip.h>

#endif // _WIN32

TEST_CASE("Poll FDs", "[pollfd]") {

    using namespace std;
    using namespace nng;
    using namespace nng::protocol;
    using _opt_ = option_names;

    std::unique_ptr<latest_pair_socket> s1;
    std::unique_ptr<latest_pair_socket> s2;

    SECTION("Given a connected Pair of Sockets") {

        // Same as ::nng_pair_open(...) == 0
        REQUIRE_NOTHROW(s1 = std::make_unique<latest_pair_socket>());
        REQUIRE_NOTHROW(s2 = std::make_unique<latest_pair_socket>());

        /* It is a known idiomatic thing that Windows Sockets are treated as 64-bit integers, sort of.
        Yet, cross platform, and with the options, it is more accurate to simply treat them as 32-bit
        integers. */

        const auto inv_sock = INVALID_SOCKET;
        const string addr = "inproc://yeahbaby";

        // Should be ~= ::nng_listen(s, addr, listenerp, 0) == 0
        REQUIRE_NOTHROW(s1->listen(addr));
        this_thread::sleep_for(50ms);

        REQUIRE_NOTHROW(s2->dial(addr));
        this_thread::sleep_for(50ms);

        SECTION("We can get a Receive File Descriptor") {
            int fd;
            //REQUIRE_NOTHROW(s1->get_option_int(_opt_::receive_file_descriptor, &fd));
            REQUIRE_NOTHROW(s1->get_option_int(_opt_::receive_file_descriptor, &fd));
            REQUIRE(fd != inv_sock);

            SECTION("And it is always the same File Descriptor") {
                int fd2;
                REQUIRE_NOTHROW(s1->get_option_int(_opt_::receive_file_descriptor, &fd2));
                REQUIRE(fd2 == fd);
            }

            SECTION("And they start non pollable") {
                pollfd pfd{ (SOCKET)fd, POLLIN, 0 };
                REQUIRE(::poll(&pfd, 1, 0) == 0);
                REQUIRE(pfd.revents == 0);
            }

            SECTION("But if we write they are pollable") {
                pollfd pfd{ (SOCKET)fd, POLLIN, 0 };
                REQUIRE_NOTHROW(s2->send("kick")); // TODO: TBD: send appears to be blocking
                REQUIRE(::poll(&pfd, 1, 1000) == 1);
                REQUIRE((pfd.revents&POLLIN));
            }
        }

        SECTION("We can get a Send File Descriptor") {
            int fd;
            REQUIRE_NOTHROW(s1->get_option_int(_opt_::send_file_descriptor, &fd));
            REQUIRE(fd != inv_sock);
            REQUIRE_NOTHROW(s1->send("oops"));
        }

        SECTION("Must have big enough size") {
            INFO("At least for now, we simply do not expose the general get/set options API through the C++ wrapper.");
        }

        SECTION("We cannot get a Send File Descriptor for Pull Socket") {

            std::unique_ptr<latest_pull_socket> s3;
            REQUIRE_NOTHROW(s3 = std::make_unique<latest_pull_socket>());

            int fd;
            // TODO: TBD: work on exception handling...
            REQUIRE_THROWS_AS(s3->get_option_int(_opt_::send_file_descriptor, &fd), nng_exception);

            SECTION("Destructor cleans up correctly") {
                REQUIRE(s3.release() == nullptr);
            }
        }

        SECTION("We cannot get a Receive File Descriptor for Push Socket") {

            std::unique_ptr<latest_push_socket> s3;
            REQUIRE_NOTHROW(s3 = std::make_unique<latest_push_socket>());

            int fd;
            // TODO: TBD: work on exception handling...
            REQUIRE_THROWS_AS(s3->get_option_int(_opt_::receive_file_descriptor, &fd), nng_exception);

            SECTION("Destructor cleans up correctly") {
                REQUIRE(s3.release() == nullptr);
            }
        }
    }

    SECTION("Destructors do not throw") {
        REQUIRE_NOTHROW(s1.release() == nullptr);
        REQUIRE_NOTHROW(s2.release() == nullptr);
    }
}
<commit_msg>updated unit testing around latest patterns<commit_after>//
// Copyright (c) 2017 Michael W Powell <mwpowellhtx@gmail.com>
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
// Copyright 2017 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include "../catch/catch_exception_matcher_base.hpp"
#include "../catch/catch_exception_translations.hpp"
#include "../catch/catch_nng_exception_matcher.hpp"
#include "../catch/catch_macros.hpp"

#include <nngcpp.h>

#include <string>
#include <memory>
#include <thread>

#ifndef _WIN32

    #include <poll.h>
    #include <unistd.h>
    #define INVALID_SOCKET -1

#else // _WIN32

    #define poll WSAPoll

    #ifndef WIN32_LEAN_AND_MEAN
        #define WIN32_LEAN_AND_MEAN
    #endif // WIN32_LEAN_AND_MEAN

    #include <Windows.h>
    #include <WinSock2.h>

    #include <MSWSock.h>
    #include <WS2tcpip.h>

#endif // _WIN32

namespace constants {
    const std::string addr = "inproc://yeahbaby";
}

TEST_CASE("Poll FDs", "[pollfd]") {

    using namespace std;
    using namespace nng;
    using namespace nng::protocol;
    using namespace Catch::Matchers;
    using namespace constants;
    using _opt_ = option_names;

    std::unique_ptr<latest_pair_socket> s1, s2;

    REQUIRE(s1 == nullptr);
    REQUIRE(s2 == nullptr);

    SECTION("Given a connected Pair of Sockets") {

        // Same as ::nng_pair_open(...) == 0
        REQUIRE_NOTHROW(s1 = make_unique<latest_pair_socket>());
        REQUIRE_NOTHROW(s2 = make_unique<latest_pair_socket>());

        /* It is a known idiomatic thing that Windows Sockets are treated as 64-bit integers, sort of.
        Yet, cross platform, and with the options, it is more accurate to simply treat them as 32-bit
        integers. */

        const auto inv_sock = INVALID_SOCKET;

        // Should be ~= ::nng_listen(s, addr, listenerp, 0) == 0
        REQUIRE_NOTHROW(s1->listen(addr));
        this_thread::sleep_for(50ms);

        REQUIRE_NOTHROW(s2->dial(addr));
        this_thread::sleep_for(50ms);

        SECTION("We can get a Receive File Descriptor") {
            int fd;
            //REQUIRE_NOTHROW(s1->get_option_int(_opt_::receive_file_descriptor, &fd));
            REQUIRE_NOTHROW(s1->get_option_int(_opt_::receive_file_descriptor, &fd));
            REQUIRE(fd != inv_sock);

            SECTION("And it is always the same File Descriptor") {
                int fd2;
                REQUIRE_NOTHROW(s1->get_option_int(_opt_::receive_file_descriptor, &fd2));
                REQUIRE(fd2 == fd);
            }

            SECTION("And they start non pollable") {
                pollfd pfd{ (SOCKET)fd, POLLIN, 0 };
                REQUIRE(::poll(&pfd, 1, 0) == 0);
                REQUIRE(pfd.revents == 0);
            }

            SECTION("But if we write they are pollable") {
                pollfd pfd{ (SOCKET)fd, POLLIN, 0 };
                REQUIRE_NOTHROW(s2->send("kick")); // TODO: TBD: send appears to be blocking
                REQUIRE(::poll(&pfd, 1, 1000) == 1);
                REQUIRE((pfd.revents&POLLIN));
            }
        }

        SECTION("We can get a Send File Descriptor") {
            int fd;
            REQUIRE_NOTHROW(s1->get_option_int(_opt_::send_file_descriptor, &fd));
            REQUIRE(fd != inv_sock);
            REQUIRE_NOTHROW(s1->send("oops"));
        }

        SECTION("Must have big enough size") {
            INFO("At least for now, we simply do not expose the general get/set options API through the C++ wrapper.");
        }

        SECTION("We cannot get a Send File Descriptor for Pull Socket") {

            std::unique_ptr<latest_pull_socket> s3;
            REQUIRE_NOTHROW(s3 = make_unique<latest_pull_socket>());

            int fd;
            // TODO: TBD: ditto working interim answer...
            REQUIRE_THROWS_AS_MATCHING(s3->get_option_int(_opt_::send_file_descriptor, &fd), nng_exception, ThrowsNngException(ec_enotsup));

            SECTION("Destructor cleans up correctly") {
                REQUIRE_NOTHROW(s3.reset());
                REQUIRE(s3 == nullptr);
            }
        }

        SECTION("We cannot get a Receive File Descriptor for Push Socket") {

            std::unique_ptr<latest_push_socket> s3;
            REQUIRE_NOTHROW(s3 = make_unique<latest_push_socket>());

            int fd;
            // TODO: TBD: this works as an interim measure, although the ResultBuilder needs a little help to better comprehend the result.
            REQUIRE_THROWS_AS_MATCHING(s3->get_option_int(_opt_::receive_file_descriptor, &fd), nng_exception, ThrowsNngException(ec_enotsup));

            SECTION("Destructor cleans up correctly") {
                REQUIRE_NOTHROW(s3.reset());
                REQUIRE(s3 == nullptr);
            }
        }
    }

    SECTION("Destructors do not throw") {
        REQUIRE_NOTHROW(s1.reset());
        REQUIRE_NOTHROW(s2.reset());
        REQUIRE(s1 == nullptr);
        REQUIRE(s2 == nullptr);
    }
}
<|endoftext|>