<commit_before>/*  This file is part of the Vc library. {{{
Copyright © 2009-2015 Matthias Kretz <kretz@kde.org>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the names of contributing organizations nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

}}}*/

#include "unittest.h"

using namespace Vc;

#define ALL_TYPES (ALL_VECTORS)

template<typename T> static constexpr T min(T a, T b) { return a < b ? a : b; }

template<typename Vec> constexpr unsigned long alignmentMask()
{
    return Vec::Size == 1 ? (
            // on 32bit the maximal alignment is 4 Bytes, even for 8-Byte doubles.
            min(sizeof(void*), sizeof(typename Vec::EntryType)) - 1
        ) : (
            // AVX::VectorAlignment is too large
            min(sizeof(Vec), alignof(Vec)) - 1
        );
}

TEST_TYPES(Vec, checkAlignment, ALL_TYPES)
{
    unsigned char i = 1;
    Vec a[10];
    unsigned long mask = alignmentMask<Vec>();
    for (i = 0; i < 10; ++i) {
        VERIFY((reinterpret_cast<size_t>(&a[i]) & mask) == 0) << "a = " << a << ", mask = " << mask;
    }
    const char *data = reinterpret_cast<const char *>(&a[0]);
    for (i = 0; i < 10; ++i) {
        VERIFY(&data[i * sizeof(Vec)] == reinterpret_cast<const char *>(&a[i]));
    }
}

void *hack_to_put_b_on_the_stack = 0;

TEST_TYPES(Vec, checkMemoryAlignment, ALL_TYPES)
{
    typedef typename Vec::EntryType T;
    const T *b = 0;
    Vc::Memory<Vec, 10> a;
    b = a;
    hack_to_put_b_on_the_stack = &b;
    size_t mask = memory_alignment<Vec>::value - 1;
    for (int i = 0; i < 10; ++i) {
        VERIFY((reinterpret_cast<size_t>(&b[i * Vec::Size]) & mask) == 0) << "b = " << b << ", mask = " << mask;
    }
}

enum Enum {
    loadArrayShortCount = 32 * 1024,
    streamingLoadCount = 1024
};
TEST_TYPES(Vec, loadArrayShort, (short_v, ushort_v, SimdArray<short, 32>, SimdArray<unsigned short, 32>))
{
    typedef typename Vec::EntryType T;

    Vc::Memory<Vec, loadArrayShortCount> array;
    for (int i = 0; i < loadArrayShortCount; ++i) {
        array[i] = i;
    }

    const Vec offsets(IndexesFromZero);
    for (int i = 0; i < loadArrayShortCount; i += Vec::Size) {
        const T *const addr = &array[i];
        Vec ii(i);
        ii += offsets;

        Vec a(addr, Vc::Aligned);
        COMPARE(a, ii);

        Vec b = Vec::Zero();
        b.load(addr, Vc::Aligned);
        COMPARE(b, ii);
    }
}

TEST_TYPES(Vec, loadArray, ALL_TYPES)
{
    typedef typename Vec::EntryType T;
    if (sizeof(T) < 4) {
        return;
    }

    enum loadArrayEnum { count = 256 * 1024 / sizeof(T) };
    Vc::Memory<Vec, count> array;
    for (int i = 0; i < count; ++i) {
        array[i] = i;
    }

    const Vec offsets(IndexesFromZero);
    for (int i = 0; i < count; i += Vec::Size) {
        const T *const addr = &array[i];
        Vec ii(i);
        ii += offsets;

        Vec a(addr, Vc::Aligned);
        COMPARE(a, ii);

        Vec b = Vec::Zero();
        b.load(addr, Vc::Aligned);
        COMPARE(b, ii);
    }

    // check that Vc allows construction from objects that auto-convert to T*
    Vec tmp0(array, Vc::Aligned);
    tmp0.load(array, Vc::Aligned);
}

TEST_TYPES(Vec, streamingLoad, ALL_TYPES)
{
    typedef typename Vec::EntryType T;

    Vc::Memory<Vec, streamingLoadCount> data;
    data[0] = static_cast<T>(-streamingLoadCount/2);
    for (int i = 1; i < streamingLoadCount; ++i) {
        data[i] = data[i - 1];
        ++data[i];
    }

    Vec ref = data.firstVector();
    for (size_t i = 0; i < streamingLoadCount - Vec::Size; ++i, ++ref) {
        Vec v1, v2;
        if (0 == i % Vec::Size) {
            v1 = Vec(&data[i], Vc::Aligned | Vc::Streaming);
            v2.load (&data[i], Vc::Aligned | Vc::Streaming);
        } else {
            v1 = Vec(&data[i], Vc::Streaming | Vc::Unaligned);
            v2.load (&data[i], Vc::Unaligned | Vc::Streaming);
        }
        COMPARE(v1, ref) << ", i = " << i;
        COMPARE(v2, ref) << ", i = " << i;
    }
}

TEST_TYPES(
    Pair, loadCvt,
    (concat<
        outer_product<Typelist<float>,
                      Typelist<double, int, unsigned int, short, unsigned short,
                               signed char, unsigned char>>,
        outer_product<Typelist<int>, Typelist<unsigned int, short, unsigned short,
                                              signed char, unsigned char>>,
        outer_product<Typelist<unsigned int>, Typelist<unsigned short, unsigned char>>,
        outer_product<Typelist<short>, Typelist<unsigned char, unsigned char>>,
        outer_product<Typelist<unsigned short>, Typelist<unsigned char>>>))
{
    using Vec = Vector<typename Pair::template at<0>>;
    using MemT = typename Pair::template at<1>;

    typedef typename Vec::EntryType VecT;
    MemT *data = Vc::malloc<MemT, Vc::AlignOnCacheline>(128);
    for (size_t i = 0; i < 128; ++i) {
        data[i] = static_cast<MemT>(i - 64);
    }

    for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
        Vec v;
        if (i % (2 * Vec::Size) == 0) {
            v = Vec(&data[i]);
        } else if (i % Vec::Size == 0) {
            v = Vec(&data[i], Vc::Aligned);
        } else {
            v = Vec(&data[i], Vc::Unaligned);
        }
        for (size_t j = 0; j < Vec::Size; ++j) {
            COMPARE(v[j], static_cast<VecT>(data[i + j]));
        }
    }
    for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
        Vec v;
        if (i % (2 * Vec::Size) == 0) {
            v.load(&data[i]);
        } else if (i % Vec::Size == 0) {
            v.load(&data[i], Vc::Aligned);
        } else {
            v.load(&data[i], Vc::Unaligned);
        }
        for (size_t j = 0; j < Vec::Size; ++j) {
            COMPARE(v[j], static_cast<VecT>(data[i + j]));
        }
    }
    for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
        Vec v;
        if (i % (2 * Vec::Size) == 0) {
            v = Vec(&data[i], Vc::Streaming);
        } else if (i % Vec::Size == 0) {
            v = Vec(&data[i], Vc::Streaming | Vc::Aligned);
        } else {
            v = Vec(&data[i], Vc::Streaming | Vc::Unaligned);
        }
        for (size_t j = 0; j < Vec::Size; ++j) {
            COMPARE(v[j], static_cast<VecT>(data[i + j]));
        }
    }
}
<commit_msg>Tests: Clang bug workaround: print index on failure<commit_after>/*  This file is part of the Vc library. {{{
Copyright © 2009-2015 Matthias Kretz <kretz@kde.org>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the names of contributing organizations nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

}}}*/

#include "unittest.h"

using namespace Vc;

#define ALL_TYPES (ALL_VECTORS)

template<typename T> static constexpr T min(T a, T b) { return a < b ? a : b; }

template<typename Vec> constexpr unsigned long alignmentMask()
{
    return Vec::Size == 1 ? (
            // on 32bit the maximal alignment is 4 Bytes, even for 8-Byte doubles.
            min(sizeof(void*), sizeof(typename Vec::EntryType)) - 1
        ) : (
            // AVX::VectorAlignment is too large
            min(sizeof(Vec), alignof(Vec)) - 1
        );
}

TEST_TYPES(Vec, checkAlignment, ALL_TYPES)
{
    unsigned char i = 1;
    Vec a[10];
    unsigned long mask = alignmentMask<Vec>();
    for (i = 0; i < 10; ++i) {
        VERIFY((reinterpret_cast<size_t>(&a[i]) & mask) == 0) << "a = " << a << ", mask = " << mask;
    }
    const char *data = reinterpret_cast<const char *>(&a[0]);
    for (i = 0; i < 10; ++i) {
        VERIFY(&data[i * sizeof(Vec)] == reinterpret_cast<const char *>(&a[i]));
    }
}

void *hack_to_put_b_on_the_stack = 0;

TEST_TYPES(Vec, checkMemoryAlignment, ALL_TYPES)
{
    typedef typename Vec::EntryType T;
    const T *b = 0;
    Vc::Memory<Vec, 10> a;
    b = a;
    hack_to_put_b_on_the_stack = &b;
    size_t mask = memory_alignment<Vec>::value - 1;
    for (int i = 0; i < 10; ++i) {
        VERIFY((reinterpret_cast<size_t>(&b[i * Vec::Size]) & mask) == 0) << "b = " << b << ", mask = " << mask;
    }
}

enum Enum {
    loadArrayShortCount = 32 * 1024,
    streamingLoadCount = 1024
};
TEST_TYPES(Vec, loadArrayShort, (short_v, ushort_v, SimdArray<short, 32>, SimdArray<unsigned short, 32>))
{
    typedef typename Vec::EntryType T;

    Vc::Memory<Vec, loadArrayShortCount> array;
    for (int i = 0; i < loadArrayShortCount; ++i) {
        array[i] = i;
    }

    const Vec offsets(IndexesFromZero);
    for (int i = 0; i < loadArrayShortCount; i += Vec::Size) {
        const T *const addr = &array[i];
        Vec ii(i);
        ii += offsets;

        Vec a(addr, Vc::Aligned);
        COMPARE(a, ii);

        Vec b = Vec::Zero();
        b.load(addr, Vc::Aligned);
        COMPARE(b, ii);
    }
}

TEST_TYPES(Vec, loadArray, ALL_TYPES)
{
    typedef typename Vec::EntryType T;
    if (sizeof(T) < 4) {
        return;
    }

    enum loadArrayEnum { count = 256 * 1024 / sizeof(T) };
    Vc::Memory<Vec, count> array;
    for (int i = 0; i < count; ++i) {
        array[i] = i;
    }

    const Vec offsets(IndexesFromZero);
    for (int i = 0; i < count; i += Vec::Size) {
        const T *const addr = &array[i];
        Vec ii(i);
        ii += offsets;

        Vec a(addr, Vc::Aligned);
        COMPARE(a, ii);

        Vec b = Vec::Zero();
        b.load(addr, Vc::Aligned);
        COMPARE(b, ii);
    }

    // check that Vc allows construction from objects that auto-convert to T*
    Vec tmp0(array, Vc::Aligned);
    tmp0.load(array, Vc::Aligned);
}

TEST_TYPES(Vec, streamingLoad, ALL_TYPES)
{
    typedef typename Vec::EntryType T;

    Vc::Memory<Vec, streamingLoadCount> data;
    data[0] = static_cast<T>(-streamingLoadCount/2);
    for (int i = 1; i < streamingLoadCount; ++i) {
        data[i] = data[i - 1];
        ++data[i];
    }

    Vec ref = data.firstVector();
    for (size_t i = 0; i < streamingLoadCount - Vec::Size; ++i, ++ref) {
        Vec v1, v2;
        if (0 == i % Vec::Size) {
            v1 = Vec(&data[i], Vc::Aligned | Vc::Streaming);
            v2.load (&data[i], Vc::Aligned | Vc::Streaming);
        } else {
            v1 = Vec(&data[i], Vc::Streaming | Vc::Unaligned);
            v2.load (&data[i], Vc::Unaligned | Vc::Streaming);
        }
        COMPARE(v1, ref) << ", i = " << i;
        COMPARE(v2, ref) << ", i = " << i;
    }
}

TEST_TYPES(
    Pair, loadCvt,
    (concat<
        outer_product<Typelist<float>,
                      Typelist<double, int, unsigned int, short, unsigned short,
                               signed char, unsigned char>>,
        outer_product<Typelist<int>, Typelist<unsigned int, short, unsigned short,
                                              signed char, unsigned char>>,
        outer_product<Typelist<unsigned int>, Typelist<unsigned short, unsigned char>>,
        outer_product<Typelist<short>, Typelist<unsigned char, unsigned char>>,
        outer_product<Typelist<unsigned short>, Typelist<unsigned char>>>))
{
    using Vec = Vector<typename Pair::template at<0>>;
    using MemT = typename Pair::template at<1>;

    typedef typename Vec::EntryType VecT;
    MemT *data = Vc::malloc<MemT, Vc::AlignOnCacheline>(128);
    for (size_t i = 0; i < 128; ++i) {
        data[i] = static_cast<MemT>(i - 64);
    }

    for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
        Vec v;
        if (i % (2 * Vec::Size) == 0) {
            v = Vec(&data[i]);
        } else if (i % Vec::Size == 0) {
            v = Vec(&data[i], Vc::Aligned);
        } else {
            v = Vec(&data[i], Vc::Unaligned);
        }
        for (size_t j = 0; j < Vec::Size; ++j) {
            COMPARE(v[j], static_cast<VecT>(data[i + j])) << "j: " << j;
        }
    }
    for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
        Vec v;
        if (i % (2 * Vec::Size) == 0) {
            v.load(&data[i]);
        } else if (i % Vec::Size == 0) {
            v.load(&data[i], Vc::Aligned);
        } else {
            v.load(&data[i], Vc::Unaligned);
        }
        for (size_t j = 0; j < Vec::Size; ++j) {
            COMPARE(v[j], static_cast<VecT>(data[i + j])) << "j: " << j;
        }
    }
    for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
        Vec v;
        if (i % (2 * Vec::Size) == 0) {
            v = Vec(&data[i], Vc::Streaming);
        } else if (i % Vec::Size == 0) {
            v = Vec(&data[i], Vc::Streaming | Vc::Aligned);
        } else {
            v = Vec(&data[i], Vc::Streaming | Vc::Unaligned);
        }
        for (size_t j = 0; j < Vec::Size; ++j) {
            COMPARE(v[j], static_cast<VecT>(data[i + j])) << "j: " << j;
        }
    }
}
<|endoftext|>


<commit_before>/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2012-10-17 Markus Litz <Markus.Litz@dlr.de>
*
* 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 "gtest/gtest.h"
#include "CTiglLogging.h"
#include <tixi.h>

#ifdef HAVE_VLD
#include <vld.h>
#endif

// make tixi quiet
void tixiSilentMessage(MessageType , const char *, ...){}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    tigl::CTiglLogging::Instance().SetTimeIdInFilenameEnabled(false);
    // disable any console logging
    tigl::CTiglLogging::Instance().SetConsoleVerbosity(TILOG_SILENT);
    tigl::CTiglLogging::Instance().LogToFile("tigltest");
    // disable tixi output
    tixiSetPrintMsgFunc(tixiSilentMessage);
    int retval = RUN_ALL_TESTS();
    tixiCleanup();
    return retval;
}
<commit_msg>Fixed build with tixi 2.2.1<commit_after>/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2012-10-17 Markus Litz <Markus.Litz@dlr.de>
*
* 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 "gtest/gtest.h"
#include "CTiglLogging.h"
#include <tixi.h>

#ifdef HAVE_VLD
#include <vld.h>
#endif

// make tixi quiet
void tixiSilentMessage(MessageType , const char *){}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    tigl::CTiglLogging::Instance().SetTimeIdInFilenameEnabled(false);
    // disable any console logging
    tigl::CTiglLogging::Instance().SetConsoleVerbosity(TILOG_SILENT);
    tigl::CTiglLogging::Instance().LogToFile("tigltest");
    // disable tixi output
    tixiSetPrintMsgFunc(tixiSilentMessage);
    int retval = RUN_ALL_TESTS();
    tixiCleanup();
    return retval;
}
<|endoftext|>


<commit_before>/*
  C++ interface test
*/
#include "libmemcached/memcached.hh"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include "server.h"

#include "test.h"

#include <string>

using namespace std;

extern "C" {
   test_return basic_test(memcached_st *memc);
   test_return increment_test(memcached_st *memc);
   test_return basic_master_key_test(memcached_st *memc);
   test_return mget_result_function(memcached_st *memc);
   test_return mget_test(memcached_st *memc);
   memcached_return callback_counter(memcached_st *,
                                     memcached_result_st *,
                                     void *context);
   void *world_create(void);
   void world_destroy(void *p);
}

test_return basic_test(memcached_st *memc)
{
  Memcached foo(memc);
  const string value_set("This is some data");
  string value;
  size_t value_length;

  foo.set("mine", value_set, 0, 0);
  value= foo.get("mine", &value_length);

  assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));

  return TEST_SUCCESS;
}

test_return increment_test(memcached_st *memc)
{
  Memcached mcach(memc);
  bool rc;
  const string key("inctest");
  const string inc_value("1");
  string ret_value;
  uint64_t int_inc_value;
  uint64_t int_ret_value;
  size_t value_length;

  mcach.set(key, inc_value, 0, 0);
  ret_value= mcach.get(key, &value_length);
  printf("\nretvalue %s\n",ret_value.c_str());
  int_inc_value= uint64_t(atol(inc_value.c_str()));
  int_ret_value= uint64_t(atol(ret_value.c_str()));
  assert(int_ret_value == int_inc_value);

  rc= mcach.increment(key, 1, &int_ret_value);
  assert(rc == true);
  assert(int_ret_value == 2);

  rc= mcach.increment(key, 1, &int_ret_value);
  assert(rc == true);
  assert(int_ret_value == 3);

  rc= mcach.increment(key, 5, &int_ret_value);
  assert(rc == true);
  assert(int_ret_value == 8);

  return TEST_SUCCESS;
}

test_return basic_master_key_test(memcached_st *memc)
{
  Memcached foo(memc);
  const string value_set("Data for server A");
  const string master_key_a("server-a");
  const string master_key_b("server-b");
  const string key("xyz");
  string value;
  size_t value_length;

  foo.set_by_key(master_key_a, key, value_set, 0, 0);
  value= foo.get_by_key(master_key_a, key, &value_length);

  assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));

  value= foo.get_by_key(master_key_b, key, &value_length);
  assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));

  return TEST_SUCCESS;
}

/* Count the results */
memcached_return callback_counter(memcached_st *,
                                  memcached_result_st *,
                                  void *context)
{
  unsigned int *counter= static_cast<unsigned int *>(context);

  *counter= *counter + 1;

  return MEMCACHED_SUCCESS;
}

test_return mget_result_function(memcached_st *memc)
{
  Memcached mc(memc);
  bool rc;
  string key1("fudge");
  string key2("son");
  string key3("food");
  vector<string> keys;
  keys.reserve(3);
  keys.push_back(key1);
  keys.push_back(key2);
  keys.push_back(key3);
  unsigned int counter;
  memcached_execute_function callbacks[1];

  /* We need to empty the server before we continue the test */
  rc= mc.flush(0);
  rc= mc.set_all(keys, keys, 50, 9);
  assert(rc == true);

  rc= mc.mget(keys);
  assert(rc == true);

  callbacks[0]= &callback_counter;
  counter= 0;
  rc= mc.fetch_execute(callbacks, static_cast<void *>(&counter), 1);

  assert(counter == 3);

  return TEST_SUCCESS;
}

test_return mget_test(memcached_st *memc)
{
  Memcached mc(memc);
  bool rc;
  memcached_return mc_rc;
  vector<string> keys;
  keys.reserve(3);
  keys.push_back("fudge");
  keys.push_back("son");
  keys.push_back("food");
  uint32_t flags;

  string return_key;
  size_t return_key_length;
  string return_value;
  size_t return_value_length;

  /* We need to empty the server before we continue the test */
  rc= mc.flush(0);
  assert(rc == true);

  rc= mc.mget(keys);
  assert(rc == true);

  while (mc.fetch(return_key, return_value, &return_key_length,
                  &return_value_length, &flags, &mc_rc))
  {
    assert(return_value.length() != 0);
  }
  assert(return_value_length == 0);
  assert(mc_rc == MEMCACHED_END);

  rc= mc.set_all(keys, keys, 50, 9);
  assert(rc == true);

  rc= mc.mget(keys);
  assert(rc == true);

  while ((mc.fetch(return_key, return_value, &return_key_length,
                   &return_value_length, &flags, &mc_rc)))
  {
    assert(return_value.length() != 0);
    assert(mc_rc == MEMCACHED_SUCCESS);
    assert(return_key_length == return_value_length);
    assert(!memcmp(return_value.c_str(), return_key.c_str(), return_value_length));
  }

  return TEST_SUCCESS;
}

test_st tests[] ={
  { "basic", 0, basic_test },
  { "basic_master_key", 0, basic_master_key_test },
  { "increment_test", 0, increment_test },
  { "mget", 1, mget_test },
  { "mget_result_function", 1, mget_result_function },
  {0, 0, 0}
};

collection_st collection[] ={
  {"block", 0, 0, tests},
  {0, 0, 0, 0}
};

#define SERVERS_TO_CREATE 1

extern "C" void *world_create(void)
{
  server_startup_st *construct;

  construct= (server_startup_st *)malloc(sizeof(server_startup_st));
  memset(construct, 0, sizeof(server_startup_st));

  construct->count= SERVERS_TO_CREATE;
  server_startup(construct);

  return construct;
}

void world_destroy(void *p)
{
  server_startup_st *construct= static_cast<server_startup_st *>(p);
  memcached_server_st *servers=
    static_cast<memcached_server_st *>(construct->servers);
  memcached_server_list_free(servers);

  server_shutdown(construct);
  free(construct);
}

void get_world(world_st *world)
{
  world->collections= collection;
  world->create= world_create;
  world->destroy= world_destroy;
}
<commit_msg>Updating the C++ test case file after making changes to the C++ interface.<commit_after>/*
  C++ interface test
*/
#include "libmemcached/memcached.hh"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include "server.h"

#include "test.h"

#include <string>

using namespace std;

extern "C" {
   test_return basic_test(memcached_st *memc);
   test_return increment_test(memcached_st *memc);
   test_return basic_master_key_test(memcached_st *memc);
   test_return mget_result_function(memcached_st *memc);
   test_return mget_test(memcached_st *memc);
   memcached_return callback_counter(memcached_st *,
                                     memcached_result_st *,
                                     void *context);
   void *world_create(void);
   void world_destroy(void *p);
}

test_return basic_test(memcached_st *memc)
{
  Memcached foo(memc);
  const string value_set("This is some data");
  string value;
  size_t value_length;

  foo.set("mine", value_set, 0, 0);
  value= foo.get("mine", &value_length);

  assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));

  return TEST_SUCCESS;
}

test_return increment_test(memcached_st *memc)
{
  Memcached mcach(memc);
  bool rc;
  const string key("inctest");
  const string inc_value("1");
  string ret_value;
  uint64_t int_inc_value;
  uint64_t int_ret_value;
  size_t value_length;

  mcach.set(key, inc_value, 0, 0);
  ret_value= mcach.get(key, &value_length);
  printf("\nretvalue %s\n",ret_value.c_str());
  int_inc_value= uint64_t(atol(inc_value.c_str()));
  int_ret_value= uint64_t(atol(ret_value.c_str()));
  assert(int_ret_value == int_inc_value);

  rc= mcach.increment(key, 1, &int_ret_value);
  assert(rc == true);
  assert(int_ret_value == 2);

  rc= mcach.increment(key, 1, &int_ret_value);
  assert(rc == true);
  assert(int_ret_value == 3);

  rc= mcach.increment(key, 5, &int_ret_value);
  assert(rc == true);
  assert(int_ret_value == 8);

  return TEST_SUCCESS;
}

test_return basic_master_key_test(memcached_st *memc)
{
  Memcached foo(memc);
  const string value_set("Data for server A");
  const string master_key_a("server-a");
  const string master_key_b("server-b");
  const string key("xyz");
  string value;
  size_t value_length;

  foo.setByKey(master_key_a, key, value_set, 0, 0);
  value= foo.getByKey(master_key_a, key, &value_length);

  assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));

  value= foo.getByKey(master_key_b, key, &value_length);
  assert((memcmp(value.c_str(), value_set.c_str(), value_length) == 0));

  return TEST_SUCCESS;
}

/* Count the results */
memcached_return callback_counter(memcached_st *,
                                  memcached_result_st *,
                                  void *context)
{
  unsigned int *counter= static_cast<unsigned int *>(context);

  *counter= *counter + 1;

  return MEMCACHED_SUCCESS;
}

test_return mget_result_function(memcached_st *memc)
{
  Memcached mc(memc);
  bool rc;
  string key1("fudge");
  string key2("son");
  string key3("food");
  vector<string> keys;
  keys.reserve(3);
  keys.push_back(key1);
  keys.push_back(key2);
  keys.push_back(key3);
  unsigned int counter;
  memcached_execute_function callbacks[1];

  /* We need to empty the server before we continue the test */
  rc= mc.flush(0);
  rc= mc.setAll(keys, keys, 50, 9);
  assert(rc == true);

  rc= mc.mget(keys);
  assert(rc == true);

  callbacks[0]= &callback_counter;
  counter= 0;
  rc= mc.fetchExecute(callbacks, static_cast<void *>(&counter), 1);

  assert(counter == 3);

  return TEST_SUCCESS;
}

test_return mget_test(memcached_st *memc)
{
  Memcached mc(memc);
  bool rc;
  memcached_return mc_rc;
  vector<string> keys;
  keys.reserve(3);
  keys.push_back("fudge");
  keys.push_back("son");
  keys.push_back("food");
  uint32_t flags;

  string return_key;
  size_t return_key_length;
  string return_value;
  size_t return_value_length;

  /* We need to empty the server before we continue the test */
  rc= mc.flush(0);
  assert(rc == true);

  rc= mc.mget(keys);
  assert(rc == true);

  while (mc.fetch(return_key, return_value, &return_key_length,
                  &return_value_length, &flags, &mc_rc))
  {
    assert(return_value.length() != 0);
  }
  assert(return_value_length == 0);
  assert(mc_rc == MEMCACHED_END);

  rc= mc.setAll(keys, keys, 50, 9);
  assert(rc == true);

  rc= mc.mget(keys);
  assert(rc == true);

  while ((mc.fetch(return_key, return_value, &return_key_length,
                   &return_value_length, &flags, &mc_rc)))
  {
    assert(return_value.length() != 0);
    assert(mc_rc == MEMCACHED_SUCCESS);
    assert(return_key_length == return_value_length);
    assert(!memcmp(return_value.c_str(), return_key.c_str(), return_value_length));
  }

  return TEST_SUCCESS;
}

test_st tests[] ={
  { "basic", 0, basic_test },
  { "basic_master_key", 0, basic_master_key_test },
  { "increment_test", 0, increment_test },
  { "mget", 1, mget_test },
  { "mget_result_function", 1, mget_result_function },
  {0, 0, 0}
};

collection_st collection[] ={
  {"block", 0, 0, tests},
  {0, 0, 0, 0}
};

#define SERVERS_TO_CREATE 1

extern "C" void *world_create(void)
{
  server_startup_st *construct;

  construct= (server_startup_st *)malloc(sizeof(server_startup_st));
  memset(construct, 0, sizeof(server_startup_st));

  construct->count= SERVERS_TO_CREATE;
  server_startup(construct);

  return construct;
}

void world_destroy(void *p)
{
  server_startup_st *construct= static_cast<server_startup_st *>(p);
  memcached_server_st *servers=
    static_cast<memcached_server_st *>(construct->servers);
  memcached_server_list_free(servers);

  server_shutdown(construct);
  free(construct);
}

void get_world(world_st *world)
{
  world->collections= collection;
  world->create= world_create;
  world->destroy= world_destroy;
}
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;
int& test(int& inval){
    return inval;
}
auto test2(int& inval) -> decltype(test(inval)){
    return test(inval);
}
int main(){
    int x = 1;
    cout<<x<<endl;
    int& try1=test(x);
    cout<<try1<<endl;
    x=2;
    cout<<try1<<endl;
    x=1;
    int &try2=test2(x);
    cout<<try2<<endl;
    x=2;
    cout<<try2<<endl;
    try2=3;
    cout<<x<<endl;
    return 0;
}
<commit_msg>Added documentation on input language<commit_after><|endoftext|>


<commit_before>/*
	This file is part of the CVD Library.

	Copyright (C) 2005 The Authors

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

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

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
inline ImageRef::ImageRef()
{
	x=y=0;
}

inline ImageRef::ImageRef(int xp, int yp)
:x(xp),y(yp)
{}

inline ImageRef::ImageRef(std::istream& is)
{
	is.read((char*)&x,sizeof(int));
	is.read((char*)&y,sizeof(int));
}

	//////////////////////////////////////////////////////////////////////////
	// the following cryptic pieces of rubbish are because inline functions //
	// must have their one and only return function as the last call        //
	// so this code makes use of the fact that expressions to the right     //
	// of || are only evaluated when the left hand side is false            //
	//////////////////////////////////////////////////////////////////////////

inline bool ImageRef::next(const ImageRef& max)	// move on to the next value
{
	return(++x != max.x || (x=0, ++y != max.y) || (y=0, false));
}

inline bool ImageRef::next(const ImageRef& min, const ImageRef& max)
{
	return (++x != max.x || (x=min.x, ++y != max.y) || (y=min.y, false));
}

inline bool ImageRef::prev(const ImageRef& max)	// move back to the previous value
{
	return(--x != -1 || (x=max.x-1, --y != -1) || (y=max.y-1, false));
}

inline bool ImageRef::prev(const ImageRef& min, const ImageRef& max)
{
	return (--x != min.x-1 || (x=max.x-1, --y != min.y-1) || (y=max.y-1, false));
}

inline void ImageRef::home()
{
	x=y=0;
}

inline void ImageRef::end(const ImageRef& size)
{
	x=size.x-1;
	y=size.y-1;
}

inline ImageRef& ImageRef::operator=(const ImageRef& ref)
{
	x=ref.x;
	y=ref.y;
	return *this;
}

inline bool ImageRef::operator ==(const ImageRef& ref) const
{
	return (x==ref.x && y==ref.y);
}

inline bool ImageRef::operator !=(const ImageRef& ref) const
{
	return (x!=ref.x || y!=ref.y);
}

inline ImageRef ImageRef::operator-() const
{
  ImageRef v(-x, -y);
  return v;
}

inline ImageRef& ImageRef::operator*=(const double scale)
{
  x=(int)(x*scale);
  y=(int)(y*scale);
  return *this;
}

inline ImageRef& ImageRef::operator/=(const double scale)
{
	x=(int)(x/scale);
	y=(int)(y/scale);
	return *this;
}

inline ImageRef& ImageRef::operator+=(const ImageRef rhs)
{
	x+=rhs.x;
	y+=rhs.y;
	return *this;
}

inline ImageRef& ImageRef::operator-=(const ImageRef rhs)
{
	x-=rhs.x;
	y-=rhs.y;
	return *this;
}

inline ImageRef ImageRef::operator*(const double scale) const
{
	ImageRef v((int)(x*scale),(int)(y*scale));
	return v;
}

inline ImageRef ImageRef::operator/(const double scale) const
{
	ImageRef v((int)(x/scale),(int)(y/scale));
	return v;
}

inline ImageRef ImageRef::operator+(const ImageRef rhs) const
{
	ImageRef v(x+rhs.x, y+rhs.y);
	return v;
}

inline ImageRef ImageRef::operator-(const ImageRef rhs) const
{
	ImageRef v(x-rhs.x, y-rhs.y);
	return v;
}

inline ImageRef& ImageRef::operator<<=(int i)
{
	x = x << i;
	y=y << i;
	return *this;
}

inline ImageRef& ImageRef::operator>>=(int i)
{
	x = x >> i;
	y=y >> i;
	return *this;
}

inline ImageRef ImageRef::shiftl(int i) const
{
	ImageRef result;
	result.x = x << i;
	result.y=y << i;
	return result;
}

inline ImageRef ImageRef::shiftr(int i) const
{
	ImageRef result;
	result.x = x >> i;
	result.y=y >> i;
	return result;
}

inline ImageRef ImageRef::operator<<(int i) const
{
	return shiftl(i);
}

inline ImageRef ImageRef::operator>>(int i) const
{
	return shiftr(i);
}

inline ImageRef operator*(const int scale, const ImageRef&  ref)
{
	return ImageRef(ref.x*scale, ref.y*scale);
}

inline bool ImageRef::operator<(const ImageRef & other) const
{
	return x < other.x || ( x == other.x && y < other.y);
}

inline int& ImageRef::operator[](int i)
{
  if(i==0)
    return x;
  if(i==1)
    return y;
  throw Exceptions::BadSubscript();
}

inline unsigned int ImageRef::mag_squared() const
{
  return (unsigned int) (x*x + y*y);
}
<commit_msg>Minor change to mag_squared(), to make it a little less likely to overflow.<commit_after>/*
	This file is part of the CVD Library.

	Copyright (C) 2005 The Authors

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

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

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
inline ImageRef::ImageRef()
{
	x=y=0;
}

inline ImageRef::ImageRef(int xp, int yp)
:x(xp),y(yp)
{}

inline ImageRef::ImageRef(std::istream& is)
{
	is.read((char*)&x,sizeof(int));
	is.read((char*)&y,sizeof(int));
}

	//////////////////////////////////////////////////////////////////////////
	// the following cryptic pieces of rubbish are because inline functions //
	// must have their one and only return function as the last call        //
	// so this code makes use of the fact that expressions to the right     //
	// of || are only evaluated when the left hand side is false            //
	//////////////////////////////////////////////////////////////////////////

inline bool ImageRef::next(const ImageRef& max)	// move on to the next value
{
	return(++x != max.x || (x=0, ++y != max.y) || (y=0, false));
}

inline bool ImageRef::next(const ImageRef& min, const ImageRef& max)
{
	return (++x != max.x || (x=min.x, ++y != max.y) || (y=min.y, false));
}

inline bool ImageRef::prev(const ImageRef& max)	// move back to the previous value
{
	return(--x != -1 || (x=max.x-1, --y != -1) || (y=max.y-1, false));
}

inline bool ImageRef::prev(const ImageRef& min, const ImageRef& max)
{
	return (--x != min.x-1 || (x=max.x-1, --y != min.y-1) || (y=max.y-1, false));
}

inline void ImageRef::home()
{
	x=y=0;
}

inline void ImageRef::end(const ImageRef& size)
{
	x=size.x-1;
	y=size.y-1;
}

inline ImageRef& ImageRef::operator=(const ImageRef& ref)
{
	x=ref.x;
	y=ref.y;
	return *this;
}

inline bool ImageRef::operator ==(const ImageRef& ref) const
{
	return (x==ref.x && y==ref.y);
}

inline bool ImageRef::operator !=(const ImageRef& ref) const
{
	return (x!=ref.x || y!=ref.y);
}

inline ImageRef ImageRef::operator-() const
{
  ImageRef v(-x, -y);
  return v;
}

inline ImageRef& ImageRef::operator*=(const double scale)
{
  x=(int)(x*scale);
  y=(int)(y*scale);
  return *this;
}

inline ImageRef& ImageRef::operator/=(const double scale)
{
	x=(int)(x/scale);
	y=(int)(y/scale);
	return *this;
}

inline ImageRef& ImageRef::operator+=(const ImageRef rhs)
{
	x+=rhs.x;
	y+=rhs.y;
	return *this;
}

inline ImageRef& ImageRef::operator-=(const ImageRef rhs)
{
	x-=rhs.x;
	y-=rhs.y;
	return *this;
}

inline ImageRef ImageRef::operator*(const double scale) const
{
	ImageRef v((int)(x*scale),(int)(y*scale));
	return v;
}

inline ImageRef ImageRef::operator/(const double scale) const
{
	ImageRef v((int)(x/scale),(int)(y/scale));
	return v;
}

inline ImageRef ImageRef::operator+(const ImageRef rhs) const
{
	ImageRef v(x+rhs.x, y+rhs.y);
	return v;
}

inline ImageRef ImageRef::operator-(const ImageRef rhs) const
{
	ImageRef v(x-rhs.x, y-rhs.y);
	return v;
}

inline ImageRef& ImageRef::operator<<=(int i)
{
	x = x << i;
	y=y << i;
	return *this;
}

inline ImageRef& ImageRef::operator>>=(int i)
{
	x = x >> i;
	y=y >> i;
	return *this;
}

inline ImageRef ImageRef::shiftl(int i) const
{
	ImageRef result;
	result.x = x << i;
	result.y=y << i;
	return result;
}

inline ImageRef ImageRef::shiftr(int i) const
{
	ImageRef result;
	result.x = x >> i;
	result.y=y >> i;
	return result;
}

inline ImageRef ImageRef::operator<<(int i) const
{
	return shiftl(i);
}

inline ImageRef ImageRef::operator>>(int i) const
{
	return shiftr(i);
}

inline ImageRef operator*(const int scale, const ImageRef&  ref)
{
	return ImageRef(ref.x*scale, ref.y*scale);
}

inline bool ImageRef::operator<(const ImageRef & other) const
{
	return x < other.x || ( x == other.x && y < other.y);
}

inline int& ImageRef::operator[](int i)
{
  if(i==0)
    return x;
  if(i==1)
    return y;
  throw Exceptions::BadSubscript();
}

inline unsigned int ImageRef::mag_squared() const
{
  typedef unsigned int uint;
  return uint(x*x) + uint(y*y);
}
<|endoftext|>


<commit_before>/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-

 * Copyright (C) 2013 Red Hat, Inc.
 *
 * Licensed under the GNU Lesser General Public License Version 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <stdlib.h>
#include <fnmatch.h>
#include "dnf-reldep.h"
#include "dnf-sack-private.hpp"
#include "hy-subject.h"
#include "hy-iutil-private.hpp"
#include "nevra.hpp"
#include "nsvcap.hpp"
#include "hy-types.h"
#include "hy-query-private.hpp"
#include "hy-selector.h"
#include "hy-util-private.hpp"
#include "sack/packageset.hpp"

// most specific to least
const HyForm HY_FORMS_MOST_SPEC[] = {
    HY_FORM_NEVRA, HY_FORM_NA, HY_FORM_NAME, HY_FORM_NEVR, HY_FORM_NEV, _HY_FORM_STOP_ };

const HyModuleForm HY_MODULE_FORMS_MOST_SPEC[] = {
        HY_MODULE_FORM_NSVCAP,
        HY_MODULE_FORM_NSVCA,
        HY_MODULE_FORM_NSVAP,
        HY_MODULE_FORM_NSVA,
        HY_MODULE_FORM_NSAP,
        HY_MODULE_FORM_NSA,
        HY_MODULE_FORM_NSVCP,
        HY_MODULE_FORM_NSVP,
        HY_MODULE_FORM_NSVC,
        HY_MODULE_FORM_NSV,
        HY_MODULE_FORM_NSP,
        HY_MODULE_FORM_NS,
        HY_MODULE_FORM_NAP,
        HY_MODULE_FORM_NA,
        HY_MODULE_FORM_NP,
        HY_MODULE_FORM_N,
        _HY_MODULE_FORM_STOP_};

HySubject
hy_subject_create(const char * pattern)
{
    return g_strdup(pattern);
}

void
hy_subject_free(HySubject subject)
{
    g_free(subject);
}

/* Given a subject, attempt to create a query choose the first one, and update
 * the query to try to match it.
 *
 * Since then, it was amended to add a `with_src` flag to avoid finding source packages
 * from provides.
 */
HyQuery
hy_subject_get_best_solution(HySubject subject, DnfSack *sack, HyForm *forms, HyNevra *out_nevra,
                             gboolean icase, gboolean with_nevra, gboolean with_provides,
                             gboolean with_filenames, gboolean with_src)
{
    if (with_nevra) {
        libdnf::Nevra nevraObj;
        const auto tryForms = !forms ? HY_FORMS_MOST_SPEC : forms;
        for (std::size_t i = 0; tryForms[i] != _HY_FORM_STOP_; ++i) {
            if (nevraObj.parse(subject, tryForms[i])) {
                auto query = hy_query_from_nevra(&nevraObj, sack, icase);
                if (!with_src)
                    hy_query_filter(query, HY_PKG_ARCH, HY_NEQ, "src");
                if (!hy_query_is_empty(query)) {
                    *out_nevra = new libdnf::Nevra(std::move(nevraObj));
                    return query;
                }
                hy_query_free(query);
            }
        }
        *out_nevra = nullptr;
        if (!forms) {
            auto query = hy_query_create(sack);
            if (!with_src)
                hy_query_filter(query, HY_PKG_ARCH, HY_NEQ, "src");
            hy_query_filter(query, HY_PKG_NEVRA, HY_GLOB, subject);
            if (!hy_query_is_empty(query))
                return query;
            hy_query_free(query);
        }
    }

    if (with_provides) {
        auto query = hy_query_create(sack);
        if (!with_src)
            hy_query_filter(query, HY_PKG_ARCH, HY_NEQ, "src");
        hy_query_filter(query, HY_PKG_PROVIDES, HY_GLOB, subject);
        if (!hy_query_is_empty(query))
            return query;
        hy_query_free(query);
    }

    if (with_filenames && hy_is_file_pattern(subject)) {
        auto query = hy_query_create(sack);
        if (!with_src)
            hy_query_filter(query, HY_PKG_ARCH, HY_NEQ, "src");
        hy_query_filter(query, HY_PKG_FILE, HY_GLOB, subject);
        return query;
    }

    auto query = hy_query_create(sack);
    hy_query_filter_empty(query);
    return query;
}

HySelector
hy_subject_get_best_selector(HySubject subject, DnfSack *sack, HyForm *forms, bool obsoletes,
    const char *reponame)
{
    HyNevra nevra{nullptr};
    HyQuery query = hy_subject_get_best_solution(subject, sack, forms, &nevra, FALSE, TRUE, TRUE,
                                                 TRUE, false);
    if (!hy_query_is_empty(query)) {
        if (obsoletes && nevra && nevra->hasJustName()) {
            DnfPackageSet *pset;
            pset = hy_query_run_set(query);
            HyQuery query_obsoletes = hy_query_clone(query);
            hy_query_filter_package_in(query_obsoletes, HY_PKG_OBSOLETES, HY_EQ, pset);
            delete pset;
            hy_query_union(query, query_obsoletes);
            hy_query_free(query_obsoletes);
        }
        if (reponame != NULL) {
            HyQuery installed_query = hy_query_clone(query);
            hy_query_filter(installed_query, HY_PKG_REPONAME, HY_EQ, HY_SYSTEM_REPO_NAME);
            hy_query_filter(query, HY_PKG_REPONAME, HY_EQ, reponame);
            hy_query_union(query, installed_query);
            hy_query_free(installed_query);
        }
    }
    delete nevra;
    HySelector selector = hy_query_to_selector(query);
    hy_query_free(query);
    return selector;
}
<commit_msg>Apply src filtering more efficiently<commit_after>/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-

 * Copyright (C) 2013 Red Hat, Inc.
 *
 * Licensed under the GNU Lesser General Public License Version 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <stdlib.h>
#include <fnmatch.h>
#include "dnf-reldep.h"
#include "dnf-sack-private.hpp"
#include "hy-subject.h"
#include "hy-iutil-private.hpp"
#include "nevra.hpp"
#include "nsvcap.hpp"
#include "hy-types.h"
#include "hy-query-private.hpp"
#include "hy-selector.h"
#include "hy-util-private.hpp"
#include "sack/packageset.hpp"

// most specific to least
const HyForm HY_FORMS_MOST_SPEC[] = {
    HY_FORM_NEVRA, HY_FORM_NA, HY_FORM_NAME, HY_FORM_NEVR, HY_FORM_NEV, _HY_FORM_STOP_ };

const HyModuleForm HY_MODULE_FORMS_MOST_SPEC[] = {
        HY_MODULE_FORM_NSVCAP,
        HY_MODULE_FORM_NSVCA,
        HY_MODULE_FORM_NSVAP,
        HY_MODULE_FORM_NSVA,
        HY_MODULE_FORM_NSAP,
        HY_MODULE_FORM_NSA,
        HY_MODULE_FORM_NSVCP,
        HY_MODULE_FORM_NSVP,
        HY_MODULE_FORM_NSVC,
        HY_MODULE_FORM_NSV,
        HY_MODULE_FORM_NSP,
        HY_MODULE_FORM_NS,
        HY_MODULE_FORM_NAP,
        HY_MODULE_FORM_NA,
        HY_MODULE_FORM_NP,
        HY_MODULE_FORM_N,
        _HY_MODULE_FORM_STOP_};

HySubject
hy_subject_create(const char * pattern)
{
    return g_strdup(pattern);
}

void
hy_subject_free(HySubject subject)
{
    g_free(subject);
}

/* Given a subject, attempt to create a query choose the first one, and update
 * the query to try to match it.
 *
 * Since then, it was amended to add a `with_src` flag to avoid finding source packages
 * from provides.
 */
HyQuery
hy_subject_get_best_solution(HySubject subject, DnfSack *sack, HyForm *forms, HyNevra *out_nevra,
                             gboolean icase, gboolean with_nevra, gboolean with_provides,
                             gboolean with_filenames, gboolean with_src)
{
    libdnf::Query baseQuery(sack);
    if (!with_src) {
        baseQuery.addFilter(HY_PKG_ARCH, HY_NEQ, "src");
    }
    baseQuery.apply();
    if (with_nevra) {
        libdnf::Nevra nevraObj;
        const auto tryForms = !forms ? HY_FORMS_MOST_SPEC : forms;
        for (std::size_t i = 0; tryForms[i] != _HY_FORM_STOP_; ++i) {
            if (nevraObj.parse(subject, tryForms[i])) {
                auto query = std::unique_ptr<libdnf::Query>(new libdnf::Query(baseQuery));
                query->addFilter(&nevraObj, icase);
                if (!query->empty()) {
                    *out_nevra = new libdnf::Nevra(std::move(nevraObj));
                    return query.release();
                }
            }
        }
        *out_nevra = nullptr;
        if (!forms) {
            auto query = std::unique_ptr<libdnf::Query>(new libdnf::Query(baseQuery));
            query->addFilter(HY_PKG_NEVRA, HY_GLOB, subject);
            if (!query->empty())
                return query.release();
        }
    }

    if (with_provides) {
        auto query = std::unique_ptr<libdnf::Query>(new libdnf::Query(baseQuery));
        query->addFilter(HY_PKG_PROVIDES, HY_GLOB, subject);
        if (!query->empty())
            return query.release();
    }

    if (with_filenames && hy_is_file_pattern(subject)) {
        auto query = std::unique_ptr<libdnf::Query>(new libdnf::Query(baseQuery));
        query->addFilter(HY_PKG_FILE, HY_GLOB, subject);
        return query.release();
    }

    auto query = std::unique_ptr<libdnf::Query>(new libdnf::Query(baseQuery));
    query->addFilter(HY_PKG_EMPTY, HY_EQ, 1);
    return query.release();
}

HySelector
hy_subject_get_best_selector(HySubject subject, DnfSack *sack, HyForm *forms, bool obsoletes,
    const char *reponame)
{
    HyNevra nevra{nullptr};
    HyQuery query = hy_subject_get_best_solution(subject, sack, forms, &nevra, FALSE, TRUE, TRUE,
                                                 TRUE, false);
    if (!hy_query_is_empty(query)) {
        if (obsoletes && nevra && nevra->hasJustName()) {
            DnfPackageSet *pset;
            pset = hy_query_run_set(query);
            HyQuery query_obsoletes = hy_query_clone(query);
            hy_query_filter_package_in(query_obsoletes, HY_PKG_OBSOLETES, HY_EQ, pset);
            delete pset;
            hy_query_union(query, query_obsoletes);
            hy_query_free(query_obsoletes);
        }
        if (reponame != NULL) {
            HyQuery installed_query = hy_query_clone(query);
            hy_query_filter(installed_query, HY_PKG_REPONAME, HY_EQ, HY_SYSTEM_REPO_NAME);
            hy_query_filter(query, HY_PKG_REPONAME, HY_EQ, reponame);
            hy_query_union(query, installed_query);
            hy_query_free(installed_query);
        }
    }
    delete nevra;
    HySelector selector = hy_query_to_selector(query);
    hy_query_free(query);
    return selector;
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Ethash.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "Ethash.h"

#include <boost/detail/endian.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <chrono>
#include <array>
#include <thread>
#include <random>
#include <thread>
#include <libdevcore/Guards.h>
#include <libdevcore/Log.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <libdevcrypto/CryptoPP.h>
#include <libdevcore/FileSystem.h>
#include <libethash/ethash.h>
#include <libethash/internal.h>
#if ETH_ETHASHCL || !ETH_TRUE
#include <libethash-cl/ethash_cl_miner.h>
#endif
#if ETH_CPUID || !ETH_TRUE
#define HAVE_STDINT_H
#include <libcpuid/libcpuid.h>
#endif
#include "BlockInfo.h"
#include "EthashAux.h"
using namespace std;
using namespace std::chrono;

namespace dev
{
namespace eth
{

const Ethash::WorkPackage Ethash::NullWorkPackage = Ethash::WorkPackage();

std::string Ethash::name()
{
	return "Ethash";
}

unsigned Ethash::revision()
{
	return ETHASH_REVISION;
}

Ethash::WorkPackage Ethash::package(BlockInfo const& _bi)
{
	WorkPackage ret;
	ret.boundary = _bi.boundary();
	ret.headerHash = _bi.headerHash(WithoutNonce);
	ret.seedHash = _bi.seedHash();
	return ret;
}

void Ethash::ensurePrecomputed(unsigned _number)
{
	if (_number % ETHASH_EPOCH_LENGTH > ETHASH_EPOCH_LENGTH * 9 / 10)
		// 90% of the way to the new epoch
		EthashAux::computeFull(EthashAux::seedHash(_number + ETHASH_EPOCH_LENGTH), true);
}

void Ethash::prep(BlockInfo const& _header, std::function<int(unsigned)> const& _f)
{
	EthashAux::full(_header.seedHash(), true, _f);
}

bool Ethash::preVerify(BlockInfo const& _header)
{
	if (_header.number >= ETHASH_EPOCH_LENGTH * 2048)
		return false;

	h256 boundary = u256((bigint(1) << 256) / _header.difficulty);

	bool ret = !!ethash_quick_check_difficulty(
			(ethash_h256_t const*)_header.headerHash(WithoutNonce).data(),
			(uint64_t)(u64)_header.nonce,
			(ethash_h256_t const*)_header.mixHash.data(),
			(ethash_h256_t const*)boundary.data());

	return ret;
}

bool Ethash::verify(BlockInfo const& _header)
{
	bool pre = preVerify(_header);
#if !ETH_DEBUG
	if (!pre)
	{
		cdebug << "Fail on preVerify";
		return false;
	}
#endif

	auto result = EthashAux::eval(_header);
	bool slow = result.value <= _header.boundary() && result.mixHash == _header.mixHash;

//	cdebug << (slow ? "VERIFY" : "VERYBAD");
//	cdebug << result.value.hex() << _header.boundary().hex();
//	cdebug << result.mixHash.hex() << _header.mixHash.hex();

#if ETH_DEBUG || !ETH_TRUE
	if (!pre && slow)
	{
		cwarn << "WARNING: evaluated result gives true whereas ethash_quick_check_difficulty gives false.";
		cwarn << "headerHash:" << _header.headerHash(WithoutNonce);
		cwarn << "nonce:" << _header.nonce;
		cwarn << "mixHash:" << _header.mixHash;
		cwarn << "difficulty:" << _header.difficulty;
		cwarn << "boundary:" << _header.boundary();
		cwarn << "result.value:" << result.value;
		cwarn << "result.mixHash:" << result.mixHash;
	}
#endif

	return slow;
}

unsigned Ethash::CPUMiner::s_numInstances = 0;

void Ethash::CPUMiner::workLoop()
{
	auto tid = std::this_thread::get_id();
	static std::mt19937_64 s_eng((time(0) + std::hash<decltype(tid)>()(tid)));

	uint64_t tryNonce = (uint64_t)(u64)Nonce::random(s_eng);
	ethash_return_value ethashReturn;

	WorkPackage w = work();

	EthashAux::FullType dag;
	while (!shouldStop() && !dag)
	{
		while (!shouldStop() && EthashAux::computeFull(w.seedHash, true) != 100)
			this_thread::sleep_for(chrono::milliseconds(500));
		dag = EthashAux::full(w.seedHash, false);
	}

	h256 boundary = w.boundary;
	unsigned hashCount = 1;
	for (; !shouldStop(); tryNonce++, hashCount++)
	{
		ethashReturn = ethash_full_compute(dag->full, *(ethash_h256_t*)w.headerHash.data(), tryNonce);
		h256 value = h256((uint8_t*)&ethashReturn.result, h256::ConstructFromPointer);
		if (value <= boundary && submitProof(Solution{(Nonce)(u64)tryNonce, h256((uint8_t*)&ethashReturn.mix_hash, h256::ConstructFromPointer)}))
			break;
		if (!(hashCount % 100))
			accumulateHashes(100);
	}
}

static string jsonEncode(map<string, string> const& _m)
{
	string ret = "{";

	for (auto const& i: _m)
	{
		string k = boost::replace_all_copy(boost::replace_all_copy(i.first, "\\", "\\\\"), "'", "\\'");
		string v = boost::replace_all_copy(boost::replace_all_copy(i.second, "\\", "\\\\"), "'", "\\'");
		if (ret.size() > 1)
			ret += ", ";
		ret += "\"" + k + "\":\"" + v + "\"";
	}

	return ret + "}";
}

std::string Ethash::CPUMiner::platformInfo()
{
	string baseline = toString(std::thread::hardware_concurrency()) + "-thread CPU";
#if ETH_CPUID || !ETH_TRUE
	if (!cpuid_present())
		return baseline;
	struct cpu_raw_data_t raw;
	struct cpu_id_t data;
	if (cpuid_get_raw_data(&raw) < 0)
		return baseline;
	if (cpu_identify(&raw, &data) < 0)
		return baseline;
	map<string, string> m;
	m["vendor"] = data.vendor_str;
	m["codename"] = data.cpu_codename;
	m["brand"] = data.brand_str;
	m["L1 cache"] = toString(data.l1_data_cache);
	m["L2 cache"] = toString(data.l2_cache);
	m["L3 cache"] = toString(data.l3_cache);
	m["cores"] = toString(data.num_cores);
	m["threads"] = toString(data.num_logical_cpus);
	m["clocknominal"] = toString(cpu_clock_by_os());
	m["clocktested"] = toString(cpu_clock_measure(200, 0));
	/*
	printf("  MMX         : %s\n", data.flags[CPU_FEATURE_MMX] ? "present" : "absent");
	printf("  MMX-extended: %s\n", data.flags[CPU_FEATURE_MMXEXT] ? "present" : "absent");
	printf("  SSE         : %s\n", data.flags[CPU_FEATURE_SSE] ? "present" : "absent");
	printf("  SSE2        : %s\n", data.flags[CPU_FEATURE_SSE2] ? "present" : "absent");
	printf("  3DNow!      : %s\n", data.flags[CPU_FEATURE_3DNOW] ? "present" : "absent");
	*/
	return jsonEncode(m);
#else
	return baseline;
#endif
}

#if ETH_ETHASHCL || !ETH_TRUE

class EthashCLHook: public ethash_cl_miner::search_hook
{
public:
	EthashCLHook(Ethash::GPUMiner* _owner): m_owner(_owner) {}

	void abort()
	{
		Guard l(x_all);
		if (m_aborted)
			return;
//		cdebug << "Attempting to abort";
		m_abort = true;
		for (unsigned timeout = 0; timeout < 100 && !m_aborted; ++timeout)
			std::this_thread::sleep_for(chrono::milliseconds(30));
//		if (!m_aborted)
//			cwarn << "Couldn't abort. Abandoning OpenCL process.";
	}

	void reset()
	{
		m_aborted = m_abort = false;
	}

protected:
	virtual bool found(uint64_t const* _nonces, uint32_t _count) override
	{
//		dev::operator <<(std::cerr << "Found nonces: ", vector<uint64_t>(_nonces, _nonces + _count)) << std::endl;
		for (uint32_t i = 0; i < _count; ++i)
		{
			if (m_owner->report(_nonces[i]))
			{
				m_aborted = true;
				return true;
			}
		}
		return m_owner->shouldStop();
	}

	virtual bool searched(uint64_t _startNonce, uint32_t _count) override
	{
		Guard l(x_all);
//		std::cerr << "Searched " << _count << " from " << _startNonce << std::endl;
		m_owner->accumulateHashes(_count);
		m_last = _startNonce + _count;
		if (m_abort || m_owner->shouldStop())
		{
			m_aborted = true;
			return true;
		}
		return false;
	}

private:
	Mutex x_all;
	uint64_t m_last;
	bool m_abort = false;
	bool m_aborted = true;
	Ethash::GPUMiner* m_owner = nullptr;
};

unsigned Ethash::GPUMiner::s_platformId = 0;
unsigned Ethash::GPUMiner::s_deviceId = 0;
unsigned Ethash::GPUMiner::s_numInstances = 0;

Ethash::GPUMiner::GPUMiner(ConstructionInfo const& _ci):
	Miner(_ci),
	Worker("gpuminer" + toString(index())),
	m_hook(new EthashCLHook(this))
{
}

Ethash::GPUMiner::~GPUMiner()
{
	pause();
	delete m_miner;
	delete m_hook;
}

bool Ethash::GPUMiner::report(uint64_t _nonce)
{
	Nonce n = (Nonce)(u64)_nonce;
	Result r = EthashAux::eval(work().seedHash, work().headerHash, n);
	if (r.value < work().boundary)
		return submitProof(Solution{n, r.mixHash});
	return false;
}

void Ethash::GPUMiner::kickOff()
{
	m_hook->reset();
	startWorking();
}

void Ethash::GPUMiner::workLoop()
{
	// take local copy of work since it may end up being overwritten by kickOff/pause.
	try {
		WorkPackage w = work();
		cnote << "workLoop" << !!m_miner << m_minerSeed << w.seedHash;
		if (!m_miner || m_minerSeed != w.seedHash)
		{
			cnote << "Initialising miner...";
			m_minerSeed = w.seedHash;

			delete m_miner;
			m_miner = new ethash_cl_miner;

			unsigned device = instances() > 1 ? index() : s_deviceId;

			EthashAux::FullType dag;
			while (true)
			{
				if ((dag = EthashAux::full(w.seedHash, true)))
					break;
				if (shouldStop())
				{
					delete m_miner;
					m_miner = nullptr;
					return;
				}
				cnote << "Awaiting DAG";
				this_thread::sleep_for(chrono::milliseconds(500));
			}
			bytesConstRef dagData = dag->data();
			m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device);
		}

		uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192);
		m_miner->search(w.headerHash.data(), upper64OfBoundary, *m_hook);
	}
	catch (cl::Error const& _e)
	{
		delete m_miner;
		m_miner = nullptr;
		cwarn << "Error GPU mining: " << _e.what() << "(" << _e.err() << ")";
	}
}

void Ethash::GPUMiner::pause()
{
	m_hook->abort();
	stopWorking();
}

std::string Ethash::GPUMiner::platformInfo()
{
	return ethash_cl_miner::platform_info(s_platformId, s_deviceId);
}

unsigned Ethash::GPUMiner::getNumDevices()
{
	return ethash_cl_miner::getNumDevices(s_platformId);
}

void Ethash::GPUMiner::listDevices()
{
	return ethash_cl_miner::listDevices();
}

bool Ethash::GPUMiner::configureGPU(
	unsigned _platformId,
	unsigned _deviceId,
	bool _allowCPU,
	unsigned _extraGPUMemory,
	bool _forceSingleChunk,
	boost::optional<uint64_t> _currentBlock
)
{
	s_platformId = _platformId;
	s_deviceId = _deviceId;
	return ethash_cl_miner::configureGPU(_allowCPU, _extraGPUMemory, _forceSingleChunk, _currentBlock);
}

#endif

}
}
<commit_msg>Switch to warning.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Ethash.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "Ethash.h"

#include <boost/detail/endian.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <chrono>
#include <array>
#include <thread>
#include <random>
#include <thread>
#include <libdevcore/Guards.h>
#include <libdevcore/Log.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <libdevcrypto/CryptoPP.h>
#include <libdevcore/FileSystem.h>
#include <libethash/ethash.h>
#include <libethash/internal.h>
#if ETH_ETHASHCL || !ETH_TRUE
#include <libethash-cl/ethash_cl_miner.h>
#endif
#if ETH_CPUID || !ETH_TRUE
#define HAVE_STDINT_H
#include <libcpuid/libcpuid.h>
#endif
#include "BlockInfo.h"
#include "EthashAux.h"
using namespace std;
using namespace std::chrono;

namespace dev
{
namespace eth
{

const Ethash::WorkPackage Ethash::NullWorkPackage = Ethash::WorkPackage();

std::string Ethash::name()
{
	return "Ethash";
}

unsigned Ethash::revision()
{
	return ETHASH_REVISION;
}

Ethash::WorkPackage Ethash::package(BlockInfo const& _bi)
{
	WorkPackage ret;
	ret.boundary = _bi.boundary();
	ret.headerHash = _bi.headerHash(WithoutNonce);
	ret.seedHash = _bi.seedHash();
	return ret;
}

void Ethash::ensurePrecomputed(unsigned _number)
{
	if (_number % ETHASH_EPOCH_LENGTH > ETHASH_EPOCH_LENGTH * 9 / 10)
		// 90% of the way to the new epoch
		EthashAux::computeFull(EthashAux::seedHash(_number + ETHASH_EPOCH_LENGTH), true);
}

void Ethash::prep(BlockInfo const& _header, std::function<int(unsigned)> const& _f)
{
	EthashAux::full(_header.seedHash(), true, _f);
}

bool Ethash::preVerify(BlockInfo const& _header)
{
	if (_header.number >= ETHASH_EPOCH_LENGTH * 2048)
		return false;

	h256 boundary = u256((bigint(1) << 256) / _header.difficulty);

	bool ret = !!ethash_quick_check_difficulty(
			(ethash_h256_t const*)_header.headerHash(WithoutNonce).data(),
			(uint64_t)(u64)_header.nonce,
			(ethash_h256_t const*)_header.mixHash.data(),
			(ethash_h256_t const*)boundary.data());

	return ret;
}

bool Ethash::verify(BlockInfo const& _header)
{
	bool pre = preVerify(_header);
#if !ETH_DEBUG
	if (!pre)
	{
		cwarn << "Fail on preVerify";
		return false;
	}
#endif

	auto result = EthashAux::eval(_header);
	bool slow = result.value <= _header.boundary() && result.mixHash == _header.mixHash;

//	cdebug << (slow ? "VERIFY" : "VERYBAD");
//	cdebug << result.value.hex() << _header.boundary().hex();
//	cdebug << result.mixHash.hex() << _header.mixHash.hex();

#if ETH_DEBUG || !ETH_TRUE
	if (!pre && slow)
	{
		cwarn << "WARNING: evaluated result gives true whereas ethash_quick_check_difficulty gives false.";
		cwarn << "headerHash:" << _header.headerHash(WithoutNonce);
		cwarn << "nonce:" << _header.nonce;
		cwarn << "mixHash:" << _header.mixHash;
		cwarn << "difficulty:" << _header.difficulty;
		cwarn << "boundary:" << _header.boundary();
		cwarn << "result.value:" << result.value;
		cwarn << "result.mixHash:" << result.mixHash;
	}
#endif

	return slow;
}

unsigned Ethash::CPUMiner::s_numInstances = 0;

void Ethash::CPUMiner::workLoop()
{
	auto tid = std::this_thread::get_id();
	static std::mt19937_64 s_eng((time(0) + std::hash<decltype(tid)>()(tid)));

	uint64_t tryNonce = (uint64_t)(u64)Nonce::random(s_eng);
	ethash_return_value ethashReturn;

	WorkPackage w = work();

	EthashAux::FullType dag;
	while (!shouldStop() && !dag)
	{
		while (!shouldStop() && EthashAux::computeFull(w.seedHash, true) != 100)
			this_thread::sleep_for(chrono::milliseconds(500));
		dag = EthashAux::full(w.seedHash, false);
	}

	h256 boundary = w.boundary;
	unsigned hashCount = 1;
	for (; !shouldStop(); tryNonce++, hashCount++)
	{
		ethashReturn = ethash_full_compute(dag->full, *(ethash_h256_t*)w.headerHash.data(), tryNonce);
		h256 value = h256((uint8_t*)&ethashReturn.result, h256::ConstructFromPointer);
		if (value <= boundary && submitProof(Solution{(Nonce)(u64)tryNonce, h256((uint8_t*)&ethashReturn.mix_hash, h256::ConstructFromPointer)}))
			break;
		if (!(hashCount % 100))
			accumulateHashes(100);
	}
}

static string jsonEncode(map<string, string> const& _m)
{
	string ret = "{";

	for (auto const& i: _m)
	{
		string k = boost::replace_all_copy(boost::replace_all_copy(i.first, "\\", "\\\\"), "'", "\\'");
		string v = boost::replace_all_copy(boost::replace_all_copy(i.second, "\\", "\\\\"), "'", "\\'");
		if (ret.size() > 1)
			ret += ", ";
		ret += "\"" + k + "\":\"" + v + "\"";
	}

	return ret + "}";
}

std::string Ethash::CPUMiner::platformInfo()
{
	string baseline = toString(std::thread::hardware_concurrency()) + "-thread CPU";
#if ETH_CPUID || !ETH_TRUE
	if (!cpuid_present())
		return baseline;
	struct cpu_raw_data_t raw;
	struct cpu_id_t data;
	if (cpuid_get_raw_data(&raw) < 0)
		return baseline;
	if (cpu_identify(&raw, &data) < 0)
		return baseline;
	map<string, string> m;
	m["vendor"] = data.vendor_str;
	m["codename"] = data.cpu_codename;
	m["brand"] = data.brand_str;
	m["L1 cache"] = toString(data.l1_data_cache);
	m["L2 cache"] = toString(data.l2_cache);
	m["L3 cache"] = toString(data.l3_cache);
	m["cores"] = toString(data.num_cores);
	m["threads"] = toString(data.num_logical_cpus);
	m["clocknominal"] = toString(cpu_clock_by_os());
	m["clocktested"] = toString(cpu_clock_measure(200, 0));
	/*
	printf("  MMX         : %s\n", data.flags[CPU_FEATURE_MMX] ? "present" : "absent");
	printf("  MMX-extended: %s\n", data.flags[CPU_FEATURE_MMXEXT] ? "present" : "absent");
	printf("  SSE         : %s\n", data.flags[CPU_FEATURE_SSE] ? "present" : "absent");
	printf("  SSE2        : %s\n", data.flags[CPU_FEATURE_SSE2] ? "present" : "absent");
	printf("  3DNow!      : %s\n", data.flags[CPU_FEATURE_3DNOW] ? "present" : "absent");
	*/
	return jsonEncode(m);
#else
	return baseline;
#endif
}

#if ETH_ETHASHCL || !ETH_TRUE

class EthashCLHook: public ethash_cl_miner::search_hook
{
public:
	EthashCLHook(Ethash::GPUMiner* _owner): m_owner(_owner) {}

	void abort()
	{
		Guard l(x_all);
		if (m_aborted)
			return;
//		cdebug << "Attempting to abort";
		m_abort = true;
		for (unsigned timeout = 0; timeout < 100 && !m_aborted; ++timeout)
			std::this_thread::sleep_for(chrono::milliseconds(30));
//		if (!m_aborted)
//			cwarn << "Couldn't abort. Abandoning OpenCL process.";
	}

	void reset()
	{
		m_aborted = m_abort = false;
	}

protected:
	virtual bool found(uint64_t const* _nonces, uint32_t _count) override
	{
//		dev::operator <<(std::cerr << "Found nonces: ", vector<uint64_t>(_nonces, _nonces + _count)) << std::endl;
		for (uint32_t i = 0; i < _count; ++i)
		{
			if (m_owner->report(_nonces[i]))
			{
				m_aborted = true;
				return true;
			}
		}
		return m_owner->shouldStop();
	}

	virtual bool searched(uint64_t _startNonce, uint32_t _count) override
	{
		Guard l(x_all);
//		std::cerr << "Searched " << _count << " from " << _startNonce << std::endl;
		m_owner->accumulateHashes(_count);
		m_last = _startNonce + _count;
		if (m_abort || m_owner->shouldStop())
		{
			m_aborted = true;
			return true;
		}
		return false;
	}

private:
	Mutex x_all;
	uint64_t m_last;
	bool m_abort = false;
	bool m_aborted = true;
	Ethash::GPUMiner* m_owner = nullptr;
};

unsigned Ethash::GPUMiner::s_platformId = 0;
unsigned Ethash::GPUMiner::s_deviceId = 0;
unsigned Ethash::GPUMiner::s_numInstances = 0;

Ethash::GPUMiner::GPUMiner(ConstructionInfo const& _ci):
	Miner(_ci),
	Worker("gpuminer" + toString(index())),
	m_hook(new EthashCLHook(this))
{
}

Ethash::GPUMiner::~GPUMiner()
{
	pause();
	delete m_miner;
	delete m_hook;
}

bool Ethash::GPUMiner::report(uint64_t _nonce)
{
	Nonce n = (Nonce)(u64)_nonce;
	Result r = EthashAux::eval(work().seedHash, work().headerHash, n);
	if (r.value < work().boundary)
		return submitProof(Solution{n, r.mixHash});
	return false;
}

void Ethash::GPUMiner::kickOff()
{
	m_hook->reset();
	startWorking();
}

void Ethash::GPUMiner::workLoop()
{
	// take local copy of work since it may end up being overwritten by kickOff/pause.
	try {
		WorkPackage w = work();
		cnote << "workLoop" << !!m_miner << m_minerSeed << w.seedHash;
		if (!m_miner || m_minerSeed != w.seedHash)
		{
			cnote << "Initialising miner...";
			m_minerSeed = w.seedHash;

			delete m_miner;
			m_miner = new ethash_cl_miner;

			unsigned device = instances() > 1 ? index() : s_deviceId;

			EthashAux::FullType dag;
			while (true)
			{
				if ((dag = EthashAux::full(w.seedHash, true)))
					break;
				if (shouldStop())
				{
					delete m_miner;
					m_miner = nullptr;
					return;
				}
				cnote << "Awaiting DAG";
				this_thread::sleep_for(chrono::milliseconds(500));
			}
			bytesConstRef dagData = dag->data();
			m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device);
		}

		uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192);
		m_miner->search(w.headerHash.data(), upper64OfBoundary, *m_hook);
	}
	catch (cl::Error const& _e)
	{
		delete m_miner;
		m_miner = nullptr;
		cwarn << "Error GPU mining: " << _e.what() << "(" << _e.err() << ")";
	}
}

void Ethash::GPUMiner::pause()
{
	m_hook->abort();
	stopWorking();
}

std::string Ethash::GPUMiner::platformInfo()
{
	return ethash_cl_miner::platform_info(s_platformId, s_deviceId);
}

unsigned Ethash::GPUMiner::getNumDevices()
{
	return ethash_cl_miner::getNumDevices(s_platformId);
}

void Ethash::GPUMiner::listDevices()
{
	return ethash_cl_miner::listDevices();
}

bool Ethash::GPUMiner::configureGPU(
	unsigned _platformId,
	unsigned _deviceId,
	bool _allowCPU,
	unsigned _extraGPUMemory,
	bool _forceSingleChunk,
	boost::optional<uint64_t> _currentBlock
)
{
	s_platformId = _platformId;
	s_deviceId = _deviceId;
	return ethash_cl_miner::configureGPU(_allowCPU, _extraGPUMemory, _forceSingleChunk, _currentBlock);
}

#endif

}
}
<|endoftext|>


<commit_before>
#pragma GCC diagnostic ignored "-Wconversion"
#include <libdevcrypto/SHA3.h>
#include <libethcore/Params.h>
#include <libevm/ExtVMFace.h>

#include "Utils.h"

extern "C"
{
	#ifdef _MSC_VER
		#define EXPORT __declspec(dllexport)
	#else
		#define EXPORT
	#endif

	using namespace dev;
	using namespace dev::eth;
	using jit::i256;

	EXPORT void env_sload(ExtVMFace* _env, i256* _index, i256* o_value)
	{
		auto index = llvm2eth(*_index);
		auto value = _env->store(index); // Interface uses native endianness
		*o_value = eth2llvm(value);
	}

	EXPORT void env_sstore(ExtVMFace* _env, i256* _index, i256* _value)
	{
		auto index = llvm2eth(*_index);
		auto value = llvm2eth(*_value);

		if (value == 0 && _env->store(index) != 0)	// If delete
			_env->sub.refunds += c_sstoreRefundGas;	// Increase refund counter

		_env->setStore(index, value);	// Interface uses native endianness
	}

	EXPORT void env_balance(ExtVMFace* _env, h256* _address, i256* o_value)
	{
		auto u = _env->balance(right160(*_address));
		*o_value = eth2llvm(u);
	}

	EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash)
	{
		*o_hash = _env->blockhash(llvm2eth(*_number));
	}

	EXPORT void env_create(ExtVMFace* _env, int64_t* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)
	{
		auto endowment = llvm2eth(*_endowment);
		if (_env->balance(_env->myAddress) >= endowment && _env->depth < 1024)
		{
			u256 gas = *io_gas;
			h256 address(_env->create(endowment, gas, {_initBeg, _initSize}, {}), h256::AlignRight);
			*io_gas = static_cast<int64_t>(gas);
			*o_address = address;
		}
		else
			*o_address = {};
	}

	EXPORT bool env_call(ExtVMFace* _env, int64_t* io_gas, int64_t _callGas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress)
	{
		auto value = llvm2eth(*_value);
		auto receiveAddress = right160(*_receiveAddress);
		auto codeAddress = right160(*_codeAddress);
		const auto isCall = receiveAddress == codeAddress; // OPT: The same address pointer can be used if not CODECALL

		*io_gas -= _callGas;
		if (*io_gas < 0)
			return false;

		if (isCall && !_env->exists(receiveAddress))
			*io_gas -= static_cast<int64_t>(c_callNewAccountGas); // no underflow, *io_gas non-negative before

		if (value > 0) // value transfer
		{
			/*static*/ assert(c_callValueTransferGas > c_callStipend && "Overflow possible");
			*io_gas -= static_cast<int64_t>(c_callValueTransferGas); // no underflow
			_callGas += static_cast<int64_t>(c_callStipend); // overflow possibility, but in the same time *io_gas < 0
		}

		if (*io_gas < 0)
			return false;

		auto ret = false;
		auto callGas = u256{_callGas};
		if (_env->balance(_env->myAddress) >= value && _env->depth < 1024)
			ret = _env->call(receiveAddress, value, {_inBeg, _inSize}, callGas, {_outBeg, _outSize}, {}, {}, codeAddress);

		*io_gas += static_cast<int64_t>(callGas); // it is never more than initial _callGas
		return ret;
	}

	EXPORT void env_sha3(byte* _begin, uint64_t _size, h256* o_hash)
	{
		auto hash = sha3({_begin, _size});
		*o_hash = hash;
	}

	EXPORT byte const* env_extcode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size)
	{
		auto addr = right160(*_addr256);
		auto& code = _env->codeAt(addr);
		*o_size = code.size();
		return code.data();
	}

	EXPORT void env_log(ExtVMFace* _env, byte* _beg, uint64_t _size, h256* _topic1, h256* _topic2, h256* _topic3, h256* _topic4)
	{
		dev::h256s topics;

		if (_topic1)
			topics.push_back(*_topic1);

		if (_topic2)
			topics.push_back(*_topic2);

		if (_topic3)
			topics.push_back(*_topic3);

		if (_topic4)
			topics.push_back(*_topic4);

		_env->log(std::move(topics), {_beg, _size});
	}
}

<commit_msg>Move assembly related files to libevmasm and Params.h/.cpp to libevmcore.<commit_after>
#pragma GCC diagnostic ignored "-Wconversion"
#include <libdevcrypto/SHA3.h>
#include <libevmcore/Params.h>
#include <libevm/ExtVMFace.h>

#include "Utils.h"

extern "C"
{
	#ifdef _MSC_VER
		#define EXPORT __declspec(dllexport)
	#else
		#define EXPORT
	#endif

	using namespace dev;
	using namespace dev::eth;
	using jit::i256;

	EXPORT void env_sload(ExtVMFace* _env, i256* _index, i256* o_value)
	{
		auto index = llvm2eth(*_index);
		auto value = _env->store(index); // Interface uses native endianness
		*o_value = eth2llvm(value);
	}

	EXPORT void env_sstore(ExtVMFace* _env, i256* _index, i256* _value)
	{
		auto index = llvm2eth(*_index);
		auto value = llvm2eth(*_value);

		if (value == 0 && _env->store(index) != 0)	// If delete
			_env->sub.refunds += c_sstoreRefundGas;	// Increase refund counter

		_env->setStore(index, value);	// Interface uses native endianness
	}

	EXPORT void env_balance(ExtVMFace* _env, h256* _address, i256* o_value)
	{
		auto u = _env->balance(right160(*_address));
		*o_value = eth2llvm(u);
	}

	EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash)
	{
		*o_hash = _env->blockhash(llvm2eth(*_number));
	}

	EXPORT void env_create(ExtVMFace* _env, int64_t* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)
	{
		auto endowment = llvm2eth(*_endowment);
		if (_env->balance(_env->myAddress) >= endowment && _env->depth < 1024)
		{
			u256 gas = *io_gas;
			h256 address(_env->create(endowment, gas, {_initBeg, _initSize}, {}), h256::AlignRight);
			*io_gas = static_cast<int64_t>(gas);
			*o_address = address;
		}
		else
			*o_address = {};
	}

	EXPORT bool env_call(ExtVMFace* _env, int64_t* io_gas, int64_t _callGas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress)
	{
		auto value = llvm2eth(*_value);
		auto receiveAddress = right160(*_receiveAddress);
		auto codeAddress = right160(*_codeAddress);
		const auto isCall = receiveAddress == codeAddress; // OPT: The same address pointer can be used if not CODECALL

		*io_gas -= _callGas;
		if (*io_gas < 0)
			return false;

		if (isCall && !_env->exists(receiveAddress))
			*io_gas -= static_cast<int64_t>(c_callNewAccountGas); // no underflow, *io_gas non-negative before

		if (value > 0) // value transfer
		{
			/*static*/ assert(c_callValueTransferGas > c_callStipend && "Overflow possible");
			*io_gas -= static_cast<int64_t>(c_callValueTransferGas); // no underflow
			_callGas += static_cast<int64_t>(c_callStipend); // overflow possibility, but in the same time *io_gas < 0
		}

		if (*io_gas < 0)
			return false;

		auto ret = false;
		auto callGas = u256{_callGas};
		if (_env->balance(_env->myAddress) >= value && _env->depth < 1024)
			ret = _env->call(receiveAddress, value, {_inBeg, _inSize}, callGas, {_outBeg, _outSize}, {}, {}, codeAddress);

		*io_gas += static_cast<int64_t>(callGas); // it is never more than initial _callGas
		return ret;
	}

	EXPORT void env_sha3(byte* _begin, uint64_t _size, h256* o_hash)
	{
		auto hash = sha3({_begin, _size});
		*o_hash = hash;
	}

	EXPORT byte const* env_extcode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size)
	{
		auto addr = right160(*_addr256);
		auto& code = _env->codeAt(addr);
		*o_size = code.size();
		return code.data();
	}

	EXPORT void env_log(ExtVMFace* _env, byte* _beg, uint64_t _size, h256* _topic1, h256* _topic2, h256* _topic3, h256* _topic4)
	{
		dev::h256s topics;

		if (_topic1)
			topics.push_back(*_topic1);

		if (_topic2)
			topics.push_back(*_topic2);

		if (_topic3)
			topics.push_back(*_topic3);

		if (_topic4)
			topics.push_back(*_topic4);

		_env->log(std::move(topics), {_beg, _size});
	}
}

<|endoftext|>


<commit_before>
#pragma GCC diagnostic ignored "-Wconversion"
#include <libdevcore/SHA3.h>
#include <libevmcore/Params.h>
#include <libevm/ExtVMFace.h>
#include <evmjit/DataTypes.h>

#include "Utils.h"

extern "C"
{
	#ifdef _MSC_VER
		#define EXPORT __declspec(dllexport)
	#else
		#define EXPORT
	#endif

	using namespace dev;
	using namespace dev::eth;
	using evmjit::i256;

	EXPORT void env_sload(ExtVMFace* _env, i256* _index, i256* o_value)
	{
		auto index = llvm2eth(*_index);
		auto value = _env->store(index); // Interface uses native endianness
		*o_value = eth2llvm(value);
	}

	EXPORT void env_sstore(ExtVMFace* _env, i256* _index, i256* _value)
	{
		auto index = llvm2eth(*_index);
		auto value = llvm2eth(*_value);

		if (value == 0 && _env->store(index) != 0)	// If delete
			_env->sub.refunds += c_sstoreRefundGas;	// Increase refund counter

		_env->setStore(index, value);	// Interface uses native endianness
	}

	EXPORT void env_balance(ExtVMFace* _env, h256* _address, i256* o_value)
	{
		auto u = _env->balance(right160(*_address));
		*o_value = eth2llvm(u);
	}

	EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash)
	{
		*o_hash = _env->blockhash(llvm2eth(*_number));
	}

	EXPORT void env_create(ExtVMFace* _env, int64_t* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)
	{
		auto endowment = llvm2eth(*_endowment);
		if (_env->balance(_env->myAddress) >= endowment && _env->depth < 1024)
		{
			u256 gas = *io_gas;
			h256 address(_env->create(endowment, gas, {_initBeg, _initSize}, {}), h256::AlignRight);
			*io_gas = static_cast<int64_t>(gas);
			*o_address = address;
		}
		else
			*o_address = {};
	}

	EXPORT bool env_call(ExtVMFace* _env, int64_t* io_gas, int64_t _callGas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress)
	{
		CallParameters params;
		params.value = llvm2eth(*_value);
		params.senderAddress = _env->myAddress;
		params.receiveAddress = right160(*_receiveAddress);
		params.codeAddress = right160(*_codeAddress);
		params.data = {_inBeg, _inSize};
		params.out = {_outBeg, _outSize};
		params.onOp = {};
		const auto isCall = params.receiveAddress == params.codeAddress; // OPT: The same address pointer can be used if not CODECALL

		*io_gas -= _callGas;
		if (*io_gas < 0)
			return false;

		if (isCall && !_env->exists(params.receiveAddress))
			*io_gas -= static_cast<int64_t>(c_callNewAccountGas); // no underflow, *io_gas non-negative before

		if (params.value > 0) // value transfer
		{
			/*static*/ assert(c_callValueTransferGas > c_callStipend && "Overflow possible");
			*io_gas -= static_cast<int64_t>(c_callValueTransferGas); // no underflow
			_callGas += static_cast<int64_t>(c_callStipend); // overflow possibility, but in the same time *io_gas < 0
		}

		if (*io_gas < 0)
			return false;

		auto ret = false;
		params.gas = u256{_callGas};
		if (_env->balance(_env->myAddress) >= params.value && _env->depth < 1024)
			ret = _env->call(params);

		*io_gas += static_cast<int64_t>(params.gas); // it is never more than initial _callGas
		return ret;
	}

	EXPORT void env_sha3(byte* _begin, uint64_t _size, h256* o_hash)
	{
		auto hash = sha3({_begin, _size});
		*o_hash = hash;
	}

	EXPORT byte const* env_extcode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size)
	{
		auto addr = right160(*_addr256);
		auto& code = _env->codeAt(addr);
		*o_size = code.size();
		return code.data();
	}

	EXPORT void env_log(ExtVMFace* _env, byte* _beg, uint64_t _size, h256* _topic1, h256* _topic2, h256* _topic3, h256* _topic4)
	{
		dev::h256s topics;

		if (_topic1)
			topics.push_back(*_topic1);

		if (_topic2)
			topics.push_back(*_topic2);

		if (_topic3)
			topics.push_back(*_topic3);

		if (_topic4)
			topics.push_back(*_topic4);

		_env->log(std::move(topics), {_beg, _size});
	}
}

<commit_msg>evmJit warnings fix<commit_after>
#pragma GCC diagnostic ignored "-Wconversion"
#include <libdevcore/SHA3.h>
#include <libevmcore/Params.h>
#include <libevm/ExtVMFace.h>
#include <evmjit/DataTypes.h>

#include "Utils.h"

extern "C"
{
	#ifdef _MSC_VER
		#define EXPORT __declspec(dllexport)
	#else
		#define EXPORT
	#endif

	using namespace dev;
	using namespace dev::eth;
	using evmjit::i256;

	EXPORT void env_sload(ExtVMFace* _env, i256* _index, i256* o_value)
	{
		auto index = llvm2eth(*_index);
		auto value = _env->store(index); // Interface uses native endianness
		*o_value = eth2llvm(value);
	}

	EXPORT void env_sstore(ExtVMFace* _env, i256* _index, i256* _value)
	{
		auto index = llvm2eth(*_index);
		auto value = llvm2eth(*_value);

		if (value == 0 && _env->store(index) != 0)	// If delete
			_env->sub.refunds += c_sstoreRefundGas;	// Increase refund counter

		_env->setStore(index, value);	// Interface uses native endianness
	}

	EXPORT void env_balance(ExtVMFace* _env, h256* _address, i256* o_value)
	{
		auto u = _env->balance(right160(*_address));
		*o_value = eth2llvm(u);
	}

	EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash)
	{
		*o_hash = _env->blockhash(llvm2eth(*_number));
	}

	EXPORT void env_create(ExtVMFace* _env, int64_t* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)
	{
		auto endowment = llvm2eth(*_endowment);
		if (_env->balance(_env->myAddress) >= endowment && _env->depth < 1024)
		{
			u256 gas = *io_gas;
			h256 address(_env->create(endowment, gas, {_initBeg, (size_t)_initSize}, {}), h256::AlignRight);
			*io_gas = static_cast<int64_t>(gas);
			*o_address = address;
		}
		else
			*o_address = {};
	}

	EXPORT bool env_call(ExtVMFace* _env, int64_t* io_gas, int64_t _callGas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress)
	{
		CallParameters params;
		params.value = llvm2eth(*_value);
		params.senderAddress = _env->myAddress;
		params.receiveAddress = right160(*_receiveAddress);
		params.codeAddress = right160(*_codeAddress);
		params.data = {_inBeg, (size_t)_inSize};
		params.out = {_outBeg, (size_t)_outSize};
		params.onOp = {};
		const auto isCall = params.receiveAddress == params.codeAddress; // OPT: The same address pointer can be used if not CODECALL

		*io_gas -= _callGas;
		if (*io_gas < 0)
			return false;

		if (isCall && !_env->exists(params.receiveAddress))
			*io_gas -= static_cast<int64_t>(c_callNewAccountGas); // no underflow, *io_gas non-negative before

		if (params.value > 0) // value transfer
		{
			/*static*/ assert(c_callValueTransferGas > c_callStipend && "Overflow possible");
			*io_gas -= static_cast<int64_t>(c_callValueTransferGas); // no underflow
			_callGas += static_cast<int64_t>(c_callStipend); // overflow possibility, but in the same time *io_gas < 0
		}

		if (*io_gas < 0)
			return false;

		auto ret = false;
		params.gas = u256{_callGas};
		if (_env->balance(_env->myAddress) >= params.value && _env->depth < 1024)
			ret = _env->call(params);

		*io_gas += static_cast<int64_t>(params.gas); // it is never more than initial _callGas
		return ret;
	}

	EXPORT void env_sha3(byte* _begin, uint64_t _size, h256* o_hash)
	{
		auto hash = sha3({_begin, (size_t)_size});
		*o_hash = hash;
	}

	EXPORT byte const* env_extcode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size)
	{
		auto addr = right160(*_addr256);
		auto& code = _env->codeAt(addr);
		*o_size = code.size();
		return code.data();
	}

	EXPORT void env_log(ExtVMFace* _env, byte* _beg, uint64_t _size, h256* _topic1, h256* _topic2, h256* _topic3, h256* _topic4)
	{
		dev::h256s topics;

		if (_topic1)
			topics.push_back(*_topic1);

		if (_topic2)
			topics.push_back(*_topic2);

		if (_topic3)
			topics.push_back(*_topic3);

		if (_topic4)
			topics.push_back(*_topic4);

		_env->log(std::move(topics), {_beg, (size_t)_size});
	}
}

<|endoftext|>