<commit_before>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_X86_SYSCALLRETURN_HH__
#define __ARCH_X86_SYSCALLRETURN_HH__

#include "base/misc.hh"
#include "cpu/thread_context.hh"
#include "sim/syscallreturn.hh"

namespace X86ISA
{
    static inline void setSyscallReturn(SyscallReturn return_value,
            ThreadContext * tc)
    {
        tc->setIntReg(INTREG_RAX, return_value.value());
    }
};

#endif // __ARCH_X86_SYSCALLRETURN_HH__
<commit_msg>X86: return -return_value.value() on failure.<commit_after>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_X86_SYSCALLRETURN_HH__
#define __ARCH_X86_SYSCALLRETURN_HH__

#include "base/misc.hh"
#include "cpu/thread_context.hh"
#include "sim/syscallreturn.hh"

namespace X86ISA
{
    static inline void setSyscallReturn(SyscallReturn return_value,
            ThreadContext * tc)
    {
        if (return_value.successful()) {
            tc->setIntReg(INTREG_RAX, return_value.value());
        } else {
            tc->setIntReg(INTREG_RAX, -return_value.value());
        }
    }
};

#endif // __ARCH_X86_SYSCALLRETURN_HH__
<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <Array.hpp>
#include <transform.hpp>
#include <math.hpp>
#include <stdexcept>
#include <err_cpu.hpp>
#include "transform_interp.hpp"

namespace cpu
{
    template <typename T>
    void calc_affine_inverse(T *txo, const T *txi)
    {
        T det = txi[0]*txi[4] - txi[1]*txi[3];

        txo[0] = txi[4] / det;
        txo[1] = txi[3] / det;
        txo[3] = txi[1] / det;
        txo[4] = txi[0] / det;

        txo[2] = txi[2] * -txo[0] + txi[5] * -txo[1];
        txo[5] = txi[2] * -txo[3] + txi[5] * -txo[4];
    }

    template <typename T>
    void calc_affine_inverse(T *tmat, const T *tmat_ptr, const bool inverse)
    {
        // The way kernel is structured, it expects an inverse
        // transform matrix by default.
        // If it is an forward transform, then we need its inverse
        if(inverse) {
            for(int i = 0; i < 6; i++)
                tmat[i] = tmat_ptr[i];
        } else {
            calc_affine_inverse(tmat, tmat_ptr);
        }
    }

    template<typename T, af_interp_type method>
    void transform_(T *out, const T *in, const float *tf,
                    const af::dim4 &odims, const af::dim4 &idims,
                    const af::dim4 &ostrides, const af::dim4 &istrides,
                    const af::dim4 &tstrides, const bool inverse)
    {
        dim_t nimages     = idims[2];
        // Multiplied in src/backend/transform.cpp
        dim_t ntransforms = odims[2] / idims[2];

        void (*t_fn)(T *, const T *, const float *, const af::dim4 &,
                     const af::dim4 &, const af::dim4 &,
                     const dim_t, const dim_t, const dim_t, const dim_t);

        switch(method) {
            case AF_INTERP_NEAREST:
                t_fn = &transform_n;
                break;
            case AF_INTERP_BILINEAR:
                t_fn = &transform_b;
                break;
            case AF_INTERP_LOWER:
                t_fn = &transform_l;
                break;
            default:
                AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
                break;
        }

        // For each transform channel
        for(int t_idx = 0; t_idx < (int)ntransforms; t_idx++) {
            // Compute inverse if required
            const float *tmat_ptr = tf + t_idx * 6;
            float tmat[6];
            calc_affine_inverse(tmat, tmat_ptr, inverse);

            // Offset for output pointer
            dim_t o_offset = t_idx * nimages * ostrides[2];

            // Do transform for image
            for(int yy = 0; yy < (int)odims[1]; yy++) {
                for(int xx = 0; xx < (int)odims[0]; xx++) {
                    t_fn(out, in, tmat, idims, ostrides, istrides, nimages, o_offset, xx, yy);
                }
            }
        }
    }

    template<typename T>
    Array<T> transform(const Array<T> &in, const Array<float> &transform, const af::dim4 &odims,
                        const af_interp_type method, const bool inverse)
    {
        const af::dim4 idims = in.dims();

        Array<T> out = createEmptyArray<T>(odims);

        switch(method) {
            case AF_INTERP_NEAREST:
                transform_<T, AF_INTERP_NEAREST>
                          (out.get(), in.get(), transform.get(), odims, idims,
                           out.strides(), in.strides(), transform.strides(), inverse);
                break;
            case AF_INTERP_BILINEAR:
                transform_<T, AF_INTERP_BILINEAR>
                          (out.get(), in.get(), transform.get(), odims, idims,
                           out.strides(), in.strides(), transform.strides(), inverse);
                break;
            case AF_INTERP_LOWER:
                transform_<T, AF_INTERP_LOWER>
                          (out.get(), in.get(), transform.get(), odims, idims,
                           out.strides(), in.strides(), transform.strides(), inverse);
                break;
            default:
                AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
                break;
        }

        return out;
    }

#define INSTANTIATE(T)                                                                  \
    template Array<T> transform(const Array<T> &in, const Array<float> &transform,      \
                                const af::dim4 &odims, const af_interp_type method,     \
                                const bool inverse);

    INSTANTIATE(float)
    INSTANTIATE(double)
    INSTANTIATE(cfloat)
    INSTANTIATE(cdouble)
    INSTANTIATE(int)
    INSTANTIATE(uint)
    INSTANTIATE(intl)
    INSTANTIATE(uintl)
    INSTANTIATE(uchar)
    INSTANTIATE(char)
    INSTANTIATE(short)
    INSTANTIATE(ushort)
}
<commit_msg>converted transform to async call<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <Array.hpp>
#include <transform.hpp>
#include <math.hpp>
#include <stdexcept>
#include <err_cpu.hpp>
#include <platform.hpp>
#include <async_queue.hpp>
#include "transform_interp.hpp"

namespace cpu
{

template <typename T>
void calc_affine_inverse(T *txo, const T *txi)
{
    T det = txi[0]*txi[4] - txi[1]*txi[3];

    txo[0] = txi[4] / det;
    txo[1] = txi[3] / det;
    txo[3] = txi[1] / det;
    txo[4] = txi[0] / det;

    txo[2] = txi[2] * -txo[0] + txi[5] * -txo[1];
    txo[5] = txi[2] * -txo[3] + txi[5] * -txo[4];
}

template <typename T>
void calc_affine_inverse(T *tmat, const T *tmat_ptr, const bool inverse)
{
    // The way kernel is structured, it expects an inverse
    // transform matrix by default.
    // If it is an forward transform, then we need its inverse
    if(inverse) {
        for(int i = 0; i < 6; i++)
            tmat[i] = tmat_ptr[i];
    } else {
        calc_affine_inverse(tmat, tmat_ptr);
    }
}

template<typename T, af_interp_type method>
void transform_(Array<T> output, const Array<T> input,
                const Array<float> transform, const bool inverse)
{
    const af::dim4 idims    = input.dims();
    const af::dim4 odims    = output.dims();
    const af::dim4 istrides = input.strides();
    const af::dim4 ostrides = output.strides();

    T * out = output.get();
    const T * in = input.get();
    const float* tf = transform.get();

    dim_t nimages     = idims[2];
    // Multiplied in src/backend/transform.cpp
    dim_t ntransforms = odims[2] / idims[2];

    void (*t_fn)(T *, const T *, const float *, const af::dim4 &,
                 const af::dim4 &, const af::dim4 &,
                 const dim_t, const dim_t, const dim_t, const dim_t);

    switch(method) {
        case AF_INTERP_NEAREST:
            t_fn = &transform_n;
            break;
        case AF_INTERP_BILINEAR:
            t_fn = &transform_b;
            break;
        case AF_INTERP_LOWER:
            t_fn = &transform_l;
            break;
        default:
            AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
            break;
    }

    // For each transform channel
    for(int t_idx = 0; t_idx < (int)ntransforms; t_idx++) {
        // Compute inverse if required
        const float *tmat_ptr = tf + t_idx * 6;
        float tmat[6];
        calc_affine_inverse(tmat, tmat_ptr, inverse);

        // Offset for output pointer
        dim_t o_offset = t_idx * nimages * ostrides[2];

        // Do transform for image
        for(int yy = 0; yy < (int)odims[1]; yy++) {
            for(int xx = 0; xx < (int)odims[0]; xx++) {
                t_fn(out, in, tmat, idims, ostrides, istrides, nimages, o_offset, xx, yy);
            }
        }
    }
}

template<typename T>
Array<T> transform(const Array<T> &in, const Array<float> &transform, const af::dim4 &odims,
                    const af_interp_type method, const bool inverse)
{
    Array<T> out = createEmptyArray<T>(odims);
    in.eval();

    switch(method) {
        case AF_INTERP_NEAREST :
            getQueue().enqueue(transform_<T, AF_INTERP_NEAREST >, out, in, transform, inverse);
            break;
        case AF_INTERP_BILINEAR:
            getQueue().enqueue(transform_<T, AF_INTERP_BILINEAR>, out, in, transform, inverse);
            break;
        case AF_INTERP_LOWER   :
            getQueue().enqueue(transform_<T, AF_INTERP_LOWER   >, out, in, transform, inverse);
            break;
        default: AF_ERROR("Unsupported interpolation type", AF_ERR_ARG); break;
    }

    return out;
}

#define INSTANTIATE(T)                                                              \
template Array<T> transform(const Array<T> &in, const Array<float> &transform,      \
                            const af::dim4 &odims, const af_interp_type method,     \
                            const bool inverse);

INSTANTIATE(float)
INSTANTIATE(double)
INSTANTIATE(cfloat)
INSTANTIATE(cdouble)
INSTANTIATE(int)
INSTANTIATE(uint)
INSTANTIATE(intl)
INSTANTIATE(uintl)
INSTANTIATE(uchar)
INSTANTIATE(char)
INSTANTIATE(short)
INSTANTIATE(ushort)

}
<|endoftext|>


<commit_before>/**********************************************************************
 * File:        mainblk.c  (Formerly main.c)
 * Description: Function to call from main() to setup.
 * Author:					Ray Smith
 * Created:					Tue Oct 22 11:09:40 BST 1991
 *
 * (C) Copyright 1991, Hewlett-Packard Ltd.
 ** 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 "mfcpch.h"
#include          "fileerr.h"
#ifdef __UNIX__
#include          <unistd.h>
#include          <signal.h>
#else
#include          <io.h>
#endif
#include          <stdlib.h>
#include          "basedir.h"
#include          "ccutil.h"

#define VARDIR        "configs/" /*variables files */
#define EXTERN

const ERRCODE NO_PATH =
"Warning:explicit path for executable will not be used for configs";
static const ERRCODE USAGE = "Usage";

namespace tesseract {
/**********************************************************************
 * main_setup
 *
 * Main for mithras demo program. Read the arguments and set up globals.
 **********************************************************************/

void CCUtil::main_setup(                 /*main demo program */
                const char *argv0,       //program name
                const char *basename     //name of image
               ) {
  imagebasename = basename;      /*name of image */
  STRING dll_module_name;
  #ifdef _WIN32
  dll_module_name = tessedit_module_name;
  #endif

  // TESSDATA_PREFIX Environment variable overrules everything.
  // Compiled in -DTESSDATA_PREFIX is next.
  // NULL goes to current directory.
  // An actual value of argv0 is used if getpath is successful.
  if (!getenv("TESSDATA_PREFIX")) {
#ifdef TESSDATA_PREFIX
#define _STR(a) #a
#define _XSTR(a) _STR(a)
    datadir = _XSTR(TESSDATA_PREFIX);
#undef _XSTR
#undef _STR
#else
    if (argv0 != NULL) {
      if (getpath(argv0, dll_module_name, datadir) < 0)
#ifdef __UNIX__
        CANTOPENFILE.error("main", ABORT, "%s to get path", argv0);
#else
        NO_PATH.error("main", DBG, NULL);
#endif
    } else {
      datadir = "./";
    }
#endif
  } else {
    datadir = getenv("TESSDATA_PREFIX");
  }

  datadir += m_data_sub_dir;     /*data directory */
}
}  // namespace tesseract
<commit_msg>fix issue 702.<commit_after>/**********************************************************************
 * File:        mainblk.c  (Formerly main.c)
 * Description: Function to call from main() to setup.
 * Author:					Ray Smith
 * Created:					Tue Oct 22 11:09:40 BST 1991
 *
 * (C) Copyright 1991, Hewlett-Packard Ltd.
 ** 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 "mfcpch.h"
#include          "fileerr.h"
#ifdef __UNIX__
#include          <unistd.h>
#include          <signal.h>
#else
#include          <io.h>
#endif
#include          <stdlib.h>
#include          "basedir.h"
#include          "ccutil.h"

#define VARDIR        "configs/" /*variables files */
#define EXTERN

const ERRCODE NO_PATH =
"Warning:explicit path for executable will not be used for configs";
static const ERRCODE USAGE = "Usage";

namespace tesseract {
/**********************************************************************
 * main_setup
 *
 * Main for mithras demo program. Read the arguments and set up globals.
 **********************************************************************/

void CCUtil::main_setup(                 /*main demo program */
                const char *argv0,       //program name
                const char *basename     //name of image
               ) {
  imagebasename = basename;      /*name of image */
  STRING dll_module_name;
  #ifdef _WIN32
  dll_module_name = tessedit_module_name;
  #endif

  // TESSDATA_PREFIX Environment variable overrules everything.
  // Compiled in -DTESSDATA_PREFIX is next.
  // NULL goes to current directory.
  // An actual value of argv0 is used if getpath is successful.
  if (!getenv("TESSDATA_PREFIX")) {
#ifdef TESSDATA_PREFIX
#define _STR(a) #a
#define _XSTR(a) _STR(a)
    datadir = _XSTR(TESSDATA_PREFIX);
#undef _XSTR
#undef _STR
#else
    if (argv0 != NULL) {
      if (getpath(argv0, dll_module_name, datadir) < 0)
#ifdef __UNIX__
        CANTOPENFILE.error("main", ABORT, "%s to get path", argv0);
#else
        NO_PATH.error("main", DBG, NULL);
#endif
    } else {
      datadir = "./";
    }
#endif
  } else {
    datadir = getenv("TESSDATA_PREFIX");
  }

  // check for missing directory separator
  const char *lastchar = datadir.string();
  lastchar += datadir.length() - 1;
  if ((strcmp(lastchar, "/") != 0) && (strcmp(lastchar, "\\") != 0))
    datadir += "/";

  datadir += m_data_sub_dir;     /*data directory */
}
}  // namespace tesseract
<|endoftext|>


<commit_before>/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; version 2 of the License.

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation,
  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */

/**
  @file storage/perfschema/pfs_check.cc
  Check the performance schema table structure.
  The code in this file is implemented in pfs_check.cc
  instead of pfs_server.cc, to separate dependencies to server
  structures (THD, ...) in a dedicated file.
  This code organization helps a lot maintenance of the unit tests.
*/

#include "my_global.h"
#include "pfs_server.h"
#include "pfs_engine_table.h"

/*
*/

/**
  Check that the performance schema tables
  have the expected structure.
  Discrepancies are written in the server log,
  but are not considered fatal, so this function does not
  return an error code:
  - some differences are compatible, and should not cause a failure
  - some differences are not compatible, but then the DBA needs an operational
  server to be able to DROP+CREATE the tables with the proper structure,
  as part of the initial server installation or during an upgrade.
  In case of discrepancies, later attempt to perform DML against
  the performance schema will be rejected with an error.
*/
void check_performance_schema()
{
  DBUG_ENTER("check_performance_schema");

  THD *thd= new THD();
  if (thd == NULL)
    DBUG_VOID_RETURN;

  thd->thread_stack= (char*) &thd;
  thd->store_globals();

  PFS_engine_table_share::check_all_tables(thd);

  delete thd;
  DBUG_VOID_RETURN;
}

<commit_msg>Bug#17928281 'CHECK_PERFORMANCE_SCHEMA()' LEAVES 'CURRENT_THD' REFERRING DESTRUCTED THD OBJ <commit_after>/* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; version 2 of the License.

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation,
  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */

/**
  @file storage/perfschema/pfs_check.cc
  Check the performance schema table structure.
  The code in this file is implemented in pfs_check.cc
  instead of pfs_server.cc, to separate dependencies to server
  structures (THD, ...) in a dedicated file.
  This code organization helps a lot maintenance of the unit tests.
*/

#include "my_global.h"
#include "pfs_server.h"
#include "pfs_engine_table.h"

/*
*/

/**
  Check that the performance schema tables
  have the expected structure.
  Discrepancies are written in the server log,
  but are not considered fatal, so this function does not
  return an error code:
  - some differences are compatible, and should not cause a failure
  - some differences are not compatible, but then the DBA needs an operational
  server to be able to DROP+CREATE the tables with the proper structure,
  as part of the initial server installation or during an upgrade.
  In case of discrepancies, later attempt to perform DML against
  the performance schema will be rejected with an error.
*/
void check_performance_schema()
{
  DBUG_ENTER("check_performance_schema");

  THD *thd= new THD();
  if (thd == NULL)
    DBUG_VOID_RETURN;

  thd->thread_stack= (char*) &thd;
  thd->store_globals();

  PFS_engine_table_share::check_all_tables(thd);

  thd->restore_globals();
  delete thd;
  DBUG_VOID_RETURN;
}

<|endoftext|>


<commit_before>/*
    SWARM

    Copyright (C) 2012-2022 Torbjorn Rognes and Frederic Mahe

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

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Contact: Torbjorn Rognes <torognes@ifi.uio.no>,
    Department of Informatics, University of Oslo,
    PO Box 1080 Blindern, NO-0316 Oslo, Norway
*/

#include "swarm.h"
#include "util.h"

void pushop(char newop, char ** cigarendp, char * op, int * count);
void finishop(char ** cigarendp, char * op, int * count);

void pushop(char newop, char ** cigarendp, char * op, int * count)
{
  constexpr unsigned int buffer_length {25};

  if (newop == *op) {
    (*count)++;
  }
  else
  {
    *--*cigarendp = *op;
    if (*count > 1)
    {
      char buf[buffer_length];
      int len = snprintf(buf, buffer_length, "%d", *count);
      assert(len >= 0);
      *cigarendp -= len;
      memcpy(*cigarendp, buf, static_cast<size_t>(len));
    }
    *op = newop;
    *count = 1;
  }
}

void finishop(char ** cigarendp, char * op, int * count)
{
  constexpr unsigned int buffer_length {25};

  if ((op != nullptr) && (count != nullptr))
  {
    *--*cigarendp = *op;
    if (*count > 1)
    {
      char buf[buffer_length];
      int len = snprintf(buf, buffer_length, "%d", *count);
      assert(len >= 0);
      *cigarendp -= len;
      memcpy(*cigarendp, buf, static_cast<size_t>(len));
    }
    *op = 0;
    *count = 0;
  }
}

const unsigned char maskup      = 1;
const unsigned char maskleft    = 2;
const unsigned char maskextup   = 4;
const unsigned char maskextleft = 8;

/*

  Needleman/Wunsch/Sellers aligner

  finds a global alignment with minimum cost
  there should be positive costs/penalties for gaps and for mismatches
  matches should have zero cost (0)

  alignment priority when backtracking (from lower right corner):
  1. left/insert/e (gap in query sequence (qseq))
  2. align/diag/h (match/mismatch)
  3. up/delete/f (gap in database sequence (dseq))

  qseq: the reference/query/upper/vertical/from sequence
  dseq: the sample/database/lower/horisontal/to sequence

  typical costs:
  match: 0
  mismatch: 3
  gapopen: 4
  gapextend: 3

  input

  dseq: pointer to start of database sequence
  dend: pointer after database sequence
  qseq: pointer to start of query sequence
  qend: pointer after database sequence
  score_matrix: 32x32 matrix of longs with scores for aligning two symbols
  gapopen: positive number indicating penalty for opening a gap of length zero
  gapextend: positive number indicating penalty for extending a gap

  output

  nwscore: the global alignment score
  nwdiff: number of non-identical nucleotides in one optimal global alignment
  nwalignmentlength: the length of one optimal alignment
  nwalignment: cigar string with one optimal alignment

*/

void nw(char * dseq,
        int64_t dlen,
        char * qseq,
        int64_t qlen,
        int64_t * score_matrix,
        int64_t gapopen,
        int64_t gapextend,
        int64_t * nwscore,
        int64_t * nwdiff,
        int64_t * nwalignmentlength,
        char ** nwalignment,
        unsigned char * dir,
        int64_t * hearray,
        uint64_t queryno,
        uint64_t dbseqno)
{
  /* dir must point to at least qlen*dlen bytes of allocated memory
     hearray must point to at least 2*qlen longs of allocated memory
     (8*qlen bytes) */
  constexpr unsigned int multiplier {5};

  int64_t n {0};
  int64_t e {0};

  memset(dir, 0, static_cast<size_t>(qlen * dlen));

  for(auto i = 0L; i < qlen; i++)
    {
      hearray[2 * i]     = 1 * gapopen + (i + 1) * gapextend; // H (N)
      hearray[2 * i + 1] = 2 * gapopen + (i + 2) * gapextend; // E
    }

  for(auto j = 0L; j < dlen; j++)
    {
      int64_t * hep {nullptr};
      hep = hearray;
      int64_t f = 2 * gapopen + (j+2) * gapextend;
      int64_t h = (j == 0) ? 0 : (gapopen + j * gapextend);

      for(auto i = 0L; i < qlen; i++)
        {
          int64_t index = qlen * j + i;

          n = *hep;
          e = *(hep+1);
          h += score_matrix
            [((nt_extract(dseq, static_cast<uint64_t>(j)) + 1) << multiplier)
             +(nt_extract(qseq, static_cast<uint64_t>(i)) + 1)];

          dir[index] |= (f < h ? maskup : 0);
          h = std::min(h, f);
          h = std::min(h, e);
          dir[index] |= (e == h ? maskleft : 0);

          *hep = h;

          h += gapopen + gapextend;
          e += gapextend;
          f += gapextend;

          dir[index] |= (f < h ? maskextup : 0);
          dir[index] |= (e < h ? maskextleft : 0);
          f = std::min(h,f);
          e = std::min(h,e);

          *(hep+1) = e;
          h = n;
          hep += 2;
        }
    }

  int64_t dist = hearray[2 * qlen - 2];

  /* backtrack: count differences and save alignment in cigar string */
  int64_t score {0};
  int64_t alength {0};
  int64_t matches {0};

  char * cigar = new char[static_cast<size_t>(qlen + dlen + 1)];
  char * cigarend {cigar + qlen + dlen + 1};

  char op {0};
  int count {0};
  *(--cigarend) = 0;

  int64_t i = qlen;
  int64_t j = dlen;

  while ((i>0) && (j>0))
    {
      int d = dir[qlen*(j-1)+(i-1)];

      alength++;

      if ((op == 'I') && ((d & maskextleft) != 0))
        {
          score += gapextend;
          j--;
          pushop('I', &cigarend, &op, &count);
        }
      else if ((op == 'D') && ((d & maskextup) != 0))
        {
          score += gapextend;
          i--;
          pushop('D', &cigarend, &op, &count);
        }
      else if ((d & maskleft) != 0)
        {
          score += gapextend;
          if (op != 'I') {
            score += gapopen;
          }
          j--;
          pushop('I', &cigarend, &op, &count);
        }
      else if ((d & maskup) != 0)
        {
          score += gapextend;
          if (op != 'D') {
            score += gapopen;
          }
          i--;
          pushop('D', &cigarend, &op, &count);
        }
      else
        {
          score += score_matrix
            [((nt_extract(dseq, static_cast<uint64_t>(j - 1)) + 1) << multiplier)
             +(nt_extract(qseq, static_cast<uint64_t>(i - 1)) + 1)];

          if (nt_extract(qseq, static_cast<uint64_t>(i - 1)) ==
              nt_extract(dseq, static_cast<uint64_t>(j - 1))) {
            matches++;
          }
          i--;
          j--;
          pushop('M', &cigarend, &op, &count);
        }
    }

  while(i>0)
    {
      alength++;
      score += gapextend;
      if (op != 'D') {
        score += gapopen;
      }
      i--;
      pushop('D', &cigarend, &op, &count);
    }

  while(j>0)
    {
      alength++;
      score += gapextend;
      if (op != 'I') {
        score += gapopen;
      }
      j--;
      pushop('I', &cigarend, &op, &count);
    }

  finishop(&cigarend, &op, &count);

  /* move and reallocate cigar */

  auto cigaralloc = static_cast<size_t>(cigar + qlen + dlen - cigarend + 1);
  memmove(cigar, cigarend, cigaralloc);
  cigar = static_cast<char*>(xrealloc(cigar, cigaralloc));

  * nwscore = dist;
  * nwdiff = alength - matches;
  * nwalignmentlength = alength;
  * nwalignment = cigar;

  assert(score == dist);

#if 0
  if (score != dist)
  {
    fprintf(stderr,
            "WARNING: Error with query no %" PRIu64 " and db sequence no %" PRIu64 ":\n",
            queryno, dbseqno);
    fprintf(stderr,
            "Initial and recomputed alignment score disagreement: %" PRId64 " %" PRId64 "\n",
            dist, score);
    fprintf(stderr, "Alignment: %s\n", cigar);
  }
#else
  (void) queryno;
  (void) dbseqno;
#endif
}
<commit_msg>remove debugging code<commit_after>/*
    SWARM

    Copyright (C) 2012-2022 Torbjorn Rognes and Frederic Mahe

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

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Contact: Torbjorn Rognes <torognes@ifi.uio.no>,
    Department of Informatics, University of Oslo,
    PO Box 1080 Blindern, NO-0316 Oslo, Norway
*/

#include "swarm.h"
#include "util.h"

void pushop(char newop, char ** cigarendp, char * op, int * count);
void finishop(char ** cigarendp, char * op, int * count);

void pushop(char newop, char ** cigarendp, char * op, int * count)
{
  constexpr unsigned int buffer_length {25};

  if (newop == *op) {
    (*count)++;
  }
  else
  {
    *--*cigarendp = *op;
    if (*count > 1)
    {
      char buf[buffer_length];
      int len = snprintf(buf, buffer_length, "%d", *count);
      assert(len >= 0);
      *cigarendp -= len;
      memcpy(*cigarendp, buf, static_cast<size_t>(len));
    }
    *op = newop;
    *count = 1;
  }
}

void finishop(char ** cigarendp, char * op, int * count)
{
  constexpr unsigned int buffer_length {25};

  if ((op != nullptr) && (count != nullptr))
  {
    *--*cigarendp = *op;
    if (*count > 1)
    {
      char buf[buffer_length];
      int len = snprintf(buf, buffer_length, "%d", *count);
      assert(len >= 0);
      *cigarendp -= len;
      memcpy(*cigarendp, buf, static_cast<size_t>(len));
    }
    *op = 0;
    *count = 0;
  }
}

const unsigned char maskup      = 1;
const unsigned char maskleft    = 2;
const unsigned char maskextup   = 4;
const unsigned char maskextleft = 8;

/*

  Needleman/Wunsch/Sellers aligner

  finds a global alignment with minimum cost
  there should be positive costs/penalties for gaps and for mismatches
  matches should have zero cost (0)

  alignment priority when backtracking (from lower right corner):
  1. left/insert/e (gap in query sequence (qseq))
  2. align/diag/h (match/mismatch)
  3. up/delete/f (gap in database sequence (dseq))

  qseq: the reference/query/upper/vertical/from sequence
  dseq: the sample/database/lower/horisontal/to sequence

  typical costs:
  match: 0
  mismatch: 3
  gapopen: 4
  gapextend: 3

  input

  dseq: pointer to start of database sequence
  dend: pointer after database sequence
  qseq: pointer to start of query sequence
  qend: pointer after database sequence
  score_matrix: 32x32 matrix of longs with scores for aligning two symbols
  gapopen: positive number indicating penalty for opening a gap of length zero
  gapextend: positive number indicating penalty for extending a gap

  output

  nwscore: the global alignment score
  nwdiff: number of non-identical nucleotides in one optimal global alignment
  nwalignmentlength: the length of one optimal alignment
  nwalignment: cigar string with one optimal alignment

*/

void nw(char * dseq,
        int64_t dlen,
        char * qseq,
        int64_t qlen,
        int64_t * score_matrix,
        int64_t gapopen,
        int64_t gapextend,
        int64_t * nwscore,
        int64_t * nwdiff,
        int64_t * nwalignmentlength,
        char ** nwalignment,
        unsigned char * dir,
        int64_t * hearray,
        uint64_t queryno,
        uint64_t dbseqno)
{
  /* dir must point to at least qlen*dlen bytes of allocated memory
     hearray must point to at least 2*qlen longs of allocated memory
     (8*qlen bytes) */
  constexpr unsigned int multiplier {5};

  int64_t n {0};
  int64_t e {0};

  memset(dir, 0, static_cast<size_t>(qlen * dlen));

  for(auto i = 0L; i < qlen; i++)
    {
      hearray[2 * i]     = 1 * gapopen + (i + 1) * gapextend; // H (N)
      hearray[2 * i + 1] = 2 * gapopen + (i + 2) * gapextend; // E
    }

  for(auto j = 0L; j < dlen; j++)
    {
      int64_t * hep {nullptr};
      hep = hearray;
      int64_t f = 2 * gapopen + (j+2) * gapextend;
      int64_t h = (j == 0) ? 0 : (gapopen + j * gapextend);

      for(auto i = 0L; i < qlen; i++)
        {
          int64_t index = qlen * j + i;

          n = *hep;
          e = *(hep+1);
          h += score_matrix
            [((nt_extract(dseq, static_cast<uint64_t>(j)) + 1) << multiplier)
             +(nt_extract(qseq, static_cast<uint64_t>(i)) + 1)];

          dir[index] |= (f < h ? maskup : 0);
          h = std::min(h, f);
          h = std::min(h, e);
          dir[index] |= (e == h ? maskleft : 0);

          *hep = h;

          h += gapopen + gapextend;
          e += gapextend;
          f += gapextend;

          dir[index] |= (f < h ? maskextup : 0);
          dir[index] |= (e < h ? maskextleft : 0);
          f = std::min(h,f);
          e = std::min(h,e);

          *(hep+1) = e;
          h = n;
          hep += 2;
        }
    }

  int64_t dist = hearray[2 * qlen - 2];

  /* backtrack: count differences and save alignment in cigar string */
  int64_t score {0};
  int64_t alength {0};
  int64_t matches {0};

  char * cigar = new char[static_cast<size_t>(qlen + dlen + 1)];
  char * cigarend {cigar + qlen + dlen + 1};

  char op {0};
  int count {0};
  *(--cigarend) = 0;

  int64_t i = qlen;
  int64_t j = dlen;

  while ((i>0) && (j>0))
    {
      int d = dir[qlen*(j-1)+(i-1)];

      alength++;

      if ((op == 'I') && ((d & maskextleft) != 0))
        {
          score += gapextend;
          j--;
          pushop('I', &cigarend, &op, &count);
        }
      else if ((op == 'D') && ((d & maskextup) != 0))
        {
          score += gapextend;
          i--;
          pushop('D', &cigarend, &op, &count);
        }
      else if ((d & maskleft) != 0)
        {
          score += gapextend;
          if (op != 'I') {
            score += gapopen;
          }
          j--;
          pushop('I', &cigarend, &op, &count);
        }
      else if ((d & maskup) != 0)
        {
          score += gapextend;
          if (op != 'D') {
            score += gapopen;
          }
          i--;
          pushop('D', &cigarend, &op, &count);
        }
      else
        {
          score += score_matrix
            [((nt_extract(dseq, static_cast<uint64_t>(j - 1)) + 1) << multiplier)
             +(nt_extract(qseq, static_cast<uint64_t>(i - 1)) + 1)];

          if (nt_extract(qseq, static_cast<uint64_t>(i - 1)) ==
              nt_extract(dseq, static_cast<uint64_t>(j - 1))) {
            matches++;
          }
          i--;
          j--;
          pushop('M', &cigarend, &op, &count);
        }
    }

  while(i>0)
    {
      alength++;
      score += gapextend;
      if (op != 'D') {
        score += gapopen;
      }
      i--;
      pushop('D', &cigarend, &op, &count);
    }

  while(j>0)
    {
      alength++;
      score += gapextend;
      if (op != 'I') {
        score += gapopen;
      }
      j--;
      pushop('I', &cigarend, &op, &count);
    }

  finishop(&cigarend, &op, &count);

  /* move and reallocate cigar */

  auto cigaralloc = static_cast<size_t>(cigar + qlen + dlen - cigarend + 1);
  memmove(cigar, cigarend, cigaralloc);
  cigar = static_cast<char*>(xrealloc(cigar, cigaralloc));

  * nwscore = dist;
  * nwdiff = alength - matches;
  * nwalignmentlength = alength;
  * nwalignment = cigar;

  assert(score == dist);

  (void) queryno;
  (void) dbseqno;
}
<|endoftext|>


<commit_before>
//
// ===============================================================================
// clReflect
// -------------------------------------------------------------------------------
// Copyright (c) 2011 Don Williamson
//
// 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.
// ===============================================================================
//

#include <clcpp/Database.h>
#include "DatabaseLoader.h"

namespace
{
	unsigned int GetNameHash(clcpp::Name name)
	{
		return name.hash;
	}
	unsigned int GetPrimitiveHash(const clcpp::Primitive& primitive)
	{
		return primitive.name.hash;
	}
	unsigned int GetPrimitivePtrHash(const clcpp::Primitive* primitive)
	{
		return primitive->name.hash;
	}

	template <typename ARRAY_TYPE, typename COMPARE_L_TYPE, unsigned int (GET_HASH_FUNC)(COMPARE_L_TYPE)>
	int BinarySearch(const clcpp::CArray<ARRAY_TYPE>& entries, unsigned int compare_hash)
	{
		int first = 0;
		int last = entries.size() - 1;

		// Binary search
		while (first <= last)
		{
			// Identify the mid point
			int mid = (first + last) / 2;

			unsigned entry_hash = GET_HASH_FUNC(entries[mid]);
			if (compare_hash > entry_hash)
			{
				// Shift search to local upper half
				first = mid + 1;
			}
			else if (compare_hash < entry_hash)
			{
				// Shift search to local lower half
				last = mid - 1;
			}
			else
			{
				// Exact match found
				return mid;
			}
		}

		return -1;
	}

	template <typename ARRAY_TYPE, typename COMPARE_L_TYPE, unsigned int (GET_HASH_FUNC)(COMPARE_L_TYPE)>
	clcpp::Range SearchNeighbours(const clcpp::CArray<ARRAY_TYPE>& entries, unsigned int compare_hash, int index)
	{
		clcpp::Range range;
		range.first = index;
		range.last = index + 1;

		// Search either side of the result, gathering further matches
		while (range.first > 0 && GET_HASH_FUNC(entries[range.first - 1]) == compare_hash)
			range.first--;
		while (range.last < entries.size() && GET_HASH_FUNC(entries[range.last]) == compare_hash)
			range.last++;

		return range;
	}

    void RebaseFunctions(clcpp::internal::DatabaseMem& dbmem, clcpp::pointer_type base_address)
	{
		// Move all function addresses from their current location to their new location
		for (int i = 0; i < dbmem.functions.size(); i++)
		{
			clcpp::Function& f = dbmem.functions[i];
			if (f.address)
				f.address = f.address - dbmem.function_base_address + base_address;
		}

		// Do the same for the GetType family of functions
		for (int i = 0; i < dbmem.get_type_functions.size(); i++)
		{
			clcpp::internal::GetTypeFunctions& f = dbmem.get_type_functions[i];
			if (f.get_typename_address)
				f.get_typename_address = f.get_typename_address - dbmem.function_base_address + base_address;
			if (f.get_type_address)
				f.get_type_address = f.get_type_address - dbmem.function_base_address + base_address;
		}
	}

#if defined(CLCPP_USING_GNUC)

    // Max length to search for instructions to patch
    #define MAX_PATCH_SEARCH_LENGTH 0x20

    // GCC specific patch functions
    template<typename T>
    void GccPatchFunction(clcpp::pointer_type function_address,
        const T& patch_value, const T& original_value)
    {
        unsigned char* function_pointer = (unsigned char*) function_address;

        // searches for 0x20 instruction headers at most
        for (int i = 0; i < 0x20; i++)
        {
#if defined(CLCPP_USING_64_BIT)
            // 64 bit patch starts here
            if (function_pointer[i] == 0x8B) {
                // MOV instruction
                // this may be what we are looking for
                clcpp::uint32 target_offset = *((clcpp::uint32*) &function_pointer[i + 2]);
                T* target_ptr = (T*) (&function_pointer[i + 6] + target_offset);

                // although we get the real target address here, we still cannot
                // say immediately if this is our target pointer to patch. On
                // Mac OS X, this pointer would first point to a stub, which
                // then points to the real pointer, so we may have two levels
                // of pointers here. In this case, we would test for both cases.
                if (*target_ptr == original_value) {
                    // there's no stubs, this is the pointer we are looking for
                    *target_ptr = patch_value;
                    return;
                }

#if defined(CLCPP_USING_GNUC_MAC)
                // we test for stub pointer on mac
                // TODO: check if other compiler has the same behaviour
                T* target_stub = *((T**) target_ptr);
                if (*target_stub == original_value) {
                    *target_stub = patch_value;
                    return;
                }
#endif // CLCPP_USING_GNUC_MAC

            }
            // 64 bit patch ends here
#else
            // 32 bit patch starts here
            if (function_pointer[i] == 0xA1) {
                T* target_addr = *((T**) (&function_pointer[i + 1]));

                if (*target_addr == original_value) {
                    *target_addr = patch_value;
                    return;
                }
            }
            // 32 bit patch ends here
#endif // CLCPP_USING_64_BIT
        }
        // TODO: we may want to add error raising code here since we failed to do the patch
        return;
    }

#endif // CLCPP_USING_GNUC

	void PatchGetTypeAddresses(clcpp::Database& db, clcpp::internal::DatabaseMem& dbmem)
	{
        unsigned int original_hash = CLCPP_INVALID_HASH;
        const clcpp::Type* original_type = (const clcpp::Type*) CLCPP_INVALID_ADDRESS;

		for (int i = 0; i < dbmem.get_type_functions.size(); i++)
		{
			clcpp::internal::GetTypeFunctions& f = dbmem.get_type_functions[i];

			// Patch up the type name hash static variable
			if (f.get_typename_address)
			{
                unsigned int hash = db.GetName(f.type_hash).hash;

#if defined(CLCPP_USING_MSVC)
				unsigned char* mov_instruction = (unsigned char*)f.get_typename_address;
				clcpp::internal::Assert(*mov_instruction == 0xA1);
                unsigned int* hash_address = *(unsigned int**)(mov_instruction + 1);
				*hash_address = hash;
#endif // CLCPP_USING_MSVC

#if defined(CLCPP_USING_GNUC)
                GccPatchFunction<unsigned int>(f.get_typename_address,
                    hash,
                    original_hash);
#endif // CLCPP_USING_GNUC
			}

			// Patch up the type pointer static variable
			if (f.get_type_address)
			{
                const clcpp::Type* type = db.GetType(f.type_hash);

#if defined(CLCPP_USING_MSVC)
				unsigned char* mov_instruction = (unsigned char*)f.get_type_address;
				clcpp::internal::Assert(*mov_instruction == 0xA1);
				const clcpp::Type** type_address = *(const clcpp::Type***)(mov_instruction + 1);
				*type_address = type;
#endif // CLCPP_USING_MSVC

#if defined(CLCPP_USING_GNUC)
                GccPatchFunction<const clcpp::Type*>(f.get_type_address,
                    type,
                    original_type);
#endif // CLCPP_USING_GNUC
			}
		}
	}

	template <typename TYPE>
	void ParentPrimitivesToDatabase(clcpp::CArray<TYPE>& primitives, clcpp::Database* database)
	{
		for (int i = 0; i < primitives.size(); i++)
			primitives[i].database = database;
	}
}

const clcpp::Primitive* clcpp::internal::FindPrimitive(const CArray<const Primitive*>& primitives, unsigned int hash)
{
	int index = BinarySearch<const Primitive*, const Primitive*, GetPrimitivePtrHash>(primitives, hash);
	if (index == -1)
		return 0;
	return primitives[index];
}

clcpp::Range clcpp::internal::FindOverloadedPrimitive(const CArray<const Primitive*>& primitives, unsigned int hash)
{
	// Search for the first entry
	int index = BinarySearch<const Primitive*, const Primitive*, GetPrimitivePtrHash>(primitives, hash);
	if (index == -1)
		return Range();

	// Look at its neighbours to widen the primitives found
	return SearchNeighbours<const Primitive*, const Primitive*, GetPrimitivePtrHash>(primitives, hash, index);
}

clcpp::Database::Database()
	: m_DatabaseMem(0)
	, m_Allocator(0)
{
}

clcpp::Database::~Database()
{
	if (m_DatabaseMem)
		m_Allocator->Free(m_DatabaseMem);
}

bool clcpp::Database::Load(IFile* file, IAllocator* allocator, clcpp::pointer_type base_address, unsigned int options)
{
	// Load the database
	internal::Assert(m_DatabaseMem == 0 && "Database already loaded");
	m_Allocator = allocator;
	m_DatabaseMem = internal::LoadMemoryMappedDatabase(file, m_Allocator);

	if (m_DatabaseMem != 0)
	{
		// If no base address is provided, rebasing will not occur and it is assumed the addresses
		// loaded are already correct. Rebasing is usually only needed for DLLs that have been moved
		// by the OS due to another DLL occupying its preferred load address.
		if (base_address != 0)
			RebaseFunctions(*m_DatabaseMem, base_address);

		if ((options & OPT_DONT_PATCH_GETTYPE) == 0)
			PatchGetTypeAddresses(*this, *m_DatabaseMem);

		// Tell each loaded primitive that they belong to this database
		ParentPrimitivesToDatabase(m_DatabaseMem->types, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->enum_constants, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->enums, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->fields, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->functions, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->classes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->templates, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->template_types, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->namespaces, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->flag_attributes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->int_attributes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->float_attributes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->primitive_attributes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->text_attributes, this);
	}

	return m_DatabaseMem != 0;
}

clcpp::Name clcpp::Database::GetName(unsigned int hash) const
{
	// Lookup the name by hash
	int index = BinarySearch<Name, Name, GetNameHash>(m_DatabaseMem->names, hash);
	if (index == -1)
		return clcpp::Name();
	return m_DatabaseMem->names[index];
}

clcpp::Name clcpp::Database::GetName(const char* text) const
{
	// Null pointer
	if (text == 0)
		return clcpp::Name();

	// Hash and exit on no value
	unsigned int hash = internal::HashNameString(text);
	if (hash == 0)
		return clcpp::Name();

	return GetName(hash);
}

const clcpp::Type* clcpp::Database::GetType(unsigned int hash) const
{
	return FindPrimitive(m_DatabaseMem->type_primitives, hash);
}

const clcpp::Namespace* clcpp::Database::GetNamespace(unsigned int hash) const
{
	int index = BinarySearch<Namespace, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->namespaces, hash);
	if (index == -1)
		return 0;
	return &m_DatabaseMem->namespaces[index];
}

const clcpp::Namespace* clcpp::Database::GetGlobalNamespace() const
{
	return &m_DatabaseMem->global_namespace;
}

const clcpp::Template* clcpp::Database::GetTemplate(unsigned int hash) const
{
	int index = BinarySearch<Template, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->templates, hash);
	if (index == -1)
		return 0;
	return &m_DatabaseMem->templates[index];
}

const clcpp::Function* clcpp::Database::GetFunction(unsigned int hash) const
{
	int index = BinarySearch<Function, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->functions, hash);
	if (index == -1)
		return 0;
	return &m_DatabaseMem->functions[index];
}

clcpp::Range clcpp::Database::GetOverloadedFunction(unsigned int hash) const
{
	// Quickly locate the first match
	int index = BinarySearch<Function, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->functions, hash);
	if (index == -1)
		return Range();

	// Functions can be overloaded so look at the neighbours to widen the primitives found
	return SearchNeighbours<Function, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->functions, hash, index);
}
<commit_msg>Remove unused define<commit_after>
//
// ===============================================================================
// clReflect
// -------------------------------------------------------------------------------
// Copyright (c) 2011 Don Williamson
//
// 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.
// ===============================================================================
//

#include <clcpp/Database.h>
#include "DatabaseLoader.h"

namespace
{
	unsigned int GetNameHash(clcpp::Name name)
	{
		return name.hash;
	}
	unsigned int GetPrimitiveHash(const clcpp::Primitive& primitive)
	{
		return primitive.name.hash;
	}
	unsigned int GetPrimitivePtrHash(const clcpp::Primitive* primitive)
	{
		return primitive->name.hash;
	}

	template <typename ARRAY_TYPE, typename COMPARE_L_TYPE, unsigned int (GET_HASH_FUNC)(COMPARE_L_TYPE)>
	int BinarySearch(const clcpp::CArray<ARRAY_TYPE>& entries, unsigned int compare_hash)
	{
		int first = 0;
		int last = entries.size() - 1;

		// Binary search
		while (first <= last)
		{
			// Identify the mid point
			int mid = (first + last) / 2;

			unsigned entry_hash = GET_HASH_FUNC(entries[mid]);
			if (compare_hash > entry_hash)
			{
				// Shift search to local upper half
				first = mid + 1;
			}
			else if (compare_hash < entry_hash)
			{
				// Shift search to local lower half
				last = mid - 1;
			}
			else
			{
				// Exact match found
				return mid;
			}
		}

		return -1;
	}

	template <typename ARRAY_TYPE, typename COMPARE_L_TYPE, unsigned int (GET_HASH_FUNC)(COMPARE_L_TYPE)>
	clcpp::Range SearchNeighbours(const clcpp::CArray<ARRAY_TYPE>& entries, unsigned int compare_hash, int index)
	{
		clcpp::Range range;
		range.first = index;
		range.last = index + 1;

		// Search either side of the result, gathering further matches
		while (range.first > 0 && GET_HASH_FUNC(entries[range.first - 1]) == compare_hash)
			range.first--;
		while (range.last < entries.size() && GET_HASH_FUNC(entries[range.last]) == compare_hash)
			range.last++;

		return range;
	}

    void RebaseFunctions(clcpp::internal::DatabaseMem& dbmem, clcpp::pointer_type base_address)
	{
		// Move all function addresses from their current location to their new location
		for (int i = 0; i < dbmem.functions.size(); i++)
		{
			clcpp::Function& f = dbmem.functions[i];
			if (f.address)
				f.address = f.address - dbmem.function_base_address + base_address;
		}

		// Do the same for the GetType family of functions
		for (int i = 0; i < dbmem.get_type_functions.size(); i++)
		{
			clcpp::internal::GetTypeFunctions& f = dbmem.get_type_functions[i];
			if (f.get_typename_address)
				f.get_typename_address = f.get_typename_address - dbmem.function_base_address + base_address;
			if (f.get_type_address)
				f.get_type_address = f.get_type_address - dbmem.function_base_address + base_address;
		}
	}

#if defined(CLCPP_USING_GNUC)

    // GCC specific patch functions
    template<typename T>
    void GccPatchFunction(clcpp::pointer_type function_address,
        const T& patch_value, const T& original_value)
    {
        unsigned char* function_pointer = (unsigned char*) function_address;

        // searches for 0x20 instruction headers at most
        for (int i = 0; i < 0x20; i++)
        {
#if defined(CLCPP_USING_64_BIT)
            // 64 bit patch starts here
            if (function_pointer[i] == 0x8B) {
                // MOV instruction
                // this may be what we are looking for
                clcpp::uint32 target_offset = *((clcpp::uint32*) &function_pointer[i + 2]);
                T* target_ptr = (T*) (&function_pointer[i + 6] + target_offset);

                // although we get the real target address here, we still cannot
                // say immediately if this is our target pointer to patch. On
                // Mac OS X, this pointer would first point to a stub, which
                // then points to the real pointer, so we may have two levels
                // of pointers here. In this case, we would test for both cases.
                if (*target_ptr == original_value) {
                    // there's no stubs, this is the pointer we are looking for
                    *target_ptr = patch_value;
                    return;
                }

#if defined(CLCPP_USING_GNUC_MAC)
                // we test for stub pointer on mac
                // TODO: check if other compiler has the same behaviour
                T* target_stub = *((T**) target_ptr);
                if (*target_stub == original_value) {
                    *target_stub = patch_value;
                    return;
                }
#endif // CLCPP_USING_GNUC_MAC

            }
            // 64 bit patch ends here
#else
            // 32 bit patch starts here
            if (function_pointer[i] == 0xA1) {
                T* target_addr = *((T**) (&function_pointer[i + 1]));

                if (*target_addr == original_value) {
                    *target_addr = patch_value;
                    return;
                }
            }
            // 32 bit patch ends here
#endif // CLCPP_USING_64_BIT
        }
        // TODO: we may want to add error raising code here since we failed to do the patch
        return;
    }

#endif // CLCPP_USING_GNUC

	void PatchGetTypeAddresses(clcpp::Database& db, clcpp::internal::DatabaseMem& dbmem)
	{
        unsigned int original_hash = CLCPP_INVALID_HASH;
        const clcpp::Type* original_type = (const clcpp::Type*) CLCPP_INVALID_ADDRESS;

		for (int i = 0; i < dbmem.get_type_functions.size(); i++)
		{
			clcpp::internal::GetTypeFunctions& f = dbmem.get_type_functions[i];

			// Patch up the type name hash static variable
			if (f.get_typename_address)
			{
                unsigned int hash = db.GetName(f.type_hash).hash;

#if defined(CLCPP_USING_MSVC)
				unsigned char* mov_instruction = (unsigned char*)f.get_typename_address;
				clcpp::internal::Assert(*mov_instruction == 0xA1);
                unsigned int* hash_address = *(unsigned int**)(mov_instruction + 1);
				*hash_address = hash;
#endif // CLCPP_USING_MSVC

#if defined(CLCPP_USING_GNUC)
                GccPatchFunction<unsigned int>(f.get_typename_address,
                    hash,
                    original_hash);
#endif // CLCPP_USING_GNUC
			}

			// Patch up the type pointer static variable
			if (f.get_type_address)
			{
                const clcpp::Type* type = db.GetType(f.type_hash);

#if defined(CLCPP_USING_MSVC)
				unsigned char* mov_instruction = (unsigned char*)f.get_type_address;
				clcpp::internal::Assert(*mov_instruction == 0xA1);
				const clcpp::Type** type_address = *(const clcpp::Type***)(mov_instruction + 1);
				*type_address = type;
#endif // CLCPP_USING_MSVC

#if defined(CLCPP_USING_GNUC)
                GccPatchFunction<const clcpp::Type*>(f.get_type_address,
                    type,
                    original_type);
#endif // CLCPP_USING_GNUC
			}
		}
	}

	template <typename TYPE>
	void ParentPrimitivesToDatabase(clcpp::CArray<TYPE>& primitives, clcpp::Database* database)
	{
		for (int i = 0; i < primitives.size(); i++)
			primitives[i].database = database;
	}
}

const clcpp::Primitive* clcpp::internal::FindPrimitive(const CArray<const Primitive*>& primitives, unsigned int hash)
{
	int index = BinarySearch<const Primitive*, const Primitive*, GetPrimitivePtrHash>(primitives, hash);
	if (index == -1)
		return 0;
	return primitives[index];
}

clcpp::Range clcpp::internal::FindOverloadedPrimitive(const CArray<const Primitive*>& primitives, unsigned int hash)
{
	// Search for the first entry
	int index = BinarySearch<const Primitive*, const Primitive*, GetPrimitivePtrHash>(primitives, hash);
	if (index == -1)
		return Range();

	// Look at its neighbours to widen the primitives found
	return SearchNeighbours<const Primitive*, const Primitive*, GetPrimitivePtrHash>(primitives, hash, index);
}

clcpp::Database::Database()
	: m_DatabaseMem(0)
	, m_Allocator(0)
{
}

clcpp::Database::~Database()
{
	if (m_DatabaseMem)
		m_Allocator->Free(m_DatabaseMem);
}

bool clcpp::Database::Load(IFile* file, IAllocator* allocator, clcpp::pointer_type base_address, unsigned int options)
{
	// Load the database
	internal::Assert(m_DatabaseMem == 0 && "Database already loaded");
	m_Allocator = allocator;
	m_DatabaseMem = internal::LoadMemoryMappedDatabase(file, m_Allocator);

	if (m_DatabaseMem != 0)
	{
		// If no base address is provided, rebasing will not occur and it is assumed the addresses
		// loaded are already correct. Rebasing is usually only needed for DLLs that have been moved
		// by the OS due to another DLL occupying its preferred load address.
		if (base_address != 0)
			RebaseFunctions(*m_DatabaseMem, base_address);

		if ((options & OPT_DONT_PATCH_GETTYPE) == 0)
			PatchGetTypeAddresses(*this, *m_DatabaseMem);

		// Tell each loaded primitive that they belong to this database
		ParentPrimitivesToDatabase(m_DatabaseMem->types, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->enum_constants, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->enums, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->fields, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->functions, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->classes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->templates, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->template_types, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->namespaces, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->flag_attributes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->int_attributes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->float_attributes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->primitive_attributes, this);
		ParentPrimitivesToDatabase(m_DatabaseMem->text_attributes, this);
	}

	return m_DatabaseMem != 0;
}

clcpp::Name clcpp::Database::GetName(unsigned int hash) const
{
	// Lookup the name by hash
	int index = BinarySearch<Name, Name, GetNameHash>(m_DatabaseMem->names, hash);
	if (index == -1)
		return clcpp::Name();
	return m_DatabaseMem->names[index];
}

clcpp::Name clcpp::Database::GetName(const char* text) const
{
	// Null pointer
	if (text == 0)
		return clcpp::Name();

	// Hash and exit on no value
	unsigned int hash = internal::HashNameString(text);
	if (hash == 0)
		return clcpp::Name();

	return GetName(hash);
}

const clcpp::Type* clcpp::Database::GetType(unsigned int hash) const
{
	return FindPrimitive(m_DatabaseMem->type_primitives, hash);
}

const clcpp::Namespace* clcpp::Database::GetNamespace(unsigned int hash) const
{
	int index = BinarySearch<Namespace, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->namespaces, hash);
	if (index == -1)
		return 0;
	return &m_DatabaseMem->namespaces[index];
}

const clcpp::Namespace* clcpp::Database::GetGlobalNamespace() const
{
	return &m_DatabaseMem->global_namespace;
}

const clcpp::Template* clcpp::Database::GetTemplate(unsigned int hash) const
{
	int index = BinarySearch<Template, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->templates, hash);
	if (index == -1)
		return 0;
	return &m_DatabaseMem->templates[index];
}

const clcpp::Function* clcpp::Database::GetFunction(unsigned int hash) const
{
	int index = BinarySearch<Function, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->functions, hash);
	if (index == -1)
		return 0;
	return &m_DatabaseMem->functions[index];
}

clcpp::Range clcpp::Database::GetOverloadedFunction(unsigned int hash) const
{
	// Quickly locate the first match
	int index = BinarySearch<Function, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->functions, hash);
	if (index == -1)
		return Range();

	// Functions can be overloaded so look at the neighbours to widen the primitives found
	return SearchNeighbours<Function, const Primitive&, GetPrimitiveHash>(m_DatabaseMem->functions, hash, index);
}
<|endoftext|>


<commit_before>#include "rhoruntime.h"
#include "common/RhoStd.h"
#include "common/StringConverter.h"
#include "ruby/ext/rho/rhoruby.h"

using namespace rhoruntime;
using namespace Platform;

extern "C" void rho_webview_navigate_back()
{
	CRhoRuntime::getInstance()->getMainPage()->GoBack();
}

extern "C" int rho_webview_active_tab()
{
	return CRhoRuntime::getInstance()->getMainPage()->tabbarGetCurrent();
}

extern "C" void rho_webview_navigate_forward()
{
    CRhoRuntime::getInstance()->getMainPage()->GoForward();
}

extern "C" const char* rho_webview_execute_js(const char* js, int index)
{
	rho::StringW jsW;
	rho::common::convertToStringW(js, jsW);
	CRhoRuntime::getInstance()->getMainPage()->executeScript(ref new String(jsW.c_str()), index);
	// TODO: implement return value
    return "";
}

extern "C" const char* rho_webview_current_location(int index)
{
	rho::String urlA = rho::common::convertToStringA(CRhoRuntime::getInstance()->getMainPage()->getCurrentURL(index)->Data());
	return urlA.c_str();
}

extern "C" unsigned long rho_webview_get_current_url(int index)
{
	return rho_ruby_create_string(rho_webview_current_location(index));
}

extern "C" void rho_webview_full_screen_mode(int enable)
{
	CRhoRuntime::getInstance()->getMainPage()->fullscreenCommand(enable);
}

extern "C" void rho_webview_set_cookie(const char *url, const char *cookie)
{
	rho::StringW urlW;
	rho::StringW cookieW;
	rho::common::convertToStringW(url, urlW);
	rho::common::convertToStringW(cookie, cookieW);
	CRhoRuntime::getInstance()->getMainPage()->setCookie(ref new String(urlW.c_str()), ref new String(cookieW.c_str()));
}

extern "C" void rho_webview_navigate(const char* url, int index)
{
	rho::StringW urlW;
	rho::common::convertToStringW(url, urlW);
	CRhoRuntime::getInstance()->getMainPage()->navigate(ref new String(urlW.c_str()), index);
}

extern "C" void rho_webview_refresh(int index)
{
	CRhoRuntime::getInstance()->getMainPage()->Refresh(index);
}
<commit_msg>fix navigate method<commit_after>#include "rhoruntime.h"
#include "common/RhoStd.h"
#include "common/StringConverter.h"
#include "common/RhodesAppBase.h"
#include "ruby/ext/rho/rhoruby.h"

using namespace rhoruntime;
using namespace Platform;

extern "C" void rho_webview_navigate_back()
{
	CRhoRuntime::getInstance()->getMainPage()->GoBack();
}

extern "C" int rho_webview_active_tab()
{
	return CRhoRuntime::getInstance()->getMainPage()->tabbarGetCurrent();
}

extern "C" void rho_webview_navigate_forward()
{
    CRhoRuntime::getInstance()->getMainPage()->GoForward();
}

extern "C" const char* rho_webview_execute_js(const char* js, int index)
{
	rho::StringW jsW;
	rho::common::convertToStringW(js, jsW);
	CRhoRuntime::getInstance()->getMainPage()->executeScript(ref new String(jsW.c_str()), index);
	// TODO: implement return value
    return "";
}

extern "C" const char* rho_webview_current_location(int index)
{
	rho::String urlA = rho::common::convertToStringA(CRhoRuntime::getInstance()->getMainPage()->getCurrentURL(index)->Data());
	return urlA.c_str();
}

extern "C" unsigned long rho_webview_get_current_url(int index)
{
	return rho_ruby_create_string(rho_webview_current_location(index));
}

extern "C" void rho_webview_full_screen_mode(int enable)
{
	CRhoRuntime::getInstance()->getMainPage()->fullscreenCommand(enable);
}

extern "C" void rho_webview_set_cookie(const char *url, const char *cookie)
{
	rho::StringW urlW;
	rho::StringW cookieW;
	rho::common::convertToStringW(url, urlW);
	rho::common::convertToStringW(cookie, cookieW);
	CRhoRuntime::getInstance()->getMainPage()->setCookie(ref new String(urlW.c_str()), ref new String(cookieW.c_str()));
}

extern "C" void rho_webview_navigate(const char* url, int index)
{
	rho::StringW urlW;
	rho::String fullUrl = RHODESAPPBASE().canonicalizeRhoUrl(url);
	rho::common::convertToStringW(fullUrl.c_str(), urlW);
	CRhoRuntime::getInstance()->getMainPage()->navigate(ref new String(urlW.c_str()), index);
}

extern "C" void rho_webview_refresh(int index)
{
	CRhoRuntime::getInstance()->getMainPage()->Refresh(index);
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 - Decho Corp.

#include "mordor/pch.h"

#include <algorithm>

#include <string.h>

#include <openssl/md5.h>
#include <openssl/sha.h>

#include "mordor/string.h"

#include "assert.h"
#include "exception.h"

#ifdef MSVC
#pragma comment(lib, "libeay32")
#endif

namespace Mordor {

std::string
base64decode(const std::string &src)
{
    std::string result;
    result.resize(src.size() * 3 / 4);
    char *writeBuf = &result[0];

    const char* ptr = src.c_str();
    const char* end = ptr + src.size();

    while(ptr < end) {
        int i = 0;
        int padding = 0;
        int packed = 0;
        for(; i < 4 && ptr < end; ++i, ++ptr) {
            if(*ptr == '=') {
                ++padding;
                packed <<= 6;
                continue;
            }

            int val = 0;
            if(*ptr >= 'A' && *ptr <= 'Z')
                val = *ptr - 'A';
            else if(*ptr >= 'a' && *ptr <= 'z')
                val = *ptr - 'a' + 26;
            else if(*ptr >= '0' && *ptr <= '9')
                val = *ptr - '0' + 52;
            else if(*ptr == '+')
                val = 62;
            else if(*ptr == '/')
                val = 63;
            else
                return "";

            packed = (packed << 6) | val;
        }
        if (i != 4)
            MORDOR_ASSERT(false);
        if (padding > 0 && ptr != end)
            MORDOR_ASSERT(false);
        if (padding > 2)
            MORDOR_ASSERT(false);

        *writeBuf++ = (char)((packed >> 16) & 0xff);
        if(padding != 2)
            *writeBuf++ = (char)((packed >> 8) & 0xff);
        if(padding == 0)
            *writeBuf++ = (char)(packed & 0xff);
    }

    result.resize(writeBuf - result.c_str());
    return result;
}

std::string
base64encode(const std::string& data)
{
    return base64encode(data.c_str(), data.size());
}

std::string
base64encode(const void* data, size_t len)
{
    const char* base64 =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    std::string ret;
    ret.reserve(len * 4 / 3 + 2);

    const unsigned char* ptr = (const unsigned char*)data;
    const unsigned char* end = ptr + len;

    while(ptr < end) {
        unsigned int packed = 0;
        int i = 0;
        int padding = 0;
        for(; i < 3 && ptr < end; ++i, ++ptr)
            packed = (packed << 8) | *ptr;
        if(i == 2)
            padding = 1;
        else if (i == 1)
            padding = 2;
        for(; i < 3; ++i)
            packed <<= 8;

        ret.append(1, base64[packed >> 18]);
        ret.append(1, base64[(packed >> 12) & 0x3f]);
        if(padding != 2)
            ret.append(1, base64[(packed >> 6) & 0x3f]);
        if(padding == 0)
            ret.append(1, base64[packed & 0x3f]);
        ret.append(padding, '=');
    }

    return ret;
}

std::string
md5(const std::string &data)
{
    return hexstringFromData(md5sum(data).c_str(), MD5_DIGEST_LENGTH);
}

std::string
sha1(const std::string &data)
{
	return hexstringFromData(sha1sum(data).c_str(), SHA_DIGEST_LENGTH);
}

std::string
md5sum(const void *data, size_t len)
{
    MD5_CTX ctx;
    MD5_Init(&ctx);
    MD5_Update(&ctx, data, len);
    std::string result;
    result.resize(MD5_DIGEST_LENGTH);
    MD5_Final((unsigned char*)&result[0], &ctx);
    return result;
}

std::string
md5sum(const std::string &data)
{
    return md5sum(data.c_str(), data.size());
}

std::string
sha1sum(const void *data, size_t len)
{
    SHA_CTX ctx;
    SHA1_Init(&ctx);
    SHA1_Update(&ctx, data, len);
    std::string result;
    result.resize(SHA_DIGEST_LENGTH);
    SHA1_Final((unsigned char*)&result[0], &ctx);
    return result;
}

std::string
sha1sum(const std::string &data)
{
    return sha1sum(data.c_str(), data.size());
}

struct xorStruct
{
    xorStruct(char value) : m_value(value) {}
    char m_value;
    char operator()(char in) const { return in ^ m_value; }
};

std::string
hmacMd5(const std::string &text, std::string key)
{
    const unsigned int B = 64;
    const unsigned int L = MD5_DIGEST_LENGTH;
    if (key.size() > B)
        key = md5sum(key);
    key.append(B - key.size(), '\0');
    std::string ipad = key, opad = key;
    std::transform(ipad.begin(), ipad.end(), ipad.begin(), xorStruct(0x36));
    std::transform(opad.begin(), opad.end(), opad.begin(), xorStruct(0x5c));
    MD5_CTX ctx;
    MD5_Init(&ctx);
    MD5_Update(&ctx, ipad.c_str(), B);
    MD5_Update(&ctx, text.c_str(), text.size());
    std::string result;
    result.resize(L);
    MD5_Final((unsigned char *)&result[0], &ctx);
    MD5_Init(&ctx);
    MD5_Update(&ctx, opad.c_str(), B);
    MD5_Update(&ctx, result.c_str(), L);
    MD5_Final((unsigned char *)&result[0], &ctx);
    return result;
}

std::string
hmacSha1(const std::string &text, std::string key)
{
    const unsigned int B = 64;
    const unsigned int L = SHA_DIGEST_LENGTH;
    if (key.size() > B)
        key = sha1sum(key);
    key.append(B - key.size(), '\0');
    std::string ipad = key, opad = key;
    std::transform(ipad.begin(), ipad.end(), ipad.begin(), xorStruct(0x36));
    std::transform(opad.begin(), opad.end(), opad.begin(), xorStruct(0x5c));
    SHA_CTX ctx;
    SHA1_Init(&ctx);
    SHA1_Update(&ctx, ipad.c_str(), B);
    SHA1_Update(&ctx, text.c_str(), text.size());
    std::string result;
    result.resize(L);
    SHA1_Final((unsigned char *)&result[0], &ctx);
    SHA1_Init(&ctx);
    SHA1_Update(&ctx, opad.c_str(), B);
    SHA1_Update(&ctx, result.c_str(), L);
    SHA1_Final((unsigned char *)&result[0], &ctx);
    return result;
}

void
hexstringFromData(const void *data, size_t len, void *output)
{
    const unsigned char *buf = (const unsigned char *)data;
    char *hex = (char *)output;
    size_t i, j;
    for (i = j = 0; i < len; ++i) {
        char c;
        c = (buf[i] >> 4) & 0xf;
        c = (c > 9) ? c + 'a' - 10 : c + '0';
        hex[j++] = c;
        c = (buf[i] & 0xf);
        c = (c > 9) ? c + 'a' - 10 : c + '0';
        hex[j++] = c;
    }
    hex[j] = '\0';
}

std::string
hexstringFromData(const void *data, size_t len)
{
    if (len == 0)
        return "";
    std::string result;
    result.resize(len * 2);
    hexstringFromData(data, len, &result[0]);
    return result;
}

void
replace(std::string &str, char find, char replaceWith)
{
    size_t index = str.find(find);
    while (index != std::string::npos) {
        str[index] = replaceWith;
        index = str.find(find, index + 1);
    }
}

std::vector<std::string>
split(const std::string &str, char delim, size_t max)
{
    MORDOR_ASSERT(max > 1);
	std::vector<std::string> result;

	size_t last = 0;
	size_t pos = str.find(delim);
	while (pos != std::string::npos) {
		result.push_back(str.substr(last, pos - last));
		last = pos + 1;
        if (--max == 1)
            break;
		pos = str.find(delim, last);
	}
    result.push_back(str.substr(last));
	return result;
}

std::vector<std::string>
split(const std::string &str, const char *delims, size_t max)
{
    MORDOR_ASSERT(max > 1);
	std::vector<std::string> result;

	size_t last = 0;
	size_t pos = str.find_first_of(delims);
	while (pos != std::string::npos) {
		result.push_back(str.substr(last, pos - last));
		last = pos + 1;
        if (--max == 1)
            break;
		pos = str.find_first_of(delims, last);
	}
    result.push_back(str.substr(last));
	return result;
}

#ifdef WINDOWS
std::string
toUtf8(const wchar_t *str, size_t len)
{
    if (len == (size_t)~0)
        len = wcslen(str);
    MORDOR_ASSERT(len < 0x80000000u);
    std::string result;
    if (len == 0)
        return result;
    int ret = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, str, (int)len, NULL, 0, NULL, NULL);
    if (ret == 0)
        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WideCharToMultiByte");
    result.resize(ret);
    ret = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, str, (int)len, &result[0], ret, NULL, NULL);
    if (ret == 0)
        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WideCharToMultiByte");
    MORDOR_ASSERT(ret == result.size());

    return result;
}

std::string
toUtf8(const std::wstring &str)
{
    MORDOR_ASSERT(str.size() < 0x80000000u);
    return toUtf8(str.c_str(), str.size());
}

std::wstring
toUtf16(const char *str, size_t len)
{
    if (len == (size_t)~0)
        len = strlen(str);
    MORDOR_ASSERT(len < 0x80000000u);
    std::wstring result;
    if (len == 0)
        return result;
    int ret = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, (int)len, NULL, 0);
    if (ret == 0)
        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("MultiByteToWideChar");
    result.resize(ret);
    ret = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, (int)len, &result[0], ret);
    if (ret == 0)
        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("MultiByteToWideChar");
    MORDOR_ASSERT(ret == result.size());

    return result;
}

std::wstring
toUtf16(const std::string &str)
{
    MORDOR_ASSERT(str.size() < 0x80000000u);
    return toUtf16(str.c_str(), str.size());
}
#endif

bool
caseinsensitiveless::operator ()(const std::string &lhs, const std::string &rhs) const
{
    return stricmp(lhs.c_str(), rhs.c_str()) < 0;
}

std::ostream &operator <<(std::ostream &os, const charslice &slice)
{
    for (size_t i = 0; i < slice.m_len; ++i) {
        os.put(slice.m_slice[i]);
    }
    return os;
}

}
<commit_msg>If WideCharToMultiByte doesn't like our flags, drop them.<commit_after>// Copyright (c) 2009 - Decho Corp.

#include "mordor/pch.h"

#include <algorithm>

#include <string.h>

#include <openssl/md5.h>
#include <openssl/sha.h>

#include "mordor/string.h"

#include "assert.h"
#include "exception.h"

#ifdef MSVC
#pragma comment(lib, "libeay32")
#endif

namespace Mordor {

std::string
base64decode(const std::string &src)
{
    std::string result;
    result.resize(src.size() * 3 / 4);
    char *writeBuf = &result[0];

    const char* ptr = src.c_str();
    const char* end = ptr + src.size();

    while(ptr < end) {
        int i = 0;
        int padding = 0;
        int packed = 0;
        for(; i < 4 && ptr < end; ++i, ++ptr) {
            if(*ptr == '=') {
                ++padding;
                packed <<= 6;
                continue;
            }

            int val = 0;
            if(*ptr >= 'A' && *ptr <= 'Z')
                val = *ptr - 'A';
            else if(*ptr >= 'a' && *ptr <= 'z')
                val = *ptr - 'a' + 26;
            else if(*ptr >= '0' && *ptr <= '9')
                val = *ptr - '0' + 52;
            else if(*ptr == '+')
                val = 62;
            else if(*ptr == '/')
                val = 63;
            else
                return "";

            packed = (packed << 6) | val;
        }
        if (i != 4)
            MORDOR_ASSERT(false);
        if (padding > 0 && ptr != end)
            MORDOR_ASSERT(false);
        if (padding > 2)
            MORDOR_ASSERT(false);

        *writeBuf++ = (char)((packed >> 16) & 0xff);
        if(padding != 2)
            *writeBuf++ = (char)((packed >> 8) & 0xff);
        if(padding == 0)
            *writeBuf++ = (char)(packed & 0xff);
    }

    result.resize(writeBuf - result.c_str());
    return result;
}

std::string
base64encode(const std::string& data)
{
    return base64encode(data.c_str(), data.size());
}

std::string
base64encode(const void* data, size_t len)
{
    const char* base64 =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    std::string ret;
    ret.reserve(len * 4 / 3 + 2);

    const unsigned char* ptr = (const unsigned char*)data;
    const unsigned char* end = ptr + len;

    while(ptr < end) {
        unsigned int packed = 0;
        int i = 0;
        int padding = 0;
        for(; i < 3 && ptr < end; ++i, ++ptr)
            packed = (packed << 8) | *ptr;
        if(i == 2)
            padding = 1;
        else if (i == 1)
            padding = 2;
        for(; i < 3; ++i)
            packed <<= 8;

        ret.append(1, base64[packed >> 18]);
        ret.append(1, base64[(packed >> 12) & 0x3f]);
        if(padding != 2)
            ret.append(1, base64[(packed >> 6) & 0x3f]);
        if(padding == 0)
            ret.append(1, base64[packed & 0x3f]);
        ret.append(padding, '=');
    }

    return ret;
}

std::string
md5(const std::string &data)
{
    return hexstringFromData(md5sum(data).c_str(), MD5_DIGEST_LENGTH);
}

std::string
sha1(const std::string &data)
{
	return hexstringFromData(sha1sum(data).c_str(), SHA_DIGEST_LENGTH);
}

std::string
md5sum(const void *data, size_t len)
{
    MD5_CTX ctx;
    MD5_Init(&ctx);
    MD5_Update(&ctx, data, len);
    std::string result;
    result.resize(MD5_DIGEST_LENGTH);
    MD5_Final((unsigned char*)&result[0], &ctx);
    return result;
}

std::string
md5sum(const std::string &data)
{
    return md5sum(data.c_str(), data.size());
}

std::string
sha1sum(const void *data, size_t len)
{
    SHA_CTX ctx;
    SHA1_Init(&ctx);
    SHA1_Update(&ctx, data, len);
    std::string result;
    result.resize(SHA_DIGEST_LENGTH);
    SHA1_Final((unsigned char*)&result[0], &ctx);
    return result;
}

std::string
sha1sum(const std::string &data)
{
    return sha1sum(data.c_str(), data.size());
}

struct xorStruct
{
    xorStruct(char value) : m_value(value) {}
    char m_value;
    char operator()(char in) const { return in ^ m_value; }
};

std::string
hmacMd5(const std::string &text, std::string key)
{
    const unsigned int B = 64;
    const unsigned int L = MD5_DIGEST_LENGTH;
    if (key.size() > B)
        key = md5sum(key);
    key.append(B - key.size(), '\0');
    std::string ipad = key, opad = key;
    std::transform(ipad.begin(), ipad.end(), ipad.begin(), xorStruct(0x36));
    std::transform(opad.begin(), opad.end(), opad.begin(), xorStruct(0x5c));
    MD5_CTX ctx;
    MD5_Init(&ctx);
    MD5_Update(&ctx, ipad.c_str(), B);
    MD5_Update(&ctx, text.c_str(), text.size());
    std::string result;
    result.resize(L);
    MD5_Final((unsigned char *)&result[0], &ctx);
    MD5_Init(&ctx);
    MD5_Update(&ctx, opad.c_str(), B);
    MD5_Update(&ctx, result.c_str(), L);
    MD5_Final((unsigned char *)&result[0], &ctx);
    return result;
}

std::string
hmacSha1(const std::string &text, std::string key)
{
    const unsigned int B = 64;
    const unsigned int L = SHA_DIGEST_LENGTH;
    if (key.size() > B)
        key = sha1sum(key);
    key.append(B - key.size(), '\0');
    std::string ipad = key, opad = key;
    std::transform(ipad.begin(), ipad.end(), ipad.begin(), xorStruct(0x36));
    std::transform(opad.begin(), opad.end(), opad.begin(), xorStruct(0x5c));
    SHA_CTX ctx;
    SHA1_Init(&ctx);
    SHA1_Update(&ctx, ipad.c_str(), B);
    SHA1_Update(&ctx, text.c_str(), text.size());
    std::string result;
    result.resize(L);
    SHA1_Final((unsigned char *)&result[0], &ctx);
    SHA1_Init(&ctx);
    SHA1_Update(&ctx, opad.c_str(), B);
    SHA1_Update(&ctx, result.c_str(), L);
    SHA1_Final((unsigned char *)&result[0], &ctx);
    return result;
}

void
hexstringFromData(const void *data, size_t len, void *output)
{
    const unsigned char *buf = (const unsigned char *)data;
    char *hex = (char *)output;
    size_t i, j;
    for (i = j = 0; i < len; ++i) {
        char c;
        c = (buf[i] >> 4) & 0xf;
        c = (c > 9) ? c + 'a' - 10 : c + '0';
        hex[j++] = c;
        c = (buf[i] & 0xf);
        c = (c > 9) ? c + 'a' - 10 : c + '0';
        hex[j++] = c;
    }
    hex[j] = '\0';
}

std::string
hexstringFromData(const void *data, size_t len)
{
    if (len == 0)
        return "";
    std::string result;
    result.resize(len * 2);
    hexstringFromData(data, len, &result[0]);
    return result;
}

void
replace(std::string &str, char find, char replaceWith)
{
    size_t index = str.find(find);
    while (index != std::string::npos) {
        str[index] = replaceWith;
        index = str.find(find, index + 1);
    }
}

std::vector<std::string>
split(const std::string &str, char delim, size_t max)
{
    MORDOR_ASSERT(max > 1);
	std::vector<std::string> result;

	size_t last = 0;
	size_t pos = str.find(delim);
	while (pos != std::string::npos) {
		result.push_back(str.substr(last, pos - last));
		last = pos + 1;
        if (--max == 1)
            break;
		pos = str.find(delim, last);
	}
    result.push_back(str.substr(last));
	return result;
}

std::vector<std::string>
split(const std::string &str, const char *delims, size_t max)
{
    MORDOR_ASSERT(max > 1);
	std::vector<std::string> result;

	size_t last = 0;
	size_t pos = str.find_first_of(delims);
	while (pos != std::string::npos) {
		result.push_back(str.substr(last, pos - last));
		last = pos + 1;
        if (--max == 1)
            break;
		pos = str.find_first_of(delims, last);
	}
    result.push_back(str.substr(last));
	return result;
}

#ifdef WINDOWS
static DWORD g_wcFlags = WC_ERR_INVALID_CHARS;
static DWORD g_mbFlags = MB_ERR_INVALID_CHARS;

std::string
toUtf8(const wchar_t *str, size_t len)
{
    if (len == (size_t)~0)
        len = wcslen(str);
    MORDOR_ASSERT(len < 0x80000000u);
    std::string result;
    if (len == 0)
        return result;
    int ret = WideCharToMultiByte(CP_UTF8, g_wcFlags, str, (int)len, NULL, 0, NULL, NULL);
    MORDOR_ASSERT(ret >= 0);
    if (ret == 0) {
        if (GetLastError() == ERROR_INVALID_FLAGS) {
            g_wcFlags = 0;
            ret = WideCharToMultiByte(CP_UTF8, g_wcFlags, str, (int)len, NULL, 0, NULL, NULL);
            MORDOR_ASSERT(ret >= 0);
        }
        if (ret == 0)
            MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WideCharToMultiByte");
    }
    result.resize(ret);
    ret = WideCharToMultiByte(CP_UTF8, g_wcFlags, str, (int)len, &result[0], ret, NULL, NULL);
    MORDOR_ASSERT(ret >= 0);
    if (ret == 0)
        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WideCharToMultiByte");
    MORDOR_ASSERT(ret == result.size());

    return result;
}

std::string
toUtf8(const std::wstring &str)
{
    MORDOR_ASSERT(str.size() < 0x80000000u);
    return toUtf8(str.c_str(), str.size());
}

std::wstring
toUtf16(const char *str, size_t len)
{
    if (len == (size_t)~0)
        len = strlen(str);
    MORDOR_ASSERT(len < 0x80000000u);
    std::wstring result;
    if (len == 0)
        return result;
    int ret = MultiByteToWideChar(CP_UTF8, g_mbFlags, str, (int)len, NULL, 0);
    MORDOR_ASSERT(ret >= 0);
    if (ret == 0) {
        if (GetLastError() == ERROR_INVALID_FLAGS) {
            g_mbFlags = 0;
            ret = MultiByteToWideChar(CP_UTF8, g_mbFlags, str, (int)len, NULL, 0);
            MORDOR_ASSERT(ret >= 0);
        }
        if (ret == 0)
            MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("MultiByteToWideChar");
    }
    result.resize(ret);
    ret = MultiByteToWideChar(CP_UTF8, g_mbFlags, str, (int)len, &result[0], ret);
    if (ret == 0)
        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("MultiByteToWideChar");
    MORDOR_ASSERT(ret == result.size());

    return result;
}

std::wstring
toUtf16(const std::string &str)
{
    MORDOR_ASSERT(str.size() < 0x80000000u);
    return toUtf16(str.c_str(), str.size());
}
#endif

bool
caseinsensitiveless::operator ()(const std::string &lhs, const std::string &rhs) const
{
    return stricmp(lhs.c_str(), rhs.c_str()) < 0;
}

std::ostream &operator <<(std::ostream &os, const charslice &slice)
{
    for (size_t i = 0; i < slice.m_len; ++i) {
        os.put(slice.m_slice[i]);
    }
    return os;
}

}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2008 Soeren Sonnenburg
 * Copyright (C) 1999-2008 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include "classifier/Perceptron.h"
#include "features/Labels.h"
#include "lib/Mathematics.h"

CPerceptron::CPerceptron() : CLinearClassifier(), learn_rate(0.1), max_iter(1000)
{
}

CPerceptron::CPerceptron(CRealFeatures* traindat, CLabels* trainlab)
 : CLinearClassifier(), learn_rate(.1), max_iter(1000)
{
	set_features(traindat);
	set_labels(trainlab);
}

CPerceptron::~CPerceptron()
{
}

bool CPerceptron::train()
{
	ASSERT(labels);
	ASSERT(features);
	bool converged=false;
	INT iter=0;
	INT num_train_labels=0;
	INT* train_labels=labels->get_int_labels(num_train_labels);
	INT num_feat=features->get_num_features();
	INT num_vec=features->get_num_vectors();

	ASSERT(num_vec==num_train_labels);
	delete[] w;
	w_dim=num_feat;
	w=new DREAL[num_feat];
	ASSERT(w);

	DREAL* output=new DREAL[num_vec];
	ASSERT(output);

	//start with uniform w, bias=0
	bias=0;
	for (INT i=0; i<num_feat; i++)
		w[i]=1.0/num_feat;

	//loop till we either get everything classified right or reach max_iter
	while (!converged && iter<max_iter)
	{
		converged=true;
		for (INT i=0; i<num_vec; i++)
			output[i]=classify_example(i);

		for (INT i=0; i<num_vec; i++)
		{
			if (CMath::sign<DREAL>(output[i]) != train_labels[i])
			{
				converged=false;
				INT vlen;
				bool vfree;
				double* vec=features->get_feature_vector(i, vlen, vfree);

				bias+=learn_rate*train_labels[i];
				for (INT j=0; j<num_feat; j++)
					w[j]+=  learn_rate*train_labels[i]*vec[j];

				features->free_feature_vector(vec, i, vfree);
			}
		}

		iter++;
	}
	if (converged)
		SG_INFO( "perceptron algorithm converged after %d iterations\n", iter);
	else
		SG_INFO( "perceptron algorithm did not converge after %d iterations\n", max_iter);

	delete[] output;
	delete[] train_labels;

	return false;
}
<commit_msg>classifier: - Fix: Perceptron::train even returned false when it had converged.<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2008 Soeren Sonnenburg
 * Copyright (C) 1999-2008 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include "classifier/Perceptron.h"
#include "features/Labels.h"
#include "lib/Mathematics.h"

CPerceptron::CPerceptron() : CLinearClassifier(), learn_rate(0.1), max_iter(1000)
{
}

CPerceptron::CPerceptron(CRealFeatures* traindat, CLabels* trainlab)
 : CLinearClassifier(), learn_rate(.1), max_iter(1000)
{
	set_features(traindat);
	set_labels(trainlab);
}

CPerceptron::~CPerceptron()
{
}

bool CPerceptron::train()
{
	ASSERT(labels);
	ASSERT(features);
	bool converged=false;
	INT iter=0;
	INT num_train_labels=0;
	INT* train_labels=labels->get_int_labels(num_train_labels);
	INT num_feat=features->get_num_features();
	INT num_vec=features->get_num_vectors();

	ASSERT(num_vec==num_train_labels);
	delete[] w;
	w_dim=num_feat;
	w=new DREAL[num_feat];
	ASSERT(w);

	DREAL* output=new DREAL[num_vec];
	ASSERT(output);

	//start with uniform w, bias=0
	bias=0;
	for (INT i=0; i<num_feat; i++)
		w[i]=1.0/num_feat;

	//loop till we either get everything classified right or reach max_iter

	while (!converged && iter<max_iter)
	{
		converged=true;
		for (INT i=0; i<num_vec; i++)
			output[i]=classify_example(i);

		for (INT i=0; i<num_vec; i++)
		{
			if (CMath::sign<DREAL>(output[i]) != train_labels[i])
			{
				converged=false;
				INT vlen;
				bool vfree;
				double* vec=features->get_feature_vector(i, vlen, vfree);

				bias+=learn_rate*train_labels[i];
				for (INT j=0; j<num_feat; j++)
					w[j]+=  learn_rate*train_labels[i]*vec[j];

				features->free_feature_vector(vec, i, vfree);
			}
		}

		iter++;
	}

	if (converged)
		SG_INFO( "perceptron algorithm converged after %d iterations\n", iter);
	else
		SG_INFO( "perceptron algorithm did not converge after %d iterations\n", max_iter);

	delete[] output;
	delete[] train_labels;

	return converged;
}
<|endoftext|>