<commit_before>// Convert DMD CodeView debug information to PDB files
// Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
//
// License for redistribution is given by the Artistic License 2.0
// see file LICENSE for further details

#include <algorithm>

#include "symutil.h"
#include "demangle.h"

extern "C" {
#include "mscvpdb.h"
}

#include <assert.h>

char dotReplacementChar = '@';
bool demangleSymbols = true;
bool useTypedefEnum = false;

int dsym2c(const BYTE* p, int len, char* cname, int maxclen)
{
	const BYTE* beg = p;
	const BYTE* end = p + len;
	int zlen, zpos, cpos = 0;

	// decompress symbol
	while (p < end)
	{
		int ch = *p++;
		if(ch == 0)
			break;
		if ((ch & 0xc0) == 0xc0)
		{
			zlen = (ch & 0x7) + 1;
			zpos = ((ch >> 3) & 7) + 1; // + zlen;
			if (zpos > cpos)
				break;
			if (cpos + zlen >= maxclen)
				break;
			for (int z = 0; z < zlen; z++)
				cname[cpos + z] = cname[cpos - zpos + z];
			cpos += zlen;
		}
		else if (ch >= 0x80)
		{
			if (p >= end)
				break;
			int ch2 = *p++;
			zlen = (ch2 & 0x7f) | ((ch & 0x38) << 4);
			if (p >= end)
				break;
			int ch3 = *p++;
			zpos = (ch3 & 0x7f) | ((ch & 7) << 7);
			if (zpos > cpos)
				break;
			if (cpos + zlen >= maxclen)
				break;
			for(int z = 0; z < zlen; z++)
				cname[cpos + z] = cname[cpos - zpos + z];
			cpos += zlen;
		}
#if 0
		if (ch == 0x80)
		{
			if (p >= end)
				break;
			zlen = *p++ & 0x7f;
			if (p >= end)
				break;
			zpos = *p++ & 0x7f;
			if (zpos > cpos)
				break;
			for(int z = 0; z < zlen; z++)
				cname[cpos + z] = cname[cpos - zpos + z];
			cpos += zlen;
		}
		else if (ch > 0x80)
		{
			zlen = (ch & 0x7) + 1;
			zpos = ((ch >> 3) & 0xf) - 7; // + zlen;
			for(int z = 0; z < zlen; z++)
				cname[cpos + z] = cname[cpos - zpos + z];
			cpos += zlen;
		}
#endif
		else
			cname[cpos++] = ch;
	}
	if (p < end)
	{
		// decompression failed, assume it's containing UTF8 encoded characters
		cpos = min(maxclen, len);
		memcpy(cname, beg, cpos);
	}
	cname[cpos] = 0;
	if(demangleSymbols)
		if (cname[0] == '_' && cname[1] == 'D' && isdigit(cname[2]))
			d_demangle(cname, cname, maxclen, true);

#if 1
	for(int i = 0; i < cpos; i++)
		if (cname[i] == '.')
			cname[i] = dotReplacementChar;
#endif

	return cpos;
}

int pstrlen(const BYTE* &p)
{
	int len = *p++;
	if(len == 0xff && *p == 0)
	{
		len = p[1] | (p[2] << 8);
		p += 3;
	}
	return len;
}

int pstrmemlen(const BYTE* p)
{
	const BYTE* q = p;
	int len = pstrlen(p);
	return len + (p - q);
}

int dstrlen(const BYTE* &p, bool cstr)
{
	if(cstr)
		return strlen((const char*)p);
	return pstrlen(p);
}

char* p2c(const BYTE* p, int idx)
{
	static char cname[4][2560];
	int len = pstrlen(p);

#if 1
	memcpy(cname[idx], p, len);
	cname[idx][len] = 0;
#else
	dsym2c(p, len, cname[idx], 2560);
#endif
	return cname[idx];
}

char* p2c(const p_string& p, int idx)
{
	return p2c(&p.namelen, idx);
}

int c2p(const char* c, BYTE* p)
{
	BYTE* q = p;
	int len = strlen(c);
	if(len > 255)
	{
		*p++ = 0xff;
		*p++ = 0;
		*p++ = len & 0xff;
		*p++ = len >> 8;
	}
	else
		*p++ = len;
	memcpy(p, c, len);
	return p + len - q;
}

int c2p(const char* c, p_string& p)
{
	return c2p(c, &p.namelen);
}

int p2ccpy(char* p, const BYTE* s)
{
	int len = pstrlen(s);
	memcpy(p, s, len);
	p[len] = 0;
	return len + 1;
}

int pstrcpy(BYTE* p, const BYTE* s)
{
	const BYTE* src = s;
	int len = pstrlen(s);
	for(int i = 0; i <= s - src; i++)
		*p++ = src[i];

	for(int i = 0; i < len; i++)
		if (s[i] == '.')
		{
			//p[i++] = ':';
			p[i] = dotReplacementChar;
		}
		else
			p[i] = s[i];
	return len + src - s; // *(BYTE*) memcpy (p, s, *s + 1) + 1;
}

int dmemcmp(const void* v1, const void* v2, int len)
{
	const BYTE* p1 = (const BYTE*) v1;
	const BYTE* p2 = (const BYTE*) v2;
	for(int i = 0; i < len; i++)
	{
		int b1 = p1[i];
		int b2 = p2[i];
		if(b1 == '.')
			b1 = dotReplacementChar;
		if(b2 == '.')
			b2 = dotReplacementChar;
		if(b1 != b2)
			return b2 - b1;
	}
	return 0;
}

int pstrcpy(p_string& p, const p_string& s)
{
	return *(BYTE*) memcpy (&p, &s, s.namelen + 1) + 1;
}

int pstrcmp(const BYTE* p1, const BYTE* p2)
{
	int len1 = pstrlen(p1);
	int len2 = pstrlen(p2);
	if (len1 != len2)
		return len2 - len1;
	return dmemcmp(p1, p2, len1);
}

bool p2ccmp(const BYTE* pp, const char* cp)
{
	int len = strlen(cp);
	int plen = pstrlen(pp);
	if (len != plen)
		return false;
	return dmemcmp(pp, cp, len) == 0;
}

bool p2ccmp(const p_string& pp, const char* cp)
{
	return p2ccmp(&pp.namelen, cp);
}

bool dstrcmp(const BYTE* s1, bool cstr1, const BYTE* s2, bool cstr2)
{
	int len1 = dstrlen(s1, cstr1);
	int len2 = dstrlen(s2, cstr2);
	if(len1 != len2)
		return false;
	return dmemcmp(s1, s2, len1) == 0;
}

int pstrcpy_v(bool v3, BYTE* d, const BYTE* s)
{
	if (!v3)
		return pstrcpy(d, s);

	int len = pstrlen(s);
	int clen = dsym2c(s, len, (char*) d, kMaxNameLen) + 1;

	return clen;
}

int cstrcpy_v(bool v3, BYTE* d, const char* s)
{
	int len = strlen(s);
	if(!v3)
	{
		assert(len < 256);
		*d++ = len;
	}
	len = (std::min)(len, kMaxNameLen-1);

	memcpy(d, s, len + 1);
	d[len] = '\0';

	for(int i = 0; i < len; i++)
		if (d[i] == '.')
			d[i] = dotReplacementChar;

	return len + 1;
}

<commit_msg>Do not crash when handling anonymous entities<commit_after>// Convert DMD CodeView debug information to PDB files
// Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
//
// License for redistribution is given by the Artistic License 2.0
// see file LICENSE for further details

#include <algorithm>

#include "symutil.h"
#include "demangle.h"

extern "C" {
#include "mscvpdb.h"
}

#include <assert.h>

char dotReplacementChar = '@';
bool demangleSymbols = true;
bool useTypedefEnum = false;

int dsym2c(const BYTE* p, int len, char* cname, int maxclen)
{
	const BYTE* beg = p;
	const BYTE* end = p + len;
	int zlen, zpos, cpos = 0;

	// decompress symbol
	while (p < end)
	{
		int ch = *p++;
		if(ch == 0)
			break;
		if ((ch & 0xc0) == 0xc0)
		{
			zlen = (ch & 0x7) + 1;
			zpos = ((ch >> 3) & 7) + 1; // + zlen;
			if (zpos > cpos)
				break;
			if (cpos + zlen >= maxclen)
				break;
			for (int z = 0; z < zlen; z++)
				cname[cpos + z] = cname[cpos - zpos + z];
			cpos += zlen;
		}
		else if (ch >= 0x80)
		{
			if (p >= end)
				break;
			int ch2 = *p++;
			zlen = (ch2 & 0x7f) | ((ch & 0x38) << 4);
			if (p >= end)
				break;
			int ch3 = *p++;
			zpos = (ch3 & 0x7f) | ((ch & 7) << 7);
			if (zpos > cpos)
				break;
			if (cpos + zlen >= maxclen)
				break;
			for(int z = 0; z < zlen; z++)
				cname[cpos + z] = cname[cpos - zpos + z];
			cpos += zlen;
		}
#if 0
		if (ch == 0x80)
		{
			if (p >= end)
				break;
			zlen = *p++ & 0x7f;
			if (p >= end)
				break;
			zpos = *p++ & 0x7f;
			if (zpos > cpos)
				break;
			for(int z = 0; z < zlen; z++)
				cname[cpos + z] = cname[cpos - zpos + z];
			cpos += zlen;
		}
		else if (ch > 0x80)
		{
			zlen = (ch & 0x7) + 1;
			zpos = ((ch >> 3) & 0xf) - 7; // + zlen;
			for(int z = 0; z < zlen; z++)
				cname[cpos + z] = cname[cpos - zpos + z];
			cpos += zlen;
		}
#endif
		else
			cname[cpos++] = ch;
	}
	if (p < end)
	{
		// decompression failed, assume it's containing UTF8 encoded characters
		cpos = min(maxclen, len);
		memcpy(cname, beg, cpos);
	}
	cname[cpos] = 0;
	if(demangleSymbols)
		if (cname[0] == '_' && cname[1] == 'D' && isdigit(cname[2]))
			d_demangle(cname, cname, maxclen, true);

#if 1
	for(int i = 0; i < cpos; i++)
		if (cname[i] == '.')
			cname[i] = dotReplacementChar;
#endif

	return cpos;
}

int pstrlen(const BYTE* &p)
{
	int len = *p++;
	if(len == 0xff && *p == 0)
	{
		len = p[1] | (p[2] << 8);
		p += 3;
	}
	return len;
}

int pstrmemlen(const BYTE* p)
{
	const BYTE* q = p;
	int len = pstrlen(p);
	return len + (p - q);
}

int dstrlen(const BYTE* &p, bool cstr)
{
	if(cstr)
		return strlen((const char*)p);
	return pstrlen(p);
}

char* p2c(const BYTE* p, int idx)
{
	static char cname[4][2560];
	int len = pstrlen(p);

#if 1
	memcpy(cname[idx], p, len);
	cname[idx][len] = 0;
#else
	dsym2c(p, len, cname[idx], 2560);
#endif
	return cname[idx];
}

char* p2c(const p_string& p, int idx)
{
	return p2c(&p.namelen, idx);
}

int c2p(const char* c, BYTE* p)
{
	BYTE* q = p;
	int len = strlen(c);
	if(len > 255)
	{
		*p++ = 0xff;
		*p++ = 0;
		*p++ = len & 0xff;
		*p++ = len >> 8;
	}
	else
		*p++ = len;
	memcpy(p, c, len);
	return p + len - q;
}

int c2p(const char* c, p_string& p)
{
	return c2p(c, &p.namelen);
}

int p2ccpy(char* p, const BYTE* s)
{
	int len = pstrlen(s);
	memcpy(p, s, len);
	p[len] = 0;
	return len + 1;
}

int pstrcpy(BYTE* p, const BYTE* s)
{
	const BYTE* src = s;
	int len = pstrlen(s);
	for(int i = 0; i <= s - src; i++)
		*p++ = src[i];

	for(int i = 0; i < len; i++)
		if (s[i] == '.')
		{
			//p[i++] = ':';
			p[i] = dotReplacementChar;
		}
		else
			p[i] = s[i];
	return len + src - s; // *(BYTE*) memcpy (p, s, *s + 1) + 1;
}

int dmemcmp(const void* v1, const void* v2, int len)
{
	const BYTE* p1 = (const BYTE*) v1;
	const BYTE* p2 = (const BYTE*) v2;
	for(int i = 0; i < len; i++)
	{
		int b1 = p1[i];
		int b2 = p2[i];
		if(b1 == '.')
			b1 = dotReplacementChar;
		if(b2 == '.')
			b2 = dotReplacementChar;
		if(b1 != b2)
			return b2 - b1;
	}
	return 0;
}

int pstrcpy(p_string& p, const p_string& s)
{
	return *(BYTE*) memcpy (&p, &s, s.namelen + 1) + 1;
}

int pstrcmp(const BYTE* p1, const BYTE* p2)
{
	int len1 = pstrlen(p1);
	int len2 = pstrlen(p2);
	if (len1 != len2)
		return len2 - len1;
	return dmemcmp(p1, p2, len1);
}

bool p2ccmp(const BYTE* pp, const char* cp)
{
	int len = strlen(cp);
	int plen = pstrlen(pp);
	if (len != plen)
		return false;
	return dmemcmp(pp, cp, len) == 0;
}

bool p2ccmp(const p_string& pp, const char* cp)
{
	return p2ccmp(&pp.namelen, cp);
}

bool dstrcmp(const BYTE* s1, bool cstr1, const BYTE* s2, bool cstr2)
{
	int len1 = dstrlen(s1, cstr1);
	int len2 = dstrlen(s2, cstr2);
	if(len1 != len2)
		return false;
	return dmemcmp(s1, s2, len1) == 0;
}

int pstrcpy_v(bool v3, BYTE* d, const BYTE* s)
{
	if (!v3)
		return pstrcpy(d, s);

	int len = pstrlen(s);
	int clen = dsym2c(s, len, (char*) d, kMaxNameLen) + 1;

	return clen;
}

int cstrcpy_v(bool v3, BYTE* d, const char* s)
{
	// Process absent names as empty ones
	if (s == NULL)
		s = "";

	int len = strlen(s);
	if(!v3)
	{
		assert(len < 256);
		*d++ = len;
	}
	len = (std::min)(len, kMaxNameLen-1);

	memcpy(d, s, len + 1);
	d[len] = '\0';

	for(int i = 0; i < len; i++)
		if (d[i] == '.')
			d[i] = dotReplacementChar;

	return len + 1;
}

<|endoftext|>


<commit_before>#include <numpy_eigen/boost_python_headers.hpp>
#include <sm/eigen/matrix_sqrt.hpp>
#include <sm/assert_macros.hpp>

Eigen::MatrixXd matrixSqrt(const Eigen::MatrixXd & M)
{
    SM_ASSERT_EQ(std::runtime_error, M.rows(), M.cols(), "The matrix must be square");
    Eigen::MatrixXd sqrtM;

    Eigen::ComputationInfo result = sm::eigen::computeMatrixSqrt(M, sqrtM);
    SM_ASSERT_EQ(std::runtime_error, result, Eigen::Success, "The matrix square root was not successful")
    return sqrtM;
}

void exportEigen()
{
    boost::python::def("computeMatrixSqrt", &matrixSqrt);
}
<commit_msg>Fixed a compilation error in the python interface<commit_after>#include <numpy_eigen/boost_python_headers.hpp>
#include <sm/eigen/matrix_sqrt.hpp>
#include <sm/assert_macros.hpp>

Eigen::MatrixXd matrixSqrt(const Eigen::MatrixXd & M)
{
    SM_ASSERT_EQ(std::runtime_error, M.rows(), M.cols(), "The matrix must be square");
    Eigen::MatrixXd sqrtM;

    /*Eigen::ComputationInfo result =*/ sm::eigen::computeMatrixSqrt(M, sqrtM);
    //SM_ASSERT_EQ(std::runtime_error, result, Eigen::Success, "The matrix square root was not successful")
    return sqrtM;
}

void exportEigen()
{
    boost::python::def("computeMatrixSqrt", &matrixSqrt);
}
<|endoftext|>


<commit_before>#pragma once

namespace svgren{

struct SubSurface{
	std::uint8_t* data; //RGBA premultiplied alpha
	unsigned stride;
	unsigned width;
	unsigned height;

	unsigned posx;
	unsigned posy;
};

}
<commit_msg>stuff<commit_after>#pragma once

namespace svgren{

struct SubSurface{
	std::uint8_t* data; //RGBA premultiplied alpha
	unsigned stride;

	unsigned width;
	unsigned height;

	//position of subsurface on the canvas
	unsigned posx;
	unsigned posy;
};

}
<|endoftext|>


<commit_before><commit_msg>Measurement jacobians<commit_after><|endoftext|>


<commit_before><commit_msg>indexcodec: Add extensive comments<commit_after><|endoftext|>


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

#include "net/base/cert_status_flags.h"

#include "base/logging.h"
#include "net/base/net_errors.h"

namespace net {

int MapNetErrorToCertStatus(int error) {
  switch (error) {
    case ERR_CERT_COMMON_NAME_INVALID:
      return CERT_STATUS_COMMON_NAME_INVALID;
    case ERR_CERT_DATE_INVALID:
      return CERT_STATUS_DATE_INVALID;
    case ERR_CERT_AUTHORITY_INVALID:
      return CERT_STATUS_AUTHORITY_INVALID;
    case ERR_CERT_NO_REVOCATION_MECHANISM:
      return CERT_STATUS_NO_REVOCATION_MECHANISM;
    case ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
      return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
    case ERR_CERT_REVOKED:
      return CERT_STATUS_REVOKED;
    // We added the ERR_CERT_CONTAINS_ERRORS error code when we were using
    // WinInet, but we never figured out how it differs from ERR_CERT_INVALID.
    // We should not use ERR_CERT_CONTAINS_ERRORS in new code.
    case ERR_CERT_CONTAINS_ERRORS:
      NOTREACHED();
      // Falls through.
    case ERR_CERT_INVALID:
      return CERT_STATUS_INVALID;
    case ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
      return CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
    default:
      return 0;
  }
}

int MapCertStatusToNetError(int cert_status) {
  // A certificate may have multiple errors.  We report the most
  // serious error.

  // Unrecoverable errors
  if (cert_status & CERT_STATUS_INVALID)
    return ERR_CERT_INVALID;
  if (cert_status & CERT_STATUS_REVOKED)
    return ERR_CERT_REVOKED;

  // Recoverable errors
  if (cert_status & CERT_STATUS_AUTHORITY_INVALID)
    return ERR_CERT_AUTHORITY_INVALID;
  if (cert_status & CERT_STATUS_COMMON_NAME_INVALID)
    return ERR_CERT_COMMON_NAME_INVALID;
  if (cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM)
    return ERR_CERT_WEAK_SIGNATURE_ALGORITHM;
  if (cert_status & CERT_STATUS_DATE_INVALID)
    return ERR_CERT_DATE_INVALID;

  // Unknown status.  Give it the benefit of the doubt.
  if (cert_status & CERT_STATUS_UNABLE_TO_CHECK_REVOCATION)
    return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
  if (cert_status & CERT_STATUS_NO_REVOCATION_MECHANISM)
    return ERR_CERT_NO_REVOCATION_MECHANISM;

  NOTREACHED();
  return ERR_UNEXPECTED;
}

}  // namespace net
<commit_msg>Consider "certificate revoked" as the most serious certificate error.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/cert_status_flags.h"

#include "base/logging.h"
#include "net/base/net_errors.h"

namespace net {

int MapNetErrorToCertStatus(int error) {
  switch (error) {
    case ERR_CERT_COMMON_NAME_INVALID:
      return CERT_STATUS_COMMON_NAME_INVALID;
    case ERR_CERT_DATE_INVALID:
      return CERT_STATUS_DATE_INVALID;
    case ERR_CERT_AUTHORITY_INVALID:
      return CERT_STATUS_AUTHORITY_INVALID;
    case ERR_CERT_NO_REVOCATION_MECHANISM:
      return CERT_STATUS_NO_REVOCATION_MECHANISM;
    case ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
      return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
    case ERR_CERT_REVOKED:
      return CERT_STATUS_REVOKED;
    // We added the ERR_CERT_CONTAINS_ERRORS error code when we were using
    // WinInet, but we never figured out how it differs from ERR_CERT_INVALID.
    // We should not use ERR_CERT_CONTAINS_ERRORS in new code.
    case ERR_CERT_CONTAINS_ERRORS:
      NOTREACHED();
      // Falls through.
    case ERR_CERT_INVALID:
      return CERT_STATUS_INVALID;
    case ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
      return CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
    default:
      return 0;
  }
}

int MapCertStatusToNetError(int cert_status) {
  // A certificate may have multiple errors.  We report the most
  // serious error.

  // Unrecoverable errors
  if (cert_status & CERT_STATUS_REVOKED)
    return ERR_CERT_REVOKED;
  if (cert_status & CERT_STATUS_INVALID)
    return ERR_CERT_INVALID;

  // Recoverable errors
  if (cert_status & CERT_STATUS_AUTHORITY_INVALID)
    return ERR_CERT_AUTHORITY_INVALID;
  if (cert_status & CERT_STATUS_COMMON_NAME_INVALID)
    return ERR_CERT_COMMON_NAME_INVALID;
  if (cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM)
    return ERR_CERT_WEAK_SIGNATURE_ALGORITHM;
  if (cert_status & CERT_STATUS_DATE_INVALID)
    return ERR_CERT_DATE_INVALID;

  // Unknown status.  Give it the benefit of the doubt.
  if (cert_status & CERT_STATUS_UNABLE_TO_CHECK_REVOCATION)
    return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
  if (cert_status & CERT_STATUS_NO_REVOCATION_MECHANISM)
    return ERR_CERT_NO_REVOCATION_MECHANISM;

  NOTREACHED();
  return ERR_UNEXPECTED;
}

}  // namespace net
<|endoftext|>


<commit_before>#include <cucumber-cpp/internal/connectors/wire/WireProtocol.hpp>
#include <cucumber-cpp/internal/connectors/wire/WireProtocolCommands.hpp>

#include <json_spirit/json_spirit_reader_template.h>
#include <json_spirit/json_spirit_writer_template.h>

#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>

#include <iostream>
#include <string>
#include <sstream>

using namespace json_spirit;

namespace cucumber {
namespace internal {

/*
 * Responses
 */

void SuccessResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

FailureResponse::FailureResponse(const std::string & message, const std::string & exceptionType) :
    message(message),
    exceptionType(exceptionType) {
}

const std::string FailureResponse::getMessage() const {
    return message;
}

const std::string FailureResponse::getExceptionType() const {
    return exceptionType;
}

void FailureResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

PendingResponse::PendingResponse(const std::string & message) :
    message(message) {
}

const std::string PendingResponse::getMessage() const {
    return message;
}

void PendingResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

StepMatchesResponse::StepMatchesResponse(const std::vector<StepMatch> & matchingSteps)
    : matchingSteps(matchingSteps) {
}

const std::vector<StepMatch>& StepMatchesResponse::getMatchingSteps() const {
    return matchingSteps;
}

void StepMatchesResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

SnippetTextResponse::SnippetTextResponse(const std::string & stepSnippet) :
    stepSnippet(stepSnippet) {
}

const std::string SnippetTextResponse::getStepSnippet() const {
    return stepSnippet;
}

void SnippetTextResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

/*
 * Command decoders
 */

class CommandDecoder {
public:
  virtual ~CommandDecoder() { }
  virtual boost::shared_ptr<WireCommand> decode(const mValue & jsonArgs) const = 0;
};

class ScenarioDecoder : public CommandDecoder {
protected:
    CukeEngine::tags_type getTags(const mValue & jsonArgs) const {
        CukeEngine::tags_type tags;
        if (!jsonArgs.is_null()) {
            const mArray & jsonTags = jsonArgs.get_obj().find("tags")->second.get_array();
            for (mArray::const_iterator i = jsonTags.begin(); i != jsonTags.end(); ++i) {
                tags.push_back(i->get_str());
            }
        }
        return tags;
    }
};

class BeginScenarioDecoder : public ScenarioDecoder {
public:
    boost::shared_ptr<WireCommand> decode(const mValue & jsonArgs) const {
        return boost::make_shared<BeginScenarioCommand>(getTags(jsonArgs));
    }
};

class EndScenarioDecoder : public ScenarioDecoder {
public:
    boost::shared_ptr<WireCommand> decode(const mValue & jsonArgs) const {
        return boost::make_shared<EndScenarioCommand>(getTags(jsonArgs));
    }
};

class StepMatchesDecoder : public CommandDecoder {
public:
    boost::shared_ptr<WireCommand> decode(const mValue & jsonArgs) const {
        mObject stepMatchesArgs(jsonArgs.get_obj());
        const std::string & nameToMatch(stepMatchesArgs["name_to_match"].get_str());
        return boost::make_shared<StepMatchesCommand>(nameToMatch);
    }
};

class InvokeDecoder : public CommandDecoder {
public:
    boost::shared_ptr<WireCommand> decode(const mValue & jsonArgs) const {
        mObject invokeParams(jsonArgs.get_obj());

        CukeEngine::invoke_args_type args;
        CukeEngine::invoke_table_type tableArg;
        const std::string & id(invokeParams["id"].get_str());
        fillInvokeArgs(invokeParams, args, tableArg);
        return boost::make_shared<InvokeCommand>(id, args, tableArg);
    }

private:
    void fillInvokeArgs(
            const mObject & invokeParams,
            CukeEngine::invoke_args_type & args,
            CukeEngine::invoke_table_type & tableArg) const {
        const mArray & jsonArgs(invokeParams.find("args")->second.get_array());
        for (mArray::const_iterator i = jsonArgs.begin(); i != jsonArgs.end(); ++i) {
            if (i->type() == str_type) {
                args.push_back(i->get_str());
            } else if (i->type() == array_type) {
                fillTableArg(i->get_array(), tableArg);
            }
        }
    }

    void fillTableArg(const mArray & jsonTableArg, CukeEngine::invoke_table_type & tableArg) const {
        typedef mArray::size_type size_type;
        size_type rows = jsonTableArg.size();
        if (rows > 0) {
            size_type columns = jsonTableArg[0].get_array().size();
            tableArg.resize(boost::extents[rows][columns]);
            for (size_type i = 0; i < rows; ++i) {
                const mArray & jsonRow(jsonTableArg[i].get_array());
                if (jsonRow.size() == columns) {
                    for (size_type j = 0; j < columns; ++j) {
                        tableArg[i][j] = jsonRow[j].get_str();
                    }
                } else {
                    // TODO: Invalid row
                }
            }
        } else {
            // TODO: Invalid table (no column specified)
        }
    }
};

class SnippetTextDecoder : public CommandDecoder {
public:
    boost::shared_ptr<WireCommand> decode(const mValue & jsonArgs) const {
        mObject snippetTextArgs(jsonArgs.get_obj());
        const std::string & stepKeyword(snippetTextArgs["step_keyword"].get_str());
        const std::string & stepName(snippetTextArgs["step_name"].get_str());
        const std::string & multilineArgClass(snippetTextArgs["multiline_arg_class"].get_str());
        return boost::make_shared<SnippetTextCommand>(stepKeyword, stepName, multilineArgClass);
    }
};

static const std::map<std::string, boost::shared_ptr<CommandDecoder> > commandDecodersMap =
  boost::assign::map_list_of<std::string, boost::shared_ptr<CommandDecoder> >
    ("begin_scenario", boost::make_shared< BeginScenarioDecoder >())
    ("end_scenario"  , boost::make_shared< EndScenarioDecoder   >())
    ("step_matches"  , boost::make_shared< StepMatchesDecoder   >())
    ("invoke"        , boost::make_shared< InvokeDecoder        >())
    ("snippet_text"  , boost::make_shared< SnippetTextDecoder   >());

JsonSpiritWireMessageCodec::JsonSpiritWireMessageCodec() {};

boost::shared_ptr<WireCommand> JsonSpiritWireMessageCodec::decode(const std::string &request) const {
    std::istringstream is(request);
    mValue json;
    try {
        read_stream(is, json);
        mArray & jsonRequest = json.get_array();
        mValue & jsonCommand = jsonRequest[0];

        const std::map<std::string, boost::shared_ptr<CommandDecoder> >::const_iterator
            commandDecoder = commandDecodersMap.find(jsonCommand.get_str());
        if (commandDecoder != commandDecodersMap.end()
         && commandDecoder->second) {
            mValue jsonArgs;
            if (jsonRequest.size() > 1) {
                jsonArgs = jsonRequest[1];
            }
            return commandDecoder->second->decode(jsonArgs);
        }
    } catch (...) {
        // LOG Error decoding wire protocol command
    }
    return boost::make_shared<FailingCommand>();
}

namespace {

    class WireResponseEncoder : public WireResponseVisitor {
    private:
        mArray jsonOutput;

        void success(const mValue *detail = 0) {
            output("success", detail);
        }

        void fail(const mValue *detail = 0) {
            output("fail", detail);
        }

        void output(const char *responseType, const mValue *detail = 0) {
            jsonOutput.push_back(responseType);
            if (detail == 0 || detail->is_null()) {
                return;
            }
            jsonOutput.push_back(*detail);
        }

    public:
        std::string encode(const WireResponse& response) {
            jsonOutput.clear();
            response.accept(*this);
            const mValue v(jsonOutput);
            return write_string(v, false);
        }

        void visit(const SuccessResponse& /*response*/) {
            success();
        }

        void visit(const FailureResponse& response) {
            mObject detailObject;
            if (!response.getMessage().empty()) {
                detailObject["message"] = response.getMessage();
            }
            if (!response.getExceptionType().empty()) {
                detailObject["exception"] = response.getExceptionType();
            }
            if (detailObject.empty()) {
                fail();
            } else {
                const mValue detail(detailObject);
                fail(&detail);
            }
        }

        void visit(const PendingResponse& response) {
            mValue jsonReponse(response.getMessage());
            output("pending", &jsonReponse);
        }

        void visit(const StepMatchesResponse& response) {
            mArray jsonMatches;
            BOOST_FOREACH(StepMatch m, response.getMatchingSteps()) {
                mObject jsonM;
                jsonM["id"] = m.id;
                mArray jsonArgs;
                BOOST_FOREACH(StepMatchArg ma, m.args) {
                    mObject jsonMa;
                    jsonMa["val"] = ma.value;
                    jsonMa["pos"] = ma.position;
                    jsonArgs.push_back(jsonMa);
                }
                jsonM["args"] = jsonArgs;
                if (!m.source.empty()) {
                    jsonM["source"] = m.source;;
                }
                if (!m.regexp.empty()) {
                    jsonM["regexp"] = m.regexp;
                }
                jsonMatches.push_back(jsonM);
            }
            mValue jsonReponse(jsonMatches);
            output("success", &jsonReponse);
        }

        void visit(const SnippetTextResponse& response) {
            mValue jsonReponse(response.getStepSnippet());
            success(&jsonReponse);
        }
    };

}

const std::string JsonSpiritWireMessageCodec::encode(const WireResponse& response) const {
    try {
        WireResponseEncoder encoder;
        return encoder.encode(response);
    } catch (...) {
        throw WireMessageCodecException("Error decoding wire protocol response");
    }
}

WireProtocolHandler::WireProtocolHandler(const WireMessageCodec& codec, CukeEngine& engine) :
    codec(codec),
    engine(engine) {
}

std::string WireProtocolHandler::handle(const std::string &request) const {
    std::string response;
    // LOG request
    try {
        boost::shared_ptr<const WireCommand> command = codec.decode(request);
        boost::shared_ptr<const WireResponse> wireResponse = command->run(engine);
        response = codec.encode(*wireResponse);
    } catch (...) {
        response = "[\"fail\"]";
    }
    // LOG response
    return response;
}

}
}
<commit_msg>Replace CommandDecoder base class for function pointer<commit_after>#include <cucumber-cpp/internal/connectors/wire/WireProtocol.hpp>
#include <cucumber-cpp/internal/connectors/wire/WireProtocolCommands.hpp>

#include <json_spirit/json_spirit_reader_template.h>
#include <json_spirit/json_spirit_writer_template.h>

#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>

#include <iostream>
#include <string>
#include <sstream>

using namespace json_spirit;

namespace cucumber {
namespace internal {

/*
 * Responses
 */

void SuccessResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

FailureResponse::FailureResponse(const std::string & message, const std::string & exceptionType) :
    message(message),
    exceptionType(exceptionType) {
}

const std::string FailureResponse::getMessage() const {
    return message;
}

const std::string FailureResponse::getExceptionType() const {
    return exceptionType;
}

void FailureResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

PendingResponse::PendingResponse(const std::string & message) :
    message(message) {
}

const std::string PendingResponse::getMessage() const {
    return message;
}

void PendingResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

StepMatchesResponse::StepMatchesResponse(const std::vector<StepMatch> & matchingSteps)
    : matchingSteps(matchingSteps) {
}

const std::vector<StepMatch>& StepMatchesResponse::getMatchingSteps() const {
    return matchingSteps;
}

void StepMatchesResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

SnippetTextResponse::SnippetTextResponse(const std::string & stepSnippet) :
    stepSnippet(stepSnippet) {
}

const std::string SnippetTextResponse::getStepSnippet() const {
    return stepSnippet;
}

void SnippetTextResponse::accept(WireResponseVisitor& visitor) const {
    visitor.visit(*this);
}

/*
 * Command decoders
 */

namespace {
    typedef boost::shared_ptr<WireCommand> (*CommandDecoder)(const mValue& jsonArgs);

    CukeEngine::tags_type getScenarioTags(const mValue& jsonArgs) {
        CukeEngine::tags_type tags;
        if (!jsonArgs.is_null()) {
            const mArray & jsonTags = jsonArgs.get_obj().find("tags")->second.get_array();
            for (mArray::const_iterator i = jsonTags.begin(); i != jsonTags.end(); ++i) {
                tags.push_back(i->get_str());
            }
        }
        return tags;
    }

    boost::shared_ptr<WireCommand> BeginScenarioDecoder(const mValue& jsonArgs) {
        return boost::make_shared<BeginScenarioCommand>(getScenarioTags(jsonArgs));
    }

    boost::shared_ptr<WireCommand> EndScenarioDecoder(const mValue& jsonArgs) {
        return boost::make_shared<EndScenarioCommand>(getScenarioTags(jsonArgs));
    }

    boost::shared_ptr<WireCommand> StepMatchesDecoder(const mValue& jsonArgs) {
        mObject stepMatchesArgs(jsonArgs.get_obj());
        const std::string& nameToMatch(stepMatchesArgs["name_to_match"].get_str());
        return boost::make_shared<StepMatchesCommand>(nameToMatch);
    }

    void fillTableArg(const mArray& jsonTableArg, CukeEngine::invoke_table_type& tableArg) {
        typedef mArray::size_type size_type;
        size_type rows = jsonTableArg.size();
        if (rows > 0) {
            size_type columns = jsonTableArg[0].get_array().size();
            tableArg.resize(boost::extents[rows][columns]);
            for (size_type i = 0; i < rows; ++i) {
                const mArray & jsonRow(jsonTableArg[i].get_array());
                if (jsonRow.size() == columns) {
                    for (size_type j = 0; j < columns; ++j) {
                        tableArg[i][j] = jsonRow[j].get_str();
                    }
                } else {
                    // TODO: Invalid row
                }
            }
        } else {
            // TODO: Invalid table (no column specified)
        }
    }

    void fillInvokeArgs(
            const mObject&                 invokeParams,
            CukeEngine::invoke_args_type&  args,
            CukeEngine::invoke_table_type& tableArg) {
        const mArray & jsonArgs(invokeParams.find("args")->second.get_array());
        for (mArray::const_iterator i = jsonArgs.begin(); i != jsonArgs.end(); ++i) {
            if (i->type() == str_type) {
                args.push_back(i->get_str());
            } else if (i->type() == array_type) {
                fillTableArg(i->get_array(), tableArg);
            }
        }
    }

    boost::shared_ptr<WireCommand> InvokeDecoder(const mValue& jsonArgs) {
        mObject invokeParams(jsonArgs.get_obj());

        CukeEngine::invoke_args_type args;
        CukeEngine::invoke_table_type tableArg;
        const std::string & id(invokeParams["id"].get_str());
        fillInvokeArgs(invokeParams, args, tableArg);
        return boost::make_shared<InvokeCommand>(id, args, tableArg);
    }

    boost::shared_ptr<WireCommand> SnippetTextDecoder(const mValue& jsonArgs) {
        mObject snippetTextArgs(jsonArgs.get_obj());
        const std::string & stepKeyword(snippetTextArgs["step_keyword"].get_str());
        const std::string & stepName(snippetTextArgs["step_name"].get_str());
        const std::string & multilineArgClass(snippetTextArgs["multiline_arg_class"].get_str());
        return boost::make_shared<SnippetTextCommand>(stepKeyword, stepName, multilineArgClass);
    }
}

static const std::map<std::string, CommandDecoder> commandDecodersMap =
  boost::assign::map_list_of<std::string, CommandDecoder>
    ("begin_scenario", BeginScenarioDecoder)
    ("end_scenario"  , EndScenarioDecoder  )
    ("step_matches"  , StepMatchesDecoder  )
    ("invoke"        , InvokeDecoder       )
    ("snippet_text"  , SnippetTextDecoder  )
  ;

JsonSpiritWireMessageCodec::JsonSpiritWireMessageCodec() {};

boost::shared_ptr<WireCommand> JsonSpiritWireMessageCodec::decode(const std::string &request) const {
    std::istringstream is(request);
    mValue json;
    try {
        read_stream(is, json);
        mArray & jsonRequest = json.get_array();
        mValue & jsonCommand = jsonRequest[0];

        const std::map<std::string, CommandDecoder>::const_iterator
            commandDecoder = commandDecodersMap.find(jsonCommand.get_str());
        if (commandDecoder != commandDecodersMap.end()
         && commandDecoder->second) {
            mValue jsonArgs;
            if (jsonRequest.size() > 1) {
                jsonArgs = jsonRequest[1];
            }
            return commandDecoder->second(jsonArgs);
        }
    } catch (...) {
        // LOG Error decoding wire protocol command
    }
    return boost::make_shared<FailingCommand>();
}

namespace {

    class WireResponseEncoder : public WireResponseVisitor {
    private:
        mArray jsonOutput;

        void success(const mValue *detail = 0) {
            output("success", detail);
        }

        void fail(const mValue *detail = 0) {
            output("fail", detail);
        }

        void output(const char *responseType, const mValue *detail = 0) {
            jsonOutput.push_back(responseType);
            if (detail == 0 || detail->is_null()) {
                return;
            }
            jsonOutput.push_back(*detail);
        }

    public:
        std::string encode(const WireResponse& response) {
            jsonOutput.clear();
            response.accept(*this);
            const mValue v(jsonOutput);
            return write_string(v, false);
        }

        void visit(const SuccessResponse& /*response*/) {
            success();
        }

        void visit(const FailureResponse& response) {
            mObject detailObject;
            if (!response.getMessage().empty()) {
                detailObject["message"] = response.getMessage();
            }
            if (!response.getExceptionType().empty()) {
                detailObject["exception"] = response.getExceptionType();
            }
            if (detailObject.empty()) {
                fail();
            } else {
                const mValue detail(detailObject);
                fail(&detail);
            }
        }

        void visit(const PendingResponse& response) {
            mValue jsonReponse(response.getMessage());
            output("pending", &jsonReponse);
        }

        void visit(const StepMatchesResponse& response) {
            mArray jsonMatches;
            BOOST_FOREACH(StepMatch m, response.getMatchingSteps()) {
                mObject jsonM;
                jsonM["id"] = m.id;
                mArray jsonArgs;
                BOOST_FOREACH(StepMatchArg ma, m.args) {
                    mObject jsonMa;
                    jsonMa["val"] = ma.value;
                    jsonMa["pos"] = ma.position;
                    jsonArgs.push_back(jsonMa);
                }
                jsonM["args"] = jsonArgs;
                if (!m.source.empty()) {
                    jsonM["source"] = m.source;;
                }
                if (!m.regexp.empty()) {
                    jsonM["regexp"] = m.regexp;
                }
                jsonMatches.push_back(jsonM);
            }
            mValue jsonReponse(jsonMatches);
            output("success", &jsonReponse);
        }

        void visit(const SnippetTextResponse& response) {
            mValue jsonReponse(response.getStepSnippet());
            success(&jsonReponse);
        }
    };

}

const std::string JsonSpiritWireMessageCodec::encode(const WireResponse& response) const {
    try {
        WireResponseEncoder encoder;
        return encoder.encode(response);
    } catch (...) {
        throw WireMessageCodecException("Error decoding wire protocol response");
    }
}

WireProtocolHandler::WireProtocolHandler(const WireMessageCodec& codec, CukeEngine& engine) :
    codec(codec),
    engine(engine) {
}

std::string WireProtocolHandler::handle(const std::string &request) const {
    std::string response;
    // LOG request
    try {
        boost::shared_ptr<const WireCommand> command = codec.decode(request);
        boost::shared_ptr<const WireResponse> wireResponse = command->run(engine);
        response = codec.encode(*wireResponse);
    } catch (...) {
        response = "[\"fail\"]";
    }
    // LOG response
    return response;
}

}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkColorFilter.h"
#include "SkColorSpaceXformCanvas.h"
#include "SkColorSpaceXformer.h"
#include "SkGradientShader.h"
#include "SkImage_Base.h"
#include "SkMakeUnique.h"
#include "SkNoDrawCanvas.h"
#include "SkSurface.h"

class SkColorSpaceXformCanvas : public SkNoDrawCanvas {
public:
    SkColorSpaceXformCanvas(SkCanvas* target,
                            std::unique_ptr<SkColorSpaceXformer> xformer)
        : SkNoDrawCanvas(SkIRect::MakeSize(target->getBaseLayerSize()))
        , fTarget(target)
        , fXformer(std::move(xformer))
    {
        // Set the matrix and clip to match |fTarget|.  Otherwise, we'll answer queries for
        // bounds/matrix differently than |fTarget| would.
        SkCanvas::onClipRect(SkRect::MakeFromIRect(fTarget->getDeviceClipBounds()),
                             SkClipOp::kIntersect, kHard_ClipEdgeStyle);
        SkCanvas::setMatrix(fTarget->getTotalMatrix());
    }

    SkImageInfo onImageInfo() const override {
        return fTarget->imageInfo();
    }

    void onDrawPaint(const SkPaint& paint) override {
        fTarget->drawPaint(fXformer->apply(paint));
    }

    void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
        fTarget->drawRect(rect, fXformer->apply(paint));
    }
    void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
        fTarget->drawOval(oval, fXformer->apply(paint));
    }
    void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
        fTarget->drawRRect(rrect, fXformer->apply(paint));
    }
    void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override {
        fTarget->drawDRRect(outer, inner, fXformer->apply(paint));
    }
    void onDrawPath(const SkPath& path, const SkPaint& paint) override {
        fTarget->drawPath(path, fXformer->apply(paint));
    }
    void onDrawArc(const SkRect& oval, SkScalar start, SkScalar sweep, bool useCenter,
                   const SkPaint& paint) override {
        fTarget->drawArc(oval, start, sweep, useCenter, fXformer->apply(paint));
    }
    void onDrawRegion(const SkRegion& region, const SkPaint& paint) override {
        fTarget->drawRegion(region, fXformer->apply(paint));
    }
    void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
                     SkBlendMode mode, const SkPaint& paint) override {
        SkColor xformed[4];
        if (colors) {
            fXformer->apply(xformed, colors, 4);
            colors = xformed;
        }

        fTarget->drawPatch(cubics, colors, texs, mode, fXformer->apply(paint));
    }
    void onDrawPoints(PointMode mode, size_t count, const SkPoint* pts,
                      const SkPaint& paint) override {
        fTarget->drawPoints(mode, count, pts, fXformer->apply(paint));
    }
    void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
                              const SkPaint& paint) override {
        sk_sp<SkVertices> copy;
        if (vertices->hasColors()) {
            int count = vertices->vertexCount();
            SkSTArray<8, SkColor> xformed(count);
            fXformer->apply(xformed.begin(), vertices->colors(), count);
            copy = SkVertices::MakeCopy(vertices->mode(), count, vertices->positions(),
                                        vertices->texCoords(), xformed.begin(),
                                        vertices->indexCount(), vertices->indices());
            vertices = copy.get();
        }

        fTarget->drawVertices(vertices, mode, fXformer->apply(paint));
    }

    void onDrawText(const void* ptr, size_t len,
                    SkScalar x, SkScalar y,
                    const SkPaint& paint) override {
        fTarget->drawText(ptr, len, x, y, fXformer->apply(paint));
    }
    void onDrawPosText(const void* ptr, size_t len,
                       const SkPoint* xys,
                       const SkPaint& paint) override {
        fTarget->drawPosText(ptr, len, xys, fXformer->apply(paint));
    }
    void onDrawPosTextH(const void* ptr, size_t len,
                        const SkScalar* xs, SkScalar y,
                        const SkPaint& paint) override {
        fTarget->drawPosTextH(ptr, len, xs, y, fXformer->apply(paint));
    }
    void onDrawTextOnPath(const void* ptr, size_t len,
                          const SkPath& path, const SkMatrix* matrix,
                          const SkPaint& paint) override {
        fTarget->drawTextOnPath(ptr, len, path, matrix, fXformer->apply(paint));
    }
    void onDrawTextRSXform(const void* ptr, size_t len,
                           const SkRSXform* xforms, const SkRect* cull,
                           const SkPaint& paint) override {
        fTarget->drawTextRSXform(ptr, len, xforms, cull, fXformer->apply(paint));
    }
    void onDrawTextBlob(const SkTextBlob* blob,
                        SkScalar x, SkScalar y,
                        const SkPaint& paint) override {
        fTarget->drawTextBlob(blob, x, y, fXformer->apply(paint));
    }

    void onDrawImage(const SkImage* img,
                     SkScalar l, SkScalar t,
                     const SkPaint* paint) override {
        fTarget->drawImage(fXformer->apply(img).get(),
                           l, t,
                           fXformer->apply(paint));
    }
    void onDrawImageRect(const SkImage* img,
                         const SkRect* src, const SkRect& dst,
                         const SkPaint* paint, SrcRectConstraint constraint) override {
        fTarget->drawImageRect(fXformer->apply(img).get(),
                               src ? *src : dst, dst,
                               fXformer->apply(paint), constraint);
    }
    void onDrawImageNine(const SkImage* img,
                         const SkIRect& center, const SkRect& dst,
                         const SkPaint* paint) override {
        fTarget->drawImageNine(fXformer->apply(img).get(),
                               center, dst,
                               fXformer->apply(paint));
    }
    void onDrawImageLattice(const SkImage* img,
                            const Lattice& lattice, const SkRect& dst,
                            const SkPaint* paint) override {
        fTarget->drawImageLattice(fXformer->apply(img).get(),
                                  lattice, dst,
                                  fXformer->apply(paint));
    }
    void onDrawAtlas(const SkImage* atlas, const SkRSXform* xforms, const SkRect* tex,
                     const SkColor* colors, int count, SkBlendMode mode,
                     const SkRect* cull, const SkPaint* paint) override {
        SkSTArray<8, SkColor> xformed;
        if (colors) {
            xformed.reset(count);
            fXformer->apply(xformed.begin(), colors, count);
            colors = xformed.begin();
        }

        fTarget->drawAtlas(fXformer->apply(atlas).get(), xforms, tex, colors, count, mode, cull,
                           fXformer->apply(paint));
    }

    void onDrawBitmap(const SkBitmap& bitmap,
                      SkScalar l, SkScalar t,
                      const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImage(image.get(), l, t, paint);
        }
    }
    void onDrawBitmapRect(const SkBitmap& bitmap,
                          const SkRect* src, const SkRect& dst,
                          const SkPaint* paint, SrcRectConstraint constraint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImageRect(image.get(), src, dst, paint, constraint);
        }
    }
    void onDrawBitmapNine(const SkBitmap& bitmap,
                          const SkIRect& center, const SkRect& dst,
                          const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImageNine(image.get(), center, dst, paint);
        }
    }
    void onDrawBitmapLattice(const SkBitmap& bitmap,
                             const Lattice& lattice, const SkRect& dst,
                             const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImageLattice(image.get(), lattice, dst, paint);
        }
    }

    // TODO: May not be ideal to unfurl pictures.
    void onDrawPicture(const SkPicture* pic,
                       const SkMatrix* matrix,
                       const SkPaint* paint) override {
        SkCanvas::onDrawPicture(pic, matrix, fXformer->apply(paint));
    }
    void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
        SkCanvas::onDrawDrawable(drawable, matrix);
    }

    SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override {
        fTarget->saveLayer({
            rec.fBounds,
            fXformer->apply(rec.fPaint),
            rec.fBackdrop,  // TODO: this is an image filter
            rec.fSaveLayerFlags,
        });
        return kNoLayer_SaveLayerStrategy;
    }

    // Everything from here on should be uninteresting strictly proxied state-change calls.
    void willSave()    override { fTarget->save(); }
    void willRestore() override { fTarget->restore(); }

    void didConcat   (const SkMatrix& m) override { fTarget->concat   (m); }
    void didSetMatrix(const SkMatrix& m) override { fTarget->setMatrix(m); }

    void onClipRect(const SkRect& clip, SkClipOp op, ClipEdgeStyle style) override {
        SkCanvas::onClipRect(clip, op, style);
        fTarget->clipRect(clip, op, style);
    }
    void onClipRRect(const SkRRect& clip, SkClipOp op, ClipEdgeStyle style) override {
        SkCanvas::onClipRRect(clip, op, style);
        fTarget->clipRRect(clip, op, style);
    }
    void onClipPath(const SkPath& clip, SkClipOp op, ClipEdgeStyle style) override {
        SkCanvas::onClipPath(clip, op, style);
        fTarget->clipPath(clip, op, style);
    }
    void onClipRegion(const SkRegion& clip, SkClipOp op) override {
        SkCanvas::onClipRegion(clip, op);
        fTarget->clipRegion(clip, op);
    }

    void onDrawAnnotation(const SkRect& rect, const char* key, SkData* val) override {
        fTarget->drawAnnotation(rect, key, val);
    }

    sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) override {
        return fTarget->makeSurface(info, &props);
    }

    SkISize getBaseLayerSize() const override { return fTarget->getBaseLayerSize(); }
    SkRect onGetLocalClipBounds() const override { return fTarget->getLocalClipBounds(); }
    SkIRect onGetDeviceClipBounds() const override { return fTarget->getDeviceClipBounds(); }
    bool isClipEmpty() const override { return fTarget->isClipEmpty(); }
    bool isClipRect() const override { return fTarget->isClipRect(); }
    bool onPeekPixels(SkPixmap* pixmap) override { return fTarget->peekPixels(pixmap); }
    bool onAccessTopLayerPixels(SkPixmap* pixmap) override {
        SkImageInfo info;
        size_t rowBytes;
        SkIPoint* origin = nullptr;
        void* addr = fTarget->accessTopLayerPixels(&info, &rowBytes, origin);
        if (addr) {
            *pixmap = SkPixmap(info, addr, rowBytes);
            return true;
        }
        return false;
    }

    bool onGetProps(SkSurfaceProps* props) const override { return fTarget->getProps(props); }
    void onFlush() override { return fTarget->flush(); }

private:
    SkCanvas*                            fTarget;
    std::unique_ptr<SkColorSpaceXformer> fXformer;
};

std::unique_ptr<SkCanvas> SkCreateColorSpaceXformCanvas(SkCanvas* target,
                                                        sk_sp<SkColorSpace> targetCS) {
    std::unique_ptr<SkColorSpaceXformer> xformer = SkColorSpaceXformer::Make(std::move(targetCS));
    if (!xformer) {
        return nullptr;
    }

    return skstd::make_unique<SkColorSpaceXformCanvas>(target, std::move(xformer));
}
<commit_msg>avoid deprecated SkRect::MakeFromIRect<commit_after>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkColorFilter.h"
#include "SkColorSpaceXformCanvas.h"
#include "SkColorSpaceXformer.h"
#include "SkGradientShader.h"
#include "SkImage_Base.h"
#include "SkMakeUnique.h"
#include "SkNoDrawCanvas.h"
#include "SkSurface.h"

class SkColorSpaceXformCanvas : public SkNoDrawCanvas {
public:
    SkColorSpaceXformCanvas(SkCanvas* target,
                            std::unique_ptr<SkColorSpaceXformer> xformer)
        : SkNoDrawCanvas(SkIRect::MakeSize(target->getBaseLayerSize()))
        , fTarget(target)
        , fXformer(std::move(xformer))
    {
        // Set the matrix and clip to match |fTarget|.  Otherwise, we'll answer queries for
        // bounds/matrix differently than |fTarget| would.
        SkCanvas::onClipRect(SkRect::Make(fTarget->getDeviceClipBounds()),
                             SkClipOp::kIntersect, kHard_ClipEdgeStyle);
        SkCanvas::setMatrix(fTarget->getTotalMatrix());
    }

    SkImageInfo onImageInfo() const override {
        return fTarget->imageInfo();
    }

    void onDrawPaint(const SkPaint& paint) override {
        fTarget->drawPaint(fXformer->apply(paint));
    }

    void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
        fTarget->drawRect(rect, fXformer->apply(paint));
    }
    void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
        fTarget->drawOval(oval, fXformer->apply(paint));
    }
    void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
        fTarget->drawRRect(rrect, fXformer->apply(paint));
    }
    void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override {
        fTarget->drawDRRect(outer, inner, fXformer->apply(paint));
    }
    void onDrawPath(const SkPath& path, const SkPaint& paint) override {
        fTarget->drawPath(path, fXformer->apply(paint));
    }
    void onDrawArc(const SkRect& oval, SkScalar start, SkScalar sweep, bool useCenter,
                   const SkPaint& paint) override {
        fTarget->drawArc(oval, start, sweep, useCenter, fXformer->apply(paint));
    }
    void onDrawRegion(const SkRegion& region, const SkPaint& paint) override {
        fTarget->drawRegion(region, fXformer->apply(paint));
    }
    void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
                     SkBlendMode mode, const SkPaint& paint) override {
        SkColor xformed[4];
        if (colors) {
            fXformer->apply(xformed, colors, 4);
            colors = xformed;
        }

        fTarget->drawPatch(cubics, colors, texs, mode, fXformer->apply(paint));
    }
    void onDrawPoints(PointMode mode, size_t count, const SkPoint* pts,
                      const SkPaint& paint) override {
        fTarget->drawPoints(mode, count, pts, fXformer->apply(paint));
    }
    void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
                              const SkPaint& paint) override {
        sk_sp<SkVertices> copy;
        if (vertices->hasColors()) {
            int count = vertices->vertexCount();
            SkSTArray<8, SkColor> xformed(count);
            fXformer->apply(xformed.begin(), vertices->colors(), count);
            copy = SkVertices::MakeCopy(vertices->mode(), count, vertices->positions(),
                                        vertices->texCoords(), xformed.begin(),
                                        vertices->indexCount(), vertices->indices());
            vertices = copy.get();
        }

        fTarget->drawVertices(vertices, mode, fXformer->apply(paint));
    }

    void onDrawText(const void* ptr, size_t len,
                    SkScalar x, SkScalar y,
                    const SkPaint& paint) override {
        fTarget->drawText(ptr, len, x, y, fXformer->apply(paint));
    }
    void onDrawPosText(const void* ptr, size_t len,
                       const SkPoint* xys,
                       const SkPaint& paint) override {
        fTarget->drawPosText(ptr, len, xys, fXformer->apply(paint));
    }
    void onDrawPosTextH(const void* ptr, size_t len,
                        const SkScalar* xs, SkScalar y,
                        const SkPaint& paint) override {
        fTarget->drawPosTextH(ptr, len, xs, y, fXformer->apply(paint));
    }
    void onDrawTextOnPath(const void* ptr, size_t len,
                          const SkPath& path, const SkMatrix* matrix,
                          const SkPaint& paint) override {
        fTarget->drawTextOnPath(ptr, len, path, matrix, fXformer->apply(paint));
    }
    void onDrawTextRSXform(const void* ptr, size_t len,
                           const SkRSXform* xforms, const SkRect* cull,
                           const SkPaint& paint) override {
        fTarget->drawTextRSXform(ptr, len, xforms, cull, fXformer->apply(paint));
    }
    void onDrawTextBlob(const SkTextBlob* blob,
                        SkScalar x, SkScalar y,
                        const SkPaint& paint) override {
        fTarget->drawTextBlob(blob, x, y, fXformer->apply(paint));
    }

    void onDrawImage(const SkImage* img,
                     SkScalar l, SkScalar t,
                     const SkPaint* paint) override {
        fTarget->drawImage(fXformer->apply(img).get(),
                           l, t,
                           fXformer->apply(paint));
    }
    void onDrawImageRect(const SkImage* img,
                         const SkRect* src, const SkRect& dst,
                         const SkPaint* paint, SrcRectConstraint constraint) override {
        fTarget->drawImageRect(fXformer->apply(img).get(),
                               src ? *src : dst, dst,
                               fXformer->apply(paint), constraint);
    }
    void onDrawImageNine(const SkImage* img,
                         const SkIRect& center, const SkRect& dst,
                         const SkPaint* paint) override {
        fTarget->drawImageNine(fXformer->apply(img).get(),
                               center, dst,
                               fXformer->apply(paint));
    }
    void onDrawImageLattice(const SkImage* img,
                            const Lattice& lattice, const SkRect& dst,
                            const SkPaint* paint) override {
        fTarget->drawImageLattice(fXformer->apply(img).get(),
                                  lattice, dst,
                                  fXformer->apply(paint));
    }
    void onDrawAtlas(const SkImage* atlas, const SkRSXform* xforms, const SkRect* tex,
                     const SkColor* colors, int count, SkBlendMode mode,
                     const SkRect* cull, const SkPaint* paint) override {
        SkSTArray<8, SkColor> xformed;
        if (colors) {
            xformed.reset(count);
            fXformer->apply(xformed.begin(), colors, count);
            colors = xformed.begin();
        }

        fTarget->drawAtlas(fXformer->apply(atlas).get(), xforms, tex, colors, count, mode, cull,
                           fXformer->apply(paint));
    }

    void onDrawBitmap(const SkBitmap& bitmap,
                      SkScalar l, SkScalar t,
                      const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImage(image.get(), l, t, paint);
        }
    }
    void onDrawBitmapRect(const SkBitmap& bitmap,
                          const SkRect* src, const SkRect& dst,
                          const SkPaint* paint, SrcRectConstraint constraint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImageRect(image.get(), src, dst, paint, constraint);
        }
    }
    void onDrawBitmapNine(const SkBitmap& bitmap,
                          const SkIRect& center, const SkRect& dst,
                          const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImageNine(image.get(), center, dst, paint);
        }
    }
    void onDrawBitmapLattice(const SkBitmap& bitmap,
                             const Lattice& lattice, const SkRect& dst,
                             const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImageLattice(image.get(), lattice, dst, paint);
        }
    }

    // TODO: May not be ideal to unfurl pictures.
    void onDrawPicture(const SkPicture* pic,
                       const SkMatrix* matrix,
                       const SkPaint* paint) override {
        SkCanvas::onDrawPicture(pic, matrix, fXformer->apply(paint));
    }
    void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
        SkCanvas::onDrawDrawable(drawable, matrix);
    }

    SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override {
        fTarget->saveLayer({
            rec.fBounds,
            fXformer->apply(rec.fPaint),
            rec.fBackdrop,  // TODO: this is an image filter
            rec.fSaveLayerFlags,
        });
        return kNoLayer_SaveLayerStrategy;
    }

    // Everything from here on should be uninteresting strictly proxied state-change calls.
    void willSave()    override { fTarget->save(); }
    void willRestore() override { fTarget->restore(); }

    void didConcat   (const SkMatrix& m) override { fTarget->concat   (m); }
    void didSetMatrix(const SkMatrix& m) override { fTarget->setMatrix(m); }

    void onClipRect(const SkRect& clip, SkClipOp op, ClipEdgeStyle style) override {
        SkCanvas::onClipRect(clip, op, style);
        fTarget->clipRect(clip, op, style);
    }
    void onClipRRect(const SkRRect& clip, SkClipOp op, ClipEdgeStyle style) override {
        SkCanvas::onClipRRect(clip, op, style);
        fTarget->clipRRect(clip, op, style);
    }
    void onClipPath(const SkPath& clip, SkClipOp op, ClipEdgeStyle style) override {
        SkCanvas::onClipPath(clip, op, style);
        fTarget->clipPath(clip, op, style);
    }
    void onClipRegion(const SkRegion& clip, SkClipOp op) override {
        SkCanvas::onClipRegion(clip, op);
        fTarget->clipRegion(clip, op);
    }

    void onDrawAnnotation(const SkRect& rect, const char* key, SkData* val) override {
        fTarget->drawAnnotation(rect, key, val);
    }

    sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) override {
        return fTarget->makeSurface(info, &props);
    }

    SkISize getBaseLayerSize() const override { return fTarget->getBaseLayerSize(); }
    SkRect onGetLocalClipBounds() const override { return fTarget->getLocalClipBounds(); }
    SkIRect onGetDeviceClipBounds() const override { return fTarget->getDeviceClipBounds(); }
    bool isClipEmpty() const override { return fTarget->isClipEmpty(); }
    bool isClipRect() const override { return fTarget->isClipRect(); }
    bool onPeekPixels(SkPixmap* pixmap) override { return fTarget->peekPixels(pixmap); }
    bool onAccessTopLayerPixels(SkPixmap* pixmap) override {
        SkImageInfo info;
        size_t rowBytes;
        SkIPoint* origin = nullptr;
        void* addr = fTarget->accessTopLayerPixels(&info, &rowBytes, origin);
        if (addr) {
            *pixmap = SkPixmap(info, addr, rowBytes);
            return true;
        }
        return false;
    }

    bool onGetProps(SkSurfaceProps* props) const override { return fTarget->getProps(props); }
    void onFlush() override { return fTarget->flush(); }

private:
    SkCanvas*                            fTarget;
    std::unique_ptr<SkColorSpaceXformer> fXformer;
};

std::unique_ptr<SkCanvas> SkCreateColorSpaceXformCanvas(SkCanvas* target,
                                                        sk_sp<SkColorSpace> targetCS) {
    std::unique_ptr<SkColorSpaceXformer> xformer = SkColorSpaceXformer::Make(std::move(targetCS));
    if (!xformer) {
        return nullptr;
    }

    return skstd::make_unique<SkColorSpaceXformCanvas>(target, std::move(xformer));
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*
COPYING CONDITIONS NOTICE:

  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation, and provided that the
  following conditions are met:

      * Redistributions of source code must retain this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below).

      * Redistributions in binary form must reproduce this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below) in the documentation and/or other materials
        provided with the distribution.

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

COPYRIGHT NOTICE:

  TokuDB, Tokutek Fractal Tree Indexing Library.
  Copyright (C) 2007-2013 Tokutek, Inc.

DISCLAIMER:

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

UNIVERSITY PATENT NOTICE:

  The technology is licensed by the Massachusetts Institute of
  Technology, Rutgers State University of New Jersey, and the Research
  Foundation of State University of New York at Stony Brook under
  United States of America Serial No. 11/760379 and to the patents
  and/or patent applications resulting from it.

PATENT MARKING NOTICE:

  This software is covered by US Patent No. 8,185,551.
  This software is covered by US Patent No. 8,489,638.

PATENT RIGHTS GRANT:

  "THIS IMPLEMENTATION" means the copyrightable works distributed by
  Tokutek as part of the Fractal Tree project.

  "PATENT CLAIMS" means the claims of patents that are owned or
  licensable by Tokutek, both currently or in the future; and that in
  the absence of this license would be infringed by THIS
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.

  "PATENT CHALLENGE" shall mean a challenge to the validity,
  patentability, enforceability and/or non-infringement of any of the
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.

  Tokutek hereby grants to you, for the term and geographical scope of
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
  irrevocable (except as stated in this section) patent license to
  make, have made, use, offer to sell, sell, import, transfer, and
  otherwise run, modify, and propagate the contents of THIS
  IMPLEMENTATION, where such license applies only to the PATENT
  CLAIMS.  This grant does not include claims that would be infringed
  only as a consequence of further modifications of THIS
  IMPLEMENTATION.  If you or your agent or licensee institute or order
  or agree to the institution of patent litigation against any entity
  (including a cross-claim or counterclaim in a lawsuit) alleging that
  THIS IMPLEMENTATION constitutes direct or contributory patent
  infringement, or inducement of patent infringement, then any rights
  granted to you under this License shall terminate as of the date
  such litigation is filed.  If you or your agent or exclusive
  licensee institute or order or agree to the institution of a PATENT
  CHALLENGE, then Tokutek may terminate any rights granted to you
  under this License.
*/

#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

// Create a lot of dirty nodes, kick off a checkpoint, and close the environment.
// Measure the time it takes to close the environment since we are speeding up that
// function.

#include "test.h"
#include <endian.h>
#include <toku_time.h>

// Insert max_rows key/val pairs into the db
static void do_inserts(DB_ENV *env, DB *db, uint64_t max_rows, size_t val_size) {
    char val_data[val_size]; memset(val_data, 0, val_size);
    int r;
    DB_TXN *txn = nullptr;
    r = env->txn_begin(env, nullptr, &txn, 0);
    CKERR(r);

    for (uint64_t i = 1; i <= max_rows; i++) {
        // pick a sequential key but it does not matter for this test.
        uint64_t k[2] = {
            htobe64(i), random64(),
        };
        DBT key = { .data = k, .size = sizeof k };
        DBT val = { .data = val_data, .size = (uint32_t) val_size };
        r = db->put(db, txn, &key, &val, 0);
        CKERR(r);

        if ((i % 1000) == 0) {
            if (verbose)
                fprintf(stderr, "put %" PRIu64 "\n", i);
            r = txn->commit(txn, 0);
            CKERR(r);
            r = env->txn_begin(env, nullptr, &txn, 0);
            CKERR(r);
        }
    }

    r = txn->commit(txn, 0);
    CKERR(r);
}

// Create a cache with a lot of dirty nodes, kick off a checkpoint, and measure the time to
// close the environment.
static void big_shutdown(void) {
    int r;

    DB_ENV *env = nullptr;
    r = db_env_create(&env, 0);
    CKERR(r);
    r = env->set_cachesize(env, 8, 0, 1);
    CKERR(r);
    r = env->open(env, TOKU_TEST_FILENAME,
                  DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE,
                  S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    DB *db = nullptr;
    r = db_create(&db, env, 0);
    CKERR(r);
    r = db->open(db, nullptr, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    do_inserts(env, db, 1000000, 1024);

    // kick the checkpoint thread
    if (verbose)
        fprintf(stderr, "env->checkpointing_set_period\n");
    r = env->checkpointing_set_period(env, 2);
    CKERR(r);
    sleep(3);

    if (verbose)
        fprintf(stderr, "db->close\n");
    r = db->close(db, 0);
    CKERR(r);

    // measure the shutdown time
    uint64_t tstart = toku_current_time_microsec();
    if (verbose)
        fprintf(stderr, "env->close\n");
    r = env->close(env, 0);
    CKERR(r);
    uint64_t tend = toku_current_time_microsec();
    if (verbose)
        fprintf(stderr, "env->close complete %" PRIu64 " sec\n", (tend - tstart)/1000000);
}

int test_main (int argc, char *const argv[]) {
    default_parse_args(argc, argv);

    // init the env directory
    toku_os_recursive_delete(TOKU_TEST_FILENAME);
    int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    // run the test
    big_shutdown();

    return 0;
}
<commit_msg>FT-312 fix centos compile<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*
COPYING CONDITIONS NOTICE:

  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation, and provided that the
  following conditions are met:

      * Redistributions of source code must retain this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below).

      * Redistributions in binary form must reproduce this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below) in the documentation and/or other materials
        provided with the distribution.

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

COPYRIGHT NOTICE:

  TokuDB, Tokutek Fractal Tree Indexing Library.
  Copyright (C) 2007-2013 Tokutek, Inc.

DISCLAIMER:

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

UNIVERSITY PATENT NOTICE:

  The technology is licensed by the Massachusetts Institute of
  Technology, Rutgers State University of New Jersey, and the Research
  Foundation of State University of New York at Stony Brook under
  United States of America Serial No. 11/760379 and to the patents
  and/or patent applications resulting from it.

PATENT MARKING NOTICE:

  This software is covered by US Patent No. 8,185,551.
  This software is covered by US Patent No. 8,489,638.

PATENT RIGHTS GRANT:

  "THIS IMPLEMENTATION" means the copyrightable works distributed by
  Tokutek as part of the Fractal Tree project.

  "PATENT CLAIMS" means the claims of patents that are owned or
  licensable by Tokutek, both currently or in the future; and that in
  the absence of this license would be infringed by THIS
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.

  "PATENT CHALLENGE" shall mean a challenge to the validity,
  patentability, enforceability and/or non-infringement of any of the
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.

  Tokutek hereby grants to you, for the term and geographical scope of
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
  irrevocable (except as stated in this section) patent license to
  make, have made, use, offer to sell, sell, import, transfer, and
  otherwise run, modify, and propagate the contents of THIS
  IMPLEMENTATION, where such license applies only to the PATENT
  CLAIMS.  This grant does not include claims that would be infringed
  only as a consequence of further modifications of THIS
  IMPLEMENTATION.  If you or your agent or licensee institute or order
  or agree to the institution of patent litigation against any entity
  (including a cross-claim or counterclaim in a lawsuit) alleging that
  THIS IMPLEMENTATION constitutes direct or contributory patent
  infringement, or inducement of patent infringement, then any rights
  granted to you under this License shall terminate as of the date
  such litigation is filed.  If you or your agent or exclusive
  licensee institute or order or agree to the institution of a PATENT
  CHALLENGE, then Tokutek may terminate any rights granted to you
  under this License.
*/

#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

// Create a lot of dirty nodes, kick off a checkpoint, and close the environment.
// Measure the time it takes to close the environment since we are speeding up that
// function.

#include "test.h"
#include <endian.h>
#include <toku_time.h>

#ifndef htobe64
#define htobe64(x) __bswap_64(x)
#endif

// Insert max_rows key/val pairs into the db
static void do_inserts(DB_ENV *env, DB *db, uint64_t max_rows, size_t val_size) {
    char val_data[val_size]; memset(val_data, 0, val_size);
    int r;
    DB_TXN *txn = nullptr;
    r = env->txn_begin(env, nullptr, &txn, 0);
    CKERR(r);

    for (uint64_t i = 1; i <= max_rows; i++) {
        // pick a sequential key but it does not matter for this test.
        uint64_t k[2] = {
            htobe64(i), random64(),
        };
        DBT key = { .data = k, .size = sizeof k };
        DBT val = { .data = val_data, .size = (uint32_t) val_size };
        r = db->put(db, txn, &key, &val, 0);
        CKERR(r);

        if ((i % 1000) == 0) {
            if (verbose)
                fprintf(stderr, "put %" PRIu64 "\n", i);
            r = txn->commit(txn, 0);
            CKERR(r);
            r = env->txn_begin(env, nullptr, &txn, 0);
            CKERR(r);
        }
    }

    r = txn->commit(txn, 0);
    CKERR(r);
}

// Create a cache with a lot of dirty nodes, kick off a checkpoint, and measure the time to
// close the environment.
static void big_shutdown(void) {
    int r;

    DB_ENV *env = nullptr;
    r = db_env_create(&env, 0);
    CKERR(r);
    r = env->set_cachesize(env, 8, 0, 1);
    CKERR(r);
    r = env->open(env, TOKU_TEST_FILENAME,
                  DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE,
                  S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    DB *db = nullptr;
    r = db_create(&db, env, 0);
    CKERR(r);
    r = db->open(db, nullptr, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    do_inserts(env, db, 1000000, 1024);

    // kick the checkpoint thread
    if (verbose)
        fprintf(stderr, "env->checkpointing_set_period\n");
    r = env->checkpointing_set_period(env, 2);
    CKERR(r);
    sleep(3);

    if (verbose)
        fprintf(stderr, "db->close\n");
    r = db->close(db, 0);
    CKERR(r);

    // measure the shutdown time
    uint64_t tstart = toku_current_time_microsec();
    if (verbose)
        fprintf(stderr, "env->close\n");
    r = env->close(env, 0);
    CKERR(r);
    uint64_t tend = toku_current_time_microsec();
    if (verbose)
        fprintf(stderr, "env->close complete %" PRIu64 " sec\n", (tend - tstart)/1000000);
}

int test_main (int argc, char *const argv[]) {
    default_parse_args(argc, argv);

    // init the env directory
    toku_os_recursive_delete(TOKU_TEST_FILENAME);
    int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    // run the test
    big_shutdown();

    return 0;
}
<|endoftext|>