<commit_before>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @file

#ifndef DO_IMAGEPROCESSING_SCALING_HPP
#define DO_IMAGEPROCESSING_SCALING_HPP

namespace DO {

  /*!
    \ingroup ImageProcessing
    \defgroup Scaling Reduce, enlarge, warp image...
    @{
   */

  // ====================================================================== //
  // Naive upsampling and downsampling functions.
  template <typename T, int N>
  Image<T, N> upscale(const Image<T, N>& I, int fact)
  {
    Image<T, N> I1(I.sizes()*fact);
    typename Image<T, N>::range_iterator it(I1.begin_range());
    typename Image<T, N>::range_iterator end(I1.end_range());
    for ( ; it != end; ++it)
      *it = I(it.coords() / fact);
    return I1;
  }

  template <typename T, int N>
  Image<T, N> downscale(const Image<T, N>& I, int fact)
  {
    Image<T, N> I1(I.sizes()/fact);
    typename Image<T, N>::range_iterator it(I1.begin_range());
    typename Image<T, N>::range_iterator end(I1.end_range());
    for ( ; it != end; ++it)
      *it = I(it.position()*fact);
    return I1;
  }

  template <typename T, int N>
  inline std::pair<T, T> range(const Matrix<T, N, 1>& v)
  {
    return std::make_pair(
      *std::min_element(v.data(), v.data()+N),
      *std::max_element(v.data(), v.data()+N)
    );
  }

  template <typename T, int N>
  Image<T, N> reduce(const Image<T,N>& I, Matrix<int, N, 1> newSizes,
                     bool keepRatio=false)
  {
    typedef Matrix<double, N, 1> Vectord;

    // Convert in floating type scalar.
    typedef typename ColorTraits<T>::Color64f Color64f;
    Image<Color64f, N> oriI;
    convert(oriI, I);

    // Determine the right blurring factor.
    Vectord oriSizes(I.sizes().template cast<double>());
    Vectord f = oriSizes.cwiseQuotient(newSizes.template cast<double>());
    std::pair<double, double> mM = range(f);
    assert(mM.first >= 1.);
    if (keepRatio)
    {
      f.fill(mM.second);
      newSizes = (oriSizes/mM.second).template cast<int>();
    }

    Vectord sigmas = 1.5*((f.array().sqrt()-.99).matrix());

    // Blur with the Deriche filter.
    inPlaceDericheBlur(oriI, sigmas);

    // Create the new image by interpolating pixel values.
    Image<T, N> nI(newSizes);
    typename Image<T, N>::range_iterator r(nI.begin_range());
    typename Image<T, N>::range_iterator end(nI.end_range());
    for ( ; r != end; ++r)
    {
      Vectord x( r.coords()->template cast<double>().cwiseProduct(f) );
      convertColor(*r, interpolate(oriI, x));
    }

    return nI;
  }

  template <typename T>
  inline  Image<T,2> reduce(const Image<T,2>& I, int w, int h, bool keepRatio=false)
  { return reduce(I, Vector2i(w,h), keepRatio); }

  template <typename T>
  inline Image<T,3> reduce(const Image<T,3>& I, int w, int h, int d, bool keepRatio=false)
  { return reduce(I, Vector3i(w,h,d), keepRatio); }

  template <typename T,int N>
  inline Image<T,N> reduce(const Image<T,N>& I,double fact)
  {
    Matrix<int, N, 1> nd( (I.sizes().template cast<double>()/fact).
                         template cast<int>() );
    return reduce(I,nd);
  }

  template <typename T, int N>
  inline Image<T,N> enlarge(const Image<T,N>& I, Matrix<int, N, 1> newSizes,
                            bool keepRatio=false)
  {
    typedef Matrix<double, N, 1> Vectord;

    // Determine the right blurring factor.
    Vectord oriSizes(I.sizes().template cast<double>());
    Vectord f = oriSizes.cwiseQuotient(newSizes.template cast<double>());
    std::pair<double, double> mM = range(f);
    assert(mM.second <= 1.);
    if (keepRatio)
    {
      f.fill(mM.second);
      newSizes = (oriSizes/mM.second).template cast<int>();
    }

    // Create the new image by interpolation.
    Image<T,N> nI(newSizes);
    typename Image<T, N>::range_iterator r(nI.begin_range());
    typename Image<T, N>::range_iterator end(nI.end_range());
    for ( ; r != end; ++r)
    {
      Vectord x( r.position().template cast<double>().cwiseProduct(f) );
      convertColor(*r, interpolate(I, x));
    }
    return nI;
  }

  template <typename T>
  inline Image<T,2> enlarge(const Image<T,2>& I, int w, int h,
                            bool keepRatio = false)
  { return enlarge(I, Point2i(w,h), keepRatio); }

  template <typename T>
  inline Image<T,3> enlarge(const Image<T,3>& I, int w, int h, int d,
                            bool keepRatio = false)
  { return enlarge(I, Vector3i(w,h,d), keepRatio); }

  template <typename T,int N>
  inline Image<T,N> enlarge(const Image<T,N>&I,double fact)
  {
    Matrix<int, N, 1> nd( (I.sizes().template cast<double>()*fact).
                         template cast<int>() );
    return enlarge(I,nd);
  }

  //! @} file
}

#endif /* DO_IMAGEPROCESSING_SCALING_HPP */<commit_msg>Clean code and add some docstrings.<commit_after>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @file

#ifndef DO_IMAGEPROCESSING_SCALING_HPP
#define DO_IMAGEPROCESSING_SCALING_HPP

#include <DO/Core/Image/Image.hpp>
#include <DO/Core/Image/Operations.hpp>
#include <DO/ImageProcessing/Deriche.hpp>
#include <DO/ImageProcessing/Interpolation.hpp>

namespace DO {

  /*!
    \ingroup ImageProcessing
    \defgroup Scaling Reduce, enlarge, warp image...
    @{
   */

  //! \brief Upscale image.
  template <typename T, int N>
  Image<T, N> upscale(const Image<T, N>& src, int fact)
  {
    Image<T, N> dst(src.sizes()*fact);
    typename Image<T, N>::array_iterator it(dst.begin_array());
    for ( ; !it.end(); ++it)
      *it = src(it.position() / fact);
    return dst;
  }

  //! \brief Downscale image.
  template <typename T, int N>
  Image<T, N> downscale(const Image<T, N>& src, int fact)
  {
    Image<T, N> dst(src.sizes()/fact);
    typename Image<T, N>::array_iterator it(dst.begin_array());
    for ( ; !it.end(); ++it)
      *it = src(it.position()*fact);
    return dst;
  }

  //! \brief Find min and max coefficient of a vector.
  template <typename T, int N>
  inline std::pair<T, T> range(const Matrix<T, N, 1>& v)
  {
    return std::make_pair(
      *std::min_element(v.data(), v.data()+N),
      *std::max_element(v.data(), v.data()+N)
    );
  }

  //! \brief Reduce image.
  template <typename T, int N>
  Image<T, N> reduce(const Image<T, N>& src, Matrix<int, N, 1> new_sizes,
                     bool keep_ratio=false)
  {
    // Typedefs.
    typedef typename PixelTraits<T>::template Cast<double>::pixel_type
      DoublePixel;
    typedef typename PixelTraits<T>::channel_type ChannelType;

    // Convert in floating type scalar.
    Image<DoublePixel, N> double_src;
    convert_channel(src, double_src);

    Matrix<double, N, 1> original_sizes;
    Matrix<double, N, 1> scale_factors;
    Matrix<double, N, 1> sigmas;
    std::pair<double, double> min_max;

    // Determine the right blurring factor.
    original_sizes = src.sizes().cast<double>();
    scale_factors = original_sizes.cwiseQuotient(new_sizes.cast<double>());
    min_max = range(scale_factors);
    if (keep_ratio)
    {
      scale_factors.fill(min_max.second);
      new_sizes = (original_sizes/min_max.second).cast<int>();
    }
    sigmas = 1.5*((scale_factors.array().sqrt()-.99).matrix());

    // Blur with Deriche filter.
    inplace_deriche_blur(double_src, sigmas);

    // Create the new image by interpolating pixel values.
    Image<T, N> dst(new_sizes);
    typename Image<T, N>::array_iterator dst_it(dst.begin_array());
    for ( ; !dst_it.end(); ++dst_it)
    {
      Matrix<double, N, 1> position( dst_it.position()
        .cast<double>()
        .cwiseProduct(scale_factors) );

      DoublePixel double_pixel_value;
      double_pixel_value = interpolate(double_src, position);
      convert_channel(double_pixel_value, *dst_it);
    }

    return dst;
  }

  //! \brief Reduce image.
  template <typename T>
  inline  Image<T, 2> reduce(const Image<T, 2>& image, int w, int h,
                             bool keep_ratio = false)
  {
    return reduce(image, Vector2i(w,h), keep_ratio);
  }

  //! \brief Reduce image.
  template <typename T>
  inline Image<T, 3> reduce(const Image<T, 3>& image, int w, int h, int d,
                            bool keep_ratio = false)
  {
    return reduce(image, Vector3i(w,h,d), keep_ratio);
  }

  //! \brief Reduce image.
  template <typename T,int N>
  inline Image<T, N> reduce(const Image<T, N>& image, double fact)
  {
    Matrix<double, N, 1> new_sizes;
    new_sizes = image.sizes().template cast<double>() / fact;
    return reduce(image, new_sizes.template cast<int>().eval());
  }

  //! \brief Reduce image.
  template <typename T, int N>
  inline Image<T, N> enlarge(const Image<T, N>& image,
                             Matrix<int, N, 1> new_sizes,
                             bool keep_ratio = false)
  {
    typedef Matrix<double, N, 1> double_coords_type;

    // Determine the right blurring factor.
    double_coords_type original_sizes(image.sizes().template cast<double>());
    double_coords_type scale_factor = original_sizes.cwiseQuotient(
      new_sizes.cast<double>());
    std::pair<double, double> min_max = range(scale_factor);

    if (keep_ratio)
    {
      scale_factor.fill(min_max.second);
      new_sizes = (original_sizes/min_max.second).cast<int>();
    }

    // Create the new image by interpolation.
    Image<T,N> dst(new_sizes);
    typename Image<T, N>::array_iterator dst_it(dst.begin_array());
    for ( ; !dst_it.end(); ++dst_it)
    {
      double_coords_type position;
      position = dst_it.position()
        .template cast<double>()
        .cwiseProduct(scale_factor);
      convert_channel(interpolate(image, position), *dst_it);
    }
    return dst;
  }

  //! \brief Enlarge image.
  template <typename T>
  inline Image<T, 2> enlarge(const Image<T, 2>& image, int w, int h,
                             bool keep_ratio = false)
  {
    return enlarge(image, Point2i(w,h), keep_ratio);
  }

  //! \brief Enlarge image.
  template <typename T>
  inline Image<T, 3> enlarge(const Image<T, 3>& image, int w, int h, int d,
                             bool keep_ratio = false)
  {
    return enlarge(image, Vector3i(w,h,d), keep_ratio);
  }

  //! \brief Enlarge image.
  template <typename T,int N>
  inline Image<T, N> enlarge(const Image<T, N>& image, double fact)
  {
    Matrix<double, N, 1> new_sizes;
    new_sizes = image.sizes().cast<double>()*fact;
    return enlarge(image, new_sizes.cast<int>().eval());
  }

  //! @} file
}

#endif /* DO_IMAGEPROCESSING_SCALING_HPP */<|endoftext|>


<commit_before>// TestCIniFile::cpp : Defines the entry point for the console application.
//
#include "../src/IniFile.h"
#include <tchar.h>
#include <string>
#include <vector>

using namespace std;

void Show(string FileName)
{
	cout << endl
		 << "++++++++++++++++++++++++++++++++++++++++"
		 << endl
		 << "+ Contents of the file are below       +"
		 << endl
		 << "++++++++++++++++++++++++++++++++++++++++"
		 << endl
		 << CIniFile::Content(FileName)
		 << endl
		 << "++++++++++++++++++++++++++++++++++++++++"
		 << endl << endl;
	system ("PAUSE");
	system("cls");
}

int _tmain(int argc, _TCHAR* argv[])
{
    string str_num = "555";
    cout << convert<int>(str_num) << endl;

    float f_num = 666.0f;
    cout << convert<string>(f_num) << endl;

    system("PAUSE");
    system("cls");

	//CIniFile IniFile;
	string FileName = "test.ini";

	// Create a new file
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to create a new file called \"test.ini\"" << endl << endl;
	cout << "string FileName = \"test.ini\";" << endl;
	cout << "CIniFile::Create(FileName);" << endl << endl;
	if (CIniFile::Create(FileName)) cout << "File was successfully created" << endl << endl;
	else cout << "Failed to create the file" << endl << endl;
	Show(FileName);

	// Create a new section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to create a new section called [MySection]" << endl << endl;
	cout << "CIniFile::AddSection(\"MySection\", FileName);" << endl << endl;
	if (CIniFile::AddSection("MySection",FileName)) cout << "Section was successfully created" << endl << endl;
	else cout << "Failed to create the section" << endl << endl;
	Show(FileName);

	// Add a key to the section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to add a new key/value (MyKey=MyValue) to [MySection]" << endl << endl;
	cout << "CIniFile::SetValue(\"MyKey\",\"MyValue\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SetValue("MyKey","MyValue","MySection",FileName)) cout << "Record was successfully created" << endl << endl;
	else cout << "Failed to create the record" << endl << endl;
	Show(FileName);

	// Add a key and create a section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to add a new key/value (TestKey=TestValue)" << endl << "and create a new section [TestSection] at the same time" << endl << endl;
	cout << "CIniFile::SetValue(\"TestKey\",\"TestValue\",\"TestSection\",FileName);" << endl << endl;
	if (CIniFile::SetValue("TestKey","TestValue","TestSection",FileName)) cout << "Record and section were successfully created" << endl << endl;
	else cout << "Failed to create the record and section" << endl << endl;
	Show(FileName);

	// Change a key value
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to change the key/value for (MyKey=MyValue) to (MyKey=YourValue)" << endl << endl;
	cout << "CIniFile::SetValue(\"MyKey\",\"YourValue\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SetValue("MyKey","YourValue","MySection",FileName)) cout << "Record was successfully changed" << endl << endl;
	else cout << "Failed to change the record" << endl << endl;
	Show(FileName);

	// Get a value
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to get the value of MyKey" << endl << endl;
	cout << "CIniFile::GetValue(\"MyKey\",\"MySection\",FileName);" << endl << endl;
	string v = CIniFile::GetValue("MyKey","MySection",FileName);
	cout << "The value of MyKey is: " << v.c_str() << endl << endl;
	Show(FileName);

	// Get a list of Sections
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to get a list of sections" << endl << endl;
	cout << "CIniFile::GetSectionNames(FileName);" << endl << endl;
	vector<string> s = CIniFile::GetSectionNames(FileName);
	cout << "The sections are returned as a std::vector<std::string>\n\n";
	for(int i=0; i < (int)s.size(); i++)
		cout << s[i].c_str() << endl;
	Show(FileName);

	// Section Exists
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to verify that [MySection] exists" << endl << endl;
	cout << "CIniFile::SectionExists(\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SectionExists("MySection",FileName)) cout << "Section exists" << endl << endl;
	else cout << "Section does not exist" << endl << endl;
	Show(FileName);

	// Record Exists
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to verify that MyKey exists" << endl << endl;
	cout << "CIniFile::RecordExists(\"MyKey\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::RecordExists("MyKey","MySection",FileName)) cout << "Record exists" << endl << endl;
	else cout << "Record does not exist" << endl << endl;
	Show(FileName);

	// Case Sensitive
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "BE CAREFUL - functions in CIniFile are CASE-SENSITIVE" << endl << endl;
	cout << "CIniFile::RecordExists(\"mykey\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::RecordExists("mykey","MySection",FileName)) cout << "Record exists" << endl << endl;
	else cout << "Record does not exist" << endl << endl;
	Show(FileName);

	// Add a comment to the section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to add comments to [MySection]" << endl << endl;
	cout << "CIniFile::SetSectionComments(\"# This Section was created by CIniFile\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SetSectionComments("# This Section was created by CIniFile","MySection",FileName)) cout << "Comments were successfully added" << endl << endl;
	else cout << "Failed to add the comments" << endl << endl;
	Show(FileName);

	// Add a comment to the record
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to add comments to MyKey" << endl << endl;
	cout << "CIniFile::SetRecordComments(\"# This Key was created by CIniFile\",\"MyKey\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SetRecordComments("# This Key was created by CIniFile","MyKey","MySection",FileName)) cout << "Comments were successfully added" << endl << endl;
	else cout << "Failed to add the comments" << endl << endl;
	Show(FileName);

	// Rename Section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to rename [MySection] to [YourSection]" << endl << endl;
	cout << "CIniFile::RenameSection(\"MySection\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::RenameSection("MySection","YourSection",FileName)) cout << "Section was successfully changed" << endl << endl;
	else cout << "Failed to change the section" << endl << endl;
	Show(FileName);

	// Multiple comments
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Multiple comments can be added by putting \\n# in the comments string" << endl << endl;
	cout << "CIniFile::SetSectionComments(\"# This Section was created by CIniFile\\n# Kids, don't try this at home \\n\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::SetSectionComments("# This Section was created by CIniFile\n# Kids, don't try this at home","YourSection",FileName)) cout << "Comments were successfully added" << endl << endl;
	else cout << "Failed to add the comments" << endl << endl;
	Show(FileName);

	// Remove comments
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Comments are removed by setting them to \"\"" << endl << endl;
	cout << "CIniFile::SetRecordComments(\"\",\"MyKey\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::SetRecordComments("","MyKey","YourSection",FileName)) cout << "Comments were successfully removed" << endl << endl;
	else cout << "Failed to remove the comments" << endl << endl;
	Show(FileName);

	// Comment entire section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to comment the entire section [YourSection]" << endl << endl;
	cout << "CIniFile::CommentSection(\"#\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::CommentSection('#',"YourSection",FileName)) cout << "Section was successfully commented" << endl << endl;
	else cout << "Failed to comment the section" << endl << endl;
	Show(FileName);

	// UnComment entire section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to un-comment the entire section [YourSection]" << endl << endl;
	cout << "CIniFile::UnCommentSection(\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::UnCommentSection("YourSection",FileName)) cout << "Section was successfully un-commented" << endl << endl;
	else cout << "Failed to un-comment the section" << endl << endl;
	Show(FileName);

	// Comment a single record
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to comment the record MyKey" << endl << endl;
	cout << "(Note that both # and ; are recognized as commented lines by CIniFile)" << endl << endl;
	cout << "CIniFile::CommentRecord(CIniFile::CommentChar::Pound,\"MyKey\",\"YourSection\",FileName);" << endl << endl;
 	if (CIniFile::CommentRecord(CIniFile::CommentChar::Pound,"MyKey","YourSection",FileName)) cout << "Record was successfully commented" << endl << endl;
	else cout << "Failed to comment the record" << endl << endl;
	Show(FileName);

	// UnComment a single record
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to un-comment the record MyKey" << endl << endl;
	cout << "CIniFile::UnCommentRecord(\"MyKey\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::UnCommentRecord("MyKey","YourSection",FileName)) cout << "Record was successfully un-commented" << endl << endl;
	else cout << "Failed to un-comment the record" << endl << endl;
	Show(FileName);

	// Sort
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to sort the file - false means ASCENDING, true means DESCENDING" << endl << endl;
	cout << "(Note that the comments will stay with their targets)" << endl << endl;
	cout << "CIniFile::Sort(FileName,false);" << endl << endl;
	if (CIniFile::Sort(FileName,false)) cout << "File was successfully sorted" << endl << endl;
	else cout << "Failed to sort the file" << endl << endl;
	Show(FileName);

	// Delete entire section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to delete the entire section [TestSection]" << endl << endl;
	cout << "CIniFile::DeleteSection(\"TestSection\",FileName);" << endl << endl;
	if (CIniFile::DeleteSection("TestSection",FileName)) cout << "Section was successfully deleted" << endl << endl;
	else cout << "Failed to delete the section" << endl << endl;
	Show(FileName);

	// Delete record
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to delete the record <yKey" << endl << endl;
	cout << "CIniFile::DeleteRecord(\"MyKey\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::DeleteRecord("MyKey","YourSection",FileName)) cout << "Record was successfully deleted" << endl << endl;
	else cout << "Failed to delete the record" << endl << endl;
	Show(FileName);

	// Content
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Finally, the content of the file can be retrieved as a std::string" << endl << endl;
	cout << "CIniFile::Content(FileName);" << endl << endl;
	cout << "The contents of the file throughout this demo have used this function to display the contents below" << endl;
	Show(FileName);

	return 0;
}<commit_msg>将输入参数改为const引用<commit_after>// TestCIniFile::cpp : Defines the entry point for the console application.
//
#include "../src/IniFile.h"
#include <tchar.h>
#include <string>
#include <vector>

using namespace std;

void Show(const string& FileName)
{
	cout << endl
		 << "++++++++++++++++++++++++++++++++++++++++"
		 << endl
		 << "+ Contents of the file are below       +"
		 << endl
		 << "++++++++++++++++++++++++++++++++++++++++"
		 << endl
		 << CIniFile::Content(FileName)
		 << endl
		 << "++++++++++++++++++++++++++++++++++++++++"
		 << endl << endl;
	system ("PAUSE");
	system("cls");
}

int _tmain(int argc, _TCHAR* argv[])
{
    string str_num = "555";
    cout << convert<int>(str_num) << endl;

    float f_num = 666.0f;
    cout << convert<string>(f_num) << endl;

    system("PAUSE");
    system("cls");

	string FileName = "test.ini";
	//CIniFile IniFile;

	// Create a new file
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to create a new file called \"test.ini\"" << endl << endl;
	cout << "string FileName = \"test.ini\";" << endl;
	cout << "CIniFile::Create(FileName);" << endl << endl;
	if (CIniFile::Create(FileName)) cout << "File was successfully created" << endl << endl;
	else cout << "Failed to create the file" << endl << endl;
	Show(FileName);

	// Create a new section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to create a new section called [MySection]" << endl << endl;
	cout << "CIniFile::AddSection(\"MySection\", FileName);" << endl << endl;
	if (CIniFile::AddSection("MySection",FileName)) cout << "Section was successfully created" << endl << endl;
	else cout << "Failed to create the section" << endl << endl;
	Show(FileName);

	// Add a key to the section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to add a new key/value (MyKey=MyValue) to [MySection]" << endl << endl;
	cout << "CIniFile::SetValue(\"MyKey\",\"MyValue\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SetValue("MyKey","MyValue","MySection",FileName)) cout << "Record was successfully created" << endl << endl;
	else cout << "Failed to create the record" << endl << endl;
	Show(FileName);

	// Add a key and create a section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to add a new key/value (TestKey=TestValue)" << endl << "and create a new section [TestSection] at the same time" << endl << endl;
	cout << "CIniFile::SetValue(\"TestKey\",\"TestValue\",\"TestSection\",FileName);" << endl << endl;
	if (CIniFile::SetValue("TestKey","TestValue","TestSection",FileName)) cout << "Record and section were successfully created" << endl << endl;
	else cout << "Failed to create the record and section" << endl << endl;
	Show(FileName);

	// Change a key value
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to change the key/value for (MyKey=MyValue) to (MyKey=YourValue)" << endl << endl;
	cout << "CIniFile::SetValue(\"MyKey\",\"YourValue\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SetValue("MyKey","YourValue","MySection",FileName)) cout << "Record was successfully changed" << endl << endl;
	else cout << "Failed to change the record" << endl << endl;
	Show(FileName);

	// Get a value
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to get the value of MyKey" << endl << endl;
	cout << "CIniFile::GetValue(\"MyKey\",\"MySection\",FileName);" << endl << endl;
	string v = CIniFile::GetValue("MyKey","MySection",FileName);
	cout << "The value of MyKey is: " << v.c_str() << endl << endl;
	Show(FileName);

	// Get a list of Sections
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to get a list of sections" << endl << endl;
	cout << "CIniFile::GetSectionNames(FileName);" << endl << endl;
	vector<string> s = CIniFile::GetSectionNames(FileName);
	cout << "The sections are returned as a std::vector<std::string>\n\n";
	for(int i=0; i < (int)s.size(); i++)
		cout << s[i].c_str() << endl;
	Show(FileName);

	// Section Exists
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to verify that [MySection] exists" << endl << endl;
	cout << "CIniFile::SectionExists(\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SectionExists("MySection",FileName)) cout << "Section exists" << endl << endl;
	else cout << "Section does not exist" << endl << endl;
	Show(FileName);

	// Record Exists
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to verify that MyKey exists" << endl << endl;
	cout << "CIniFile::RecordExists(\"MyKey\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::RecordExists("MyKey","MySection",FileName)) cout << "Record exists" << endl << endl;
	else cout << "Record does not exist" << endl << endl;
	Show(FileName);

	// Case Sensitive
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "BE CAREFUL - functions in CIniFile are CASE-SENSITIVE" << endl << endl;
	cout << "CIniFile::RecordExists(\"mykey\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::RecordExists("mykey","MySection",FileName)) cout << "Record exists" << endl << endl;
	else cout << "Record does not exist" << endl << endl;
	Show(FileName);

	// Add a comment to the section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to add comments to [MySection]" << endl << endl;
	cout << "CIniFile::SetSectionComments(\"# This Section was created by CIniFile\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SetSectionComments("# This Section was created by CIniFile","MySection",FileName)) cout << "Comments were successfully added" << endl << endl;
	else cout << "Failed to add the comments" << endl << endl;
	Show(FileName);

	// Add a comment to the record
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to add comments to MyKey" << endl << endl;
	cout << "CIniFile::SetRecordComments(\"# This Key was created by CIniFile\",\"MyKey\",\"MySection\",FileName);" << endl << endl;
	if (CIniFile::SetRecordComments("# This Key was created by CIniFile","MyKey","MySection",FileName)) cout << "Comments were successfully added" << endl << endl;
	else cout << "Failed to add the comments" << endl << endl;
	Show(FileName);

	// Rename Section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to rename [MySection] to [YourSection]" << endl << endl;
	cout << "CIniFile::RenameSection(\"MySection\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::RenameSection("MySection","YourSection",FileName)) cout << "Section was successfully changed" << endl << endl;
	else cout << "Failed to change the section" << endl << endl;
	Show(FileName);

	// Multiple comments
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Multiple comments can be added by putting \\n# in the comments string" << endl << endl;
	cout << "CIniFile::SetSectionComments(\"# This Section was created by CIniFile\\n# Kids, don't try this at home \\n\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::SetSectionComments("# This Section was created by CIniFile\n# Kids, don't try this at home","YourSection",FileName)) cout << "Comments were successfully added" << endl << endl;
	else cout << "Failed to add the comments" << endl << endl;
	Show(FileName);

	// Remove comments
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Comments are removed by setting them to \"\"" << endl << endl;
	cout << "CIniFile::SetRecordComments(\"\",\"MyKey\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::SetRecordComments("","MyKey","YourSection",FileName)) cout << "Comments were successfully removed" << endl << endl;
	else cout << "Failed to remove the comments" << endl << endl;
	Show(FileName);

	// Comment entire section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to comment the entire section [YourSection]" << endl << endl;
	cout << "CIniFile::CommentSection(\"#\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::CommentSection('#',"YourSection",FileName)) cout << "Section was successfully commented" << endl << endl;
	else cout << "Failed to comment the section" << endl << endl;
	Show(FileName);

	// UnComment entire section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to un-comment the entire section [YourSection]" << endl << endl;
	cout << "CIniFile::UnCommentSection(\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::UnCommentSection("YourSection",FileName)) cout << "Section was successfully un-commented" << endl << endl;
	else cout << "Failed to un-comment the section" << endl << endl;
	Show(FileName);

	// Comment a single record
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to comment the record MyKey" << endl << endl;
	cout << "(Note that both # and ; are recognized as commented lines by CIniFile)" << endl << endl;
	cout << "CIniFile::CommentRecord(CIniFile::CommentChar::Pound,\"MyKey\",\"YourSection\",FileName);" << endl << endl;
 	if (CIniFile::CommentRecord(CIniFile::CommentChar::Pound,"MyKey","YourSection",FileName)) cout << "Record was successfully commented" << endl << endl;
	else cout << "Failed to comment the record" << endl << endl;
	Show(FileName);

	// UnComment a single record
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to un-comment the record MyKey" << endl << endl;
	cout << "CIniFile::UnCommentRecord(\"MyKey\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::UnCommentRecord("MyKey","YourSection",FileName)) cout << "Record was successfully un-commented" << endl << endl;
	else cout << "Failed to un-comment the record" << endl << endl;
	Show(FileName);

	// Sort
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to sort the file - false means ASCENDING, true means DESCENDING" << endl << endl;
	cout << "(Note that the comments will stay with their targets)" << endl << endl;
	cout << "CIniFile::Sort(FileName,false);" << endl << endl;
	if (CIniFile::Sort(FileName,false)) cout << "File was successfully sorted" << endl << endl;
	else cout << "Failed to sort the file" << endl << endl;
	Show(FileName);

	// Delete entire section
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to delete the entire section [TestSection]" << endl << endl;
	cout << "CIniFile::DeleteSection(\"TestSection\",FileName);" << endl << endl;
	if (CIniFile::DeleteSection("TestSection",FileName)) cout << "Section was successfully deleted" << endl << endl;
	else cout << "Failed to delete the section" << endl << endl;
	Show(FileName);

	// Delete record
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Attempting to delete the record <yKey" << endl << endl;
	cout << "CIniFile::DeleteRecord(\"MyKey\",\"YourSection\",FileName);" << endl << endl;
	if (CIniFile::DeleteRecord("MyKey","YourSection",FileName)) cout << "Record was successfully deleted" << endl << endl;
	else cout << "Failed to delete the record" << endl << endl;
	Show(FileName);

	// Content
	cout << "TestIniFile - Demo program for the CIniFile Class" << endl << endl;
	cout << "Finally, the content of the file can be retrieved as a std::string" << endl << endl;
	cout << "CIniFile::Content(FileName);" << endl << endl;
	cout << "The contents of the file throughout this demo have used this function to display the contents below" << endl;
	Show(FileName);

	return 0;
}<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
//  TEST    Foundation::Common
#include "Stroika/Foundation/StroikaPreComp.h"
/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
//  TEST    Foundation::Traveral
#include "Stroika/Foundation/StroikaPreComp.h"

#include "Stroika/Foundation/Characters/String.h"
#include "Stroika/Foundation/Characters/ToString.h"
#include "Stroika/Foundation/Common/GUID.h"
#include "Stroika/Foundation/Common/Property.h"
#include "Stroika/Foundation/Common/TemplateUtilities.h"
#include "Stroika/Foundation/Configuration/Endian.h"
#include "Stroika/Foundation/Memory/ObjectFieldUtilities.h"

#include "../TestHarness/TestHarness.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Common;
using namespace Stroika::Foundation::Traversal;

static_assert (is_same_v<Identity<double>::type, double>);

static_assert (is_same_v<DifferenceType<int>, int>);
static_assert (is_same_v<DifferenceType<double>, double>);

static_assert (is_same_v<UnsignedOfIf<int>, unsigned int>);
static_assert (is_same_v<UnsignedOfIf<double>, double>);
static_assert (is_same_v<UnsignedOfIf<string>, string>);

namespace {
    void Test_1_SpaceshipAutoGenForOpEqualsForCommonGUIDBug_ ()
    {
        Debug::TraceContextBumper ctx{L"{}::Test_1_SpaceshipAutoGenForOpEqualsForCommonGUIDBug_ ()"};
        {
            Common::GUID guidFromStr{L"61e4d49d-8c26-3480-f5c8-564e155c67a6"};
            Common::GUID guidFromArray{array<uint8_t, 16>{0x9d, 0xd4, 0xe4, 0x61, 0x26, 0x8c, 0x80, 0x34, 0xf5, 0xc8, 0x56, 0x4e, 0x15, 0x5c, 0x67, 0xa6}};
            if (Configuration ::GetEndianness () == Configuration::Endian::eX86) {
                VerifyTestResult (memcmp (&guidFromStr, &guidFromArray, sizeof (Common::GUID)) == 0);
            }
            if (memcmp (&guidFromStr, &guidFromArray, sizeof (Common::GUID)) == 0) {
                VerifyTestResult (guidFromStr == guidFromArray); // fails due to qCompilerAndStdLib_SpaceshipAutoGenForOpEqualsForCommonGUID_Buggy
            }
        }
    }
}

namespace {
    namespace Test02_Properties_ {
        namespace Private_ {

            struct Headers {
            public:
                Headers ();
                Headers (const Headers& src);
                Headers (Headers&& src);
                nonvirtual Headers& operator= (const Headers& rhs) = default; // properties are assignable, so this is OK
                nonvirtual Headers& operator                       = (Headers&& rhs);

                Property<unsigned int>           contentLength1; // both refer to the private fContentLength_ field
                Property<unsigned int>           contentLength2;
                Property<unsigned int>           contentLength3;
                ExtendableProperty<unsigned int> contentLength4;

            private:
                unsigned int fContentLength_{0};
            };
            Headers::Headers ()
                // Can implement getter/setters with this capture (wastes a bit of space)
                : contentLength1{
                      [this] ([[maybe_unused]] const auto* property) {
                          return fContentLength_;
                      },
                      [this] ([[maybe_unused]] auto* property, const auto& contentLength) {
                          fContentLength_ = contentLength;
                      }}
                // Can implement getter/setters with Memory::GetObjectOwningField - to save space, but counts on exact
                // storage layout and not totally legal with non- is_standard_layout<> - see Memory::GetObjectOwningField
                , contentLength2{
                      [] (const auto* property) {
                          const Headers* thisObj = Memory::GetObjectOwningField (property, &Headers::contentLength2);
                          return thisObj->fContentLength_;
                      },
                      [] (auto* property, auto contentLength) {
                          Headers* thisObj         = Memory::GetObjectOwningField (property, &Headers::contentLength2);
                          thisObj->fContentLength_ = contentLength;
                      }}
                , contentLength3{
                      [qStroika_Foundation_Common_Property_ExtraCaptureStuff] (const auto* property) {
                          const Headers* headerObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Headers::contentLength3);
                          return headerObj->fContentLength_;
                      },
                      [qStroika_Foundation_Common_Property_ExtraCaptureStuff] (auto* property, auto contentLength) {
                          Headers* thisObj         = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Headers::contentLength3);
                          thisObj->fContentLength_ = contentLength;
                      }}
                , contentLength4{
                      [qStroika_Foundation_Common_Property_ExtraCaptureStuff] (const auto* property) {
                          const Headers* headerObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Headers::contentLength4);
                          return headerObj->fContentLength_;
                      },
                      [qStroika_Foundation_Common_Property_ExtraCaptureStuff] (auto* property, auto contentLength) {
                          Headers* thisObj         = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Headers::contentLength4);
                          thisObj->fContentLength_ = contentLength;
                      }}
            {
            }
            Headers::Headers (const Headers& src)
                : Headers{} // do default initialization of properties
            {
                // NOTE - cannot INITIALIZE properties with src.Properties values since they are not copy constructible
                // but they are assignable, so do that
                contentLength1 = src.contentLength1;
                contentLength2 = src.contentLength2;
                // COULD EITHER initialize fContentLength_ or pContentLength1/pContentLength2 - but no need to do both
            }
            Headers::Headers (Headers&& src)
                : Headers{} // do default initialization of properties
            {
                // NOTE - cannot MOVE properties with src.Properties values since they are not copy constructible
                // but they are assignable, so do that
                contentLength1 = src.contentLength1;
                contentLength2 = src.contentLength2;
                // COULD EITHER initialize fContentLength_ or pContentLength1/pContentLength2 - but no need to do both
            }
            Headers& Headers::operator= (Headers&& rhs)
            {
                // Could copy either properties or underlying field - no matter which
                fContentLength_ = rhs.fContentLength_;
                return *this;
            }
        }
        void Run ()
        {
            Private_::Headers h;
            VerifyTestResult (h.contentLength1 == 0);
            h.contentLength1 = 2;
            VerifyTestResult (h.contentLength2 == 2);
            h.contentLength2 = 4;
            VerifyTestResult (h.contentLength1 == 4);
            Private_::Headers h2 = h;
            VerifyTestResult (h2.contentLength1 == 4);
            h.contentLength2 = 5;
            VerifyTestResult (h.contentLength1 == 5);
            VerifyTestResult (h2.contentLength1 == 4);

            {
                // event handlers
                VerifyTestResult (h2.contentLength4 == 4);
                h2.contentLength4 = 5;
                VerifyTestResult (h2.contentLength4 == 5);
                h2.contentLength4.rwHandlers ().push_front ([] ([[maybe_unused]] const auto& changes) {
                    DbgTrace ("first event handler called");
                    return true;
                });
                h2.contentLength4 = 6;
                VerifyTestResult (h2.contentLength4 == 6);
                h2.contentLength4.rwHandlers ().push_front ([] ([[maybe_unused]] const auto& changes) {
                    DbgTrace ("second event handler called");
                    return false;
                });
                h2.contentLength4 = 7;
                VerifyTestResult (h2.contentLength4 == 6); // because event handler returned false, this time NO
            }
        }
    }
}

namespace {
    void DoRegressionTests_ ()
    {
        Debug::TraceContextBumper ctx{L"{}::DoRegressionTests_"};
        Test_1_SpaceshipAutoGenForOpEqualsForCommonGUIDBug_ ();
        Test02_Properties_::Run ();
    }
}

int main ([[maybe_unused]] int argc, [[maybe_unused]] const char* argv[])
{
    Stroika::TestHarness::Setup ();
    return Stroika::TestHarness::PrintPassOrFail (DoRegressionTests_);
}
<commit_msg>improved regtests<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
//  TEST    Foundation::Common
#include "Stroika/Foundation/StroikaPreComp.h"
/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
//  TEST    Foundation::Traveral
#include "Stroika/Foundation/StroikaPreComp.h"

#include "Stroika/Foundation/Characters/String.h"
#include "Stroika/Foundation/Characters/ToString.h"
#include "Stroika/Foundation/Common/GUID.h"
#include "Stroika/Foundation/Common/Property.h"
#include "Stroika/Foundation/Common/TemplateUtilities.h"
#include "Stroika/Foundation/Configuration/Endian.h"
#include "Stroika/Foundation/Memory/ObjectFieldUtilities.h"

#include "../TestHarness/TestHarness.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Common;
using namespace Stroika::Foundation::Traversal;

static_assert (is_same_v<Identity<double>::type, double>);

static_assert (is_same_v<DifferenceType<int>, int>);
static_assert (is_same_v<DifferenceType<double>, double>);

static_assert (is_same_v<UnsignedOfIf<int>, unsigned int>);
static_assert (is_same_v<UnsignedOfIf<double>, double>);
static_assert (is_same_v<UnsignedOfIf<string>, string>);

namespace {
    void Test_1_SpaceshipAutoGenForOpEqualsForCommonGUIDBug_ ()
    {
        Debug::TraceContextBumper ctx{L"{}::Test_1_SpaceshipAutoGenForOpEqualsForCommonGUIDBug_ ()"};
        {
            Common::GUID guidFromStr{L"61e4d49d-8c26-3480-f5c8-564e155c67a6"};
            Common::GUID guidFromArray{array<uint8_t, 16>{0x9d, 0xd4, 0xe4, 0x61, 0x26, 0x8c, 0x80, 0x34, 0xf5, 0xc8, 0x56, 0x4e, 0x15, 0x5c, 0x67, 0xa6}};
            if (Configuration ::GetEndianness () == Configuration::Endian::eX86) {
                VerifyTestResult (memcmp (&guidFromStr, &guidFromArray, sizeof (Common::GUID)) == 0);
            }
            if (memcmp (&guidFromStr, &guidFromArray, sizeof (Common::GUID)) == 0) {
                VerifyTestResult (guidFromStr == guidFromArray); // fails due to qCompilerAndStdLib_SpaceshipAutoGenForOpEqualsForCommonGUID_Buggy
            }
        }
    }
}

namespace {
    namespace Test02_Properties_ {
        namespace Private_ {

            struct Headers {
            public:
                Headers ();
                Headers (const Headers& src);
                Headers (Headers&& src);
                nonvirtual Headers& operator= (const Headers& rhs) = default; // properties are assignable, so this is OK
                nonvirtual Headers& operator                       = (Headers&& rhs);

                Property<unsigned int>           contentLength1; // both refer to the private fContentLength_ field
                Property<unsigned int>           contentLength2;
                Property<unsigned int>           contentLength3;
                ExtendableProperty<unsigned int> contentLength4;

            private:
                unsigned int fContentLength_{0};
            };
            Headers::Headers ()
                // Can implement getter/setters with this capture (wastes a bit of space)
                : contentLength1{
                      [this] ([[maybe_unused]] const auto* property) {
                          return fContentLength_;
                      },
                      [this] ([[maybe_unused]] auto* property, const auto& contentLength) {
                          fContentLength_ = contentLength;
                      }}
                // Can implement getter/setters with Memory::GetObjectOwningField - to save space, but counts on exact
                // storage layout and not totally legal with non- is_standard_layout<> - see Memory::GetObjectOwningField
                , contentLength2{
                      [] (const auto* property) {
                          const Headers* thisObj = Memory::GetObjectOwningField (property, &Headers::contentLength2);
                          return thisObj->fContentLength_;
                      },
                      [] (auto* property, auto contentLength) {
                          Headers* thisObj         = Memory::GetObjectOwningField (property, &Headers::contentLength2);
                          thisObj->fContentLength_ = contentLength;
                      }}
                , contentLength3{
                      [qStroika_Foundation_Common_Property_ExtraCaptureStuff] (const auto* property) {
                          const Headers* headerObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Headers::contentLength3);
                          return headerObj->fContentLength_;
                      },
                      [qStroika_Foundation_Common_Property_ExtraCaptureStuff] (auto* property, auto contentLength) {
                          Headers* thisObj         = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Headers::contentLength3);
                          thisObj->fContentLength_ = contentLength;
                      }}
                , contentLength4{
                      [qStroika_Foundation_Common_Property_ExtraCaptureStuff] (const auto* property) {
                          const Headers* headerObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Headers::contentLength4);
                          return headerObj->fContentLength_;
                      },
                      [qStroika_Foundation_Common_Property_ExtraCaptureStuff] (auto* property, auto contentLength) {
                          Headers* thisObj         = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Headers::contentLength4);
                          thisObj->fContentLength_ = contentLength;
                      }}
            {
            }
            Headers::Headers (const Headers& src)
                : Headers{} // do default initialization of properties
            {
                // NOTE - cannot INITIALIZE properties with src.Properties values since they are not copy constructible
                // but they are assignable, so do that
                contentLength1 = src.contentLength1;
                contentLength2 = src.contentLength2;
                // COULD EITHER initialize fContentLength_ or pContentLength1/pContentLength2 - but no need to do both
            }
            Headers::Headers (Headers&& src)
                : Headers{} // do default initialization of properties
            {
                // NOTE - cannot MOVE properties with src.Properties values since they are not copy constructible
                // but they are assignable, so do that
                contentLength1 = src.contentLength1;
                contentLength2 = src.contentLength2;
                // COULD EITHER initialize fContentLength_ or pContentLength1/pContentLength2 - but no need to do both
            }
            Headers& Headers::operator= (Headers&& rhs)
            {
                // Could copy either properties or underlying field - no matter which
                fContentLength_ = rhs.fContentLength_;
                return *this;
            }
        }
        void Run ()
        {
            Private_::Headers h;
            VerifyTestResult (h.contentLength1 == 0);
            h.contentLength1 = 2;
            VerifyTestResult (h.contentLength2 == 2);
            h.contentLength2 = 4;
            VerifyTestResult (h.contentLength1 == 4);
            Private_::Headers h2 = h;
            VerifyTestResult (h2.contentLength1 == 4);
            h.contentLength2 = 5;
            VerifyTestResult (h.contentLength1 == 5);
            VerifyTestResult (h2.contentLength1 == 4);

            {
                // event handlers
                VerifyTestResult (h2.contentLength4 == 4);
                h2.contentLength4 = 5;
                VerifyTestResult (h2.contentLength4 == 5);
                bool firstEventHanlderCalled{false};
                h2.contentLength4.rwHandlers ().push_front ([&] ([[maybe_unused]] const auto& changes) {
                    DbgTrace ("first event handler called");
                    firstEventHanlderCalled = true;
                    return true;
                });
                h2.contentLength4 = 6;
                VerifyTestResult (h2.contentLength4 == 6);
                bool secondEventHanlderCalled{false};
                VerifyTestResult (firstEventHanlderCalled);
                h2.contentLength4.rwHandlers ().push_front ([&] ([[maybe_unused]] const auto& changes) {
                    DbgTrace ("second event handler called");
                    secondEventHanlderCalled = true;
                    return false;
                });
                h2.contentLength4 = 7;
                VerifyTestResult (secondEventHanlderCalled);
                VerifyTestResult (h2.contentLength4 == 6); // because event handler returned false, this time NO
            }
        }
    }
}

namespace {
    void DoRegressionTests_ ()
    {
        Debug::TraceContextBumper ctx{L"{}::DoRegressionTests_"};
        Test_1_SpaceshipAutoGenForOpEqualsForCommonGUIDBug_ ();
        Test02_Properties_::Run ();
    }
}

int main ([[maybe_unused]] int argc, [[maybe_unused]] const char* argv[])
{
    Stroika::TestHarness::Setup ();
    return Stroika::TestHarness::PrintPassOrFail (DoRegressionTests_);
}
<|endoftext|>


<commit_before>#include <node.h>

#include <stdint.h>
#include <cstring>
#include <string>
#include <tuple>

#include "../argon2/include/argon2.h"
#include "argon2_node.h"

namespace NodeArgon2 {

template<class T = uint32_t>
T fromJust(v8::Local<v8::Value> info) {
    return Nan::To<T>(info).FromJust();
}

using size_type = std::string::size_type;

enum OBJECTS {
    RESERVED = 0,
    THIS_OBJ,
    RESOLVE,
    REJECT,
};

constexpr uint32_t log(uint64_t number, uint64_t base = 2u)
{
    return (number > 1) ? 1u + log(number / base, base) : 0u;
}

constexpr size_type base64Length(size_type length)
{
    return ((length + 2u) / 3u) * 4u;
}

size_type encodedLength(size_type hashLength, size_type saltLength)
{
    /* statically calculate maximum encoded hash length */
    constexpr size_type extraLength = sizeof "$argon2x$m=,t=,p=$$" +
        log(static_cast<uint64_t>(ARGON2_MAX_MEMORY) + 1u, 10u) +
        log(static_cast<uint64_t>(ARGON2_MAX_TIME) + 1u, 10u) +
        log(static_cast<uint64_t>(ARGON2_MAX_LANES) + 1u, 10u);

    return extraLength + base64Length(hashLength) + base64Length(saltLength);
}

HashWorker::HashWorker(std::string&& plain, std::string&& salt,
        uint32_t l, uint32_t t, uint32_t m, uint32_t p, argon2_type a):
    Nan::AsyncWorker{nullptr}, plain{std::move(plain)}, salt{std::move(salt)},
    hash_length{l}, time_cost{t}, memory_cost{m}, parallelism{p}, type{a}
{ }

void HashWorker::Execute()
{
    const auto ENCODED_LEN = encodedLength(hash_length, salt.size());
    output.reset(new char[ENCODED_LEN]);

    auto result = argon2_hash(time_cost, 1u << memory_cost, parallelism,
            plain.c_str(), plain.size(), salt.c_str(), salt.size(), nullptr,
            hash_length, output.get(), ENCODED_LEN, type, ARGON2_VERSION_NUMBER);

    if (result != ARGON2_OK) {
        /* LCOV_EXCL_START */
        SetErrorMessage(argon2_error_message(result));
        /* LCOV_EXCL_STOP */
    }
}

void HashWorker::HandleOKCallback()
{
    using namespace v8;
    using std::strlen;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::Encode(output.get(), strlen(output.get()))};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(RESOLVE).As<Function>(), 1, argv);
}

/* LCOV_EXCL_START */
void HashWorker::HandleErrorCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(ErrorMessage()).ToLocalChecked()};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(REJECT).As<Function>(), 1, argv);
}
/* LCOV_EXCL_STOP */

NAN_METHOD(Hash) {
    using namespace node;
    using namespace v8;

    assert(info.Length() >= 5);

    const auto plain = Nan::To<Object>(info[0]).ToLocalChecked();
    const auto salt = Nan::To<Object>(info[1]).ToLocalChecked();
    const auto options = Nan::To<Object>(info[2]).ToLocalChecked();

    const auto getArg = [&](const char* key) {
        auto localKey = Nan::New(key).ToLocalChecked();
        return Nan::Get(options, localKey).ToLocalChecked();
    };

    auto worker = new HashWorker{
            {Buffer::Data(plain), Buffer::Length(plain)},
            {Buffer::Data(salt), Buffer::Length(salt)},
            fromJust(getArg("hashLength")), fromJust(getArg("timeCost")),
            fromJust(getArg("memoryCost")), fromJust(getArg("parallelism")),
            fromJust<bool>(getArg("argon2d")) ? Argon2_d : Argon2_i};

    worker->SaveToPersistent(THIS_OBJ, info.This());
    worker->SaveToPersistent(RESOLVE, Local<Function>::Cast(info[3]));
    worker->SaveToPersistent(REJECT, Local<Function>::Cast(info[4]));

    Nan::AsyncQueueWorker(worker);
}

VerifyWorker::VerifyWorker(std::string&& hash, std::string&& plain):
    Nan::AsyncWorker{nullptr}, hash{std::move(hash)}, plain{std::move(plain)}
{ }

void VerifyWorker::Execute()
{
    auto type = (hash.at(7) == 'd') ? Argon2_d : Argon2_i;
    auto result = argon2_verify(hash.c_str(), plain.c_str(), plain.size(), type);

    switch (result) {
        case ARGON2_OK:
        case ARGON2_VERIFY_MISMATCH:
            output = result == ARGON2_OK;
            break;
        default:
            /* LCOV_EXCL_START */
            SetErrorMessage(argon2_error_message(result));
            break;
            /* LCOV_EXCL_STOP */
    }
}

void VerifyWorker::HandleOKCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(output)};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(RESOLVE).As<Function>(), 1, argv);
}

/* LCOV_EXCL_START */
void VerifyWorker::HandleErrorCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(ErrorMessage()).ToLocalChecked()};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(REJECT).As<Function>(), 1, argv);
}
/* LCOV_EXCL_STOP */

NAN_METHOD(Verify) {
    using namespace node;
    using namespace v8;

    assert(info.Length() >= 4);

    const auto hash = Nan::To<Object>(info[0]).ToLocalChecked();
    const auto plain = Nan::To<Object>(info[1]).ToLocalChecked();

    auto worker = new VerifyWorker{{Buffer::Data(hash), Buffer::Length(hash)},
            {Buffer::Data(plain), Buffer::Length(plain)}};

    worker->SaveToPersistent(THIS_OBJ, info.This());
    worker->SaveToPersistent(RESOLVE, Local<Function>::Cast(info[2]));
    worker->SaveToPersistent(REJECT, Local<Function>::Cast(info[3]));

    Nan::AsyncQueueWorker(worker);
}

NAN_MODULE_INIT(init) {
    using namespace v8;

    auto limits = Nan::New<Object>();

    const auto setMaxMin = [&](const char* name, uint32_t max, uint32_t min) {
        auto obj = Nan::New<Object>();
        Nan::Set(obj, Nan::New("max").ToLocalChecked(), Nan::New<Number>(max));
        Nan::Set(obj, Nan::New("min").ToLocalChecked(), Nan::New<Number>(min));
        Nan::Set(limits, Nan::New(name).ToLocalChecked(), obj);
    };

    setMaxMin("hashLength", ARGON2_MAX_OUTLEN, ARGON2_MIN_OUTLEN);
    setMaxMin("memoryCost", log(ARGON2_MAX_MEMORY), log(ARGON2_MIN_MEMORY));
    setMaxMin("timeCost", ARGON2_MAX_TIME, ARGON2_MIN_TIME);
    setMaxMin("parallelism", ARGON2_MAX_LANES, ARGON2_MIN_LANES);

    Nan::Set(target, Nan::New("limits").ToLocalChecked(), limits);
    Nan::Export(target, "hash", Hash);
    Nan::Export(target, "verify", Verify);
}

}

NODE_MODULE(argon2_lib, NodeArgon2::init);
<commit_msg>Remove unneeded include<commit_after>#include <node.h>

#include <stdint.h>
#include <cstring>
#include <string>

#include "../argon2/include/argon2.h"
#include "argon2_node.h"

namespace NodeArgon2 {

template<class T = uint32_t>
T fromJust(v8::Local<v8::Value> info) {
    return Nan::To<T>(info).FromJust();
}

using size_type = std::string::size_type;

enum OBJECTS {
    RESERVED = 0,
    THIS_OBJ,
    RESOLVE,
    REJECT,
};

constexpr uint32_t log(uint64_t number, uint64_t base = 2u)
{
    return (number > 1) ? 1u + log(number / base, base) : 0u;
}

constexpr size_type base64Length(size_type length)
{
    return ((length + 2u) / 3u) * 4u;
}

size_type encodedLength(size_type hashLength, size_type saltLength)
{
    /* statically calculate maximum encoded hash length */
    constexpr size_type extraLength = sizeof "$argon2x$m=,t=,p=$$" +
        log(static_cast<uint64_t>(ARGON2_MAX_MEMORY) + 1u, 10u) +
        log(static_cast<uint64_t>(ARGON2_MAX_TIME) + 1u, 10u) +
        log(static_cast<uint64_t>(ARGON2_MAX_LANES) + 1u, 10u);

    return extraLength + base64Length(hashLength) + base64Length(saltLength);
}

HashWorker::HashWorker(std::string&& plain, std::string&& salt,
        uint32_t l, uint32_t t, uint32_t m, uint32_t p, argon2_type a):
    Nan::AsyncWorker{nullptr}, plain{std::move(plain)}, salt{std::move(salt)},
    hash_length{l}, time_cost{t}, memory_cost{m}, parallelism{p}, type{a}
{ }

void HashWorker::Execute()
{
    const auto ENCODED_LEN = encodedLength(hash_length, salt.size());
    output.reset(new char[ENCODED_LEN]);

    auto result = argon2_hash(time_cost, 1u << memory_cost, parallelism,
            plain.c_str(), plain.size(), salt.c_str(), salt.size(), nullptr,
            hash_length, output.get(), ENCODED_LEN, type, ARGON2_VERSION_NUMBER);

    if (result != ARGON2_OK) {
        /* LCOV_EXCL_START */
        SetErrorMessage(argon2_error_message(result));
        /* LCOV_EXCL_STOP */
    }
}

void HashWorker::HandleOKCallback()
{
    using namespace v8;
    using std::strlen;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::Encode(output.get(), strlen(output.get()))};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(RESOLVE).As<Function>(), 1, argv);
}

/* LCOV_EXCL_START */
void HashWorker::HandleErrorCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(ErrorMessage()).ToLocalChecked()};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(REJECT).As<Function>(), 1, argv);
}
/* LCOV_EXCL_STOP */

NAN_METHOD(Hash) {
    using namespace node;
    using namespace v8;

    assert(info.Length() >= 5);

    const auto plain = Nan::To<Object>(info[0]).ToLocalChecked();
    const auto salt = Nan::To<Object>(info[1]).ToLocalChecked();
    const auto options = Nan::To<Object>(info[2]).ToLocalChecked();

    const auto getArg = [&](const char* key) {
        auto localKey = Nan::New(key).ToLocalChecked();
        return Nan::Get(options, localKey).ToLocalChecked();
    };

    auto worker = new HashWorker{
            {Buffer::Data(plain), Buffer::Length(plain)},
            {Buffer::Data(salt), Buffer::Length(salt)},
            fromJust(getArg("hashLength")), fromJust(getArg("timeCost")),
            fromJust(getArg("memoryCost")), fromJust(getArg("parallelism")),
            fromJust<bool>(getArg("argon2d")) ? Argon2_d : Argon2_i};

    worker->SaveToPersistent(THIS_OBJ, info.This());
    worker->SaveToPersistent(RESOLVE, Local<Function>::Cast(info[3]));
    worker->SaveToPersistent(REJECT, Local<Function>::Cast(info[4]));

    Nan::AsyncQueueWorker(worker);
}

VerifyWorker::VerifyWorker(std::string&& hash, std::string&& plain):
    Nan::AsyncWorker{nullptr}, hash{std::move(hash)}, plain{std::move(plain)}
{ }

void VerifyWorker::Execute()
{
    auto type = (hash.at(7) == 'd') ? Argon2_d : Argon2_i;
    auto result = argon2_verify(hash.c_str(), plain.c_str(), plain.size(), type);

    switch (result) {
        case ARGON2_OK:
        case ARGON2_VERIFY_MISMATCH:
            output = result == ARGON2_OK;
            break;
        default:
            /* LCOV_EXCL_START */
            SetErrorMessage(argon2_error_message(result));
            break;
            /* LCOV_EXCL_STOP */
    }
}

void VerifyWorker::HandleOKCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(output)};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(RESOLVE).As<Function>(), 1, argv);
}

/* LCOV_EXCL_START */
void VerifyWorker::HandleErrorCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(ErrorMessage()).ToLocalChecked()};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(REJECT).As<Function>(), 1, argv);
}
/* LCOV_EXCL_STOP */

NAN_METHOD(Verify) {
    using namespace node;
    using namespace v8;

    assert(info.Length() >= 4);

    const auto hash = Nan::To<Object>(info[0]).ToLocalChecked();
    const auto plain = Nan::To<Object>(info[1]).ToLocalChecked();

    auto worker = new VerifyWorker{{Buffer::Data(hash), Buffer::Length(hash)},
            {Buffer::Data(plain), Buffer::Length(plain)}};

    worker->SaveToPersistent(THIS_OBJ, info.This());
    worker->SaveToPersistent(RESOLVE, Local<Function>::Cast(info[2]));
    worker->SaveToPersistent(REJECT, Local<Function>::Cast(info[3]));

    Nan::AsyncQueueWorker(worker);
}

NAN_MODULE_INIT(init) {
    using namespace v8;

    auto limits = Nan::New<Object>();

    const auto setMaxMin = [&](const char* name, uint32_t max, uint32_t min) {
        auto obj = Nan::New<Object>();
        Nan::Set(obj, Nan::New("max").ToLocalChecked(), Nan::New<Number>(max));
        Nan::Set(obj, Nan::New("min").ToLocalChecked(), Nan::New<Number>(min));
        Nan::Set(limits, Nan::New(name).ToLocalChecked(), obj);
    };

    setMaxMin("hashLength", ARGON2_MAX_OUTLEN, ARGON2_MIN_OUTLEN);
    setMaxMin("memoryCost", log(ARGON2_MAX_MEMORY), log(ARGON2_MIN_MEMORY));
    setMaxMin("timeCost", ARGON2_MAX_TIME, ARGON2_MIN_TIME);
    setMaxMin("parallelism", ARGON2_MAX_LANES, ARGON2_MIN_LANES);

    Nan::Set(target, Nan::New("limits").ToLocalChecked(), limits);
    Nan::Export(target, "hash", Hash);
    Nan::Export(target, "verify", Verify);
}

}

NODE_MODULE(argon2_lib, NodeArgon2::init);
<|endoftext|>


<commit_before>// Copyright ***********************************************************
//
// File ecmdArrayUser.C
//
// IBM Confidential
// OCO Source Materials
// 9400 Licensed Internal Code
// (C) COPYRIGHT IBM CORP. 2003
//
// The source code for this program is not published or otherwise
// divested of its trade secrets, irrespective of what has been
// deposited with the U.S. Copyright Office.
//
// End Copyright *******************************************************
/* $Header$ */

// Module Description **************************************************
//
// Description:
//
// End Module Description **********************************************

//----------------------------------------------------------------------
//  Includes
//----------------------------------------------------------------------
#define ecmdArrayUser_C
#include <ecmdCommandUtils.H>
#include <ecmdReturnCodes.H>
#include <ecmdClientCapi.H>
#include <ecmdUtils.H>
#include <ecmdDataBuffer.H>
#undef ecmdArrayUser_C
//----------------------------------------------------------------------
//  User Types
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Constants
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Macros
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Internal Function Prototypes
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Global Variables
//----------------------------------------------------------------------

//---------------------------------------------------------------------
// Member Function Specifications
//---------------------------------------------------------------------

int ecmdGetArrayUser(int argc, char * argv[]) {
  int rc = ECMD_SUCCESS;

  /* get format flag, if it's there */
  std::string format;
  char * formatPtr = ecmdParseOptionWithArgs(&argc, &argv, "-o");
  if (formatPtr == NULL) {
    format = "x";
  }
  else {
    format = formatPtr;
  }

  /************************************************************************/
  /* Parse Common Cmdline Args                                            */
  /************************************************************************/

  rc = ecmdCommandArgs(&argc, &argv);
  if (rc) return rc;

  /************************************************************************/
  /* Parse Local ARGS here!                                               */
  /************************************************************************/
  if (argc < 3) {
    ecmdOutputError("getarray - Too few arguments specified; you need at least a chip, an array, and an address.\n");
    ecmdOutputError("getarray - Type 'getarray -h' for usage.");
    return ECMD_INVALID_ARGS;
  }

  //Setup the target that will be used to query the system config
  ecmdChipTarget target;
  target.chipType = argv[0];
  target.chipTypeState = ECMD_TARGET_QUERY_FIELD_VALID;
  target.cageState = target.nodeState = target.slotState = target.posState = target.coreState = ECMD_TARGET_QUERY_WILDCARD;
  target.threadState = ECMD_TARGET_FIELD_UNUSED;

  std::string arrayName = argv[1];

  ecmdDataBuffer address;
  /* Set the length based on the data provided */
  address.setBitLength(strlen(argv[2]) * 4);
  rc = address.insertFromHexRight(argv[2]);
  if (rc) return rc;

  ecmdDataBuffer buffer;

  bool validPosFound = false;
  rc = ecmdConfigLooperInit(target, ECMD_SELECTED_TARGETS_LOOP);
  if (rc) return rc;
  std::string printed;

  while ( ecmdConfigLooperNext(target) ) {

    rc = getArray(target, arrayName.c_str(), address, buffer);

    if (rc == ECMD_TARGET_NOT_CONFIGURED) {
      continue;
    }
    else if (rc) {
        printed = "getarray - Error occured performing getarray on ";
        printed += ecmdWriteTarget(target) + "\n";
        ecmdOutputError( printed.c_str() );
        return rc;
    }
    else {
      validPosFound = true;
    }

    printed = ecmdWriteTarget(target) + " " + arrayName + " " + address.genHexRightStr();

    std::string dataStr = ecmdWriteDataFormatted(buffer, format);
    if (dataStr[0] != '\n') {
      printed += "\n";
    }

    printed += dataStr;

    ecmdOutput( printed.c_str() );

  }

  if (!validPosFound) {
    //this is an error common across all UI functions
    ecmdOutputError("getarray - Unable to find a valid chip to execute command on\n");
    return ECMD_TARGET_NOT_CONFIGURED;
  }

  return rc;
}

int ecmdPutArrayUser(int argc, char * argv[]) {
  int rc = ECMD_SUCCESS;

  /* get format flag, if it's there */
  std::string format;
  char * formatPtr = ecmdParseOptionWithArgs(&argc, &argv, "-i");
  if (formatPtr == NULL) {
    format = "x";
  }
  else {
    format = formatPtr;
  }

  /************************************************************************/
  /* Parse Common Cmdline Args                                            */
  /************************************************************************/

  rc = ecmdCommandArgs(&argc, &argv);
  if (rc) return rc;

  /************************************************************************/
  /* Parse Local ARGS here!                                               */
  /************************************************************************/
  if (argc < 4) {
    ecmdOutputError("putarray - Too few arguments specified; you need at least a chip, an array, an address, and some data.\n");
    ecmdOutputError("putarray - Type 'putarray -h' for usage.");
    return ECMD_INVALID_ARGS;
  }

  //Setup the target that will be used to query the system config
  ecmdChipTarget target;
  target.chipType = argv[0];
  target.chipTypeState = ECMD_TARGET_QUERY_FIELD_VALID;
  target.cageState = target.nodeState = target.slotState = target.posState = target.coreState = ECMD_TARGET_QUERY_WILDCARD;
  target.threadState = ECMD_TARGET_FIELD_UNUSED;

  std::string arrayName = argv[1];

  ecmdDataBuffer address;
  address.setBitLength(strlen(argv[2]) * 4);
  rc = address.insertFromHexRight(argv[2]);
  if (rc) return rc;

  ecmdDataBuffer buffer;
  rc = ecmdReadDataFormatted(buffer, argv[3], format);
  if (rc) {
    ecmdOutputError("putarray - Problems occurred parsing input data, must be an invalid format\n");
    return rc;
  }

  bool validPosFound = false;
  rc = ecmdConfigLooperInit(target, ECMD_SELECTED_TARGETS_LOOP);
  if (rc) return rc;
  std::string printed;

  while ( ecmdConfigLooperNext(target) ) {

    rc = putArray(target, arrayName.c_str(), address, buffer);

    if (rc == ECMD_TARGET_NOT_CONFIGURED) {
      continue;
    }
    else if (rc) {
        printed = "putarray - Error occured performing putarray on ";
        printed += ecmdWriteTarget(target) + "\n";
        ecmdOutputError( printed.c_str() );
        return rc;
    }
    else {
      validPosFound = true;
    }

  }

  if (!validPosFound) {
    //this is an error common across all UI functions
    ecmdOutputError("putarray - Unable to find a valid chip to execute command on\n");
    return ECMD_TARGET_NOT_CONFIGURED;
  }

  return rc;
}

<commit_msg>Added support for getarray reading multiple consecutive entries<commit_after>// Copyright ***********************************************************
//
// File ecmdArrayUser.C
//
// IBM Confidential
// OCO Source Materials
// 9400 Licensed Internal Code
// (C) COPYRIGHT IBM CORP. 2003
//
// The source code for this program is not published or otherwise
// divested of its trade secrets, irrespective of what has been
// deposited with the U.S. Copyright Office.
//
// End Copyright *******************************************************
/* $Header$ */

// Module Description **************************************************
//
// Description:
//
// End Module Description **********************************************

//----------------------------------------------------------------------
//  Includes
//----------------------------------------------------------------------
#define ecmdArrayUser_C
#include <ecmdCommandUtils.H>
#include <ecmdReturnCodes.H>
#include <ecmdClientCapi.H>
#include <ecmdUtils.H>
#include <ecmdDataBuffer.H>
#undef ecmdArrayUser_C
//----------------------------------------------------------------------
//  User Types
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Constants
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Macros
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Internal Function Prototypes
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Global Variables
//----------------------------------------------------------------------

//---------------------------------------------------------------------
// Member Function Specifications
//---------------------------------------------------------------------

int ecmdGetArrayUser(int argc, char * argv[]) {
  int rc = ECMD_SUCCESS;

  ecmdChipTarget target;        ///< Current target
  std::string arrayName;        ///< Name of array to access
  ecmdDataBuffer address;       ///< Buffer to store address
  ecmdDataBuffer address_copy;  ///< Copy of address to modify in entry loop
  int  numEntries = 1;          ///< Number of consecutive entries to fetch
  bool validPosFound = false;   ///< Did we find something to actually execute on ?
  std::string printed;          ///< Print Buffer
  bool printedHeader;           ///< Have we printed the array name and pos
  std::list<ecmdArrayEntry> entries;    ///< List of arrays to fetch, to use getArrayMultiple
  ecmdArrayEntry entry;         ///< Array entry to fetch
  uint32_t* add_buffer;         ///< Buffer to do temp work with the address for incrementing
  ecmdArrayData arrayData;      ///< Query data about array

  /* get format flag, if it's there */
  std::string format;
  char * formatPtr = ecmdParseOptionWithArgs(&argc, &argv, "-o");
  if (formatPtr == NULL) {
    format = "x";
  }
  else {
    format = formatPtr;
  }

  /************************************************************************/
  /* Parse Common Cmdline Args                                            */
  /************************************************************************/

  rc = ecmdCommandArgs(&argc, &argv);
  if (rc) return rc;

  /************************************************************************/
  /* Parse Local ARGS here!                                               */
  /************************************************************************/
  if (argc < 3) {
    ecmdOutputError("getarray - Too few arguments specified; you need at least a chip, an array, and an address.\n");
    ecmdOutputError("getarray - Type 'getarray -h' for usage.");
    return ECMD_INVALID_ARGS;
  }

  //Setup the target that will be used to query the system config
  target.chipType = argv[0];
  target.chipTypeState = ECMD_TARGET_QUERY_FIELD_VALID;
  target.cageState = target.nodeState = target.slotState = target.posState = target.coreState = ECMD_TARGET_QUERY_WILDCARD;
  target.threadState = ECMD_TARGET_FIELD_UNUSED;

  arrayName = argv[1];

  /* Did the specify more then one entry ? */
  if (argc > 3) {
    numEntries = atoi(argv[3]);
  }

  rc = ecmdConfigLooperInit(target, ECMD_SELECTED_TARGETS_LOOP);
  if (rc) return rc;

  while ( ecmdConfigLooperNext(target) ) {

    /* We need to find out info about this array */
    rc = ecmdQueryArray(target, arrayData , arrayName.c_str());
    if (rc) {
      printed = "getarray - Problems retrieving data about array '" + arrayName + "' on ";
      printed += ecmdWriteTarget(target) + "\n";
      ecmdOutputError( printed.c_str() );
      return rc;
    }

    /* Set the length  */
    address.setBitLength(arrayData.addressLength);
    rc = address.insertFromHexRight(argv[2], arrayData.addressLength);
    if (rc) return rc;

    add_buffer = new uint32_t[address.getWordLength()];
    int idx, word;
    uint32_t add_inc = 1;           ///< Address increment, this will increment data by 1 for left aligned buffer
    uint32_t add_mask = 0xFFFFFFFF;     ///< Mask of valid bits in the last word of the address
    if (address.getBitLength() % 32) {
      add_inc = 1 << (32 - (address.getBitLength() % 32));
      add_mask <<= (32 - (address.getBitLength() % 32));
    }

    /* Extract the address into a buffer we can deal with */
    for (idx = 0; idx < address.getWordLength(); idx ++) {
      add_buffer[idx] = address.getWord(idx);
    }
    /* Setup the array entries we are going to fetch */
    for (int idx = 0; idx < numEntries; idx ++) {
      entry.address.setBitLength(address.getBitLength());
      entry.address.insert(add_buffer, 0, address.getBitLength());

      entries.push_back(entry);

      /* Increment for the next one */
      if (add_buffer[address.getWordLength()-1] == add_mask) {
        /* We are going to rollover */
        if (address.getWordLength() == 1) {
          printed = "getarray - Address overflow on " + arrayName + " ";
          printed += ecmdWriteTarget(target) + "\n";
          ecmdOutputError( printed.c_str() );
          return ECMD_DATA_OVERFLOW;
        }

        add_buffer[address.getWordLength()-1] = 0;
        for (int word = address.getWordLength()-2; word >= 0; word --) {
          if (add_buffer[word] == 0xFFFFFFFF) {
            /* We are going to rollover */
            if (word == 0) {
              printed = "getarray - Address overflow on " + arrayName + " ";
              printed += ecmdWriteTarget(target) + "\n";
              ecmdOutputError( printed.c_str() );
              return ECMD_DATA_OVERFLOW;
            }
            add_buffer[word] = 0;
          } else {
            add_buffer[word] ++;
            /* We took care of the carryover, let's get out of here */
            break;
          }

        }
      } else {
        add_buffer[address.getWordLength()-1] += add_inc;
      }

    }

    printedHeader = false;

    /* Actually go fetch the data */
    rc = getArrayMultiple(target, arrayName.c_str(), entries);
    if (rc == ECMD_TARGET_NOT_CONFIGURED) {
      continue;
    }
    else if (rc) {
      printed = "getarray - Error occured performing getArrayMultiple on ";
      printed += ecmdWriteTarget(target) + "\n";
      ecmdOutputError( printed.c_str() );
      return rc;
    }
    else {
      validPosFound = true;
    }

    for (std::list<ecmdArrayEntry>::iterator entit = entries.begin(); entit != entries.end(); entit ++) {
      if (!printedHeader) {
        printed = ecmdWriteTarget(target) + " " + arrayName + "\n" + entit->address.genHexRightStr() + "\t";
        printedHeader = true;
      } else {
        printed = entit->address.genHexRightStr() + "\t";
      }

      printed += ecmdWriteDataFormatted(entit->buffer, format);

      ecmdOutput( printed.c_str() );
    }

  }

  if (!validPosFound) {
    //this is an error common across all UI functions
    ecmdOutputError("getarray - Unable to find a valid chip to execute command on\n");
    return ECMD_TARGET_NOT_CONFIGURED;
  }

  return rc;
}

int ecmdPutArrayUser(int argc, char * argv[]) {
  int rc = ECMD_SUCCESS;

  ecmdChipTarget target;        ///< Current target
  std::string arrayName;        ///< Name of array to access
  ecmdDataBuffer address;       ///< Buffer to store address
  ecmdDataBuffer buffer;        ///< Buffer to store data to write with
  bool validPosFound = false;   ///< Did we find something to actually execute on ?
  std::string printed;          ///< Print Buffer

  /* get format flag, if it's there */
  std::string format;
  char * formatPtr = ecmdParseOptionWithArgs(&argc, &argv, "-i");
  if (formatPtr == NULL) {
    format = "x";
  }
  else {
    format = formatPtr;
  }

  /************************************************************************/
  /* Parse Common Cmdline Args                                            */
  /************************************************************************/

  rc = ecmdCommandArgs(&argc, &argv);
  if (rc) return rc;

  /************************************************************************/
  /* Parse Local ARGS here!                                               */
  /************************************************************************/
  if (argc < 4) {
    ecmdOutputError("putarray - Too few arguments specified; you need at least a chip, an array, an address, and some data.\n");
    ecmdOutputError("putarray - Type 'putarray -h' for usage.");
    return ECMD_INVALID_ARGS;
  }

  //Setup the target that will be used to query the system config
  target.chipType = argv[0];
  target.chipTypeState = ECMD_TARGET_QUERY_FIELD_VALID;
  target.cageState = target.nodeState = target.slotState = target.posState = target.coreState = ECMD_TARGET_QUERY_WILDCARD;
  target.threadState = ECMD_TARGET_FIELD_UNUSED;

  arrayName = argv[1];

  address.setBitLength(strlen(argv[2]) * 4);
  rc = address.insertFromHexRight(argv[2]);
  if (rc) return rc;

  rc = ecmdReadDataFormatted(buffer, argv[3], format);
  if (rc) {
    ecmdOutputError("putarray - Problems occurred parsing input data, must be an invalid format\n");
    return rc;
  }

  rc = ecmdConfigLooperInit(target, ECMD_SELECTED_TARGETS_LOOP);
  if (rc) return rc;

  while ( ecmdConfigLooperNext(target) ) {

    rc = putArray(target, arrayName.c_str(), address, buffer);

    if (rc == ECMD_TARGET_NOT_CONFIGURED) {
      continue;
    }
    else if (rc) {
        printed = "putarray - Error occured performing putarray on ";
        printed += ecmdWriteTarget(target) + "\n";
        ecmdOutputError( printed.c_str() );
        return rc;
    }
    else {
      validPosFound = true;
    }

  }

  if (!validPosFound) {
    //this is an error common across all UI functions
    ecmdOutputError("putarray - Unable to find a valid chip to execute command on\n");
    return ECMD_TARGET_NOT_CONFIGURED;
  }

  return rc;
}

<|endoftext|>


<commit_before><commit_msg>Updated combat timer mechanic.<commit_after><|endoftext|>