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

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt 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.

 =========================================================================*/
#include "otbSuperimpose.h"

#include <iostream>

#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbGenericRSResampleImageFilter.h"
#include "otbBCOInterpolateImageFunction.h"
#include "itkExceptionObject.h"
#include "otbStandardWriterWatcher.h"

namespace otb
{

int Superimpose::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("Superimpose");
  descriptor->SetDescription("Using available image metadata, project one image onto another one");
  descriptor->AddOption("DEMDirectory","Directory were to find the DEM tiles","dem", 1, false, otb::ApplicationDescriptor::DirectoryName);
  descriptor->AddOption("NumStreamDivisions","Number of streaming divisions (optional)","stream", 1, false, otb::ApplicationDescriptor::Integer);
  descriptor->AddOption("LocMapSpacing","Generate a coarser deformation field with the given spacing.","lmSpacing", 1, false, otb::ApplicationDescriptor::Real);
  descriptor->AddOption("ReferenceInput","The reference input","inR", 1, true, otb::ApplicationDescriptor::InputImage);
  descriptor->AddOption("MovingInput","The image to reproject","inM", 1, true, otb::ApplicationDescriptor::InputImage);
  descriptor->AddOption("AvailableMemory","Set the maximum of available memory for the pipeline execution in mega bytes (optional, 256 by default)","ram", 1, false, otb::ApplicationDescriptor::Integer);
  descriptor->AddOutputImage();

  return EXIT_SUCCESS;
}

int Superimpose::Execute(otb::ApplicationOptionsResult* parseResult)
{
  try
    {

    typedef unsigned short int PixelType;

    typedef otb::VectorImage<PixelType, 2>                ImageType;
    typedef otb::ImageFileReader<ImageType>               ReaderType;
    typedef otb::StreamingImageFileWriter<ImageType>      WriterType;
    typedef otb::BCOInterpolateImageFunction<ImageType>   InterpolatorType;

    typedef otb::GenericRSResampleImageFilter<ImageType, ImageType>  ResamplerType;

    // Read input images information
    ReaderType::Pointer refReader = ReaderType::New();
    refReader->SetFileName(parseResult->GetParameterString("ReferenceInput"));
    refReader->GenerateOutputInformation();

    ReaderType::Pointer movingReader = ReaderType::New();
    movingReader->SetFileName(parseResult->GetParameterString("MovingInput"));
    movingReader->GenerateOutputInformation();

    // Resample filter
    ResamplerType::Pointer    resampler = ResamplerType::New();
    InterpolatorType::Pointer interpolator = InterpolatorType::New();
    resampler->SetInterpolator(interpolator);

    // Add DEM if any
    if(parseResult->IsOptionPresent("DEMDirectory"))
      {
      resampler->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory", 0));
      }

    // Set up output image informations
    ImageType::SpacingType spacing = refReader->GetOutput()->GetSpacing();
    ImageType::IndexType start = refReader->GetOutput()->GetLargestPossibleRegion().GetIndex();
    ImageType::SizeType size = refReader->GetOutput()->GetLargestPossibleRegion().GetSize();
    ImageType::PointType origin = refReader->GetOutput()->GetOrigin();

    if(parseResult->IsOptionPresent("LocMapSpacing"))
      {
      double defScalarSpacing = parseResult->GetParameterFloat("LocMapSpacing");
      std::cout<<"Generating coarse deformation field (spacing="<<defScalarSpacing<<")"<<std::endl;
      ImageType::SpacingType defSpacing;

      defSpacing[0] = defScalarSpacing;
      defSpacing[1] = defScalarSpacing;

      resampler->SetDeformationFieldSpacing(defSpacing);
      }
    else
      {
      ImageType::SpacingType defSpacing;
      defSpacing[0]=10*spacing[0];
      defSpacing[1]=10*spacing[1];
      resampler->SetDeformationFieldSpacing(defSpacing);
      }

    ImageType::PixelType defaultValue;
    itk::PixelBuilder<ImageType::PixelType>::Zero(defaultValue,
                                                  movingReader->GetOutput()->GetNumberOfComponentsPerPixel());

    resampler->SetInput(movingReader->GetOutput());
    resampler->SetOutputOrigin(origin);
    resampler->SetOutputSpacing(spacing);
    resampler->SetOutputSize(size);
    resampler->SetOutputStartIndex(start);
    resampler->SetOutputKeywordList(refReader->GetOutput()->GetImageKeywordlist());
    resampler->SetOutputProjectionRef(refReader->GetOutput()->GetProjectionRef());
    resampler->SetEdgePaddingValue(defaultValue);

    WriterType::Pointer writer = WriterType::New();
    writer->SetFileName(parseResult->GetOutputImage());
    writer->SetInput(resampler->GetOutput());
    writer->SetWriteGeomFile(true);

    unsigned int ram = 256;
    if (parseResult->IsOptionPresent("AvailableMemory"))
      {
      ram = parseResult->GetParameterUInt("AvailableMemory");
      }
    writer->SetAutomaticTiledStreaming(ram);

    otb::StandardWriterWatcher w4(writer, resampler,"Superimposition");
    writer->Update();
    }
  catch ( itk::ExceptionObject & err )
    {
    std::cout << "Exception itk::ExceptionObject raised !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }
  catch ( std::bad_alloc & err )
    {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
    }
  catch ( ... )
    {
    std::cout << "Unknown exception raised !" << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;

}

}
<commit_msg>ENH: add possibility to set DEM from the configuration file<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt 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.

 =========================================================================*/
#include "otbSuperimpose.h"

#include <iostream>

#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbGenericRSResampleImageFilter.h"
#include "otbBCOInterpolateImageFunction.h"
#include "itkExceptionObject.h"
#include "otbStandardWriterWatcher.h"

namespace otb
{

int Superimpose::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("Superimpose");
  descriptor->SetDescription("Using available image metadata, project one image onto another one");
  descriptor->AddOption("DEMDirectory","Directory were to find the DEM tiles","dem", 1, false, otb::ApplicationDescriptor::DirectoryName);
  descriptor->AddOption("NumStreamDivisions","Number of streaming divisions (optional)","stream", 1, false, otb::ApplicationDescriptor::Integer);
  descriptor->AddOption("LocMapSpacing","Generate a coarser deformation field with the given spacing.","lmSpacing", 1, false, otb::ApplicationDescriptor::Real);
  descriptor->AddOption("ReferenceInput","The reference input","inR", 1, true, otb::ApplicationDescriptor::InputImage);
  descriptor->AddOption("MovingInput","The image to reproject","inM", 1, true, otb::ApplicationDescriptor::InputImage);
  descriptor->AddOption("AvailableMemory","Set the maximum of available memory for the pipeline execution in mega bytes (optional, 256 by default)","ram", 1, false, otb::ApplicationDescriptor::Integer);
  descriptor->AddOutputImage();

  return EXIT_SUCCESS;
}

int Superimpose::Execute(otb::ApplicationOptionsResult* parseResult)
{
  try
    {

    typedef unsigned short int PixelType;

    typedef otb::VectorImage<PixelType, 2>                ImageType;
    typedef otb::ImageFileReader<ImageType>               ReaderType;
    typedef otb::StreamingImageFileWriter<ImageType>      WriterType;
    typedef otb::BCOInterpolateImageFunction<ImageType>   InterpolatorType;

    typedef otb::GenericRSResampleImageFilter<ImageType, ImageType>  ResamplerType;

    // Read input images information
    ReaderType::Pointer refReader = ReaderType::New();
    refReader->SetFileName(parseResult->GetParameterString("ReferenceInput"));
    refReader->GenerateOutputInformation();

    ReaderType::Pointer movingReader = ReaderType::New();
    movingReader->SetFileName(parseResult->GetParameterString("MovingInput"));
    movingReader->GenerateOutputInformation();

    // Resample filter
    ResamplerType::Pointer    resampler = ResamplerType::New();
    InterpolatorType::Pointer interpolator = InterpolatorType::New();
    resampler->SetInterpolator(interpolator);

    // Configure DEM directory
    if(parseResult->IsOptionPresent("DEMDirectory"))
      {
      resampler->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory", 0));
      }
    else
      {
      if ( otb::ConfigurationFile::GetInstance()->IsValid() )
        {
        resampler->SetDEMDirectory(otb::ConfigurationFile::GetInstance()->GetDEMDirectory());
        }
      }

    // Set up output image informations
    ImageType::SpacingType spacing = refReader->GetOutput()->GetSpacing();
    ImageType::IndexType start = refReader->GetOutput()->GetLargestPossibleRegion().GetIndex();
    ImageType::SizeType size = refReader->GetOutput()->GetLargestPossibleRegion().GetSize();
    ImageType::PointType origin = refReader->GetOutput()->GetOrigin();

    if(parseResult->IsOptionPresent("LocMapSpacing"))
      {
      double defScalarSpacing = parseResult->GetParameterFloat("LocMapSpacing");
      std::cout<<"Generating coarse deformation field (spacing="<<defScalarSpacing<<")"<<std::endl;
      ImageType::SpacingType defSpacing;

      defSpacing[0] = defScalarSpacing;
      defSpacing[1] = defScalarSpacing;

      resampler->SetDeformationFieldSpacing(defSpacing);
      }
    else
      {
      ImageType::SpacingType defSpacing;
      defSpacing[0]=10*spacing[0];
      defSpacing[1]=10*spacing[1];
      resampler->SetDeformationFieldSpacing(defSpacing);
      }

    ImageType::PixelType defaultValue;
    itk::PixelBuilder<ImageType::PixelType>::Zero(defaultValue,
                                                  movingReader->GetOutput()->GetNumberOfComponentsPerPixel());

    resampler->SetInput(movingReader->GetOutput());
    resampler->SetOutputOrigin(origin);
    resampler->SetOutputSpacing(spacing);
    resampler->SetOutputSize(size);
    resampler->SetOutputStartIndex(start);
    resampler->SetOutputKeywordList(refReader->GetOutput()->GetImageKeywordlist());
    resampler->SetOutputProjectionRef(refReader->GetOutput()->GetProjectionRef());
    resampler->SetEdgePaddingValue(defaultValue);

    WriterType::Pointer writer = WriterType::New();
    writer->SetFileName(parseResult->GetOutputImage());
    writer->SetInput(resampler->GetOutput());
    writer->SetWriteGeomFile(true);

    unsigned int ram = 256;
    if (parseResult->IsOptionPresent("AvailableMemory"))
      {
      ram = parseResult->GetParameterUInt("AvailableMemory");
      }
    writer->SetAutomaticTiledStreaming(ram);

    otb::StandardWriterWatcher w4(writer, resampler,"Superimposition");
    writer->Update();
    }
  catch ( itk::ExceptionObject & err )
    {
    std::cout << "Exception itk::ExceptionObject raised !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }
  catch ( std::bad_alloc & err )
    {
    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
    return EXIT_FAILURE;
    }
  catch ( ... )
    {
    std::cout << "Unknown exception raised !" << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;

}

}
<|endoftext|>


<commit_before>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#define FOREGROUND 0x000000
#define BACKGROUND 0xffffff
//#define FOREGROUND 0xffffff
//#define BACKGROUND 0x000000

FILE* indexfp;

enum ColorModes
{
    EModeDefault,   //ForeGroundBlack
    EModeComment,   //ForeGroundGreen
    EModeString,    //ForeGroundYellow
    EModeBrackets,  //ForeGroundBlue
    EModeOperator1, //ForeGroundBlue
    EModeOperator2, //ForeGroundMagenta
    EModeNumber,    //ForeGroundRed
};

int quoted=0,commented=0;
void ResetColorPrint()
{
    quoted=0;
    commented=0;
}

void ColorMode(FILE* fp,int type)
{
    int color=FOREGROUND;
    switch (type)
    {
    case EModeDefault:   //ForeGroundBlack
        color = FOREGROUND; break;
    case EModeComment:   //ForeGroundGreen
        color = 0x00ff00; break;
    case EModeString:    //ForeGroundYellow
        color = 0xa2a200; break;
    case EModeBrackets:  //ForeGroundBlue
        color = 0x0000ff; break;
    case EModeOperator1: //ForeGroundBlue
        color = 0x0000ff; break;
    case EModeOperator2: //ForeGroundMagenta
        color = 0xff00ff; break;
    case EModeNumber:    //ForeGroundRed
        color = 0xff0000; break;
    }
    fprintf(fp,"",color);
}

void ColorPrint(FILE* out,char* buf)
{
    int i,nr=strlen(buf);
    for (i=0;i<nr;i++)
    {
        if (commented || quoted)
        {

            fprintf(out,"%c",buf[i]);
            if (buf[i+1] == '/' && buf[i] == '*')
            {
                fprintf(out,"%c",buf[i+1]);
                i++;
                commented=0;
            }
            if (buf[i] == '\"')
            {
                quoted=0;
            }
        }
        else
        {
            if (buf[i] == '/' && buf[i+1] == '*')
            {
                ColorMode(out,EModeComment);
                commented=1;
            }
            else if (buf[i] == '\"')
            {
                ColorMode(out,EModeString);
                quoted=1;
            }
            else if (strchr("{}()[]",buf[i])!=NULL)
            {
                ColorMode(out,EModeBrackets);
            }
            else if (strchr("+-*/=:!^<>",buf[i])!=NULL)
            {
                ColorMode(out,EModeOperator1);
            }
            else if (strchr("_,;#",buf[i])!=NULL)
            {
                ColorMode(out,EModeOperator2);
            }
            else if (strchr("0123456789.",buf[i])!=NULL)
            {
                ColorMode(out,EModeNumber);
            }
            else
            {
                ColorMode(out,EModeDefault);
            }
            fprintf(out,"%c",buf[i]);
        }
    }
}

int nrops;
#define MAXOPS 100
char *ops[MAXOPS];

char root[128];

void PutFile(FILE* out, FILE* in)
{
    char buffer[1000];

    fgets(buffer,1000,in);

    ResetColorPrint();
    while (!feof(in))
    {
        int i;
        for (i=0;i<nrops;i++)
        {
            if (ops[i])
            {
                if (strstr(buffer, ops[i]))
                {
                    fprintf(out,"",ops[i]);
                    free(ops[i]);
                    ops[i]=NULL;
                }
            }
        }

        ColorPrint(out,buffer);

        fgets(buffer,1000,in);
    }
}

void Htmlize(char* filename)
{
    FILE *fp,*deffp,*htmlfp;
    char infile[256];
    char deffile[256];
    char htmlfile[256];
    strcpy(infile,root);
    strcat(infile,filename);

    fp=fopen(infile,"r");
    if (fp == NULL)
    {
        printf("Warning: could not find file %s\n",infile);
        return;
    }

    strcpy(htmlfile,filename);
    strcat(htmlfile,".html");
    htmlfp=fopen(htmlfile,"w");
    if (htmlfp == NULL)
    {
        fclose(fp);
        return;
    }

    fprintf(indexfp,"
\n%s
\n",htmlfile,filename);

    strcpy(deffile,"../scripts/");
    strcat(deffile,filename);
    strcat(deffile,".def");
    deffp=fopen(deffile,"r");

    fprintf(htmlfp,"\n\n<title>%s</title>\n\n",filename);
    fprintf(htmlfp,"");

    nrops=0;
    if (deffp)
    {
        char op[100];
        fscanf(deffp,"%s",op);
        while(!feof(deffp))
        {
            if (strcmp(op,"}"))
            {
                assert(nrops<MAXOPS);
                fprintf(htmlfp,"%s ",htmlfile,op,op);
                ops[nrops++] = strdup(op);
            }
            fscanf(deffp,"%s",op);
        }
    }

    fprintf(htmlfp,"
%s
\n",filename);

    fprintf(htmlfp,"
\n
\n
",BACKGROUND);
    fprintf(htmlfp,"",FOREGROUND);

    PutFile(htmlfp,fp);

    fprintf(htmlfp,"
\n
\n\n\n");

    if (deffp)
        fclose(deffp);
    fclose(htmlfp);
    fclose(fp);

    {
        int i;
        for (i=0;i<nrops;i++)
        {
            free(ops[i]);
        }
        nrops=0;
    }
}

int main(void)
{
    indexfp = fopen("scriptsindex.html","w");
    if (indexfp==NULL)
    {
        printf("Error : could not create index\n");
        return 0;
    }
    fprintf(indexfp,"\n\n
\n");

    strcpy(root,"../scripts/examples/");
    fprintf(indexfp,"

Examples

");
    Htmlize("plot2d");
    Htmlize("queens");

    strcpy(root,"../scripts/");
    fprintf(indexfp,"

Source

");
    Htmlize("array");
    Htmlize("assoc");
    Htmlize("complex");
    Htmlize("constants");
    Htmlize("controlflow");
    Htmlize("deffunc");
    Htmlize("deriv");
    Htmlize("edit");
    Htmlize("example");
    Htmlize("factors");
    Htmlize("fakedb");
    Htmlize("formula");
    Htmlize("functional");
    Htmlize("html");
    Htmlize("integrate");
    Htmlize("linalg");
    Htmlize("lists");
    Htmlize("newly");
    Htmlize("numbers");
    Htmlize("padic");
    Htmlize("patterns");
    Htmlize("predicates");
    Htmlize("random");
    Htmlize("simplify");
    Htmlize("standard");
    Htmlize("stdfuncs");
    Htmlize("stdopers");
    Htmlize("solve");
    Htmlize("stats");
    Htmlize("stubs");
    Htmlize("substitute");
    Htmlize("sums");
    Htmlize("tensor");
    Htmlize("testers");
    Htmlize("trigsimp");
    Htmlize("univar");
    Htmlize("yacasinit");

    fprintf(indexfp,"
\n\n\n");
    fclose(indexfp);
    {
        FILE*fp;
        fp=fopen("scriptsmain.html","w");

        fprintf(fp,"\n");
        fprintf(fp,"<FRAMESET BORDER=\"0\" COLS=\"150,*\">\n");
        fprintf(fp,"  <FRAME SRC=\"scriptsindex.html\">\n");
        fprintf(fp,"  </FRAME>\n");
        fprintf(fp,"\n");
        fprintf(fp,"  <FRAME SRC=\"scriptsintro.html\" NAME=\"Chapters\">\n");
        fprintf(fp,"  </FRAME>\n");
        fprintf(fp,"</FRAMESET>\n");
        fprintf(fp,"\n");
        fclose(fp);

        fp=fopen("scriptsintro.html","w");
        fprintf(indexfp,"\n\n");
        fprintf(indexfp,"This page allows you to browse the standard library ");
        fprintf(indexfp,"scripts that come with Yacas. The left pane shows ");
        fprintf(indexfp,"a list of the files in the distribution. At the ");
        fprintf(indexfp,"top of each file are links to the places the ");
        fprintf(indexfp,"functions are mentioned for the first time.");
        fprintf(indexfp,"\n\n");
        fclose(fp);
    }

    return 0;
}

<commit_msg>Removed comma at end of enumerator list, it was causing probems with gcc3<commit_after>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#define FOREGROUND 0x000000
#define BACKGROUND 0xffffff
//#define FOREGROUND 0xffffff
//#define BACKGROUND 0x000000

FILE* indexfp;

enum ColorModes
{
    EModeDefault,   //ForeGroundBlack
    EModeComment,   //ForeGroundGreen
    EModeString,    //ForeGroundYellow
    EModeBrackets,  //ForeGroundBlue
    EModeOperator1, //ForeGroundBlue
    EModeOperator2, //ForeGroundMagenta
    EModeNumber     //ForeGroundRed
};

int quoted=0,commented=0;
void ResetColorPrint()
{
    quoted=0;
    commented=0;
}

void ColorMode(FILE* fp,int type)
{
    int color=FOREGROUND;
    switch (type)
    {
    case EModeDefault:   //ForeGroundBlack
        color = FOREGROUND; break;
    case EModeComment:   //ForeGroundGreen
        color = 0x00ff00; break;
    case EModeString:    //ForeGroundYellow
        color = 0xa2a200; break;
    case EModeBrackets:  //ForeGroundBlue
        color = 0x0000ff; break;
    case EModeOperator1: //ForeGroundBlue
        color = 0x0000ff; break;
    case EModeOperator2: //ForeGroundMagenta
        color = 0xff00ff; break;
    case EModeNumber:    //ForeGroundRed
        color = 0xff0000; break;
    }
    fprintf(fp,"",color);
}

void ColorPrint(FILE* out,char* buf)
{
    int i,nr=strlen(buf);
    for (i=0;i<nr;i++)
    {
        if (commented || quoted)
        {

            fprintf(out,"%c",buf[i]);
            if (buf[i+1] == '/' && buf[i] == '*')
            {
                fprintf(out,"%c",buf[i+1]);
                i++;
                commented=0;
            }
            if (buf[i] == '\"')
            {
                quoted=0;
            }
        }
        else
        {
            if (buf[i] == '/' && buf[i+1] == '*')
            {
                ColorMode(out,EModeComment);
                commented=1;
            }
            else if (buf[i] == '\"')
            {
                ColorMode(out,EModeString);
                quoted=1;
            }
            else if (strchr("{}()[]",buf[i])!=NULL)
            {
                ColorMode(out,EModeBrackets);
            }
            else if (strchr("+-*/=:!^<>",buf[i])!=NULL)
            {
                ColorMode(out,EModeOperator1);
            }
            else if (strchr("_,;#",buf[i])!=NULL)
            {
                ColorMode(out,EModeOperator2);
            }
            else if (strchr("0123456789.",buf[i])!=NULL)
            {
                ColorMode(out,EModeNumber);
            }
            else
            {
                ColorMode(out,EModeDefault);
            }
            fprintf(out,"%c",buf[i]);
        }
    }
}

int nrops;
#define MAXOPS 100
char *ops[MAXOPS];

char root[128];

void PutFile(FILE* out, FILE* in)
{
    char buffer[1000];

    fgets(buffer,1000,in);

    ResetColorPrint();
    while (!feof(in))
    {
        int i;
        for (i=0;i<nrops;i++)
        {
            if (ops[i])
            {
                if (strstr(buffer, ops[i]))
                {
                    fprintf(out,"",ops[i]);
                    free(ops[i]);
                    ops[i]=NULL;
                }
            }
        }

        ColorPrint(out,buffer);

        fgets(buffer,1000,in);
    }
}

void Htmlize(char* filename)
{
    FILE *fp,*deffp,*htmlfp;
    char infile[256];
    char deffile[256];
    char htmlfile[256];
    strcpy(infile,root);
    strcat(infile,filename);

    fp=fopen(infile,"r");
    if (fp == NULL)
    {
        printf("Warning: could not find file %s\n",infile);
        return;
    }

    strcpy(htmlfile,filename);
    strcat(htmlfile,".html");
    htmlfp=fopen(htmlfile,"w");
    if (htmlfp == NULL)
    {
        fclose(fp);
        return;
    }

    fprintf(indexfp,"
\n%s
\n",htmlfile,filename);

    strcpy(deffile,"../scripts/");
    strcat(deffile,filename);
    strcat(deffile,".def");
    deffp=fopen(deffile,"r");

    fprintf(htmlfp,"\n\n<title>%s</title>\n\n",filename);
    fprintf(htmlfp,"");

    nrops=0;
    if (deffp)
    {
        char op[100];
        fscanf(deffp,"%s",op);
        while(!feof(deffp))
        {
            if (strcmp(op,"}"))
            {
                assert(nrops<MAXOPS);
                fprintf(htmlfp,"%s ",htmlfile,op,op);
                ops[nrops++] = strdup(op);
            }
            fscanf(deffp,"%s",op);
        }
    }

    fprintf(htmlfp,"
%s
\n",filename);

    fprintf(htmlfp,"
\n
\n
",BACKGROUND);
    fprintf(htmlfp,"",FOREGROUND);

    PutFile(htmlfp,fp);

    fprintf(htmlfp,"
\n
\n\n\n");

    if (deffp)
        fclose(deffp);
    fclose(htmlfp);
    fclose(fp);

    {
        int i;
        for (i=0;i<nrops;i++)
        {
            free(ops[i]);
        }
        nrops=0;
    }
}

int main(void)
{
    indexfp = fopen("scriptsindex.html","w");
    if (indexfp==NULL)
    {
        printf("Error : could not create index\n");
        return 0;
    }
    fprintf(indexfp,"\n\n
\n");

    strcpy(root,"../scripts/examples/");
    fprintf(indexfp,"

Examples

");
    Htmlize("plot2d");
    Htmlize("queens");

    strcpy(root,"../scripts/");
    fprintf(indexfp,"

Source

");
    Htmlize("array");
    Htmlize("assoc");
    Htmlize("complex");
    Htmlize("constants");
    Htmlize("controlflow");
    Htmlize("deffunc");
    Htmlize("deriv");
    Htmlize("edit");
    Htmlize("example");
    Htmlize("factors");
    Htmlize("fakedb");
    Htmlize("formula");
    Htmlize("functional");
    Htmlize("html");
    Htmlize("integrate");
    Htmlize("linalg");
    Htmlize("lists");
    Htmlize("newly");
    Htmlize("numbers");
    Htmlize("padic");
    Htmlize("patterns");
    Htmlize("predicates");
    Htmlize("random");
    Htmlize("simplify");
    Htmlize("standard");
    Htmlize("stdfuncs");
    Htmlize("stdopers");
    Htmlize("solve");
    Htmlize("stats");
    Htmlize("stubs");
    Htmlize("substitute");
    Htmlize("sums");
    Htmlize("tensor");
    Htmlize("testers");
    Htmlize("trigsimp");
    Htmlize("univar");
    Htmlize("yacasinit");

    fprintf(indexfp,"
\n\n\n");
    fclose(indexfp);
    {
        FILE*fp;
        fp=fopen("scriptsmain.html","w");

        fprintf(fp,"\n");
        fprintf(fp,"<FRAMESET BORDER=\"0\" COLS=\"150,*\">\n");
        fprintf(fp,"  <FRAME SRC=\"scriptsindex.html\">\n");
        fprintf(fp,"  </FRAME>\n");
        fprintf(fp,"\n");
        fprintf(fp,"  <FRAME SRC=\"scriptsintro.html\" NAME=\"Chapters\">\n");
        fprintf(fp,"  </FRAME>\n");
        fprintf(fp,"</FRAMESET>\n");
        fprintf(fp,"\n");
        fclose(fp);

        fp=fopen("scriptsintro.html","w");
        fprintf(indexfp,"\n\n");
        fprintf(indexfp,"This page allows you to browse the standard library ");
        fprintf(indexfp,"scripts that come with Yacas. The left pane shows ");
        fprintf(indexfp,"a list of the files in the distribution. At the ");
        fprintf(indexfp,"top of each file are links to the places the ");
        fprintf(indexfp,"functions are mentioned for the first time.");
        fprintf(indexfp,"\n\n");
        fclose(fp);
    }

    return 0;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dlgejpg.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 21:33:36 $
 *
 *  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_svtools.hxx"
#include "dlgejpg.hxx"
#include "dlgejpg.hrc"
#include "strings.hrc"
#include <svtools/FilterConfigItem.hxx>

#define KEY_QUALITY     "Quality"
#define KEY_GRAYSCALES  "ColorMode"

/*************************************************************************
|*
|* Ctor
|*
\************************************************************************/

DlgExportEJPG::DlgExportEJPG( FltCallDialogParameter& rPara ) :
                ModalDialog         ( rPara.pWindow, ResId( DLG_EXPORT_JPG, *rPara.pResMgr ) ),
                rFltCallPara        ( rPara ),
                aFiDescr            ( this, ResId( FI_DESCR, *rPara.pResMgr ) ),
                aNumFldQuality      ( this, ResId( NUM_FLD_QUALITY, *rPara.pResMgr ) ),
                aGrpQuality         ( this, ResId( GRP_QUALITY, *rPara.pResMgr ) ),
                aRbGray             ( this, ResId( RB_GRAY, *rPara.pResMgr ) ),
                aRbRGB              ( this, ResId( RB_RGB, *rPara.pResMgr ) ),
                aGrpColors          ( this, ResId( GRP_COLORS, *rPara.pResMgr ) ),
                aBtnOK              ( this, ResId( BTN_OK, *rPara.pResMgr ) ),
                aBtnCancel          ( this, ResId( BTN_CANCEL, *rPara.pResMgr ) ),
                aBtnHelp            ( this, ResId( BTN_HELP, *rPara.pResMgr ) )
{
    FreeResource();
    String  aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Export/JPG" ) );
    pConfigItem = new FilterConfigItem( aFilterConfigPath, &rPara.aFilterData );

    // reading filter options
    sal_Int32 nQuality = pConfigItem->ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( KEY_QUALITY ) ), 75 );
    sal_Int32 nColorMode = pConfigItem->ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( KEY_GRAYSCALES ) ), 0 );
    aNumFldQuality.SetValue( nQuality );

    if ( nColorMode  )
        aRbGray.Check( sal_True );
    else
        aRbRGB.Check( sal_True );

    aBtnOK.SetClickHdl( LINK( this, DlgExportEJPG, OK ) );
}

/*************************************************************************
|*
|* Speichert eingestellte Werte in ini-Datei
|*
\************************************************************************/

IMPL_LINK( DlgExportEJPG, OK, void *, EMPTYARG )
{
    // Config-Parameter schreiben
    pConfigItem->WriteInt32( String( RTL_CONSTASCII_USTRINGPARAM( KEY_QUALITY ) ), (sal_Int32)aNumFldQuality.GetValue() );
    pConfigItem->WriteInt32( String( RTL_CONSTASCII_USTRINGPARAM( KEY_GRAYSCALES ) ), aRbGray.IsChecked() ? 1 : 0 );
    rFltCallPara.aFilterData = pConfigItem->GetFilterData();
    EndDialog( RET_OK );
    return 0;
}

DlgExportEJPG::~DlgExportEJPG()
{
    delete pConfigItem;
}

<commit_msg>INTEGRATION: CWS fwk66 (1.7.60); FILE MERGED 2007/06/06 08:41:13 pb 1.7.60.1: fix: syntax error after resync<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dlgejpg.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: ihi $ $Date: 2007-07-10 15:17:25 $
 *
 *  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_svtools.hxx"
#include "dlgejpg.hxx"
#include "dlgejpg.hrc"
#include "strings.hrc"
#include <svtools/FilterConfigItem.hxx>

#define KEY_QUALITY     "Quality"
#define KEY_GRAYSCALES  "ColorMode"

/*************************************************************************
|*
|* Ctor
|*
\************************************************************************/

DlgExportEJPG::DlgExportEJPG( FltCallDialogParameter& rPara ) :
                ModalDialog         ( rPara.pWindow, ResId( DLG_EXPORT_JPG, *rPara.pResMgr ) ),
                rFltCallPara        ( rPara ),
                aFiDescr            ( this, ResId( FI_DESCR, *rPara.pResMgr ) ),
                aNumFldQuality      ( this, ResId( NUM_FLD_QUALITY, *rPara.pResMgr ) ),
                aGrpQuality         ( this, ResId( GRP_QUALITY, *rPara.pResMgr ) ),
                aRbGray             ( this, ResId( RB_GRAY, *rPara.pResMgr ) ),
                aRbRGB              ( this, ResId( RB_RGB, *rPara.pResMgr ) ),
                aGrpColors          ( this, ResId( GRP_COLORS, *rPara.pResMgr ) ),
                aBtnOK              ( this, ResId( BTN_OK, *rPara.pResMgr ) ),
                aBtnCancel          ( this, ResId( BTN_CANCEL, *rPara.pResMgr ) ),
                aBtnHelp            ( this, ResId( BTN_HELP, *rPara.pResMgr ) )
{
    FreeResource();
    String  aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Export/JPG" ) );
    pConfigItem = new FilterConfigItem( aFilterConfigPath, &rPara.aFilterData );

    // reading filter options
    sal_Int32 nQuality = pConfigItem->ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( KEY_QUALITY ) ), 75 );
    sal_Int32 nColorMode = pConfigItem->ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( KEY_GRAYSCALES ) ), 0 );
    aNumFldQuality.SetValue( nQuality );

    if ( nColorMode  )
        aRbGray.Check( sal_True );
    else
        aRbRGB.Check( sal_True );

    aBtnOK.SetClickHdl( LINK( this, DlgExportEJPG, OK ) );
}

/*************************************************************************
|*
|* Speichert eingestellte Werte in ini-Datei
|*
\************************************************************************/

IMPL_LINK( DlgExportEJPG, OK, void *, EMPTYARG )
{
    // Config-Parameter schreiben
    pConfigItem->WriteInt32( String( RTL_CONSTASCII_USTRINGPARAM( KEY_QUALITY ) ), (sal_Int32)aNumFldQuality.GetValue() );
    pConfigItem->WriteInt32( String( RTL_CONSTASCII_USTRINGPARAM( KEY_GRAYSCALES ) ), aRbGray.IsChecked() ? 1 : 0 );
    rFltCallPara.aFilterData = pConfigItem->GetFilterData();
    EndDialog( RET_OK );
    return 0;
}

DlgExportEJPG::~DlgExportEJPG()
{
    delete pConfigItem;
}

<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %cling -std=gnu99 -x c -Xclang -verify 2>&1 | FileCheck %s
// RUN: cat %s | %cling -D__STRICT_ANSI__ -std=gnu++11 -Xclang -verify 2>&1 | FileCheck %s
// RUN: cat %s | %cling -D__STRICT_ANSI__ -std=gnu++14 -Xclang -verify 2>&1 | FileCheck %s
// RUN: cat %s | %cling -D__STRICT_ANSI__ -std=gnu++1z -Xclang -verify 2>&1 | FileCheck %s

#ifdef __cplusplus
extern "C" int printf(const char*, ...);
#else
int printf(const char*, ...);
#endif

typeof (int) Val = 22;
typeof (const char*) This = "THIS";

printf("TEST: %d '%s'\n", Val, This);
// CHECK: TEST: 22 'THIS'

// expected-no-diagnostics
.q
<commit_msg>Don't run Gnu.C test on Windows...<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %cling -std=gnu99 -x c -Xclang -verify 2>&1 | FileCheck %s
// RUN: cat %s | %cling -D__STRICT_ANSI__ -std=gnu++11 -Xclang -verify 2>&1 | FileCheck %s
// RUN: cat %s | %cling -D__STRICT_ANSI__ -std=gnu++14 -Xclang -verify 2>&1 | FileCheck %s
// RUN: cat %s | %cling -D__STRICT_ANSI__ -std=gnu++1z -Xclang -verify 2>&1 | FileCheck %s
// REQUIRES: not_system-windows

#ifdef __cplusplus
extern "C" int printf(const char*, ...);
#else
int printf(const char*, ...);
#endif

typeof (int) Val = 22;
typeof (const char*) This = "THIS";

printf("TEST: %d '%s'\n", Val, This);
// CHECK: TEST: 22 'THIS'

// expected-no-diagnostics
.q
<|endoftext|>


<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "Common.h"
#include "ParserWorker.h"
#include "Parser.h"
#include "Media.h"
#include "medialibrary/filesystem/Errors.h"
#include "Folder.h"

namespace medialibrary
{
namespace parser
{

Worker::Worker()
    : m_parserCb( nullptr )
    , m_stopParser( false )
    , m_paused( false )
    , m_idle( true )
{
}

void Worker::start()
{
    // This function is called from a locked context.

    // Ensure we don't start multiple times.
    assert( m_thread.joinable() == false );
    m_thread = compat::Thread{ &Worker::mainloop, this };
}

void Worker::pause()
{
    std::lock_guard<compat::Mutex> lock( m_lock );
    m_paused = true;
}

void Worker::resume()
{
    std::lock_guard<compat::Mutex> lock( m_lock );
    m_paused = false;
    m_cond.notify_all();
}

void Worker::signalStop()
{
    {
        std::lock_guard<compat::Mutex> lock( m_lock );
        m_stopParser = true;
    }
    m_cond.notify_all();
    m_service->stop();
}

void Worker::stop()
{
    if ( m_thread.joinable() == true )
        m_thread.join();
}

void Worker::parse( std::shared_ptr<Task> t )
{
    // Avoid flickering from idle/not idle when not many tasks are running.
    // The thread calling parse for the next parser step might not have
    // something left to do and would turn idle, potentially causing all
    // services to be idle for a very short time, until this parser
    // thread awakes/starts, causing the global parser idle state to be
    // restored back to false.
    // Since we are queuing a task, we already know that this thread is
    // not idle
    setIdle( false );

    // Even if no threads appear to be started, we need to lock this in case
    // we're currently doing a stop/start
    {
        std::lock_guard<compat::Mutex> lock( m_lock );
        m_tasks.push( std::move( t ) );
        if ( m_thread.get_id() == compat::Thread::id{} )
        {
            start();
            return;
        }
    }
    m_cond.notify_all();
}

bool Worker::initialize( MediaLibrary* ml, IParserCb* parserCb,
                               std::shared_ptr<IParserService> service )
{
    m_ml = ml;
    m_service = std::move( service );
    m_parserCb = parserCb;
    // Run the service specific initializer
    return m_service->initialize( ml );
}

bool Worker::isIdle() const
{
    return m_idle;
}

void Worker::flush()
{
    std::unique_lock<compat::Mutex> lock( m_lock );
    assert( m_paused == true || m_thread.get_id() == compat::Thread::id{} );
    m_idleCond.wait( lock, [this]() {
        return m_idle == true;
    });
    while ( m_tasks.empty() == false )
        m_tasks.pop();
    m_service->onFlushing();
}

void Worker::restart()
{
    m_service->onRestarted();
}

void Worker::mainloop() ML_UNHANDLED_EXCEPTION_INIT
{
    // It would be unsafe to call name() at the end of this function, since
    // we might stop the thread during ParserService destruction. This implies
    // that the underlying service has been deleted already.
    std::string serviceName = m_service->name();
    LOG_INFO("Entering ParserService [", serviceName, "] thread");
    setIdle( false );

    while ( true )
    {
        std::shared_ptr<Task> task;
        {
            std::unique_lock<compat::Mutex> lock( m_lock );
            if ( m_stopParser == true )
                break;
            if ( m_tasks.empty() == true || m_paused == true )
            {
                LOG_DEBUG( "Halting ParserService [", serviceName, "] mainloop" );
                setIdle( true );
                m_idleCond.notify_all();
                m_cond.wait( lock, [this]() {
                    return ( m_tasks.empty() == false && m_paused == false )
                            || m_stopParser == true;
                });
                LOG_DEBUG( "Resuming ParserService [", serviceName, "] mainloop" );
                // We might have been woken up because the parser is being destroyed
                if ( m_stopParser  == true )
                    break;
                setIdle( false );
            }
            // Otherwise it's safe to assume we have at least one element.
            LOG_DEBUG('[', serviceName, "] has ", m_tasks.size(), " tasks remaining" );
            task = std::move( m_tasks.front() );
            m_tasks.pop();
        }
        // Special case to restore uncompleted tasks from a parser thread
        if ( task == nullptr )
        {
            restoreTasks();
            continue;
        }
        if ( task->isStepCompleted( m_service->targetedStep() ) == true )
        {
            LOG_DEBUG( "Skipping completed task [", serviceName, "] on ", task->mrl() );
            m_parserCb->done( std::move( task ), Status::Success );
            continue;
        }
        Status status;
        try
        {
            LOG_DEBUG( "Executing ", serviceName, " task on ", task->mrl() );
            auto chrono = std::chrono::steady_clock::now();
            auto file = std::static_pointer_cast<File>( task->file() );

            if ( file != nullptr && file->isRemovable() )
            {
                auto folder = Folder::fetch( m_ml, file->folderId() );
                assert( folder != nullptr );
                if ( folder == nullptr || folder->isPresent() == false )
                {
                    LOG_DEBUG( "Postponing parsing of ", file->rawMrl(),
                              " until the device containing it gets mounted back" );
                    m_parserCb->done( std::move( task ), Status::TemporaryUnavailable );
                    continue;
                }
            }
            task->startParserStep();
            status = m_service->run( *task );
            auto duration = std::chrono::steady_clock::now() - chrono;
            LOG_DEBUG( "Done executing ", serviceName, " task on ", task->mrl(), " in ",
                       std::chrono::duration_cast<std::chrono::milliseconds>( duration ).count(),
                       "ms. Result: ",
                       static_cast<std::underlying_type_t<parser::Status>>( status ) );
        }
        catch ( const fs::errors::DeviceRemoved& )
        {
            LOG_ERROR( "Parsing of ", task->mrl(), " was interrupted "
                       "due to its containing device being unmounted" );
            status = Status::TemporaryUnavailable;
        }
        catch ( const std::exception& ex )
        {
            LOG_ERROR( "Caught an exception during ", task->mrl(), " [", serviceName, "] parsing: ", ex.what() );
            status = Status::Fatal;
        }
        if ( handleServiceResult( *task, status ) == false )
            status = Status::Fatal;
        m_parserCb->done( std::move( task ), status );
    }
    LOG_INFO("Exiting ParserService [", serviceName, "] thread");
    setIdle( true );
}
ML_UNHANDLED_EXCEPTION_BODY( "ParserWorker" )

void Worker::setIdle(bool isIdle)
{
    // Calling the idleChanged callback will trigger a call to isIdle, so set the value before
    // invoking it, otherwise we have an incoherent state.
    if ( m_idle != isIdle )
    {
        m_idle = isIdle;
        m_parserCb->onIdleChanged( isIdle );
    }
}

bool Worker::handleServiceResult( Task& task, Status status )
{
    if ( status == Status::Success )
    {
        task.markStepCompleted( m_service->targetedStep() );
        // We don't want to save the extraction step in database, as restarting a
        // task with extraction completed but analysis uncompleted wouldn't run
        // the extraction again, causing the analysis to run with no info.
        if ( m_service->targetedStep() != Step::MetadataExtraction )
            return task.saveParserStep();
        // We don't want to reset the entire retry count, as we would be stuck in
        // a "loop" in case the metadata analysis fails (we'd always reset the retry
        // count to zero, then fail, then run the extraction again, reset the retry,
        // fail the analysis, and so on.
        // We can't not increment the retry count for metadata extraction, since
        // in case a file makes (lib)VLC crash, we would always try again, and
        // therefor we would keep on crashing.
        // However we don't want to just increment the retry count, since it
        // would reach the maximum value too quickly (extraction would set retry
        // count to 1, analysis to 2, and in case of failure, next run would set
        // it over 3, while we only tried 2 times. Instead we just decrement it
        // when the extraction step succeeds
        return task.decrementRetryCount();
    }
    else if ( status == Status::Completed )
    {
        task.markStepCompleted( Step::Completed );
        return task.saveParserStep();
    }
    else if ( status == Status::Discarded )
    {
        return Task::destroy( m_ml, task.id() );
    }
    return true;
}

void Worker::restoreTasks()
{
    auto tasks = Task::fetchUncompleted( m_ml );
    if ( tasks.size() > 0 )
        LOG_INFO( "Resuming parsing on ", tasks.size(), " tasks" );
    else
        LOG_DEBUG( "No task to resume." );
    for ( auto& t : tasks )
    {
        {
            std::lock_guard<compat::Mutex> lock( m_lock );
            if ( m_stopParser == true )
                break;
        }

        if ( t->restoreLinkedEntities() == false )
            continue;
        m_parserCb->parse( std::move( t ) );
    }
}

}
}
<commit_msg>ParserWorker: Catch filesystem exceptions only<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "Common.h"
#include "ParserWorker.h"
#include "Parser.h"
#include "Media.h"
#include "medialibrary/filesystem/Errors.h"
#include "Folder.h"

namespace medialibrary
{
namespace parser
{

Worker::Worker()
    : m_parserCb( nullptr )
    , m_stopParser( false )
    , m_paused( false )
    , m_idle( true )
{
}

void Worker::start()
{
    // This function is called from a locked context.

    // Ensure we don't start multiple times.
    assert( m_thread.joinable() == false );
    m_thread = compat::Thread{ &Worker::mainloop, this };
}

void Worker::pause()
{
    std::lock_guard<compat::Mutex> lock( m_lock );
    m_paused = true;
}

void Worker::resume()
{
    std::lock_guard<compat::Mutex> lock( m_lock );
    m_paused = false;
    m_cond.notify_all();
}

void Worker::signalStop()
{
    {
        std::lock_guard<compat::Mutex> lock( m_lock );
        m_stopParser = true;
    }
    m_cond.notify_all();
    m_service->stop();
}

void Worker::stop()
{
    if ( m_thread.joinable() == true )
        m_thread.join();
}

void Worker::parse( std::shared_ptr<Task> t )
{
    // Avoid flickering from idle/not idle when not many tasks are running.
    // The thread calling parse for the next parser step might not have
    // something left to do and would turn idle, potentially causing all
    // services to be idle for a very short time, until this parser
    // thread awakes/starts, causing the global parser idle state to be
    // restored back to false.
    // Since we are queuing a task, we already know that this thread is
    // not idle
    setIdle( false );

    // Even if no threads appear to be started, we need to lock this in case
    // we're currently doing a stop/start
    {
        std::lock_guard<compat::Mutex> lock( m_lock );
        m_tasks.push( std::move( t ) );
        if ( m_thread.get_id() == compat::Thread::id{} )
        {
            start();
            return;
        }
    }
    m_cond.notify_all();
}

bool Worker::initialize( MediaLibrary* ml, IParserCb* parserCb,
                               std::shared_ptr<IParserService> service )
{
    m_ml = ml;
    m_service = std::move( service );
    m_parserCb = parserCb;
    // Run the service specific initializer
    return m_service->initialize( ml );
}

bool Worker::isIdle() const
{
    return m_idle;
}

void Worker::flush()
{
    std::unique_lock<compat::Mutex> lock( m_lock );
    assert( m_paused == true || m_thread.get_id() == compat::Thread::id{} );
    m_idleCond.wait( lock, [this]() {
        return m_idle == true;
    });
    while ( m_tasks.empty() == false )
        m_tasks.pop();
    m_service->onFlushing();
}

void Worker::restart()
{
    m_service->onRestarted();
}

void Worker::mainloop() ML_UNHANDLED_EXCEPTION_INIT
{
    // It would be unsafe to call name() at the end of this function, since
    // we might stop the thread during ParserService destruction. This implies
    // that the underlying service has been deleted already.
    std::string serviceName = m_service->name();
    LOG_INFO("Entering ParserService [", serviceName, "] thread");
    setIdle( false );

    while ( true )
    {
        std::shared_ptr<Task> task;
        {
            std::unique_lock<compat::Mutex> lock( m_lock );
            if ( m_stopParser == true )
                break;
            if ( m_tasks.empty() == true || m_paused == true )
            {
                LOG_DEBUG( "Halting ParserService [", serviceName, "] mainloop" );
                setIdle( true );
                m_idleCond.notify_all();
                m_cond.wait( lock, [this]() {
                    return ( m_tasks.empty() == false && m_paused == false )
                            || m_stopParser == true;
                });
                LOG_DEBUG( "Resuming ParserService [", serviceName, "] mainloop" );
                // We might have been woken up because the parser is being destroyed
                if ( m_stopParser  == true )
                    break;
                setIdle( false );
            }
            // Otherwise it's safe to assume we have at least one element.
            LOG_DEBUG('[', serviceName, "] has ", m_tasks.size(), " tasks remaining" );
            task = std::move( m_tasks.front() );
            m_tasks.pop();
        }
        // Special case to restore uncompleted tasks from a parser thread
        if ( task == nullptr )
        {
            restoreTasks();
            continue;
        }
        if ( task->isStepCompleted( m_service->targetedStep() ) == true )
        {
            LOG_DEBUG( "Skipping completed task [", serviceName, "] on ", task->mrl() );
            m_parserCb->done( std::move( task ), Status::Success );
            continue;
        }
        Status status;
        try
        {
            LOG_DEBUG( "Executing ", serviceName, " task on ", task->mrl() );
            auto chrono = std::chrono::steady_clock::now();
            auto file = std::static_pointer_cast<File>( task->file() );

            if ( file != nullptr && file->isRemovable() )
            {
                auto folder = Folder::fetch( m_ml, file->folderId() );
                assert( folder != nullptr );
                if ( folder == nullptr || folder->isPresent() == false )
                {
                    LOG_DEBUG( "Postponing parsing of ", file->rawMrl(),
                              " until the device containing it gets mounted back" );
                    m_parserCb->done( std::move( task ), Status::TemporaryUnavailable );
                    continue;
                }
            }
            task->startParserStep();
            status = m_service->run( *task );
            auto duration = std::chrono::steady_clock::now() - chrono;
            LOG_DEBUG( "Done executing ", serviceName, " task on ", task->mrl(), " in ",
                       std::chrono::duration_cast<std::chrono::milliseconds>( duration ).count(),
                       "ms. Result: ",
                       static_cast<std::underlying_type_t<parser::Status>>( status ) );
        }
        catch ( const fs::errors::DeviceRemoved& )
        {
            LOG_ERROR( "Parsing of ", task->mrl(), " was interrupted "
                       "due to its containing device being unmounted" );
            status = Status::TemporaryUnavailable;
        }
        catch ( const fs::errors::Exception& ex )
        {
            LOG_ERROR( "Caught an FS exception during ", task->mrl(), " [", serviceName, "] parsing: ", ex.what() );
            status = Status::Fatal;
        }
        if ( handleServiceResult( *task, status ) == false )
            status = Status::Fatal;
        m_parserCb->done( std::move( task ), status );
    }
    LOG_INFO("Exiting ParserService [", serviceName, "] thread");
    setIdle( true );
}
ML_UNHANDLED_EXCEPTION_BODY( "ParserWorker" )

void Worker::setIdle(bool isIdle)
{
    // Calling the idleChanged callback will trigger a call to isIdle, so set the value before
    // invoking it, otherwise we have an incoherent state.
    if ( m_idle != isIdle )
    {
        m_idle = isIdle;
        m_parserCb->onIdleChanged( isIdle );
    }
}

bool Worker::handleServiceResult( Task& task, Status status )
{
    if ( status == Status::Success )
    {
        task.markStepCompleted( m_service->targetedStep() );
        // We don't want to save the extraction step in database, as restarting a
        // task with extraction completed but analysis uncompleted wouldn't run
        // the extraction again, causing the analysis to run with no info.
        if ( m_service->targetedStep() != Step::MetadataExtraction )
            return task.saveParserStep();
        // We don't want to reset the entire retry count, as we would be stuck in
        // a "loop" in case the metadata analysis fails (we'd always reset the retry
        // count to zero, then fail, then run the extraction again, reset the retry,
        // fail the analysis, and so on.
        // We can't not increment the retry count for metadata extraction, since
        // in case a file makes (lib)VLC crash, we would always try again, and
        // therefor we would keep on crashing.
        // However we don't want to just increment the retry count, since it
        // would reach the maximum value too quickly (extraction would set retry
        // count to 1, analysis to 2, and in case of failure, next run would set
        // it over 3, while we only tried 2 times. Instead we just decrement it
        // when the extraction step succeeds
        return task.decrementRetryCount();
    }
    else if ( status == Status::Completed )
    {
        task.markStepCompleted( Step::Completed );
        return task.saveParserStep();
    }
    else if ( status == Status::Discarded )
    {
        return Task::destroy( m_ml, task.id() );
    }
    return true;
}

void Worker::restoreTasks()
{
    auto tasks = Task::fetchUncompleted( m_ml );
    if ( tasks.size() > 0 )
        LOG_INFO( "Resuming parsing on ", tasks.size(), " tasks" );
    else
        LOG_DEBUG( "No task to resume." );
    for ( auto& t : tasks )
    {
        {
            std::lock_guard<compat::Mutex> lock( m_lock );
            if ( m_stopParser == true )
                break;
        }

        if ( t->restoreLinkedEntities() == false )
            continue;
        m_parserCb->parse( std::move( t ) );
    }
}

}
}
<|endoftext|>


<commit_before>#include <common.cxx>
#include <fs/disk.hpp>
#include <fs/memdisk.hpp>
#include <util/sha1.hpp>
using namespace fs;

static MemDisk* mdisk = nullptr;
static Disk_ptr disk = nullptr;

CASE("Prepare custom memdisk")
{
  const char* rootp(getenv("INCLUDEOS_SRC"));
  std::string path;
  if (rootp == nullptr) path = "..";
  else path = std::string(rootp) + "/test";

  path += "/memdisk.fat";
  auto* fp = fopen(path.c_str(), "rb");
  EXPECT(fp != nullptr);
  fseek(fp, 0L, SEEK_END);
  long int size = ftell(fp);
  rewind(fp);
  // read file into buffer
  char* buffer = new char[size];
  EXPECT(buffer);
  size_t res = fread(buffer, size, 1, fp);
  EXPECT(res == 1);
  // create memdisk
  mdisk = new MemDisk(buffer, buffer + size);
  EXPECT(mdisk);
}

CASE("Initialize FAT fs")
{
  disk = std::make_shared<Disk> (*mdisk);
  disk->init_fs(
    [&lest_env] (auto err, File_system& fs)
    {
      EXPECT(!err);
    });
}

CASE("List root directory")
{
  auto& fs = disk->fs();
  auto res = fs.ls("/");
  // validate root directory
  EXPECT(!res.error);
  EXPECT(res.entries->size() == 8);

  // validate each entry
  auto& ents = *res.entries;
  EXPECT(ents.at(0).name() == ".");
  EXPECT(ents.at(1).name() == "..");
  EXPECT(ents.at(2).name() == "folder");
  EXPECT(ents.at(3).name() == "test.pem");
  EXPECT(ents.at(4).name() == "test.der");
  EXPECT(ents.at(5).name() == "build.sh");
  EXPECT(ents.at(6).name() == "server.key");
  EXPECT(ents.at(7).name() == "test.key");
}

CASE("Validate /folder")
{
  auto& fs = disk->fs();
  // validate folder sync
  auto res = fs.ls("/folder/");
  EXPECT(!res.error);
  EXPECT(res.entries->size() == 3);

  // validate each entry
  auto& ents = *res.entries;
  EXPECT(ents.at(0).name() == ".");
  EXPECT(ents.at(1).name() == "..");
  EXPECT(ents.at(2).name() == "file.txt");

  // validate folder async
  fs.ls("/folder",
  [&lest_env] (auto error, Dirvec_ptr dirvec)
  {
    EXPECT(!error);
    auto& ents = *dirvec;
    EXPECT(ents.at(0).name() == ".");
    EXPECT(ents.at(1).name() == "..");
    EXPECT(ents.at(2).name() == "file.txt");
  });
}

CASE("Validate /folder using dirent")
{
  auto& fs = disk->fs();
  // get dirent by using stat()
  auto ent = fs.stat("/folder");
  EXPECT(ent.is_valid());
  EXPECT(ent.is_dir());

  // validate folder sync using dirent
  auto res = fs.ls(ent);
  EXPECT(!res.error);
  EXPECT(res.entries->size() == 3);

  // validate each entry
  auto& ents = *res.entries;
  EXPECT(ents.at(0).name() == ".");
  EXPECT(ents.at(1).name() == "..");
  EXPECT(ents.at(2).name() == "file.txt");

  // validate folder async using dirent
  fs.ls(ent,
  [&lest_env] (auto error, Dirvec_ptr dirvec)
  {
    EXPECT(!error);
    auto& ents = *dirvec;
    EXPECT(ents.at(0).name() == ".");
    EXPECT(ents.at(1).name() == "..");
    EXPECT(ents.at(2).name() == "file.txt");
  });
}

CASE("Validate /folder/file.txt")
{
  auto& fs = disk->fs();
  // read and validate file
  auto buffer = fs.read_file("/folder/file.txt");
  EXPECT(buffer.size() == 24);
  SHA1 sha1;
  sha1.update(buffer.data(), buffer.size());
  const std::string hash = sha1.as_hex();

  EXPECT(hash == "de1d4db81aa9344377ccfd49f5a239533d4f4ee3");

  const std::string text((const char*) buffer.data(), buffer.size());
  EXPECT(text == "This file contains text\n");
}

CASE("Stat /folder/file.txt")
{
  auto& fs = disk->fs();
  // get dirent by stat()
  auto ent = fs.stat("/folder/file.txt");
  EXPECT(ent.is_valid());
  EXPECT(ent.is_file());
  EXPECT(ent.size() == 24);

  // read and validate file using dirent
  auto buffer = fs.read(ent, 0, ent.size());
  EXPECT(buffer.size() == 24);

  const std::string text((const char*) buffer.data(), buffer.size());
  EXPECT(text == "This file contains text\n");
}
<commit_msg>test: added default to look for memdisk.fat in current directory<commit_after>#include <common.cxx>
#include <fs/disk.hpp>
#include <fs/memdisk.hpp>
#include <util/sha1.hpp>
#include <unistd.h>
using namespace fs;

static MemDisk* mdisk = nullptr;
static Disk_ptr disk = nullptr;

CASE("Prepare custom memdisk")
{
  const char* rootp(getenv("INCLUDEOS_SRC"));
  std::string path="memdisk.fat";
  if (access(path.c_str(),F_OK) == -1)
  {
    if (rootp == nullptr) path = "..";
    else path = std::string(rootp) + "/test";
    path += "/memdisk.fat";
  }
  auto* fp = fopen(path.c_str(), "rb");
  EXPECT(fp != nullptr);
  fseek(fp, 0L, SEEK_END);
  long int size = ftell(fp);
  rewind(fp);
  // read file into buffer
  char* buffer = new char[size];
  EXPECT(buffer);
  size_t res = fread(buffer, size, 1, fp);
  EXPECT(res == 1);
  // create memdisk
  mdisk = new MemDisk(buffer, buffer + size);
  EXPECT(mdisk);
}

CASE("Initialize FAT fs")
{
  disk = std::make_shared<Disk> (*mdisk);
  disk->init_fs(
    [&lest_env] (auto err, File_system& fs)
    {
      EXPECT(!err);
    });
}

CASE("List root directory")
{
  auto& fs = disk->fs();
  auto res = fs.ls("/");
  // validate root directory
  EXPECT(!res.error);
  EXPECT(res.entries->size() == 8);

  // validate each entry
  auto& ents = *res.entries;
  EXPECT(ents.at(0).name() == ".");
  EXPECT(ents.at(1).name() == "..");
  EXPECT(ents.at(2).name() == "folder");
  EXPECT(ents.at(3).name() == "test.pem");
  EXPECT(ents.at(4).name() == "test.der");
  EXPECT(ents.at(5).name() == "build.sh");
  EXPECT(ents.at(6).name() == "server.key");
  EXPECT(ents.at(7).name() == "test.key");
}

CASE("Validate /folder")
{
  auto& fs = disk->fs();
  // validate folder sync
  auto res = fs.ls("/folder/");
  EXPECT(!res.error);
  EXPECT(res.entries->size() == 3);

  // validate each entry
  auto& ents = *res.entries;
  EXPECT(ents.at(0).name() == ".");
  EXPECT(ents.at(1).name() == "..");
  EXPECT(ents.at(2).name() == "file.txt");

  // validate folder async
  fs.ls("/folder",
  [&lest_env] (auto error, Dirvec_ptr dirvec)
  {
    EXPECT(!error);
    auto& ents = *dirvec;
    EXPECT(ents.at(0).name() == ".");
    EXPECT(ents.at(1).name() == "..");
    EXPECT(ents.at(2).name() == "file.txt");
  });
}

CASE("Validate /folder using dirent")
{
  auto& fs = disk->fs();
  // get dirent by using stat()
  auto ent = fs.stat("/folder");
  EXPECT(ent.is_valid());
  EXPECT(ent.is_dir());

  // validate folder sync using dirent
  auto res = fs.ls(ent);
  EXPECT(!res.error);
  EXPECT(res.entries->size() == 3);

  // validate each entry
  auto& ents = *res.entries;
  EXPECT(ents.at(0).name() == ".");
  EXPECT(ents.at(1).name() == "..");
  EXPECT(ents.at(2).name() == "file.txt");

  // validate folder async using dirent
  fs.ls(ent,
  [&lest_env] (auto error, Dirvec_ptr dirvec)
  {
    EXPECT(!error);
    auto& ents = *dirvec;
    EXPECT(ents.at(0).name() == ".");
    EXPECT(ents.at(1).name() == "..");
    EXPECT(ents.at(2).name() == "file.txt");
  });
}

CASE("Validate /folder/file.txt")
{
  auto& fs = disk->fs();
  // read and validate file
  auto buffer = fs.read_file("/folder/file.txt");
  EXPECT(buffer.size() == 24);
  SHA1 sha1;
  sha1.update(buffer.data(), buffer.size());
  const std::string hash = sha1.as_hex();

  EXPECT(hash == "de1d4db81aa9344377ccfd49f5a239533d4f4ee3");

  const std::string text((const char*) buffer.data(), buffer.size());
  EXPECT(text == "This file contains text\n");
}

CASE("Stat /folder/file.txt")
{
  auto& fs = disk->fs();
  // get dirent by stat()
  auto ent = fs.stat("/folder/file.txt");
  EXPECT(ent.is_valid());
  EXPECT(ent.is_file());
  EXPECT(ent.size() == 24);

  // read and validate file using dirent
  auto buffer = fs.read(ent, 0, ent.size());
  EXPECT(buffer.size() == 24);

  const std::string text((const char*) buffer.data(), buffer.size());
  EXPECT(text == "This file contains text\n");
}
<|endoftext|>


<commit_before><commit_msg>Update net.cpp<commit_after><|endoftext|>


<commit_before>#pragma once

namespace principia {
namespace quantities {

template<int LengthExponent, int MassExponent, int TimeExponent,
         int CurrentExponent, int TemperatureExponent, int AmountExponent,
         int LuminousIntensityExponent, int WindingExponent,
         int AngleExponent, int SolidAngleExponent>
struct Dimensions {
  enum {
    Length            = LengthExponent,
    Mass              = MassExponent,
    Time              = TimeExponent,
    Current           = CurrentExponent,
    Temperature       = TemperatureExponent,
    Amount            = AmountExponent,
    LuminousIntensity = LuminousIntensityExponent,
    Winding           = WindingExponent,
    Angle             = AngleExponent,
    SolidAngle        = SolidAngleExponent
  };
};

namespace type_generators {
template<typename Q>
struct Collapse { typedef Q ResultType; };
template<>
struct Collapse<Quantity<NoDimensions>> { typedef Dimensionless ResultType; };
template<typename Left, typename Right>
struct ProductGenerator {
  enum {
    Length            = Left::Dimensions::Length + Right::Dimensions::Length,
    Mass              = Left::Dimensions::Mass + Right::Dimensions::Mass,
    Time              = Left::Dimensions::Time + Right::Dimensions::Time,
    Current           = Left::Dimensions::Current + Right::Dimensions::Current,
    Temperature       = Left::Dimensions::Temperature +
                        Right::Dimensions::Temperature,
    Amount            = Left::Dimensions::Amount + Right::Dimensions::Amount,
    LuminousIntensity = Left::Dimensions::LuminousIntensity +
                        Right:: Dimensions::LuminousIntensity,
    Winding           = Left::Dimensions::Winding + Right::Dimensions::Winding,
    Angle             = Left::Dimensions::Angle + Right::Dimensions::Angle,
    SolidAngle        = Left::Dimensions::SolidAngle +
                        Right::Dimensions::SolidAngle
  };
  typedef typename Collapse<
      Quantity<Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                          LuminousIntensity, Winding, Angle,
                          SolidAngle>>>::ResultType ResultType;
};
template<typename Left>
struct ProductGenerator<Left, Dimensionless> { typedef Left ResultType; };
template<typename Right>
struct ProductGenerator<Dimensionless, Right> { typedef Right ResultType; };
template<>
struct ProductGenerator<Dimensionless, Dimensionless> {
 typedef Dimensionless ResultType;
};
template<typename Left, typename Right>
struct QuotientGenerator {
  enum {
    Length            = Left::Dimensions::Length - Right::Dimensions::Length,
    Mass              = Left::Dimensions::Mass - Right::Dimensions::Mass,
    Time              = Left::Dimensions::Time - Right::Dimensions::Time,
    Current           = Left::Dimensions::Current - Right::Dimensions::Current,
    Temperature       = Left::Dimensions::Temperature -
                        Right::Dimensions::Temperature,
    Amount            = Left::Dimensions::Amount - Right::Dimensions::Amount,
    LuminousIntensity = Left::Dimensions::LuminousIntensity -
                        Right:: Dimensions::LuminousIntensity,
    Winding           = Left::Dimensions::Winding - Right::Dimensions::Winding,
    Angle             = Left::Dimensions::Angle - Right::Dimensions::Angle,
    SolidAngle        = Left::Dimensions::SolidAngle -
                        Right::Dimensions::SolidAngle
  };
  typedef typename Collapse<
      Quantity<Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                          LuminousIntensity, Winding, Angle,
                          SolidAngle>>>::ResultType ResultType;
};
template<typename Left>
struct QuotientGenerator<Left, Dimensionless> { typedef Left ResultType; };
template<>
struct QuotientGenerator<Dimensionless, Dimensionless> {
  typedef Dimensionless ResultType;
};
template<typename Right>
struct QuotientGenerator<Dimensionless, Right> {
  enum {
    Length            = -Right::Dimensions::Length,
    Mass              = -Right::Dimensions::Mass,
    Time              = -Right::Dimensions::Time,
    Current           = -Right::Dimensions::Current,
    Temperature       = -Right::Dimensions::Temperature,
    Amount            = -Right::Dimensions::Amount,
    LuminousIntensity = -Right::Dimensions::LuminousIntensity,
    Winding           = -Right::Dimensions::Winding,
    Angle             = -Right::Dimensions::Angle,
    SolidAngle        = -Right::Dimensions::SolidAngle
  };
  typedef Quantity<
      Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                 LuminousIntensity, Winding, Angle, SolidAngle>> ResultType;
};
template<typename Q, int Exponent, typename>
struct PowerGenerator {};
template<typename Q, int Exponent>
struct PowerGenerator<Q, Exponent, Range<(Exponent > 1)>> {
  typedef Product<
      typename PowerGenerator<Q, Exponent - 1>::ResultType, Q> ResultType;
};
template<typename Q, int Exponent>
struct PowerGenerator<Q, Exponent, Range<(Exponent < 1)>>{
  typedef Quotient<
      typename PowerGenerator<Q, Exponent + 1>::ResultType, Q> ResultType;
};
template<typename Q, int Exponent>
struct PowerGenerator<Q, Exponent, Range<(Exponent == 1)>>{
  typedef Q ResultType;
};
}  // namespace type_generators
namespace factories {
inline Length Metres(Dimensionless const& number) { return Length(number); }
inline Mass Kilograms(Dimensionless const& number) { return Mass(number); }
inline Time Seconds(Dimensionless const& number) { return Time(number); }
inline Current Amperes(Dimensionless const& number) { return Current(number); }
inline Temperature Kelvins(Dimensionless const& number) {
  return Temperature(number);
}
inline Amount Moles(Dimensionless const& number) { return Amount(number); }
inline LuminousIntensity Candelas(Dimensionless const& number) {
 return LuminousIntensity(number);
}
inline Winding Cycles(Dimensionless const& number) { return Winding(number); }
inline Angle Radians(Dimensionless const& number) { return Angle(number); }
inline SolidAngle Steradians(Dimensionless const& number) {
  return SolidAngle(number);
}
}  // namespace factories
template<typename D>
template<int Exponent>
Exponentiation<Quantity<D>, Exponent> Quantity<D>::Pow() const {
  return Exponentiation<Quantity<D>,
                        Exponent>(magnitude_.Pow(Exponent));
}

template<typename D>
inline Quantity<D>::Quantity(Dimensionless const& magnitude)
    : magnitude_(magnitude) {}

#pragma region Additive group
template<typename D>
inline Quantity<D> operator+(Quantity<D> const& right) {
  return Quantity<D>(+right.magnitude_);
}
template<typename D>
inline Quantity<D> operator-(Quantity<D> const& right) {
  return Quantity<D>(-right.magnitude_);
}
template<typename D>
inline Quantity<D> operator+(Quantity<D> const& left,
                             Quantity<D> const& right) {
  return Quantity<D>(left.magnitude_ + right.magnitude_);
}
template<typename D>
inline Quantity<D> operator-(Quantity<D> const& left,
                             Quantity<D> const& right) {
  return Quantity<D>(left.magnitude_ - right.magnitude_);
}
#pragma endregion
#pragma region Multiplicative group
template<typename DLeft, typename DRight>
inline Product <typename Quantity<DLeft>, typename Quantity <DRight>>
operator*(Quantity<DLeft> const& left,
          Quantity<DRight> const& right) {
  return Product<typename Quantity<DLeft>,
                 typename Quantity<DRight>>(left.magnitude_ *
                                             right.magnitude_);
}
template<typename DLeft, typename DRight>
inline Quotient<typename Quantity<DLeft>, typename Quantity <DRight>>
operator/(Quantity<DLeft> const& left,
          Quantity<DRight> const& right) {
  return Quotient<typename Quantity<DLeft>,
                  typename Quantity<DRight>>(left.magnitude_ /
                                              right.magnitude_);
}
template<typename D>
inline Quantity<D> operator*(Quantity<D> const& left,
                             Dimensionless const& right) {
  return Quantity<D>(left.magnitude_ * right);
}
template<typename D>
inline Quantity<D> operator*(Dimensionless const& left,
                             Quantity<D> const& right) {
  return Quantity<D>(left * right.magnitude_);
}
template<typename D>
inline Quantity<D> operator/(Quantity<D> const& left,
                             Dimensionless const& right) {
  return Quantity<D>(left.magnitude_ / right);
}
template<typename D>
inline Inverse<Quantity<D>> operator/(Dimensionless const& left,
                                      Quantity<D> const& right) {
  return Inverse<Quantity<D>>(left / right.magnitude_);
}
#pragma endregion
#pragma region Assigment operators
template<typename D>
inline void operator+=(Quantity<D>& left, Quantity<D> const& right) {
  left = left + right;
}
template<typename D>
inline void operator-=(Quantity<D>& left, Quantity<D> const& right) {
  left = left - right;
}
template<typename D>
inline void operator*=(Quantity<D>& left, Dimensionless const& right) {
  left = left * right;
}
template<typename D>
inline void operator/=(Quantity<D>& left, Dimensionless const& right) {
  left = left / right;
}
#pragma endregion
#pragma region Comparison operators
template<typename D>
inline bool operator>(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ > right.magnitude_;
}
template<typename D>
inline bool operator<(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ < right.magnitude_;
}
template<typename D>
inline bool operator>=(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ >= right.magnitude_;
}
template<typename D>
inline bool operator<=(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ <= right.magnitude_;
}
template<typename D>
inline bool operator==(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ == right.magnitude_;
}
template<typename D>
inline bool operator!=(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ != right.magnitude_;
}
#pragma endregion

template<typename D>
inline Quantity<D> Abs(Quantity<D> const& quantity) {
  return Quantity<D>(Abs(quantity.magnitude_));
}

template<typename D>
inline std::wstring ToString(Quantity<D> const& quantity,
                             unsigned char const precision) {
  return ToString(quantity.magnitude_, precision) +
      (D::Length            != 0 ? L" m^" + std::to_wstring(D::Length) : L"") +
      (D::Mass              != 0 ? L" kg^" + std::to_wstring(D::Mass) : L"") +
      (D::Time              != 0 ? L" s^" + std::to_wstring(D::Time) : L"") +
      (D::Current           != 0 ? L" A^" + std::to_wstring(D::Current) : L"") +
      (D::Temperature       != 0 ?
          L" K^" + std::to_wstring(D::Temperature) : L"") +
      (D::Amount            != 0 ?
          L" mol^" + std::to_wstring(D::Amount) : L"") +
      (D::LuminousIntensity != 0 ?
          L" cd^" + std::to_wstring(D::LuminousIntensity) : L"") +
      (D::Winding           != 0 ?
          L" cycle^" + std::to_wstring(D::Winding) : L"") +
      (D::Angle             != 0 ? L" rad^" + std::to_wstring(D::Angle) : L"") +
      (D::SolidAngle        != 0 ?
          L" sr^" + std::to_wstring(D::SolidAngle) : L"");
  }
  }  // namespace quantities
  }  // namespace principia
<commit_msg>Fix Quantities-body following review by @pleroy.<commit_after>#pragma once

#include <string>

namespace principia {
namespace quantities {

template<int LengthExponent, int MassExponent, int TimeExponent,
         int CurrentExponent, int TemperatureExponent, int AmountExponent,
         int LuminousIntensityExponent, int WindingExponent,
         int AngleExponent, int SolidAngleExponent>
struct Dimensions {
  enum {
    Length            = LengthExponent,
    Mass              = MassExponent,
    Time              = TimeExponent,
    Current           = CurrentExponent,
    Temperature       = TemperatureExponent,
    Amount            = AmountExponent,
    LuminousIntensity = LuminousIntensityExponent,
    Winding           = WindingExponent,
    Angle             = AngleExponent,
    SolidAngle        = SolidAngleExponent
  };
};

namespace type_generators {
template<typename Q>
struct Collapse { typedef Q ResultType; };
template<>
struct Collapse<Quantity<NoDimensions>> { typedef Dimensionless ResultType; };
template<typename Left, typename Right>
struct ProductGenerator {
  enum {
    Length            = Left::Dimensions::Length + Right::Dimensions::Length,
    Mass              = Left::Dimensions::Mass + Right::Dimensions::Mass,
    Time              = Left::Dimensions::Time + Right::Dimensions::Time,
    Current           = Left::Dimensions::Current + Right::Dimensions::Current,
    Temperature       = Left::Dimensions::Temperature +
                        Right::Dimensions::Temperature,
    Amount            = Left::Dimensions::Amount + Right::Dimensions::Amount,
    LuminousIntensity = Left::Dimensions::LuminousIntensity +
                        Right:: Dimensions::LuminousIntensity,
    Winding           = Left::Dimensions::Winding + Right::Dimensions::Winding,
    Angle             = Left::Dimensions::Angle + Right::Dimensions::Angle,
    SolidAngle        = Left::Dimensions::SolidAngle +
                        Right::Dimensions::SolidAngle
  };
  typedef typename Collapse<
      Quantity<Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                          LuminousIntensity, Winding, Angle,
                          SolidAngle>>>::ResultType ResultType;
};
template<typename Left>
struct ProductGenerator<Left, Dimensionless> { typedef Left ResultType; };
template<typename Right>
struct ProductGenerator<Dimensionless, Right> { typedef Right ResultType; };
template<>
struct ProductGenerator<Dimensionless, Dimensionless> {
 typedef Dimensionless ResultType;
};
template<typename Left, typename Right>
struct QuotientGenerator {
  enum {
    Length            = Left::Dimensions::Length - Right::Dimensions::Length,
    Mass              = Left::Dimensions::Mass - Right::Dimensions::Mass,
    Time              = Left::Dimensions::Time - Right::Dimensions::Time,
    Current           = Left::Dimensions::Current - Right::Dimensions::Current,
    Temperature       = Left::Dimensions::Temperature -
                        Right::Dimensions::Temperature,
    Amount            = Left::Dimensions::Amount - Right::Dimensions::Amount,
    LuminousIntensity = Left::Dimensions::LuminousIntensity -
                        Right:: Dimensions::LuminousIntensity,
    Winding           = Left::Dimensions::Winding - Right::Dimensions::Winding,
    Angle             = Left::Dimensions::Angle - Right::Dimensions::Angle,
    SolidAngle        = Left::Dimensions::SolidAngle -
                        Right::Dimensions::SolidAngle
  };
  typedef typename Collapse<
      Quantity<Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                          LuminousIntensity, Winding, Angle,
                          SolidAngle>>>::ResultType ResultType;
};
template<typename Left>
struct QuotientGenerator<Left, Dimensionless> { typedef Left ResultType; };
template<>
struct QuotientGenerator<Dimensionless, Dimensionless> {
  typedef Dimensionless ResultType;
};
template<typename Right>
struct QuotientGenerator<Dimensionless, Right> {
  enum {
    Length            = -Right::Dimensions::Length,
    Mass              = -Right::Dimensions::Mass,
    Time              = -Right::Dimensions::Time,
    Current           = -Right::Dimensions::Current,
    Temperature       = -Right::Dimensions::Temperature,
    Amount            = -Right::Dimensions::Amount,
    LuminousIntensity = -Right::Dimensions::LuminousIntensity,
    Winding           = -Right::Dimensions::Winding,
    Angle             = -Right::Dimensions::Angle,
    SolidAngle        = -Right::Dimensions::SolidAngle
  };
  typedef Quantity<
      Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                 LuminousIntensity, Winding, Angle, SolidAngle>> ResultType;
};
template<typename Q, int Exponent, typename>
struct PowerGenerator {};
template<typename Q, int Exponent>
struct PowerGenerator<Q, Exponent, Range<(Exponent > 1)>> {
  typedef Product<
      typename PowerGenerator<Q, Exponent - 1>::ResultType, Q> ResultType;
};
template<typename Q, int Exponent>
struct PowerGenerator<Q, Exponent, Range<(Exponent < 1)>>{
  typedef Quotient<
      typename PowerGenerator<Q, Exponent + 1>::ResultType, Q> ResultType;
};
template<typename Q, int Exponent>
struct PowerGenerator<Q, Exponent, Range<(Exponent == 1)>>{
  typedef Q ResultType;
};
}  // namespace type_generators
namespace factories {
inline Length Metres(Dimensionless const& number) { return Length(number); }
inline Mass Kilograms(Dimensionless const& number) { return Mass(number); }
inline Time Seconds(Dimensionless const& number) { return Time(number); }
inline Current Amperes(Dimensionless const& number) { return Current(number); }
inline Temperature Kelvins(Dimensionless const& number) {
  return Temperature(number);
}
inline Amount Moles(Dimensionless const& number) { return Amount(number); }
inline LuminousIntensity Candelas(Dimensionless const& number) {
 return LuminousIntensity(number);
}
inline Winding Cycles(Dimensionless const& number) { return Winding(number); }
inline Angle Radians(Dimensionless const& number) { return Angle(number); }
inline SolidAngle Steradians(Dimensionless const& number) {
  return SolidAngle(number);
}
}  // namespace factories
template<typename D>
template<int Exponent>
Exponentiation<Quantity<D>, Exponent> Quantity<D>::Pow() const {
  return Exponentiation<Quantity<D>,
                        Exponent>(magnitude_.Pow(Exponent));
}

template<typename D>
inline Quantity<D>::Quantity(Dimensionless const& magnitude)
    : magnitude_(magnitude) {}

#pragma region Additive group
template<typename D>
inline Quantity<D> operator+(Quantity<D> const& right) {
  return Quantity<D>(+right.magnitude_);
}
template<typename D>
inline Quantity<D> operator-(Quantity<D> const& right) {
  return Quantity<D>(-right.magnitude_);
}
template<typename D>
inline Quantity<D> operator+(Quantity<D> const& left,
                             Quantity<D> const& right) {
  return Quantity<D>(left.magnitude_ + right.magnitude_);
}
template<typename D>
inline Quantity<D> operator-(Quantity<D> const& left,
                             Quantity<D> const& right) {
  return Quantity<D>(left.magnitude_ - right.magnitude_);
}
#pragma endregion
#pragma region Multiplicative group
template<typename DLeft, typename DRight>
inline Product <typename Quantity<DLeft>, typename Quantity <DRight>>
operator*(Quantity<DLeft> const& left,
          Quantity<DRight> const& right) {
  return Product<typename Quantity<DLeft>,
                 typename Quantity<DRight>>(left.magnitude_ *
                                             right.magnitude_);
}
template<typename DLeft, typename DRight>
inline Quotient<typename Quantity<DLeft>, typename Quantity <DRight>>
operator/(Quantity<DLeft> const& left,
          Quantity<DRight> const& right) {
  return Quotient<typename Quantity<DLeft>,
                  typename Quantity<DRight>>(left.magnitude_ /
                                              right.magnitude_);
}
template<typename D>
inline Quantity<D> operator*(Quantity<D> const& left,
                             Dimensionless const& right) {
  return Quantity<D>(left.magnitude_ * right);
}
template<typename D>
inline Quantity<D> operator*(Dimensionless const& left,
                             Quantity<D> const& right) {
  return Quantity<D>(left * right.magnitude_);
}
template<typename D>
inline Quantity<D> operator/(Quantity<D> const& left,
                             Dimensionless const& right) {
  return Quantity<D>(left.magnitude_ / right);
}
template<typename D>
inline Inverse<Quantity<D>> operator/(Dimensionless const& left,
                                      Quantity<D> const& right) {
  return Inverse<Quantity<D>>(left / right.magnitude_);
}
#pragma endregion
#pragma region Assigment operators
template<typename D>
inline void operator+=(Quantity<D>& left, Quantity<D> const& right) {
  left = left + right;
}
template<typename D>
inline void operator-=(Quantity<D>& left, Quantity<D> const& right) {
  left = left - right;
}
template<typename D>
inline void operator*=(Quantity<D>& left, Dimensionless const& right) {
  left = left * right;
}
template<typename D>
inline void operator/=(Quantity<D>& left, Dimensionless const& right) {
  left = left / right;
}
#pragma endregion
#pragma region Comparison operators
template<typename D>
inline bool operator>(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ > right.magnitude_;
}
template<typename D>
inline bool operator<(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ < right.magnitude_;
}
template<typename D>
inline bool operator>=(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ >= right.magnitude_;
}
template<typename D>
inline bool operator<=(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ <= right.magnitude_;
}
template<typename D>
inline bool operator==(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ == right.magnitude_;
}
template<typename D>
inline bool operator!=(Quantity<D> const& left, Quantity<D> const& right) {
  return left.magnitude_ != right.magnitude_;
}
#pragma endregion

template<typename D>
inline Quantity<D> Abs(Quantity<D> const& quantity) {
  return Quantity<D>(Abs(quantity.magnitude_));
}

inline std::wstring FormatUnit(std::wstring name, int const exponent) {
  switch(exponent) {
    case 0:
      return L"";
      break;
    case 1:
      return name;
    default:
      return L" " + name + L"^" + std::to_wstring(exponent);
  }
}

template<typename D>
inline std::wstring ToString(Quantity<D> const& quantity,
                             unsigned char const precision) {
  return ToString(quantity.magnitude_, precision) +
      FormatUnit(L"m", D::Length) + FormatUnit(L"kg", D::Mass) +
      FormatUnit(L"s", D::Time) + FormatUnit(L"A", D::Current) +
      FormatUnit(L"K", D::Temperature) + FormatUnit(L"mol", D::Amount) +
      FormatUnit(L"cd", D::LuminousIntensity) +
      FormatUnit(L"cycle", D::Winding) + FormatUnit(L"rad", D::Angle) +
      FormatUnit(L"sr", D::SolidAngle);
  }
  }  // namespace quantities
  }  // namespace principia
<|endoftext|>