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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <mitkTestFixture.h>
#include "mitkException.h"
#include <mitkTestingMacros.h>
#include <mitkStandardFileLocations.h>

#include <mitkExtractSliceFilter.h>
#include "mitkIOUtil.h"
#include "mitkITKImageImport.h"

#include "itksys/SystemTools.hxx"
#include <itkImageRegionIterator.h>

#include <iostream>
#include <fstream>

#ifdef WIN32
#include "process.h"
#else
#include <unistd.h>
#endif

class mitkItkImageIOTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkItkImageIOTestSuite);
  MITK_TEST(TestImageWriterJpg);
  MITK_TEST(TestImageWriterPng1);
  MITK_TEST(TestImageWriterPng2);
  MITK_TEST(TestImageWriterPng3);
  MITK_TEST(TestImageWriterSimple);
  MITK_TEST(TestWrite3DImageWithOnePlane);
  MITK_TEST(TestWrite3DImageWithTwoPlanes);
  CPPUNIT_TEST_SUITE_END();

public:

  void setUp() override
  {

  }

  void tearDown() override
  {
  }

  void TestImageWriterJpg()
  {
    TestImageWriter("NrrdWritingTestImage.jpg");
  }

  void TestImageWriterPng1()
  {
    TestImageWriter("Png2D-bw.png");
  }

  void TestImageWriterPng2()
  {
    TestImageWriter("RenderingTestData/rgbImage.png");
  }

  void TestImageWriterPng3()
  {
    TestImageWriter("RenderingTestData/rgbaImage.png");
  }

  void TestImageWriterSimple()
  {
    // TODO
  }

  std::string AppendExtension(const std::string &filename, const char *extension)
  {
    std::string new_filename = filename;

    new_filename += extension;
    return new_filename;
  }

  bool CompareImageMetaData( mitk::Image::Pointer image, mitk::Image::Pointer reference, bool checkPixelType = true )
  {
    // switch to AreIdentical() methods as soon as Bug 11925 (Basic comparison operators) is fixed

    if( image->GetDimension() != reference->GetDimension() )
    {
      MITK_ERROR << "The image dimension differs: IN (" << image->GetDimension() << ") REF(" << reference->GetDimension() << ")";
      return false;
    }

    // pixel type
    if( checkPixelType &&
        ( image->GetPixelType() != reference->GetPixelType()
        && image->GetPixelType().GetBitsPerComponent() != reference->GetPixelType().GetBitsPerComponent() ) )
    {
      MITK_ERROR << "Pixeltype differs ( image=" << image->GetPixelType().GetPixelTypeAsString() << "[" << image->GetPixelType().GetBitsPerComponent() << "]" << " reference=" << reference->GetPixelType().GetPixelTypeAsString() << "[" << reference->GetPixelType().GetBitsPerComponent() << "]" << " )";
      return false;
    }

    return true;
  }

  /*
  Test writing picture formats like *.bmp, *.png, *.tiff or *.jpg
  NOTE: Saving as picture format must ignore PixelType comparison - not all bits per components are supported (see specification of the format)
  */
  void TestPictureWriting(mitk::Image* image, const std::string& filename, const std::string& extension)
  {
    const std::string fullFileName = AppendExtension(filename, extension.c_str());

    mitk::Image::Pointer singleSliceImage = NULL;
    if( image->GetDimension() == 3 )
    {
      mitk::ExtractSliceFilter::Pointer extractFilter = mitk::ExtractSliceFilter::New();
      extractFilter->SetInput( image );
      extractFilter->SetWorldGeometry( image->GetSlicedGeometry()->GetPlaneGeometry(0) );

      extractFilter->Update();
      singleSliceImage = extractFilter->GetOutput();

      // test 3D writing in format supporting only 2D
      mitk::IOUtil::Save(image, fullFileName);

      // test images
      unsigned int foundImagesCount = 0;

      //if the image only contains one sinlge slice the itkImageSeriesWriter won't add a number like filename.XX.extension
      if(image->GetDimension(2) == 1)
      {
        std::stringstream series_filenames;
        series_filenames << filename << extension;
        mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() );
        if( compareImage.IsNotNull() )
        {
          foundImagesCount++;
          MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component
        }
        remove( series_filenames.str().c_str() );
      }
      else //test the whole slice stack
      {
        for( unsigned int i=0; i< image->GetDimension(2); i++)
        {
          std::stringstream series_filenames;
          series_filenames << filename << "." << i+1 << extension;
          mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() );
          if( compareImage.IsNotNull() )
          {
            foundImagesCount++;
            MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component
          }
          remove( series_filenames.str().c_str() );
        }
      }
      MITK_TEST_CONDITION( foundImagesCount == image->GetDimension(2), "All 2D-Slices of a 3D image were stored correctly.");
    }
    else if( image->GetDimension() == 2 )
    {
      singleSliceImage = image;
    }

    // test 2D writing
    if( singleSliceImage.IsNotNull() )
    {
      try
      {
        mitk::IOUtil::Save(singleSliceImage, fullFileName);

        mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(fullFileName.c_str());
        MITK_TEST_CONDITION_REQUIRED( compareImage.IsNotNull(), "Image stored was succesfully loaded again");

        MITK_TEST_CONDITION_REQUIRED( CompareImageMetaData(singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. ");//ignore bits per component
        remove(fullFileName.c_str());
      }
      catch(itk::ExceptionObject &e)
      {
        MITK_TEST_FAILED_MSG(<< "Exception during file writing for ." << extension << ": " << e.what() );
      }

    }

  }

  /**
  *  test for "ImageWriter".
  *
  *  argc and argv are the command line parameters which were passed to
  *  the ADD_TEST command in the CMakeLists.txt file. For the automatic
  *  tests, argv is either empty for the simple tests or contains the filename
  *  of a test image for the image tests (see CMakeLists.txt).
  */
  void TestImageWriter(std::string sourcefile)
  {

    sourcefile = GetTestDataFilePath(sourcefile);

    // load image
    CPPUNIT_ASSERT_MESSAGE("Checking whether source image exists", itksys::SystemTools::FileExists(sourcefile.c_str()));

    mitk::Image::Pointer image = NULL;

    try
    {
      image = mitk::IOUtil::LoadImage( sourcefile );
    }
    catch (...)
    {
      CPPUNIT_FAIL("Exception during file loading:");
    }

    CPPUNIT_ASSERT_MESSAGE("loaded image not NULL", image.IsNotNull());

    // write ITK .mhd image (2D and 3D only)
    if( image->GetDimension() <= 3 )
    {
      std::ofstream tmpStream;
      std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.mhd");
      tmpStream.close();

      std::string tmpFilePathWithoutExt = tmpFilePath.substr(0, tmpFilePath.size() - 4);

      try
      {
        mitk::IOUtil::Save(image, tmpFilePath);

        mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(tmpFilePath);
        CPPUNIT_ASSERT_MESSAGE("Image stored in MHD format was succesfully loaded again! ", compareImage.IsNotNull());

        CPPUNIT_ASSERT_MESSAGE(".mhd file exists", itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".mhd").c_str()));
        CPPUNIT_ASSERT_MESSAGE(".raw or .zraw exists", itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".raw").c_str()) ||
          itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".zraw").c_str()));

        // delete
        remove(tmpFilePath.c_str());
        remove((tmpFilePathWithoutExt + ".raw").c_str());
        remove((tmpFilePathWithoutExt + ".zraw").c_str());
      }
      catch (...)
      {
        CPPUNIT_FAIL("Exception during.mhd file writing");
      }
    }

    //testing more component image writing as nrrd files

    {
      std::ofstream tmpStream;
      std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.nrrd");
      tmpStream.close();

      try
      {
        mitk::IOUtil::Save(image, tmpFilePath);

        mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(tmpFilePath);
        CPPUNIT_ASSERT_MESSAGE("Image stored in NRRD format was succesfully loaded again", compareImage.IsNotNull());

        remove(tmpFilePath.c_str());
      }
      catch(...)
      {
        std::remove(tmpFilePath.c_str());
        CPPUNIT_FAIL("Exception during.mhd file writing");
      }
    }

    std::ofstream tmpStream;
    std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX");
    tmpStream.close();

    TestPictureWriting(image, tmpFilePath, ".png");
    TestPictureWriting(image, tmpFilePath, ".jpg");
    TestPictureWriting(image, tmpFilePath, ".tiff");
    TestPictureWriting(image, tmpFilePath, ".bmp");
    // always end with this!

  }

  /**
  * Try to write a 3D image with only one plane (a 2D images in disguise for all intents and purposes)
  */
  void TestWrite3DImageWithOnePlane(){
    typedef itk::Image<unsigned char, 3>  ImageType;

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

    ImageType::IndexType start;
    start.Fill(0);

    ImageType::SizeType size;
    size[0] = 100;
    size[1] = 100;
    size[2] = 1;

    ImageType::RegionType region;
    region.SetSize(size);
    region.SetIndex(start);
    itkImage->SetRegions(region);
    itkImage->Allocate();
    itkImage->FillBuffer(0);

    itk::ImageRegionIterator<ImageType> imageIterator(itkImage, itkImage->GetLargestPossibleRegion());

    // Make two squares
    while (!imageIterator.IsAtEnd())
    {
      if ((imageIterator.GetIndex()[0] > 5 && imageIterator.GetIndex()[0] < 20) &&
        (imageIterator.GetIndex()[1] > 5 && imageIterator.GetIndex()[1] < 20))
      {
        imageIterator.Set(255);
      }

      if ((imageIterator.GetIndex()[0] > 50 && imageIterator.GetIndex()[0] < 70) &&
        (imageIterator.GetIndex()[1] > 50 && imageIterator.GetIndex()[1] < 70))
      {
        imageIterator.Set(60);
      }
      ++imageIterator;
    }

    mitk::Image::Pointer image = mitk::ImportItkImage(itkImage);

    mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.nrrd"));
    mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.png"));

  }

  /**
  * Try to write a 3D image with only one plane (a 2D images in disguise for all intents and purposes)
  */
  void TestWrite3DImageWithTwoPlanes(){
    typedef itk::Image<unsigned char, 3>  ImageType;

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

    ImageType::IndexType start;
    start.Fill(0);

    ImageType::SizeType size;
    size[0] = 100;
    size[1] = 100;
    size[2] = 2;

    ImageType::RegionType region;
    region.SetSize(size);
    region.SetIndex(start);
    itkImage->SetRegions(region);
    itkImage->Allocate();
    itkImage->FillBuffer(0);

    itk::ImageRegionIterator<ImageType> imageIterator(itkImage, itkImage->GetLargestPossibleRegion());

    // Make two squares
    while (!imageIterator.IsAtEnd())
    {
      if ((imageIterator.GetIndex()[0] > 5 && imageIterator.GetIndex()[0] < 20) &&
        (imageIterator.GetIndex()[1] > 5 && imageIterator.GetIndex()[1] < 20))
      {
        imageIterator.Set(255);
      }
      if ((imageIterator.GetIndex()[0] > 50 && imageIterator.GetIndex()[0] < 70) &&
        (imageIterator.GetIndex()[1] > 50 && imageIterator.GetIndex()[1] < 70))
      {
        imageIterator.Set(60);
      }
      ++imageIterator;
    }
    mitk::Image::Pointer image = mitk::ImportItkImage(itkImage);

    mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.nrrd"));

    CPPUNIT_ASSERT_THROW(mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.png")), mitk::Exception);

  }

};

MITK_TEST_SUITE_REGISTRATION(mitkItkImageIO)
<commit_msg>added tests for mitkItkImageIoTest to check different geometry types.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <mitkTestFixture.h>
#include "mitkException.h"
#include <mitkTestingMacros.h>
#include <mitkStandardFileLocations.h>

#include <mitkExtractSliceFilter.h>
#include "mitkIOUtil.h"
#include "mitkITKImageImport.h"

#include "itksys/SystemTools.hxx"
#include <itkImageRegionIterator.h>

#include <iostream>
#include <fstream>

#ifdef WIN32
#include "process.h"
#else
#include <unistd.h>
#endif

class mitkItkImageIOTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkItkImageIOTestSuite);
  MITK_TEST(TestImageWriterJpg);
  MITK_TEST(TestImageWriterPng1);
  MITK_TEST(TestImageWriterPng2);
  MITK_TEST(TestImageWriterPng3);
  MITK_TEST(TestImageWriterSimple);
  MITK_TEST(TestWrite3DImageWithOnePlane);
  MITK_TEST(TestWrite3DImageWithTwoPlanes);
  MITK_TEST(TestWrite3DplusT_ArbitraryTG);
  MITK_TEST(TestWrite3DplusT_ProportionalTG);
  CPPUNIT_TEST_SUITE_END();

public:

  void setUp() override
  {

  }

  void tearDown() override
  {
  }

  void TestImageWriterJpg()
  {
    TestImageWriter("NrrdWritingTestImage.jpg");
  }

  void TestImageWriterPng1()
  {
    TestImageWriter("Png2D-bw.png");
  }

  void TestImageWriterPng2()
  {
    TestImageWriter("RenderingTestData/rgbImage.png");
  }

  void TestImageWriterPng3()
  {
    TestImageWriter("RenderingTestData/rgbaImage.png");
  }

  void TestWrite3DplusT_ArbitraryTG()
  {
    TestImageWriter("3D+t-ITKIO-TestData/LinearModel_4D_arbitrary_time_geometry.nrrd");
  }

  void TestWrite3DplusT_ProportionalTG()
  {
    TestImageWriter("3D+t-ITKIO-TestData/LinearModel_4D_prop_time_geometry.nrrd");
  }

  void TestImageWriterSimple()
  {
    // TODO
  }

  std::string AppendExtension(const std::string &filename, const char *extension)
  {
    std::string new_filename = filename;

    new_filename += extension;
    return new_filename;
  }

  bool CompareImageMetaData( mitk::Image::Pointer image, mitk::Image::Pointer reference, bool checkPixelType = true )
  {
    // switch to AreIdentical() methods as soon as Bug 11925 (Basic comparison operators) is fixed

    if( image->GetDimension() != reference->GetDimension() )
    {
      MITK_ERROR << "The image dimension differs: IN (" << image->GetDimension() << ") REF(" << reference->GetDimension() << ")";
      return false;
    }

    // pixel type
    if( checkPixelType &&
        ( image->GetPixelType() != reference->GetPixelType()
        && image->GetPixelType().GetBitsPerComponent() != reference->GetPixelType().GetBitsPerComponent() ) )
    {
      MITK_ERROR << "Pixeltype differs ( image=" << image->GetPixelType().GetPixelTypeAsString() << "[" << image->GetPixelType().GetBitsPerComponent() << "]" << " reference=" << reference->GetPixelType().GetPixelTypeAsString() << "[" << reference->GetPixelType().GetBitsPerComponent() << "]" << " )";
      return false;
    }

    return true;
  }

  /*
  Test writing picture formats like *.bmp, *.png, *.tiff or *.jpg
  NOTE: Saving as picture format must ignore PixelType comparison - not all bits per components are supported (see specification of the format)
  */
  void TestPictureWriting(mitk::Image* image, const std::string& filename, const std::string& extension)
  {
    const std::string fullFileName = AppendExtension(filename, extension.c_str());

    mitk::Image::Pointer singleSliceImage = NULL;
    if( image->GetDimension() == 3 )
    {
      mitk::ExtractSliceFilter::Pointer extractFilter = mitk::ExtractSliceFilter::New();
      extractFilter->SetInput( image );
      extractFilter->SetWorldGeometry( image->GetSlicedGeometry()->GetPlaneGeometry(0) );

      extractFilter->Update();
      singleSliceImage = extractFilter->GetOutput();

      // test 3D writing in format supporting only 2D
      mitk::IOUtil::Save(image, fullFileName);

      // test images
      unsigned int foundImagesCount = 0;

      //if the image only contains one sinlge slice the itkImageSeriesWriter won't add a number like filename.XX.extension
      if(image->GetDimension(2) == 1)
      {
        std::stringstream series_filenames;
        series_filenames << filename << extension;
        mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() );
        if( compareImage.IsNotNull() )
        {
          foundImagesCount++;
          MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component
        }
        remove( series_filenames.str().c_str() );
      }
      else //test the whole slice stack
      {
        for( unsigned int i=0; i< image->GetDimension(2); i++)
        {
          std::stringstream series_filenames;
          series_filenames << filename << "." << i+1 << extension;
          mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() );
          if( compareImage.IsNotNull() )
          {
            foundImagesCount++;
            MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component
          }
          remove( series_filenames.str().c_str() );
        }
      }
      MITK_TEST_CONDITION( foundImagesCount == image->GetDimension(2), "All 2D-Slices of a 3D image were stored correctly.");
    }
    else if( image->GetDimension() == 2 )
    {
      singleSliceImage = image;
    }

    // test 2D writing
    if( singleSliceImage.IsNotNull() )
    {
      try
      {
        mitk::IOUtil::Save(singleSliceImage, fullFileName);

        mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(fullFileName.c_str());
        MITK_TEST_CONDITION_REQUIRED( compareImage.IsNotNull(), "Image stored was succesfully loaded again");

        MITK_TEST_CONDITION_REQUIRED( CompareImageMetaData(singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. ");//ignore bits per component
        remove(fullFileName.c_str());
      }
      catch(itk::ExceptionObject &e)
      {
        MITK_TEST_FAILED_MSG(<< "Exception during file writing for ." << extension << ": " << e.what() );
      }

    }

  }

  /**
  *  test for "ImageWriter".
  *
  *  argc and argv are the command line parameters which were passed to
  *  the ADD_TEST command in the CMakeLists.txt file. For the automatic
  *  tests, argv is either empty for the simple tests or contains the filename
  *  of a test image for the image tests (see CMakeLists.txt).
  */
  void TestImageWriter(std::string sourcefile)
  {

    sourcefile = GetTestDataFilePath(sourcefile);

    // load image
    CPPUNIT_ASSERT_MESSAGE("Checking whether source image exists", itksys::SystemTools::FileExists(sourcefile.c_str()));

    mitk::Image::Pointer image = NULL;

    try
    {
      image = mitk::IOUtil::LoadImage( sourcefile );
    }
    catch (...)
    {
      CPPUNIT_FAIL("Exception during file loading:");
    }

    CPPUNIT_ASSERT_MESSAGE("loaded image not NULL", image.IsNotNull());

    // write ITK .mhd image (2D and 3D only)
    if( image->GetDimension() <= 3 )
    {
      std::ofstream tmpStream;
      std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.mhd");
      tmpStream.close();

      std::string tmpFilePathWithoutExt = tmpFilePath.substr(0, tmpFilePath.size() - 4);

      try
      {
        mitk::IOUtil::Save(image, tmpFilePath);

        mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(tmpFilePath);
        CPPUNIT_ASSERT_MESSAGE("Image stored in MHD format was succesfully loaded again! ", compareImage.IsNotNull());

        CPPUNIT_ASSERT_MESSAGE(".mhd file exists", itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".mhd").c_str()));
        CPPUNIT_ASSERT_MESSAGE(".raw or .zraw exists", itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".raw").c_str()) ||
          itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".zraw").c_str()));

        // delete
        remove(tmpFilePath.c_str());
        remove((tmpFilePathWithoutExt + ".raw").c_str());
        remove((tmpFilePathWithoutExt + ".zraw").c_str());
      }
      catch (...)
      {
        CPPUNIT_FAIL("Exception during.mhd file writing");
      }
    }

    //testing more component image writing as nrrd files

    {
      std::ofstream tmpStream;
      std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.nrrd");
      tmpStream.close();

      try
      {
        mitk::IOUtil::Save(image, tmpFilePath);

        mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(tmpFilePath);
        CPPUNIT_ASSERT_MESSAGE("Image stored in NRRD format was succesfully loaded again", compareImage.IsNotNull());

        remove(tmpFilePath.c_str());
      }
      catch(...)
      {
        std::remove(tmpFilePath.c_str());
        CPPUNIT_FAIL("Exception during.mhd file writing");
      }
    }

    std::ofstream tmpStream;
    std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX");
    tmpStream.close();

    TestPictureWriting(image, tmpFilePath, ".png");
    TestPictureWriting(image, tmpFilePath, ".jpg");
    TestPictureWriting(image, tmpFilePath, ".tiff");
    TestPictureWriting(image, tmpFilePath, ".bmp");
    // always end with this!

  }

  /**
  * Try to write a 3D image with only one plane (a 2D images in disguise for all intents and purposes)
  */
  void TestWrite3DImageWithOnePlane(){
    typedef itk::Image<unsigned char, 3>  ImageType;

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

    ImageType::IndexType start;
    start.Fill(0);

    ImageType::SizeType size;
    size[0] = 100;
    size[1] = 100;
    size[2] = 1;

    ImageType::RegionType region;
    region.SetSize(size);
    region.SetIndex(start);
    itkImage->SetRegions(region);
    itkImage->Allocate();
    itkImage->FillBuffer(0);

    itk::ImageRegionIterator<ImageType> imageIterator(itkImage, itkImage->GetLargestPossibleRegion());

    // Make two squares
    while (!imageIterator.IsAtEnd())
    {
      if ((imageIterator.GetIndex()[0] > 5 && imageIterator.GetIndex()[0] < 20) &&
        (imageIterator.GetIndex()[1] > 5 && imageIterator.GetIndex()[1] < 20))
      {
        imageIterator.Set(255);
      }

      if ((imageIterator.GetIndex()[0] > 50 && imageIterator.GetIndex()[0] < 70) &&
        (imageIterator.GetIndex()[1] > 50 && imageIterator.GetIndex()[1] < 70))
      {
        imageIterator.Set(60);
      }
      ++imageIterator;
    }

    mitk::Image::Pointer image = mitk::ImportItkImage(itkImage);

    mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.nrrd"));
    mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.png"));

  }

  /**
  * Try to write a 3D image with only one plane (a 2D images in disguise for all intents and purposes)
  */
  void TestWrite3DImageWithTwoPlanes(){
    typedef itk::Image<unsigned char, 3>  ImageType;

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

    ImageType::IndexType start;
    start.Fill(0);

    ImageType::SizeType size;
    size[0] = 100;
    size[1] = 100;
    size[2] = 2;

    ImageType::RegionType region;
    region.SetSize(size);
    region.SetIndex(start);
    itkImage->SetRegions(region);
    itkImage->Allocate();
    itkImage->FillBuffer(0);

    itk::ImageRegionIterator<ImageType> imageIterator(itkImage, itkImage->GetLargestPossibleRegion());

    // Make two squares
    while (!imageIterator.IsAtEnd())
    {
      if ((imageIterator.GetIndex()[0] > 5 && imageIterator.GetIndex()[0] < 20) &&
        (imageIterator.GetIndex()[1] > 5 && imageIterator.GetIndex()[1] < 20))
      {
        imageIterator.Set(255);
      }
      if ((imageIterator.GetIndex()[0] > 50 && imageIterator.GetIndex()[0] < 70) &&
        (imageIterator.GetIndex()[1] > 50 && imageIterator.GetIndex()[1] < 70))
      {
        imageIterator.Set(60);
      }
      ++imageIterator;
    }
    mitk::Image::Pointer image = mitk::ImportItkImage(itkImage);

    mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.nrrd"));

    CPPUNIT_ASSERT_THROW(mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.png")), mitk::Exception);

  }

};

MITK_TEST_SUITE_REGISTRATION(mitkItkImageIO)
<|endoftext|>


<commit_before>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

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

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "DigitalInput.h"
#include "board/Board.h"
#include "Variables.h"
#include "database/Database.h"

///
/// \brief Used for buttonPCinc/buttonPCdec messages when each button press/encoder rotation sends incremented or decremented PC value.
/// 16 entries in array are used for 16 MIDI channels.
///
uint8_t     lastPCvalue[16];

///
/// \brief Array holding state for all encoders (whether they're enabled or disabled).
///
uint8_t     encoderEnabled[MAX_NUMBER_OF_ENCODERS/8+1];

///
/// \brief Default constructor.
///
DigitalInput::DigitalInput()
{

}

///
/// \brief Used to store specific parameters from EEPROM to internal arrays for faster access.
///
void DigitalInput::init()
{
    //store some parameters from eeprom to ram for faster access
    for (int i=0; i<MAX_NUMBER_OF_ENCODERS; i++)
    {
        uint8_t arrayIndex = i/8;
        uint8_t encoderIndex = i - 8*arrayIndex;

        BIT_WRITE(encoderEnabled[arrayIndex], encoderIndex, 1);//database.read(DB_BLOCK_ENCODERS, dbSection_encoders_enable, i));
    }

    buttons.init();
    encoders.init();
}

///
/// \brief Checks if encoder is enabled or disabled.
/// @param [in] encoderID    Index of encoder which is being checked.
/// \returns True if encoder is enabled, false otherwise.
///
bool DigitalInput::isEncoderEnabled(uint8_t encoderID)
{
    uint8_t arrayIndex = encoderID/8;
    uint8_t encoderIndex = encoderID - 8*arrayIndex;

    return BIT_READ(encoderEnabled[arrayIndex], encoderIndex);
}

///
/// \brief Used to check if button and encoder data is available.
/// Data source (pins) for both buttons and encoders is same.
///
void DigitalInput::update()
{
    if (!board.digitalInputDataAvailable())
        return;

    buttons.update();
    encoders.update();
}

DigitalInput digitalInput;<commit_msg>remove debug leftovers<commit_after>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

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

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "DigitalInput.h"
#include "board/Board.h"
#include "Variables.h"
#include "database/Database.h"

///
/// \brief Used for buttonPCinc/buttonPCdec messages when each button press/encoder rotation sends incremented or decremented PC value.
/// 16 entries in array are used for 16 MIDI channels.
///
uint8_t     lastPCvalue[16];

///
/// \brief Array holding state for all encoders (whether they're enabled or disabled).
///
uint8_t     encoderEnabled[MAX_NUMBER_OF_ENCODERS/8+1];

///
/// \brief Default constructor.
///
DigitalInput::DigitalInput()
{

}

///
/// \brief Used to store specific parameters from EEPROM to internal arrays for faster access.
///
void DigitalInput::init()
{
    //store some parameters from eeprom to ram for faster access
    for (int i=0; i<MAX_NUMBER_OF_ENCODERS; i++)
    {
        uint8_t arrayIndex = i/8;
        uint8_t encoderIndex = i - 8*arrayIndex;

        BIT_WRITE(encoderEnabled[arrayIndex], encoderIndex, database.read(DB_BLOCK_ENCODERS, dbSection_encoders_enable, i));
    }

    buttons.init();
    encoders.init();
}

///
/// \brief Checks if encoder is enabled or disabled.
/// @param [in] encoderID    Index of encoder which is being checked.
/// \returns True if encoder is enabled, false otherwise.
///
bool DigitalInput::isEncoderEnabled(uint8_t encoderID)
{
    uint8_t arrayIndex = encoderID/8;
    uint8_t encoderIndex = encoderID - 8*arrayIndex;

    return BIT_READ(encoderEnabled[arrayIndex], encoderIndex);
}

///
/// \brief Used to check if button and encoder data is available.
/// Data source (pins) for both buttons and encoders is same.
///
void DigitalInput::update()
{
    if (!board.digitalInputDataAvailable())
        return;

    buttons.update();
    encoders.update();
}

DigitalInput digitalInput;<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: rangeseq.cxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "core_pch.hxx"
#endif

#pragma hdrstop

#include <svtools/zforlist.hxx>
#include <tools/solmath.hxx>

#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>

#include "rangeseq.hxx"
#include "document.hxx"
#include "scmatrix.hxx"

using namespace com::sun::star;

//------------------------------------------------------------------------

long lcl_DoubleToLong( double fVal )
{
    double fInt = (fVal >= 0.0) ? SolarMath::ApproxFloor( fVal ) :
                                  SolarMath::ApproxCeil( fVal );
    if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
        return (long)fInt;
    else
        return 0.0;     // out of range
}

BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    USHORT nTab = rRange.aStart.Tab();
    USHORT nStartCol = rRange.aStart.Col();
    USHORT nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    uno::Sequence< uno::Sequence<INT32> > aRowSeq( nRowCount );
    uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<INT32> aColSeq( nColCount );
        INT32* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
            pColAry[nCol] = lcl_DoubleToLong( pDoc->GetValue(
                ScAddress( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    USHORT nColCount, nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<INT32> > aRowSeq( nRowCount );
    uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
    for (USHORT nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<INT32> aColSeq( nColCount );
        INT32* pColAry = aColSeq.getArray();
        for (USHORT nCol = 0; nCol < nColCount; nCol++)
            if ( pMatrix->IsString( nCol, nRow ) )
                pColAry[nCol] = 0;
            else
                pColAry[nCol] = lcl_DoubleToLong( pMatrix->GetDouble( nCol, nRow ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    USHORT nTab = rRange.aStart.Tab();
    USHORT nStartCol = rRange.aStart.Col();
    USHORT nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
    uno::Sequence<double>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<double> aColSeq( nColCount );
        double* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
            pColAry[nCol] = pDoc->GetValue(
                ScAddress( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    USHORT nColCount, nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
    uno::Sequence<double>* pRowAry = aRowSeq.getArray();
    for (USHORT nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<double> aColSeq( nColCount );
        double* pColAry = aColSeq.getArray();
        for (USHORT nCol = 0; nCol < nColCount; nCol++)
            if ( pMatrix->IsString( nCol, nRow ) )
                pColAry[nCol] = 0.0;
            else
                pColAry[nCol] = pMatrix->GetDouble( nCol, nRow );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    USHORT nTab = rRange.aStart.Tab();
    USHORT nStartCol = rRange.aStart.Col();
    USHORT nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    String aDocStr;

    uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount );
    uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<rtl::OUString> aColSeq( nColCount );
        rtl::OUString* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
        {
            pDoc->GetString( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab, aDocStr );
            pColAry[nCol] = rtl::OUString( aDocStr );
        }
        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, const ScMatrix* pMatrix,
                                            SvNumberFormatter* pFormatter )
{
    if (!pMatrix)
        return FALSE;

    USHORT nColCount, nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount );
    uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
    for (USHORT nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<rtl::OUString> aColSeq( nColCount );
        rtl::OUString* pColAry = aColSeq.getArray();
        for (USHORT nCol = 0; nCol < nColCount; nCol++)
        {
            String aStr;
            if ( pMatrix->IsString( nCol, nRow ) )
            {
                if ( !pMatrix->IsEmpty( nCol, nRow ) )
                    aStr = pMatrix->GetString( nCol, nRow );
            }
            else if ( pFormatter )
            {
                double fVal = pMatrix->GetDouble( nCol, nRow );
                Color* pColor;
                pFormatter->GetOutputString( fVal, 0, aStr, &pColor );
            }
            pColAry[nCol] = rtl::OUString( aStr );
        }

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    USHORT nTab = rRange.aStart.Tab();
    USHORT nStartCol = rRange.aStart.Col();
    USHORT nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    String aDocStr;

    uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
    uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<uno::Any> aColSeq( nColCount );
        uno::Any* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
        {
            if ( pDoc->HasValueData( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) )
                pColAry[nCol] <<= (double) pDoc->GetValue(
                    ScAddress( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) );
            else
            {
                pDoc->GetString( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab, aDocStr );
                pColAry[nCol] <<= rtl::OUString( aDocStr );
            }
        }
        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    USHORT nColCount, nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
    uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
    for (USHORT nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<uno::Any> aColSeq( nColCount );
        uno::Any* pColAry = aColSeq.getArray();
        for (USHORT nCol = 0; nCol < nColCount; nCol++)
        {
            if ( pMatrix->IsString( nCol, nRow ) )
            {
                String aStr;
                if ( !pMatrix->IsEmpty( nCol, nRow ) )
                    aStr = pMatrix->GetString( nCol, nRow );
                pColAry[nCol] <<= rtl::OUString( aStr );
            }
            else
                pColAry[nCol] <<= (double) pMatrix->GetDouble( nCol, nRow );
        }

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

<commit_msg>#79625# FillMixedArray: handling of formula errors<commit_after>/*************************************************************************
 *
 *  $RCSfile: rangeseq.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: nn $ $Date: 2000-10-18 18:23:33 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "core_pch.hxx"
#endif

#pragma hdrstop

#include <svtools/zforlist.hxx>
#include <tools/solmath.hxx>
#include <tools/debug.hxx>

#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>

#include "rangeseq.hxx"
#include "document.hxx"
#include "scmatrix.hxx"
#include "cell.hxx"

using namespace com::sun::star;

//------------------------------------------------------------------------

long lcl_DoubleToLong( double fVal )
{
    double fInt = (fVal >= 0.0) ? SolarMath::ApproxFloor( fVal ) :
                                  SolarMath::ApproxCeil( fVal );
    if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
        return (long)fInt;
    else
        return 0.0;     // out of range
}

BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    USHORT nTab = rRange.aStart.Tab();
    USHORT nStartCol = rRange.aStart.Col();
    USHORT nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    uno::Sequence< uno::Sequence<INT32> > aRowSeq( nRowCount );
    uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<INT32> aColSeq( nColCount );
        INT32* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
            pColAry[nCol] = lcl_DoubleToLong( pDoc->GetValue(
                ScAddress( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    USHORT nColCount, nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<INT32> > aRowSeq( nRowCount );
    uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
    for (USHORT nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<INT32> aColSeq( nColCount );
        INT32* pColAry = aColSeq.getArray();
        for (USHORT nCol = 0; nCol < nColCount; nCol++)
            if ( pMatrix->IsString( nCol, nRow ) )
                pColAry[nCol] = 0;
            else
                pColAry[nCol] = lcl_DoubleToLong( pMatrix->GetDouble( nCol, nRow ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    USHORT nTab = rRange.aStart.Tab();
    USHORT nStartCol = rRange.aStart.Col();
    USHORT nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
    uno::Sequence<double>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<double> aColSeq( nColCount );
        double* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
            pColAry[nCol] = pDoc->GetValue(
                ScAddress( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    USHORT nColCount, nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
    uno::Sequence<double>* pRowAry = aRowSeq.getArray();
    for (USHORT nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<double> aColSeq( nColCount );
        double* pColAry = aColSeq.getArray();
        for (USHORT nCol = 0; nCol < nColCount; nCol++)
            if ( pMatrix->IsString( nCol, nRow ) )
                pColAry[nCol] = 0.0;
            else
                pColAry[nCol] = pMatrix->GetDouble( nCol, nRow );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    USHORT nTab = rRange.aStart.Tab();
    USHORT nStartCol = rRange.aStart.Col();
    USHORT nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    String aDocStr;

    uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount );
    uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<rtl::OUString> aColSeq( nColCount );
        rtl::OUString* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
        {
            pDoc->GetString( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab, aDocStr );
            pColAry[nCol] = rtl::OUString( aDocStr );
        }
        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, const ScMatrix* pMatrix,
                                            SvNumberFormatter* pFormatter )
{
    if (!pMatrix)
        return FALSE;

    USHORT nColCount, nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount );
    uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
    for (USHORT nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<rtl::OUString> aColSeq( nColCount );
        rtl::OUString* pColAry = aColSeq.getArray();
        for (USHORT nCol = 0; nCol < nColCount; nCol++)
        {
            String aStr;
            if ( pMatrix->IsString( nCol, nRow ) )
            {
                if ( !pMatrix->IsEmpty( nCol, nRow ) )
                    aStr = pMatrix->GetString( nCol, nRow );
            }
            else if ( pFormatter )
            {
                double fVal = pMatrix->GetDouble( nCol, nRow );
                Color* pColor;
                pFormatter->GetOutputString( fVal, 0, aStr, &pColor );
            }
            pColAry[nCol] = rtl::OUString( aStr );
        }

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

double lcl_GetValueFromCell( ScBaseCell& rCell )
{
    //! ScBaseCell member function?

    CellType eType = rCell.GetCellType();
    if ( eType == CELLTYPE_VALUE )
        return ((ScValueCell&)rCell).GetValue();
    else if ( eType == CELLTYPE_FORMULA )
        return ((ScFormulaCell&)rCell).GetValue();      // called only if result is value

    DBG_ERROR( "GetValueFromCell: wrong type" );
    return 0;
}

BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange,
                                        BOOL bAllowNV )
{
    USHORT nTab = rRange.aStart.Tab();
    USHORT nStartCol = rRange.aStart.Col();
    USHORT nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    String aDocStr;
    BOOL bHasErrors = FALSE;

    uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
    uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<uno::Any> aColSeq( nColCount );
        uno::Any* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
        {
            uno::Any& rElement = pColAry[nCol];

            ScAddress aPos( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab );
            ScBaseCell* pCell = pDoc->GetCell( aPos );
            if ( pCell )
            {
                if ( pCell->GetCellType() == CELLTYPE_FORMULA &&
                        ((ScFormulaCell*)pCell)->GetErrCode() != 0 )
                {
                    // if NV is allowed, leave empty for errors
                    bHasErrors = TRUE;
                }
                else if ( pCell->HasValueData() )
                    rElement <<= (double) lcl_GetValueFromCell( *pCell );
                else
                    rElement <<= rtl::OUString( pCell->GetStringData() );
            }
            else
                rElement <<= rtl::OUString();       // empty: empty string
        }
        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return bAllowNV || !bHasErrors;
}

BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    USHORT nColCount, nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
    uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
    for (USHORT nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<uno::Any> aColSeq( nColCount );
        uno::Any* pColAry = aColSeq.getArray();
        for (USHORT nCol = 0; nCol < nColCount; nCol++)
        {
            if ( pMatrix->IsString( nCol, nRow ) )
            {
                String aStr;
                if ( !pMatrix->IsEmpty( nCol, nRow ) )
                    aStr = pMatrix->GetString( nCol, nRow );
                pColAry[nCol] <<= rtl::OUString( aStr );
            }
            else
                pColAry[nCol] <<= (double) pMatrix->GetDouble( nCol, nRow );
        }

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: userlist.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: ihi $ $Date: 2006-08-04 11:34:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

//------------------------------------------------------------------------

#include <unotools/charclass.hxx>
#include <string.h>

#include "global.hxx"
#include "userlist.hxx"

#ifndef _UNOTOOLS_LOCALEDATAWRAPPER_HXX
#include <unotools/localedatawrapper.hxx>
#endif
#ifndef _UNOTOOLS_CALENDARWRAPPER_HXX
#include <unotools/calendarwrapper.hxx>
#endif
#ifndef _UNOTOOLS_TRANSLITERATIONWRAPPER_HXX
#include <unotools/transliterationwrapper.hxx>
#endif

// STATIC DATA -----------------------------------------------------------

//------------------------------------------------------------------------

void ScUserListData::InitTokens()
{
    sal_Unicode cSep = ScGlobal::cListDelimiter;
    nTokenCount = (USHORT) aStr.GetTokenCount(cSep);
    if (nTokenCount)
    {
        pSubStrings = new String[nTokenCount];
        pUpperSub   = new String[nTokenCount];
        for (USHORT i=0; i<nTokenCount; i++)
        {
            pUpperSub[i] = pSubStrings[i] = aStr.GetToken((xub_StrLen)i,cSep);
            ScGlobal::pCharClass->toUpper(pUpperSub[i]);
        }
    }
    else
        pSubStrings = pUpperSub = NULL;
}

ScUserListData::ScUserListData(const String& rStr) :
    aStr(rStr)
{
    InitTokens();
}

ScUserListData::ScUserListData(const ScUserListData& rData) :
    aStr(rData.aStr)
{
    InitTokens();
}

__EXPORT ScUserListData::~ScUserListData()
{
    delete[] pSubStrings;
    delete[] pUpperSub;
}

ScUserListData::ScUserListData( SvStream& rStream )
{
    rStream.ReadByteString( aStr, rStream.GetStreamCharSet() );
    InitTokens();
}

BOOL ScUserListData::Store( SvStream& rStream ) const
{
    rStream.WriteByteString( aStr, rStream.GetStreamCharSet() );
    return TRUE;
}

void ScUserListData::SetString( const String& rStr )
{
    delete[] pSubStrings;
    delete[] pUpperSub;

    aStr = rStr;
    InitTokens();
}

USHORT ScUserListData::GetSubCount() const
{
    return nTokenCount;
}

BOOL ScUserListData::GetSubIndex(const String& rSubStr, USHORT& rIndex) const
{
    USHORT i;
    for (i=0; i<nTokenCount; i++)
        if (rSubStr == pSubStrings[i])
        {
            rIndex = i;
            return TRUE;
        }

    String aUpStr = rSubStr;
    ScGlobal::pCharClass->toUpper(aUpStr);
    for (i=0; i<nTokenCount; i++)
        if (aUpStr == pUpperSub[i])
        {
            rIndex = i;
            return TRUE;
        }

    return FALSE;
}

String ScUserListData::GetSubStr(USHORT nIndex) const
{
    if (nIndex < nTokenCount)
        return pSubStrings[nIndex];
    else
        return EMPTY_STRING;
}

StringCompare ScUserListData::Compare(const String& rSubStr1, const String& rSubStr2) const
{
    USHORT nIndex1;
    USHORT nIndex2;
    BOOL bFound1 = GetSubIndex(rSubStr1, nIndex1);
    BOOL bFound2 = GetSubIndex(rSubStr2, nIndex2);
    if (bFound1)
    {
        if (bFound2)
        {
            if (nIndex1 < nIndex2)
                return COMPARE_LESS;
            else if (nIndex1 > nIndex2)
                return COMPARE_GREATER;
            else
                return COMPARE_EQUAL;
        }
        else
            return COMPARE_LESS;
    }
    else if (bFound2)
        return COMPARE_GREATER;
    else
        return (StringCompare) ScGlobal::pCaseTransliteration->compareString( rSubStr1, rSubStr2 );
}

StringCompare ScUserListData::ICompare(const String& rSubStr1, const String& rSubStr2) const
{
    USHORT nIndex1;
    USHORT nIndex2;
    BOOL bFound1 = GetSubIndex(rSubStr1, nIndex1);
    BOOL bFound2 = GetSubIndex(rSubStr2, nIndex2);
    if (bFound1)
    {
        if (bFound2)
        {
            if (nIndex1 < nIndex2)
                return COMPARE_LESS;
            else if (nIndex1 > nIndex2)
                return COMPARE_GREATER;
            else
                return COMPARE_EQUAL;
        }
        else
            return COMPARE_LESS;
    }
    else if (bFound2)
        return COMPARE_GREATER;
    else
        return (StringCompare) ScGlobal::pTransliteration->compareString( rSubStr1, rSubStr2 );
}

ScUserList::ScUserList(USHORT nLim, USHORT nDel) :
    Collection  ( nLim, nDel )
{
    using namespace ::com::sun::star;

    sal_Unicode cDelimiter = ScGlobal::cListDelimiter;
    uno::Sequence< i18n::CalendarItem > xCal;

    uno::Sequence< i18n::Calendar > xCalendars(
            ScGlobal::pLocaleData->getAllCalendars() );

    for ( sal_Int32 j = 0; j < xCalendars.getLength(); ++j )
    {
        xCal = xCalendars[j].Days;
        if ( xCal.getLength() )
        {
            String sDayShort, sDayLong;
            sal_Int32 i;
            sal_Int32 nLen = xCal.getLength();
            rtl::OUString sStart = xCalendars[j].StartOfWeek;
            sal_Int16 nStart = nLen;
            while (nStart > 0)
            {
                if (xCal[--nStart].ID == sStart)
                    break;
            }
            sal_Int16 nLast = (nStart + nLen - 1) % nLen;
            for (i = nStart; i != nLast; i = (i+1) % nLen)
            {
                sDayShort += String( xCal[i].AbbrevName );
                sDayShort += cDelimiter;
                sDayLong  += String( xCal[i].FullName );
                sDayLong  += cDelimiter;
            }
            sDayShort += String( xCal[i].AbbrevName );
            sDayLong  += String( xCal[i].FullName );

            if ( !HasEntry( sDayShort ) )
                Insert( new ScUserListData( sDayShort ));
            if ( !HasEntry( sDayLong ) )
                Insert( new ScUserListData( sDayLong ));
        }

        xCal = xCalendars[j].Months;
        if ( xCal.getLength() )
        {
            String sMonthShort, sMonthLong;
            sal_Int32 i;
            sal_Int32 nLen = xCal.getLength() - 1;
            for (i = 0; i < nLen; i++)
            {
                sMonthShort += String( xCal[i].AbbrevName );
                sMonthShort += cDelimiter;
                sMonthLong  += String( xCal[i].FullName );
                sMonthLong  += cDelimiter;
            }
            sMonthShort += String( xCal[i].AbbrevName );
            sMonthLong  += String( xCal[i].FullName );

            if ( !HasEntry( sMonthShort ) )
                Insert( new ScUserListData( sMonthShort ));
            if ( !HasEntry( sMonthLong ) )
                Insert( new ScUserListData( sMonthLong ));
        }
    }
}

BOOL ScUserList::Load( SvStream& rStream )
{
    BOOL    bSuccess = TRUE;
    USHORT  nNewCount;

    while( nCount > 0 )
        AtFree(0);                  // alles loeschen

    rStream >> nNewCount;

    for ( USHORT i=0; i<nNewCount && bSuccess; i++ )
        Insert( new ScUserListData( rStream ) );

    return bSuccess;
}

BOOL ScUserList::Store( SvStream& rStream ) const
{
    BOOL bSuccess = TRUE;

    rStream << nCount;

    for ( USHORT i=0; i<nCount && bSuccess; i++ )
        bSuccess = ((const ScUserListData*)At(i))->Store( rStream );

    return bSuccess;
}

DataObject* ScUserList::Clone() const
{
    return ( new ScUserList( *this ) );
}

ScUserListData* ScUserList::GetData(const String& rSubStr) const
{
    USHORT  nIndex;
    USHORT  i = 0;
    for (i=0; i < nCount; i++)
        if (((ScUserListData*)pItems[i])->GetSubIndex(rSubStr, nIndex))
            return (ScUserListData*)pItems[i];
    return NULL;
}

BOOL ScUserList::operator==( const ScUserList& r ) const
{
    BOOL bEqual = (nCount == r.nCount);

    if ( bEqual )
    {
        ScUserListData* pMyData    = NULL;
        ScUserListData* pOtherData = NULL;

        for ( USHORT i=0; i<nCount && bEqual; i++)
        {
            pMyData    = (ScUserListData*)At(i);
            pOtherData = (ScUserListData*)r.At(i);

            bEqual =(   (pMyData->nTokenCount == pOtherData->nTokenCount)
                     && (pMyData->aStr        == pOtherData->aStr) );
        }
    }

    return bEqual;
}

BOOL ScUserList::HasEntry( const String& rStr ) const
{
    for ( USHORT i=0; i<nCount; i++)
    {
        const ScUserListData* pMyData = (ScUserListData*) At(i);
        if ( pMyData->aStr == rStr )
            return TRUE;
    }
    return FALSE;
}

<commit_msg>INTEGRATION: CWS calcwarnings (1.9.88); FILE MERGED 2006/12/06 13:34:23 nn 1.9.88.2: #i69284# warning-free: core, unxlngi6 2006/11/28 13:24:50 nn 1.9.88.1: #i69284# warning-free: core, wntmsci10<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: userlist.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: vg $ $Date: 2007-02-27 12:20:03 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

//------------------------------------------------------------------------

#include <unotools/charclass.hxx>
#include <string.h>

#include "global.hxx"
#include "userlist.hxx"

#ifndef _UNOTOOLS_LOCALEDATAWRAPPER_HXX
#include <unotools/localedatawrapper.hxx>
#endif
#ifndef _UNOTOOLS_CALENDARWRAPPER_HXX
#include <unotools/calendarwrapper.hxx>
#endif
#ifndef _UNOTOOLS_TRANSLITERATIONWRAPPER_HXX
#include <unotools/transliterationwrapper.hxx>
#endif

// STATIC DATA -----------------------------------------------------------

//------------------------------------------------------------------------

void ScUserListData::InitTokens()
{
    sal_Unicode cSep = ScGlobal::cListDelimiter;
    nTokenCount = (USHORT) aStr.GetTokenCount(cSep);
    if (nTokenCount)
    {
        pSubStrings = new String[nTokenCount];
        pUpperSub   = new String[nTokenCount];
        for (USHORT i=0; i<nTokenCount; i++)
        {
            pUpperSub[i] = pSubStrings[i] = aStr.GetToken((xub_StrLen)i,cSep);
            ScGlobal::pCharClass->toUpper(pUpperSub[i]);
        }
    }
    else
        pSubStrings = pUpperSub = NULL;
}

ScUserListData::ScUserListData(const String& rStr) :
    aStr(rStr)
{
    InitTokens();
}

ScUserListData::ScUserListData(const ScUserListData& rData) :
    DataObject(),
    aStr(rData.aStr)
{
    InitTokens();
}

__EXPORT ScUserListData::~ScUserListData()
{
    delete[] pSubStrings;
    delete[] pUpperSub;
}

ScUserListData::ScUserListData( SvStream& rStream )
{
    rStream.ReadByteString( aStr, rStream.GetStreamCharSet() );
    InitTokens();
}

BOOL ScUserListData::Store( SvStream& rStream ) const
{
    rStream.WriteByteString( aStr, rStream.GetStreamCharSet() );
    return TRUE;
}

void ScUserListData::SetString( const String& rStr )
{
    delete[] pSubStrings;
    delete[] pUpperSub;

    aStr = rStr;
    InitTokens();
}

USHORT ScUserListData::GetSubCount() const
{
    return nTokenCount;
}

BOOL ScUserListData::GetSubIndex(const String& rSubStr, USHORT& rIndex) const
{
    USHORT i;
    for (i=0; i<nTokenCount; i++)
        if (rSubStr == pSubStrings[i])
        {
            rIndex = i;
            return TRUE;
        }

    String aUpStr = rSubStr;
    ScGlobal::pCharClass->toUpper(aUpStr);
    for (i=0; i<nTokenCount; i++)
        if (aUpStr == pUpperSub[i])
        {
            rIndex = i;
            return TRUE;
        }

    return FALSE;
}

String ScUserListData::GetSubStr(USHORT nIndex) const
{
    if (nIndex < nTokenCount)
        return pSubStrings[nIndex];
    else
        return EMPTY_STRING;
}

StringCompare ScUserListData::Compare(const String& rSubStr1, const String& rSubStr2) const
{
    USHORT nIndex1;
    USHORT nIndex2;
    BOOL bFound1 = GetSubIndex(rSubStr1, nIndex1);
    BOOL bFound2 = GetSubIndex(rSubStr2, nIndex2);
    if (bFound1)
    {
        if (bFound2)
        {
            if (nIndex1 < nIndex2)
                return COMPARE_LESS;
            else if (nIndex1 > nIndex2)
                return COMPARE_GREATER;
            else
                return COMPARE_EQUAL;
        }
        else
            return COMPARE_LESS;
    }
    else if (bFound2)
        return COMPARE_GREATER;
    else
        return (StringCompare) ScGlobal::pCaseTransliteration->compareString( rSubStr1, rSubStr2 );
}

StringCompare ScUserListData::ICompare(const String& rSubStr1, const String& rSubStr2) const
{
    USHORT nIndex1;
    USHORT nIndex2;
    BOOL bFound1 = GetSubIndex(rSubStr1, nIndex1);
    BOOL bFound2 = GetSubIndex(rSubStr2, nIndex2);
    if (bFound1)
    {
        if (bFound2)
        {
            if (nIndex1 < nIndex2)
                return COMPARE_LESS;
            else if (nIndex1 > nIndex2)
                return COMPARE_GREATER;
            else
                return COMPARE_EQUAL;
        }
        else
            return COMPARE_LESS;
    }
    else if (bFound2)
        return COMPARE_GREATER;
    else
        return (StringCompare) ScGlobal::pTransliteration->compareString( rSubStr1, rSubStr2 );
}

ScUserList::ScUserList(USHORT nLim, USHORT nDel) :
    Collection  ( nLim, nDel )
{
    using namespace ::com::sun::star;

    sal_Unicode cDelimiter = ScGlobal::cListDelimiter;
    uno::Sequence< i18n::CalendarItem > xCal;

    uno::Sequence< i18n::Calendar > xCalendars(
            ScGlobal::pLocaleData->getAllCalendars() );

    for ( sal_Int32 j = 0; j < xCalendars.getLength(); ++j )
    {
        xCal = xCalendars[j].Days;
        if ( xCal.getLength() )
        {
            String sDayShort, sDayLong;
            sal_Int32 i;
            sal_Int32 nLen = xCal.getLength();
            rtl::OUString sStart = xCalendars[j].StartOfWeek;
            sal_Int16 nStart = sal::static_int_cast<sal_Int16>(nLen);
            while (nStart > 0)
            {
                if (xCal[--nStart].ID == sStart)
                    break;
            }
            sal_Int16 nLast = sal::static_int_cast<sal_Int16>( (nStart + nLen - 1) % nLen );
            for (i = nStart; i != nLast; i = (i+1) % nLen)
            {
                sDayShort += String( xCal[i].AbbrevName );
                sDayShort += cDelimiter;
                sDayLong  += String( xCal[i].FullName );
                sDayLong  += cDelimiter;
            }
            sDayShort += String( xCal[i].AbbrevName );
            sDayLong  += String( xCal[i].FullName );

            if ( !HasEntry( sDayShort ) )
                Insert( new ScUserListData( sDayShort ));
            if ( !HasEntry( sDayLong ) )
                Insert( new ScUserListData( sDayLong ));
        }

        xCal = xCalendars[j].Months;
        if ( xCal.getLength() )
        {
            String sMonthShort, sMonthLong;
            sal_Int32 i;
            sal_Int32 nLen = xCal.getLength() - 1;
            for (i = 0; i < nLen; i++)
            {
                sMonthShort += String( xCal[i].AbbrevName );
                sMonthShort += cDelimiter;
                sMonthLong  += String( xCal[i].FullName );
                sMonthLong  += cDelimiter;
            }
            sMonthShort += String( xCal[i].AbbrevName );
            sMonthLong  += String( xCal[i].FullName );

            if ( !HasEntry( sMonthShort ) )
                Insert( new ScUserListData( sMonthShort ));
            if ( !HasEntry( sMonthLong ) )
                Insert( new ScUserListData( sMonthLong ));
        }
    }
}

BOOL ScUserList::Load( SvStream& rStream )
{
    BOOL    bSuccess = TRUE;
    USHORT  nNewCount;

    while( nCount > 0 )
        AtFree(0);                  // alles loeschen

    rStream >> nNewCount;

    for ( USHORT i=0; i<nNewCount && bSuccess; i++ )
        Insert( new ScUserListData( rStream ) );

    return bSuccess;
}

BOOL ScUserList::Store( SvStream& rStream ) const
{
    BOOL bSuccess = TRUE;

    rStream << nCount;

    for ( USHORT i=0; i<nCount && bSuccess; i++ )
        bSuccess = ((const ScUserListData*)At(i))->Store( rStream );

    return bSuccess;
}

DataObject* ScUserList::Clone() const
{
    return ( new ScUserList( *this ) );
}

ScUserListData* ScUserList::GetData(const String& rSubStr) const
{
    USHORT  nIndex;
    USHORT  i = 0;
    for (i=0; i < nCount; i++)
        if (((ScUserListData*)pItems[i])->GetSubIndex(rSubStr, nIndex))
            return (ScUserListData*)pItems[i];
    return NULL;
}

BOOL ScUserList::operator==( const ScUserList& r ) const
{
    BOOL bEqual = (nCount == r.nCount);

    if ( bEqual )
    {
        ScUserListData* pMyData    = NULL;
        ScUserListData* pOtherData = NULL;

        for ( USHORT i=0; i<nCount && bEqual; i++)
        {
            pMyData    = (ScUserListData*)At(i);
            pOtherData = (ScUserListData*)r.At(i);

            bEqual =(   (pMyData->nTokenCount == pOtherData->nTokenCount)
                     && (pMyData->aStr        == pOtherData->aStr) );
        }
    }

    return bEqual;
}

BOOL ScUserList::HasEntry( const String& rStr ) const
{
    for ( USHORT i=0; i<nCount; i++)
    {
        const ScUserListData* pMyData = (ScUserListData*) At(i);
        if ( pMyData->aStr == rStr )
            return TRUE;
    }
    return FALSE;
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#include "couchbase.h"
#include <cstring>
#include <cstdio>
#include <cassert>

using namespace Couchnode;
using namespace std;

static bool get_string(const v8::Handle<v8::Value> &jv,
                       char **strp,
                       size_t *szp)
{
    if (!jv->IsString()) {
#ifdef COUCHNODE_DEBUG
        printf("Not a string..\n");
#endif
        return false;
    }

    v8::Local<v8::String> s = jv->ToString();
    *szp = s->Length();
    if (!*szp) {
        return false;
    }

    *strp = new char[*szp];
    s->WriteAscii(*strp, 0, *szp, v8::String::NO_NULL_TERMINATION);
    return true;
}

#define GET_DPARAM(lval, bidx) \
    if (!dict.IsEmpty()) { \
        lval = dict->Get(NameMap::names[NameMap::##bidx]); \
    }

CommonArgs::CommonArgs(const v8::Arguments &argv, int pmax, int reqmax)
    : args(argv), key(NULL), params_max(pmax), required_max(reqmax), stale(false)
{
}

bool CommonArgs::parse()
{
    if (use_dictparams) {
        if (args.Length() < required_max + 2) {
            throw Couchnode::Exception("Bad arguments");
        }
        if (args.Length() == required_max + 3) {
            if (!args[required_max + 2]->IsObject()) {
                throw Couchnode::Exception(
                    "Have last argument, but it's not an Object",
                    args[required_max + 2]);
            }
            dict = args[required_max + 2]->ToObject();
        }
    } else if (args.Length() < (params_max + 2)) {
        throw Couchnode::Exception("Bad arguments");
    }

    if (!extractKey()) {
        return false;
    }

    if (!extractUdata()) {
        return false;
    }
    return true;
}

bool CommonArgs::extractKey()
{
    if (!get_string(args[0], &key, &nkey)) {
#ifdef COUCHNODE_DEBUG
        printf("Arg at pos %d\n", 0);
#endif
        throw Couchnode::Exception("Couldn't extract string");
    }
    return true;
}

bool CommonArgs::extractUdata()
{
    // { "key", .. params_max ..., function() { .. }, "Data" }
    // Index should be 1 + params_max

    int ix;
    if (use_dictparams) {
        ix = required_max + 1;
    } else {
        ix = params_max + 1;
    }

    ucb = v8::Local<v8::Function>::Cast(args[ix]);
    if (!ucb->IsFunction()) {
#ifdef COUCHNODE_DEBUG
        printf("Not a function at index %d\n", ix);
#endif
        throw Couchnode::Exception("Not a function", args[ix]);
    }

    getParam(ix + 1, NameMap::DATA, &udata);
    return true;
}

void CommonArgs::extractCas(const v8::Handle<v8::Value> &arg,
                            libcouchbase_cas_t *cas)
{
    if (arg.IsEmpty() || arg->IsUndefined()) {
        *cas = 0;
    } else if (arg->IsObject()) {
        *cas = Cas::GetCas(arg->ToObject());
    } else {
        throw Couchnode::Exception("Couldn't parse CAS", arg);
    }
}

void CommonArgs::extractExpiry(const v8::Handle<v8::Value> &arg, time_t *exp)
{
    if (arg.IsEmpty() || arg->IsUndefined()) {
        *exp = 0;
    } else if (arg->IsNumber()) {
        *exp = arg->Uint32Value();
    } else {
        throw Couchnode::Exception("Couldn't extract expiration", arg);
    }
}

CouchbaseCookie *CommonArgs::makeCookie()
{
    return new CouchbaseCookie(args.This(), ucb, udata, 1);
}

void CommonArgs::bailout(CouchbaseCookie *cookie, libcouchbase_error_t err)
{
    cookie->result(err, key, nkey);
}

CommonArgs::~CommonArgs()
{
    if (stale) {
        return;
    }

    if (key) {
        delete[] key;
        key = NULL;
    }
}

// store(key, value, exp, cas, cb, data)
StorageArgs::StorageArgs(const v8::Arguments &argv, int vparams)
    : CommonArgs(argv, vparams + 3, 1),

      data(NULL), ndata(0), exp(0), cas(0)
{
}

bool StorageArgs::parse()
{

    if (!CommonArgs::parse()) {
        return false;
    }

    if (!extractValue()) {
        return false;
    }

    v8::Local<v8::Value> arg_exp, arg_cas;
    getParam(params_max, NameMap::CAS, &arg_cas);
    getParam(params_max - 1, NameMap::EXPIRY, &arg_exp);

    extractExpiry(arg_exp, &exp);
    extractCas(arg_cas, &cas);
    return true;
}

bool StorageArgs::extractValue()
{
    if (!get_string(args[1], &data, &ndata)) {
        throw Couchnode::Exception("Bad value", args[1]);
    }

    return true;
}

StorageArgs::~StorageArgs()
{
    if (stale) {
        return;
    }

    if (data) {
        delete[] data;
        data = NULL;
    }
}

MGetArgs::MGetArgs(const v8::Arguments &args, int nkparams)
    : CommonArgs(args, nkparams),
      kcount(0), single_exp(0), keys(NULL), sizes(NULL), exps(NULL)
{
}

bool MGetArgs::extractKey()
{

    if (args[0]->IsString()) {
        if (!CommonArgs::extractKey()) {
            return false;
        }

        kcount = 1;
        v8::Local<v8::Value> arg_exp;
        getParam(1, NameMap::EXPIRY, &arg_exp);

        extractExpiry(arg_exp, &single_exp);
        assert(key);

        keys = &key;
        sizes = &nkey;

        if (single_exp) {
            exps = &single_exp;
        }

        return true;
    }

    exps = NULL;

    if (!args[0]->IsArray()) {
        return false;
    }

    v8::Local<v8::Array> karry = v8::Local<v8::Array>::Cast(args[0]);
    kcount = karry->Length();

    keys = new char*[kcount];
    sizes = new size_t[kcount];

    memset(keys, 0, sizeof(char *) * kcount);
    memset(sizes, 0, sizeof(size_t) * kcount);

    for (unsigned ii = 0; ii < karry->Length(); ii++) {
        if (!get_string(karry->Get(ii), keys + ii, sizes + ii)) {
            return false;
        }
    }
    return true;
}

void MGetArgs::bailout(CouchbaseCookie *cookie, libcouchbase_error_t err)
{
    for (unsigned ii = 0; ii < kcount; ii++) {
        cookie->result(err, keys[ii], sizes[ii]);
    }
}

MGetArgs::~MGetArgs()
{
    if (stale) {
        return;
    }

    if (exps && exps != &single_exp) {
        delete[] exps;
    }

    if (sizes && sizes != &nkey) {
        delete[] sizes;
    }

    if (keys && keys != &key) {
        for (unsigned ii = 0; ii < kcount; ii++) {
            delete[] keys[ii];
        }
        delete[] keys;
    }

    exps = NULL;
    sizes = NULL;
    keys = NULL;
}

KeyopArgs::KeyopArgs(const v8::Arguments &args)
    : CommonArgs(args, 1), cas(0)
{
}

bool KeyopArgs::parse()
{
    if (!CommonArgs::parse()) {
        return false;
    }

    v8::Local<v8::Value> arg_cas;
    getParam(1, NameMap::CAS, &arg_cas);

    extractCas(arg_cas, &cas);
    return true;
}

// arithmetic(key, delta, initial, exp, cas, ...)
ArithmeticArgs::ArithmeticArgs(const v8::Arguments &args)
    : StorageArgs(args, 1),
      delta(0), initial(0), create(false)
{
}

bool ArithmeticArgs::extractValue()
{
    if (args[1]->IsNumber() == false) {
        throw Couchnode::Exception("Delta must be numeric", args[1]);
    }

    delta = args[1]->IntegerValue();

    v8::Local<v8::Value> arg_initial;
    getParam(2, NameMap::INITIAL, &arg_initial);

    if (!arg_initial.IsEmpty()) {
        if (arg_initial->IsNumber()) {
            initial = arg_initial->IntegerValue();
            create = true;
        } else {
            if (!arg_initial->IsUndefined()) {
                throw Couchnode::Exception("Initial value must be numeric",
                                           arg_initial);
            }
            create = false;
        }

    } else {
        create = false;
    }

    return true;
}
<commit_msg>Make cas/expiry parsing more tolerant of false-ish values<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#include "couchbase.h"
#include <cstring>
#include <cstdio>
#include <cassert>

using namespace Couchnode;
using namespace std;

static bool get_string(const v8::Handle<v8::Value> &jv,
                       char **strp,
                       size_t *szp)
{
    if (!jv->IsString()) {
#ifdef COUCHNODE_DEBUG
        printf("Not a string..\n");
#endif
        return false;
    }

    v8::Local<v8::String> s = jv->ToString();
    *szp = s->Length();
    if (!*szp) {
        return false;
    }

    *strp = new char[*szp];
    s->WriteAscii(*strp, 0, *szp, v8::String::NO_NULL_TERMINATION);
    return true;
}

#define GET_DPARAM(lval, bidx) \
    if (!dict.IsEmpty()) { \
        lval = dict->Get(NameMap::names[NameMap::##bidx]); \
    }

static inline bool isFalseValue(const v8::Handle<v8::Value> &v)
{
    return (v.IsEmpty() || v->BooleanValue() == false);
}

CommonArgs::CommonArgs(const v8::Arguments &argv, int pmax, int reqmax)
    : args(argv), key(NULL), params_max(pmax), required_max(reqmax), stale(false)
{
}

bool CommonArgs::parse()
{
    if (use_dictparams) {
        if (args.Length() < required_max + 2) {
            throw Couchnode::Exception("Bad arguments");
        }
        if (args.Length() == required_max + 3) {
            if (!args[required_max + 2]->IsObject()) {
                throw Couchnode::Exception(
                    "Have last argument, but it's not an Object",
                    args[required_max + 2]);
            }
            dict = args[required_max + 2]->ToObject();
        }
    } else if (args.Length() < (params_max + 2)) {
        throw Couchnode::Exception("Bad arguments");
    }

    if (!extractKey()) {
        return false;
    }

    if (!extractUdata()) {
        return false;
    }
    return true;
}

bool CommonArgs::extractKey()
{
    if (!get_string(args[0], &key, &nkey)) {
#ifdef COUCHNODE_DEBUG
        printf("Arg at pos %d\n", 0);
#endif
        throw Couchnode::Exception("Couldn't extract string");
    }
    return true;
}

bool CommonArgs::extractUdata()
{
    // { "key", .. params_max ..., function() { .. }, "Data" }
    // Index should be 1 + params_max

    int ix;
    if (use_dictparams) {
        ix = required_max + 1;
    } else {
        ix = params_max + 1;
    }

    ucb = v8::Local<v8::Function>::Cast(args[ix]);
    if (!ucb->IsFunction()) {
#ifdef COUCHNODE_DEBUG
        printf("Not a function at index %d\n", ix);
#endif
        throw Couchnode::Exception("Not a function", args[ix]);
    }

    getParam(ix + 1, NameMap::DATA, &udata);
    return true;
}

void CommonArgs::extractCas(const v8::Handle<v8::Value> &arg,
                            libcouchbase_cas_t *cas)
{
    if (isFalseValue(arg)) {
        *cas = 0;
    } else if (arg->IsObject()) {
        *cas = Cas::GetCas(arg->ToObject());
    } else {
        throw Couchnode::Exception("Couldn't parse CAS", arg);
    }
}

void CommonArgs::extractExpiry(const v8::Handle<v8::Value> &arg, time_t *exp)
{
    if (isFalseValue(arg)) {
        *exp = 0;
    } else if (arg->IsNumber()) {
        *exp = arg->Uint32Value();
    } else {
        throw Couchnode::Exception("Couldn't extract expiration", arg);
    }
}

CouchbaseCookie *CommonArgs::makeCookie()
{
    return new CouchbaseCookie(args.This(), ucb, udata, 1);
}

void CommonArgs::bailout(CouchbaseCookie *cookie, libcouchbase_error_t err)
{
    cookie->result(err, key, nkey);
}

CommonArgs::~CommonArgs()
{
    if (stale) {
        return;
    }

    if (key) {
        delete[] key;
        key = NULL;
    }
}

// store(key, value, exp, cas, cb, data)
StorageArgs::StorageArgs(const v8::Arguments &argv, int vparams)
    : CommonArgs(argv, vparams + 3, 1),

      data(NULL), ndata(0), exp(0), cas(0)
{
}

bool StorageArgs::parse()
{

    if (!CommonArgs::parse()) {
        return false;
    }

    if (!extractValue()) {
        return false;
    }

    v8::Local<v8::Value> arg_exp, arg_cas;
    getParam(params_max, NameMap::CAS, &arg_cas);
    getParam(params_max - 1, NameMap::EXPIRY, &arg_exp);

    extractExpiry(arg_exp, &exp);
    extractCas(arg_cas, &cas);
    return true;
}

bool StorageArgs::extractValue()
{
    if (!get_string(args[1], &data, &ndata)) {
        throw Couchnode::Exception("Bad value", args[1]);
    }

    return true;
}

StorageArgs::~StorageArgs()
{
    if (stale) {
        return;
    }

    if (data) {
        delete[] data;
        data = NULL;
    }
}

MGetArgs::MGetArgs(const v8::Arguments &args, int nkparams)
    : CommonArgs(args, nkparams),
      kcount(0), single_exp(0), keys(NULL), sizes(NULL), exps(NULL)
{
}

bool MGetArgs::extractKey()
{

    if (args[0]->IsString()) {
        if (!CommonArgs::extractKey()) {
            return false;
        }

        kcount = 1;
        v8::Local<v8::Value> arg_exp;
        getParam(1, NameMap::EXPIRY, &arg_exp);

        extractExpiry(arg_exp, &single_exp);
        assert(key);

        keys = &key;
        sizes = &nkey;

        if (single_exp) {
            exps = &single_exp;
        }

        return true;
    }

    exps = NULL;

    if (!args[0]->IsArray()) {
        return false;
    }

    v8::Local<v8::Array> karry = v8::Local<v8::Array>::Cast(args[0]);
    kcount = karry->Length();

    keys = new char*[kcount];
    sizes = new size_t[kcount];

    memset(keys, 0, sizeof(char *) * kcount);
    memset(sizes, 0, sizeof(size_t) * kcount);

    for (unsigned ii = 0; ii < karry->Length(); ii++) {
        if (!get_string(karry->Get(ii), keys + ii, sizes + ii)) {
            return false;
        }
    }
    return true;
}

void MGetArgs::bailout(CouchbaseCookie *cookie, libcouchbase_error_t err)
{
    for (unsigned ii = 0; ii < kcount; ii++) {
        cookie->result(err, keys[ii], sizes[ii]);
    }
}

MGetArgs::~MGetArgs()
{
    if (stale) {
        return;
    }

    if (exps && exps != &single_exp) {
        delete[] exps;
    }

    if (sizes && sizes != &nkey) {
        delete[] sizes;
    }

    if (keys && keys != &key) {
        for (unsigned ii = 0; ii < kcount; ii++) {
            delete[] keys[ii];
        }
        delete[] keys;
    }

    exps = NULL;
    sizes = NULL;
    keys = NULL;
}

KeyopArgs::KeyopArgs(const v8::Arguments &args)
    : CommonArgs(args, 1), cas(0)
{
}

bool KeyopArgs::parse()
{
    if (!CommonArgs::parse()) {
        return false;
    }

    v8::Local<v8::Value> arg_cas;
    getParam(1, NameMap::CAS, &arg_cas);

    extractCas(arg_cas, &cas);
    return true;
}

// arithmetic(key, delta, initial, exp, cas, ...)
ArithmeticArgs::ArithmeticArgs(const v8::Arguments &args)
    : StorageArgs(args, 1),
      delta(0), initial(0), create(false)
{
}

bool ArithmeticArgs::extractValue()
{
    if (args[1]->IsNumber() == false) {
        throw Couchnode::Exception("Delta must be numeric", args[1]);
    }

    delta = args[1]->IntegerValue();

    v8::Local<v8::Value> arg_initial;
    getParam(2, NameMap::INITIAL, &arg_initial);

    if (!arg_initial.IsEmpty()) {
        if (arg_initial->IsNumber()) {
            initial = arg_initial->IntegerValue();
            create = true;
        } else {
            if (!arg_initial->IsUndefined()) {
                throw Couchnode::Exception("Initial value must be numeric",
                                           arg_initial);
            }
            create = false;
        }

    } else {
        create = false;
    }

    return true;
}
<|endoftext|>