<commit_before>// Copyright (c) 2007, 2008 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include <cmath>

#include "libmv/image/image.h"
#include "libmv/image/convolve.h"

namespace libmv {

// Compute a Gaussian kernel and derivative, such that you can take the
// derivative of an image by convolving with the kernel horizontally then the
// derivative vertically to get (eg) the y derivative.
void ComputeGaussianKernel(double sigma, Vec *kernel, Vec *derivative) {
  assert(sigma >= 0.0);

  // 0.004 implies a 3 pixel kernel with 1 pixel sigma.
  const float truncation_factor = 0.004f;

  // Calculate the kernel size based on sigma such that it is odd.
  float precisehalfwidth = GaussianInversePositive(truncation_factor, sigma);
  int width = lround(2*precisehalfwidth);
  if (width % 2 == 0) {
    width++;
  }
  // Calculate the gaussian kernel and its derivative.
  kernel->resize(width);
  derivative->resize(width);
  kernel->setZero();
  derivative->setZero();
  int halfwidth = width / 2;
  for (int i = -halfwidth; i <= halfwidth; ++i)  {
    (*kernel)(i + halfwidth) = Gaussian(i, sigma);
    (*derivative)(i + halfwidth) = GaussianDerivative(i, sigma);
  }
  // Since images should not get brighter or darker, normalize.
  NormalizeL1(kernel);

  // Normalize the derivative differently. See
  // www.cs.duke.edu/courses/spring03/cps296.1/handouts/Image%20Processing.pdf
  double factor = 0.;
  for (int i = -halfwidth; i <= halfwidth; ++i)  {
    factor -= i*(*derivative)(i+halfwidth);
  }
  *derivative /= factor;
}

template <int size, bool vertical>
void FastConvolve(const Vec &kernel, int width, int height,
                  const float* src, int src_stride, int src_line_stride,
                  float* dst, int dst_stride) {
  double coefficients[2 * size + 1];
  for (int k = 0; k < 2 * size + 1; ++k) {
    coefficients[k] = kernel(2 * size - k);
  }
  // Fast path: if the kernel has a certain size, use the constant sized loops.
  for (int y = 0; y < height; ++y) {
    for (int x = 0; x < width; ++x) {
      double sum = 0;
      for (int k = -size; k <= size; ++k) {
        if (vertical) {
          if (y + k >= 0 && y + k < height) {
            sum += src[k * src_line_stride] * coefficients[k + size];
          }
        } else {
          if (x + k >= 0 && x + k < width) {
            sum += src[k * src_stride] * coefficients[k + size];
          }
        }
      }
      dst[0] = static_cast<float>(sum);
      src += src_stride;
      dst += dst_stride;
    }
  }
}

template<bool vertical>
void Convolve(const Array3Df &in,
              const Vec &kernel,
              Array3Df *out_pointer,
              int plane) {
  int width = in.Width();
  int height = in.Height();
  Array3Df &out = *out_pointer;
  if (plane == -1) {
    out.ResizeLike(in);
    plane = 0;
  }

  assert(kernel.size() % 2 == 1);
  assert(&in != out_pointer);

  int src_line_stride = in.Stride(0);
  int src_stride = in.Stride(1);
  int dst_stride = out.Stride(1);
  const float* src = in.Data();
  float* dst = out.Data()+plane;

  // Use a dispatch table to make most convolutions used in practice use the
  // fast path.
  int half_width = kernel.size() / 2;
  switch (half_width) {
    case 1:
      FastConvolve<1, vertical>(kernel, width, height, src, src_stride,
                                src_line_stride, dst, dst_stride);
      break;
    case 2:
      FastConvolve<2, vertical>(kernel, width, height, src, src_stride,
                                src_line_stride, dst, dst_stride);
      break;
    case 3:
      FastConvolve<3, vertical>(kernel, width, height, src, src_stride,
                                src_line_stride, dst, dst_stride);
      break;
    case 4:
      FastConvolve<4, vertical>(kernel, width, height, src, src_stride,
                                src_line_stride, dst, dst_stride);
      break;
    case 5:
      FastConvolve<5, vertical>(kernel, width, height, src, src_stride,
                                src_line_stride, dst, dst_stride);
      break;
    case 6:
      FastConvolve<6, vertical>(kernel, width, height, src, src_stride,
                                src_line_stride, dst, dst_stride);
      break;
    case 7:
      FastConvolve<7, vertical>(kernel, width, height, src, src_stride,
                                src_line_stride, dst, dst_stride);
      break;
    default:
      int dynamic_size = kernel.size() / 2;
      for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
          double sum = 0;
          // Slow path: this loop cannot be unrolled.
          for (int k = -dynamic_size; k <= dynamic_size; ++k) {
            if(vertical) {
              if (y + k >= 0 && y + k < height) {
                sum += src[k * src_line_stride] * kernel(2 * dynamic_size - (k + dynamic_size));
              }
            } else {
              if (x + k >= 0 && x + k < width) {
                sum += src[k * src_stride] * kernel(2 * dynamic_size - (k + dynamic_size));
              }
            }
          }
          dst[0] = static_cast<float>(sum);
          src += src_stride;
          dst += dst_stride;
        }
      }
  }
}

void ConvolveHorizontal(const Array3Df &in,
                        const Vec &kernel,
                        Array3Df *out_pointer,
                        int plane) {
  Convolve<false>(in, kernel, out_pointer, plane);
}

void ConvolveVertical(const Array3Df &in,
                      const Vec &kernel,
                      Array3Df *out_pointer,
                      int plane) {
  Convolve<true>(in, kernel, out_pointer, plane);
}

void ConvolveGaussian(const Array3Df &in,
                      double sigma,
                      Array3Df *out_pointer) {
  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);

  Array3Df tmp;
  ConvolveVertical(in, kernel, &tmp);
  ConvolveHorizontal(tmp, kernel, out_pointer);
}

void BlurredImageAndDerivatives(const Array3Df &in,
                                double sigma,
                                Array3Df *blurred_image,
                                Array3Df *gradient_x,
                                Array3Df *gradient_y) {
  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);
  Array3Df tmp;

  // Compute convolved image.
  ConvolveVertical(in, kernel, &tmp);
  ConvolveHorizontal(tmp, kernel, blurred_image);

  // Compute first derivative in x (reusing vertical convolution above).
  ConvolveHorizontal(tmp, derivative, gradient_x);

  // Compute first derivative in y.
  ConvolveHorizontal(in, kernel, &tmp);
  ConvolveVertical(tmp, derivative, gradient_y);
}

// Compute the gaussian blur of an image and the derivatives of the blurred
// image, and store the results in three channels. Since the blurred value and
// gradients are closer in memory, this leads to better performance if all
// three values are needed at the same time.
void BlurredImageAndDerivativesChannels(const Array3Df &in,
                                        double sigma,
                                        Array3Df *blurred_and_gradxy) {
  assert(in.Depth() == 1);

  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);

  // Compute convolved image.
  Array3Df tmp;
  ConvolveVertical(in, kernel, &tmp);
  blurred_and_gradxy->Resize(in.Height(), in.Width(), 3);
  ConvolveHorizontal(tmp, kernel, blurred_and_gradxy, 0);

  // Compute first derivative in x.
  ConvolveHorizontal(tmp, derivative, blurred_and_gradxy, 1);

  // Compute first derivative in y.
  ConvolveHorizontal(in, kernel, &tmp);
  ConvolveVertical(tmp, derivative, blurred_and_gradxy, 2);
}

void BoxFilterHorizontal(const Array3Df &in,
                         int window_size,
                         Array3Df *out_pointer) {
  Array3Df &out = *out_pointer;
  out.ResizeLike(in);
  int half_width = (window_size - 1) / 2;

  for (int k = 0; k < in.Depth(); ++k) {
    for (int i=0; i<in.Height(); ++i) {
      float sum = 0;
      // Init sum.
      for (int j=0; j<half_width; ++j) {
        sum += in(i, j, k);
      }
      // Fill left border.
      for (int j=0; j < half_width + 1; ++j) {
        sum += in(i, j + half_width, k);
        out(i, j, k) = sum;
      }
      // Fill interior.
      for (int j = half_width + 1; j<in.Width()-half_width; ++j) {
        sum -= in(i, j - half_width - 1, k);
        sum += in(i, j + half_width, k);
        out(i, j, k) = sum;
      }
      // Fill right border.
      for (int j = in.Width() - half_width; j<in.Width(); ++j) {
        sum -= in(i, j - half_width - 1, k);
        out(i, j, k) = sum;
      }
    }
  }
}

void BoxFilterVertical(const Array3Df &in,
                       int window_size,
                       Array3Df *out_pointer) {
  Array3Df &out = *out_pointer;
  out.ResizeLike(in);
  int half_width = (window_size - 1) / 2;

  for (int k = 0; k < in.Depth(); ++k) {
    for (int j = 0; j < in.Width(); ++j) {
      float sum = 0;
      // Init sum.
      for (int i=0; i<half_width; ++i) {
        sum += in(i, j, k);
      }
      // Fill left border.
      for (int i=0; i < half_width + 1; ++i) {
        sum += in(i + half_width, j, k);
        out(i, j, k) = sum;
      }
      // Fill interior.
      for (int i = half_width + 1; i<in.Height()-half_width; ++i) {
        sum -= in(i - half_width - 1, j, k);
        sum += in(i + half_width, j, k);
        out(i, j, k) = sum;
      }
      // Fill right border.
      for (int i = in.Height() - half_width; i<in.Height(); ++i) {
        sum -= in(i - half_width - 1, j, k);
        out(i, j, k) = sum;
      }
    }
  }
}

void BoxFilter(const Array3Df &in,
               int box_width,
               Array3Df *out) {
  Array3Df tmp;
  BoxFilterHorizontal(in, box_width, &tmp);
  BoxFilterVertical(tmp, box_width, out);
}

}  // namespace libmv
<commit_msg>Reduce convolution boilerplate.<commit_after>// Copyright (c) 2007, 2008 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include <cmath>

#include "libmv/image/image.h"
#include "libmv/image/convolve.h"

namespace libmv {

// Compute a Gaussian kernel and derivative, such that you can take the
// derivative of an image by convolving with the kernel horizontally then the
// derivative vertically to get (eg) the y derivative.
void ComputeGaussianKernel(double sigma, Vec *kernel, Vec *derivative) {
  assert(sigma >= 0.0);

  // 0.004 implies a 3 pixel kernel with 1 pixel sigma.
  const float truncation_factor = 0.004f;

  // Calculate the kernel size based on sigma such that it is odd.
  float precisehalfwidth = GaussianInversePositive(truncation_factor, sigma);
  int width = lround(2*precisehalfwidth);
  if (width % 2 == 0) {
    width++;
  }
  // Calculate the gaussian kernel and its derivative.
  kernel->resize(width);
  derivative->resize(width);
  kernel->setZero();
  derivative->setZero();
  int halfwidth = width / 2;
  for (int i = -halfwidth; i <= halfwidth; ++i)  {
    (*kernel)(i + halfwidth) = Gaussian(i, sigma);
    (*derivative)(i + halfwidth) = GaussianDerivative(i, sigma);
  }
  // Since images should not get brighter or darker, normalize.
  NormalizeL1(kernel);

  // Normalize the derivative differently. See
  // www.cs.duke.edu/courses/spring03/cps296.1/handouts/Image%20Processing.pdf
  double factor = 0.;
  for (int i = -halfwidth; i <= halfwidth; ++i)  {
    factor -= i*(*derivative)(i+halfwidth);
  }
  *derivative /= factor;
}

template <int size, bool vertical>
void FastConvolve(const Vec &kernel, int width, int height,
                  const float* src, int src_stride, int src_line_stride,
                  float* dst, int dst_stride) {
  double coefficients[2 * size + 1];
  for (int k = 0; k < 2 * size + 1; ++k) {
    coefficients[k] = kernel(2 * size - k);
  }
  // Fast path: if the kernel has a certain size, use the constant sized loops.
  for (int y = 0; y < height; ++y) {
    for (int x = 0; x < width; ++x) {
      double sum = 0;
      for (int k = -size; k <= size; ++k) {
        if (vertical) {
          if (y + k >= 0 && y + k < height) {
            sum += src[k * src_line_stride] * coefficients[k + size];
          }
        } else {
          if (x + k >= 0 && x + k < width) {
            sum += src[k * src_stride] * coefficients[k + size];
          }
        }
      }
      dst[0] = static_cast<float>(sum);
      src += src_stride;
      dst += dst_stride;
    }
  }
}

template<bool vertical>
void Convolve(const Array3Df &in,
              const Vec &kernel,
              Array3Df *out_pointer,
              int plane) {
  int width = in.Width();
  int height = in.Height();
  Array3Df &out = *out_pointer;
  if (plane == -1) {
    out.ResizeLike(in);
    plane = 0;
  }

  assert(kernel.size() % 2 == 1);
  assert(&in != out_pointer);

  int src_line_stride = in.Stride(0);
  int src_stride = in.Stride(1);
  int dst_stride = out.Stride(1);
  const float* src = in.Data();
  float* dst = out.Data() + plane;

  // Use a dispatch table to make most convolutions used in practice use the
  // fast path.
  int half_width = kernel.size() / 2;
  switch (half_width) {
#define static_convolution( size ) case size: \
  FastConvolve<size, vertical>(kernel, width, height, src, src_stride, \
                               src_line_stride, dst, dst_stride); break;
    static_convolution(1)
    static_convolution(2)
    static_convolution(3)
    static_convolution(4)
    static_convolution(5)
    static_convolution(6)
    static_convolution(7)
#undef static_convolution
    default:
      int dynamic_size = kernel.size() / 2;
      for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
          double sum = 0;
          // Slow path: this loop cannot be unrolled.
          for (int k = -dynamic_size; k <= dynamic_size; ++k) {
            if(vertical) {
              if (y + k >= 0 && y + k < height) {
                sum += src[k * src_line_stride] * kernel(2 * dynamic_size - (k + dynamic_size));
              }
            } else {
              if (x + k >= 0 && x + k < width) {
                sum += src[k * src_stride] * kernel(2 * dynamic_size - (k + dynamic_size));
              }
            }
          }
          dst[0] = static_cast<float>(sum);
          src += src_stride;
          dst += dst_stride;
        }
      }
  }
}

void ConvolveHorizontal(const Array3Df &in,
                        const Vec &kernel,
                        Array3Df *out_pointer,
                        int plane) {
  Convolve<false>(in, kernel, out_pointer, plane);
}

void ConvolveVertical(const Array3Df &in,
                      const Vec &kernel,
                      Array3Df *out_pointer,
                      int plane) {
  Convolve<true>(in, kernel, out_pointer, plane);
}

void ConvolveGaussian(const Array3Df &in,
                      double sigma,
                      Array3Df *out_pointer) {
  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);

  Array3Df tmp;
  ConvolveVertical(in, kernel, &tmp);
  ConvolveHorizontal(tmp, kernel, out_pointer);
}

void BlurredImageAndDerivatives(const Array3Df &in,
                                double sigma,
                                Array3Df *blurred_image,
                                Array3Df *gradient_x,
                                Array3Df *gradient_y) {
  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);
  Array3Df tmp;

  // Compute convolved image.
  ConvolveVertical(in, kernel, &tmp);
  ConvolveHorizontal(tmp, kernel, blurred_image);

  // Compute first derivative in x (reusing vertical convolution above).
  ConvolveHorizontal(tmp, derivative, gradient_x);

  // Compute first derivative in y.
  ConvolveHorizontal(in, kernel, &tmp);
  ConvolveVertical(tmp, derivative, gradient_y);
}

// Compute the gaussian blur of an image and the derivatives of the blurred
// image, and store the results in three channels. Since the blurred value and
// gradients are closer in memory, this leads to better performance if all
// three values are needed at the same time.
void BlurredImageAndDerivativesChannels(const Array3Df &in,
                                        double sigma,
                                        Array3Df *blurred_and_gradxy) {
  assert(in.Depth() == 1);

  Vec kernel, derivative;
  ComputeGaussianKernel(sigma, &kernel, &derivative);

  // Compute convolved image.
  Array3Df tmp;
  ConvolveVertical(in, kernel, &tmp);
  blurred_and_gradxy->Resize(in.Height(), in.Width(), 3);
  ConvolveHorizontal(tmp, kernel, blurred_and_gradxy, 0);

  // Compute first derivative in x.
  ConvolveHorizontal(tmp, derivative, blurred_and_gradxy, 1);

  // Compute first derivative in y.
  ConvolveHorizontal(in, kernel, &tmp);
  ConvolveVertical(tmp, derivative, blurred_and_gradxy, 2);
}

void BoxFilterHorizontal(const Array3Df &in,
                         int window_size,
                         Array3Df *out_pointer) {
  Array3Df &out = *out_pointer;
  out.ResizeLike(in);
  int half_width = (window_size - 1) / 2;

  for (int k = 0; k < in.Depth(); ++k) {
    for (int i=0; i<in.Height(); ++i) {
      float sum = 0;
      // Init sum.
      for (int j=0; j<half_width; ++j) {
        sum += in(i, j, k);
      }
      // Fill left border.
      for (int j=0; j < half_width + 1; ++j) {
        sum += in(i, j + half_width, k);
        out(i, j, k) = sum;
      }
      // Fill interior.
      for (int j = half_width + 1; j<in.Width()-half_width; ++j) {
        sum -= in(i, j - half_width - 1, k);
        sum += in(i, j + half_width, k);
        out(i, j, k) = sum;
      }
      // Fill right border.
      for (int j = in.Width() - half_width; j<in.Width(); ++j) {
        sum -= in(i, j - half_width - 1, k);
        out(i, j, k) = sum;
      }
    }
  }
}

void BoxFilterVertical(const Array3Df &in,
                       int window_size,
                       Array3Df *out_pointer) {
  Array3Df &out = *out_pointer;
  out.ResizeLike(in);
  int half_width = (window_size - 1) / 2;

  for (int k = 0; k < in.Depth(); ++k) {
    for (int j = 0; j < in.Width(); ++j) {
      float sum = 0;
      // Init sum.
      for (int i=0; i<half_width; ++i) {
        sum += in(i, j, k);
      }
      // Fill left border.
      for (int i=0; i < half_width + 1; ++i) {
        sum += in(i + half_width, j, k);
        out(i, j, k) = sum;
      }
      // Fill interior.
      for (int i = half_width + 1; i<in.Height()-half_width; ++i) {
        sum -= in(i - half_width - 1, j, k);
        sum += in(i + half_width, j, k);
        out(i, j, k) = sum;
      }
      // Fill right border.
      for (int i = in.Height() - half_width; i<in.Height(); ++i) {
        sum -= in(i - half_width - 1, j, k);
        out(i, j, k) = sum;
      }
    }
  }
}

void BoxFilter(const Array3Df &in,
               int box_width,
               Array3Df *out) {
  Array3Df tmp;
  BoxFilterHorizontal(in, box_width, &tmp);
  BoxFilterVertical(tmp, box_width, out);
}

}  // namespace libmv
<|endoftext|>


<commit_before>#include <rleahylib/rleahylib.hpp>
#include <chat/chat.hpp>
#include <command/command.hpp>
#include <permissions/permissions.hpp>
#include <mod.hpp>
#include <algorithm>

using namespace MCPP;

static const Word priority=1;
static const String name("Permissions Commands");
static const String add_identifier("addgroup");
static const String remove_identifier("removegroup");
static const String grant_identifier("grant");
static const String revoke_identifier("revoke");
static const String all_suffix("_all");
static const String identifiers []={
	grant_identifier,
	revoke_identifier,
	add_identifier,
	remove_identifier
};
static const String group_arg("-g");
static const String all_arg("-a");
static const String quiet_arg("-q");

class PermissionsCommand : public Module, public Command {

	private:

		class Arguments {

			public:

				bool All;
				bool Group;
				bool Quiet;
				String Name;
				Vector<String> Args;

		};

		static Nullable<Arguments> parse (Vector<String> args) {

			Nullable<Arguments> retr;

			if (args.Count()==0) return retr;

			retr.Construct();
			retr->All=false;
			retr->Group=false;
			retr->Quiet=false;
			bool first=true;
			bool complete=false;
			for (auto & s : args) {

				if (first) {

					if (s==group_arg) {

						if (retr->Group) break;

						retr->Group=true;

					} else if (s==all_arg) {

						if (retr->All) break;

						retr->All=true;

					} else if (s==quiet_arg) {

						if (retr->Quiet) break;

						retr->Quiet=true;

					} else {

						first=false;

						retr->Name=std::move(s);

						if (retr->All) complete=true;

					}

				} else if (retr->All) {

					break;

				} else {

					retr->Args.Add(std::move(s));

					complete=true;

				}

			}

			if (!complete) retr.Destroy();

			return retr;

		}

		enum class Type {

			Add,
			Remove,
			Grant,
			Revoke

		};

		static Type get_type (const String & str) noexcept {

			if (str==add_identifier) return Type::Add;
			if (str==remove_identifier) return Type::Remove;
			if (str==grant_identifier) return Type::Grant;
			return Type::Revoke;

		}

		static bool check_syntax (const String & identifier, const Arguments & args) {

			switch (get_type(identifier)) {

				case Type::Add:
				case Type::Remove:
					if (
						args.All ||
						(args.Args.Count()!=1)
					) return false;
					break;

				default:break;

			}

			return true;

		}

		static bool check_permissions (const String & identifier, const Arguments & args, const PermissionsHandle & handle) {

			//	If a user is granted the _all permission,
			//	they can always proceed
			if (handle.Check(identifier+all_suffix)) return true;

			//	If the user isn't granted the particular
			//	permission, they can never proceed
			if (!handle.Check(identifier)) return false;

			//	Otherwise check particular conditions
			switch (get_type(identifier)) {

				case Type::Add:
				case Type::Remove:

					//	User must be a member of the
					//	target group
					if (!handle.IsMember(args.Args[0])) return false;

					break;

				default:

					//	If we're granting/revoking all
					//	permissions, user must themselves
					//	have all permissions
					//
					//	Since we short-circuit out above
					//	if the user has a certain permission,
					//	getting here means the user does NOT
					//	have all permissions
					if (args.All) return false;

					//	Check each permission -- user
					//	must have them all
					for (auto & perm : args.Args) if (!handle.Check(perm)) return false;

					break;

			}

			return true;

		}

		static ChatMessage add_remove (PermissionsHandle handle, Arguments args, bool add) {

			ChatMessage retr;
			ChatMessage send;

			if (add) send << ChatStyle::BrightGreen << "Adding to ";
			else send << ChatStyle::Red << "Removing from ";

			send	<<	(handle.IsGroup() ? "group" : "user")
					<<	" "
					<<	ChatStyle::Bold
					<<	handle.Name()
					<<	ChatFormat::Pop
					<<	" group "
					<<	ChatStyle::Bold
					<<	args.Args[0];

			if (add) handle.Add(std::move(args.Args[0]));
			else handle.Remove(std::move(args.Args[0]));

			if (args.Quiet) retr=std::move(send);
			else Chat::Get().Send(send);

			return retr;

		}

		static ChatMessage add (PermissionsHandle handle, Arguments args) {

			return add_remove(
				std::move(handle),
				std::move(args),
				true
			);

		}

		static ChatMessage remove (PermissionsHandle handle, Arguments args) {

			return add_remove(
				std::move(handle),
				std::move(args),
				false
			);

		}

		static ChatMessage grant_revoke (PermissionsHandle handle, Arguments args, bool grant) {

			ChatMessage retr;
			ChatMessage send;

			std::sort(args.Args.begin(),args.Args.end());

			if (grant) send << ChatStyle::BrightGreen << "Granting";
			else send << ChatStyle::Red << "Revoking from";

			send	<<	" "
					<<	(handle.IsGroup() ? "group" : "user")
					<<	" "
					<<	ChatStyle::Bold
					<<	handle.Name()
					<<	ChatFormat::Pop
					<<	" ";

			if (args.All) {

				send	<<	ChatStyle::Bold
						<<	"all permissions";

				handle.Revoke();

			} else {

				send	<<	"permissions: "
						<<	ChatStyle::Bold;

				bool first=true;
				for (auto & s : args.Args) {

					if (first) first=false;
					else send << ", ";

					send << s;

					if (grant) handle.Grant(std::move(s));
					else handle.Revoke(std::move(s));

				}

			}

			if (args.Quiet) retr=std::move(send);
			else Chat::Get().Send(send);

			return retr;

		}

		static ChatMessage grant (PermissionsHandle handle, Arguments args) {

			return grant_revoke(
				std::move(handle),
				std::move(args),
				true
			);

		}

		static ChatMessage revoke (PermissionsHandle handle, Arguments args) {

			return grant_revoke(
				std::move(handle),
				std::move(args),
				false
			);

		}

	public:

		virtual Word Priority () const noexcept override {

			return priority;

		}

		virtual const String & Name () const noexcept override {

			return name;

		}

		virtual void Install () override {

			auto & commands=Commands::Get();

			for (auto & i : identifiers) commands.Add(i,this);

		}

		virtual void Summary (const String & identifier, ChatMessage & message) override {

			switch (get_type(identifier)) {

				case Type::Add:
					message << "Adds groups to users and groups.";
					break;
				case Type::Remove:
					message << "Removes groups from users and groups.";
					break;
				case Type::Grant:
					message << "Grants permissions.";
					break;
				case Type::Revoke:
				default:
					message << "Revokes permissions.";
					break;

			}

		}

		virtual void Help (const String & identifier, ChatMessage & message) override {

			message	<<	"Syntax: "
					<<	ChatStyle::Bold
					<<	"/"
					<<	identifier
					<<	" [-g] ";

			auto type=get_type(identifier);
			switch (type) {

				case Type::Add:
				case Type::Remove:
					message	<<	"<user/group name> <group name>"
							<<	ChatFormat::Pop
							<<	Newline
							<<	((type==Type::Add) ? "Adds" : "Removes")
							<<	" the requested group "
							<<	((type==Type::Add) ? "to" : "from")
							<<	" the given user or group.  The resulting permissions of the user- or group-in-question "
								"will be "
							<<	(
									(type==Type::Add)
										?	"a union of the user or group's previous permissions, and the permissions "
											"associated with the group being added."
										:	"the permissions that user or group has as a result of permissions specifically "
											"granted them, or granted to a group which is still associated with them."
								);

					break;
				case Type::Grant:
				case Type::Revoke:
				default:
					message	<<	"[-a] <user/group name> <permissions>"
							<<	ChatFormat::Pop
							<<	Newline
							<<	((type==Type::Grant) ? "Grants" : "Revokes")
							<<	" requested permissions.  "
								"If permissions are added to a group which does not exist, it will be created.  "
								"The -a flag specifies that all permissions should be "
							<<	((type==Type::Grant) ? "granted" : "revoked")
							<<	" and must not be specified alongside a list of permissions.";
					break;

			}

			message	<<	"  The -g flag specifies that a group is being named, rather than a user.";

		}

		virtual bool Check (const CommandEvent & event) override {

			//	Console is always permitted
			if (event.Issuer.IsNull()) return true;

			auto handle=Permissions::Get().GetUser(event.Issuer);

			return (
				handle.Check(event.Identifier) ||
				handle.Check(event.Identifier+all_suffix)
			);

		}

		virtual CommandResult Execute (CommandEvent event) override {

			CommandResult retr;

			auto args=parse(std::move(event.Arguments));

			//	Make sure the arguments are valid
			if (args.IsNull() || !check_syntax(event.Identifier,*args)) {

				retr.Status=CommandStatus::SyntaxError;

				return retr;

			}

			//	Get the permissions handle for this
			//	user or group
			auto & permissions=Permissions::Get();
			auto handle=args->Group ? permissions.GetGroup(std::move(args->Name)) : permissions.GetUser(std::move(args->Name));

			//	Check permissions
			if (!(event.Issuer.IsNull() || check_permissions(
				event.Identifier,
				*args,
				permissions.GetUser(event.Issuer)
			))) {

				retr.Status=CommandStatus::Forbidden;

				return retr;

			}

			retr.Status=CommandStatus::Success;

			//	Invoke
			switch (get_type(event.Identifier)) {

				case Type::Add:
					retr.Message=add(std::move(handle),std::move(*args));
					break;
				case Type::Remove:
					retr.Message=remove(std::move(handle),std::move(*args));
					break;
				case Type::Grant:
					retr.Message=grant(std::move(handle),std::move(*args));
					break;
				case Type::Revoke:
				default:
					retr.Message=revoke(std::move(handle),std::move(*args));
					break;

			}

			return retr;

		}

};

INSTALL_MODULE(PermissionsCommand)
<commit_msg>Permissions Command Fix<commit_after>#include <rleahylib/rleahylib.hpp>
#include <chat/chat.hpp>
#include <command/command.hpp>
#include <permissions/permissions.hpp>
#include <mod.hpp>
#include <algorithm>

using namespace MCPP;

static const Word priority=1;
static const String name("Permissions Commands");
static const String add_identifier("addgroup");
static const String remove_identifier("removegroup");
static const String grant_identifier("grant");
static const String revoke_identifier("revoke");
static const String all_suffix("_all");
static const String identifiers []={
	grant_identifier,
	revoke_identifier,
	add_identifier,
	remove_identifier
};
static const String group_arg("-g");
static const String all_arg("-a");
static const String quiet_arg("-q");

class PermissionsCommand : public Module, public Command {

	private:

		class Arguments {

			public:

				bool All;
				bool Group;
				bool Quiet;
				String Name;
				Vector<String> Args;

		};

		static Nullable<Arguments> parse (Vector<String> args) {

			Nullable<Arguments> retr;

			if (args.Count()==0) return retr;

			retr.Construct();
			retr->All=false;
			retr->Group=false;
			retr->Quiet=false;
			bool first=true;
			bool complete=false;
			for (auto & s : args) {

				if (first) {

					if (s==group_arg) {

						if (retr->Group) break;

						retr->Group=true;

					} else if (s==all_arg) {

						if (retr->All) break;

						retr->All=true;

					} else if (s==quiet_arg) {

						if (retr->Quiet) break;

						retr->Quiet=true;

					} else {

						first=false;

						retr->Name=std::move(s);

						if (retr->All) complete=true;

					}

				} else if (retr->All) {

					break;

				} else {

					retr->Args.Add(std::move(s));

					complete=true;

				}

			}

			if (!complete) retr.Destroy();

			return retr;

		}

		enum class Type {

			Add,
			Remove,
			Grant,
			Revoke

		};

		static Type get_type (const String & str) noexcept {

			if (str==add_identifier) return Type::Add;
			if (str==remove_identifier) return Type::Remove;
			if (str==grant_identifier) return Type::Grant;
			return Type::Revoke;

		}

		static bool check_syntax (const String & identifier, const Arguments & args) {

			switch (get_type(identifier)) {

				case Type::Add:
				case Type::Remove:
					if (
						args.All ||
						(args.Args.Count()!=1)
					) return false;
					break;

				default:break;

			}

			return true;

		}

		static bool check_permissions (const String & identifier, const Arguments & args, const PermissionsHandle & handle) {

			//	If a user is granted the _all permission,
			//	they can always proceed
			if (handle.Check(identifier+all_suffix)) return true;

			//	If the user isn't granted the particular
			//	permission, they can never proceed
			if (!handle.Check(identifier)) return false;

			//	Otherwise check particular conditions
			switch (get_type(identifier)) {

				case Type::Add:
				case Type::Remove:

					//	User must be a member of the
					//	target group
					if (!handle.IsMember(args.Args[0])) return false;

					break;

				default:

					//	If we're granting/revoking all
					//	permissions, user must themselves
					//	have all permissions
					//
					//	Since we short-circuit out above
					//	if the user has a certain permission,
					//	getting here means the user does NOT
					//	have all permissions
					if (args.All) return false;

					//	Check each permission -- user
					//	must have them all
					for (auto & perm : args.Args) if (!handle.Check(perm)) return false;

					break;

			}

			return true;

		}

		static ChatMessage add_remove (PermissionsHandle handle, Arguments args, bool add) {

			ChatMessage retr;
			ChatMessage send;

			if (add) send << ChatStyle::BrightGreen << "Adding to ";
			else send << ChatStyle::Red << "Removing from ";

			send	<<	(handle.IsGroup() ? "group" : "user")
					<<	" "
					<<	ChatStyle::Bold
					<<	handle.Name()
					<<	ChatFormat::Pop
					<<	" group "
					<<	ChatStyle::Bold
					<<	args.Args[0];

			if (add) handle.Add(std::move(args.Args[0]));
			else handle.Remove(std::move(args.Args[0]));

			if (args.Quiet) retr=std::move(send);
			else Chat::Get().Send(send);

			return retr;

		}

		static ChatMessage add (PermissionsHandle handle, Arguments args) {

			return add_remove(
				std::move(handle),
				std::move(args),
				true
			);

		}

		static ChatMessage remove (PermissionsHandle handle, Arguments args) {

			return add_remove(
				std::move(handle),
				std::move(args),
				false
			);

		}

		static ChatMessage grant_revoke (PermissionsHandle handle, Arguments args, bool grant) {

			ChatMessage retr;
			ChatMessage send;

			std::sort(args.Args.begin(),args.Args.end());

			if (grant) send << ChatStyle::BrightGreen << "Granting";
			else send << ChatStyle::Red << "Revoking from";

			send	<<	" "
					<<	(handle.IsGroup() ? "group" : "user")
					<<	" "
					<<	ChatStyle::Bold
					<<	handle.Name()
					<<	ChatFormat::Pop
					<<	" ";

			if (args.All) {

				send	<<	ChatStyle::Bold
						<<	"all permissions";

				if (grant) handle.Grant();
				else handle.Revoke();

			} else {

				send	<<	"permissions: "
						<<	ChatStyle::Bold;

				bool first=true;
				for (auto & s : args.Args) {

					if (first) first=false;
					else send << ", ";

					send << s;

					if (grant) handle.Grant(std::move(s));
					else handle.Revoke(std::move(s));

				}

			}

			if (args.Quiet) retr=std::move(send);
			else Chat::Get().Send(send);

			return retr;

		}

		static ChatMessage grant (PermissionsHandle handle, Arguments args) {

			return grant_revoke(
				std::move(handle),
				std::move(args),
				true
			);

		}

		static ChatMessage revoke (PermissionsHandle handle, Arguments args) {

			return grant_revoke(
				std::move(handle),
				std::move(args),
				false
			);

		}

	public:

		virtual Word Priority () const noexcept override {

			return priority;

		}

		virtual const String & Name () const noexcept override {

			return name;

		}

		virtual void Install () override {

			auto & commands=Commands::Get();

			for (auto & i : identifiers) commands.Add(i,this);

		}

		virtual void Summary (const String & identifier, ChatMessage & message) override {

			switch (get_type(identifier)) {

				case Type::Add:
					message << "Adds groups to users and groups.";
					break;
				case Type::Remove:
					message << "Removes groups from users and groups.";
					break;
				case Type::Grant:
					message << "Grants permissions.";
					break;
				case Type::Revoke:
				default:
					message << "Revokes permissions.";
					break;

			}

		}

		virtual void Help (const String & identifier, ChatMessage & message) override {

			message	<<	"Syntax: "
					<<	ChatStyle::Bold
					<<	"/"
					<<	identifier
					<<	" [-g] ";

			auto type=get_type(identifier);
			switch (type) {

				case Type::Add:
				case Type::Remove:
					message	<<	"<user/group name> <group name>"
							<<	ChatFormat::Pop
							<<	Newline
							<<	((type==Type::Add) ? "Adds" : "Removes")
							<<	" the requested group "
							<<	((type==Type::Add) ? "to" : "from")
							<<	" the given user or group.  The resulting permissions of the user- or group-in-question "
								"will be "
							<<	(
									(type==Type::Add)
										?	"a union of the user or group's previous permissions, and the permissions "
											"associated with the group being added."
										:	"the permissions that user or group has as a result of permissions specifically "
											"granted them, or granted to a group which is still associated with them."
								);

					break;
				case Type::Grant:
				case Type::Revoke:
				default:
					message	<<	"[-a] <user/group name> <permissions>"
							<<	ChatFormat::Pop
							<<	Newline
							<<	((type==Type::Grant) ? "Grants" : "Revokes")
							<<	" requested permissions.  "
								"If permissions are added to a group which does not exist, it will be created.  "
								"The -a flag specifies that all permissions should be "
							<<	((type==Type::Grant) ? "granted" : "revoked")
							<<	" and must not be specified alongside a list of permissions.";
					break;

			}

			message	<<	"  The -g flag specifies that a group is being named, rather than a user.";

		}

		virtual bool Check (const CommandEvent & event) override {

			//	Console is always permitted
			if (event.Issuer.IsNull()) return true;

			auto handle=Permissions::Get().GetUser(event.Issuer);

			return (
				handle.Check(event.Identifier) ||
				handle.Check(event.Identifier+all_suffix)
			);

		}

		virtual CommandResult Execute (CommandEvent event) override {

			CommandResult retr;

			auto args=parse(std::move(event.Arguments));

			//	Make sure the arguments are valid
			if (args.IsNull() || !check_syntax(event.Identifier,*args)) {

				retr.Status=CommandStatus::SyntaxError;

				return retr;

			}

			//	Get the permissions handle for this
			//	user or group
			auto & permissions=Permissions::Get();
			auto handle=args->Group ? permissions.GetGroup(std::move(args->Name)) : permissions.GetUser(std::move(args->Name));

			//	Check permissions
			if (!(event.Issuer.IsNull() || check_permissions(
				event.Identifier,
				*args,
				permissions.GetUser(event.Issuer)
			))) {

				retr.Status=CommandStatus::Forbidden;

				return retr;

			}

			retr.Status=CommandStatus::Success;

			//	Invoke
			switch (get_type(event.Identifier)) {

				case Type::Add:
					retr.Message=add(std::move(handle),std::move(*args));
					break;
				case Type::Remove:
					retr.Message=remove(std::move(handle),std::move(*args));
					break;
				case Type::Grant:
					retr.Message=grant(std::move(handle),std::move(*args));
					break;
				case Type::Revoke:
				default:
					retr.Message=revoke(std::move(handle),std::move(*args));
					break;

			}

			return retr;

		}

};

INSTALL_MODULE(PermissionsCommand)
<|endoftext|>


<commit_before>#include "Transform.h"
#include <math.h>

Matrix4 Transform::GetTranslationMatrix(const Vector3& _position)
{
	return Matrix4 (1.0f, 0.0f, 0.0f, _position.x,
					0.0f, 1.0f, 0.0f, _position.y,
					0.0f, 0.0f, 1.0f, _position.z,
					0.0f, 0.0f, 0.0f, 1.0f
					);
}

Matrix4 Transform::GetScaleMatrix(const Vector3& _scale)
{
	return Matrix4(	_scale.x,	0.0f,		0.0f,		0.0f,
					0.0f,		_scale.y,	0.0f,		0.0f,
					0.0f,		0.0f,		_scale.z,	0.0f,
					0.0f,		0.0f,		0.0f,		1.0f
					);
}

// Right-hand
Matrix4 Transform::GetRotationMatrix(const Vector3& _rotation)
{
	// X-axis
	Matrix4 roll(	1.0f, 0.0f,					0.0f,				0.0f,
					0.0f, cosf(_rotation.x),	-sinf(_rotation.x), 0.0f,
					0.0f, sinf(_rotation.x),	cosf(_rotation.x),	0.0f,
					0.0f, 0.0f,					0.0f,				1.0f
	);

	 // Y-axis
	 Matrix4 yaw(	cosf(_rotation.y),	0.0f, sinf(_rotation.y),	0.0f,
					0.0f,				1.0f, 0.0f,					0.0f,
					-sinf(_rotation.y),	0.0f, cosf(_rotation.y),	0.0f,
					0.0f,				0.0f, 0.0f,					1.0f
	 );

	 // Z-axis
	 Matrix4 pitch(	cosf(_rotation.z),	-sinf(_rotation.z),	0.0f, 0.0f,
					sinf(_rotation.z),	cosf(_rotation.z),	0.0f, 0.0f,
					0.0f,				0.0f,				1.0f, 0.0f,
					0.0f,				0.0f,				0.0f, 1.0f
	 );

	 return yaw * pitch * roll;
}

Transform::Transform(const Vector3 & pos, const Vector3 & scl, const Vector3 & rot, Transform * _parent, SceneObject * obj)
{
	position = pos;
	scale = scl;
	rotation = rot;
	parent = _parent;
	object = obj;

	UpdateTransform();
}

Transform & Transform::operator=(const Transform & t)
{
	parent = t.parent;
	m = t.m;
	position = t.position;
	scale = t.scale;
	rotation = t.rotation;
	object = t.object;
	return *this;
}

Transform & Transform::operator=(Transform && t)
{
	parent = t.parent;
	m = t.m;
	position = t.position;
	scale = t.scale;
	rotation = t.rotation;
	object = t.object;
	return *this;
}

void Transform::SetPosition(const Vector3& position)
{
	this->position = position;
	UpdateTransform();
}

void Transform::SetScale(const Vector3& scale)
{
	this->scale = scale;
	UpdateTransform();
}

void Transform::SetRotation(const Vector3& rotation)
{
	this->rotation = rotation;
	UpdateTransform();
}

void Transform::SetPosition(float x, float y, float z)
{
	SetPosition(Vector3(x, y, z));
}

void Transform::SetScale(float x, float y, float z)
{
	SetScale(Vector3(x, y, z));
}

void Transform::SetRotation(float roll, float yaw, float pitch)
{
	SetRotation(Vector3(roll, yaw, pitch));
}

void Transform::Translate(const Vector3& position_)
{
	position = position + position_;
	UpdateTransform();
}

void Transform::Translate(float x, float y, float z)
{
	Translate(Vector3(x, y, z));
}

void Transform::Scale(const Vector3& scale_)
{
	scale = scale + scale_;
	UpdateTransform();
}

void Transform::Scale(float x, float y, float z)
{
	Scale(Vector3(x, y, z));
}

void Transform::Rotate(const Vector3& rotation_)
{
	rotation = rotation + rotation_;
	UpdateTransform();
}

void Transform::Rotate(float roll, float yaw, float pitch)
{
	Rotate(Vector3(roll, yaw, pitch));
}

void Transform::SetParent(Transform * par)
{
	parent = par;
	dirty = true;
}

Transform Transform::Combine(const Transform & other) const
{
	return Transform(position + other.position, rotation + other.rotation, scale + other.scale, other.parent, other.object);
}

<commit_msg>Update Transform.cpp<commit_after>#include "Transform.h"
#include <math.h>

Matrix4 Transform::GetTranslationMatrix(const Vector3& _position)
{
	return Matrix4 (1.0f, 0.0f, 0.0f, _position.x,
					0.0f, 1.0f, 0.0f, _position.y,
					0.0f, 0.0f, 1.0f, _position.z,
					0.0f, 0.0f, 0.0f, 1.0f
					);
}

Matrix4 Transform::GetScaleMatrix(const Vector3& _scale)
{
	return Matrix4(	_scale.x,	0.0f,		0.0f,		0.0f,
					0.0f,		_scale.y,	0.0f,		0.0f,
					0.0f,		0.0f,		_scale.z,	0.0f,
					0.0f,		0.0f,		0.0f,		1.0f
					);
}

// Right-hand
Matrix4 Transform::GetRotationMatrix(const Vector3& _rotation)
{
	// X-axis
	Matrix4 roll(	1.0f, 0.0f,					0.0f,				0.0f,
					0.0f, cosf(_rotation.x),	-sinf(_rotation.x), 0.0f,
					0.0f, sinf(_rotation.x),	cosf(_rotation.x),	0.0f,
					0.0f, 0.0f,					0.0f,				1.0f
	);

	 // Y-axis
	 Matrix4 yaw(	cosf(_rotation.y),	0.0f, sinf(_rotation.y),	0.0f,
					0.0f,				1.0f, 0.0f,					0.0f,
					-sinf(_rotation.y),	0.0f, cosf(_rotation.y),	0.0f,
					0.0f,				0.0f, 0.0f,					1.0f
	 );

	 // Z-axis
	 Matrix4 pitch(	cosf(_rotation.z),	-sinf(_rotation.z),	0.0f, 0.0f,
					sinf(_rotation.z),	cosf(_rotation.z),	0.0f, 0.0f,
					0.0f,				0.0f,				1.0f, 0.0f,
					0.0f,				0.0f,				0.0f, 1.0f
	 );

	 return yaw * pitch * roll;
}

Transform::Transform(const Vector3 & pos, const Vector3 & scl, const Vector3 & rot, Transform * _parent, SceneObject * obj)
{
	position = pos;
	scale = scl;
	rotation = rot;
	parent = _parent;
	object = obj;

	UpdateTransform();
}

Transform & Transform::operator=(const Transform & t)
{
	parent = t.parent;
	m = t.m;
	position = t.position;
	scale = t.scale;
	rotation = t.rotation;
	object = t.object;
	return *this;
}

Transform & Transform::operator=(Transform && t)
{
	parent = t.parent;
	m = t.m;
	position = t.position;
	scale = t.scale;
	rotation = t.rotation;
	object = t.object;
	return *this;
}

void Transform::SetPosition(const Vector3& position)
{
	this->position = position;
	UpdateTransform();
}

void Transform::SetScale(const Vector3& scale)
{
	this->scale = scale;
	UpdateTransform();
}

void Transform::SetRotation(const Vector3& rotation)
{
	this->rotation = rotation;
	UpdateTransform();
}

void Transform::SetPosition(float x, float y, float z)
{
	SetPosition(Vector3(x, y, z));
}

void Transform::SetScale(float x, float y, float z)
{
	SetScale(Vector3(x, y, z));
}

void Transform::SetRotation(float roll, float yaw, float pitch)
{
	SetRotation(Vector3(roll, yaw, pitch));
}

void Transform::Translate(const Vector3& position_)
{
	position = position + position_;
	UpdateTransform();
}

void Transform::Translate(float x, float y, float z)
{
	Translate(Vector3(x, y, z));
}

void Transform::Scale(const Vector3& scale_)
{
	scale = scale + scale_;
	UpdateTransform();
}

void Transform::Scale(float x, float y, float z)
{
	Scale(Vector3(x, y, z));
}

void Transform::Rotate(const Vector3& radRotation_)
{
	rotation = rotation + radRotation_;
	UpdateTransform();
}

void Transform::RotateDeg(const Vector3 & rotation_)
{
	Rotate(rotation_ * TO_RADIANS);
}

void Transform::Rotate(float radRoll, float radYaw, float radPitch)
{
	Rotate(Vector3(radRoll, radYaw, radPitch));
}

void Transform::RotateDeg(float roll, float yaw, float pitch)
{
	Rotate(Vector3(roll, yaw, pitch)* TO_RADIANS);
}

void Transform::SetParent(Transform * par)
{
	parent = par;
	dirty = true;
}

Transform Transform::Combine(const Transform & other) const
{
	return Transform(position + other.position, rotation + other.rotation, scale + other.scale, other.parent, other.object);
}

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 *             Copyright (c) 2009 Sony Pictures Imageworks, Inc.
 *                            All rights reserved.
 *
 *  This material contains the confidential and proprietary information
 *  of Sony Pictures Imageworks, Inc. and may not be disclosed, copied or
 *  duplicated in any form, electronic or hardcopy, in whole or in part,
 *  without the express prior written consent of Sony Pictures Imageworks,
 *  Inc. This copyright notice does not imply publication.
 *
 *****************************************************************************/

#include <iostream>

#include "oslexec_pvt.h"
#include "oslops.h"

#include "OpenImageIO/varyingref.h"

namespace OSL {
namespace pvt {

// Heavy lifting of 'assign', this is a specialized version that assumes
// the types of
template <class RET, class SRC>
static DECLOP (specialized_assign)
{
    if (exec->debug())
        std::cout << "Executing specialized_assign!\n";
    // Get references to the symbols this op accesses
    Symbol &Result (exec->sym (args[0]));
    Symbol &Src (exec->sym (args[1]));

    // Adjust the result's uniform/varying status
    exec->adjust_varying (Result, Src.is_varying(),
                          Result.data() == Src.data());

    // Loop over points, do the assignment.
    VaryingRef<RET> result ((RET *)Result.data(), Result.step());
    VaryingRef<SRC> src ((SRC *)Src.data(), Src.step());
    if (result.is_uniform()) {
        // Result (and src) are uniform
        *result = RET (*src);
    } else {
        // Potentially varying case
        for (int i = beginpoint;  i < endpoint;  ++i)
            if (runflags[i])
                result[i] = RET (src[i]);
    }
}

// Syntax of matrix assignment of scalar is slightly different because
// Imath::Matrix44 defines operator= as setting all components to the
// scalar, whereas OSL defines the operation as just setting the
// diagonal to the scalar (i.e. m=f is equiv to m = Identity * f)
template <class SRC>
static DECLOP (specialized_assign_matrix_scalar)
{
    if (exec->debug())
        std::cout << "Executing specialized_assign for matrix!\n";
    typedef Imath::M44f RET;
    // Get references to the symbols this op accesses
    Symbol &Result (exec->sym (args[0]));
    Symbol &Src (exec->sym (args[1]));

    // Adjust the result's uniform/varying status
    exec->adjust_varying (Result, Src.is_varying(),
                          Result.data() == Src.data());

    // Loop over points, do the assignment.
    VaryingRef<RET> result ((RET *)Result.data(), Result.step());
    VaryingRef<SRC> src ((SRC *)Src.data(), Src.step());
    if (result.is_uniform()) {
        // Result (and src) are uniform
        *result = 1.0f;
        *result *= *src;
    } else {
        // Potentially varying case
        for (int i = beginpoint;  i < endpoint;  ++i)
            if (runflags[i]) {
                result[i] = 1.0f;
                result[i] *= (src[i]);
            }
    }
}

DECLOP (OP_assign)
{
    if (exec->debug())
        std::cout << "Executing assign!\n";
    ASSERT (nargs == 2);
    Symbol &Result (exec->sym (args[0]));
    Symbol &Src (exec->sym (args[1]));
    if (exec->debug()) {
        std::cout << "  Result is " << Result.typespec().string()
                  << " " << Result.mangled() << " @ " << (void *)Result.data() << "\n";
        std::cout << "  Src is " << Src.typespec().string()
                  << " " << Src.mangled() << " @ " << (void*)Src.data() << "\n";
    }
    ASSERT (! Result.typespec().is_closure() &&
            ! Result.typespec().is_structure() &&
            ! Result.typespec().is_array());   // Not yet
    ASSERT (! Src.typespec().is_closure() &&
            ! Src.typespec().is_structure() &&
            ! Src.typespec().is_array());   // Not yet
    OpImpl impl = NULL;
    if (Result.typespec().is_closure()) {
        // FIXME -- not handled yet
    } else if (Result.typespec().is_structure()) {
        // FIXME -- not handled yet
    } else if (Result.typespec().is_float()) {
        if (Src.typespec().is_float()) {
            impl = specialized_assign<float,float>;
        } if (Src.typespec().is_int()) {
            impl = specialized_assign<float,int>;
        } else {
            // Nothing else can be assigned to a float
        }
    } else if (Result.typespec().is_triple()) {
        if (Src.typespec().is_triple()) {
            impl = specialized_assign<Imath::V3f,Imath::V3f>;
        } else if (Src.typespec().is_float()) {
            impl = specialized_assign<Imath::V3f,float>;
        } if (Src.typespec().is_int()) {
            impl = specialized_assign<Imath::V3f,int>;
        } else {
            // Nothing else can be assigned to a float
        }
    } else if (Result.typespec().is_matrix()) {
        if (Src.typespec().is_matrix()) {
            impl = specialized_assign<Imath::M44f,Imath::M44f>;
        } else if (Src.typespec().is_float()) {
            impl = specialized_assign_matrix_scalar<float>;
        } if (Src.typespec().is_int()) {
            impl = specialized_assign_matrix_scalar<int>;
        } else {
            // Nothing else can be assigned to a float
        }
    }
    if (impl) {
        impl (exec, nargs, args, runflags, beginpoint, endpoint);
        // Use the specialized one for next time!  Never have to check the
        // types or do the other sanity checks again.
        // FIXME -- is this thread-safe?
        exec->op().implementation (impl);
        return;
    }
    ASSERT (0 && "Assignment types can't be handled");
}

}; // namespace pvt
}; // namespace OSL
<commit_msg>Simplify specialized_assign with a proxy class that defined the missing Matrix operations.<commit_after>/*****************************************************************************
 *
 *             Copyright (c) 2009 Sony Pictures Imageworks, Inc.
 *                            All rights reserved.
 *
 *  This material contains the confidential and proprietary information
 *  of Sony Pictures Imageworks, Inc. and may not be disclosed, copied or
 *  duplicated in any form, electronic or hardcopy, in whole or in part,
 *  without the express prior written consent of Sony Pictures Imageworks,
 *  Inc. This copyright notice does not imply publication.
 *
 *****************************************************************************/

#include <iostream>

#include "oslexec_pvt.h"
#include "oslops.h"

#include "OpenImageIO/varyingref.h"

namespace OSL {
namespace pvt {

// Proxy type that derives from Matrix44 but allows assignment of a float
// to mean f*Identity.
class MatrixProxy : public Matrix44 {
public:
    MatrixProxy (float a, float b, float c, float d,
                 float e, float f, float g, float h,
                 float i, float j, float k, float l,
                 float m, float n, float o, float p)
        : Matrix44 (a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p) { }

    MatrixProxy (float f) : Matrix44 (f,0,0,0, 0,f,0,0, 0,0,f,0, 0,0,0,f) { }

    const MatrixProxy& operator= (float f) {
        *this = MatrixProxy (f);
        return *this;
    }
};

// Heavy lifting of 'assign', this is a specialized version that knows
// the types of the arguments.
template <class RET, class SRC>
static DECLOP (specialized_assign)
{
    if (exec->debug())
        std::cout << "Executing specialized_assign!\n";
    // Get references to the symbols this op accesses
    Symbol &Result (exec->sym (args[0]));
    Symbol &Src (exec->sym (args[1]));

    // Adjust the result's uniform/varying status
    exec->adjust_varying (Result, Src.is_varying(),
                          Result.data() == Src.data());

    // Loop over points, do the assignment.
    VaryingRef<RET> result ((RET *)Result.data(), Result.step());
    VaryingRef<SRC> src ((SRC *)Src.data(), Src.step());
    if (result.is_uniform()) {
        // Uniform case
        *result = RET (*src);
    } else {
        // Potentially varying case
        for (int i = beginpoint;  i < endpoint;  ++i)
            if (runflags[i])
                result[i] = RET (src[i]);
    }
}

DECLOP (OP_assign)
{
    if (exec->debug())
        std::cout << "Executing assign!\n";
    ASSERT (nargs == 2);
    Symbol &Result (exec->sym (args[0]));
    Symbol &Src (exec->sym (args[1]));
    if (exec->debug()) {
        std::cout << "  Result is " << Result.typespec().string()
                  << " " << Result.mangled() << " @ " << (void *)Result.data() << "\n";
        std::cout << "  Src is " << Src.typespec().string()
                  << " " << Src.mangled() << " @ " << (void*)Src.data() << "\n";
    }
    ASSERT (! Result.typespec().is_closure() &&
            ! Result.typespec().is_structure() &&
            ! Result.typespec().is_array());   // Not yet
    ASSERT (! Src.typespec().is_closure() &&
            ! Src.typespec().is_structure() &&
            ! Src.typespec().is_array());   // Not yet
    OpImpl impl = NULL;
    if (Result.typespec().is_closure()) {
        // FIXME -- not handled yet
    } else if (Result.typespec().is_structure()) {
        // FIXME -- not handled yet
    } else if (Result.typespec().is_float()) {
        if (Src.typespec().is_float()) {
            impl = specialized_assign<float,float>;
        } if (Src.typespec().is_int()) {
            impl = specialized_assign<float,int>;
        } else {
            // Nothing else can be assigned to a float
        }
    } else if (Result.typespec().is_triple()) {
        if (Src.typespec().is_triple()) {
            impl = specialized_assign<Vec3,Vec3>;
        } else if (Src.typespec().is_float()) {
            impl = specialized_assign<Vec3,float>;
        } if (Src.typespec().is_int()) {
            impl = specialized_assign<Vec3,int>;
        } else {
            // Nothing else can be assigned to a triple
        }
    } else if (Result.typespec().is_matrix()) {
        if (Src.typespec().is_matrix()) {
            impl = specialized_assign<Matrix44,Matrix44>;
        } else if (Src.typespec().is_float()) {
            impl = specialized_assign<MatrixProxy,float>;
        } if (Src.typespec().is_int()) {
            impl = specialized_assign<MatrixProxy,int>;
        } else {
            // Nothing else can be assigned to a matrix
        }
    } else if (Result.typespec().is_string()) {
        if (Src.typespec().is_string())
            impl = specialized_assign<ustring,ustring>;
    }
    if (impl) {
        impl (exec, nargs, args, runflags, beginpoint, endpoint);
        // Use the specialized one for next time!  Never have to check the
        // types or do the other sanity checks again.
        // FIXME -- is this thread-safe?
        exec->op().implementation (impl);
        return;
    }
    ASSERT (0 && "Assignment types can't be handled");
}

}; // namespace pvt
}; // namespace OSL
<|endoftext|>


<commit_before>// Time:  O(C(n, k))
// Space: O(k)

class Solution {
public:
    vector<vector<int> > combinationSum3(int k, int n) {
        vector<vector<int>> res;
        vector<int> combination;
        combinationSum3(res, combination, 1, k, n);
        return res;
    }
private:
    void combinationSum3(vector<vector<int> > &res, vector<int> &combination, int start, int k, int n) {
        if (!k && !n) {
            res.push_back(combination);
            return;
        } else if (k < 0) {
            return;
        }

        for (int i = start; i < 10 && n >=  k * i + k * (k - 1) / 2; ++i) {
            combination.push_back(i);
            combinationSum3(res, combination, i + 1, k - 1, n - i);
            combination.pop_back();
        }
    }
};
<commit_msg>Update combination-sum-iii.cpp<commit_after>// Time:  O(k * C(n, k))
// Space: O(k)

class Solution {
public:
    vector<vector<int> > combinationSum3(int k, int n) {
        vector<vector<int>> res;
        vector<int> combination;
        combinationSum3(res, combination, 1, k, n);
        return res;
    }
private:
    void combinationSum3(vector<vector<int> > &res, vector<int> &combination, int start, int k, int n) {
        if (!k && !n) {
            res.push_back(combination);
            return;
        } else if (k < 0) {
            return;
        }

        for (int i = start; i < 10 && n >=  k * i + k * (k - 1) / 2; ++i) {
            combination.push_back(i);
            combinationSum3(res, combination, i + 1, k - 1, n - i);
            combination.pop_back();
        }
    }
};
<|endoftext|>


<commit_before>/************************************************************************************
**
* @copyright (c) 2013-2100, ChengDu Duyer Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @file		g_sys.cpp
* @version
* @brief
* @author	duye
* @date		2014-03-04
* @note
*
*  1. 2014-03-04 duye Created this file
*
*/

#include <unistd.h>
#include <stdarg.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <g_sys.h>

namespace gsys {

void System::sleep(const GUint64 time)
{
	::sleep(time);
}

void System::usleep(const GUint64 time)
{
	::usleep(time);
}

GUint64 System::pformat(GInt8* buffer, const GUint64 size, const GInt8* args, ...)
{
	IS_NULL_R(buffer);

	va_list vaList;
	va_start(vaList, args);
	GUint64 strLen = vsnprintf(buffer, size, args, vaList);
	va_end(vaList);
	return strLen;
}

GResult System::shell(const GInt8* cmd)
{
	IS_NULL_R(cmd);

	FILE* retStream = popen(cmd, "r");
	if (retStream == NULL)
	{
		return G_NO;
	}

	pclose(retStream);

	return G_YES;
}

GResult System::shell(const GInt8* cmd, GInt8* buffer, const GUint32 size)
{
	IS_NULL_R(cmd);
	IS_NULL_R(buffer);

	FILE* retStream = popen(cmd, "r");
	if (retStream == NULL)
	{
		return G_NO;
	}

	memset(buffer, 0, size);
	fread(buffer, sizeof(GInt8), size, retStream);

	pclose(retStream);

	return G_YES;
}

GUint64 System::sysTime()
{
	struct timeval now;
	struct timezone tz;
	if (gettimeofday(&now, &tz) < 0)
	{
		return 0;
	}

	return (GUint64)(now.tv_sec) * 1000000 + now.tv_usec;
}

GResult System::sysTime(const GInt8* format, GInt8* buffer, const GUint32 size)
{
	IS_NULL_R(format);
	IS_NULL_R(buffer);

    struct timeval tv;
    struct tm tm;

    gettimeofday(&tv, NULL);
    localtime_r(&tv.tv_sec, &tm);
    //strftime(buffer, size, "%Y-%m-%d %H:%M:%S", &tm);
    GUint32 len = strftime(buffer, size, format, &tm);
    if (len + 7 >= size)
    {
    	return G_NO;
    }

    snprintf(buffer + len, size - len, ".%6d", (GInt32)tv.tv_usec);

    return G_YES;
}

GResult System::optArg(GInt32 argc, GInt8** argv, GInt8* cmd, GInt64& value)
{
	IS_NULL_R(argv);
	IS_NULL_R(cmd);

	if (getopt(argc, argv, cmd) != cmd[0])
	{
		return G_NO;
	}

	const std::string temp_str(optarg);
	value = (GInt64)std::stoi(temp_str);

	return G_YES;
}

GResult System::optArg(GInt32 argc, GInt8** argv, GInt8* cmd, GUint64& value)
{
	IS_NULL_R(argv);
	IS_NULL_R(cmd);

	if (getopt(argc, argv, cmd) != cmd[0])
	{
		return G_NO;
	}

	const std::string temp_str(optarg);
	value = (GUint64)std::stoi(temp_str);

	return G_YES;
}

GResult System::optArg(GInt32 argc, GInt8** argv, GInt8* cmd, std::string& value)
{
	IS_NULL_R(argv);
	IS_NULL_R(cmd);

	if (getopt(argc, argv, cmd) != cmd[0])
	{
		return G_NO;
	}

	value.assign(optarg);

	return G_YES;
}

}
<commit_msg>Update g_sys.cpp<commit_after>/************************************************************************************
**
* @copyright (c) 2013-2100, ChengDu Duyer Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @file	    g_sys.cpp
* @version
* @brief
* @author   duye
* @date	    2014-03-04
* @note
*
*  1. 2014-03-04 duye Created this file
*
*/
#include <unistd.h>
#include <stdarg.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <g_sys.h>

namespace gsys {

void System::sleep(const GUint64 time)
{
    ::sleep(time);
}

void System::usleep(const GUint64 time)
{
    ::usleep(time);
}

GUint64 System::pformat(GInt8* buffer, const GUint64 size, const GInt8* args, ...)
{
    IS_NULL_R(buffer);
    va_list vaList;
    va_start(vaList, args);
    GUint64 strLen = vsnprintf(buffer, size, args, vaList);
    va_end(vaList);
    return strLen;
}

GResult System::shell(const GInt8* cmd)
{
    IS_NULL_R(cmd);

    FILE* retStream = popen(cmd, "r");
    if (retStream == NULL)
    {
    	return G_NO;
    }

    pclose(retStream);
    return G_YES;
}

GResult System::shell(const GInt8* cmd, GInt8* buffer, const GUint32 size)
{
    IS_NULL_R(cmd);
    IS_NULL_R(buffer);

    FILE* retStream = popen(cmd, "r");
    if (retStream == NULL)
    {
    	return G_NO;
    }

    memset(buffer, 0, size);
    fread(buffer, sizeof(GInt8), size, retStream);

    pclose(retStream);
    return G_YES;
}

GUint64 System::sysTime()
{
    struct timeval now;
    struct timezone tz;
    if (gettimeofday(&now, &tz) < 0)
    {
    	return 0;
    }

    return (GUint64)(now.tv_sec) * 1000000 + now.tv_usec;
}

GResult System::sysTime(const GInt8* format, GInt8* buffer, const GUint32 size)
{
    IS_NULL_R(format);
    IS_NULL_R(buffer);

    struct timeval tv;
    struct tm tm;

    gettimeofday(&tv, NULL);
    localtime_r(&tv.tv_sec, &tm);
    //strftime(buffer, size, "%Y-%m-%d %H:%M:%S", &tm);
    GUint32 len = strftime(buffer, size, format, &tm);
    if (len + 7 >= size)
    {
    	return G_NO;
    }

    snprintf(buffer + len, size - len, ".%6d", (GInt32)tv.tv_usec);

    return G_YES;
}

GResult System::optArg(GInt32 argc, GInt8** argv, GInt8* cmd, GInt64& value)
{
    IS_NULL_R(argv);
    IS_NULL_R(cmd);

    if (getopt(argc, argv, cmd) != cmd[0])
    {
    	return G_NO;
    }

    const std::string temp_str(optarg);
    value = (GInt64)std::stoi(temp_str);
    return G_YES;
}

GResult System::optArg(GInt32 argc, GInt8** argv, GInt8* cmd, GUint64& value)
{
    IS_NULL_R(argv);
    IS_NULL_R(cmd);

    if (getopt(argc, argv, cmd) != cmd[0])
    {
    	return G_NO;
    }

    const std::string temp_str(optarg);
    value = (GUint64)std::stoi(temp_str);
    return G_YES;
}

GResult System::optArg(GInt32 argc, GInt8** argv, GInt8* cmd, std::string& value)
{
    IS_NULL_R(argv);
    IS_NULL_R(cmd);

    if (getopt(argc, argv, cmd) != cmd[0])
    {
    	return G_NO;
    }

    value.assign(optarg);
    return G_YES;
}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``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 <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMA
 */

#include <stdlib.h>
#include "CppUTest/TestHarness.h"
#undef malloc
#undef free
#undef calloc
#undef realloc
#undef strdup
#undef strndup

#ifdef CPPUTEST_HAVE_GETTIMEOFDAY
#include <sys/time.h>
#endif
#if defined(CPPUTEST_HAVE_FORK) && defined(CPPUTEST_HAVE_WAITPID)
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#endif

#include <time.h>
#include <stdio.h>
#include <stdarg.h>
#include <setjmp.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <signal.h>

#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
#include <pthread.h>
#endif

#include "CppUTest/PlatformSpecificFunctions.h"

static jmp_buf test_exit_jmp_buf[10];
static int jmp_buf_index = 0;

// There is a possibility that a compiler provides fork but not waitpid.
// TODO consider using spawn() and cwait()?
#if !defined(CPPUTEST_HAVE_FORK) || !defined(CPPUTEST_HAVE_WAITPID)

static void BorlandPlatformSpecificRunTestInASeperateProcess(UtestShell* shell, TestPlugin*, TestResult* result)
{
    result->addFailure(TestFailure(shell, "-p doesn't work on this platform, as it is lacking fork.\b"));
}

static int PlatformSpecificForkImplementation(void)
{
    return 0;
}

static int PlatformSpecificWaitPidImplementation(int, int*, int)
{
    return 0;
}

#else

static void SetTestFailureByStatusCode(UtestShell* shell, TestResult* result, int status)
{
    if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
        result->addFailure(TestFailure(shell, "Failed in separate process"));
    } else if (WIFSIGNALED(status)) {
        SimpleString message("Failed in separate process - killed by signal ");
        message += StringFrom(WTERMSIG(status));
        result->addFailure(TestFailure(shell, message));
    } else if (WIFSTOPPED(status)) {
        result->addFailure(TestFailure(shell, "Stopped in separate process - continuing"));
    }
}

static void BorlandPlatformSpecificRunTestInASeperateProcess(UtestShell* shell, TestPlugin* plugin, TestResult* result)
{
    const pid_t syscallError = -1;
    pid_t cpid;
    pid_t w;
    int status = 0;

    cpid = PlatformSpecificFork();

    if (cpid == syscallError) {
        result->addFailure(TestFailure(shell, "Call to fork() failed"));
        return;
    }

    if (cpid == 0) {            /* Code executed by child */
        const size_t initialFailureCount = result->getFailureCount(); // LCOV_EXCL_LINE
        shell->runOneTestInCurrentProcess(plugin, *result);        // LCOV_EXCL_LINE
        _exit(initialFailureCount < result->getFailureCount());    // LCOV_EXCL_LINE
    } else {                    /* Code executed by parent */
        size_t amountOfRetries = 0;
        do {
            w = PlatformSpecificWaitPid(cpid, &status, WUNTRACED);
            if (w == syscallError) {
                // OS X debugger causes EINTR
                if (EINTR == errno) {
                  if (amountOfRetries > 30) {
                    result->addFailure(TestFailure(shell, "Call to waitpid() failed with EINTR. Tried 30 times and giving up! Sometimes happens in debugger"));
                    return;
                  }
                  amountOfRetries++;
                }
                else {
                    result->addFailure(TestFailure(shell, "Call to waitpid() failed"));
                    return;
                }
            } else {
                SetTestFailureByStatusCode(shell, result, status);
                if (WIFSTOPPED(status)) kill(w, SIGCONT);
            }
        } while ((w == syscallError) || (!WIFEXITED(status) && !WIFSIGNALED(status)));
    }
}

static pid_t PlatformSpecificForkImplementation(void)
{
    return fork();
}

static pid_t PlatformSpecificWaitPidImplementation(int pid, int* status, int options)
{
    return waitpid(pid, status, options);
}

#endif

TestOutput::WorkingEnvironment PlatformSpecificGetWorkingEnvironment()
{
    return TestOutput::eclipse;
}

void (*PlatformSpecificRunTestInASeperateProcess)(UtestShell* shell, TestPlugin* plugin, TestResult* result) =
        BorlandPlatformSpecificRunTestInASeperateProcess;
int (*PlatformSpecificFork)(void) = PlatformSpecificForkImplementation;
int (*PlatformSpecificWaitPid)(int, int*, int) = PlatformSpecificWaitPidImplementation;

extern "C" {

static int PlatformSpecificSetJmpImplementation(void (*function) (void* data), void* data)
{
    if (0 == setjmp(test_exit_jmp_buf[jmp_buf_index])) {
        jmp_buf_index++;
        function(data);
        jmp_buf_index--;
        return 1;
    }
    return 0;
}

static void PlatformSpecificLongJmpImplementation()
{
    jmp_buf_index--;
    longjmp(test_exit_jmp_buf[jmp_buf_index], 1);
}

static void PlatformSpecificRestoreJumpBufferImplementation()
{
    jmp_buf_index--;
}

void (*PlatformSpecificLongJmp)() = PlatformSpecificLongJmpImplementation;
int (*PlatformSpecificSetJmp)(void (*)(void*), void*) = PlatformSpecificSetJmpImplementation;
void (*PlatformSpecificRestoreJumpBuffer)() = PlatformSpecificRestoreJumpBufferImplementation;

///////////// Time in millis

static long TimeInMillisImplementation()
{
#ifdef CPPUTEST_HAVE_GETTIMEOFDAY
    struct timeval tv;
    struct timezone tz;
    gettimeofday(&tv, &tz);
    return (tv.tv_sec * 1000) + (long)((double)tv.tv_usec * 0.001);
#else
    return 0;
#endif
}

static const char* TimeStringImplementation()
{
    time_t theTime = time(NULLPTR);
    static char dateTime[80];
    struct tm *tmp = localtime(&theTime);
    strftime(dateTime, 80, "%Y-%m-%dT%H:%M:%S", tmp);
    return dateTime;
}

long (*GetPlatformSpecificTimeInMillis)() = TimeInMillisImplementation;
const char* (*GetPlatformSpecificTimeString)() = TimeStringImplementation;

int (*PlatformSpecificVSNprintf)(char *str, size_t size, const char* format, va_list va_args_list) = vsnprintf;

static PlatformSpecificFile PlatformSpecificFOpenImplementation(const char* filename, const char* flag)
{
   return fopen(filename, flag);
}

static void PlatformSpecificFPutsImplementation(const char* str, PlatformSpecificFile file)
{
   fputs(str, (FILE*)file);
}

static void PlatformSpecificFCloseImplementation(PlatformSpecificFile file)
{
   fclose((FILE*)file);
}

static void PlatformSpecificFlushImplementation()
{
  fflush(stdout);
}

PlatformSpecificFile (*PlatformSpecificFOpen)(const char*, const char*) = PlatformSpecificFOpenImplementation;
void (*PlatformSpecificFPuts)(const char*, PlatformSpecificFile) = PlatformSpecificFPutsImplementation;
void (*PlatformSpecificFClose)(PlatformSpecificFile) = PlatformSpecificFCloseImplementation;

int (*PlatformSpecificPutchar)(int) = putchar;
void (*PlatformSpecificFlush)() = PlatformSpecificFlushImplementation;

void* (*PlatformSpecificMalloc)(size_t size) = malloc;
void* (*PlatformSpecificRealloc)(void*, size_t) = realloc;
void (*PlatformSpecificFree)(void* memory) = free;
void* (*PlatformSpecificMemCpy)(void*, const void*, size_t) = memcpy;
void* (*PlatformSpecificMemset)(void*, int, size_t) = memset;

static int IsNanImplementation(double d)
{
    return isnan(d);
}

static int IsInfImplementation(double d)
{
    return isinf(d);
}

double (*PlatformSpecificFabs)(double) = fabs;
void (*PlatformSpecificSrand)(unsigned int) = srand;
int (*PlatformSpecificRand)(void) = rand;
int (*PlatformSpecificIsNan)(double) = IsNanImplementation;
int (*PlatformSpecificIsInf)(double) = IsInfImplementation;
int (*PlatformSpecificAtExit)(void(*func)(void)) = atexit;  /// this was undefined before

static PlatformSpecificMutex PThreadMutexCreate(void)
{
#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
    pthread_mutex_t *mutex = new pthread_mutex_t;

    pthread_mutex_init(mutex, NULLPTR);
    return (PlatformSpecificMutex)mutex;
#else
    return NULLPTR;
#endif

}

#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
static void PThreadMutexLock(PlatformSpecificMutex mtx)
{
    pthread_mutex_lock((pthread_mutex_t *)mtx);
}
#else
static void PThreadMutexLock(PlatformSpecificMutex)
{
}
#endif

#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
static void PThreadMutexUnlock(PlatformSpecificMutex mtx)
{
    pthread_mutex_unlock((pthread_mutex_t *)mtx);
}
#else
static void PThreadMutexUnlock(PlatformSpecificMutex)
{
}
#endif

#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
static void PThreadMutexDestroy(PlatformSpecificMutex mtx)
{
    pthread_mutex_t *mutex = (pthread_mutex_t *)mtx;
    pthread_mutex_destroy(mutex);
    delete mutex;
}
#else
static void PThreadMutexDestroy(PlatformSpecificMutex)
{
}
#endif

PlatformSpecificMutex (*PlatformSpecificMutexCreate)(void) = PThreadMutexCreate;
void (*PlatformSpecificMutexLock)(PlatformSpecificMutex) = PThreadMutexLock;
void (*PlatformSpecificMutexUnlock)(PlatformSpecificMutex) = PThreadMutexUnlock;
void (*PlatformSpecificMutexDestroy)(PlatformSpecificMutex) = PThreadMutexDestroy;

}
<commit_msg>Update UtestPlatform.cpp<commit_after>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``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 <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdlib.h>
#include "CppUTest/TestHarness.h"
#undef malloc
#undef free
#undef calloc
#undef realloc
#undef strdup
#undef strndup

#ifdef CPPUTEST_HAVE_GETTIMEOFDAY
#include <sys/time.h>
#endif
#if defined(CPPUTEST_HAVE_FORK) && defined(CPPUTEST_HAVE_WAITPID)
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#endif

#include <time.h>
#include <stdio.h>
#include <stdarg.h>
#include <setjmp.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include <ctype.h>
#include <signal.h>

#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
#include <pthread.h>
#endif

#include "CppUTest/PlatformSpecificFunctions.h"

static jmp_buf test_exit_jmp_buf[10];
static int jmp_buf_index = 0;

// There is a possibility that a compiler provides fork but not waitpid.
// TODO consider using spawn() and cwait()?
#if !defined(CPPUTEST_HAVE_FORK) || !defined(CPPUTEST_HAVE_WAITPID)

static void BorlandPlatformSpecificRunTestInASeperateProcess(UtestShell* shell, TestPlugin*, TestResult* result)
{
    result->addFailure(TestFailure(shell, "-p doesn't work on this platform, as it is lacking fork.\b"));
}

static int PlatformSpecificForkImplementation(void)
{
    return 0;
}

static int PlatformSpecificWaitPidImplementation(int, int*, int)
{
    return 0;
}

#else

static void SetTestFailureByStatusCode(UtestShell* shell, TestResult* result, int status)
{
    if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
        result->addFailure(TestFailure(shell, "Failed in separate process"));
    } else if (WIFSIGNALED(status)) {
        SimpleString message("Failed in separate process - killed by signal ");
        message += StringFrom(WTERMSIG(status));
        result->addFailure(TestFailure(shell, message));
    } else if (WIFSTOPPED(status)) {
        result->addFailure(TestFailure(shell, "Stopped in separate process - continuing"));
    }
}

static void BorlandPlatformSpecificRunTestInASeperateProcess(UtestShell* shell, TestPlugin* plugin, TestResult* result)
{
    const pid_t syscallError = -1;
    pid_t cpid;
    pid_t w;
    int status = 0;

    cpid = PlatformSpecificFork();

    if (cpid == syscallError) {
        result->addFailure(TestFailure(shell, "Call to fork() failed"));
        return;
    }

    if (cpid == 0) {            /* Code executed by child */
        const size_t initialFailureCount = result->getFailureCount(); // LCOV_EXCL_LINE
        shell->runOneTestInCurrentProcess(plugin, *result);        // LCOV_EXCL_LINE
        _exit(initialFailureCount < result->getFailureCount());    // LCOV_EXCL_LINE
    } else {                    /* Code executed by parent */
        size_t amountOfRetries = 0;
        do {
            w = PlatformSpecificWaitPid(cpid, &status, WUNTRACED);
            if (w == syscallError) {
                // OS X debugger causes EINTR
                if (EINTR == errno) {
                  if (amountOfRetries > 30) {
                    result->addFailure(TestFailure(shell, "Call to waitpid() failed with EINTR. Tried 30 times and giving up! Sometimes happens in debugger"));
                    return;
                  }
                  amountOfRetries++;
                }
                else {
                    result->addFailure(TestFailure(shell, "Call to waitpid() failed"));
                    return;
                }
            } else {
                SetTestFailureByStatusCode(shell, result, status);
                if (WIFSTOPPED(status)) kill(w, SIGCONT);
            }
        } while ((w == syscallError) || (!WIFEXITED(status) && !WIFSIGNALED(status)));
    }
}

static pid_t PlatformSpecificForkImplementation(void)
{
    return fork();
}

static pid_t PlatformSpecificWaitPidImplementation(int pid, int* status, int options)
{
    return waitpid(pid, status, options);
}

#endif

TestOutput::WorkingEnvironment PlatformSpecificGetWorkingEnvironment()
{
    return TestOutput::eclipse;
}

void (*PlatformSpecificRunTestInASeperateProcess)(UtestShell* shell, TestPlugin* plugin, TestResult* result) =
        BorlandPlatformSpecificRunTestInASeperateProcess;
int (*PlatformSpecificFork)(void) = PlatformSpecificForkImplementation;
int (*PlatformSpecificWaitPid)(int, int*, int) = PlatformSpecificWaitPidImplementation;

extern "C" {

static int PlatformSpecificSetJmpImplementation(void (*function) (void* data), void* data)
{
    if (0 == setjmp(test_exit_jmp_buf[jmp_buf_index])) {
        jmp_buf_index++;
        function(data);
        jmp_buf_index--;
        return 1;
    }
    return 0;
}

static void PlatformSpecificLongJmpImplementation()
{
    jmp_buf_index--;
    longjmp(test_exit_jmp_buf[jmp_buf_index], 1);
}

static void PlatformSpecificRestoreJumpBufferImplementation()
{
    jmp_buf_index--;
}

void (*PlatformSpecificLongJmp)() = PlatformSpecificLongJmpImplementation;
int (*PlatformSpecificSetJmp)(void (*)(void*), void*) = PlatformSpecificSetJmpImplementation;
void (*PlatformSpecificRestoreJumpBuffer)() = PlatformSpecificRestoreJumpBufferImplementation;

///////////// Time in millis

static long TimeInMillisImplementation()
{
#ifdef CPPUTEST_HAVE_GETTIMEOFDAY
    struct timeval tv;
    struct timezone tz;
    gettimeofday(&tv, &tz);
    return (tv.tv_sec * 1000) + (long)((double)tv.tv_usec * 0.001);
#else
    return 0;
#endif
}

static const char* TimeStringImplementation()
{
    time_t theTime = time(NULLPTR);
    static char dateTime[80];
    struct tm *tmp = localtime(&theTime);
    strftime(dateTime, 80, "%Y-%m-%dT%H:%M:%S", tmp);
    return dateTime;
}

long (*GetPlatformSpecificTimeInMillis)() = TimeInMillisImplementation;
const char* (*GetPlatformSpecificTimeString)() = TimeStringImplementation;

int (*PlatformSpecificVSNprintf)(char *str, size_t size, const char* format, va_list va_args_list) = vsnprintf;

static PlatformSpecificFile PlatformSpecificFOpenImplementation(const char* filename, const char* flag)
{
   return fopen(filename, flag);
}

static void PlatformSpecificFPutsImplementation(const char* str, PlatformSpecificFile file)
{
   fputs(str, (FILE*)file);
}

static void PlatformSpecificFCloseImplementation(PlatformSpecificFile file)
{
   fclose((FILE*)file);
}

static void PlatformSpecificFlushImplementation()
{
  fflush(stdout);
}

PlatformSpecificFile (*PlatformSpecificFOpen)(const char*, const char*) = PlatformSpecificFOpenImplementation;
void (*PlatformSpecificFPuts)(const char*, PlatformSpecificFile) = PlatformSpecificFPutsImplementation;
void (*PlatformSpecificFClose)(PlatformSpecificFile) = PlatformSpecificFCloseImplementation;

int (*PlatformSpecificPutchar)(int) = putchar;
void (*PlatformSpecificFlush)() = PlatformSpecificFlushImplementation;

void* (*PlatformSpecificMalloc)(size_t size) = malloc;
void* (*PlatformSpecificRealloc)(void*, size_t) = realloc;
void (*PlatformSpecificFree)(void* memory) = free;
void* (*PlatformSpecificMemCpy)(void*, const void*, size_t) = memcpy;
void* (*PlatformSpecificMemset)(void*, int, size_t) = memset;

static int IsNanImplementation(double d)
{
    return _isnan(d);
}

static int IsInfImplementation(double d)
{
    return isinf(d);
}

double (*PlatformSpecificFabs)(double) = fabs;
void (*PlatformSpecificSrand)(unsigned int) = srand;
int (*PlatformSpecificRand)(void) = rand;
int (*PlatformSpecificIsNan)(double) = IsNanImplementation;
int (*PlatformSpecificIsInf)(double) = IsInfImplementation;
int (*PlatformSpecificAtExit)(void(*func)(void)) = atexit;  /// this was undefined before

static PlatformSpecificMutex PThreadMutexCreate(void)
{
#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
    pthread_mutex_t *mutex = new pthread_mutex_t;

    pthread_mutex_init(mutex, NULLPTR);
    return (PlatformSpecificMutex)mutex;
#else
    return NULLPTR;
#endif

}

#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
static void PThreadMutexLock(PlatformSpecificMutex mtx)
{
    pthread_mutex_lock((pthread_mutex_t *)mtx);
}
#else
static void PThreadMutexLock(PlatformSpecificMutex)
{
}
#endif

#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
static void PThreadMutexUnlock(PlatformSpecificMutex mtx)
{
    pthread_mutex_unlock((pthread_mutex_t *)mtx);
}
#else
static void PThreadMutexUnlock(PlatformSpecificMutex)
{
}
#endif

#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
static void PThreadMutexDestroy(PlatformSpecificMutex mtx)
{
    pthread_mutex_t *mutex = (pthread_mutex_t *)mtx;
    pthread_mutex_destroy(mutex);
    delete mutex;
}
#else
static void PThreadMutexDestroy(PlatformSpecificMutex)
{
}
#endif

PlatformSpecificMutex (*PlatformSpecificMutexCreate)(void) = PThreadMutexCreate;
void (*PlatformSpecificMutexLock)(PlatformSpecificMutex) = PThreadMutexLock;
void (*PlatformSpecificMutexUnlock)(PlatformSpecificMutex) = PThreadMutexUnlock;
void (*PlatformSpecificMutexDestroy)(PlatformSpecificMutex) = PThreadMutexDestroy;

}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <primitives/block.h>

#ifndef NO_GLOBALTOKEN_HARDFORK
#include <globaltoken/hardfork.h>
#else
#define IsHardForkActivated(nTime) (((nTime) >= (1527811200)) ? true : false)
#endif
#include <hash.h>
#include <tinyformat.h>
#include <utilstrencodings.h>
#include <crypto/common.h>
#include <crypto/algos/hashlib/multihash.h>
#include <crypto/algos/neoscrypt/neoscrypt.h>
#include <crypto/algos/scrypt/scrypt.h>
#include <crypto/algos/yescrypt/yescrypt.h>

#ifndef NO_GLOBALTOKEN_HARDFORK
uint256 CBlockHeader::GetHash(const Consensus::Params& params) const
{
    int version;
    if (IsHardForkActivated(nTime, params)) {
        version = PROTOCOL_VERSION;
    } else {
        version = PROTOCOL_VERSION | SERIALIZE_BLOCK_LEGACY;
    }
    CHashWriter writer(SER_GETHASH, version);
    ::Serialize(writer, *this);
    return writer.GetHash();
}

uint256 CBlockHeader::GetHash() const
{
    const Consensus::Params& consensusParams = Params().GetConsensus();
    return GetHash(consensusParams);
}
#else
uint256 CBlockHeader::GetHash() const
{
    int version;
    if (IsHardForkActivated(nTime)) {
        version = PROTOCOL_VERSION;
    } else {
        version = PROTOCOL_VERSION | SERIALIZE_BLOCK_LEGACY;
    }
    CHashWriter writer(SER_GETHASH, version);
    ::Serialize(writer, *this);
    return writer.GetHash();
}
#endif
int CBlockHeader::GetAlgo() const
{
	if (IsHardForkActivated(nTime))
	{
		return nAlgo;
	}
	return ALGO_SHA256D;
}

uint256 CBlockHeader::GetPoWHash(int algo) const
{
    switch (algo)
    {
        case ALGO_SHA256D:
            return GetHash();
        case ALGO_SCRYPT:
        {
            uint256 thash;
            scrypt_1024_1_1_256(BEGIN(nVersion), BEGIN(thash));
            return thash;
        }
        case ALGO_X11:
        {
            uint32_t default_nonce = (uint32_t)nNonce.GetUint64(0);
            return HashX11(BEGIN(nVersion), END(default_nonce));
        }
        case ALGO_NEOSCRYPT:
        {
            unsigned int profile = 0x0;
            uint256 thash;
            neoscrypt((unsigned char *) &nVersion, (unsigned char *) &thash, profile);
            return thash;
        }
        case ALGO_EQUIHASH:
            return GetHash();
        case ALGO_YESCRYPT:
        {
            uint256 thash;
            yescrypt_hash(BEGIN(nVersion), BEGIN(thash));
            return thash;
        }
        case ALGO_HMQ1725:
        {
            uint32_t default_nonce = (uint32_t)nNonce.GetUint64(0);
            return HMQ1725(BEGIN(nVersion), END(default_nonce));
        }
    }
    return GetHash();
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=0x%08x, powalgo=%u, powalgoname=%s, powhash=%s, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%s, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        GetAlgo(),
        GetAlgoName(GetAlgo()),
        GetPoWHash(GetAlgo()).ToString(),
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce.GetHex(),
        vtx.size());
    for (const auto& tx : vtx) {
        s << "  " << tx->ToString() << "\n";
    }
    return s.str();
}

std::string GetAlgoName(int Algo)
{
    switch (Algo)
    {
        case ALGO_SHA256D:
            return std::string("sha256d");
        case ALGO_SCRYPT:
            return std::string("scrypt");
        case ALGO_X11:
            return std::string("x11");
        case ALGO_NEOSCRYPT:
            return std::string("neoscrypt");
        case ALGO_YESCRYPT:
            return std::string("yescrypt");
        case ALGO_EQUIHASH:
            return std::string("equihash");
	case ALGO_HMQ1725:
            return std::string("hmq1725");
    }
    return std::string("unknown");
}
<commit_msg>chainparams.h not included<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <primitives/block.h>

#ifndef NO_GLOBALTOKEN_HARDFORK
#include <globaltoken/hardfork.h>
#else
#define IsHardForkActivated(nTime) (((nTime) >= (1527811200)) ? true : false)
#endif
#include <hash.h>
#include <tinyformat.h>
#include <utilstrencodings.h>
#include <chainparams.h>
#include <crypto/common.h>
#include <crypto/algos/hashlib/multihash.h>
#include <crypto/algos/neoscrypt/neoscrypt.h>
#include <crypto/algos/scrypt/scrypt.h>
#include <crypto/algos/yescrypt/yescrypt.h>

#ifndef NO_GLOBALTOKEN_HARDFORK
uint256 CBlockHeader::GetHash(const Consensus::Params& params) const
{
    int version;
    if (IsHardForkActivated(nTime, params)) {
        version = PROTOCOL_VERSION;
    } else {
        version = PROTOCOL_VERSION | SERIALIZE_BLOCK_LEGACY;
    }
    CHashWriter writer(SER_GETHASH, version);
    ::Serialize(writer, *this);
    return writer.GetHash();
}

uint256 CBlockHeader::GetHash() const
{
    const Consensus::Params& consensusParams = Params().GetConsensus();
    return GetHash(consensusParams);
}
#else
uint256 CBlockHeader::GetHash() const
{
    int version;
    if (IsHardForkActivated(nTime)) {
        version = PROTOCOL_VERSION;
    } else {
        version = PROTOCOL_VERSION | SERIALIZE_BLOCK_LEGACY;
    }
    CHashWriter writer(SER_GETHASH, version);
    ::Serialize(writer, *this);
    return writer.GetHash();
}
#endif
int CBlockHeader::GetAlgo() const
{
	if (IsHardForkActivated(nTime))
	{
		return nAlgo;
	}
	return ALGO_SHA256D;
}

uint256 CBlockHeader::GetPoWHash(int algo) const
{
    switch (algo)
    {
        case ALGO_SHA256D:
            return GetHash();
        case ALGO_SCRYPT:
        {
            uint256 thash;
            scrypt_1024_1_1_256(BEGIN(nVersion), BEGIN(thash));
            return thash;
        }
        case ALGO_X11:
        {
            uint32_t default_nonce = (uint32_t)nNonce.GetUint64(0);
            return HashX11(BEGIN(nVersion), END(default_nonce));
        }
        case ALGO_NEOSCRYPT:
        {
            unsigned int profile = 0x0;
            uint256 thash;
            neoscrypt((unsigned char *) &nVersion, (unsigned char *) &thash, profile);
            return thash;
        }
        case ALGO_EQUIHASH:
            return GetHash();
        case ALGO_YESCRYPT:
        {
            uint256 thash;
            yescrypt_hash(BEGIN(nVersion), BEGIN(thash));
            return thash;
        }
        case ALGO_HMQ1725:
        {
            uint32_t default_nonce = (uint32_t)nNonce.GetUint64(0);
            return HMQ1725(BEGIN(nVersion), END(default_nonce));
        }
    }
    return GetHash();
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=0x%08x, powalgo=%u, powalgoname=%s, powhash=%s, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%s, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        GetAlgo(),
        GetAlgoName(GetAlgo()),
        GetPoWHash(GetAlgo()).ToString(),
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce.GetHex(),
        vtx.size());
    for (const auto& tx : vtx) {
        s << "  " << tx->ToString() << "\n";
    }
    return s.str();
}

std::string GetAlgoName(int Algo)
{
    switch (Algo)
    {
        case ALGO_SHA256D:
            return std::string("sha256d");
        case ALGO_SCRYPT:
            return std::string("scrypt");
        case ALGO_X11:
            return std::string("x11");
        case ALGO_NEOSCRYPT:
            return std::string("neoscrypt");
        case ALGO_YESCRYPT:
            return std::string("yescrypt");
        case ALGO_EQUIHASH:
            return std::string("equihash");
	case ALGO_HMQ1725:
            return std::string("hmq1725");
    }
    return std::string("unknown");
}
<|endoftext|>