<commit_before>/*************************************************************************
 *   Copyright (C) 2011-2012 by Paul-Louis Ageneau                       *
 *   paul-louis (at) ageneau (dot) org                                   *
 *                                                                       *
 *   This file is part of TeapotNet.                                     *
 *                                                                       *
 *   TeapotNet 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.                 *
 *                                                                       *
 *   TeapotNet 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 TeapotNet.                                       *
 *   If not, see <http://www.gnu.org/licenses/>.                         *
 *************************************************************************/

#include "tpn/message.h"
#include "tpn/core.h"
#include "tpn/bytestring.h"
#include "tpn/sha512.h"
#include "tpn/yamlserializer.h"

namespace tpn
{

String Message::GenerateStamp(void)
{
	return String::random(4) + String::hexa(Time::Now().toUnixTime());
}

Message::Message(const String &content) :
	mContent(content),
	mTime(Time::Now()),
	mStamp(GenerateStamp()),
	mIsPublic(false),
	mIsIncoming(false),
	mIsRead(false)
{

}

Message::~Message(void)
{

}

Time Message::time(void) const
{
	return mTime;
}

Identifier Message::peering(void) const
{
	return mPeering;
}

String Message::stamp(void) const
{
	return mStamp;
}

bool Message::isPublic(void) const
{
	return mIsPublic;
}

const String &Message::content(void) const
{
	return mContent;
}

const StringMap &Message::headers(void) const
{
	return mHeaders;
}

bool Message::header(const String &name, String &value) const
{
	return mHeaders.get(name, value);
}

String Message::header(const String &name) const
{
	String value;
	if(mHeaders.get(name, value)) return value;
	else return String();
}

void Message::setPeering(const Identifier &peering)
{
	mPeering = peering.getDigest();
}

void Message::setContent(const String &content)
{
	mContent = content;
}

void Message::setHeaders(const StringMap &headers)
{
	mHeaders = headers;
}

void Message::setHeader(const String &name, const String &value)
{
	mHeaders[name] = value;
}

void Message::setDefaultHeader(const String &name, const String &value)
{
	if(!mHeaders.contains(name))
		mHeaders[name] = value;
}

bool Message::toggleIncoming(void)
{
	mIsIncoming = !mIsIncoming;
	return mIsIncoming;
}

bool Message::isIncoming(void) const
{
	return mIsIncoming;
}

bool Message::isRead(void) const
{
	return mIsRead;
}

void Message::markRead(bool read) const
{
	mIsRead = read;
}

bool Message::send(void) const
{
	String tmp;
	YamlSerializer serializer(&tmp);
	serializer.output(*this);

	Notification notification(tmp);
	notification.setParameter("type", "message");
	return notification.send();
}

bool Message::send(const Identifier &peering) const
{
	String tmp;
	YamlSerializer serializer(&tmp);
	serializer.output(*this);

	Notification notification(tmp);
	notification.setParameter("type", "message");
	return notification.send(peering);
}

bool Message::recv(const Notification &notification)
{
	String type;
	notification.parameter("type", type);
	if(!type.empty() && type != "message") return false;

	String tmp = notification.content();
	VAR(tmp);
	YamlSerializer serializer(&tmp);
	serializer.input(*this);
	VAR(mContent);
	return true;
}

void Message::serialize(Serializer &s) const
{
	ConstSerializableWrapper<bool> isPublicWrapper(mIsPublic);
	ConstSerializableWrapper<bool> isIncomingWrapper(mIsIncoming);
	ConstSerializableWrapper<bool> isReadWrapper(mIsRead);

	Serializer::ConstObjectMapping mapping;
	mapping["headers"] = &mHeaders;
        mapping["content"] = &mContent;
        mapping["peering"] = &mPeering;
        mapping["stamp"] = &mStamp;
	mapping["parent"] = &mParent;
        mapping["time"] = &mTime;
	mapping["public"] = &isPublicWrapper;
        mapping["incoming"] = &isIncomingWrapper;
	mapping["isread"] = &isReadWrapper;

	s.outputObject(mapping);
}

bool Message::deserialize(Serializer &s)
{
	mHeaders.clear();
        mContent.clear();
	mStamp.clear();
	mPeering = Identifier::Null;
	mTime = Time::Now();
	mIsPublic = false;
	mIsIncoming = false;
	mIsRead = false;

	SerializableWrapper<bool> isPublicWrapper(&mIsPublic);
	SerializableWrapper<bool> isIncomingWrapper(&mIsIncoming);
	SerializableWrapper<bool> isReadWrapper(&mIsRead);

	Serializer::ObjectMapping mapping;
	mapping["headers"] = &mHeaders;
        mapping["content"] = &mContent;
	mapping["peering"] = &mPeering;
	mapping["stamp"] = &mStamp;
	mapping["parent"] = &mParent;
	mapping["time"] = &mTime;
	mapping["public"] = &isPublicWrapper;
	mapping["incoming"] = &isIncomingWrapper;
	mapping["isread"] = &isReadWrapper;

	return s.inputObject(mapping);
}

bool Message::isInlineSerializable(void) const
{
	return false;
}

bool operator < (const Message &m1, const Message &m2)
{
	return m1.time() < m2.time();
}

bool operator > (const Message &m1, const Message &m2)
{
	return m1.time() > m2.time();
}

bool operator == (const Message &m1, const Message &m2)
{
	return ((m1.time() != m2.time())
		&& (m1.content() != m2.content()));
}

bool operator != (const Message &m1, const Message &m2)
{
	return !(m1 == m2);
}

}
<commit_msg>Removed debug logging<commit_after>/*************************************************************************
 *   Copyright (C) 2011-2012 by Paul-Louis Ageneau                       *
 *   paul-louis (at) ageneau (dot) org                                   *
 *                                                                       *
 *   This file is part of TeapotNet.                                     *
 *                                                                       *
 *   TeapotNet 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.                 *
 *                                                                       *
 *   TeapotNet 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 TeapotNet.                                       *
 *   If not, see <http://www.gnu.org/licenses/>.                         *
 *************************************************************************/

#include "tpn/message.h"
#include "tpn/core.h"
#include "tpn/bytestring.h"
#include "tpn/sha512.h"
#include "tpn/yamlserializer.h"

namespace tpn
{

String Message::GenerateStamp(void)
{
	return String::random(4) + String::hexa(Time::Now().toUnixTime());
}

Message::Message(const String &content) :
	mContent(content),
	mTime(Time::Now()),
	mStamp(GenerateStamp()),
	mIsPublic(false),
	mIsIncoming(false),
	mIsRead(false)
{

}

Message::~Message(void)
{

}

Time Message::time(void) const
{
	return mTime;
}

Identifier Message::peering(void) const
{
	return mPeering;
}

String Message::stamp(void) const
{
	return mStamp;
}

bool Message::isPublic(void) const
{
	return mIsPublic;
}

const String &Message::content(void) const
{
	return mContent;
}

const StringMap &Message::headers(void) const
{
	return mHeaders;
}

bool Message::header(const String &name, String &value) const
{
	return mHeaders.get(name, value);
}

String Message::header(const String &name) const
{
	String value;
	if(mHeaders.get(name, value)) return value;
	else return String();
}

void Message::setPeering(const Identifier &peering)
{
	mPeering = peering.getDigest();
}

void Message::setContent(const String &content)
{
	mContent = content;
}

void Message::setHeaders(const StringMap &headers)
{
	mHeaders = headers;
}

void Message::setHeader(const String &name, const String &value)
{
	mHeaders[name] = value;
}

void Message::setDefaultHeader(const String &name, const String &value)
{
	if(!mHeaders.contains(name))
		mHeaders[name] = value;
}

bool Message::toggleIncoming(void)
{
	mIsIncoming = !mIsIncoming;
	return mIsIncoming;
}

bool Message::isIncoming(void) const
{
	return mIsIncoming;
}

bool Message::isRead(void) const
{
	return mIsRead;
}

void Message::markRead(bool read) const
{
	mIsRead = read;
}

bool Message::send(void) const
{
	String tmp;
	YamlSerializer serializer(&tmp);
	serializer.output(*this);

	Notification notification(tmp);
	notification.setParameter("type", "message");
	return notification.send();
}

bool Message::send(const Identifier &peering) const
{
	String tmp;
	YamlSerializer serializer(&tmp);
	serializer.output(*this);

	Notification notification(tmp);
	notification.setParameter("type", "message");
	return notification.send(peering);
}

bool Message::recv(const Notification &notification)
{
	String type;
	notification.parameter("type", type);
	if(!type.empty() && type != "message") return false;

	String tmp = notification.content();
	YamlSerializer serializer(&tmp);
	serializer.input(*this);
	return true;
}

void Message::serialize(Serializer &s) const
{
	ConstSerializableWrapper<bool> isPublicWrapper(mIsPublic);
	ConstSerializableWrapper<bool> isIncomingWrapper(mIsIncoming);
	ConstSerializableWrapper<bool> isReadWrapper(mIsRead);

	Serializer::ConstObjectMapping mapping;
	mapping["headers"] = &mHeaders;
        mapping["content"] = &mContent;
        mapping["peering"] = &mPeering;
        mapping["stamp"] = &mStamp;
	mapping["parent"] = &mParent;
        mapping["time"] = &mTime;
	mapping["public"] = &isPublicWrapper;
        mapping["incoming"] = &isIncomingWrapper;
	mapping["isread"] = &isReadWrapper;

	s.outputObject(mapping);
}

bool Message::deserialize(Serializer &s)
{
	mHeaders.clear();
        mContent.clear();
	mStamp.clear();
	mPeering = Identifier::Null;
	mTime = Time::Now();
	mIsPublic = false;
	mIsIncoming = false;
	mIsRead = false;

	SerializableWrapper<bool> isPublicWrapper(&mIsPublic);
	SerializableWrapper<bool> isIncomingWrapper(&mIsIncoming);
	SerializableWrapper<bool> isReadWrapper(&mIsRead);

	Serializer::ObjectMapping mapping;
	mapping["headers"] = &mHeaders;
        mapping["content"] = &mContent;
	mapping["peering"] = &mPeering;
	mapping["stamp"] = &mStamp;
	mapping["parent"] = &mParent;
	mapping["time"] = &mTime;
	mapping["public"] = &isPublicWrapper;
	mapping["incoming"] = &isIncomingWrapper;
	mapping["isread"] = &isReadWrapper;

	return s.inputObject(mapping);
}

bool Message::isInlineSerializable(void) const
{
	return false;
}

bool operator < (const Message &m1, const Message &m2)
{
	return m1.time() < m2.time();
}

bool operator > (const Message &m1, const Message &m2)
{
	return m1.time() > m2.time();
}

bool operator == (const Message &m1, const Message &m2)
{
	return ((m1.time() != m2.time())
		&& (m1.content() != m2.content()));
}

bool operator != (const Message &m1, const Message &m2)
{
	return !(m1 == m2);
}

}
<|endoftext|>


<commit_before>#include "core/tz.hpp"
#include "gl/device.hpp"
#include "gl/renderer.hpp"

int main()
{
    constexpr std::size_t frame_number = 10;
    tz::initialise({"tz_renderer_test", tz::Version{1, 0, 0}, tz::info()}, tz::ApplicationType::Headless);
    {
        // Simply create some basic shaders. Don't try and render or anything.
        tz::gl::Device device{tz::gl::DeviceBuilder{}};

        tz::gl::ShaderBuilder builder;
        builder.set_shader_file(tz::gl::ShaderType::VertexShader, ".\\test\\gl\\shader_test.vertex.glsl");
        builder.set_shader_file(tz::gl::ShaderType::FragmentShader, ".\\test\\gl\\shader_test.fragment.glsl");
        tz::gl::Shader shader = device.create_shader(builder);

        std::array<int, 5> values{1, 2, 3, 4, 5};
        tz::gl::BufferResource int_resource{tz::gl::BufferData::from_array<int>(values)};

        tz::gl::RendererBuilder renderer_builder;
        tz::gl::ResourceHandle int_handle = renderer_builder.add_resource(int_resource);
        renderer_builder.set_output(tz::window());
        renderer_builder.set_pass(tz::gl::RenderPassAttachment::Colour);
        renderer_builder.set_shader(shader);
        tz::gl::Renderer renderer = device.create_renderer(renderer_builder);

        tz_assert(renderer.input_count() == 0, "Renderer had unexpected number of inputs");
        tz_assert(renderer.input_count_of(tz::gl::RendererInputDataAccess::StaticFixed) == 0, "Renderer had unexpected number of static inputs. Expected %d, but it has %zu", 0, renderer.input_count_of(tz::gl::RendererInputDataAccess::StaticFixed));
        tz_assert(renderer.input_count_of(tz::gl::RendererInputDataAccess::DynamicFixed) == 0, "Renderer had unexpected number of dynamic inputs. Expected %d, but it has %zu", 0, renderer.input_count_of(tz::gl::RendererInputDataAccess::DynamicFixed));

        tz_assert(renderer.resource_count() == 1, "Renderer had unexpected number of resources. Expected %d, got %zu", 1, renderer.resource_count());
        tz_assert(renderer.resource_count_of(tz::gl::ResourceType::Buffer) == 1, "Renderer had unexpected number of buffer resources. Expected %d, but it has %zu", 1, renderer.resource_count_of(tz::gl::ResourceType::Buffer));
        tz_assert(renderer.resource_count_of(tz::gl::ResourceType::Texture) == 0, "Renderer had unexpected number of texture resources. Expected %d, but it has %zu", 0, renderer.resource_count_of(tz::gl::ResourceType::Texture));
        // Clear Colour
        constexpr tz::Vec4 default_clear_colour{0.0f, 0.0f, 0.0f, 0.0f};
        tz_assert(renderer.get_clear_colour() == default_clear_colour, "Default renderer clear-colour is not {0, 0, 0, 0}");
        constexpr tz::Vec4 my_clear_colour{1.0f, 1.0f, 1.0f, 1.0f};
        renderer.set_clear_colour(my_clear_colour);
        tz::Vec4 rend_cc = renderer.get_clear_colour();
        tz_assert(rend_cc == my_clear_colour, "Expected clear colour {1, 1, 1, 1}, got {%.2f, %.2f, %.2f, %.2f}", rend_cc[0], rend_cc[1], rend_cc[2], rend_cc[3]);

        // Ensure resources make sense.
        tz::gl::IResource* same_int_resource = renderer.get_resource(int_handle);
        tz_assert(same_int_resource != nullptr, "Renderer failed to process resource");
        tz_assert(same_int_resource != &int_resource, "Renderer does not clone resource");
        {
            std::span<const std::byte> byte_span = same_int_resource->get_resource_bytes();
            auto* values_again = reinterpret_cast<const int*>(byte_span.data());
            tz_assert(byte_span.size_bytes() == sizeof(values), "Renderer resource had unexpected byte span size. Expected %zu, got %zu.", sizeof(values), byte_span.size_bytes());
            for(std::size_t i = 0; i < values.size(); i++)
            {
                tz_assert(values[i] == values_again[i], "Renderer static resource data does not match the resource provided in the RendererBuilder.");
            }
        }

        for(std::size_t i = 0; i < frame_number; i++)
        {
            tz::window().update();
            renderer.render();
        }
    }
    tz::terminate();
}<commit_msg>* Fixed missing include in renderer_test causing it to fail<commit_after>#include "core/tz.hpp"
#include "gl/device.hpp"
#include "gl/renderer.hpp"
#include "gl/resource.hpp"

int main()
{
    constexpr std::size_t frame_number = 10;
    tz::initialise({"tz_renderer_test", tz::Version{1, 0, 0}, tz::info()}, tz::ApplicationType::Headless);
    {
        // Simply create some basic shaders. Don't try and render or anything.
        tz::gl::Device device{tz::gl::DeviceBuilder{}};

        tz::gl::ShaderBuilder builder;
        builder.set_shader_file(tz::gl::ShaderType::VertexShader, ".\\test\\gl\\shader_test.vertex.glsl");
        builder.set_shader_file(tz::gl::ShaderType::FragmentShader, ".\\test\\gl\\shader_test.fragment.glsl");
        tz::gl::Shader shader = device.create_shader(builder);

        std::array<int, 5> values{1, 2, 3, 4, 5};
        tz::gl::BufferResource int_resource{tz::gl::BufferData::from_array<int>(values)};

        tz::gl::RendererBuilder renderer_builder;
        tz::gl::ResourceHandle int_handle = renderer_builder.add_resource(int_resource);
        renderer_builder.set_output(tz::window());
        renderer_builder.set_pass(tz::gl::RenderPassAttachment::Colour);
        renderer_builder.set_shader(shader);
        tz::gl::Renderer renderer = device.create_renderer(renderer_builder);

        tz_assert(renderer.input_count() == 0, "Renderer had unexpected number of inputs");
        tz_assert(renderer.input_count_of(tz::gl::RendererInputDataAccess::StaticFixed) == 0, "Renderer had unexpected number of static inputs. Expected %d, but it has %zu", 0, renderer.input_count_of(tz::gl::RendererInputDataAccess::StaticFixed));
        tz_assert(renderer.input_count_of(tz::gl::RendererInputDataAccess::DynamicFixed) == 0, "Renderer had unexpected number of dynamic inputs. Expected %d, but it has %zu", 0, renderer.input_count_of(tz::gl::RendererInputDataAccess::DynamicFixed));

        tz_assert(renderer.resource_count() == 1, "Renderer had unexpected number of resources. Expected %d, got %zu", 1, renderer.resource_count());
        tz_assert(renderer.resource_count_of(tz::gl::ResourceType::Buffer) == 1, "Renderer had unexpected number of buffer resources. Expected %d, but it has %zu", 1, renderer.resource_count_of(tz::gl::ResourceType::Buffer));
        tz_assert(renderer.resource_count_of(tz::gl::ResourceType::Texture) == 0, "Renderer had unexpected number of texture resources. Expected %d, but it has %zu", 0, renderer.resource_count_of(tz::gl::ResourceType::Texture));
        // Clear Colour
        constexpr tz::Vec4 default_clear_colour{0.0f, 0.0f, 0.0f, 0.0f};
        tz_assert(renderer.get_clear_colour() == default_clear_colour, "Default renderer clear-colour is not {0, 0, 0, 0}");
        constexpr tz::Vec4 my_clear_colour{1.0f, 1.0f, 1.0f, 1.0f};
        renderer.set_clear_colour(my_clear_colour);
        tz::Vec4 rend_cc = renderer.get_clear_colour();
        tz_assert(rend_cc == my_clear_colour, "Expected clear colour {1, 1, 1, 1}, got {%.2f, %.2f, %.2f, %.2f}", rend_cc[0], rend_cc[1], rend_cc[2], rend_cc[3]);

        // Ensure resources make sense.
        tz::gl::IResource* same_int_resource = renderer.get_resource(int_handle);
        tz_assert(same_int_resource != nullptr, "Renderer failed to process resource");
        tz_assert(same_int_resource != &int_resource, "Renderer does not clone resource");
        {
            std::span<const std::byte> byte_span = same_int_resource->get_resource_bytes();
            auto* values_again = reinterpret_cast<const int*>(byte_span.data());
            tz_assert(byte_span.size_bytes() == sizeof(values), "Renderer resource had unexpected byte span size. Expected %zu, got %zu.", sizeof(values), byte_span.size_bytes());
            for(std::size_t i = 0; i < values.size(); i++)
            {
                tz_assert(values[i] == values_again[i], "Renderer static resource data does not match the resource provided in the RendererBuilder.");
            }
        }

        for(std::size_t i = 0; i < frame_number; i++)
        {
            tz::window().update();
            renderer.render();
        }
    }
    tz::terminate();
}<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "./vpx_config.h"
#include "test/codec_factory.h"
#include "test/decode_test_driver.h"
#include "test/ivf_video_source.h"
#include "test/util.h"
#if CONFIG_WEBM_IO
#include "test/webm_video_source.h"
#endif
#include "vpx_mem/vpx_mem.h"

namespace {

class InvalidFileTest
    : public ::libvpx_test::DecoderTest,
      public ::libvpx_test::CodecTestWithParam<const char*> {
 protected:
  InvalidFileTest() : DecoderTest(GET_PARAM(0)), res_file_(NULL) {}

  virtual ~InvalidFileTest() {
    if (res_file_ != NULL)
      fclose(res_file_);
  }

  void OpenResFile(const std::string &res_file_name_) {
    res_file_ = libvpx_test::OpenTestDataFile(res_file_name_);
    ASSERT_TRUE(res_file_ != NULL) << "Result file open failed. Filename: "
        << res_file_name_;
  }

  virtual bool HandleDecodeResult(
      const vpx_codec_err_t res_dec,
      const libvpx_test::CompressedVideoSource &video,
      libvpx_test::Decoder *decoder) {
    EXPECT_TRUE(res_file_ != NULL);
    int expected_res_dec;

    // Read integer result.
    const int res = fscanf(res_file_, "%d", &expected_res_dec);
    EXPECT_NE(res, EOF) << "Read result data failed";

    // Check results match.
    EXPECT_EQ(expected_res_dec, res_dec)
        << "Results don't match: frame number = " << video.frame_number();

    return !HasFailure();
  }

 private:
  FILE *res_file_;
};

TEST_P(InvalidFileTest, ReturnCode) {
  const std::string filename = GET_PARAM(1);
  libvpx_test::CompressedVideoSource *video = NULL;

  // Open compressed video file.
  if (filename.substr(filename.length() - 3, 3) == "ivf") {
    video = new libvpx_test::IVFVideoSource(filename);
  } else if (filename.substr(filename.length() - 4, 4) == "webm") {
#if CONFIG_WEBM_IO
    video = new libvpx_test::WebMVideoSource(filename);
#else
    fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
            filename.c_str());
    return;
#endif
  }
  video->Init();

  // Construct result file name. The file holds a list of expected integer
  // results, one for each decoded frame.  Any result that doesn't match
  // the files list will cause a test failure.
  const std::string res_filename = filename + ".res";
  OpenResFile(res_filename);

  // Decode frame, and check the md5 matching.
  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
  delete video;
}

const char *const kVP9InvalidFileTests[] = {
  "invalid-vp90-01.webm",
  "invalid-vp90-02.webm",
  "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf",
  "invalid-vp90-03.webm",
  "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf",
  "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf",
};

#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))

VP9_INSTANTIATE_TEST_CASE(InvalidFileTest,
                          ::testing::ValuesIn(kVP9InvalidFileTests,
                                              kVP9InvalidFileTests +
                                              NELEMENTS(kVP9InvalidFileTests)));

}  // namespace
<commit_msg>invalid_file_test: output error detail on mismatch<commit_after>/*
 *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "./vpx_config.h"
#include "test/codec_factory.h"
#include "test/decode_test_driver.h"
#include "test/ivf_video_source.h"
#include "test/util.h"
#if CONFIG_WEBM_IO
#include "test/webm_video_source.h"
#endif
#include "vpx_mem/vpx_mem.h"

namespace {

class InvalidFileTest
    : public ::libvpx_test::DecoderTest,
      public ::libvpx_test::CodecTestWithParam<const char*> {
 protected:
  InvalidFileTest() : DecoderTest(GET_PARAM(0)), res_file_(NULL) {}

  virtual ~InvalidFileTest() {
    if (res_file_ != NULL)
      fclose(res_file_);
  }

  void OpenResFile(const std::string &res_file_name_) {
    res_file_ = libvpx_test::OpenTestDataFile(res_file_name_);
    ASSERT_TRUE(res_file_ != NULL) << "Result file open failed. Filename: "
        << res_file_name_;
  }

  virtual bool HandleDecodeResult(
      const vpx_codec_err_t res_dec,
      const libvpx_test::CompressedVideoSource &video,
      libvpx_test::Decoder *decoder) {
    EXPECT_TRUE(res_file_ != NULL);
    int expected_res_dec;

    // Read integer result.
    const int res = fscanf(res_file_, "%d", &expected_res_dec);
    EXPECT_NE(res, EOF) << "Read result data failed";

    // Check results match.
    EXPECT_EQ(expected_res_dec, res_dec)
        << "Results don't match: frame number = " << video.frame_number()
        << ". (" << decoder->DecodeError() << ")";

    return !HasFailure();
  }

 private:
  FILE *res_file_;
};

TEST_P(InvalidFileTest, ReturnCode) {
  const std::string filename = GET_PARAM(1);
  libvpx_test::CompressedVideoSource *video = NULL;

  // Open compressed video file.
  if (filename.substr(filename.length() - 3, 3) == "ivf") {
    video = new libvpx_test::IVFVideoSource(filename);
  } else if (filename.substr(filename.length() - 4, 4) == "webm") {
#if CONFIG_WEBM_IO
    video = new libvpx_test::WebMVideoSource(filename);
#else
    fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
            filename.c_str());
    return;
#endif
  }
  video->Init();

  // Construct result file name. The file holds a list of expected integer
  // results, one for each decoded frame.  Any result that doesn't match
  // the files list will cause a test failure.
  const std::string res_filename = filename + ".res";
  OpenResFile(res_filename);

  // Decode frame, and check the md5 matching.
  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
  delete video;
}

const char *const kVP9InvalidFileTests[] = {
  "invalid-vp90-01.webm",
  "invalid-vp90-02.webm",
  "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.ivf",
  "invalid-vp90-03.webm",
  "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf",
  "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf",
};

#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))

VP9_INSTANTIATE_TEST_CASE(InvalidFileTest,
                          ::testing::ValuesIn(kVP9InvalidFileTests,
                                              kVP9InvalidFileTests +
                                              NELEMENTS(kVP9InvalidFileTests)));

}  // namespace
<|endoftext|>


<commit_before>#include <matrix/math.hpp>
#include "test_macros.hpp"

using namespace matrix;

template class Matrix<float, 3, 3>;

int main()
{
    Matrix3f m;
    m.setZero();
    m(0, 0) = 1;
    m(0, 1) = 2;
    m(0, 2) = 3;
    m(1, 0) = 4;
    m(1, 1) = 5;
    m(1, 2) = 6;
    m(2, 0) = 7;
    m(2, 1) = 8;
    m(2, 2) = 9;

    float data[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    Matrix3f m2(data);

    for(int i=0; i<9; i++) {
        TEST(fabs(data[i] - m2.data()[i]) < 1e-6f);
    }

    float data_times_2[9] = {2, 4, 6, 8, 10, 12, 14, 16, 18};
    Matrix3f m3(data_times_2);

    TEST(isEqual(m, m2));
    TEST(!(m == m3));

    m2 *= 2;
    TEST(m2 == m3);

    m2 /= 2;
    m2 -= 1;
    float data_minus_1[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
    TEST(Matrix3f(data_minus_1) == m2);

    m2 += 1;
    TEST(Matrix3f(data) == m2);

    m3 -= m2;

    TEST(m3 == m2);

    float data_row_02_swap[9] = {
        7, 8, 9,
        4, 5, 6,
        1, 2, 3,
    };

    float data_col_02_swap[9] = {
        3, 2, 1,
        6, 5, 4,
        9, 8, 7
    };

    Matrix3f m4(data);

    TEST(-m4 == m4*(-1));

    m4.swapCols(0, 2);
    TEST(m4 == Matrix3f(data_col_02_swap));
    m4.swapCols(0, 2);
    m4.swapRows(0, 2);
    TEST(m4 == Matrix3f(data_row_02_swap));
    TEST(fabs(m4.min() - 1) < 1e-5);

    Scalar<float> s;
    s = 1;
    TEST(fabs(s - 1) < 1e-5);

    Matrix<float, 1, 1> m5 = s;
    TEST(fabs(m5(0,0) - s) < 1e-5);

    Matrix<float, 2, 2> m6;
    m6.setRow(0, Vector2f(1, 2));
    float m7_array[] = {1,2,0,0};
    Matrix<float, 2, 2> m7(m7_array);
    TEST(isEqual(m6, m7));
    m6.setCol(0, Vector2f(3, 4));
    float m8_array[] = {3,2,4,0};
    Matrix<float, 2, 2> m8(m8_array);
    TEST(isEqual(m6, m8));

    return 0;
}

/* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */
<commit_msg>Found a few coverage gaps with local coverage testing.<commit_after>#include <matrix/math.hpp>
#include "test_macros.hpp"

using namespace matrix;

template class Matrix<float, 3, 3>;

int main()
{
    Matrix3f m;
    m.setZero();
    m(0, 0) = 1;
    m(0, 1) = 2;
    m(0, 2) = 3;
    m(1, 0) = 4;
    m(1, 1) = 5;
    m(1, 2) = 6;
    m(2, 0) = 7;
    m(2, 1) = 8;
    m(2, 2) = 9;

    float data[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    Matrix3f m2(data);

    for(int i=0; i<9; i++) {
        TEST(fabs(data[i] - m2.data()[i]) < 1e-6f);
    }

    float data_times_2[9] = {2, 4, 6, 8, 10, 12, 14, 16, 18};
    Matrix3f m3(data_times_2);

    TEST(isEqual(m, m2));
    TEST(!(m == m3));

    m2 *= 2;
    TEST(isEqual(m2, m3));

    m2 /= 2;
    m2 -= 1;
    float data_minus_1[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
    TEST(isEqual(Matrix3f(data_minus_1), m2));

    m2 += 1;
    TEST(isEqual(Matrix3f(data), m2));

    m3 -= m2;

    TEST(isEqual(m3, m2));

    float data_row_02_swap[9] = {
        7, 8, 9,
        4, 5, 6,
        1, 2, 3,
    };

    float data_col_02_swap[9] = {
        3, 2, 1,
        6, 5, 4,
        9, 8, 7
    };

    Matrix3f m4(data);

    TEST(isEqual(-m4, m4*(-1)));

    // col swap
    m4.swapCols(0, 2);
    TEST(isEqual(m4, Matrix3f(data_col_02_swap)));
    m4.swapCols(0, 2);

    // row swap
    m4.swapRows(0, 2);
    TEST(isEqual(m4, Matrix3f(data_row_02_swap)));
    m4.swapRows(0, 2);

    // swapping with same row should do nothing
    m4.swapRows(0, 0);
    m4.swapRows(1, 1);
    m4.swapRows(2, 2);
    TEST(isEqual(m4, Matrix3f(data)));

    // swapping with same col should do nothing
    m4.swapCols(0, 0);
    m4.swapCols(1, 1);
    m4.swapCols(2, 2);
    TEST(isEqual(m4, Matrix3f(data)));

    TEST(fabs(m4.min() - 1) < 1e-5);
    TEST(fabs((-m4).min() + 9) < 1e-5);

    Scalar<float> s;
    s = 1;
    TEST(fabs(s - 1) < 1e-5);

    Matrix<float, 1, 1> m5 = s;
    TEST(fabs(m5(0,0) - s) < 1e-5);

    Matrix<float, 2, 2> m6;
    m6.setRow(0, Vector2f(1, 2));
    float m7_array[] = {1,2,0,0};
    Matrix<float, 2, 2> m7(m7_array);
    TEST(isEqual(m6, m7));
    m6.setCol(0, Vector2f(3, 4));
    float m8_array[] = {3,2,4,0};
    Matrix<float, 2, 2> m8(m8_array);
    TEST(isEqual(m6, m8));

    return 0;
}

/* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */
<|endoftext|>


<commit_before><commit_msg>cyber: fix bug in destructor，may cause error in UT for low probability.<commit_after><|endoftext|>


<commit_before>/*
Resembla
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

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.
*/

#ifndef RESEMBLA_RERANKER_HPP
#define RESEMBLA_RERANKER_HPP

#include <vector>
#include <algorithm>

#ifdef DEBUG
#include <string>
#include <iostream>
#include "string_util.hpp"
#endif

namespace resembla {

template<typename Original>
class Reranker
{
public:
    using output_type = std::pair<Original, double>;

    template<typename Iterator, typename ScoreFunction>
    std::vector<output_type> rerank(
        const typename std::iterator_traits<Iterator>::value_type& target,
        const Iterator begin, const Iterator end,
        const ScoreFunction& score_func,
        double threshold = 0.0, size_t max_output = 0
    ) const
    {
#ifdef DEBUG
        std::cerr << "DEBUG: " << "target=" << cast_string<std::string>(target.first) << std::endl;
        std::cerr << "DEBUG: " << "===========before reranking=============" << std::endl;
        for(auto i = begin; i != end; ++i){
            std::cerr << "DEBUG: " << cast_string<std::string>(i->first) << std::endl;
        }
        std::cerr << "DEBUG: " << "start reranking: threshold==" << threshold << ", max_output=" << max_output << std::endl;
#endif
        std::vector<output_type> result;
        for(auto i = begin; i != end; ++i){
            auto score = score_func(target.second, i->second);
            if(threshold == 0.0 || score >= threshold){
                result.push_back(std::make_pair(i->first, score));
            }
        }

        if(max_output != 0 && result.size() > max_output){
            std::partial_sort(std::begin(result), std::begin(result) + max_output, std::end(result), Sorter());
            result.erase(std::begin(result) + max_output, std::end(result));
        }
        else{
            std::sort(std::begin(result), std::end(result), Sorter());
        }
#ifdef DEBUG
        std::cerr << "DEBUG: " << "===========after reranking=============" << std::endl;
        for(const auto& r: result){
            std::cerr << "DEBUG: " << "text=" << cast_string<std::string>(r.first) << ", score=" << r.second << std::endl;
        }
#endif
        return result;
    }

protected:
    struct Sorter
    {
        bool operator()(const output_type& a, const output_type& b) const
        {
            return a.second > b.second;
        }
    };
};

}
#endif
<commit_msg>remove const<commit_after>/*
Resembla
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

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.
*/

#ifndef RESEMBLA_RERANKER_HPP
#define RESEMBLA_RERANKER_HPP

#include <vector>
#include <algorithm>

#ifdef DEBUG
#include <string>
#include <iostream>
#include "string_util.hpp"
#endif

namespace resembla {

template<typename Original>
class Reranker
{
public:
    using output_type = std::pair<Original, double>;

    template<typename Iterator, typename ScoreFunction>
    std::vector<output_type> rerank(
        const typename std::iterator_traits<Iterator>::value_type& target,
        Iterator begin, Iterator end,
        const ScoreFunction& score_func,
        double threshold = 0.0, size_t max_output = 0
    ) const
    {
#ifdef DEBUG
        std::cerr << "DEBUG: " << "target=" << cast_string<std::string>(target.first) << std::endl;
        std::cerr << "DEBUG: " << "===========before reranking=============" << std::endl;
        for(auto i = begin; i != end; ++i){
            std::cerr << "DEBUG: " << cast_string<std::string>(i->first) << std::endl;
        }
        std::cerr << "DEBUG: " << "start reranking: threshold==" << threshold << ", max_output=" << max_output << std::endl;
#endif
        std::vector<output_type> result;
        for(auto i = begin; i != end; ++i){
            auto score = score_func(target.second, i->second);
            if(threshold == 0.0 || score >= threshold){
                result.push_back(std::make_pair(i->first, score));
            }
        }

        if(max_output != 0 && result.size() > max_output){
            std::partial_sort(std::begin(result), std::begin(result) + max_output, std::end(result), Sorter());
            result.erase(std::begin(result) + max_output, std::end(result));
        }
        else{
            std::sort(std::begin(result), std::end(result), Sorter());
        }
#ifdef DEBUG
        std::cerr << "DEBUG: " << "===========after reranking=============" << std::endl;
        for(const auto& r: result){
            std::cerr << "DEBUG: " << "text=" << cast_string<std::string>(r.first) << ", score=" << r.second << std::endl;
        }
#endif
        return result;
    }

protected:
    struct Sorter
    {
        bool operator()(const output_type& a, const output_type& b) const
        {
            return a.second > b.second;
        }
    };
};

}
#endif
<|endoftext|>


<commit_before>
#include <togo/assert.hpp>
#include <togo/utility.hpp>
#include <togo/string.hpp>
#include <togo/log.hpp>
#include <togo/hash.hpp>
#include <togo/fixed_array.hpp>
#include <togo/resource.hpp>

#include <initializer_list>

using namespace togo;

void test_path(
	ResourcePathParts& pp,
	StringRef const path,
	bool const expect_valid,
	StringRef const name,
	StringRef const type,
	std::initializer_list<StringRef> tags
) {
	bool const valid = resource::parse_path(path, pp);
	TOGO_LOGF("%s: '%.*s'\n", valid ? "valid  " : "invalid", path.size, path.data);
	if (valid) {
		TOGO_LOGF("  name: 0x%016lx '%.*s'\n", pp.name_hash, pp.name.size, pp.name.data);
		TOGO_LOGF("  type: 0x%08x%8s '%.*s'\n", pp.type_hash, "", pp.type.size, pp.type.data);
		TOGO_LOG ("  tags: [");
		for (unsigned i = 0; i < fixed_array::size(pp.tags); ++i) {
			TOGO_LOGF(
				"0x%08x '%.*s'%.*s",
				pp.tags[i].hash,
				pp.tags[i].name.size,
				pp.tags[i].name.data,
				fixed_array::size(pp.tags) == i + 1 ? 0 : 2, ", "
			);
		}
		TOGO_LOG("]\n\n");

		auto const type_hash = hash::calc_generic<ResourceType>(type);
		auto const name_hash = hash::calc_generic<ResourceNameHash>(name);
		TOGO_ASSERTE(type_hash == pp.type_hash);
		TOGO_ASSERTE(string::compare_equal(type, pp.type));
		TOGO_ASSERTE(name_hash == pp.name_hash);
		TOGO_ASSERTE(string::compare_equal(name, pp.name));

		for (unsigned i = 0; i < fixed_array::size(pp.tags); ++i) {
			auto const name = *(begin(tags) + i);
			auto const hash = hash::calc32(name);
			TOGO_ASSERTE(hash == pp.tags[i].hash);
			TOGO_ASSERTE(string::compare_equal(name, pp.tags[i].name));
		}
		TOGO_ASSERTE(fixed_array::size(pp.tags) == tags.size());
	}
	TOGO_ASSERTE(valid == expect_valid);
}

signed main() {
	ResourcePathParts pp;

	test_path(pp, "", false, "", "", {});
	test_path(pp, ".", false, "", "", {});
	test_path(pp, "/.", false, "", "", {});
	test_path(pp, "\\.", false, "", "", {});
	test_path(pp, ".c", false, "", "", {});
	test_path(pp, "b.", false, "", "", {});
	test_path(pp, "a", false, "", "", {});
	test_path(pp, "a/", false, "", "", {});
	test_path(pp, "a/.", false, "", "", {});
	test_path(pp, "a/b.", false, "", "", {});
	test_path(pp, "a/b.c.", false, "", "", {});
	test_path(pp, "a/b.c#.1", false, "", "", {});
	test_path(pp, "a#1", false, "", "", {});
	test_path(pp, ".#1", false, "", "", {});
	test_path(pp, "/.#1", false, "", "", {});
	test_path(pp, "\\.#1", false, "", "", {});
	test_path(pp, "b.#1", false, "", "", {});
	test_path(pp, ".c#1", false, "", "", {});
	test_path(pp, ".c#1", false, "", "", {});
	test_path(pp, "#", false, "", "", {});
	test_path(pp, "##", false, "", "", {});
	test_path(pp, "b.c#", false, "", "", {});
	test_path(pp, "b.c#1#", false, "", "", {});
	test_path(pp, "b.c##", false, "", "", {});
	test_path(pp, "b.c##1", false, "", "", {});
	test_path(pp, "b.c#1#2#3#4#5#6#7#8#9", false, "", "", {});

	TOGO_LOG("\n");
	test_path(pp, "b.c", true, "b", "c", {});
	test_path(pp, "a/b.c", true, "a/b", "c", {});
	test_path(pp, "b.c#1", true, "b", "c", {"1"});
	test_path(pp, "b.c#1#2", true, "b", "c", {"1", "2"});

	test_path(
		pp, "core/renderer/default_rc.render_config#linux",
		true,
		"core/renderer/default_rc",
		"render_config",
		{"linux"}
	);

	return 0;
}
<commit_msg>test/resource/general: added inner dot path test.<commit_after>
#include <togo/assert.hpp>
#include <togo/utility.hpp>
#include <togo/string.hpp>
#include <togo/log.hpp>
#include <togo/hash.hpp>
#include <togo/fixed_array.hpp>
#include <togo/resource.hpp>

#include <initializer_list>

using namespace togo;

void test_path(
	ResourcePathParts& pp,
	StringRef const path,
	bool const expect_valid,
	StringRef const name,
	StringRef const type,
	std::initializer_list<StringRef> tags
) {
	bool const valid = resource::parse_path(path, pp);
	TOGO_LOGF("%s: '%.*s'\n", valid ? "valid  " : "invalid", path.size, path.data);
	if (valid) {
		TOGO_LOGF("  name: 0x%016lx '%.*s'\n", pp.name_hash, pp.name.size, pp.name.data);
		TOGO_LOGF("  type: 0x%08x%8s '%.*s'\n", pp.type_hash, "", pp.type.size, pp.type.data);
		TOGO_LOG ("  tags: [");
		for (unsigned i = 0; i < fixed_array::size(pp.tags); ++i) {
			TOGO_LOGF(
				"0x%08x '%.*s'%.*s",
				pp.tags[i].hash,
				pp.tags[i].name.size,
				pp.tags[i].name.data,
				fixed_array::size(pp.tags) == i + 1 ? 0 : 2, ", "
			);
		}
		TOGO_LOG("]\n\n");

		auto const type_hash = hash::calc_generic<ResourceType>(type);
		auto const name_hash = hash::calc_generic<ResourceNameHash>(name);
		TOGO_ASSERTE(type_hash == pp.type_hash);
		TOGO_ASSERTE(string::compare_equal(type, pp.type));
		TOGO_ASSERTE(name_hash == pp.name_hash);
		TOGO_ASSERTE(string::compare_equal(name, pp.name));

		for (unsigned i = 0; i < fixed_array::size(pp.tags); ++i) {
			auto const name = *(begin(tags) + i);
			auto const hash = hash::calc32(name);
			TOGO_ASSERTE(hash == pp.tags[i].hash);
			TOGO_ASSERTE(string::compare_equal(name, pp.tags[i].name));
		}
		TOGO_ASSERTE(fixed_array::size(pp.tags) == tags.size());
	}
	TOGO_ASSERTE(valid == expect_valid);
}

signed main() {
	ResourcePathParts pp;

	test_path(pp, "", false, "", "", {});
	test_path(pp, ".", false, "", "", {});
	test_path(pp, "/.", false, "", "", {});
	test_path(pp, "\\.", false, "", "", {});
	test_path(pp, ".c", false, "", "", {});
	test_path(pp, "b.", false, "", "", {});
	test_path(pp, "a", false, "", "", {});
	test_path(pp, "a/", false, "", "", {});
	test_path(pp, "a/.", false, "", "", {});
	test_path(pp, "a/b.", false, "", "", {});
	test_path(pp, "a/b.c.", false, "", "", {});
	test_path(pp, "a/b.c#.1", false, "", "", {});
	test_path(pp, "a#1", false, "", "", {});
	test_path(pp, ".#1", false, "", "", {});
	test_path(pp, "/.#1", false, "", "", {});
	test_path(pp, "\\.#1", false, "", "", {});
	test_path(pp, "b.#1", false, "", "", {});
	test_path(pp, ".c#1", false, "", "", {});
	test_path(pp, ".c#1", false, "", "", {});
	test_path(pp, "#", false, "", "", {});
	test_path(pp, "##", false, "", "", {});
	test_path(pp, "b.c#", false, "", "", {});
	test_path(pp, "b.c#1#", false, "", "", {});
	test_path(pp, "b.c##", false, "", "", {});
	test_path(pp, "b.c##1", false, "", "", {});
	test_path(pp, "a.b/c.d", false, "", "", {});
	test_path(pp, "b.c#1#2#3#4#5#6#7#8#9", false, "", "", {});

	TOGO_LOG("\n");
	test_path(pp, "b.c", true, "b", "c", {});
	test_path(pp, "a/b.c", true, "a/b", "c", {});
	test_path(pp, "b.c#1", true, "b", "c", {"1"});
	test_path(pp, "b.c#1#2", true, "b", "c", {"1", "2"});

	test_path(
		pp, "core/renderer/default_rc.render_config#linux",
		true,
		"core/renderer/default_rc",
		"render_config",
		{"linux"}
	);

	return 0;
}
<|endoftext|>


<commit_before>/*
 * data_storage_test.cc
 *
 *  Created on: Feb 9, 2015
 *      Author: liao
 */
#include <iostream>
#include <sstream>
#include <sys/time.h>
#include "data_storage.h"
#include "simple_log.h"

int main() {
    int hash_size = 100000;

    DataStorageConfig config;
    config.data_config.dir = "/tmp/";
    config.data_config.file_name = "testudo_test.data";
    config.data_config.key_limit_size = 15;
    config.data_config.value_limit_size = 100;
    config.data_config.hash_size = 100000;

    DataStorage storage;
    int ret = storage.init(config);
    if (ret != 0) {
        LOG_ERROR("STORAGE INIT ERROR WHCH ret:%d", ret);
        return ret;
    }
//
//    std::string key = "111";
//    std::string value = "tom1";
//    ret = storage.put(key, value);
//    if (ret != 0) {
//        return ret;
//    }

//    std::string key2 = "222";
//    std::string value2 = "jetty3";
//    ret = storage.put(key2, value2);
//
//    std::string value3;
//    ret = storage.get(key2, value3);
//    if (ret != 0) {
//        LOG_INFO("NOT FOUND FOR key2:%s", key2.c_str());
//        return ret;
//    } else {
//        LOG_INFO("FOUND FOR key2:%s, value:%s", key2.c_str(), value3.c_str());
//    }

    struct timeval start, end;
    gettimeofday(&start, NULL);

    int put_size = 100000;
    for (size_t i = 0; i < 100000; i++) {
        std::stringstream temp;
        temp << "k_" << rand();
        std::string key4 = temp.str();
        std::string value4 = "jetty6";
        ret = storage.put(key4, value4);
        //storage.del(key4);
        ret = storage.get(key4, value4);
        if (ret != 0) {
            LOG_ERROR("CAN NOT GET FOR KEY:%s, ret:%d", key4.c_str(), ret);
        }
    }

    gettimeofday(&end, NULL);
    int cost_time = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000;
    LOG_INFO("####### TESTUDO hash_size:%d, put_size:%d, cost_time:%d ms #######", hash_size, put_size, cost_time);

    return ret;
}
<commit_msg>code factor<commit_after>/*
 * data_storage_test.cc
 *
 *  Created on: Feb 9, 2015
 *      Author: liao
 */
#include <iostream>
#include <sstream>
#include <sys/time.h>
#include "data_storage.h"
#include "simple_log.h"

int main() {
    int hash_size = 100000;

    DataStorageConfig config;
    config.data_config.dir = "/tmp/";
    config.data_config.file_name = "testudo_test.data";
    config.data_config.key_limit_size = 15;
    config.data_config.value_limit_size = 100;
    config.data_config.hash_size = hash_size;

    DataStorage storage;
    int ret = storage.init(config);
    if (ret != 0) {
        LOG_ERROR("STORAGE INIT ERROR WHCH ret:%d", ret);
        return ret;
    }
//
//    std::string key = "111";
//    std::string value = "tom1";
//    ret = storage.put(key, value);
//    if (ret != 0) {
//        return ret;
//    }

//    std::string key2 = "222";
//    std::string value2 = "jetty3";
//    ret = storage.put(key2, value2);
//
//    std::string value3;
//    ret = storage.get(key2, value3);
//    if (ret != 0) {
//        LOG_INFO("NOT FOUND FOR key2:%s", key2.c_str());
//        return ret;
//    } else {
//        LOG_INFO("FOUND FOR key2:%s, value:%s", key2.c_str(), value3.c_str());
//    }

    struct timeval start, end;
    gettimeofday(&start, NULL);

    int put_size = 100000;
    for (size_t i = 0; i < put_size; i++) {
        std::stringstream temp;
        temp << "k_" << rand();
        std::string key4 = temp.str();
        std::string value4 = "jetty6";
        ret = storage.put(key4, value4);
        //storage.del(key4);
        ret = storage.get(key4, value4);
        if (ret != 0) {
            LOG_ERROR("CAN NOT GET FOR KEY:%s, ret:%d", key4.c_str(), ret);
        }
    }

    gettimeofday(&end, NULL);
    int cost_time = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000;
    LOG_INFO("####### TESTUDO hash_size:%d, put_size:%d, cost_time:%d ms #######", hash_size, put_size, cost_time);

    return ret;
}
<|endoftext|>


<commit_before>#ifndef selection_hh_INCLUDED
#define selection_hh_INCLUDED

#include "buffer.hh"

namespace Kakoune
{

// An oriented, inclusive buffer range
struct Range
{
public:
    Range(BufferCoord first, BufferCoord last)
        : m_first{first}, m_last{last} {}

    void merge_with(const Range& range);

    BufferCoord& first() { return m_first; }
    BufferCoord& last() { return m_last; }

    const BufferCoord& first() const { return m_first; }
    const BufferCoord& last() const { return m_last; }

    bool operator== (const Range& other) const
    {
        return m_first == other.m_first and m_last == other.m_last;
    }

    const BufferCoord& min() const { return std::min(m_first, m_last); }
    const BufferCoord& max() const { return std::max(m_first, m_last); }

private:
    BufferCoord m_first;
    BufferCoord m_last;
};

inline bool overlaps(const Range& lhs, const Range& rhs)
{
    return lhs.min() <= rhs.min() ? lhs.max() >= rhs.min()
                                  : lhs.min() <= rhs.max();
}

inline String content(const Buffer& buffer, const Range& range)
{
    return buffer.string(range.min(), buffer.char_next(range.max()));
}

inline BufferIterator erase(Buffer& buffer, const Range& range)
{
    return buffer.erase(buffer.iterator_at(range.min()),
                        utf8::next(buffer.iterator_at(range.max())));
}

inline CharCount char_length(const Buffer& buffer, const Range& range)
{
    return utf8::distance(buffer.iterator_at(range.min()),
                          utf8::next(buffer.iterator_at(range.max())));
}

inline void avoid_eol(const Buffer& buffer, BufferCoord& coord)
{
    const auto column = coord.column;
    const auto& line = buffer[coord.line];
    if (column != 0 and column == line.length() - 1)
        coord.column = line.byte_count_to(line.char_length() - 2);
}

inline void avoid_eol(const Buffer& buffer, Range& sel)
{
    avoid_eol(buffer, sel.first());
    avoid_eol(buffer, sel.last());
}

using CaptureList = std::vector<String>;

// A selection is a Range, associated with a CaptureList
struct Selection : public Range
{
    explicit Selection(BufferCoord pos) : Range(pos,pos) {}
    Selection(BufferCoord first, BufferCoord last,
              CaptureList captures = {})
        : Range(first, last), m_captures(std::move(captures)) {}

    Selection(const Range& range)
        : Range(range) {}

    CaptureList& captures() { return m_captures; }
    const CaptureList& captures() const { return m_captures; }

private:
    CaptureList m_captures;
};

static bool compare_selections(const Selection& lhs, const Selection& rhs)
{
    return lhs.min() < rhs.min();
}

struct SelectionList : std::vector<Selection>
{
    SelectionList() = default;
    SelectionList(BufferCoord c) : std::vector<Selection>{Selection{c,c}} {}
    SelectionList(Selection s) : std::vector<Selection>{s} {}

    void update_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end);
    void update_erase(const Buffer& buffer, BufferCoord begin, BufferCoord end);

    void check_invariant() const;

    const Selection& main() const { return (*this)[m_main]; }
    Selection& main() { return (*this)[m_main]; }
    size_t main_index() const { return m_main; }
    void set_main_index(size_t main) { kak_assert(main < size()); m_main = main; }

    void rotate_main(int count) { m_main = (m_main + count) % size(); }

    template<typename OverlapsFunc>
    void merge_overlapping(OverlapsFunc overlaps)
    {
        kak_assert(std::is_sorted(begin(), end(), compare_selections));
        for (size_t i = 0; i+1 < size() and size() > 1;)
        {
            if (overlaps((*this)[i], (*this)[i+1]))
            {
                (*this)[i].merge_with((*this)[i+1]);
                erase(begin() + i + 1);
                if (i + 1 <= m_main)
                    --m_main;
            }
            else
               ++i;
        }
    }

    void sort_and_merge_overlapping()
    {
        if (size() == 1)
            return;

        const auto& main = this->main();
        const auto main_begin = main.min();
        m_main = std::count_if(begin(), end(), [&](const Selection& sel) {
                                   auto begin = sel.min();
                                   if (begin == main_begin)
                                       return &sel < &main;
                                   else
                                       return begin < main_begin;
                               });
        std::stable_sort(begin(), end(), compare_selections);
        merge_overlapping(overlaps);
    }

private:
    size_t m_main = 0;
};

}

#endif // selection_hh_INCLUDED
<commit_msg>Much faster implementation of SelectionList::merge_overlapping<commit_after>#ifndef selection_hh_INCLUDED
#define selection_hh_INCLUDED

#include "buffer.hh"

namespace Kakoune
{

// An oriented, inclusive buffer range
struct Range
{
public:
    Range(BufferCoord first, BufferCoord last)
        : m_first{first}, m_last{last} {}

    void merge_with(const Range& range);

    BufferCoord& first() { return m_first; }
    BufferCoord& last() { return m_last; }

    const BufferCoord& first() const { return m_first; }
    const BufferCoord& last() const { return m_last; }

    bool operator== (const Range& other) const
    {
        return m_first == other.m_first and m_last == other.m_last;
    }

    const BufferCoord& min() const { return std::min(m_first, m_last); }
    const BufferCoord& max() const { return std::max(m_first, m_last); }

private:
    BufferCoord m_first;
    BufferCoord m_last;
};

inline bool overlaps(const Range& lhs, const Range& rhs)
{
    return lhs.min() <= rhs.min() ? lhs.max() >= rhs.min()
                                  : lhs.min() <= rhs.max();
}

inline String content(const Buffer& buffer, const Range& range)
{
    return buffer.string(range.min(), buffer.char_next(range.max()));
}

inline BufferIterator erase(Buffer& buffer, const Range& range)
{
    return buffer.erase(buffer.iterator_at(range.min()),
                        utf8::next(buffer.iterator_at(range.max())));
}

inline CharCount char_length(const Buffer& buffer, const Range& range)
{
    return utf8::distance(buffer.iterator_at(range.min()),
                          utf8::next(buffer.iterator_at(range.max())));
}

inline void avoid_eol(const Buffer& buffer, BufferCoord& coord)
{
    const auto column = coord.column;
    const auto& line = buffer[coord.line];
    if (column != 0 and column == line.length() - 1)
        coord.column = line.byte_count_to(line.char_length() - 2);
}

inline void avoid_eol(const Buffer& buffer, Range& sel)
{
    avoid_eol(buffer, sel.first());
    avoid_eol(buffer, sel.last());
}

using CaptureList = std::vector<String>;

// A selection is a Range, associated with a CaptureList
struct Selection : public Range
{
    explicit Selection(BufferCoord pos) : Range(pos,pos) {}
    Selection(BufferCoord first, BufferCoord last,
              CaptureList captures = {})
        : Range(first, last), m_captures(std::move(captures)) {}

    Selection(const Range& range)
        : Range(range) {}

    CaptureList& captures() { return m_captures; }
    const CaptureList& captures() const { return m_captures; }

private:
    CaptureList m_captures;
};

static bool compare_selections(const Selection& lhs, const Selection& rhs)
{
    return lhs.min() < rhs.min();
}

struct SelectionList : std::vector<Selection>
{
    SelectionList() = default;
    SelectionList(BufferCoord c) : std::vector<Selection>{Selection{c,c}} {}
    SelectionList(Selection s) : std::vector<Selection>{s} {}

    void update_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end);
    void update_erase(const Buffer& buffer, BufferCoord begin, BufferCoord end);

    void check_invariant() const;

    const Selection& main() const { return (*this)[m_main]; }
    Selection& main() { return (*this)[m_main]; }
    size_t main_index() const { return m_main; }
    void set_main_index(size_t main) { kak_assert(main < size()); m_main = main; }

    void rotate_main(int count) { m_main = (m_main + count) % size(); }

    template<typename OverlapsFunc>
    void merge_overlapping(OverlapsFunc overlaps)
    {
        kak_assert(std::is_sorted(begin(), end(), compare_selections));
        size_t i = 0;
        for (size_t j = 1; j < size(); ++j)
        {
            if (overlaps((*this)[i], (*this)[j]))
            {
                (*this)[i].merge_with((*this)[j]);
                if (i < m_main)
                    --m_main;
            }
            else
            {
                ++i;
                if (i != j)
                    (*this)[i] = std::move((*this)[j]);
            }
        }
        erase(begin() + i + 1, end());
        kak_assert(std::is_sorted(begin(), end(), compare_selections));
    }

    void sort_and_merge_overlapping()
    {
        if (size() == 1)
            return;

        const auto& main = this->main();
        const auto main_begin = main.min();
        m_main = std::count_if(begin(), end(), [&](const Selection& sel) {
                                   auto begin = sel.min();
                                   if (begin == main_begin)
                                       return &sel < &main;
                                   else
                                       return begin < main_begin;
                               });
        std::stable_sort(begin(), end(), compare_selections);
        merge_overlapping(overlaps);
    }

private:
    size_t m_main = 0;
};

}

#endif // selection_hh_INCLUDED
<|endoftext|>


<commit_before>#include "selectors.hh"

#include "string.hh"

#include <algorithm>

#include <boost/optional.hpp>

namespace Kakoune
{

Selection select_line(const Buffer& buffer, const Selection& selection)
{
    Utf8Iterator first = buffer.iterator_at(selection.cursor());
    if (*first == '\n' and first + 1 != buffer.end())
        ++first;

    while (first != buffer.begin() and *(first - 1) != '\n')
        --first;

    Utf8Iterator last = first;
    while (last + 1 != buffer.end() and *last != '\n')
        ++last;
    return utf8_range(first, last);
}

Selection select_matching(const Buffer& buffer, const Selection& selection)
{
    std::vector<Codepoint> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' };
    Utf8Iterator it = buffer.iterator_at(selection.cursor());
    std::vector<Codepoint>::iterator match = matching_pairs.end();
    while (not is_eol(*it))
    {
        match = std::find(matching_pairs.begin(), matching_pairs.end(), *it);
        if (match != matching_pairs.end())
            break;
        ++it;
    }
    if (match == matching_pairs.end())
        return selection;

    Utf8Iterator begin = it;

    if (((match - matching_pairs.begin()) % 2) == 0)
    {
        int level = 0;
        const Codepoint opening = *match;
        const Codepoint closing = *(match+1);
        while (it != buffer.end())
        {
            if (*it == opening)
                ++level;
            else if (*it == closing and --level == 0)
                return utf8_range(begin, it);
            ++it;
        }
    }
    else
    {
        int level = 0;
        const Codepoint opening = *(match-1);
        const Codepoint closing = *match;
        while (true)
        {
            if (*it == closing)
                ++level;
            else if (*it == opening and --level == 0)
                return utf8_range(begin, it);
            if (it == buffer.begin())
                break;
            --it;
        }
    }
    return selection;
}

// c++14 will add std::optional, so we use boost::optional until then
using boost::optional;
static optional<Selection> find_surrounding(const Buffer& buffer,
                                            BufferCoord coord,
                                            CodepointPair matching,
                                            ObjectFlags flags, int init_level)
{
    const bool to_begin = flags & ObjectFlags::ToBegin;
    const bool to_end   = flags & ObjectFlags::ToEnd;
    const bool nestable = matching.first != matching.second;
    auto pos = buffer.iterator_at(coord);
    Utf8Iterator first = pos;
    if (to_begin)
    {
        int level = nestable ? init_level : 0;
        while (first != buffer.begin())
        {
            if (nestable and first != pos and *first == matching.second)
                ++level;
            else if (*first == matching.first)
            {
                if (level == 0)
                    break;
                else
                    --level;
            }
            --first;
        }
        if (level != 0 or *first != matching.first)
            return optional<Selection>{};
    }

    Utf8Iterator last = pos;
    if (to_end)
    {
        int level = nestable ? init_level : 0;
        while (last != buffer.end())
        {
            if (nestable and last != pos and *last == matching.first)
                ++level;
            else if (*last == matching.second)
            {
                if (level == 0)
                    break;
                else
                    --level;
            }
            ++last;
        }
        if (level != 0 or last == buffer.end())
            return optional<Selection>{};
    }

    if (flags & ObjectFlags::Inner)
    {
        if (to_begin and first != last)
            ++first;
        if (to_end and first != last)
            --last;
    }
    return to_end ? utf8_range(first, last) : utf8_range(last, first);
}

Selection select_surrounding(const Buffer& buffer, const Selection& selection,
                             CodepointPair matching, int level,
                             ObjectFlags flags)
{
    const bool nestable = matching.first != matching.second;
    auto pos = selection.cursor();
    if (not nestable or flags & ObjectFlags::Inner)
    {
        if (auto res = find_surrounding(buffer, pos, matching, flags, level))
            return *res;
        return selection;
    }

    auto c = buffer.byte_at(pos);
    if ((flags == ObjectFlags::ToBegin and c == matching.first) or
        (flags == ObjectFlags::ToEnd and c == matching.second))
        ++level;

    auto res = find_surrounding(buffer, pos, matching, flags, level);
    if (not res)
        return selection;

    if (flags == (ObjectFlags::ToBegin | ObjectFlags::ToEnd) and
        res->min() == selection.min() and res->max() == selection.max())
    {
        if (auto res_parent = find_surrounding(buffer, pos, matching, flags, level+1))
            return Selection{*res_parent};
    }
    return *res;
}

Selection select_to(const Buffer& buffer, const Selection& selection,
                    Codepoint c, int count, bool inclusive)
{
    Utf8Iterator begin = buffer.iterator_at(selection.cursor());
    Utf8Iterator end = begin;
    do
    {
        ++end;
        skip_while(end, buffer.end(), [c](Codepoint cur) { return cur != c; });
        if (end == buffer.end())
            return selection;
    }
    while (--count > 0);

    return utf8_range(begin, inclusive ? end : end-1);
}

Selection select_to_reverse(const Buffer& buffer, const Selection& selection,
                            Codepoint c, int count, bool inclusive)
{
    Utf8Iterator begin = buffer.iterator_at(selection.cursor());
    Utf8Iterator end = begin;
    do
    {
        --end;
        skip_while_reverse(end, buffer.begin(), [c](Codepoint cur) { return cur != c; });
        if (end == buffer.begin())
            return selection;
    }
    while (--count > 0);

    return utf8_range(begin, inclusive ? end : end+1);
}

Selection select_to_eol(const Buffer& buffer, const Selection& selection)
{
    Utf8Iterator begin = buffer.iterator_at(selection.cursor());
    Utf8Iterator end = begin;
    skip_while(end, buffer.end(), [](Codepoint cur) { return not is_eol(cur); });
    return utf8_range(begin, end != begin ? end-1 : end);
}

Selection select_to_eol_reverse(const Buffer& buffer, const Selection& selection)
{
    Utf8Iterator begin = buffer.iterator_at(selection.cursor());
    Utf8Iterator end = begin - 1;
    skip_while_reverse(end, buffer.begin(), [](Codepoint cur) { return not is_eol(cur); });
    return utf8_range(begin, end == buffer.begin() ? end : end+1);
}

static bool is_end_of_sentence(char c)
{
    return c == '.' or c == ';' or c == '!' or c == '?';
}

Selection select_whole_sentence(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{
    BufferIterator first = buffer.iterator_at(selection.cursor());
    BufferIterator last = first;

    if (flags & ObjectFlags::ToBegin)
    {
        bool saw_non_blank = false;
        while (first != buffer.begin())
        {
            char cur = *first;
            char prev = *(first-1);
            if (not is_blank(cur))
                saw_non_blank = true;
            if (is_eol(prev) and is_eol(cur))
            {
                ++first;
                break;
            }
            else if (is_end_of_sentence(prev))
            {
                if (saw_non_blank)
                    break;
                else if (flags & ObjectFlags::ToEnd)
                    last = first-1;
            }
            --first;
        }
        skip_while(first, buffer.end(), is_blank);
    }
    if (flags & ObjectFlags::ToEnd)
    {
        while (last != buffer.end())
        {
            char cur = *last;
            if (is_end_of_sentence(cur) or
                (is_eol(cur) and (last+1 == buffer.end() or is_eol(*(last+1)))))
                break;
            ++last;
        }
        if (not (flags & ObjectFlags::Inner) and last != buffer.end())
        {
            ++last;
            skip_while(last, buffer.end(), is_blank);
            --last;
        }
    }
    return (flags & ObjectFlags::ToEnd) ? Selection{first.coord(), last.coord()}
                                        : Selection{last.coord(), first.coord()};
}

Selection select_whole_paragraph(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{
    BufferIterator first = buffer.iterator_at(selection.cursor());
    BufferIterator last = first;

    if (flags & ObjectFlags::ToBegin and first != buffer.begin())
    {
        skip_while_reverse(first, buffer.begin(), is_eol);
        if (flags & ObjectFlags::ToEnd)
            last = first;
        while (first != buffer.begin())
        {
            char cur = *first;
            char prev = *(first-1);
            if (is_eol(prev) and is_eol(cur))
            {
                ++first;
                break;
            }
            --first;
        }
    }
    if (flags & ObjectFlags::ToEnd)
    {
        if (last != buffer.end() && is_eol(*last))
            ++last;
        while (last != buffer.end())
        {
            char cur = *last;
            char prev = *(last-1);
            if (is_eol(cur) and is_eol(prev))
            {
                if (not (flags & ObjectFlags::Inner))
                    skip_while(last, buffer.end(), is_eol);
                break;
            }
            ++last;
        }
        --last;
    }
    return (flags & ObjectFlags::ToEnd) ? Selection{first.coord(), last.coord()}
                                        : Selection{last.coord(), first.coord()};
}

static CharCount get_indent(const String& str, int tabstop)
{
    CharCount indent = 0;
    for (auto& c : str)
    {
    if (c == ' ')
        ++indent;
    else if (c =='\t')
        indent = (indent / tabstop + 1) * tabstop;
    else
        break;
    }
    return indent;
}

Selection select_whole_indent(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{
    int tabstop = buffer.options()["tabstop"].get<int>();
    LineCount line = selection.cursor().line;
    auto indent = get_indent(buffer[line], tabstop);

    LineCount begin_line = line - 1;
    if (flags & ObjectFlags::ToBegin)
    {
        while (begin_line >= 0 and (buffer[begin_line] == "\n" or get_indent(buffer[begin_line], tabstop) >= indent))
            --begin_line;
    }
    ++begin_line;
    LineCount end_line = line + 1;
    if (flags & ObjectFlags::ToEnd)
    {
        LineCount end = buffer.line_count();
        while (end_line < end and (buffer[end_line] == "\n" or get_indent(buffer[end_line], tabstop) >= indent))
            ++end_line;
    }
    --end_line;
    BufferCoord first = begin_line;
    // keep the first line indent in inner mode
    if (flags & ObjectFlags::Inner)
    {
        CharCount i = 0;
        for (; i < indent; ++first.column)
        {
            auto c = buffer.byte_at(first);
            if (c == ' ')
                ++i;
            if (c == '\t')
                i = (i / tabstop + 1) * tabstop;
        }
    }
    return Selection{first, {end_line, buffer[end_line].length() - 1}};
}

Selection select_whole_lines(const Buffer& buffer, const Selection& selection)
{
    // no need to be utf8 aware for is_eol as we only use \n as line seperator
    BufferIterator first = buffer.iterator_at(selection.anchor());
    BufferIterator last  = buffer.iterator_at(selection.cursor());
    BufferIterator& to_line_start = first <= last ? first : last;
    BufferIterator& to_line_end = first <= last ? last : first;

    --to_line_start;
    skip_while_reverse(to_line_start, buffer.begin(), [](char cur) { return not is_eol(cur); });
    if (is_eol(*to_line_start))
        ++to_line_start;

    skip_while(to_line_end, buffer.end(), [](char cur) { return not is_eol(cur); });
    if (to_line_end == buffer.end())
        --to_line_end;

    return Selection(first.coord(), last.coord());
}

Selection trim_partial_lines(const Buffer& buffer, const Selection& selection)
{
    // same as select_whole_lines
    BufferIterator first = buffer.iterator_at(selection.anchor());
    BufferIterator last =  buffer.iterator_at(selection.cursor());
    BufferIterator& to_line_start = first <= last ? first : last;
    BufferIterator& to_line_end = first <= last ? last : first;

    while (to_line_start != buffer.begin() and *(to_line_start-1) != '\n')
        ++to_line_start;
    while (*(to_line_end+1) != '\n' and to_line_end != to_line_start)
        --to_line_end;

    return Selection(first.coord(), last.coord());
}

void select_whole_buffer(const Buffer& buffer, SelectionList& selections)
{
    selections = SelectionList{ Selection({0,0}, buffer.back_coord()) };
}

void select_all_matches(const Buffer& buffer, SelectionList& selections,
                        const Regex& regex)
{
    SelectionList result;
    for (auto& sel : selections)
    {
        auto sel_end = utf8::next(buffer.iterator_at(sel.max()));
        RegexIterator re_it(buffer.iterator_at(sel.min()), sel_end, regex);
        RegexIterator re_end;

        for (; re_it != re_end; ++re_it)
        {
            auto& begin = (*re_it)[0].first;
            auto& end   = (*re_it)[0].second;

            if (begin == sel_end)
                continue;

            CaptureList captures;
            for (auto& match : *re_it)
                captures.emplace_back(match.first, match.second);

            result.emplace_back(begin.coord(),
                                (begin == end ? end : utf8::previous(end)).coord(),
                                std::move(captures));
        }
    }
    if (result.empty())
        throw runtime_error("nothing selected");
    result.set_main_index(result.size() - 1);
    selections = std::move(result);
}

void split_selections(const Buffer& buffer, SelectionList& selections,
                      const Regex& regex)
{
    SelectionList result;
    for (auto& sel : selections)
    {
        auto begin = buffer.iterator_at(sel.min());
        auto sel_end = utf8::next(buffer.iterator_at(sel.max()));
        RegexIterator re_it(begin, sel_end, regex,
                            boost::regex_constants::match_nosubs);
        RegexIterator re_end;

        for (; re_it != re_end; ++re_it)
        {
            BufferIterator end = (*re_it)[0].first;

            result.emplace_back(begin.coord(), (begin == end) ? end.coord() : utf8::previous(end).coord());
            begin = (*re_it)[0].second;
        }
        if (begin.coord() <= sel.max())
            result.emplace_back(begin.coord(), sel.max());
    }
    result.set_main_index(result.size() - 1);
    selections = std::move(result);
}

}
<commit_msg>Select previous sentence or paragraph if selecting backward from the first char<commit_after>#include "selectors.hh"

#include "string.hh"

#include <algorithm>

#include <boost/optional.hpp>

namespace Kakoune
{

Selection select_line(const Buffer& buffer, const Selection& selection)
{
    Utf8Iterator first = buffer.iterator_at(selection.cursor());
    if (*first == '\n' and first + 1 != buffer.end())
        ++first;

    while (first != buffer.begin() and *(first - 1) != '\n')
        --first;

    Utf8Iterator last = first;
    while (last + 1 != buffer.end() and *last != '\n')
        ++last;
    return utf8_range(first, last);
}

Selection select_matching(const Buffer& buffer, const Selection& selection)
{
    std::vector<Codepoint> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' };
    Utf8Iterator it = buffer.iterator_at(selection.cursor());
    std::vector<Codepoint>::iterator match = matching_pairs.end();
    while (not is_eol(*it))
    {
        match = std::find(matching_pairs.begin(), matching_pairs.end(), *it);
        if (match != matching_pairs.end())
            break;
        ++it;
    }
    if (match == matching_pairs.end())
        return selection;

    Utf8Iterator begin = it;

    if (((match - matching_pairs.begin()) % 2) == 0)
    {
        int level = 0;
        const Codepoint opening = *match;
        const Codepoint closing = *(match+1);
        while (it != buffer.end())
        {
            if (*it == opening)
                ++level;
            else if (*it == closing and --level == 0)
                return utf8_range(begin, it);
            ++it;
        }
    }
    else
    {
        int level = 0;
        const Codepoint opening = *(match-1);
        const Codepoint closing = *match;
        while (true)
        {
            if (*it == closing)
                ++level;
            else if (*it == opening and --level == 0)
                return utf8_range(begin, it);
            if (it == buffer.begin())
                break;
            --it;
        }
    }
    return selection;
}

// c++14 will add std::optional, so we use boost::optional until then
using boost::optional;
static optional<Selection> find_surrounding(const Buffer& buffer,
                                            BufferCoord coord,
                                            CodepointPair matching,
                                            ObjectFlags flags, int init_level)
{
    const bool to_begin = flags & ObjectFlags::ToBegin;
    const bool to_end   = flags & ObjectFlags::ToEnd;
    const bool nestable = matching.first != matching.second;
    auto pos = buffer.iterator_at(coord);
    Utf8Iterator first = pos;
    if (to_begin)
    {
        int level = nestable ? init_level : 0;
        while (first != buffer.begin())
        {
            if (nestable and first != pos and *first == matching.second)
                ++level;
            else if (*first == matching.first)
            {
                if (level == 0)
                    break;
                else
                    --level;
            }
            --first;
        }
        if (level != 0 or *first != matching.first)
            return optional<Selection>{};
    }

    Utf8Iterator last = pos;
    if (to_end)
    {
        int level = nestable ? init_level : 0;
        while (last != buffer.end())
        {
            if (nestable and last != pos and *last == matching.first)
                ++level;
            else if (*last == matching.second)
            {
                if (level == 0)
                    break;
                else
                    --level;
            }
            ++last;
        }
        if (level != 0 or last == buffer.end())
            return optional<Selection>{};
    }

    if (flags & ObjectFlags::Inner)
    {
        if (to_begin and first != last)
            ++first;
        if (to_end and first != last)
            --last;
    }
    return to_end ? utf8_range(first, last) : utf8_range(last, first);
}

Selection select_surrounding(const Buffer& buffer, const Selection& selection,
                             CodepointPair matching, int level,
                             ObjectFlags flags)
{
    const bool nestable = matching.first != matching.second;
    auto pos = selection.cursor();
    if (not nestable or flags & ObjectFlags::Inner)
    {
        if (auto res = find_surrounding(buffer, pos, matching, flags, level))
            return *res;
        return selection;
    }

    auto c = buffer.byte_at(pos);
    if ((flags == ObjectFlags::ToBegin and c == matching.first) or
        (flags == ObjectFlags::ToEnd and c == matching.second))
        ++level;

    auto res = find_surrounding(buffer, pos, matching, flags, level);
    if (not res)
        return selection;

    if (flags == (ObjectFlags::ToBegin | ObjectFlags::ToEnd) and
        res->min() == selection.min() and res->max() == selection.max())
    {
        if (auto res_parent = find_surrounding(buffer, pos, matching, flags, level+1))
            return Selection{*res_parent};
    }
    return *res;
}

Selection select_to(const Buffer& buffer, const Selection& selection,
                    Codepoint c, int count, bool inclusive)
{
    Utf8Iterator begin = buffer.iterator_at(selection.cursor());
    Utf8Iterator end = begin;
    do
    {
        ++end;
        skip_while(end, buffer.end(), [c](Codepoint cur) { return cur != c; });
        if (end == buffer.end())
            return selection;
    }
    while (--count > 0);

    return utf8_range(begin, inclusive ? end : end-1);
}

Selection select_to_reverse(const Buffer& buffer, const Selection& selection,
                            Codepoint c, int count, bool inclusive)
{
    Utf8Iterator begin = buffer.iterator_at(selection.cursor());
    Utf8Iterator end = begin;
    do
    {
        --end;
        skip_while_reverse(end, buffer.begin(), [c](Codepoint cur) { return cur != c; });
        if (end == buffer.begin())
            return selection;
    }
    while (--count > 0);

    return utf8_range(begin, inclusive ? end : end+1);
}

Selection select_to_eol(const Buffer& buffer, const Selection& selection)
{
    Utf8Iterator begin = buffer.iterator_at(selection.cursor());
    Utf8Iterator end = begin;
    skip_while(end, buffer.end(), [](Codepoint cur) { return not is_eol(cur); });
    return utf8_range(begin, end != begin ? end-1 : end);
}

Selection select_to_eol_reverse(const Buffer& buffer, const Selection& selection)
{
    Utf8Iterator begin = buffer.iterator_at(selection.cursor());
    Utf8Iterator end = begin - 1;
    skip_while_reverse(end, buffer.begin(), [](Codepoint cur) { return not is_eol(cur); });
    return utf8_range(begin, end == buffer.begin() ? end : end+1);
}

static bool is_end_of_sentence(char c)
{
    return c == '.' or c == ';' or c == '!' or c == '?';
}

Selection select_whole_sentence(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{
    BufferIterator first = buffer.iterator_at(selection.cursor());

    if (not (flags & ObjectFlags::ToEnd))
    {
        BufferIterator prev_non_blank = first-1;
        skip_while_reverse(prev_non_blank, buffer.begin(),
                           [](char c) { return is_blank(c) or is_eol(c); });
        if (is_end_of_sentence(*prev_non_blank))
            first = prev_non_blank;
    }

    BufferIterator last = first;

    if (flags & ObjectFlags::ToBegin)
    {
        bool saw_non_blank = false;
        while (first != buffer.begin())
        {
            char cur = *first;
            char prev = *(first-1);
            if (not is_blank(cur))
                saw_non_blank = true;
            if (is_eol(prev) and is_eol(cur))
            {
                ++first;
                break;
            }
            else if (is_end_of_sentence(prev))
            {
                if (saw_non_blank)
                    break;
                else if (flags & ObjectFlags::ToEnd)
                    last = first-1;
            }
            --first;
        }
        skip_while(first, buffer.end(), is_blank);
    }
    if (flags & ObjectFlags::ToEnd)
    {
        while (last != buffer.end())
        {
            char cur = *last;
            if (is_end_of_sentence(cur) or
                (is_eol(cur) and (last+1 == buffer.end() or is_eol(*(last+1)))))
                break;
            ++last;
        }
        if (not (flags & ObjectFlags::Inner) and last != buffer.end())
        {
            ++last;
            skip_while(last, buffer.end(), is_blank);
            --last;
        }
    }
    return (flags & ObjectFlags::ToEnd) ? Selection{first.coord(), last.coord()}
                                        : Selection{last.coord(), first.coord()};
}

Selection select_whole_paragraph(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{
    BufferIterator first = buffer.iterator_at(selection.cursor());

    if (not (flags & ObjectFlags::ToEnd) and buffer.offset(first.coord()) > 1 and
        *(first-1) == '\n' and *(first-2) == '\n')
        --first;

    BufferIterator last = first;

    if ((flags & ObjectFlags::ToBegin) and first != buffer.begin())
    {
        skip_while_reverse(first, buffer.begin(), is_eol);
        if (flags & ObjectFlags::ToEnd)
            last = first;
        while (first != buffer.begin())
        {
            char cur = *first;
            char prev = *(first-1);
            if (is_eol(prev) and is_eol(cur))
            {
                ++first;
                break;
            }
            --first;
        }
    }
    if (flags & ObjectFlags::ToEnd)
    {
        if (last != buffer.end() && is_eol(*last))
            ++last;
        while (last != buffer.end())
        {
            char cur = *last;
            char prev = *(last-1);
            if (is_eol(cur) and is_eol(prev))
            {
                if (not (flags & ObjectFlags::Inner))
                    skip_while(last, buffer.end(), is_eol);
                break;
            }
            ++last;
        }
        --last;
    }
    return (flags & ObjectFlags::ToEnd) ? Selection{first.coord(), last.coord()}
                                        : Selection{last.coord(), first.coord()};
}

static CharCount get_indent(const String& str, int tabstop)
{
    CharCount indent = 0;
    for (auto& c : str)
    {
    if (c == ' ')
        ++indent;
    else if (c =='\t')
        indent = (indent / tabstop + 1) * tabstop;
    else
        break;
    }
    return indent;
}

Selection select_whole_indent(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{
    int tabstop = buffer.options()["tabstop"].get<int>();
    LineCount line = selection.cursor().line;
    auto indent = get_indent(buffer[line], tabstop);

    LineCount begin_line = line - 1;
    if (flags & ObjectFlags::ToBegin)
    {
        while (begin_line >= 0 and (buffer[begin_line] == "\n" or get_indent(buffer[begin_line], tabstop) >= indent))
            --begin_line;
    }
    ++begin_line;
    LineCount end_line = line + 1;
    if (flags & ObjectFlags::ToEnd)
    {
        LineCount end = buffer.line_count();
        while (end_line < end and (buffer[end_line] == "\n" or get_indent(buffer[end_line], tabstop) >= indent))
            ++end_line;
    }
    --end_line;
    BufferCoord first = begin_line;
    // keep the first line indent in inner mode
    if (flags & ObjectFlags::Inner)
    {
        CharCount i = 0;
        for (; i < indent; ++first.column)
        {
            auto c = buffer.byte_at(first);
            if (c == ' ')
                ++i;
            if (c == '\t')
                i = (i / tabstop + 1) * tabstop;
        }
    }
    return Selection{first, {end_line, buffer[end_line].length() - 1}};
}

Selection select_whole_lines(const Buffer& buffer, const Selection& selection)
{
    // no need to be utf8 aware for is_eol as we only use \n as line seperator
    BufferIterator first = buffer.iterator_at(selection.anchor());
    BufferIterator last  = buffer.iterator_at(selection.cursor());
    BufferIterator& to_line_start = first <= last ? first : last;
    BufferIterator& to_line_end = first <= last ? last : first;

    --to_line_start;
    skip_while_reverse(to_line_start, buffer.begin(), [](char cur) { return not is_eol(cur); });
    if (is_eol(*to_line_start))
        ++to_line_start;

    skip_while(to_line_end, buffer.end(), [](char cur) { return not is_eol(cur); });
    if (to_line_end == buffer.end())
        --to_line_end;

    return Selection(first.coord(), last.coord());
}

Selection trim_partial_lines(const Buffer& buffer, const Selection& selection)
{
    // same as select_whole_lines
    BufferIterator first = buffer.iterator_at(selection.anchor());
    BufferIterator last =  buffer.iterator_at(selection.cursor());
    BufferIterator& to_line_start = first <= last ? first : last;
    BufferIterator& to_line_end = first <= last ? last : first;

    while (to_line_start != buffer.begin() and *(to_line_start-1) != '\n')
        ++to_line_start;
    while (*(to_line_end+1) != '\n' and to_line_end != to_line_start)
        --to_line_end;

    return Selection(first.coord(), last.coord());
}

void select_whole_buffer(const Buffer& buffer, SelectionList& selections)
{
    selections = SelectionList{ Selection({0,0}, buffer.back_coord()) };
}

void select_all_matches(const Buffer& buffer, SelectionList& selections,
                        const Regex& regex)
{
    SelectionList result;
    for (auto& sel : selections)
    {
        auto sel_end = utf8::next(buffer.iterator_at(sel.max()));
        RegexIterator re_it(buffer.iterator_at(sel.min()), sel_end, regex);
        RegexIterator re_end;

        for (; re_it != re_end; ++re_it)
        {
            auto& begin = (*re_it)[0].first;
            auto& end   = (*re_it)[0].second;

            if (begin == sel_end)
                continue;

            CaptureList captures;
            for (auto& match : *re_it)
                captures.emplace_back(match.first, match.second);

            result.emplace_back(begin.coord(),
                                (begin == end ? end : utf8::previous(end)).coord(),
                                std::move(captures));
        }
    }
    if (result.empty())
        throw runtime_error("nothing selected");
    result.set_main_index(result.size() - 1);
    selections = std::move(result);
}

void split_selections(const Buffer& buffer, SelectionList& selections,
                      const Regex& regex)
{
    SelectionList result;
    for (auto& sel : selections)
    {
        auto begin = buffer.iterator_at(sel.min());
        auto sel_end = utf8::next(buffer.iterator_at(sel.max()));
        RegexIterator re_it(begin, sel_end, regex,
                            boost::regex_constants::match_nosubs);
        RegexIterator re_end;

        for (; re_it != re_end; ++re_it)
        {
            BufferIterator end = (*re_it)[0].first;

            result.emplace_back(begin.coord(), (begin == end) ? end.coord() : utf8::previous(end).coord());
            begin = (*re_it)[0].second;
        }
        if (begin.coord() <= sel.max())
            result.emplace_back(begin.coord(), sel.max());
    }
    result.set_main_index(result.size() - 1);
    selections = std::move(result);
}

}
<|endoftext|>