<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    Image4.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
// Software Guide : BeginLatex
//
// Even though \href{http://www.itk.org}{ITK} can be used for performing
// general image processing tasks, the primary purpose of the toolkit is the
// processing of medical image data.  In that perspective, additional
// information about the images is considered mandatory. In particular the
// information associated with the physical spacing between pixels and the
// position of the image in space with respect to some world coordinate
// system are extremely important.
//
// Image origin and spacing are fundamental to many
// applications. Registration, for example, is performed in physical
// coordinates. Improperly defined spacing and origins will result in
// inconsistent results in such processes. Medical images with no spatial
// information should not be used for medical diagnosis, image analysis,
// feature extraction, assisted radiation therapy or image guided surgery. In
// other words, medical images lacking spatial information are not only
// useless but rather hazardous.
//
// \begin{figure} \center
// \includegraphics[width=15cm]{ImageOriginAndSpacing.eps}
// \caption{Geometrical concepts associated with the ITK image.}
// \label{fig:ImageOriginAndSpacing}
// \end{figure}
//
// Figure \ref{fig:ImageOriginAndSpacing} illustrates the main geometrical
// concepts associated with the \doxygen{Image}. In this figure, circles are
// used to represent the center of pixels. The value of the pixel is assumed
// to exist as a Dirac Delta Function located at the pixel center. Pixel
// spacing is measured between the pixel centers and can be different along
// each dimension. The image origin is associated with the coordinates of the
// first pixel in the image. A \emph{Pixel} is considered to be the
// rectangular region surrounding the pixel center holding the data
// value. This can be viewed as the Voronoi region of the image grid, as
// illustrated in the right side of the figure.  Linear interpolation of
// image values is performed inside the Delaunay region whose corners
// are pixel centers.
//
// Software Guide : EndLatex

#include "itkImage.h"
#include "itkPoint.h"

int main()
{
  typedef itk::Image< unsigned short, 3 > ImageType;

  ImageType::Pointer image = ImageType::New();

  ImageType::IndexType start;
  ImageType::SizeType  size;

  size[0]  = 200;  // size along X
  size[1]  = 200;  // size along Y
  size[2]  = 200;  // size along Z

  start[0] =   0;  // first index on X
  start[1] =   0;  // first index on Y
  start[2] =   0;  // first index on Z

  ImageType::RegionType region;
  region.SetSize( size );
  region.SetIndex( start );

  image->SetRegions( region );
  image->Allocate();

  image->FillBuffer( 0 );

  // Software Guide : BeginLatex
  //
  // Image spacing is represented in a \code{C-like} array of \code{double}
  // whose size matches the dimension of the image. In order to manually set
  // the spacing of the image, an array of the corresponding type must be
  // created.  The elements of the array should then be initialized with the
  // spacing between the centers of the adjacent pixels. The following code
  // illustrates the methods available in the image class for dealing with
  // spacing and origin.
  //
  // \index{itk::Image!Spacing}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  double spacing[ ImageType::ImageDimension ];

  spacing[0] = 0.33; // spacing in millimeters along X
  spacing[1] = 0.33; // spacing in millimeters along Y
  spacing[2] = 1.20; // spacing in millimeters along Z
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The array can be assigned to the image using
  // the \code{SetSpacing()} method.
  //
  // \index{itk::Image!SetSpacing()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  image->SetSpacing( spacing );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // The spacing information can be retrieved from an image by using the
  // \code{GetSpacing()} method. This method returns a pointer to a static
  // array of \code{double}. The returned pointer can then be used to read the
  // content of the array. Note the use of the \code{const} keyword to indicate
  // that the array content will not be modified.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const double * sp = image->GetSpacing();

  std::cout << "Spacing = ";
  std::cout << sp[0] << ", " << sp[1] << ", " << sp[2] << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The image origin is managed in a similar way to the spacing.  A
  // \code{C-like} array of \code{double} matching the dimension of the image
  // must be allocated first.  The coordinates of the origin can then be
  // assigned to every component.  These coordinates correspond to the
  // position of the first pixel of the image with respect to an arbitrary
  // reference system in physical space. It is the user's responsibility to
  // make sure that multiple images used in the same application are using a
  // consistent reference system. This is extremly important in image
  // registration applications.
  //
  // The following code illustrates the creation and assignment of a variable
  // suitable for initializing the image origin.
  //
  // \index{itk::Image!origin}
  // \index{itk::Image!SetOrigin()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  double origin[ ImageType::ImageDimension ];

  origin[0] = 0.0;  // coordinates of the
  origin[1] = 0.0;  // first pixel in N-D
  origin[2] = 0.0;

  image->SetOrigin( origin );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The origin can also be retrieved from an image by using the
  //  \code{GetOrigin()} method. This will return a pointer to an internal
  //  array of \code{doubles}. The pointer can be used to read the content of
  //  the array. Note again the use of the \code{const} keyword to indicate
  //  that the array content will not be modified.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const double * orgn = image->GetOrigin();

  std::cout << "Origin = ";
  std::cout << orgn[0] << ", " << orgn[1] << ", " << orgn[2] << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Once the spacing and origin of the image have been initialized the image
  // will correctly map pixel indices to and from physical space
  // coordinates. The following code illustrates how a point in physical
  // space can be mapped into an image index for the purpose of reading the
  // content of the closest pixel.
  //
  // First, a \doxygen{Point} type must be declared. The point type is
  // templated over the type used to represent coordinates and over the
  // dimension of the space. In this particular case, the dimension of the
  // point must match the dimension of the image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::Point< double, ImageType::ImageDimension > PointType;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // An \doxygen{Point}, like an \doxygen{Index}, is a relatively small and
  // simple object.  for this reason it is not reference counted like the
  // large data objects in ITK---as a consequence it is not manipulated
  // with \doxygen{SmartPointer}s.  Point objects are simply declared as
  // instances of any other C++ class.  Once the point is declared, its
  // components can be accessed using traditional array notation. In
  // particular the \code{[]} operator is available. For efficiency reasons,
  // no bounds checking is performed on the index used to access a particular
  // point component. It is the user's responsibility to make sure that the
  // index is in the range $\{0,Dimension-1\}$
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  PointType point;

  point[0] = 1.45;    // x coordinate
  point[1] = 7.21;    // y coordinate
  point[2] = 9.28;    // z coordinate
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The image will map the point to an index using the values of the
  // current spacing and origin. An index object must be provided to
  // receive the results of the mapping. The index object can be
  // instantiated by using the \code{IndexType} defined in the Image
  // type.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  ImageType::IndexType pixelIndex;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \code{TransformPhysicalPointToIndex()} method of the image class
  // will compute the pixel index closest to the point provided. The method
  // checks for this index to be contained inside the current buffered pixel
  // data. The method returns a boolean indicating whether the resulting
  // index falls inside the buffered region or not. The output index should
  // not be used when the returned value of the method is \code{false}.
  //
  // The following lines illustrate the point to index mapping and the
  // subsequent use of the pixel index for accessing pixel data from the
  // image.
  //
  // \index{itk::Image!TransformPhysicalPointToIndex()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  bool isInside = image->TransformPhysicalPointToIndex( point, pixelIndex );

  if ( isInside )
    {
    ImageType::PixelType pixelValue = image->GetPixel( pixelIndex );

    pixelValue += 5;

    image->SetPixel( pixelValue );
    }
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Remember that \code{GetPixel()} and \code{SetPixel()} are very
  // inefficient methods for accessing pixel data. Image iterators should be
  // used when massive access to pixel data is required.
  //
  // Software Guide : EndLatex

  return 0;
}

<commit_msg>BUG: SetPixel() needs two arguments.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    Image4.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
// Software Guide : BeginLatex
//
// Even though \href{http://www.itk.org}{ITK} can be used for performing
// general image processing tasks, the primary purpose of the toolkit is the
// processing of medical image data.  In that perspective, additional
// information about the images is considered mandatory. In particular the
// information associated with the physical spacing between pixels and the
// position of the image in space with respect to some world coordinate
// system are extremely important.
//
// Image origin and spacing are fundamental to many
// applications. Registration, for example, is performed in physical
// coordinates. Improperly defined spacing and origins will result in
// inconsistent results in such processes. Medical images with no spatial
// information should not be used for medical diagnosis, image analysis,
// feature extraction, assisted radiation therapy or image guided surgery. In
// other words, medical images lacking spatial information are not only
// useless but rather hazardous.
//
// \begin{figure} \center
// \includegraphics[width=15cm]{ImageOriginAndSpacing.eps}
// \caption{Geometrical concepts associated with the ITK image.}
// \label{fig:ImageOriginAndSpacing}
// \end{figure}
//
// Figure \ref{fig:ImageOriginAndSpacing} illustrates the main geometrical
// concepts associated with the \doxygen{Image}. In this figure, circles are
// used to represent the center of pixels. The value of the pixel is assumed
// to exist as a Dirac Delta Function located at the pixel center. Pixel
// spacing is measured between the pixel centers and can be different along
// each dimension. The image origin is associated with the coordinates of the
// first pixel in the image. A \emph{Pixel} is considered to be the
// rectangular region surrounding the pixel center holding the data
// value. This can be viewed as the Voronoi region of the image grid, as
// illustrated in the right side of the figure.  Linear interpolation of
// image values is performed inside the Delaunay region whose corners
// are pixel centers.
//
// Software Guide : EndLatex

#include "itkImage.h"
#include "itkPoint.h"

int main()
{
  typedef itk::Image< unsigned short, 3 > ImageType;

  ImageType::Pointer image = ImageType::New();

  ImageType::IndexType start;
  ImageType::SizeType  size;

  size[0]  = 200;  // size along X
  size[1]  = 200;  // size along Y
  size[2]  = 200;  // size along Z

  start[0] =   0;  // first index on X
  start[1] =   0;  // first index on Y
  start[2] =   0;  // first index on Z

  ImageType::RegionType region;
  region.SetSize( size );
  region.SetIndex( start );

  image->SetRegions( region );
  image->Allocate();

  image->FillBuffer( 0 );

  // Software Guide : BeginLatex
  //
  // Image spacing is represented in a \code{C-like} array of \code{double}
  // whose size matches the dimension of the image. In order to manually set
  // the spacing of the image, an array of the corresponding type must be
  // created.  The elements of the array should then be initialized with the
  // spacing between the centers of the adjacent pixels. The following code
  // illustrates the methods available in the image class for dealing with
  // spacing and origin.
  //
  // \index{itk::Image!Spacing}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  double spacing[ ImageType::ImageDimension ];

  spacing[0] = 0.33; // spacing in millimeters along X
  spacing[1] = 0.33; // spacing in millimeters along Y
  spacing[2] = 1.20; // spacing in millimeters along Z
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The array can be assigned to the image using
  // the \code{SetSpacing()} method.
  //
  // \index{itk::Image!SetSpacing()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  image->SetSpacing( spacing );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // The spacing information can be retrieved from an image by using the
  // \code{GetSpacing()} method. This method returns a pointer to a static
  // array of \code{double}. The returned pointer can then be used to read the
  // content of the array. Note the use of the \code{const} keyword to indicate
  // that the array content will not be modified.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const double * sp = image->GetSpacing();

  std::cout << "Spacing = ";
  std::cout << sp[0] << ", " << sp[1] << ", " << sp[2] << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The image origin is managed in a similar way to the spacing.  A
  // \code{C-like} array of \code{double} matching the dimension of the image
  // must be allocated first.  The coordinates of the origin can then be
  // assigned to every component.  These coordinates correspond to the
  // position of the first pixel of the image with respect to an arbitrary
  // reference system in physical space. It is the user's responsibility to
  // make sure that multiple images used in the same application are using a
  // consistent reference system. This is extremly important in image
  // registration applications.
  //
  // The following code illustrates the creation and assignment of a variable
  // suitable for initializing the image origin.
  //
  // \index{itk::Image!origin}
  // \index{itk::Image!SetOrigin()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  double origin[ ImageType::ImageDimension ];

  origin[0] = 0.0;  // coordinates of the
  origin[1] = 0.0;  // first pixel in N-D
  origin[2] = 0.0;

  image->SetOrigin( origin );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The origin can also be retrieved from an image by using the
  //  \code{GetOrigin()} method. This will return a pointer to an internal
  //  array of \code{doubles}. The pointer can be used to read the content of
  //  the array. Note again the use of the \code{const} keyword to indicate
  //  that the array content will not be modified.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const double * orgn = image->GetOrigin();

  std::cout << "Origin = ";
  std::cout << orgn[0] << ", " << orgn[1] << ", " << orgn[2] << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Once the spacing and origin of the image have been initialized the image
  // will correctly map pixel indices to and from physical space
  // coordinates. The following code illustrates how a point in physical
  // space can be mapped into an image index for the purpose of reading the
  // content of the closest pixel.
  //
  // First, a \doxygen{Point} type must be declared. The point type is
  // templated over the type used to represent coordinates and over the
  // dimension of the space. In this particular case, the dimension of the
  // point must match the dimension of the image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::Point< double, ImageType::ImageDimension > PointType;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // An \doxygen{Point}, like an \doxygen{Index}, is a relatively small and
  // simple object.  for this reason it is not reference counted like the
  // large data objects in ITK---as a consequence it is not manipulated
  // with \doxygen{SmartPointer}s.  Point objects are simply declared as
  // instances of any other C++ class.  Once the point is declared, its
  // components can be accessed using traditional array notation. In
  // particular the \code{[]} operator is available. For efficiency reasons,
  // no bounds checking is performed on the index used to access a particular
  // point component. It is the user's responsibility to make sure that the
  // index is in the range $\{0,Dimension-1\}$
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  PointType point;

  point[0] = 1.45;    // x coordinate
  point[1] = 7.21;    // y coordinate
  point[2] = 9.28;    // z coordinate
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The image will map the point to an index using the values of the
  // current spacing and origin. An index object must be provided to
  // receive the results of the mapping. The index object can be
  // instantiated by using the \code{IndexType} defined in the Image
  // type.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  ImageType::IndexType pixelIndex;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \code{TransformPhysicalPointToIndex()} method of the image class
  // will compute the pixel index closest to the point provided. The method
  // checks for this index to be contained inside the current buffered pixel
  // data. The method returns a boolean indicating whether the resulting
  // index falls inside the buffered region or not. The output index should
  // not be used when the returned value of the method is \code{false}.
  //
  // The following lines illustrate the point to index mapping and the
  // subsequent use of the pixel index for accessing pixel data from the
  // image.
  //
  // \index{itk::Image!TransformPhysicalPointToIndex()}
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  bool isInside = image->TransformPhysicalPointToIndex( point, pixelIndex );

  if ( isInside )
    {
    ImageType::PixelType pixelValue = image->GetPixel( pixelIndex );

    pixelValue += 5;

    image->SetPixel( pixelIndex, pixelValue );
    }
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Remember that \code{GetPixel()} and \code{SetPixel()} are very
  // inefficient methods for accessing pixel data. Image iterators should be
  // used when massive access to pixel data is required.
  //
  // Software Guide : EndLatex

  return 0;
}

<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

//---------------------------------------------------------------------
//
//  This test program is used, in conjunction with a set of test data files,
//  to verify support for different character encodings in XML.
//
//---------------------------------------------------------------------

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLException.hpp>

#include <xercesc/sax/SAXException.hpp>
#include <xercesc/sax/ErrorHandler.hpp>
#include <xercesc/sax/SAXParseException.hpp>

#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOM.hpp>
#include <stdio.h>

static int gTestsFailed = 0;
static int gTestsRun    = 0;
static XercesDOMParser* parser = 0;

//-----------------------------------------------------------------------
//
//  ErrorHandler.   The DOM Parser will report any parsing errors by means
//                  of call-backs to the methods of this class.
//                  This is just necessary boilerplate, as far as this
//                  program is concerned.
//
//-----------------------------------------------------------------------

class  ParseErrorHandler: public ErrorHandler
{
public:
    void warning(const SAXParseException& e);
    void error(const SAXParseException& e);
    void fatalError(const SAXParseException& e);
    void resetErrors() {};

};

void ParseErrorHandler::error(const SAXParseException& e)
{
    fprintf(stderr, "\nError at file \"%s\", line %d, char %d:  %s\n",
        XMLString::transcode(e.getSystemId()), e.getLineNumber(),
        e.getColumnNumber(), XMLString::transcode(e.getMessage()));
    throw e;

};

void ParseErrorHandler::fatalError(const SAXParseException& e)
{
    fprintf(stderr, "\nFatal Error at file \"%s\", line %d, char %d:  %s\n",
        XMLString::transcode(e.getSystemId()), e.getLineNumber(),
        e.getColumnNumber(), XMLString::transcode(e.getMessage()));
    throw e;
};

void ParseErrorHandler::warning(const SAXParseException& e)
{
    fprintf(stderr, "\nWarning at file \"%s\", line %d, char %d:  %s\n",
        XMLString::transcode(e.getSystemId()), e.getLineNumber(),
        e.getColumnNumber(), XMLString::transcode(e.getMessage()));
    throw e;

};

//------------------------------------------------------------------------
//
//   parseFile  - a simpler to use function for just parsing an XML file
//                and getting the DOM Document back.
//
//------------------------------------------------------------------------
static DOMDocument* parseFile(char *fileName)
{
    ParseErrorHandler eh;
    parser = new XercesDOMParser;
    parser->setDoValidation(false);
    parser->setErrorHandler(&eh);
    try
    {
        parser->parse(fileName);
    }

    catch (const XMLException& e )
    {
		fprintf(stderr, "Exception Occurred \"%s\".  \n",
			XMLString::transcode(e.getMessage()));
		fprintf(stderr, "File being parsed is \"%s\".\n", fileName);
        return 0;  // A null document.
    }

	catch (...)
	{
		fprintf(stderr, "Unexpected Exception thrown during parse of file \"%s\".\n",
		                 fileName);
		return 0;
	}
    return parser->getDocument();
}

//------------------------------------------------------------------------
//
//  writeUData - Write out a udata xml element for a XMLCh* contents.
//
//------------------------------------------------------------------------
static void writeUData(const XMLCh* s)
{
    unsigned int i;
    printf("<udata>\n");
    size_t len = XMLString::stringLen(s);
    for (i=0; i<len; i++)
    {
        if (i % 16 == 0)
            printf("\n");
        XMLCh c = s[i];
        printf("%4x ", c);
    }
    printf("\n</udata>\n");
};

//------------------------------------------------------------------------
//
//  eatWhiteSpace -  XMLCh*s are kind of short on utility functions :-(
//
//------------------------------------------------------------------------
static void eatWhiteSpace(XMLCh* s, unsigned int &i)
{
    while (i < XMLString::stringLen(s))
    {
    XMLCh c = s[i];
    if (!(c == 0x20 ||           // These are the official XML space characters,
        c == 0x09 ||             //   expressed as Unicode constants.
        c == 0x0A))
        break;
    i++;
    }
}

//------------------------------------------------------------------------
//
//   convertHexValue     if the XMLCh* contains a hex number at position i,
//                       convert it and return it, and update i to index the
//                       first char not in the string.
//                       return 0 if string[i] didn't have a hex digit.
//                       0 return is ambiguous, but it doesn't matter for XML,
//                       where 0 is not a valid character.
//
//------------------------------------------------------------------------
static int convertHexValue(XMLCh* s, unsigned int &i)
{
    int value = 0;

                                   // For reference, the digits  0-9 are Unicode 0x30-39
                                   //                the letters A-F are Unicode 0x41-0x46
                                   //                the letters a-f are Unicode 0x61-66
                                   // We can't use character literals - we might be
                                   //  building on an EBCDIC machine.
    while (i < XMLString::stringLen(s))
    {
        XMLCh c = s[i];
        if (c >= 0x61 && c <= 0x66)     // Uppercase a-f to A-F.
            c -= 0x20;

        if (c < 0x30 || c >0x46)        // Stop if not a hex digit
            break;
        if (c > 0x39 && c <0x41)
            break;

        value = value << 4;             // Append this digit to accumulating value
        if (c <= 0x39)
            value += c-0x30;
        else
            value += 0xA + c - 0x41;

        i++;
    }
    return value;
}

//------------------------------------------------------------------------
//
//  processTestFile   Given the file name of an encoding test xml file,
//                    run it.
//
//------------------------------------------------------------------------
static bool  processTestFile(const XMLCh* fileName)
{
    //
    //  Send the input file through the parse, create a DOM document for it.
    //
    char *cFileName = XMLString::transcode(fileName);
    DOMDocument* testDoc = parseFile(cFileName);
    if (testDoc == 0)
        return false;    // parse errors in the source xml.

    //
    //  Pull the "data" element out of the document.
    //
    XMLCh tempStr[4000];
    XMLString::transcode("data", tempStr, 3999);
    DOMNodeList* nl = testDoc->getElementsByTagName(tempStr);
    if (nl->getLength() != 1) {
        fprintf(stderr, "Test file \"%s\" must have exactly one \"data\" element.\n", cFileName);
        return false;
    };
    DOMNode* tmpNode = nl->item(0);
    DOMElement* data = (DOMElement*) tmpNode;

    //
    //  Build up a string containing the character data contents of the data element.
    //
    DOMNode* child;
    XMLBuffer elData;
    for (child=data->getFirstChild(); child != 0; child= child->getNextSibling())
    {
		if (child->getNodeType() == DOMNode::COMMENT_NODE)
			continue;
        if (! (child->getNodeType() == DOMNode::TEXT_NODE ||
               child->getNodeType() == DOMNode::CDATA_SECTION_NODE ||
               child->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE))
        {
               fprintf(stderr, "Test file \"%s\": data element contains unexpected children.",
                    cFileName);
               return false;
        }
        elData.append(((DOMCharacterData *)child)->getData());
    };

    //
    //  Pull the "udata" element out of the document
    //
    XMLString::transcode("udata", tempStr, 3999);
    nl = testDoc->getElementsByTagName(tempStr);
    if (nl->getLength() != 1) {
        fprintf(stderr, "Test file \"%s\" must have exactly one \"udata\" element.\n", cFileName);
        return false;
    };
    DOMNode* tmpNode1 = nl->item(0);
    DOMElement* udata = (DOMElement*) tmpNode1;

    //
    //  Build up a string containing the character data contents of the udata element.
    //  This will consist of a whole bunch hex numbers, still in string from
    //

    XMLBuffer rawUData;
    for (child=udata->getFirstChild(); child != 0; child= child->getNextSibling())
    {
        if (child->getNodeType() == DOMNode::COMMENT_NODE)
            continue;
        if (! (child->getNodeType() == DOMNode::TEXT_NODE ||
            child->getNodeType() == DOMNode::CDATA_SECTION_NODE ||
            child->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE))
        {
            fprintf(stderr, "Test file \"%s\": udata element contains unexpected children.",
                cFileName);
            return false;
        }
        rawUData.append(((DOMCharacterData *)child)->getData());
    };

    //
    // Convert the raw (hex numbers)  form of the udata to the corresponding string.
    //
    XMLBuffer uData;
    unsigned int rawIndex = 0;

    while (rawIndex < rawUData.getLen())
    {
        eatWhiteSpace(rawUData.getRawBuffer(), rawIndex);
        XMLCh c = convertHexValue(rawUData.getRawBuffer(), rawIndex);
        if (c > 0)
            uData.append(c);
        else
            if (rawIndex < rawUData.getLen())
            {
                fprintf(stderr, "Test file \"%s\": Bad hex number in udata element.  "
                    "Data character number %d\n", cFileName, uData.getLen());
                return false;
            }
    }

    //
    // Compare the two strings.
    //
    unsigned int i;
    for (i=0; i< elData.getLen(); i++)
    {
        XMLCh* elDataRaw = elData.getRawBuffer();
        XMLCh* uDataRaw = uData.getRawBuffer();
        if (i >= uData.getLen())
        {
            fprintf(stderr, "Test file \"%s\": udata element shorter than data at char number %d\n",
                cFileName, i);
            writeUData(elDataRaw);
            return false;
        }
        if (uDataRaw[i] != elDataRaw[i])
        {
            fprintf(stderr, "Test file \"%s\": comparison failure at character number %d\n",
                cFileName, i);
            writeUData(elDataRaw);
            return false;
        };
    }

    if (elData.getLen() != uData.getLen())
    {
        fprintf(stderr, "Test file \"%s\": udata element longer than data at char number %d\n",
            cFileName, i);
        writeUData(elData.getRawBuffer());
        return false;
    }

    delete [] cFileName;

    return true;
}

int main(int argc, char ** argv) {

   //
    // Initialize the Xerces-c environment
    //
	try
    {
        XMLPlatformUtils::Initialize();
    }

    catch (const XMLException& toCatch)
    {
        fprintf(stderr, "Error during initialization of xerces-c: %s\n",
            XMLString::transcode(toCatch.getMessage()));
         return 1;
    }

    //
    // Parse the command line, which should specify exactly one file, which is an
    //   xml file containing the list of test files to be processed.
    //
    if (argc != 2) {
        printf("usage: %s file_name \n"
               "   where file name is the xml file specifying the list of test files.", argv[0]);
        return 1;
    }
    DOMDocument* fileListDoc = parseFile(argv[1]);
    if (fileListDoc == 0) return 1;

    //
    // Iterate over the list of files, running each as a test.
    //
    XMLCh tempStr[4000];
    XMLString::transcode("testFile", tempStr, 3999);
    DOMNodeList* list = fileListDoc->getElementsByTagName(tempStr);
    int i;
    int numFiles = list->getLength();
    for (i=0; i<numFiles; i++)
    {
        ++gTestsRun;
        DOMNode* tmpNode3 = list->item(i);
        XMLString::transcode("name", tempStr, 3999);
        const XMLCh* fileName = ((DOMElement*) tmpNode3)->getAttribute(tempStr);
        if (processTestFile(fileName) == false)
            ++gTestsFailed;
    };

    //
    // We are done.  Print out a summary of the results
    //
    printf("Encoding Tests Results Summary: \n"
           "   %d encoding tests run.\n"
           "   %d tests passed,\n"
           "   %d tests failed\n", gTestsRun, gTestsRun-gTestsFailed, gTestsFailed);

   return 0;
};
<commit_msg>Clear memory leak in EncodingTest.cpp<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

//---------------------------------------------------------------------
//
//  This test program is used, in conjunction with a set of test data files,
//  to verify support for different character encodings in XML.
//
//---------------------------------------------------------------------

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLException.hpp>

#include <xercesc/sax/SAXException.hpp>
#include <xercesc/sax/ErrorHandler.hpp>
#include <xercesc/sax/SAXParseException.hpp>

#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOM.hpp>
#include <stdio.h>

static int gTestsFailed = 0;
static int gTestsRun    = 0;
static XercesDOMParser* parser = 0;

//-----------------------------------------------------------------------
//
//  ErrorHandler.   The DOM Parser will report any parsing errors by means
//                  of call-backs to the methods of this class.
//                  This is just necessary boilerplate, as far as this
//                  program is concerned.
//
//-----------------------------------------------------------------------

class  ParseErrorHandler: public ErrorHandler
{
public:
    void warning(const SAXParseException& e);
    void error(const SAXParseException& e);
    void fatalError(const SAXParseException& e);
    void resetErrors() {};

};

void ParseErrorHandler::error(const SAXParseException& e)
{
    char* systemId = XMLString::transcode(e.getSystemId());
    char* message = XMLString::transcode(e.getMessage());

    fprintf(stderr, "\nError at file \"%s\", line %d, char %d:  %s\n",
        systemId, e.getLineNumber(),
        e.getColumnNumber(), message);

    delete [] systemId;
    delete [] message;
    throw e;

};

void ParseErrorHandler::fatalError(const SAXParseException& e)
{
    char* systemId = XMLString::transcode(e.getSystemId());
    char* message = XMLString::transcode(e.getMessage());

    fprintf(stderr, "\nFatal Error at file \"%s\", line %d, char %d:  %s\n",
        systemId, e.getLineNumber(),
        e.getColumnNumber(), message);

    delete [] systemId;
    delete [] message;
    throw e;
};

void ParseErrorHandler::warning(const SAXParseException& e)
{
    char* systemId = XMLString::transcode(e.getSystemId());
    char* message = XMLString::transcode(e.getMessage());

    fprintf(stderr, "\nWarning at file \"%s\", line %d, char %d:  %s\n",
        systemId, e.getLineNumber(),
        e.getColumnNumber(), message);

    delete [] systemId;
    delete [] message;
    throw e;

};

//------------------------------------------------------------------------
//
//   parseFile  - a simpler to use function for just parsing an XML file
//                and getting the DOM Document back.
//
//------------------------------------------------------------------------
static DOMDocument* parseFile(char *fileName)
{
    ParseErrorHandler eh;
    if (!parser)
        parser = new XercesDOMParser;
    parser->setDoValidation(false);
    parser->setErrorHandler(&eh);
    try
    {
        parser->parse(fileName);
    }

    catch (const XMLException& e )
    {
		fprintf(stderr, "Exception Occurred \"%s\".  \n",
			XMLString::transcode(e.getMessage()));
		fprintf(stderr, "File being parsed is \"%s\".\n", fileName);
        return 0;  // A null document.
    }

	catch (...)
	{
		fprintf(stderr, "Unexpected Exception thrown during parse of file \"%s\".\n",
		                 fileName);
		return 0;
	}
    return parser->getDocument();
}

//------------------------------------------------------------------------
//
//  writeUData - Write out a udata xml element for a XMLCh* contents.
//
//------------------------------------------------------------------------
static void writeUData(const XMLCh* s)
{
    unsigned int i;
    printf("<udata>\n");
    size_t len = XMLString::stringLen(s);
    for (i=0; i<len; i++)
    {
        if (i % 16 == 0)
            printf("\n");
        XMLCh c = s[i];
        printf("%4x ", c);
    }
    printf("\n</udata>\n");
};

//------------------------------------------------------------------------
//
//  eatWhiteSpace -  XMLCh*s are kind of short on utility functions :-(
//
//------------------------------------------------------------------------
static void eatWhiteSpace(XMLCh* s, unsigned int &i)
{
    while (i < XMLString::stringLen(s))
    {
    XMLCh c = s[i];
    if (!(c == 0x20 ||           // These are the official XML space characters,
        c == 0x09 ||             //   expressed as Unicode constants.
        c == 0x0A))
        break;
    i++;
    }
}

//------------------------------------------------------------------------
//
//   convertHexValue     if the XMLCh* contains a hex number at position i,
//                       convert it and return it, and update i to index the
//                       first char not in the string.
//                       return 0 if string[i] didn't have a hex digit.
//                       0 return is ambiguous, but it doesn't matter for XML,
//                       where 0 is not a valid character.
//
//------------------------------------------------------------------------
static int convertHexValue(XMLCh* s, unsigned int &i)
{
    int value = 0;

                                   // For reference, the digits  0-9 are Unicode 0x30-39
                                   //                the letters A-F are Unicode 0x41-0x46
                                   //                the letters a-f are Unicode 0x61-66
                                   // We can't use character literals - we might be
                                   //  building on an EBCDIC machine.
    while (i < XMLString::stringLen(s))
    {
        XMLCh c = s[i];
        if (c >= 0x61 && c <= 0x66)     // Uppercase a-f to A-F.
            c -= 0x20;

        if (c < 0x30 || c >0x46)        // Stop if not a hex digit
            break;
        if (c > 0x39 && c <0x41)
            break;

        value = value << 4;             // Append this digit to accumulating value
        if (c <= 0x39)
            value += c-0x30;
        else
            value += 0xA + c - 0x41;

        i++;
    }
    return value;
}

//------------------------------------------------------------------------
//
//  processTestFile   Given the file name of an encoding test xml file,
//                    run it.
//
//------------------------------------------------------------------------
static bool  processTestFile(const XMLCh* fileName)
{
    //
    //  Send the input file through the parse, create a DOM document for it.
    //
    char cFileName[4000];
    XMLString::transcode(fileName, cFileName, 3999);
    DOMDocument* testDoc = parseFile(cFileName);
    if (testDoc == 0)
        return false;    // parse errors in the source xml.

    //
    //  Pull the "data" element out of the document.
    //
    XMLCh tempStr[4000];
    XMLString::transcode("data", tempStr, 3999);
    DOMNodeList* nl = testDoc->getElementsByTagName(tempStr);
    if (nl->getLength() != 1) {
        fprintf(stderr, "Test file \"%s\" must have exactly one \"data\" element.\n", cFileName);
        return false;
    };
    DOMNode* tmpNode = nl->item(0);
    DOMElement* data = (DOMElement*) tmpNode;

    //
    //  Build up a string containing the character data contents of the data element.
    //
    DOMNode* child;
    XMLBuffer elData;
    for (child=data->getFirstChild(); child != 0; child= child->getNextSibling())
    {
		if (child->getNodeType() == DOMNode::COMMENT_NODE)
			continue;
        if (! (child->getNodeType() == DOMNode::TEXT_NODE ||
               child->getNodeType() == DOMNode::CDATA_SECTION_NODE ||
               child->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE))
        {
               fprintf(stderr, "Test file \"%s\": data element contains unexpected children.",
                    cFileName);
               return false;
        }
        elData.append(((DOMCharacterData *)child)->getData());
    };

    //
    //  Pull the "udata" element out of the document
    //
    XMLString::transcode("udata", tempStr, 3999);
    nl = testDoc->getElementsByTagName(tempStr);
    if (nl->getLength() != 1) {
        fprintf(stderr, "Test file \"%s\" must have exactly one \"udata\" element.\n", cFileName);
        return false;
    };
    DOMNode* tmpNode1 = nl->item(0);
    DOMElement* udata = (DOMElement*) tmpNode1;

    //
    //  Build up a string containing the character data contents of the udata element.
    //  This will consist of a whole bunch hex numbers, still in string from
    //

    XMLBuffer rawUData;
    for (child=udata->getFirstChild(); child != 0; child= child->getNextSibling())
    {
        if (child->getNodeType() == DOMNode::COMMENT_NODE)
            continue;
        if (! (child->getNodeType() == DOMNode::TEXT_NODE ||
            child->getNodeType() == DOMNode::CDATA_SECTION_NODE ||
            child->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE))
        {
            fprintf(stderr, "Test file \"%s\": udata element contains unexpected children.",
                cFileName);
            return false;
        }
        rawUData.append(((DOMCharacterData *)child)->getData());
    };

    //
    // Convert the raw (hex numbers)  form of the udata to the corresponding string.
    //
    XMLBuffer uData;
    unsigned int rawIndex = 0;

    while (rawIndex < rawUData.getLen())
    {
        eatWhiteSpace(rawUData.getRawBuffer(), rawIndex);
        XMLCh c = convertHexValue(rawUData.getRawBuffer(), rawIndex);
        if (c > 0)
            uData.append(c);
        else
            if (rawIndex < rawUData.getLen())
            {
                fprintf(stderr, "Test file \"%s\": Bad hex number in udata element.  "
                    "Data character number %d\n", cFileName, uData.getLen());
                return false;
            }
    }

    //
    // Compare the two strings.
    //
    unsigned int i;
    for (i=0; i< elData.getLen(); i++)
    {
        XMLCh* elDataRaw = elData.getRawBuffer();
        XMLCh* uDataRaw = uData.getRawBuffer();
        if (i >= uData.getLen())
        {
            fprintf(stderr, "Test file \"%s\": udata element shorter than data at char number %d\n",
                cFileName, i);
            writeUData(elDataRaw);
            return false;
        }
        if (uDataRaw[i] != elDataRaw[i])
        {
            fprintf(stderr, "Test file \"%s\": comparison failure at character number %d\n",
                cFileName, i);
            writeUData(elDataRaw);
            return false;
        };
    }

    if (elData.getLen() != uData.getLen())
    {
        fprintf(stderr, "Test file \"%s\": udata element longer than data at char number %d\n",
            cFileName, i);
        writeUData(elData.getRawBuffer());
        return false;
    }

    return true;
}

int main(int argc, char ** argv) {

   //
    // Initialize the Xerces-c environment
    //
	try
    {
        XMLPlatformUtils::Initialize();
    }

    catch (const XMLException& toCatch)
    {
        fprintf(stderr, "Error during initialization of xerces-c: %s\n",
            XMLString::transcode(toCatch.getMessage()));
         return 1;
    }

    //
    // Parse the command line, which should specify exactly one file, which is an
    //   xml file containing the list of test files to be processed.
    //
    if (argc != 2) {
        printf("usage: %s file_name \n"
               "   where file name is the xml file specifying the list of test files.", argv[0]);
        return 1;
    }
    DOMDocument* fileListDoc = parseFile(argv[1]);
    if (fileListDoc == 0) return 1;

    //
    // Iterate over the list of files, running each as a test.
    //
    XMLCh tempStr[4000];
    XMLString::transcode("testFile", tempStr, 3999);
    DOMNodeList* list = fileListDoc->getElementsByTagName(tempStr);
    int i;
    int numFiles = list->getLength();
    for (i=0; i<numFiles; i++)
    {
        ++gTestsRun;
        DOMNode* tmpNode3 = list->item(i);
        XMLString::transcode("name", tempStr, 3999);
        const XMLCh* fileName = ((DOMElement*) tmpNode3)->getAttribute(tempStr);
        if (processTestFile(fileName) == false)
            ++gTestsFailed;
    };

    //
    // We are done.  Print out a summary of the results
    //
    printf("Encoding Tests Results Summary: \n"
           "   %d encoding tests run.\n"
           "   %d tests passed,\n"
           "   %d tests failed\n", gTestsRun, gTestsRun-gTestsFailed, gTestsFailed);

    delete parser;
    parser = 0;
   return 0;
};
<|endoftext|>


<commit_before>#include "Exceptions.h"
#include "ToolBase.h"
#include "Helper.h"
#include "NGSHelper.h"
#include "FastqFileStream.h"
#include "BedFile.h"
#include "Settings.h"
#include "FastaFileIndex.h"
#include <chrono>

#include "api/BamReader.h"
using namespace BamTools;

class ConcreteTool
		: public ToolBase
{
	Q_OBJECT

public:
	ConcreteTool(int& argc, char *argv[])
		: ToolBase(argc, argv)
	{
	}

	virtual void setup()
	{
		setDescription("Paired-end read simulator for Illumina reads.");
		addInfile("roi", "Target region BED file (the corresponding reference genome is taken from the settings.ini file).", false);
		addInt("count", "Number of read pairs to generate.", false);
		addOutfile("out1", "Forward reads output file in .FASTQ.GZ format.", false);
		addOutfile("out2", "Reverse reads output file in .FASTQ.GZ format.", false);
		//optional
		addInt("length", "Read length for forward/reverse reads.", true, 100);
		addInt("ins_mean", "Library insert size mean value.", true, 200);
		addInt("ins_stdev", "Library insert size mean standard deviation.", true, 70);
		addFloat("error", "Base error probability (uniform distribution).", true, 0.01);
		addString("a1", "Forward read sequencing adapter sequence (for read-through).", true, "AGATCGGAAGAGCACACGTCTGAACTCCAGTCACGAGTTA");
		addString("a2", "Reverse read sequencing adapter sequence (for read-through).", true, "AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGTAGATCTC");
		addInfile("ref", "Reference genome FASTA file. If unset 'reference_genome' from the 'settings.ini' file is used.", true, false);
		addFlag("v", "Enable verbose debug output.");
	}

	int addNoise(QByteArray& sequence, double error_probabilty, std::mt19937& gen)
	{
		int ec = 0;

		//uniform distribution
		std::uniform_real_distribution<double> error_dist(0, 1);

		//bases vector
		QByteArray bases = "ACGT";
		for(int i=0; i<sequence.length(); ++i)
		{
			//base error?
			bool error = error_dist(gen) < error_probabilty;

			//replace base at random
			if (error)
			{
				do
				{
					std::random_shuffle(bases.begin(), bases.end());
				}
				while (sequence[i]==bases[0]);
				sequence[i] = bases[0];

				++ec;
			}
		}

		return ec;
	}

	virtual void main()
	{
		//init
		QTextStream out(stdout);
		FastqOutfileStream out1(getOutfile("out1"), false);
		FastqOutfileStream out2(getOutfile("out2"), false);
		BedFile roi;
		roi.load(getInfile("roi"));
		long count = getInt("count");
		int length = getInt("length");
		int ins_mean = getInt("ins_mean");
		int ins_stdev = getInt("ins_stdev");
		QString a1 = getString("a1");
		QString a2 = getString("a2");
		bool verbose = getFlag("v");
		double error = getFloat("error");

		//set qualities
		QByteArray qualities = "AAAAAFFFFFFFGGGGGGFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
		qualities = qualities.left(length);

		//open refererence genome file
		QString ref_file = getInfile("ref");
		if (ref_file=="") ref_file = Settings::string("reference_genome");
		FastaFileIndex reference(ref_file);

		//normal distribution for insert size
		unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
		std::mt19937 gen(seed);
		std::normal_distribution<> insert_dist(ins_mean, ins_stdev);

		//determine overall ROI size
		roi.merge();
		double overall_bases = roi.baseCount();

		//simulate reads (for each target region)
		for (int r=0; r<roi.count(); ++r)
		{
			const BedLine& reg = roi[r];
			const Chromosome& chr = reg.chr();

			//determine how many reads to generate for this region
			long r_count = std::round((double)count * reg.length() / overall_bases);
			out << "Region: " << chr.str() << ":" << reg.start() << "-" << reg.end() << " length=" << reg.length() << " reads=" << r_count << endl;
			for (long i=0; i<r_count; ++i)
			{
				//determine insert size
				int is = std::max((int)insert_dist(gen), 0);

				//determine start and end position (the read should overlap with the region)
				std::uniform_int_distribution<int> start_dist(reg.start()-is/2, reg.end()-is/2);
				int start = start_dist(gen);
				int end = start + is;
				if (start<0) start=0;
				if (end>reference.lengthOf(chr)) end = reference.lengthOf(chr);

				//get insert sequence;
				Sequence seq = reference.seq(chr, start, end-start);
				if (verbose) out << "  Insert: " << chr.str() << ":" << start << "-" << (end-1) << " length=" << seq.length() << endl;

				//get read seqence
				FastqEntry r1;
				FastqEntry r2;
				r1.bases = seq.left(length);
				r2.bases = seq.right(length);
				r2.bases = NGSHelper::changeSeq(r2.bases, true, true);

				//append sequencing adapers (if too short)
				int a_length = length - r1.bases.length();
				if (a_length>0)
				{
					r1.bases.append(a1.left(a_length));
					r2.bases.append(a2.left(a_length));
				}

				//append random sequence (if still too short)
				int r_length = length - r1.bases.length();
				r1.bases.append(Helper::randomString(r_length, "ACGT"));
				r2.bases.append(Helper::randomString(r_length, "ACGT"));

				//add noise
				int ec1 = addNoise(r1.bases, error, gen);
				int ec2 = addNoise(r2.bases, error, gen);
				if (verbose) out << "    Read 1: errors=" << ec1 << " seq=" << r1.bases << endl;
				if (verbose) out << "    Read 2: errors=" << ec2 << " seq=" << r2.bases << endl;

				//set headers and qualities
				r1.header = "@PERsim:1:ABCDEF:1:" + chr.str() + ":" + QByteArray::number(start) + ":" + QByteArray::number(end-1) + " 1:N:0:AACGTGAT";
				r2.header = "@PERsim:1:ABCDEF:1:" + chr.str() + ":" + QByteArray::number(start) + ":" + QByteArray::number(end-1) + " 2:N:0:AACGTGAT";
				r1.header2 = "+";
				r2.header2 = "+";
				r1.qualities = qualities;
				r2.qualities = qualities;

				//validate data
				r1.validate();
				r2.validate();
				if (r1.bases.length()!=length) THROW(ProgrammingException, "Read 1 is only " + QString::number(r1.bases.length()) + " bases long!");
				if (r2.bases.length()!=length) THROW(ProgrammingException, "Read 2 is only " + QString::number(r2.bases.length()) + " bases long!");

				//write output
				out1.write(r1);
				out2.write(r2);
			}
		}
	}
};

/*
TODO:
- more realistic error model (high at beginning of read/index, higher for later cycles)
- error model for insertions/deletions/N
- implement test!
*/

#include "main.moc"

int main(int argc, char *argv[])
{
	ConcreteTool tool(argc, argv);
	return tool.execute();
}
<commit_msg>PERsim: added overrepresentation of A after adapters<commit_after>#include "Exceptions.h"
#include "ToolBase.h"
#include "Helper.h"
#include "NGSHelper.h"
#include "FastqFileStream.h"
#include "BedFile.h"
#include "Settings.h"
#include "FastaFileIndex.h"
#include <chrono>

#include "api/BamReader.h"
using namespace BamTools;

class ConcreteTool
		: public ToolBase
{
	Q_OBJECT

public:
	ConcreteTool(int& argc, char *argv[])
		: ToolBase(argc, argv)
	{
	}

	virtual void setup()
	{
		setDescription("Paired-end read simulator for Illumina reads.");
		addInfile("roi", "Target region BED file (the corresponding reference genome is taken from the settings.ini file).", false);
		addInt("count", "Number of read pairs to generate.", false);
		addOutfile("out1", "Forward reads output file in .FASTQ.GZ format.", false);
		addOutfile("out2", "Reverse reads output file in .FASTQ.GZ format.", false);
		//optional
		addInt("length", "Read length for forward/reverse reads.", true, 100);
		addInt("ins_mean", "Library insert size mean value.", true, 200);
		addInt("ins_stdev", "Library insert size mean standard deviation.", true, 70);
		addFloat("error", "Base error probability (uniform distribution).", true, 0.01);
		addString("a1", "Forward read sequencing adapter sequence (for read-through).", true, "AGATCGGAAGAGCACACGTCTGAACTCCAGTCACGAGTTA");
		addString("a2", "Reverse read sequencing adapter sequence (for read-through).", true, "AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGTAGATCTC");
		addInfile("ref", "Reference genome FASTA file. If unset 'reference_genome' from the 'settings.ini' file is used.", true, false);
		addFlag("v", "Enable verbose debug output.");
	}

	int addNoise(QByteArray& sequence, double error_probabilty, std::mt19937& gen)
	{
		int ec = 0;

		//uniform distribution
		std::uniform_real_distribution<double> error_dist(0, 1);

		//bases vector
		QByteArray bases = "ACGT";
		for(int i=0; i<sequence.length(); ++i)
		{
			//base error?
			bool error = error_dist(gen) < error_probabilty;

			//replace base at random
			if (error)
			{
				do
				{
					std::random_shuffle(bases.begin(), bases.end());
				}
				while (sequence[i]==bases[0]);
				sequence[i] = bases[0];

				++ec;
			}
		}

		return ec;
	}

	virtual void main()
	{
		//init
		QTextStream out(stdout);
		FastqOutfileStream out1(getOutfile("out1"), false);
		FastqOutfileStream out2(getOutfile("out2"), false);
		BedFile roi;
		roi.load(getInfile("roi"));
		long count = getInt("count");
		int length = getInt("length");
		int ins_mean = getInt("ins_mean");
		int ins_stdev = getInt("ins_stdev");
		QString a1 = getString("a1");
		QString a2 = getString("a2");
		bool verbose = getFlag("v");
		double error = getFloat("error");

		//set qualities
		QByteArray qualities = "AAAAAFFFFFFFGGGGGGFFFFFFFFFFEEEEEEEEEEEEEEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
		qualities = qualities.left(length);

		//open refererence genome file
		QString ref_file = getInfile("ref");
		if (ref_file=="") ref_file = Settings::string("reference_genome");
		FastaFileIndex reference(ref_file);

		//normal distribution for insert size
		unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
		std::mt19937 gen(seed);
		std::normal_distribution<> insert_dist(ins_mean, ins_stdev);

		//determine overall ROI size
		roi.merge();
		double overall_bases = roi.baseCount();

		//simulate reads (for each target region)
		for (int r=0; r<roi.count(); ++r)
		{
			const BedLine& reg = roi[r];
			const Chromosome& chr = reg.chr();

			//determine how many reads to generate for this region
			long r_count = std::round((double)count * reg.length() / overall_bases);
			out << "Region: " << chr.str() << ":" << reg.start() << "-" << reg.end() << " length=" << reg.length() << " reads=" << r_count << endl;
			for (long i=0; i<r_count; ++i)
			{
				//determine insert size
				int is = std::max((int)insert_dist(gen), 0);

				//determine start and end position (the read should overlap with the region)
				std::uniform_int_distribution<int> start_dist(reg.start()-is/2, reg.end()-is/2);
				int start = start_dist(gen);
				int end = start + is;
				if (start<0) start=0;
				if (end>reference.lengthOf(chr)) end = reference.lengthOf(chr);

				//get insert sequence;
				Sequence seq = reference.seq(chr, start, end-start);
				if (verbose) out << "  Insert: " << chr.str() << ":" << start << "-" << (end-1) << " length=" << seq.length() << endl;

				//get read seqence
				FastqEntry r1;
				FastqEntry r2;
				r1.bases = seq.left(length);
				r2.bases = seq.right(length);
				r2.bases = NGSHelper::changeSeq(r2.bases, true, true);

				//append sequencing adapers (if too short)
				int a_length = length - r1.bases.length();
				if (a_length>0)
				{
					r1.bases.append(a1.left(a_length));
					r2.bases.append(a2.left(a_length));
				}

				//append random sequence with overrepresended 'A' (if still too short)
				int r_length = length - r1.bases.length();
				r1.bases.append(Helper::randomString(r_length, "AACGT"));
				r2.bases.append(Helper::randomString(r_length, "AACGT"));

				//add noise
				int ec1 = addNoise(r1.bases, error, gen);
				int ec2 = addNoise(r2.bases, error, gen);
				if (verbose) out << "    Read 1: errors=" << ec1 << " seq=" << r1.bases << endl;
				if (verbose) out << "    Read 2: errors=" << ec2 << " seq=" << r2.bases << endl;

				//set headers and qualities
				r1.header = "@PERsim:1:ABCDEF:1:" + chr.str() + ":" + QByteArray::number(start) + ":" + QByteArray::number(end-1) + " 1:N:0:AACGTGAT";
				r2.header = "@PERsim:1:ABCDEF:1:" + chr.str() + ":" + QByteArray::number(start) + ":" + QByteArray::number(end-1) + " 2:N:0:AACGTGAT";
				r1.header2 = "+";
				r2.header2 = "+";
				r1.qualities = qualities;
				r2.qualities = qualities;

				//validate data
				r1.validate();
				r2.validate();
				if (r1.bases.length()!=length) THROW(ProgrammingException, "Read 1 is only " + QString::number(r1.bases.length()) + " bases long!");
				if (r2.bases.length()!=length) THROW(ProgrammingException, "Read 2 is only " + QString::number(r2.bases.length()) + " bases long!");

				//write output
				out1.write(r1);
				out2.write(r2);
			}
		}
	}
};

/*
TODO:
- more realistic error model (high at beginning of read/index, higher for later cycles)
- error model for insertions/deletions/N
- implement test!
*/

#include "main.moc"

int main(int argc, char *argv[])
{
	ConcreteTool tool(argc, argv);
	return tool.execute();
}
<|endoftext|>


<commit_before>/*
Made by XorfacX
*/

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/sdlut/sdlutgraphics.hpp"

#include "guichan/exception.hpp"
#include "guichan/font.hpp"
#include "guichan/image.hpp"
#include "guichan/sdlut/sdlutimage.hpp"
#include "guichan/sdlut/sdlutpixel.hpp"
#include "guichan/sdlut/sdlutimageloader.hpp" //for magicPink

// For some reason an old version of MSVC did not like std::abs,
// so we added this macro.
#ifndef ABS
#define ABS(x) ((x)<0?-(x):(x))
#endif

namespace gcn
{

SDLutGraphics::SDLutGraphics()
{
    mAlpha = false;
}

void SDLutGraphics::setTarget(video::ScreenBuffer* target)
{
    mTarget = target;
}

video::ScreenBuffer* SDLutGraphics::getTarget() const
{
    return mTarget;
}

// Inherited from Graphics
void SDLutGraphics::_beginDraw()
{
    Rectangle area (0, 0, mTarget->getWidth(), mTarget->getHeight() );
    /*area.x = 0;
    area.y = 0;
    area.width = mTarget->getWidth();
    area.height = mTarget->getHeight();*/

	if (!Image4Pixels.get() || Image4Pixels->getWidth() != mTarget->getWidth() || Image4Pixels->getHeight() != mTarget->getHeight() )
    {
        Image4Pixels.reset( new video::Image(mTarget->getWidth(), mTarget->getHeight(), mTarget->getBPP(), false, false ) );
		Image4PixelsDim = video::Rect(0, 0, Image4Pixels->getWidth(), Image4Pixels->getHeight());
    }
	Image4Pixels->fill(video::Color(0,0,0,0));

    pushClipArea(area);
}

void SDLutGraphics::_endDraw()
{
    tempImage4PixelsDim = Image4PixelsDim;
    popClipArea();
    mTarget->blit(*Image4Pixels.get(), tempImage4PixelsDim);

}

bool SDLutGraphics::pushClipArea(Rectangle area)
{

    bool result = Graphics::pushClipArea(area);

    const ClipRectangle& carea = mClipStack.top();

    video::Rect rect( carea.x, carea.y, carea.width, carea.height );

    mTarget->resetClipRect(rect);

    //SDL_SetClipRect(mTarget, &rect);

    return result;
}

void SDLutGraphics::popClipArea()
{
    Graphics::popClipArea();

    if (mClipStack.empty())
    {
        return;
    }

    const ClipRectangle& carea = mClipStack.top();
    video::Rect rect(carea.x, carea.y, carea.width, carea.height);

    mTarget->resetClipRect(rect);
}

void SDLutGraphics::drawImage(const gcn::Image* image,
                              int srcX,
                              int srcY,
                              int dstX,
                              int dstY,
                              int width,
                              int height)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

    video::Rect src (srcX, srcY, width, height);
    video::Rect dst (dstX + top.xOffset, dstY + top.yOffset, width, height);
    /*src.setx( srcX );
    src.sety( srcY );
    src.setw( width );
    src.seth( height );
    dst.setx( dstX + top.xOffset );
    dst.sety( dstY + top.yOffset );*/

    const SDLutImage* srcImage = dynamic_cast<const SDLutImage*>(image);

    if (srcImage == NULL)
    {
        throw GCN_EXCEPTION("Trying to draw an image of unknown format, must be an SDLutImage.");
    }

    //mTarget->blit(*(srcImage->getSurface()), dst, src);
	Image4Pixels->blit(*(srcImage->getSurface()), dst, src);

    //SDL_BlitSurface(srcImage->getSurface(), &src, mTarget, &dst);
}

void SDLutGraphics::fillRectangle(const Rectangle& rectangle)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

    Rectangle area = rectangle;
    area.x += top.xOffset;
    area.y += top.yOffset;

    if (!area.isIntersecting(top))
    {
        return;
    }

	video::Rect rect;
    if (mAlpha)
    {
        int x1 = area.x > top.x ? area.x : top.x;
        int y1 = area.y > top.y ? area.y : top.y;
        int x2 = area.x + area.width < top.x + top.width ? area.x + area.width : top.x + top.width;
        int y2 = area.y + area.height < top.y + top.height ? area.y + area.height : top.y + top.height;
        /*int x, y;

        for (y = y1; y < y2; y++)
        {
            for (x = x1; x < x2; x++)
            {
                SDLutputPixel(Image4Pixels.get(), x, y, mColor);
            }
        }*/
		rect = video::Rect(x1, y1, x2-x1, y2-y1);
    }
    else
    {
        rect = video::Rect(area.x, area.y, area.width, area.height);
        //video::Color rgbacolor( (unsigned char)mColor.r, (unsigned char)mColor.g, (unsigned char)mColor.b, (unsigned char)mColor.a );

        //mTarget->fill(rgbacolor, rect );
        //Image4Pixels->fill(rgbacolor, rect );

    }
	video::Color rgbacolor( (unsigned char)mColor.r, (unsigned char)mColor.g, (unsigned char)mColor.b, (unsigned char)mColor.a );
	Image4Pixels->fill(rgbacolor, rect );
}

void SDLutGraphics::drawPoint(int x, int y)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

    x += top.xOffset;
    y += top.yOffset;

    if (!top.isPointInRect(x,y))
        return;

    SDLutputPixel(Image4Pixels.get(), x, y, mColor);
}

void SDLutGraphics::drawHLine(int x1, int y, int x2)
{
    //drawLine(x1, y, x2, y);
	fillRectangle( gcn::Rectangle(std::min<int>(x1, x2), y, abs(x2-x1), 1) );
}

void SDLutGraphics::drawVLine(int x, int y1, int y2)
{
    //drawLine(x, y1, x, y2);
	fillRectangle( gcn::Rectangle(x, std::min<int>(y1, y2), 1, abs(y2-y1)) );
}

void SDLutGraphics::drawRectangle(const Rectangle& rectangle)
{
    int x1 = rectangle.x;
    int x2 = rectangle.x + rectangle.width - 1;
    int y1 = rectangle.y;
    int y2 = rectangle.y + rectangle.height - 1;

    drawHLine(x1, y1, x2);
    drawHLine(x1, y2, x2);

    drawVLine(x1, y1, y2);
    drawVLine(x2, y1, y2);
}

void SDLutGraphics::drawLine(int x1, int y1, int x2, int y2)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

    x1 += top.xOffset;
    y1 += top.yOffset;
    x2 += top.xOffset;
    y2 += top.yOffset;

    // Draw a line with Bresenham

    int dx = ABS(x2 - x1);
    int dy = ABS(y2 - y1);

    if (dx > dy)
    {
        if (x1 > x2)
        {
            // swap x1, x2
            x1 ^= x2;
            x2 ^= x1;
            x1 ^= x2;

            // swap y1, y2
            y1 ^= y2;
            y2 ^= y1;
            y1 ^= y2;
        }

        if (y1 < y2)
        {
            int y = y1;
            int p = 0;

            for (int x = x1; x <= x2; x++)
            {
                if (top.isPointInRect(x, y))
                {
                    SDLutputPixel(Image4Pixels.get(), x, y, mColor);
                }

                p += dy;

                if (p * 2 >= dx)
                {
                    y++;
                    p -= dx;
                }
            }
        }
        else
        {
            int y = y1;
            int p = 0;

            for (int x = x1; x <= x2; x++)
            {
                if (top.isPointInRect(x, y))
                {
                    SDLutputPixel(Image4Pixels.get(), x, y, mColor);
                }

                p += dy;

                if (p * 2 >= dx)
                {
                    y--;
                    p -= dx;
                }
            }
        }
    }
    else
    {
        if (y1 > y2)
        {
            // swap y1, y2
            y1 ^= y2;
            y2 ^= y1;
            y1 ^= y2;

            // swap x1, x2
            x1 ^= x2;
            x2 ^= x1;
            x1 ^= x2;
        }

        if (x1 < x2)
        {
            int x = x1;
            int p = 0;

            for (int y = y1; y <= y2; y++)
            {
                if (top.isPointInRect(x, y))
                {
                    SDLutputPixel(Image4Pixels.get(), x, y, mColor);
                }

                p += dx;

                if (p * 2 >= dy)
                {
                    x++;
                    p -= dy;
                }
            }
        }
        else
        {
            int x = x1;
            int p = 0;

            for (int y = y1; y <= y2; y++)
            {
                if (top.isPointInRect(x, y))
                {
                    SDLutputPixel(Image4Pixels.get(), x, y, mColor);
                }

                p += dx;

                if (p * 2 >= dy)
                {
                    x--;
                    p -= dy;
                }
            }
        }
    }
}

void SDLutGraphics::setColor(const gcn::Color& color)
{
    mColor = color;

    mAlpha = (color.a < 255);
}

const gcn::Color& SDLutGraphics::getColor() const
{
    return mColor;
}

void SDLutGraphics::drawSDLutSurface(video::Image& surface,
                                     video::Rect& source,
                                     video::Rect& destination)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

    destination.resetx( top.xOffset + destination.getx() );
    destination.resety( top.yOffset + destination.gety() );

    //mTarget->blit( surface, destination, source);
	Image4Pixels->blit( surface, destination, source);
}

} //gcn
<commit_msg>> small fix on width/height size > small fix on draw lines to call horiz & vert if applicable (fastest)<commit_after>/*
Made by XorfacX
*/

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/sdlut/sdlutgraphics.hpp"

#include "guichan/exception.hpp"
#include "guichan/font.hpp"
#include "guichan/image.hpp"
#include "guichan/sdlut/sdlutimage.hpp"
#include "guichan/sdlut/sdlutpixel.hpp"
#include "guichan/sdlut/sdlutimageloader.hpp" //for magicPink

// For some reason an old version of MSVC did not like std::abs,
// so we added this macro.
#ifndef ABS
#define ABS(x) ((x)<0?-(x):(x))
#endif

namespace gcn
{

SDLutGraphics::SDLutGraphics()
{
    mAlpha = false;
}

void SDLutGraphics::setTarget(video::ScreenBuffer* target)
{
    mTarget = target;
}

video::ScreenBuffer* SDLutGraphics::getTarget() const
{
    return mTarget;
}

// Inherited from Graphics
void SDLutGraphics::_beginDraw()
{
    Rectangle area (0, 0, mTarget->getWidth(), mTarget->getHeight() );
    /*area.x = 0;
    area.y = 0;
    area.width = mTarget->getWidth();
    area.height = mTarget->getHeight();*/

	if (!Image4Pixels.get() || Image4Pixels->getWidth() != mTarget->getWidth() || Image4Pixels->getHeight() != mTarget->getHeight() )
    {
        Image4Pixels.reset( new video::Image(mTarget->getWidth(), mTarget->getHeight(), mTarget->getBPP(), false, false ) );
		Image4PixelsDim = video::Rect(0, 0, Image4Pixels->getWidth(), Image4Pixels->getHeight());
    }
	Image4Pixels->fill(video::Color(0,0,0,0));

    pushClipArea(area);
}

void SDLutGraphics::_endDraw()
{
    tempImage4PixelsDim = Image4PixelsDim;
    popClipArea();

    mTarget->blit(*Image4Pixels.get(), tempImage4PixelsDim);
}

bool SDLutGraphics::pushClipArea(Rectangle area)
{

    bool result = Graphics::pushClipArea(area);

    const ClipRectangle& carea = mClipStack.top();

    video::Rect rect( carea.x, carea.y, carea.width, carea.height );

    mTarget->resetClipRect(rect);

    //SDL_SetClipRect(mTarget, &rect);

    return result;
}

void SDLutGraphics::popClipArea()
{
    Graphics::popClipArea();

    if (mClipStack.empty())
    {
        return;
    }

    const ClipRectangle& carea = mClipStack.top();
    video::Rect rect(carea.x, carea.y, carea.width, carea.height);

    mTarget->resetClipRect(rect);
}

void SDLutGraphics::drawImage(const gcn::Image* image,
                              int srcX,
                              int srcY,
                              int dstX,
                              int dstY,
                              int width,
                              int height)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

    video::Rect src (srcX, srcY, width, height);
    video::Rect dst (dstX + top.xOffset, dstY + top.yOffset, width, height);
    /*src.setx( srcX );
    src.sety( srcY );
    src.setw( width );
    src.seth( height );
    dst.setx( dstX + top.xOffset );
    dst.sety( dstY + top.yOffset );*/

    const SDLutImage* srcImage = dynamic_cast<const SDLutImage*>(image);

    if (srcImage == NULL)
    {
        throw GCN_EXCEPTION("Trying to draw an image of unknown format, must be an SDLutImage.");
    }

    //mTarget->blit(*(srcImage->getSurface()), dst, src);
	Image4Pixels->blit(*(srcImage->getSurface()), dst, src);

    //SDL_BlitSurface(srcImage->getSurface(), &src, mTarget, &dst);
}

void SDLutGraphics::fillRectangle(const Rectangle& rectangle)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

    Rectangle area = rectangle;
    area.x += top.xOffset;
    area.y += top.yOffset;

    if (!area.isIntersecting(top))
    {
        return;
    }

	video::Rect rect;
    if (mAlpha)
    {
        int x1 = area.x > top.x ? area.x : top.x;
        int y1 = area.y > top.y ? area.y : top.y;
        int x2 = area.x + area.width < top.x + top.width ? area.x + area.width : top.x + top.width;
        int y2 = area.y + area.height < top.y + top.height ? area.y + area.height : top.y + top.height;
        /*int x, y;

        for (y = y1; y < y2; y++)
        {
            for (x = x1; x < x2; x++)
            {
                SDLutputPixel(Image4Pixels.get(), x, y, mColor);
            }
        }*/
		//rect = video::Rect(x1, y1, x2-x1+1, y2-y1+1);
		rect = video::Rect(std::min<int>(x1, x2), std::min<int>(y1, y2), abs(x2-x1)+1, abs(y2-y1)+1);
    }
    else
    {
        rect = video::Rect(area.x, area.y, area.width, area.height);
        //video::Color rgbacolor( (unsigned char)mColor.r, (unsigned char)mColor.g, (unsigned char)mColor.b, (unsigned char)mColor.a );

        //mTarget->fill(rgbacolor, rect );
        //Image4Pixels->fill(rgbacolor, rect );

    }
	video::Color rgbacolor( (unsigned char)mColor.r, (unsigned char)mColor.g, (unsigned char)mColor.b, (unsigned char)mColor.a );
	Image4Pixels->fill(rgbacolor, rect );
}

void SDLutGraphics::drawPoint(int x, int y)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

    x += top.xOffset;
    y += top.yOffset;

    if (!top.isPointInRect(x,y))
        return;

    SDLutputPixel(Image4Pixels.get(), x, y, mColor);
}

void SDLutGraphics::drawHLine(int x1, int y, int x2)
{
    //drawLine(x1, y, x2, y);
	fillRectangle( gcn::Rectangle(std::min<int>(x1, x2), y, abs(x2-x1)+1, 1) );
}

void SDLutGraphics::drawVLine(int x, int y1, int y2)
{
    //drawLine(x, y1, x, y2);
	fillRectangle( gcn::Rectangle(x, std::min<int>(y1, y2), 1, abs(y2-y1)+1) );
}

void SDLutGraphics::drawRectangle(const Rectangle& rectangle)
{
    int x1 = rectangle.x;
    int x2 = rectangle.x + rectangle.width - 1;
    int y1 = rectangle.y;
    int y2 = rectangle.y + rectangle.height - 1;

    drawHLine(x1, y1, x2);
    drawHLine(x1, y2, x2);

    drawVLine(x1, y1, y2);
    drawVLine(x2, y1, y2);
}

void SDLutGraphics::drawLine(int x1, int y1, int x2, int y2)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

	if (x1 == x2)
	{
		drawVLine(x1, y1, y2);
	}
	else if (y1 == y2)
	{
		drawHLine(x1, y1, x2);
	}
	else
	{

		x1 += top.xOffset;
		y1 += top.yOffset;
		x2 += top.xOffset;
		y2 += top.yOffset;

		// Draw a line with Bresenham

		int dx = ABS(x2 - x1);
		int dy = ABS(y2 - y1);

		if (dx > dy)
		{
			if (x1 > x2)
			{
				// swap x1, x2
				x1 ^= x2;
				x2 ^= x1;
				x1 ^= x2;

				// swap y1, y2
				y1 ^= y2;
				y2 ^= y1;
				y1 ^= y2;
			}

			if (y1 < y2)
			{
				int y = y1;
				int p = 0;

				for (int x = x1; x <= x2; x++)
				{
					if (top.isPointInRect(x, y))
					{
						SDLutputPixel(Image4Pixels.get(), x, y, mColor);
					}

					p += dy;

					if (p * 2 >= dx)
					{
						y++;
						p -= dx;
					}
				}
			}
			else
			{
				int y = y1;
				int p = 0;

				for (int x = x1; x <= x2; x++)
				{
					if (top.isPointInRect(x, y))
					{
						SDLutputPixel(Image4Pixels.get(), x, y, mColor);
					}

					p += dy;

					if (p * 2 >= dx)
					{
						y--;
						p -= dx;
					}
				}
			}
		}
		else
		{
			if (y1 > y2)
			{
				// swap y1, y2
				y1 ^= y2;
				y2 ^= y1;
				y1 ^= y2;

				// swap x1, x2
				x1 ^= x2;
				x2 ^= x1;
				x1 ^= x2;
			}

			if (x1 < x2)
			{
				int x = x1;
				int p = 0;

				for (int y = y1; y <= y2; y++)
				{
					if (top.isPointInRect(x, y))
					{
						SDLutputPixel(Image4Pixels.get(), x, y, mColor);
					}

					p += dx;

					if (p * 2 >= dy)
					{
						x++;
						p -= dy;
					}
				}
			}
			else
			{
				int x = x1;
				int p = 0;

				for (int y = y1; y <= y2; y++)
				{
					if (top.isPointInRect(x, y))
					{
						SDLutputPixel(Image4Pixels.get(), x, y, mColor);
					}

					p += dx;

					if (p * 2 >= dy)
					{
						x--;
						p -= dy;
					}
				}
			}
		}
	}
}

void SDLutGraphics::setColor(const gcn::Color& color)
{
    mColor = color;

    mAlpha = (color.a < 255);
}

const gcn::Color& SDLutGraphics::getColor() const
{
    return mColor;
}

void SDLutGraphics::drawSDLutSurface(video::Image& surface,
                                     video::Rect& source,
                                     video::Rect& destination)
{
    if (mClipStack.empty())
    {
        throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
    }

    const ClipRectangle& top = mClipStack.top();

    destination.resetx( top.xOffset + destination.getx() );
    destination.resety( top.yOffset + destination.gety() );

    //mTarget->blit( surface, destination, source);
	Image4Pixels->blit( surface, destination, source);
}

} //gcn
<|endoftext|>


<commit_before>#include "cspersonservice.h"

//Bool variablers are used in sorting to decide the order of sorting, DESCending and ASCending
bool sortByNameDESC(const CSPerson &lhs, const CSPerson &rhs) { return lhs.getName() < rhs.getName(); }
bool sortByNameASCC(const CSPerson &lhs, const CSPerson &rhs) { return lhs.getName() > rhs.getName(); }
bool sortByGenderDESC(const CSPerson &lhs, const CSPerson &rhs) { return lhs.getGender() < rhs.getGender(); }
bool sortByDeathYearASCC(const CSPerson &lhs, const CSPerson &rhs) {return lhs.getPassedAwayYear() > rhs.getPassedAwayYear(); }
bool sortByBirthYearDESC(const CSPerson &lhs, const CSPerson &rhs) {return lhs.getBirthYear() < rhs.getBirthYear(); }
bool sortByBirthYearASCC(const CSPerson &lhs, const CSPerson &rhs) {return lhs.getBirthYear() > rhs.getBirthYear(); }
bool sortByAgeASCC(const CSPerson &lhs, const CSPerson &rhs)
{
    CSPerson tempLeft = lhs;//Copy our const into a temp variable, so we can work with our int value and get the age.
    CSPerson tempRight = rhs;
    return tempLeft.getAge() > tempRight.getAge();
}

CSPersonService::CSPersonService()
{
    _fileKeeper = _data.readFromFile();
}

bool CSPersonService::addNewPersonToList(const string name,const string gender, string birthYear, string deathYear,const string comment)
{
    //We will set years to 0 if they are not valid.
    int tempBirthYear = 0, tempDeathYear = 0;
    if(validNumber(birthYear)) //If number is valid
    {
        //tempBirthYear = stoi(birthYear);
        //tempBirthYear = birthYear;
    }
    if(validNumber(deathYear))
    {
        tempDeathYear = stoi(deathYear);
        //tempDeathYear = deathYear;
    }
    //Save our new person in our vector
    _fileKeeper.push_back(CSPerson (name, gender, tempBirthYear, tempDeathYear, comment));
    _data.writeToFile(_fileKeeper);// Write our updated vector to file
    return true;//Return true that we made it
}
//We take in id as a string to avoid strange letters/input
bool CSPersonService::removePersonFromList(const string id)
{
    size_t index = 0;
    try
    {
        index = stoi(id);
        index--; //Off by one
    }
    catch(int e)
    {
        return false;
    }
    if(index < _fileKeeper.size())
    {
        removeNodeFromList(index);
        return true;//Return true that we successfully removed the person
    }
    return false;
}
bool CSPersonService::editPersonFromList(const string oldID, CSPerson person)
{
    size_t index = 0;
    try
    {
        index = stoi(oldID);
        index--; //Off by one
    }
    catch(int e)
    {
        return false;
    }
    if(index < _fileKeeper.size())
    {
        _fileKeeper[index] = person;
        _data.writeToFile(_fileKeeper);
        return true;//Return true that we successfully edited the person
    }
    return false;
}

int CSPersonService::getIndexOfValueByName(const string name)
{
    for(size_t i = 0; i < _fileKeeper.size(); i++)
    {
        if(name == _fileKeeper[i].getName())
        {
            return i;
        }
    }
    return -1;//Return value less then 0
}
void CSPersonService::removeNodeFromList(const int index)
{
    _fileKeeper.erase(_fileKeeper.begin() + index);
    _data.writeToFile(_fileKeeper);
}

//Search by name, find every value that we find and return all of those values in a vector
vector<CSPerson> CSPersonService::searchByName(const string searchString)
{
    vector<CSPerson> tempVector;
    for(size_t i = 0; i < _fileKeeper.size(); i++)
    {
        if(checkIfStringSameIgnoreUpper(_fileKeeper[i].getName(), searchString))
        {
            tempVector.push_back(_fileKeeper[i]);
        }
    }
    return tempVector;
}

bool CSPersonService::validNumber(string number)
{
    int inputNumber = 0;
    try
    {
        inputNumber = atoi(number.c_str());//Try to convert string to int
    }
    catch(int e)
    {
        return false;
    }
    if(inputNumber > 0  || inputNumber < 3000)//If the year is beetween 1 - 2999
    {
        return true;
    }
    else
    {
        return false;
    }
}

vector<CSPerson> CSPersonService::searchByYearOfBirth(const string searchString)
{
    vector<CSPerson> tempVector;
    if(validNumber(searchString))
    {
        for(size_t i = 0; i < _fileKeeper.size(); i++)
        {
            string temp = to_string(_fileKeeper[i].getBirthYear());
            if(checkIfStringSameIgnoreUpper(temp, searchString))
            {
                tempVector.push_back(_fileKeeper[i]);
            }
        }
    }
    return tempVector;
}

vector<CSPerson> CSPersonService::searchByYearOfDeath(const string searchString)
{
    vector<CSPerson> tempVector;
    if(validNumber(searchString))
    {
        for(size_t i = 0; i < _fileKeeper.size(); i++)
        {
            string temp = to_string(_fileKeeper[i].getPassedAwayYear());
            if(checkIfStringSameIgnoreUpper(temp, searchString))
            {
                tempVector.push_back(_fileKeeper[i]);
            }
        }
    }
    return tempVector;
}

//Returns true if string2 is a part of string1, no matter upper or lower case.
bool CSPersonService::checkIfStringSameIgnoreUpper(string orginalString, string searchFor)
{
    //Make sure both strings are the same case
    transform(orginalString.begin(), orginalString.end(),orginalString.begin(), ::tolower);
    transform(searchFor.begin(), searchFor.end(),searchFor.begin(), ::tolower);
    if(orginalString.find(searchFor) != string::npos)//If string.find is not size_t max size
    {
        return true;
    }
    else
    {
        return false;
    }
}

//Sorts

void CSPersonService::sortByName()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByNameDESC);
    _data.writeToFile(_fileKeeper);//Write our change to the file
}
void CSPersonService::sortByNameASC()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByNameASCC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByGender()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByGenderDESC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByDeathYear()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByDeathYearASCC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByBirthYear()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByBirthYearDESC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByBirthYearASC()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByBirthYearASCC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByAge()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByAgeASCC);
    _data.writeToFile(_fileKeeper);
}
<commit_msg>addnewperson fix<commit_after>#include "cspersonservice.h"

//Bool variablers are used in sorting to decide the order of sorting, DESCending and ASCending
bool sortByNameDESC(const CSPerson &lhs, const CSPerson &rhs) { return lhs.getName() < rhs.getName(); }
bool sortByNameASCC(const CSPerson &lhs, const CSPerson &rhs) { return lhs.getName() > rhs.getName(); }
bool sortByGenderDESC(const CSPerson &lhs, const CSPerson &rhs) { return lhs.getGender() < rhs.getGender(); }
bool sortByDeathYearASCC(const CSPerson &lhs, const CSPerson &rhs) {return lhs.getPassedAwayYear() > rhs.getPassedAwayYear(); }
bool sortByBirthYearDESC(const CSPerson &lhs, const CSPerson &rhs) {return lhs.getBirthYear() < rhs.getBirthYear(); }
bool sortByBirthYearASCC(const CSPerson &lhs, const CSPerson &rhs) {return lhs.getBirthYear() > rhs.getBirthYear(); }
bool sortByAgeASCC(const CSPerson &lhs, const CSPerson &rhs)
{
    CSPerson tempLeft = lhs;//Copy our const into a temp variable, so we can work with our int value and get the age.
    CSPerson tempRight = rhs;
    return tempLeft.getAge() > tempRight.getAge();
}

CSPersonService::CSPersonService()
{
    _fileKeeper = _data.readFromFile();
}

bool CSPersonService::addNewPersonToList(const string name,const string gender, string birthYear, string deathYear,const string comment)
{
    //We will set years to 0 if they are not valid.
    int tempBirthYear = 0, tempDeathYear = 0;
    if(validNumber(birthYear)) //If number is valid
    {
        tempBirthYear = stoi(birthYear);
        //tempBirthYear = birthYear;
    }
    if(validNumber(deathYear))
    {
        tempDeathYear = stoi(deathYear);
        //tempDeathYear = deathYear;
    }
    //Save our new person in our vector
    _fileKeeper.push_back(CSPerson (name, gender, tempBirthYear, tempDeathYear, comment));
    _data.writeToFile(_fileKeeper);// Write our updated vector to file
    return true;//Return true that we made it
}
//We take in id as a string to avoid strange letters/input
bool CSPersonService::removePersonFromList(const string id)
{
    size_t index = 0;
    try
    {
        index = stoi(id);
        index--; //Off by one
    }
    catch(int e)
    {
        return false;
    }
    if(index < _fileKeeper.size())
    {
        removeNodeFromList(index);
        return true;//Return true that we successfully removed the person
    }
    return false;
}
bool CSPersonService::editPersonFromList(const string oldID, CSPerson person)
{
    size_t index = 0;
    try
    {
        index = stoi(oldID);
        index--; //Off by one
    }
    catch(int e)
    {
        return false;
    }
    if(index < _fileKeeper.size())
    {
        _fileKeeper[index] = person;
        _data.writeToFile(_fileKeeper);
        return true;//Return true that we successfully edited the person
    }
    return false;
}

int CSPersonService::getIndexOfValueByName(const string name)
{
    for(size_t i = 0; i < _fileKeeper.size(); i++)
    {
        if(name == _fileKeeper[i].getName())
        {
            return i;
        }
    }
    return -1;//Return value less then 0
}
void CSPersonService::removeNodeFromList(const int index)
{
    _fileKeeper.erase(_fileKeeper.begin() + index);
    _data.writeToFile(_fileKeeper);
}

//Search by name, find every value that we find and return all of those values in a vector
vector<CSPerson> CSPersonService::searchByName(const string searchString)
{
    vector<CSPerson> tempVector;
    for(size_t i = 0; i < _fileKeeper.size(); i++)
    {
        if(checkIfStringSameIgnoreUpper(_fileKeeper[i].getName(), searchString))
        {
            tempVector.push_back(_fileKeeper[i]);
        }
    }
    return tempVector;
}

bool CSPersonService::validNumber(string number)
{
    int inputNumber = 0;
    try
    {
        inputNumber = atoi(number.c_str());//Try to convert string to int
    }
    catch(int e)
    {
        return false;
    }
    if(inputNumber > 0  || inputNumber < 3000)//If the year is beetween 1 - 2999
    {
        return true;
    }
    else
    {
        return false;
    }
}

vector<CSPerson> CSPersonService::searchByYearOfBirth(const string searchString)
{
    vector<CSPerson> tempVector;
    if(validNumber(searchString))
    {
        for(size_t i = 0; i < _fileKeeper.size(); i++)
        {
            string temp = to_string(_fileKeeper[i].getBirthYear());
            if(checkIfStringSameIgnoreUpper(temp, searchString))
            {
                tempVector.push_back(_fileKeeper[i]);
            }
        }
    }
    return tempVector;
}

vector<CSPerson> CSPersonService::searchByYearOfDeath(const string searchString)
{
    vector<CSPerson> tempVector;
    if(validNumber(searchString))
    {
        for(size_t i = 0; i < _fileKeeper.size(); i++)
        {
            string temp = to_string(_fileKeeper[i].getPassedAwayYear());
            if(checkIfStringSameIgnoreUpper(temp, searchString))
            {
                tempVector.push_back(_fileKeeper[i]);
            }
        }
    }
    return tempVector;
}

//Returns true if string2 is a part of string1, no matter upper or lower case.
bool CSPersonService::checkIfStringSameIgnoreUpper(string orginalString, string searchFor)
{
    //Make sure both strings are the same case
    transform(orginalString.begin(), orginalString.end(),orginalString.begin(), ::tolower);
    transform(searchFor.begin(), searchFor.end(),searchFor.begin(), ::tolower);
    if(orginalString.find(searchFor) != string::npos)//If string.find is not size_t max size
    {
        return true;
    }
    else
    {
        return false;
    }
}

//Sorts

void CSPersonService::sortByName()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByNameDESC);
    _data.writeToFile(_fileKeeper);//Write our change to the file
}
void CSPersonService::sortByNameASC()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByNameASCC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByGender()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByGenderDESC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByDeathYear()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByDeathYearASCC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByBirthYear()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByBirthYearDESC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByBirthYearASC()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByBirthYearASCC);
    _data.writeToFile(_fileKeeper);
}
void CSPersonService::sortByAge()
{
    sort(_fileKeeper.begin(), _fileKeeper.end(), sortByAgeASCC);
    _data.writeToFile(_fileKeeper);
}
<|endoftext|>