<commit_before>
// cFile.cpp

// Implements the cFile class providing an OS-independent abstraction of a file.

#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "cFile.h"

/// Simple constructor - creates an unopened file object, use Open() to open / create a real file
cFile::cFile(void) :
	#ifdef USE_STDIO_FILE
	m_File(NULL)
	#else
	m_File(INVALID_HANDLE_VALUE)
	#endif  // USE_STDIO_FILE
{
	// Nothing needed yet
}

/// Constructs and opens / creates the file specified, use IsOpen() to check for success
cFile::cFile(const char * iFileName, EMode iMode) :
	#ifdef USE_STDIO_FILE
	m_File(NULL)
	#else
	m_File(INVALID_HANDLE_VALUE)
	#endif  // USE_STDIO_FILE
{
	Open(iFileName, iMode);
}

/// Auto-closes the file, if open
cFile::~cFile()
{
	if (IsOpen())
	{
		Close();
	}
}

bool cFile::Open(const char * iFileName, EMode iMode)
{
	assert(!IsOpen());  // You should close the file before opening another one

	if (IsOpen())
	{
		Close();
	}

	const char * Mode = NULL;
	switch (iMode)
	{
		case fmRead:      Mode = "rb";  break;
		case fmWrite:     Mode = "wb";  break;
		case fmReadWrite: Mode = "ab+"; break;
		default:
		{
			assert(!"Unhandled file mode");
			return false;
		}
	}
	m_File = fopen(iFileName, Mode);
	return (m_File != NULL);
}

void cFile::Close(void)
{
	assert(IsOpen());  // You should not close file objects that don't have an open file.

	if (!IsOpen())
	{
		return;
	}

	fclose(m_File);
}

bool cFile::IsOpen(void) const
{
	return (m_File != NULL);
}

bool cFile::IsEOF(void) const
{
	assert(IsOpen());

	if (!IsOpen())
	{
		// Unopened files behave as at EOF
		return true;
	}

	return (feof(m_File) != 0);
}

/// Reads  up to iNumBytes bytes into iBuffer, returns the number of bytes actually read,    or -1 on failure; asserts if not open
int cFile::Read (void * iBuffer, int iNumBytes)
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return fread(iBuffer, 1, iNumBytes, m_File);  // fread() returns the portion of Count parameter actually read, so we need to send iNumBytes as Count
}

/// Writes up to iNumBytes bytes from iBuffer, returns the number of bytes actually written, or -1 on failure; asserts if not open
int cFile::Write(const void * iBuffer, int iNumBytes)
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return fwrite(iBuffer, 1, iNumBytes, m_File);  // fwrite() returns the portion of Count parameter actually written, so we need to send iNumBytes as Count
}

/// Seeks to iPosition bytes from file start, returns old position or -1 for failure
int cFile::Seek (int iPosition)
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	if (fseek(m_File, iPosition, SEEK_SET) != 0)
	{
		return -1;
	}
	return ftell(m_File);
}

/// Returns the current position (bytes from file start)
int cFile::Tell (void) const
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return ftell(m_File);
}

/// Returns the size of file, in bytes, or -1 for failure; asserts if not open
int cFile::GetSize(void) const
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	int CurPos = ftell(m_File);
	if (CurPos < 0)
	{
		return -1;
	}
	if (fseek(m_File, 0, SEEK_END) != 0)
	{
		return -1;
	}
	int res = ftell(m_File);
	if (fseek(m_File, CurPos, SEEK_SET) != 0)
	{
		return -1;
	}
	return res;
}

<commit_msg>Fixed a sigsegv on *nix (cFile double-closing files)<commit_after>
// cFile.cpp

// Implements the cFile class providing an OS-independent abstraction of a file.

#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "cFile.h"

/// Simple constructor - creates an unopened file object, use Open() to open / create a real file
cFile::cFile(void) :
	#ifdef USE_STDIO_FILE
	m_File(NULL)
	#else
	m_File(INVALID_HANDLE_VALUE)
	#endif  // USE_STDIO_FILE
{
	// Nothing needed yet
}

/// Constructs and opens / creates the file specified, use IsOpen() to check for success
cFile::cFile(const char * iFileName, EMode iMode) :
	#ifdef USE_STDIO_FILE
	m_File(NULL)
	#else
	m_File(INVALID_HANDLE_VALUE)
	#endif  // USE_STDIO_FILE
{
	Open(iFileName, iMode);
}

/// Auto-closes the file, if open
cFile::~cFile()
{
	if (IsOpen())
	{
		Close();
	}
}

bool cFile::Open(const char * iFileName, EMode iMode)
{
	assert(!IsOpen());  // You should close the file before opening another one

	if (IsOpen())
	{
		Close();
	}

	const char * Mode = NULL;
	switch (iMode)
	{
		case fmRead:      Mode = "rb";  break;
		case fmWrite:     Mode = "wb";  break;
		case fmReadWrite: Mode = "ab+"; break;
		default:
		{
			assert(!"Unhandled file mode");
			return false;
		}
	}
	m_File = fopen(iFileName, Mode);
	return (m_File != NULL);
}

void cFile::Close(void)
{
	assert(IsOpen());  // You should not close file objects that don't have an open file.

	if (!IsOpen())
	{
		return;
	}

	fclose(m_File);
	m_File = NULL;
}

bool cFile::IsOpen(void) const
{
	return (m_File != NULL);
}

bool cFile::IsEOF(void) const
{
	assert(IsOpen());

	if (!IsOpen())
	{
		// Unopened files behave as at EOF
		return true;
	}

	return (feof(m_File) != 0);
}

/// Reads  up to iNumBytes bytes into iBuffer, returns the number of bytes actually read,    or -1 on failure; asserts if not open
int cFile::Read (void * iBuffer, int iNumBytes)
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return fread(iBuffer, 1, iNumBytes, m_File);  // fread() returns the portion of Count parameter actually read, so we need to send iNumBytes as Count
}

/// Writes up to iNumBytes bytes from iBuffer, returns the number of bytes actually written, or -1 on failure; asserts if not open
int cFile::Write(const void * iBuffer, int iNumBytes)
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return fwrite(iBuffer, 1, iNumBytes, m_File);  // fwrite() returns the portion of Count parameter actually written, so we need to send iNumBytes as Count
}

/// Seeks to iPosition bytes from file start, returns old position or -1 for failure
int cFile::Seek (int iPosition)
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	if (fseek(m_File, iPosition, SEEK_SET) != 0)
	{
		return -1;
	}
	return ftell(m_File);
}

/// Returns the current position (bytes from file start)
int cFile::Tell (void) const
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return ftell(m_File);
}

/// Returns the size of file, in bytes, or -1 for failure; asserts if not open
int cFile::GetSize(void) const
{
	assert(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	int CurPos = ftell(m_File);
	if (CurPos < 0)
	{
		return -1;
	}
	if (fseek(m_File, 0, SEEK_END) != 0)
	{
		return -1;
	}
	int res = ftell(m_File);
	if (fseek(m_File, CurPos, SEEK_SET) != 0)
	{
		return -1;
	}
	return res;
}

<|endoftext|>


<commit_before>#include "photoeffects.hpp"
#include <math.h>

using namespace cv;

#define MAX_KERNELSIZE 15

int edgeBlur(InputArray src, OutputArray dst, int indentTop, int indentLeft)
{
    CV_Assert(src.type() == CV_8UC3);
    dst.create(src.size(), src.type());
    Mat image = src.getMat(), outputImage = dst.getMat();

    CV_Assert(indentTop >= 0 && indentTop <= (image.rows / 2 - 10));
    CV_Assert(indentLeft >= 0 && indentLeft <= (image.cols / 2 - 10));

    float halfWidth = (image.cols / 2.0f) * (image.cols / 2.0f);
    float halfHeight = (image.rows / 2.0f) * (image.rows / 2.0f);
    float a = (image.cols / 2.0f - indentLeft)
            * (image.cols / 2.0f - indentLeft);
    float b = (image.rows / 2.0f - indentTop)
            * (image.rows / 2.0f - indentTop);
    int kSizeEdges = halfWidth / a + halfHeight / b;

    kSizeEdges = MIN(kSizeEdges, MAX_KERNELSIZE);
    Mat bearingImage(image.rows + 2 * kSizeEdges,
                    image.cols + 2 * kSizeEdges,
                    CV_8UC3);
    copyMakeBorder(image, bearingImage, kSizeEdges, kSizeEdges,
        kSizeEdges, kSizeEdges, BORDER_REPLICATE);

    for (int i = kSizeEdges; i < bearingImage.rows - kSizeEdges; i++)
    {
        for (int j = kSizeEdges; j < bearingImage.cols - kSizeEdges; j++)
        {
            int size;
            Vec3f sumF;
            Vec3b Color;
            float sumC = 0.0f, coeff;
            float bearHalfWidth = bearingImage.cols / 2.0f;
            float bearHalfHeight = bearingImage.rows / 2.0f;
            float radius = (bearHalfHeight - i)
                    * (bearHalfHeight - i)
                    / b

                    + (bearHalfWidth - j)
                    * (bearHalfWidth - j)
                    / a;
            if (radius < 1.0f)
            {
                outputImage.at<Vec3b>(i - kSizeEdges, j - kSizeEdges) =
                    bearingImage.at<Vec3b>(i, j);
                continue;
            }
            size = radius;
            radius = 2.0f * (radius - 0.5f) * (radius - 0.5f);
            size = MIN(size, kSizeEdges);
            for (int x = -size; x <= size; x++)
            {
                for (int y = -size; y <= size; y++)
                {
                    coeff = 1.0f / (CV_PI * radius)
                            * exp(- (x * x + y * y) / radius);

                    Color = bearingImage.at<Vec3b>(x + i, y + j);
                    sumF += (Vec3f) (coeff * Color);
                    sumC += coeff;
                }
            }
            sumF *= (1.0f / sumC);
            outputImage.at<Vec3b>(i - kSizeEdges, j - kSizeEdges) = sumF;
        }
    }

    return 0;
}
<commit_msg>Strange effect<commit_after>#include "photoeffects.hpp"
#include <math.h>

using namespace cv;

#define MAX_KERNELSIZE 15

int edgeBlur(InputArray src, OutputArray dst, int indentTop, int indentLeft)
{
    CV_Assert(src.type() == CV_8UC3);
    dst.create(src.size(), src.type());
    Mat image = src.getMat(), outputImage = dst.getMat();

    CV_Assert(indentTop >= 0 && indentTop <= (image.rows / 2 - 10));
    CV_Assert(indentLeft >= 0 && indentLeft <= (image.cols / 2 - 10));

    float halfWidth = (image.cols / 2.0f) * (image.cols / 2.0f);
    float halfHeight = (image.rows / 2.0f) * (image.rows / 2.0f);
    float a = (image.cols / 2.0f - indentLeft)
            * (image.cols / 2.0f - indentLeft);
    float b = (image.rows / 2.0f - indentTop)
            * (image.rows / 2.0f - indentTop);
    int kSizeEdges = halfWidth / a + halfHeight / b;

    kSizeEdges = MIN(kSizeEdges, MAX_KERNELSIZE);
    Mat bearingImage(image.rows + 2 * kSizeEdges,
                    image.cols + 2 * kSizeEdges,
                    CV_8UC3);
    copyMakeBorder(image, bearingImage, kSizeEdges, kSizeEdges,
        kSizeEdges, kSizeEdges, BORDER_REPLICATE);

    for (int i = kSizeEdges; i < bearingImage.rows - kSizeEdges; i++)
    {
        for (int j = kSizeEdges; j < bearingImage.cols - kSizeEdges; j++)
        {
            int size;
            Vec3f sumF;
            Vec3b Color;
            float sumC = 0.0f, coeff;
            float bearHalfWidth = bearingImage.cols / 2.0f;
            float bearHalfHeight = bearingImage.rows / 2.0f;
            float radius = (bearHalfHeight - i)
                    * (bearHalfHeight - i)
                    / b

                    + (bearHalfWidth - j)
                    * (bearHalfWidth - j)
                    / a;
            if (radius < 1.0f)
            {
                outputImage.at<Vec3b>(i - kSizeEdges, j - kSizeEdges) =
                    bearingImage.at<Vec3b>(i, j);
                continue;
            }
            size = radius;
            radius = 2.0f * (radius - 0.5f) * (radius - 0.5f);
            size = MIN(size, kSizeEdges);
            for (int x = -size; x <= size; x++)
            {
                for (int y = -size; y <= size; y++)
                {
                    coeff = 1.0f / (CV_PI * radius)
                            * exp(- (x * x + y * y) / radius);

                    Color = bearingImage.at<Vec3b>(x + i, y + j);
                    sumF += coeff * Color;
                    sumC += coeff;
                }
            }
            sumF *= (1.0f / sumC);
            outputImage.at<Vec3b>(i - kSizeEdges, j - kSizeEdges) = sumF;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>#ifndef INCLUDING_MPL_APPLY_V_HPP
#define INCLUDING_MPL_APPLY_V_HPP

#include <utility>

#include "mpl_utils.hpp"

namespace mpl {

	namespace detail::apply_values {

		template <typename TFunctor, typename TTuple, size_t... Indices>
		constexpr auto impl(TFunctor const & functor, TTuple && t, std::index_sequence<Indices...>)
		{
			return functor(std::get<Indices>(std::forward<TTuple>(t))...);
		}

		template <typename TFunctor, typename TTuple, size_t... Indices>
		constexpr auto impl(TFunctor & functor, TTuple && t, std::index_sequence<Indices...>)
		{
		 	return functor(std::get<Indices>(std::forward<TTuple>(t))...);
		}

	}

	template<typename TFunctor, typename TTuple>
	constexpr auto apply_values(TFunctor && functor, TTuple && elements) {
		return impl(
			std::forward<TFunctor>(functor),
			std::forward<TTuple>(elements),
			detail::sequence(std::forward<TTuple>(elements))
		);
	}

}

#define INCLUDED_MPL_APPLY_VALUES_HPP
#elif !defined(INCLUDED_MPL_APPLY_VALUES_HPP)
#	error circular inclusion
#endif<commit_msg>Add mpl::apply_v_constructor.<commit_after>#ifndef INCLUDING_MPL_APPLY_V_HPP
#define INCLUDING_MPL_APPLY_V_HPP

#include <utility>

#include "mpl_utils.hpp"
#include "mpl_indices.hpp"

namespace mpl {

	namespace detail::apply_values {

		template <typename TFunctor, typename TTuple, size_t... Indices>
		constexpr auto impl(TFunctor const & functor, TTuple && t, std::index_sequence<Indices...>)
		{
			return functor(std::get<Indices>(std::forward<TTuple>(t))...);
		}

		template <typename TFunctor, typename TTuple, size_t... Indices>
		constexpr auto impl(TFunctor & functor, TTuple && t, std::index_sequence<Indices...>)
		{
		 	return functor(std::get<Indices>(std::forward<TTuple>(t))...);
		}

		template <typename T, typename TTuple, size_t... Indices>
		constexpr auto impl_ctor(TTuple && t, std::index_sequence<Indices...>) {
			return T(std::get<Indices>(std::forward<TTuple>(t))...);
		}
	}

	template<typename TFunctor, typename TTuple>
	constexpr auto apply_v(TFunctor && functor, TTuple && elements) {
		return impl(
			std::forward<TFunctor>(functor),
			std::forward<TTuple>(elements),
			indices_of<TTuple>()
		);
	}

	template<typename T, typename TTuple>
	constexpr auto apply_v_constructor(TTuple && elements) {
		return detail::apply_values::impl_ctor<T>(
			std::forward<TTuple>(elements),
			indices_of<TTuple>()
		);
	}
}

#define INCLUDED_MPL_APPLY_VALUES_HPP
#elif !defined(INCLUDED_MPL_APPLY_VALUES_HPP)
#	error circular inclusion
#endif<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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 <stdint.h>
#include <unicode/uchar.h>
#include <unicode/utf16.h>
#include <algorithm>

#include <minikin/Emoji.h>
#include <minikin/GraphemeBreak.h>
#include "MinikinInternal.h"
#include "utils/WindowsUtils.h"

namespace minikin {

int32_t tailoredGraphemeClusterBreak(uint32_t c) {
  // Characters defined as Control that we want to treat them as Extend.
  // These are curated manually.
  if (c == 0x00AD                      // SHY
      || c == 0x061C                   // ALM
      || c == 0x180E                   // MONGOLIAN VOWEL SEPARATOR
      || c == 0x200B                   // ZWSP
      || c == 0x200E                   // LRM
      || c == 0x200F                   // RLM
      || (0x202A <= c && c <= 0x202E)  // LRE, RLE, PDF, LRO, RLO
      || ((c | 0xF) ==
          0x206F)     // WJ, invisible math operators, LRI, RLI, FSI, PDI,
                      // and the deprecated invisible format controls
      || c == 0xFEFF  // BOM
      || ((c | 0x7F) ==
          0xE007F))  // recently undeprecated tag characters in Plane 14
    return U_GCB_EXTEND;
  // THAI CHARACTER SARA AM is treated as a normal letter by most other
  // implementations: they allow a grapheme break before it.
  else if (c == 0x0E33)
    return U_GCB_OTHER;
  else
    return u_getIntPropertyValue(c, UCHAR_GRAPHEME_CLUSTER_BREAK);
}

// Returns true for all characters whose IndicSyllabicCategory is Pure_Killer.
// From http://www.unicode.org/Public/9.0.0/ucd/IndicSyllabicCategory.txt
bool isPureKiller(uint32_t c) {
  return (c == 0x0E3A || c == 0x0E4E || c == 0x0F84 || c == 0x103A ||
          c == 0x1714 || c == 0x1734 || c == 0x17D1 || c == 0x1BAA ||
          c == 0x1BF2 || c == 0x1BF3 || c == 0xA806 || c == 0xA953 ||
          c == 0xABED || c == 0x11134 || c == 0x112EA || c == 0x1172B);
}

bool GraphemeBreak::isGraphemeBreak(const float* advances,
                                    const uint16_t* buf,
                                    size_t start,
                                    size_t count,
                                    const size_t offset) {
  // This implementation closely follows Unicode Standard Annex #29 on
  // Unicode Text Segmentation (http://www.unicode.org/reports/tr29/),
  // implementing a tailored version of extended grapheme clusters.
  // The GB rules refer to section 3.1.1, Grapheme Cluster Boundary Rules.

  // Rule GB1, sot ÷; Rule GB2, ÷ eot
  if (offset <= start || offset >= start + count) {
    return true;
  }
  if (U16_IS_TRAIL(buf[offset])) {
    // Don't break a surrogate pair, but a lonely trailing surrogate pair is a
    // break
    return !U16_IS_LEAD(buf[offset - 1]);
  }
  uint32_t c1 = 0;
  uint32_t c2 = 0;
  size_t offset_back = offset;
  size_t offset_forward = offset;
  U16_PREV(buf, start, offset_back, c1);
  U16_NEXT(buf, offset_forward, start + count, c2);
  int32_t p1 = tailoredGraphemeClusterBreak(c1);
  int32_t p2 = tailoredGraphemeClusterBreak(c2);
  // Rule GB3, CR x LF
  if (p1 == U_GCB_CR && p2 == U_GCB_LF) {
    return false;
  }
  // Rule GB4, (Control | CR | LF) ÷
  if (p1 == U_GCB_CONTROL || p1 == U_GCB_CR || p1 == U_GCB_LF) {
    return true;
  }
  // Rule GB5, ÷ (Control | CR | LF)
  if (p2 == U_GCB_CONTROL || p2 == U_GCB_CR || p2 == U_GCB_LF) {
    return true;
  }
  // Rule GB6, L x ( L | V | LV | LVT )
  if (p1 == U_GCB_L &&
      (p2 == U_GCB_L || p2 == U_GCB_V || p2 == U_GCB_LV || p2 == U_GCB_LVT)) {
    return false;
  }
  // Rule GB7, ( LV | V ) x ( V | T )
  if ((p1 == U_GCB_LV || p1 == U_GCB_V) && (p2 == U_GCB_V || p2 == U_GCB_T)) {
    return false;
  }
  // Rule GB8, ( LVT | T ) x T
  if ((p1 == U_GCB_LVT || p1 == U_GCB_T) && p2 == U_GCB_T) {
    return false;
  }
  // Rule GB9, x (Extend | ZWJ); Rule GB9a, x SpacingMark; Rule GB9b, Prepend x
  if (p2 == U_GCB_EXTEND || p2 == U_GCB_ZWJ || p2 == U_GCB_SPACING_MARK ||
      p1 == U_GCB_PREPEND) {
    return false;
  }

  // This is used to decide font-dependent grapheme clusters. If we don't have
  // the advance information, we become conservative in grapheme breaking and
  // assume that it has no advance.
  const bool c2_has_advance =
      (advances != nullptr && advances[offset - start] != 0.0);

  // All the following rules are font-dependent, in the way that if we know c2
  // has an advance, we definitely know that it cannot form a grapheme with the
  // character(s) before it. So we make the decision in favor a grapheme break
  // early.
  if (c2_has_advance) {
    return true;
  }

  // Note: For Rule GB10 and GB11 below, we do not use the Unicode line breaking
  // properties for determining emoji-ness and carry our own data, because our
  // data could be more fresh than what ICU provides.
  //
  // Tailored version of Rule GB10, (E_Base | EBG) Extend* × E_Modifier.
  // The rule itself says do not break between emoji base and emoji modifiers,
  // skipping all Extend characters. Variation selectors are considered Extend,
  // so they are handled fine.
  //
  // We tailor this by requiring that an actual ligature is formed. If the font
  // doesn't form a ligature, we allow a break before the modifier.
  if (isEmojiModifier(c2)) {
    uint32_t c0 = c1;
    size_t offset_backback = offset_back;
    int32_t p0 = p1;
    if (p0 == U_GCB_EXTEND && offset_backback > start) {
      // skip over emoji variation selector
      U16_PREV(buf, start, offset_backback, c0);
      p0 = tailoredGraphemeClusterBreak(c0);
    }
    if (isEmojiBase(c0)) {
      return false;
    }
  }

  // Tailored version of Rule GB11, ZWJ × (Glue_After_Zwj | EBG)
  // We try to make emoji sequences with ZWJ a single grapheme cluster, but only
  // if they actually merge to one cluster. So we are more relaxed than the UAX
  // #29 rules in accepting any emoji character after the ZWJ, but are tighter
  // in that we only treat it as one cluster if a ligature is actually formed
  // and we also require the character before the ZWJ to also be an emoji.
  if (p1 == U_GCB_ZWJ && isEmoji(c2) && offset_back > start) {
    // look at character before ZWJ to see that both can participate in an
    // emoji zwj sequence
    uint32_t c0 = 0;
    size_t offset_backback = offset_back;
    U16_PREV(buf, start, offset_backback, c0);
    if (c0 == 0xFE0F && offset_backback > start) {
      // skip over emoji variation selector
      U16_PREV(buf, start, offset_backback, c0);
    }
    if (isEmoji(c0)) {
      return false;
    }
  }

  // Tailored version of Rule GB12 and Rule GB13 that look at even-odd cases.
  // sot   (RI RI)*  RI x RI
  // [^RI] (RI RI)*  RI x RI
  //
  // If we have font information, we have already broken the cluster if and only
  // if the second character had no advance, which means a ligature was formed.
  // If we don't, we look back like UAX #29 recommends, but only up to 1000 code
  // units.
  if (p1 == U_GCB_REGIONAL_INDICATOR && p2 == U_GCB_REGIONAL_INDICATOR) {
    if (advances != nullptr) {
      // We have advances information. But if we are here, we already know c2
      // has no advance. So we should definitely disallow a break.
      return false;
    } else {
      // Look at up to 1000 code units.
      const size_t lookback_barrier =
          std::max((ssize_t)start, (ssize_t)offset_back - 1000);
      size_t offset_backback = offset_back;
      while (offset_backback > lookback_barrier) {
        uint32_t c0 = 0;
        U16_PREV(buf, lookback_barrier, offset_backback, c0);
        if (tailoredGraphemeClusterBreak(c0) != U_GCB_REGIONAL_INDICATOR) {
          offset_backback += U16_LENGTH(c0);
          break;
        }
      }
      // The number 4 comes from the number of code units in a whole flag.
      return (offset - offset_backback) % 4 == 0;
    }
  }
  // Cluster Indic syllables together (tailoring of UAX #29).
  // Immediately after each virama (that is not just a pure killer) followed by
  // a letter, we disallow grapheme breaks (if we are here, we don't know about
  // advances, or we already know that c2 has no advance).
  if (u_getIntPropertyValue(c1, UCHAR_CANONICAL_COMBINING_CLASS) == 9  // virama
      && !isPureKiller(c1) &&
      u_getIntPropertyValue(c2, UCHAR_GENERAL_CATEGORY) == U_OTHER_LETTER) {
    return false;
  }
  // Rule GB999, Any ÷ Any
  return true;
}

size_t GraphemeBreak::getTextRunCursor(const float* advances,
                                       const uint16_t* buf,
                                       size_t start,
                                       size_t count,
                                       size_t offset,
                                       MoveOpt opt) {
  switch (opt) {
    case AFTER:
      if (offset < start + count) {
        offset++;
      }
      // fall through
    case AT_OR_AFTER:
      while (!isGraphemeBreak(advances, buf, start, count, offset)) {
        offset++;
      }
      break;
    case BEFORE:
      if (offset > start) {
        offset--;
      }
      // fall through
    case AT_OR_BEFORE:
      while (!isGraphemeBreak(advances, buf, start, count, offset)) {
        offset--;
      }
      break;
    case AT:
      if (!isGraphemeBreak(advances, buf, start, count, offset)) {
        offset = (size_t)-1;
      }
      break;
  }
  return offset;
}

}  // namespace minikin
<commit_msg>Eliminate unused write to local (#8541)<commit_after>/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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 <stdint.h>
#include <unicode/uchar.h>
#include <unicode/utf16.h>
#include <algorithm>

#include <minikin/Emoji.h>
#include <minikin/GraphemeBreak.h>
#include "MinikinInternal.h"
#include "utils/WindowsUtils.h"

namespace minikin {

int32_t tailoredGraphemeClusterBreak(uint32_t c) {
  // Characters defined as Control that we want to treat them as Extend.
  // These are curated manually.
  if (c == 0x00AD                      // SHY
      || c == 0x061C                   // ALM
      || c == 0x180E                   // MONGOLIAN VOWEL SEPARATOR
      || c == 0x200B                   // ZWSP
      || c == 0x200E                   // LRM
      || c == 0x200F                   // RLM
      || (0x202A <= c && c <= 0x202E)  // LRE, RLE, PDF, LRO, RLO
      || ((c | 0xF) ==
          0x206F)     // WJ, invisible math operators, LRI, RLI, FSI, PDI,
                      // and the deprecated invisible format controls
      || c == 0xFEFF  // BOM
      || ((c | 0x7F) ==
          0xE007F))  // recently undeprecated tag characters in Plane 14
    return U_GCB_EXTEND;
  // THAI CHARACTER SARA AM is treated as a normal letter by most other
  // implementations: they allow a grapheme break before it.
  else if (c == 0x0E33)
    return U_GCB_OTHER;
  else
    return u_getIntPropertyValue(c, UCHAR_GRAPHEME_CLUSTER_BREAK);
}

// Returns true for all characters whose IndicSyllabicCategory is Pure_Killer.
// From http://www.unicode.org/Public/9.0.0/ucd/IndicSyllabicCategory.txt
bool isPureKiller(uint32_t c) {
  return (c == 0x0E3A || c == 0x0E4E || c == 0x0F84 || c == 0x103A ||
          c == 0x1714 || c == 0x1734 || c == 0x17D1 || c == 0x1BAA ||
          c == 0x1BF2 || c == 0x1BF3 || c == 0xA806 || c == 0xA953 ||
          c == 0xABED || c == 0x11134 || c == 0x112EA || c == 0x1172B);
}

bool GraphemeBreak::isGraphemeBreak(const float* advances,
                                    const uint16_t* buf,
                                    size_t start,
                                    size_t count,
                                    const size_t offset) {
  // This implementation closely follows Unicode Standard Annex #29 on
  // Unicode Text Segmentation (http://www.unicode.org/reports/tr29/),
  // implementing a tailored version of extended grapheme clusters.
  // The GB rules refer to section 3.1.1, Grapheme Cluster Boundary Rules.

  // Rule GB1, sot ÷; Rule GB2, ÷ eot
  if (offset <= start || offset >= start + count) {
    return true;
  }
  if (U16_IS_TRAIL(buf[offset])) {
    // Don't break a surrogate pair, but a lonely trailing surrogate pair is a
    // break
    return !U16_IS_LEAD(buf[offset - 1]);
  }
  uint32_t c1 = 0;
  uint32_t c2 = 0;
  size_t offset_back = offset;
  size_t offset_forward = offset;
  U16_PREV(buf, start, offset_back, c1);
  U16_NEXT(buf, offset_forward, start + count, c2);
  int32_t p1 = tailoredGraphemeClusterBreak(c1);
  int32_t p2 = tailoredGraphemeClusterBreak(c2);
  // Rule GB3, CR x LF
  if (p1 == U_GCB_CR && p2 == U_GCB_LF) {
    return false;
  }
  // Rule GB4, (Control | CR | LF) ÷
  if (p1 == U_GCB_CONTROL || p1 == U_GCB_CR || p1 == U_GCB_LF) {
    return true;
  }
  // Rule GB5, ÷ (Control | CR | LF)
  if (p2 == U_GCB_CONTROL || p2 == U_GCB_CR || p2 == U_GCB_LF) {
    return true;
  }
  // Rule GB6, L x ( L | V | LV | LVT )
  if (p1 == U_GCB_L &&
      (p2 == U_GCB_L || p2 == U_GCB_V || p2 == U_GCB_LV || p2 == U_GCB_LVT)) {
    return false;
  }
  // Rule GB7, ( LV | V ) x ( V | T )
  if ((p1 == U_GCB_LV || p1 == U_GCB_V) && (p2 == U_GCB_V || p2 == U_GCB_T)) {
    return false;
  }
  // Rule GB8, ( LVT | T ) x T
  if ((p1 == U_GCB_LVT || p1 == U_GCB_T) && p2 == U_GCB_T) {
    return false;
  }
  // Rule GB9, x (Extend | ZWJ); Rule GB9a, x SpacingMark; Rule GB9b, Prepend x
  if (p2 == U_GCB_EXTEND || p2 == U_GCB_ZWJ || p2 == U_GCB_SPACING_MARK ||
      p1 == U_GCB_PREPEND) {
    return false;
  }

  // This is used to decide font-dependent grapheme clusters. If we don't have
  // the advance information, we become conservative in grapheme breaking and
  // assume that it has no advance.
  const bool c2_has_advance =
      (advances != nullptr && advances[offset - start] != 0.0);

  // All the following rules are font-dependent, in the way that if we know c2
  // has an advance, we definitely know that it cannot form a grapheme with the
  // character(s) before it. So we make the decision in favor a grapheme break
  // early.
  if (c2_has_advance) {
    return true;
  }

  // Note: For Rule GB10 and GB11 below, we do not use the Unicode line breaking
  // properties for determining emoji-ness and carry our own data, because our
  // data could be more fresh than what ICU provides.
  //
  // Tailored version of Rule GB10, (E_Base | EBG) Extend* × E_Modifier.
  // The rule itself says do not break between emoji base and emoji modifiers,
  // skipping all Extend characters. Variation selectors are considered Extend,
  // so they are handled fine.
  //
  // We tailor this by requiring that an actual ligature is formed. If the font
  // doesn't form a ligature, we allow a break before the modifier.
  if (isEmojiModifier(c2)) {
    uint32_t c0 = c1;
    size_t offset_backback = offset_back;
    int32_t p0 = p1;
    if (p0 == U_GCB_EXTEND && offset_backback > start) {
      // skip over emoji variation selector
      U16_PREV(buf, start, offset_backback, c0);
    }
    if (isEmojiBase(c0)) {
      return false;
    }
  }

  // Tailored version of Rule GB11, ZWJ × (Glue_After_Zwj | EBG)
  // We try to make emoji sequences with ZWJ a single grapheme cluster, but only
  // if they actually merge to one cluster. So we are more relaxed than the UAX
  // #29 rules in accepting any emoji character after the ZWJ, but are tighter
  // in that we only treat it as one cluster if a ligature is actually formed
  // and we also require the character before the ZWJ to also be an emoji.
  if (p1 == U_GCB_ZWJ && isEmoji(c2) && offset_back > start) {
    // look at character before ZWJ to see that both can participate in an
    // emoji zwj sequence
    uint32_t c0 = 0;
    size_t offset_backback = offset_back;
    U16_PREV(buf, start, offset_backback, c0);
    if (c0 == 0xFE0F && offset_backback > start) {
      // skip over emoji variation selector
      U16_PREV(buf, start, offset_backback, c0);
    }
    if (isEmoji(c0)) {
      return false;
    }
  }

  // Tailored version of Rule GB12 and Rule GB13 that look at even-odd cases.
  // sot   (RI RI)*  RI x RI
  // [^RI] (RI RI)*  RI x RI
  //
  // If we have font information, we have already broken the cluster if and only
  // if the second character had no advance, which means a ligature was formed.
  // If we don't, we look back like UAX #29 recommends, but only up to 1000 code
  // units.
  if (p1 == U_GCB_REGIONAL_INDICATOR && p2 == U_GCB_REGIONAL_INDICATOR) {
    if (advances != nullptr) {
      // We have advances information. But if we are here, we already know c2
      // has no advance. So we should definitely disallow a break.
      return false;
    } else {
      // Look at up to 1000 code units.
      const size_t lookback_barrier =
          std::max((ssize_t)start, (ssize_t)offset_back - 1000);
      size_t offset_backback = offset_back;
      while (offset_backback > lookback_barrier) {
        uint32_t c0 = 0;
        U16_PREV(buf, lookback_barrier, offset_backback, c0);
        if (tailoredGraphemeClusterBreak(c0) != U_GCB_REGIONAL_INDICATOR) {
          offset_backback += U16_LENGTH(c0);
          break;
        }
      }
      // The number 4 comes from the number of code units in a whole flag.
      return (offset - offset_backback) % 4 == 0;
    }
  }
  // Cluster Indic syllables together (tailoring of UAX #29).
  // Immediately after each virama (that is not just a pure killer) followed by
  // a letter, we disallow grapheme breaks (if we are here, we don't know about
  // advances, or we already know that c2 has no advance).
  if (u_getIntPropertyValue(c1, UCHAR_CANONICAL_COMBINING_CLASS) == 9  // virama
      && !isPureKiller(c1) &&
      u_getIntPropertyValue(c2, UCHAR_GENERAL_CATEGORY) == U_OTHER_LETTER) {
    return false;
  }
  // Rule GB999, Any ÷ Any
  return true;
}

size_t GraphemeBreak::getTextRunCursor(const float* advances,
                                       const uint16_t* buf,
                                       size_t start,
                                       size_t count,
                                       size_t offset,
                                       MoveOpt opt) {
  switch (opt) {
    case AFTER:
      if (offset < start + count) {
        offset++;
      }
      // fall through
    case AT_OR_AFTER:
      while (!isGraphemeBreak(advances, buf, start, count, offset)) {
        offset++;
      }
      break;
    case BEFORE:
      if (offset > start) {
        offset--;
      }
      // fall through
    case AT_OR_BEFORE:
      while (!isGraphemeBreak(advances, buf, start, count, offset)) {
        offset--;
      }
      break;
    case AT:
      if (!isGraphemeBreak(advances, buf, start, count, offset)) {
        offset = (size_t)-1;
      }
      break;
  }
  return offset;
}

}  // namespace minikin
<|endoftext|>


<commit_before>

enum disir_status
basic_section(struct disir_mold **mold)
{
    enum disir_status status;
    struct disir_context *context_section;
    struct disir_context *context_mold;

    status = dc_mold_begin (&context_mold);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_add_documentation (context_mold, "test_doc", strlen ("test_doc"));
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_begin (context_mold, DISIR_CONTEXT_SECTION, &context_section);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_set_name (context_section, "section_name", strlen ("section_name"));
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_add_keyval_string (context_section, "k1", "k1value", "k1value doc", NULL);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_add_keyval_string (context_section, "k2", "k2value", "k2value doc", NULL);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_add_keyval_string (context_section, "k3", "k3value", "k3value doc", NULL);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_finalize (&context_section);
    if (status != DISIR_STATUS_OK);
        goto error;

    status = dc_mold_finalize (&context_mold, mold);
    if (status != DISIR_STATUS_OK)
        goto error;

    return DISIR_STATUS_OK;
error:
    if (context_section)
    {
        dc_destroy (&context_section);
    }
    if (context_mold)
    {
        dc_destroy (&context_mold);
    }
    return status;
}

<commit_msg>fix: remove semicolon in if-statement.<commit_after>

enum disir_status
basic_section(struct disir_mold **mold)
{
    enum disir_status status;
    struct disir_context *context_section;
    struct disir_context *context_mold;

    status = dc_mold_begin (&context_mold);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_add_documentation (context_mold, "test_doc", strlen ("test_doc"));
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_begin (context_mold, DISIR_CONTEXT_SECTION, &context_section);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_set_name (context_section, "section_name", strlen ("section_name"));
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_add_keyval_string (context_section, "k1", "k1value", "k1value doc", NULL);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_add_keyval_string (context_section, "k2", "k2value", "k2value doc", NULL);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_add_keyval_string (context_section, "k3", "k3value", "k3value doc", NULL);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_finalize (&context_section);
    if (status != DISIR_STATUS_OK)
        goto error;

    status = dc_mold_finalize (&context_mold, mold);
    if (status != DISIR_STATUS_OK)
        goto error;

    return DISIR_STATUS_OK;
error:
    if (context_section)
    {
        dc_destroy (&context_section);
    }
    if (context_mold)
    {
        dc_destroy (&context_mold);
    }
    return status;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Dmitry Marakasov <amdmi3@amdmi3.ru>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <binfmt/Buffer.hh>

#include <binfmt/internal/ManagedChunk.hh>

#include <algorithm>

namespace BinFmt {

Buffer::Buffer(std::shared_ptr<Internal::Chunk> chunk, size_t offset, size_t size) : chunk_(chunk), offset_(offset), size_(size) {
	size_t real_size = chunk_->GetSize();
	if (offset_ > real_size)
		offset_ = real_size;
	if (size_ > real_size - offset_)
		size_ = real_size - offset_;
}

Buffer::Buffer(size_t size) : chunk_(new Internal::ManagedChunk(size)) {
}

Buffer::~Buffer() {
}

// Modifiers
void Buffer::Realloc(size_t size) {
	Internal::ManagedChunk* chunk = new Internal::ManagedChunk(0, size);
	chunk->Append(chunk_->GetData() + offset_, std::min(size, size_));
	chunk_.reset(chunk);
	offset_ = 0;
}

void Buffer::Reserve(size_t size) {
	ReserveGreedy(size, size);
}

void Buffer::ReserveGreedy(size_t needed, size_t desired) {
	// we'll not shrink
	if (needed < size_)
		needed = size_;
	if (desired < needed)
		desired = needed;

	// ensure chunk is appendable (slice ends where chunk used space ends, e.g.
	// there's no data possibly used by other slice we may override) and that
	// there's enough space
	if (offset_ + size_ != chunk_->GetSize() || needed > chunk_->GetCapacity() - offset_)
		Realloc(desired);
}

void Buffer::Append(Byte data) {
	Append(&data, 1);
}

void Buffer::Append(const Byte* data, size_t size) {
	ReserveGreedy(size_ + size, std::max(size_ + size, size_ * 2));
	chunk_->Append(data, size);
	size_ += size;
}

void Buffer::Append(const Byte* start, const Byte* end) {
	Append(start, end - start);
}

void Buffer::Append(const Slicable& data) {
	Buffer slice = data.GetSlice();
	Append(slice.GetData(), slice.GetSize());
}

// Pointer/size getters
Byte* Buffer::GetData() {
	return chunk_->GetData() + offset_;
}

const Byte* Buffer::GetData() const {
	return chunk_->GetData() + offset_;
}

size_t Buffer::GetSize() const {
	return size_;
}

size_t Buffer::GetCapacity() const {
	return chunk_->GetCapacity() - offset_;
}

// subslice
Buffer Buffer::GetSlice(size_t offset, size_t size) const {
	if (offset > size_)
		offset = size_;
	if (size > size_ - offset)
		size = size_ - offset;

	return Buffer(chunk_, offset_ + offset, size);
}

Byte Buffer::operator[](size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return *offptr;
}

uint8_t Buffer::GetU8(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return (uint8_t)*offptr;
}

int8_t Buffer::GetS8(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return (int8_t)*offptr;
}

uint16_t Buffer::GetU16LE(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return (uint16_t)(uint8_t)*(offptr)
		| ((uint16_t)(uint8_t)*(offptr + 1) << 8);
}

int16_t Buffer::GetS16LE(size_t offset) const {
	return (int16_t)GetU16LE(offset);
}

uint16_t Buffer::GetU16BE(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return ((uint16_t)(uint8_t)*(offptr) << 8)
		| (uint16_t)(uint8_t)*(offptr + 1);
}
int16_t Buffer::GetS16BE(size_t offset) const {
	return (int16_t)GetU16BE(offset);
}

uint32_t Buffer::GetU32LE(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return (uint32_t)(uint8_t)*(offptr)
		| ((uint32_t)(uint8_t)*(offptr + 1) << 8)
		| ((uint32_t)(uint8_t)*(offptr + 2) << 16)
		| ((uint32_t)(uint8_t)*(offptr + 3) << 24);
}

int32_t Buffer::GetS32LE(size_t offset) const {
	return (int32_t)GetU32LE(offset);
}

uint32_t Buffer::GetU32BE(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return ((uint32_t)(uint8_t)*(offptr) << 24)
		| ((uint32_t)(uint8_t)*(offptr + 1) << 16)
		| ((uint32_t)(uint8_t)*(offptr + 2) << 8)
		| (uint32_t)(uint8_t)*(offptr + 3);
}

int32_t Buffer::GetS32BE(size_t offset) const {
	return (int32_t)GetU32BE(offset);
}

std::string Buffer::GetString(size_t offset, size_t length) const {
	if (offset > size_)
		offset = size_;
	if (length > size_ - offset)
		length = size_ - offset;
	const Byte* start = chunk_->GetData() + offset_ + offset;
	const Byte* zeropos = std::find(start, start + length, (Byte)0);
	if (zeropos != start + length)
		length = zeropos - start;
	return std::string(reinterpret_cast<const char*>(start), length);
}

}
<commit_msg>Fix unitialized members<commit_after>/*
 * Copyright (c) 2015 Dmitry Marakasov <amdmi3@amdmi3.ru>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <binfmt/Buffer.hh>

#include <binfmt/internal/ManagedChunk.hh>

#include <algorithm>

namespace BinFmt {

Buffer::Buffer(std::shared_ptr<Internal::Chunk> chunk, size_t offset, size_t size) : chunk_(chunk), offset_(offset), size_(size) {
	size_t real_size = chunk_->GetSize();
	if (offset_ > real_size)
		offset_ = real_size;
	if (size_ > real_size - offset_)
		size_ = real_size - offset_;
}

Buffer::Buffer(size_t size) : chunk_(new Internal::ManagedChunk(size)), offset_(0), size_(size) {
}

Buffer::~Buffer() {
}

// Modifiers
void Buffer::Realloc(size_t size) {
	Internal::ManagedChunk* chunk = new Internal::ManagedChunk(0, size);
	chunk->Append(chunk_->GetData() + offset_, std::min(size, size_));
	chunk_.reset(chunk);
	offset_ = 0;
}

void Buffer::Reserve(size_t size) {
	ReserveGreedy(size, size);
}

void Buffer::ReserveGreedy(size_t needed, size_t desired) {
	// we'll not shrink
	if (needed < size_)
		needed = size_;
	if (desired < needed)
		desired = needed;

	// ensure chunk is appendable (slice ends where chunk used space ends, e.g.
	// there's no data possibly used by other slice we may override) and that
	// there's enough space
	if (offset_ + size_ != chunk_->GetSize() || needed > chunk_->GetCapacity() - offset_)
		Realloc(desired);
}

void Buffer::Append(Byte data) {
	Append(&data, 1);
}

void Buffer::Append(const Byte* data, size_t size) {
	ReserveGreedy(size_ + size, std::max(size_ + size, size_ * 2));
	chunk_->Append(data, size);
	size_ += size;
}

void Buffer::Append(const Byte* start, const Byte* end) {
	Append(start, end - start);
}

void Buffer::Append(const Slicable& data) {
	Buffer slice = data.GetSlice();
	Append(slice.GetData(), slice.GetSize());
}

// Pointer/size getters
Byte* Buffer::GetData() {
	return chunk_->GetData() + offset_;
}

const Byte* Buffer::GetData() const {
	return chunk_->GetData() + offset_;
}

size_t Buffer::GetSize() const {
	return size_;
}

size_t Buffer::GetCapacity() const {
	return chunk_->GetCapacity() - offset_;
}

// subslice
Buffer Buffer::GetSlice(size_t offset, size_t size) const {
	if (offset > size_)
		offset = size_;
	if (size > size_ - offset)
		size = size_ - offset;

	return Buffer(chunk_, offset_ + offset, size);
}

Byte Buffer::operator[](size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return *offptr;
}

uint8_t Buffer::GetU8(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return (uint8_t)*offptr;
}

int8_t Buffer::GetS8(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return (int8_t)*offptr;
}

uint16_t Buffer::GetU16LE(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return (uint16_t)(uint8_t)*(offptr)
		| ((uint16_t)(uint8_t)*(offptr + 1) << 8);
}

int16_t Buffer::GetS16LE(size_t offset) const {
	return (int16_t)GetU16LE(offset);
}

uint16_t Buffer::GetU16BE(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return ((uint16_t)(uint8_t)*(offptr) << 8)
		| (uint16_t)(uint8_t)*(offptr + 1);
}
int16_t Buffer::GetS16BE(size_t offset) const {
	return (int16_t)GetU16BE(offset);
}

uint32_t Buffer::GetU32LE(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return (uint32_t)(uint8_t)*(offptr)
		| ((uint32_t)(uint8_t)*(offptr + 1) << 8)
		| ((uint32_t)(uint8_t)*(offptr + 2) << 16)
		| ((uint32_t)(uint8_t)*(offptr + 3) << 24);
}

int32_t Buffer::GetS32LE(size_t offset) const {
	return (int32_t)GetU32LE(offset);
}

uint32_t Buffer::GetU32BE(size_t offset) const {
	const Byte* offptr = chunk_->GetData() + offset_ + offset;
	return ((uint32_t)(uint8_t)*(offptr) << 24)
		| ((uint32_t)(uint8_t)*(offptr + 1) << 16)
		| ((uint32_t)(uint8_t)*(offptr + 2) << 8)
		| (uint32_t)(uint8_t)*(offptr + 3);
}

int32_t Buffer::GetS32BE(size_t offset) const {
	return (int32_t)GetU32BE(offset);
}

std::string Buffer::GetString(size_t offset, size_t length) const {
	if (offset > size_)
		offset = size_;
	if (length > size_ - offset)
		length = size_ - offset;
	const Byte* start = chunk_->GetData() + offset_ + offset;
	const Byte* zeropos = std::find(start, start + length, (Byte)0);
	if (zeropos != start + length)
		length = zeropos - start;
	return std::string(reinterpret_cast<const char*>(start), length);
}

}
<|endoftext|>


<commit_before>
#include <sys/stat.h>
#include <iostream>
#include <string>
using namespace std;

#include "config.h"

#include "mds/MDCluster.h"
#include "mds/MDS.h"
#include "osd/OSD.h"
#include "client/Client.h"
#include "client/SyntheticClient.h"

#include "msg/TCPMessenger.h"

#include "common/Timer.h"

#define NUMMDS g_conf.num_mds
#define NUMOSD g_conf.num_osd
#define NUMCLIENT g_conf.num_client

class C_Test : public Context {
public:
  void finish(int r) {
	cout << "C_Test->finish(" << r << ")" << endl;
  }
};

#include "msg/mpistarter.cc"

utime_t tick_start;

class C_Tick : public Context {
public:
  void finish(int) {
	utime_t now = g_clock.now() - tick_start;
	dout(0) << "tick +" << g_conf.tick << " -> " << now << endl;
	g_timer.add_event_after(g_conf.tick, new C_Tick);
  }
};

class C_Die : public Context {
public:
  void finish(int) {
	cerr << "die" << endl;
	exit(1);
  }
};

class C_Debug : public Context {
  public:
  void finish(int) {
	int size = &g_conf.debug_after - &g_conf.debug;
	memcpy((char*)&g_conf.debug, (char*)&g_debug_after_conf.debug, size);
	dout(0) << "debug_after flipping debug settings" << endl;
  }
};

int main(int argc, char **argv)
{
  vector<char*> args;
  argv_to_vec(argc, argv, args);

  parse_config_options(args);

  parse_syn_options(args);

  if (g_conf.kill_after)
	g_timer.add_event_after(g_conf.kill_after, new C_Die);
  if (g_conf.debug_after)
	g_timer.add_event_after(g_conf.debug_after, new C_Debug);

  if (g_conf.tick) {
	tick_start = g_clock.now();
	g_timer.add_event_after(g_conf.tick, new C_Tick);
  }

  vector<char*> nargs;
  for (unsigned i=0; i<args.size(); i++) {
	//cout << "a " << args[i] << endl;
	// unknown arg, pass it on.
	nargs.push_back(args[i]);
  }

  args = nargs;
  if (!args.empty()) {
	for (unsigned i=0; i<args.size(); i++)
	  cout << "stray arg " << args[i] << endl;
  }
  assert(args.empty());

  // start up tcp messenger via MPI
  pair<int,int> mpiwho = mpi_bootstrap_tcp(argc, argv);
  int myrank = mpiwho.first;
  int world = mpiwho.second;

  if (myrank == 0)
	cerr << "nummds " << NUMMDS << "  numosd " << NUMOSD << "  numclient " << NUMCLIENT << endl;
  assert(NUMMDS + NUMOSD + (NUMCLIENT?1:0) <= world);

  MDCluster *mdc = new MDCluster(NUMMDS, NUMOSD);

  char hostname[100];
  gethostname(hostname,100);
  int pid = getpid();

  int started = 0;

  //if (myrank == 0) g_conf.debug = 20;

  // create mds
  MDS *mds[NUMMDS];
  for (int i=0; i<NUMMDS; i++) {
	if (myrank != g_conf.tcp_skip_rank0+i) continue;
	TCPMessenger *m = new TCPMessenger(MSG_ADDR_MDS(i));
	cerr << "mds" << i << " on tcprank " << tcpmessenger_get_rank() << " " << hostname << "." << pid << endl;
	mds[i] = new MDS(mdc, i, m);
	mds[i]->init();
	started++;
  }

  // create osd
  OSD *osd[NUMOSD];
  for (int i=0; i<NUMOSD; i++) {
	if (myrank != g_conf.tcp_skip_rank0+NUMMDS + i) continue;
	TCPMessenger *m = new TCPMessenger(MSG_ADDR_OSD(i));
	cerr << "osd" << i << " on tcprank " << tcpmessenger_get_rank() <<  " " << hostname << "." << pid << endl;
	osd[i] = new OSD(i, m);
	osd[i]->init();
	started++;
  }

  // create client
  int client_nodes = world - NUMMDS - NUMOSD - g_conf.tcp_skip_rank0;
  int clients_per_node = 1;
  if (NUMCLIENT) clients_per_node = (NUMCLIENT-1) / client_nodes + 1;
  set<int> clientlist;
  Client *client[NUMCLIENT];
  SyntheticClient *syn[NUMCLIENT];
  for (int i=0; i<NUMCLIENT; i++) {
	//if (myrank != NUMMDS + NUMOSD + i % client_nodes) continue;
	if (myrank != g_conf.tcp_skip_rank0+NUMMDS + NUMOSD + i / clients_per_node) continue;
	clientlist.insert(i);
	client[i] = new Client(new TCPMessenger(MSG_ADDR_CLIENT(i)) );

	// logger?
	if (client_logger == 0) {
	  char s[80];
	  sprintf(s,"clnode.%d", myrank);
	  client_logger = new Logger(s, &client_logtype);

	  client_logtype.add_inc("lsum");
	  client_logtype.add_inc("lnum");
	  client_logtype.add_inc("lwsum");
	  client_logtype.add_inc("lwnum");
	  client_logtype.add_inc("lrsum");
	  client_logtype.add_inc("lrnum");
	  client_logtype.add_inc("trsum");
	  client_logtype.add_inc("trnum");
	}

	client[i]->init();
	started++;
  }

  int nclients = 0;
  for (set<int>::iterator it = clientlist.begin();
	   it != clientlist.end();
	   it++) {
	int i = *it;

	client[i]->mount();

	//cout << "starting synthetic client on rank " << myrank << endl;
	syn[i] = new SyntheticClient(client[i]);

	syn[i]->start_thread();

	nclients++;
  }
  if (nclients) {
	cerr << nclients << " clients on tcprank " << tcpmessenger_get_rank() << " " << hostname << "." << pid << endl;
  }

  for (set<int>::iterator it = clientlist.begin();
	   it != clientlist.end();
	   it++) {
	int i = *it;

	//	  cout << "waiting for synthetic client" << i << " to finish" << endl;
	syn[i]->join_thread();
	delete syn[i];

	client[i]->unmount();
	//cout << "client" << i << " unmounted" << endl;
	client[i]->shutdown();
  }

  if (myrank && !started) {
	//dout(1) << "IDLE" << endl;
	cerr << "idle on tcprank " << tcpmessenger_get_rank() << " " << hostname << "." << pid << endl;
	tcpmessenger_stop_rankserver();
  }

  // wait for everything to finish
  tcpmessenger_wait();

  if (started) cerr << "tcpsyn finishing" << endl;

  tcpmessenger_shutdown();

  /*
  // cleanup
  for (int i=0; i<NUMMDS; i++) {
	if (myrank != MPI_DEST_TO_RANK(MSG_ADDR_MDS(i),world)) continue;
	delete mds[i];
  }
  for (int i=0; i<NUMOSD; i++) {
	if (myrank != MPI_DEST_TO_RANK(MSG_ADDR_OSD(i),world)) continue;
	delete osd[i];
  }
  for (int i=0; i<NUMCLIENT; i++) {
	if (myrank != MPI_DEST_TO_RANK(MSG_ADDR_CLIENT(i),world)) continue;
	delete client[i];
  }
  */
  delete mdc;

  return 0;
}

<commit_msg>*** empty log message ***<commit_after>
#include <sys/stat.h>
#include <iostream>
#include <string>
using namespace std;

#include "config.h"

#include "mds/MDCluster.h"
#include "mds/MDS.h"
#include "osd/OSD.h"
#include "client/Client.h"
#include "client/SyntheticClient.h"

#include "msg/TCPMessenger.h"

#include "common/Timer.h"

#define NUMMDS g_conf.num_mds
#define NUMOSD g_conf.num_osd
#define NUMCLIENT g_conf.num_client

class C_Test : public Context {
public:
  void finish(int r) {
	cout << "C_Test->finish(" << r << ")" << endl;
  }
};

#include "msg/mpistarter.cc"

utime_t tick_start;
int tick_count = 0;

class C_Tick : public Context {
public:
  void finish(int) {
	utime_t now = g_clock.now() - tick_start;
	dout(0) << "tick +" << g_conf.tick << " -> " << now << "  (" << tick_count << ")" << endl;
	tick_count += g_conf.tick;
	utime_t next = tick_start;
	next.sec_ref() += tick_count;
	g_timer.add_event_at(next, new C_Tick);
  }
};

class C_Die : public Context {
public:
  void finish(int) {
	cerr << "die" << endl;
	exit(1);
  }
};

class C_Debug : public Context {
  public:
  void finish(int) {
	int size = &g_conf.debug_after - &g_conf.debug;
	memcpy((char*)&g_conf.debug, (char*)&g_debug_after_conf.debug, size);
	dout(0) << "debug_after flipping debug settings" << endl;
  }
};

int main(int argc, char **argv)
{
  vector<char*> args;
  argv_to_vec(argc, argv, args);

  parse_config_options(args);

  parse_syn_options(args);

  if (g_conf.kill_after)
	g_timer.add_event_after(g_conf.kill_after, new C_Die);
  if (g_conf.debug_after)
	g_timer.add_event_after(g_conf.debug_after, new C_Debug);

  if (g_conf.tick) {
	tick_start = g_clock.now();
	g_timer.add_event_after(g_conf.tick, new C_Tick);
  }

  vector<char*> nargs;
  for (unsigned i=0; i<args.size(); i++) {
	//cout << "a " << args[i] << endl;
	// unknown arg, pass it on.
	nargs.push_back(args[i]);
  }

  args = nargs;
  if (!args.empty()) {
	for (unsigned i=0; i<args.size(); i++)
	  cout << "stray arg " << args[i] << endl;
  }
  assert(args.empty());

  // start up tcp messenger via MPI
  pair<int,int> mpiwho = mpi_bootstrap_tcp(argc, argv);
  int myrank = mpiwho.first;
  int world = mpiwho.second;

  if (myrank == 0)
	cerr << "nummds " << NUMMDS << "  numosd " << NUMOSD << "  numclient " << NUMCLIENT << endl;
  assert(NUMMDS + NUMOSD + (NUMCLIENT?1:0) <= world);

  MDCluster *mdc = new MDCluster(NUMMDS, NUMOSD);

  char hostname[100];
  gethostname(hostname,100);
  int pid = getpid();

  int started = 0;

  //if (myrank == 0) g_conf.debug = 20;

  // create mds
  MDS *mds[NUMMDS];
  for (int i=0; i<NUMMDS; i++) {
	if (myrank != g_conf.tcp_skip_rank0+i) continue;
	TCPMessenger *m = new TCPMessenger(MSG_ADDR_MDS(i));
	cerr << "mds" << i << " on tcprank " << tcpmessenger_get_rank() << " " << hostname << "." << pid << endl;
	mds[i] = new MDS(mdc, i, m);
	mds[i]->init();
	started++;
  }

  // create osd
  OSD *osd[NUMOSD];
  for (int i=0; i<NUMOSD; i++) {
	if (myrank != g_conf.tcp_skip_rank0+NUMMDS + i) continue;
	TCPMessenger *m = new TCPMessenger(MSG_ADDR_OSD(i));
	cerr << "osd" << i << " on tcprank " << tcpmessenger_get_rank() <<  " " << hostname << "." << pid << endl;
	osd[i] = new OSD(i, m);
	osd[i]->init();
	started++;
  }

  // create client
  int client_nodes = world - NUMMDS - NUMOSD - g_conf.tcp_skip_rank0;
  int clients_per_node = 1;
  if (NUMCLIENT) clients_per_node = (NUMCLIENT-1) / client_nodes + 1;
  set<int> clientlist;
  Client *client[NUMCLIENT];
  SyntheticClient *syn[NUMCLIENT];
  for (int i=0; i<NUMCLIENT; i++) {
	//if (myrank != NUMMDS + NUMOSD + i % client_nodes) continue;
	if (myrank != g_conf.tcp_skip_rank0+NUMMDS + NUMOSD + i / clients_per_node) continue;
	clientlist.insert(i);
	client[i] = new Client(new TCPMessenger(MSG_ADDR_CLIENT(i)) );

	// logger?
	if (client_logger == 0) {
	  char s[80];
	  sprintf(s,"clnode.%d", myrank);
	  client_logger = new Logger(s, &client_logtype);

	  client_logtype.add_inc("lsum");
	  client_logtype.add_inc("lnum");
	  client_logtype.add_inc("lwsum");
	  client_logtype.add_inc("lwnum");
	  client_logtype.add_inc("lrsum");
	  client_logtype.add_inc("lrnum");
	  client_logtype.add_inc("trsum");
	  client_logtype.add_inc("trnum");
	}

	client[i]->init();
	started++;
  }

  int nclients = 0;
  for (set<int>::iterator it = clientlist.begin();
	   it != clientlist.end();
	   it++) {
	int i = *it;

	client[i]->mount();

	//cout << "starting synthetic client on rank " << myrank << endl;
	syn[i] = new SyntheticClient(client[i]);

	syn[i]->start_thread();

	nclients++;
  }
  if (nclients) {
	cerr << nclients << " clients on tcprank " << tcpmessenger_get_rank() << " " << hostname << "." << pid << endl;
  }

  for (set<int>::iterator it = clientlist.begin();
	   it != clientlist.end();
	   it++) {
	int i = *it;

	//	  cout << "waiting for synthetic client" << i << " to finish" << endl;
	syn[i]->join_thread();
	delete syn[i];

	client[i]->unmount();
	//cout << "client" << i << " unmounted" << endl;
	client[i]->shutdown();
  }

  if (myrank && !started) {
	//dout(1) << "IDLE" << endl;
	cerr << "idle on tcprank " << tcpmessenger_get_rank() << " " << hostname << "." << pid << endl;
	tcpmessenger_stop_rankserver();
  }

  // wait for everything to finish
  tcpmessenger_wait();

  if (started) cerr << "tcpsyn finishing" << endl;

  tcpmessenger_shutdown();

  /*
  // cleanup
  for (int i=0; i<NUMMDS; i++) {
	if (myrank != MPI_DEST_TO_RANK(MSG_ADDR_MDS(i),world)) continue;
	delete mds[i];
  }
  for (int i=0; i<NUMOSD; i++) {
	if (myrank != MPI_DEST_TO_RANK(MSG_ADDR_OSD(i),world)) continue;
	delete osd[i];
  }
  for (int i=0; i<NUMCLIENT; i++) {
	if (myrank != MPI_DEST_TO_RANK(MSG_ADDR_CLIENT(i),world)) continue;
	delete client[i];
  }
  */
  delete mdc;

  return 0;
}

<|endoftext|>


<commit_before>/*
 * VapourSynth D2V Plugin
 *
 * Copyright (c) 2012 Derek Buitenhuis
 *
 * This file is part of d2vsource.
 *
 * d2vsource 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.
 *
 * d2vsource 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 d2vsource; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

extern "C" {
#include <stdint.h>
#include <stdlib.h>
}

#include <algorithm>

#include <VapourSynth.h>
#include <VSHelper.h>

#include "applyrff.hpp"
#include "d2v.hpp"
#include "gop.hpp"

void VS_CC rffInit(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi)
{
    rffData *d = (rffData *) *instanceData;
    vsapi->setVideoInfo(&d->vi, 1, node);
}

const VSFrameRef *VS_CC rffGetFrame(int n, int activationReason, void **instanceData, void **frameData,
                                    VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi)
{
    const rffData *d = (const rffData *) *instanceData;
    const VSFrameRef *st, *sb;
    VSFrameRef *f;
    string msg;
    int top, bottom;
    int i;
    bool samefields;

    /* What frames to use for fields. */
    top    = d->frames[n].top;
    bottom = d->frames[n].bottom;

    samefields = top == bottom;

    /* Request out source frames. */
    if (activationReason == arInitial) {
        if (samefields) {
            vsapi->requestFrameFilter(top, d->node, frameCtx);
        } else {
            vsapi->requestFrameFilter(min(top, bottom), d->node, frameCtx);
            vsapi->requestFrameFilter(max(top, bottom), d->node, frameCtx);
        }
        return NULL;
    }

    /* Check if we're ready yet. */
    if (activationReason != arAllFramesReady)
        return NULL;

    /* Source and destination frames. */
    st = vsapi->getFrameFilter(top, d->node, frameCtx);
    sb = samefields ? NULL : vsapi->getFrameFilter(bottom, d->node, frameCtx);

    /* Copy into VS's buffers. */
    if (samefields) {
        f = vsapi->copyFrame(st, core);
    } else {
        int dst_stride[3], srct_stride[3], srcb_stride[3];

        f  = vsapi->newVideoFrame(d->vi.format, d->vi.width, d->vi.height, NULL, core);

        for (i = 0; i < d->vi.format->numPlanes; i++) {
            dst_stride[i]  = vsapi->getStride(f, i);
            srct_stride[i] = vsapi->getStride(st, i);
            srcb_stride[i] = vsapi->getStride(sb, i);

            uint8_t *dstp = vsapi->getWritePtr(f, i);
            const uint8_t *srctp = vsapi->getReadPtr(st, i);
            const uint8_t *srcbp = vsapi->getReadPtr(sb, i);
            int width = vsapi->getFrameWidth(f, i);
            int height = vsapi->getFrameHeight(f, i);

            vs_bitblt(dstp, dst_stride[i] * 2,
                      srctp, srct_stride[i] * 2,
                      width * d->vi.format->bytesPerSample, height / 2);

            vs_bitblt(dstp + dst_stride[i], dst_stride[i] * 2,
                      srcbp + srcb_stride[i], srcb_stride[i] * 2,
                      width * d->vi.format->bytesPerSample, height / 2);
        }
    }

    /*
     * Set progressive/interlaced flag.
     *
     * This assumes the d2v has been properly run through d2vfix,
     * so that there is only one field order.
     *
     * This is probably wildly wrong. I hope nothign relies on this.
     */
    if (samefields) {
        VSMap *props = vsapi->getFramePropsRW(f);
        frame top_f = d->d2v->frames[top];

        vsapi->propSetInt(props, "_FieldBased",
                          1 + !!(d->d2v->gops[top_f.gop].flags[top_f.offset] & FRAME_FLAG_TFF), paReplace);
    }

    vsapi->freeFrame(st);
    if (!samefields)
        vsapi->freeFrame(sb);

    return f;
}

void VS_CC rffFree(void *instanceData, VSCore *core, const VSAPI *vsapi)
{
    rffData *d = (rffData *) instanceData;
    vsapi->freeNode(d->node);
    d2vfreep(&d->d2v);
    d->frames.clear();
    delete d;
}

void VS_CC rffCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi)
{
    rffData *data;
    fieldFrame ff = { -1, -1 };
    string msg;
    int total_fields;
    int i;

    /* Allocate our private data. */
    data = new(nothrow) rffData;
    if (!data) {
        vsapi->setError(out, "Cannot allocate private data.");
        return;
    }

    /* Parse the D2V to get flags. */
    data->d2v = d2vparse((char *) vsapi->propGetData(in, "d2v", 0, 0), msg);
    if (!data->d2v) {
        vsapi->setError(out, msg.c_str());
        delete data;
        return;
    }

    /* Get our frame info and copy it, so we can modify it after. */
    data->node = vsapi->propGetNode(in, "clip", 0, 0);
    data->vi   = *vsapi->getVideoInfo(data->node);

    /*
     * Parse all the RFF flags to figure out which fields go
     * with which frames, and out total number of frames after
     * apply the RFF flags.
     */
    total_fields = 0;
    data->frames.push_back(ff);
    for(i = 0; i < data->vi.numFrames; i++) {
        frame f = data->d2v->frames[i];
        int rff = data->d2v->gops[f.gop].flags[f.offset] & FRAME_FLAG_RFF;
        int pos = data->frames.size() - 1;

        if (rff) {
            if (data->frames[pos].top == -1) {
                data->frames[pos].top    = i;
                data->frames[pos].bottom = i;

                ff.top    = i;
                ff.bottom = -1;
            } else if (data->frames[pos].bottom == -1) {
                data->frames[pos].bottom = i;

                ff.top    = i;
                ff.bottom = i;
            } else {
                ff.top    = i;
                ff.bottom = i;

                data->frames.push_back(ff);

                ff.bottom = -1;
            }
        } else {
            if (data->frames[pos].top == -1) {
                data->frames[pos].top    = i;
                data->frames[pos].bottom = i;

                ff.top    = -1;
                ff.bottom = -1;
            } else if (data->frames[pos].bottom == -1) {
                data->frames[pos].bottom = i;

                ff.top    = i;
                ff.bottom = -1;
            } else {
                ff.top    = i;
                ff.bottom = i;
            }
        }
        data->frames.push_back(ff);

        total_fields += 2 + rff;
    }

    data->vi.numFrames = total_fields / 2;

    vsapi->createFilter(in, out, "applyrff", rffInit, rffGetFrame, rffFree, fmParallel, nfMakeLinear, data, core);
}
<commit_msg>applyrff: Correctly handle bottom field first streams<commit_after>/*
 * VapourSynth D2V Plugin
 *
 * Copyright (c) 2012 Derek Buitenhuis
 *
 * This file is part of d2vsource.
 *
 * d2vsource 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.
 *
 * d2vsource 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 d2vsource; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

extern "C" {
#include <stdint.h>
#include <stdlib.h>
}

#include <algorithm>

#include <VapourSynth.h>
#include <VSHelper.h>

#include "applyrff.hpp"
#include "d2v.hpp"
#include "gop.hpp"

void VS_CC rffInit(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi)
{
    rffData *d = (rffData *) *instanceData;
    vsapi->setVideoInfo(&d->vi, 1, node);
}

const VSFrameRef *VS_CC rffGetFrame(int n, int activationReason, void **instanceData, void **frameData,
                                    VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi)
{
    const rffData *d = (const rffData *) *instanceData;
    const VSFrameRef *st, *sb;
    VSFrameRef *f;
    string msg;
    int top, bottom;
    int i;
    bool samefields;

    /* What frames to use for fields. */
    top    = d->frames[n].top;
    bottom = d->frames[n].bottom;

    samefields = top == bottom;

    /* Request out source frames. */
    if (activationReason == arInitial) {
        if (samefields) {
            vsapi->requestFrameFilter(top, d->node, frameCtx);
        } else {
            vsapi->requestFrameFilter(min(top, bottom), d->node, frameCtx);
            vsapi->requestFrameFilter(max(top, bottom), d->node, frameCtx);
        }
        return NULL;
    }

    /* Check if we're ready yet. */
    if (activationReason != arAllFramesReady)
        return NULL;

    /* Source and destination frames. */
    st = vsapi->getFrameFilter(top, d->node, frameCtx);
    sb = samefields ? NULL : vsapi->getFrameFilter(bottom, d->node, frameCtx);

    /* Copy into VS's buffers. */
    if (samefields) {
        f = vsapi->copyFrame(st, core);
    } else {
        int dst_stride[3], srct_stride[3], srcb_stride[3];

        f  = vsapi->newVideoFrame(d->vi.format, d->vi.width, d->vi.height, NULL, core);

        for (i = 0; i < d->vi.format->numPlanes; i++) {
            dst_stride[i]  = vsapi->getStride(f, i);
            srct_stride[i] = vsapi->getStride(st, i);
            srcb_stride[i] = vsapi->getStride(sb, i);

            uint8_t *dstp = vsapi->getWritePtr(f, i);
            const uint8_t *srctp = vsapi->getReadPtr(st, i);
            const uint8_t *srcbp = vsapi->getReadPtr(sb, i);
            int width = vsapi->getFrameWidth(f, i);
            int height = vsapi->getFrameHeight(f, i);

            vs_bitblt(dstp, dst_stride[i] * 2,
                      srctp, srct_stride[i] * 2,
                      width * d->vi.format->bytesPerSample, height / 2);

            vs_bitblt(dstp + dst_stride[i], dst_stride[i] * 2,
                      srcbp + srcb_stride[i], srcb_stride[i] * 2,
                      width * d->vi.format->bytesPerSample, height / 2);
        }
    }

    /*
     * Set progressive/interlaced flag.
     *
     * This assumes the d2v has been properly run through d2vfix,
     * so that there is only one field order.
     *
     * This is probably wildly wrong. I hope nothign relies on this.
     */
    if (samefields) {
        VSMap *props = vsapi->getFramePropsRW(f);
        frame top_f = d->d2v->frames[top];

        vsapi->propSetInt(props, "_FieldBased",
                          1 + !!(d->d2v->gops[top_f.gop].flags[top_f.offset] & FRAME_FLAG_TFF), paReplace);
    }

    vsapi->freeFrame(st);
    if (!samefields)
        vsapi->freeFrame(sb);

    return f;
}

void VS_CC rffFree(void *instanceData, VSCore *core, const VSAPI *vsapi)
{
    rffData *d = (rffData *) instanceData;
    vsapi->freeNode(d->node);
    d2vfreep(&d->d2v);
    d->frames.clear();
    delete d;
}

void VS_CC rffCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi)
{
    rffData *data;
    fieldFrame ff = { -1, -1 };
    string msg;
    int total_fields;
    int i;

    /* Allocate our private data. */
    data = new(nothrow) rffData;
    if (!data) {
        vsapi->setError(out, "Cannot allocate private data.");
        return;
    }

    /* Parse the D2V to get flags. */
    data->d2v = d2vparse((char *) vsapi->propGetData(in, "d2v", 0, 0), msg);
    if (!data->d2v) {
        vsapi->setError(out, msg.c_str());
        delete data;
        return;
    }

    /* Get our frame info and copy it, so we can modify it after. */
    data->node = vsapi->propGetNode(in, "clip", 0, 0);
    data->vi   = *vsapi->getVideoInfo(data->node);

    /*
     * Parse all the RFF flags to figure out which fields go
     * with which frames, and out total number of frames after
     * apply the RFF flags.
     */
    total_fields = 0;
    data->frames.push_back(ff);
    for(i = 0; i < data->vi.numFrames; i++) {
        frame f = data->d2v->frames[i];
        int rff = data->d2v->gops[f.gop].flags[f.offset] & FRAME_FLAG_RFF;
        int tff = data->d2v->gops[f.gop].flags[f.offset] & FRAME_FLAG_TFF;
        int pos = data->frames.size() - 1;

        int *pos_first, *pos_second, *ff_first, *ff_second;
        if (tff) {
            pos_first = &data->frames[pos].top;
            pos_second = &data->frames[pos].bottom;
            ff_first = &ff.top;
            ff_second = &ff.bottom;
        } else {
            pos_first = &data->frames[pos].bottom;
            pos_second = &data->frames[pos].top;
            ff_first = &ff.bottom;
            ff_second = &ff.top;
        }

        if (rff) {
            if (*pos_first == -1) {
                *pos_first  = i;
                *pos_second = i;

                *ff_first  = i;
                *ff_second = -1;
            } else if (*pos_second == -1) {
                *pos_second = i;

                *ff_first  = i;
                *ff_second = i;
            } else {
                *ff_first  = i;
                *ff_second = i;

                data->frames.push_back(ff);

                *ff_second = -1;
            }
        } else {
            if (*pos_first == -1) {
                *pos_first  = i;
                *pos_second = i;

                *ff_first  = -1;
                *ff_second = -1;
            } else if (*pos_second == -1) {
                *pos_second = i;

                *ff_first  = i;
                *ff_second = -1;
            } else {
                *ff_first  = i;
                *ff_second = i;
            }
        }
        data->frames.push_back(ff);

        total_fields += 2 + rff;
    }

    data->vi.numFrames = total_fields / 2;

    vsapi->createFilter(in, out, "applyrff", rffInit, rffGetFrame, rffFree, fmParallel, nfMakeLinear, data, core);
}
<|endoftext|>


<commit_before>//*****************************************************
//
// Dialog which report the earning made with stake over time
// Original coding by Remy5
//

#include "stakereportdialog.h"
#include "ui_stakereportdialog.h"

#include "guiconstants.h"
#include "walletmodel.h"
#include "sequenceunits.h"
#include "rpc/rpcserver.h"
#include "optionsmodel.h"
#include "main.h"
#include "chain.h"
#include "util.h"

#include "wallet/wallet.h"
#include "wallet/walletdb.h"

#include <QWidget>
#include <QDateTime>
#include <QTimer>
#include <QClipboard>

// using namespace json_spirit;
using namespace boost;
using namespace std;

struct StakePeriodRange_T {
    int64_t Start;
    int64_t End;
    int64_t Total;
    int Count;
    string Name;
};

typedef vector<StakePeriodRange_T> vStakePeriodRange_T;

extern vStakePeriodRange_T PrepareRangeForStakeReport();
extern int GetStakeSubTotal(vStakePeriodRange_T& aRange, const isminefilter filter);

StakeReportDialog::StakeReportDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::StakeReportDialog)
{
    ui->setupUi(this);

    QTableWidget *TableW = ui->StakeReportTable;

    alreadyConnected = false;

    // fill the table with clone of row 0
    for(int y=TableW->rowCount(); --y >= 1;)
        for(int x=TableW->columnCount(); --x >= 0;)
            TableW->setItem(y, x,
                TableW->item(0, x)->clone());

    TableW->horizontalHeader()->resizeSection(1,160);

    QApplication::processEvents();

    updateStakeReportNow();  // 1st update
}

StakeReportDialog::~StakeReportDialog()
{
    delete ui;
}

void StakeReportDialog::setModel(WalletModel *model)
{
    this->ex_model = model;

    if(ex_model && ex_model->getOptionsModel() && !alreadyConnected)
    {
        alreadyConnected = true;

        connect(ex_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit(int)));
        connect(ui->button_Refresh, SIGNAL(clicked()), this, SLOT(updateStakeReportNow()));
        connect(ui->CopytoClipboard, SIGNAL(clicked()), this, SLOT(CopyAllToClipboard()));

        disablereportupdate = GetBoolArg("-disablereportupdate", false);

        if (!disablereportupdate)
        {
            QTimer *timer = new QTimer(this);
            connect(timer, SIGNAL(timeout()), this, SLOT(updateStakeReportTimer()));
         	connect(ex_model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(updateStakeReportbalanceChanged(qint64, qint64, qint64, qint64)));

            timer->start(MODEL_UPDATE_DELAY*5);
        }
    }
}

void StakeReportDialog::updateStakeReportbalanceChanged(qint64, qint64, qint64, qint64)
{
    StakeReportDialog::updateStakeReportNow();
}

void StakeReportDialog::updateDisplayUnit(int)
{
    StakeReportDialog::updateStakeReportNow();
}

void StakeReportDialog::updateStakeReportTimer()
{
    static int lastBest = 0 ;
    if (lastBest != chainActive.Height())
    {
        lastBest = chainActive.Height();
        StakeReportDialog::updateStakeReport(false);
    }
}

void StakeReportDialog::showEvent( QShowEvent* event )
{
    QWidget::showEvent( event );
    StakeReportDialog::updateStakeReportNow();
}

// Extendable localtime format
QString HalfDate(int64_t nTime, QString TimeMode="")
{
    QDateTime OrigDate = QDateTime::fromTime_t((qint32)nTime);
    QString LocalDate = OrigDate.date().toString("yyyy-MM-dd");
    if (TimeMode != "")
        LocalDate += " " + OrigDate.toString(TimeMode);

    return LocalDate;
}

// format Sequencevalue with all trailing zero
QString Coin_0Pad(int nUnit, int64_t amount)
{
    QString result = SequenceUnits::format(nUnit, amount);

    int poin = result.indexOf(".") + 1;
    poin += SequenceUnits::decimals(nUnit);

    return result.leftJustified(poin, '0');
}

void StakeReportDialog::updateStakeReportNow()
{
    updateStakeReport(true);
}

void StakeReportDialog::updateStakeReport(bool fImmediate=false)
{
    static vStakePeriodRange_T aRange;
    int nItemCounted=0;

    if (fImmediate) nLastReportUpdate = 0;

    if (this->isHidden())
        return;

    int64_t nTook = GetTimeMillis();

    // Skip report recalc if not immediate or before 5 minutes from last
    if (GetTime() - nLastReportUpdate > 300)
    {
        QApplication::processEvents();

        ui->TimeTook->setText(tr("Please wait..."));
        ui->TimeTook->repaint();
        QApplication::processEvents();

        aRange = PrepareRangeForStakeReport();

        // get subtotal calc
        nItemCounted = GetStakeSubTotal(aRange, ISMINE_SPENDABLE);

        nLastReportUpdate = GetTime();

        nTook = GetTimeMillis() - nTook;

    }

    int64_t nTook2 = GetTimeMillis();

    // actually update labels
    int nDisplayUnit = SequenceUnits::SEQ;
    if (ex_model && ex_model->getOptionsModel())
         nDisplayUnit = ex_model->getOptionsModel()->getDisplayUnit();

    ui->L_Coin->setText(SequenceUnits::name(nDisplayUnit) + " " + tr("SubTotal"));

    QTableWidget *TableW = ui->StakeReportTable;

    TableW->horizontalHeaderItem(1)->setText(SequenceUnits::name(nDisplayUnit) + " " +tr("Amount"));

    int i=30;

    TableW->setSortingEnabled(false);
    for(int y=0; y<i; y++)
    {
       TableW->item(y,0)->setText(HalfDate(aRange[y].Start));
       TableW->item(y,1)->setText(Coin_0Pad(nDisplayUnit, aRange[y].Total));
       TableW->item(y,2)->setText(QString::number(aRange[y].Count));
    }
    TableW->setSortingEnabled(true);

    ui->Amount_24H->setText(Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" DYN"));
    ui->Stake_24H->setText(QString::number(aRange[i++].Count));
    ui->Amount_7D->setText(Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" DYN"));
    ui->Stake_7D->setText(QString::number(aRange[i++].Count));
    ui->Amount_30D->setText(Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" DYN"));
    ui->Stake_30D->setText(QString::number(aRange[i++].Count));
    ui->Amount_365D->setText(Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" DYN"));
    ui->Stake_365D->setText(QString::number(aRange[i++].Count));

    ui->Amount_Last->setText(tr("Amount: ") + Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" DYN"));
    ui->L_LastStakeTime->setText(tr("Latest stake date: ") + HalfDate(aRange[i].Start, "hh:mm"));

    ui->Stake_Counted->setText(tr("Stakes analysed: ") + QString::number(nItemCounted));
    if (nItemCounted)
        ui->TimeTook->setText(tr("Last Recalc took ") + QString::number(nTook) +  "ms");

    ui->TimeTook_2->setText(tr("Refresh took ") + QString::number(GetTimeMillis() -nTook2) +  "ms");

    string sRefreshType = disablereportupdate ? "Manual refresh" : "Auto refresh";

    string strCurr_block_info = strprintf("%s  -  %s : %6d @ %s\nhash %s\n",
           sRefreshType.c_str(), "Current Block", chainActive.Height(),
           HalfDate((chainActive.Tip()->GetMedianTimePast()+1), "hh:mm:ss").toStdString().c_str(),
           chainActive.Tip()->GetBlockHash().ToString());

    ui->L_CurrentBlock->setText(strCurr_block_info.c_str() );

}

QString GridGetLabelTextAt(QGridLayout * Grid, int row, int column, QString Empty = "")
{
    if (Grid && Grid->itemAtPosition(row, column) &&
            Grid->itemAtPosition(row, column)->widget())
        return ((QLabel *) Grid->itemAtPosition(row, column)->widget())->text();
    else
        return Empty;
}

void StakeReportDialog::CopyAllToClipboard()
{
    QString Repo;

    Repo += "           Sequence Stake Mini Report\n";
    Repo += "           ----------------------\n";

    QString  RowForm = "%1 %2 %3\n";

    for(int y=0; y<ui->gridLayout->rowCount(); y++)
    {
        if (y == 5)
            Repo += "\n"; //  separator line
        else
            Repo += RowForm
                .arg(GridGetLabelTextAt(ui->gridLayout, y,0), -16)
                .arg(GridGetLabelTextAt(ui->gridLayout, y,1), 16)
                .arg(GridGetLabelTextAt(ui->gridLayout, y,2), 7);
    }

    Repo += "\n";

    QTableWidget *TableW = ui->StakeReportTable;
    RowForm = "%1, %2, %3\n";

    Repo += RowForm
        .arg(TableW->horizontalHeaderItem(0)->text(), -10)
        .arg(TableW->horizontalHeaderItem(1)->text(), 16)
        .arg(TableW->horizontalHeaderItem(2)->text(), 7);

    for(int y=0; y<30; y++)
    {
        Repo += RowForm
            .arg(TableW->item(y,0)->text(), -10)
            .arg(TableW->item(y,1)->text(), 16)
            .arg(TableW->item(y,2)->text(), 7);
    }

    Repo += "\n" + ui->L_CurrentBlock->text() + "\n";

    QApplication::clipboard()->setText(Repo);

}<commit_msg>Amend<commit_after>//*****************************************************
//
// Dialog which report the earning made with stake over time
// Original coding by Remy5
//

#include "stakereportdialog.h"
#include "ui_rpcconsole.h"

#include "guiconstants.h"
#include "walletmodel.h"
#include "sequenceunits.h"
#include "rpc/rpcserver.h"
#include "optionsmodel.h"
#include "main.h"
#include "chain.h"
#include "util.h"

#include "wallet/wallet.h"
#include "wallet/walletdb.h"

#include <QWidget>
#include <QDateTime>
#include <QTimer>
#include <QClipboard>

// using namespace json_spirit;
using namespace boost;
using namespace std;

struct StakePeriodRange_T {
    int64_t Start;
    int64_t End;
    int64_t Total;
    int Count;
    string Name;
};

typedef vector<StakePeriodRange_T> vStakePeriodRange_T;

extern vStakePeriodRange_T PrepareRangeForStakeReport();
extern int GetStakeSubTotal(vStakePeriodRange_T& aRange, const isminefilter filter);

StakeReportDialog::StakeReportDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::StakeReportDialog)
{
    ui->setupUi(this);

    QTableWidget *TableW = ui->StakeReportTable;

    alreadyConnected = false;

    // fill the table with clone of row 0
    for(int y=TableW->rowCount(); --y >= 1;)
        for(int x=TableW->columnCount(); --x >= 0;)
            TableW->setItem(y, x,
                TableW->item(0, x)->clone());

    TableW->horizontalHeader()->resizeSection(1,160);

    QApplication::processEvents();

    updateStakeReportNow();  // 1st update
}

StakeReportDialog::~StakeReportDialog()
{
    delete ui;
}

void StakeReportDialog::setModel(WalletModel *model)
{
    this->ex_model = model;

    if(ex_model && ex_model->getOptionsModel() && !alreadyConnected)
    {
        alreadyConnected = true;

        connect(ex_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit(int)));
        connect(ui->button_Refresh, SIGNAL(clicked()), this, SLOT(updateStakeReportNow()));
        connect(ui->CopytoClipboard, SIGNAL(clicked()), this, SLOT(CopyAllToClipboard()));

        disablereportupdate = GetBoolArg("-disablereportupdate", false);

        if (!disablereportupdate)
        {
            QTimer *timer = new QTimer(this);
            connect(timer, SIGNAL(timeout()), this, SLOT(updateStakeReportTimer()));
         	connect(ex_model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(updateStakeReportbalanceChanged(qint64, qint64, qint64, qint64)));

            timer->start(MODEL_UPDATE_DELAY*5);
        }
    }
}

void StakeReportDialog::updateStakeReportbalanceChanged(qint64, qint64, qint64, qint64)
{
    StakeReportDialog::updateStakeReportNow();
}

void StakeReportDialog::updateDisplayUnit(int)
{
    StakeReportDialog::updateStakeReportNow();
}

void StakeReportDialog::updateStakeReportTimer()
{
    static int lastBest = 0 ;
    if (lastBest != chainActive.Height())
    {
        lastBest = chainActive.Height();
        StakeReportDialog::updateStakeReport(false);
    }
}

void StakeReportDialog::showEvent( QShowEvent* event )
{
    QWidget::showEvent( event );
    StakeReportDialog::updateStakeReportNow();
}

// Extendable localtime format
QString HalfDate(int64_t nTime, QString TimeMode="")
{
    QDateTime OrigDate = QDateTime::fromTime_t((qint32)nTime);
    QString LocalDate = OrigDate.date().toString("yyyy-MM-dd");
    if (TimeMode != "")
        LocalDate += " " + OrigDate.toString(TimeMode);

    return LocalDate;
}

// format Sequencevalue with all trailing zero
QString Coin_0Pad(int nUnit, int64_t amount)
{
    QString result = SequenceUnits::format(nUnit, amount);

    int poin = result.indexOf(".") + 1;
    poin += SequenceUnits::decimals(nUnit);

    return result.leftJustified(poin, '0');
}

void StakeReportDialog::updateStakeReportNow()
{
    updateStakeReport(true);
}

void StakeReportDialog::updateStakeReport(bool fImmediate=false)
{
    static vStakePeriodRange_T aRange;
    int nItemCounted=0;

    if (fImmediate) nLastReportUpdate = 0;

    if (this->isHidden())
        return;

    int64_t nTook = GetTimeMillis();

    // Skip report recalc if not immediate or before 5 minutes from last
    if (GetTime() - nLastReportUpdate > 300)
    {
        QApplication::processEvents();

        ui->TimeTook->setText(tr("Please wait..."));
        ui->TimeTook->repaint();
        QApplication::processEvents();

        aRange = PrepareRangeForStakeReport();

        // get subtotal calc
        nItemCounted = GetStakeSubTotal(aRange, ISMINE_SPENDABLE);

        nLastReportUpdate = GetTime();

        nTook = GetTimeMillis() - nTook;

    }

    int64_t nTook2 = GetTimeMillis();

    // actually update labels
    int nDisplayUnit = SequenceUnits::SEQ;
    if (ex_model && ex_model->getOptionsModel())
         nDisplayUnit = ex_model->getOptionsModel()->getDisplayUnit();

    ui->L_Coin->setText(SequenceUnits::name(nDisplayUnit) + " " + tr("SubTotal"));

    QTableWidget *TableW = ui->StakeReportTable;

    TableW->horizontalHeaderItem(1)->setText(SequenceUnits::name(nDisplayUnit) + " " +tr("Amount"));

    int i=30;

    TableW->setSortingEnabled(false);
    for(int y=0; y<i; y++)
    {
       TableW->item(y,0)->setText(HalfDate(aRange[y].Start));
       TableW->item(y,1)->setText(Coin_0Pad(nDisplayUnit, aRange[y].Total));
       TableW->item(y,2)->setText(QString::number(aRange[y].Count));
    }
    TableW->setSortingEnabled(true);

    ui->Amount_24H->setText(Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" SEQ"));
    ui->Stake_24H->setText(QString::number(aRange[i++].Count));
    ui->Amount_7D->setText(Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" SEQ"));
    ui->Stake_7D->setText(QString::number(aRange[i++].Count));
    ui->Amount_30D->setText(Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" SEQ"));
    ui->Stake_30D->setText(QString::number(aRange[i++].Count));
    ui->Amount_365D->setText(Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" SEQ"));
    ui->Stake_365D->setText(QString::number(aRange[i++].Count));

    ui->Amount_Last->setText(tr("Amount: ") + Coin_0Pad(nDisplayUnit, aRange[i].Total) + tr(" SEQ"));
    ui->L_LastStakeTime->setText(tr("Latest stake date: ") + HalfDate(aRange[i].Start, "hh:mm"));

    ui->Stake_Counted->setText(tr("Stakes analysed: ") + QString::number(nItemCounted));
    if (nItemCounted)
        ui->TimeTook->setText(tr("Last Recalc took ") + QString::number(nTook) +  "ms");

    ui->TimeTook_2->setText(tr("Refresh took ") + QString::number(GetTimeMillis() -nTook2) +  "ms");

    string sRefreshType = disablereportupdate ? "Manual refresh" : "Auto refresh";

    string strCurr_block_info = strprintf("%s  -  %s : %6d @ %s\nhash %s\n",
           sRefreshType.c_str(), "Current Block", chainActive.Height(),
           HalfDate((chainActive.Tip()->GetMedianTimePast()+1), "hh:mm:ss").toStdString().c_str(),
           chainActive.Tip()->GetBlockHash().ToString());

    ui->L_CurrentBlock->setText(strCurr_block_info.c_str() );

}

QString GridGetLabelTextAt(QGridLayout * Grid, int row, int column, QString Empty = "")
{
    if (Grid && Grid->itemAtPosition(row, column) &&
            Grid->itemAtPosition(row, column)->widget())
        return ((QLabel *) Grid->itemAtPosition(row, column)->widget())->text();
    else
        return Empty;
}

void StakeReportDialog::CopyAllToClipboard()
{
    QString Repo;

    Repo += "           Sequence Stake Mini Report\n";
    Repo += "           ----------------------\n";

    QString  RowForm = "%1 %2 %3\n";

    for(int y=0; y<ui->gridLayout->rowCount(); y++)
    {
        if (y == 5)
            Repo += "\n"; //  separator line
        else
            Repo += RowForm
                .arg(GridGetLabelTextAt(ui->gridLayout, y,0), -16)
                .arg(GridGetLabelTextAt(ui->gridLayout, y,1), 16)
                .arg(GridGetLabelTextAt(ui->gridLayout, y,2), 7);
    }

    Repo += "\n";

    QTableWidget *TableW = ui->StakeReportTable;
    RowForm = "%1, %2, %3\n";

    Repo += RowForm
        .arg(TableW->horizontalHeaderItem(0)->text(), -10)
        .arg(TableW->horizontalHeaderItem(1)->text(), 16)
        .arg(TableW->horizontalHeaderItem(2)->text(), 7);

    for(int y=0; y<30; y++)
    {
        Repo += RowForm
            .arg(TableW->item(y,0)->text(), -10)
            .arg(TableW->item(y,1)->text(), 16)
            .arg(TableW->item(y,2)->text(), 7);
    }

    Repo += "\n" + ui->L_CurrentBlock->text() + "\n";

    QApplication::clipboard()->setText(Repo);

}<|endoftext|>