<commit_before>/*
	Optimal Read Normalization Algorithm:
	Developed by : Dilip A Durai and Marcel H Schulz
*/

//File last modified 28/11/2016

#include <gatb/gatb_core.hpp>
#include <iostream>
#include <string.h>
#include <math.h>

typedef Kmer<>::Type bloom;
//Error Correction
int errorcorrection(Graph graph, Kmer<>::ModelCanonical::Iterator itKmer, Kmer<>::ModelCanonical model, int length, int kmer){

	int stretch=0;
	int startkmer = 0;
	int endkmer = 0;
	int flag=1;
	int position = 0;
	int numerror=0;
	for(itKmer.first(); !itKmer.isDone(); itKmer.next())
	{
		std::string ts = model.toString (itKmer->value());
		const char* tsq = ts.c_str();
		Node tnode = graph.buildNode(tsq);
		if(!(graph.contains(tnode)) && (startkmer==1))
		{
			stretch+=1;
			position+=1;
		}
		else
		{
			if(position==0)
			{
				startkmer=1;
			}
			if(position == (length-kmer))
			{
				endkmer=1;
			}
			if(stretch==kmer)
			{
				if((startkmer==1)){
					numerror=1;
				}
			}
			stretch=0;
			position+=1;
		}
	}
	if(numerror==1)
	{
		if(endkmer==1)
		{
			flag=0;
		}
	}
	return flag;
}

int readacceptance(Graph graph, Kmer<>::ModelCanonical::Iterator itKmer, Kmer<>::ModelCanonical model, int *counter, int t){
	int acceptance=0;
	for (itKmer.first(); !itKmer.isDone(); itKmer.next())
	{
		std::string s = model.toString (itKmer->value());
		const char* sq = s.c_str();
		Node node = graph.buildNode(sq);
		//Checking whether the node exists.
		if(!(graph.contains(node)))
	       	{
			__sync_fetch_and_add (&acceptance, 1);
		}
		else
		{
			auto index = graph.nodeMPHFIndex(node);
			auto abund = graph.queryAbundance(node);
			if(abund > t){
				t = ceil(log10(abund));
			}
			if(counter[index] < t)
		        {
				__sync_fetch_and_add (&acceptance, 1);
				//__sync_fetch_and_add (&counter[index], 1);
	       		}
		}
	}
	return acceptance;
}
/*
int garbageremoval(char *data, int size)
{
	int flag=0;
	int ch[5] = {0,0,0,0,0};
	for (size_t i=0; i<seq.getDataSize (); i++)
	{
		if (data[i]=='N' ) {
			ch[0]+=1;
		}
		else if (data[i]=='A' ) {
			ch[1]+=1;
		}
		else if (data[i]=='C' ) {
			ch[2]+=1;
		}
		else if (data[i]=='T' ) {
			ch[3]+=1;
		}
		else{
			ch[4]+=1;
		}
	}
	for(int i=1;i<=4;i++)
	{
		if(ch[i]>=0.70*length)
		{
			flag=0;
		}
	}
	if(ch[0]>=10)
	{
		flag=0;
	}
	return flag;
}*/

int main (int argc, char* argv[])
{
    try
    {
        //Variables required by ORNA
        int count=0;
        int t=atoi(argv[3]);
        int kmer = atoi(argv[4]);
        const char* filename = argv[1];
	const char* out_file= argv[2];

        //Multithreading variables test (last modified 23/11/2016)
        auto nbCores = atoi(argv[5]);
        Dispatcher dispatcher (nbCores);
	ISynchronizer* synchro = System::thread().newSynchronizer();	//Locking a section

        //Variables required for GATB
        IBank* bank = Bank::open (filename);
        ProgressIterator<Sequence> itSeq (*bank);
        IBank* outBank = new BankFasta (out_file);

        //Creating a graph and an iterator. from the parameters. The threshold value is kept as the minimum abundance parameter of the graph. kmer size is the actual kmer+1
        Graph graph = Graph::create (Bank::open(argv[1]), "-kmer-size %s -abundance-min 3", argv[4]);
        Graph::Iterator<Node> it = graph.iterator();

        int node_size= it.size();
        int *counter = new int[node_size];
        int *flg= new int[node_size];

        //Initializing the counter for each node in the de Bruijn graph
        for(int i=0;i<node_size;i++)
        {
            counter[i]=0;
            flg[i]=0;
        }

	//Iterating over sequences
        dispatcher.iterate (itSeq, [&] (Sequence& seq)
	{
		int length = seq.getDataSize();
		int flag=1;
		int gb = 1;
		int acceptance=0;

		Kmer<>::ModelCanonical model (kmer);
        	Kmer<>::ModelCanonical::Iterator itKmer (model);
		itKmer.setData (seq.getData());
		char* data = seq.getDataBuffer();
		//Garbage Removal
		//gb = garbageremoval(graph, )
		//Error Correction
		if(gb==1){
			flag=errorcorrection(graph, itKmer, model, length, kmer);
		}
		//checking the thresholding
		if(flag==1){
			acceptance=readacceptance(graph, itKmer, model, counter, t);
		}
		if(acceptance > 0)
		{
			for (itKmer.first(); !itKmer.isDone(); itKmer.next())
			{
				std::string s = model.toString (itKmer->value());
				const char* sq = s.c_str();
				Node node = graph.buildNode(sq);
				//Checking whether the node exists.
				if(graph.contains(node))
	       			{
					auto index = graph.nodeMPHFIndex(node);
					__sync_fetch_and_add (&counter[index], 1);
				}
			}
			synchro->lock();
			outBank->insert(seq);
			count++;
			synchro->unlock();
		}

	});
	std::cout << count << std::endl;

	//Free the memory
        delete [] counter;
        delete [] flg;
        bank->flush();
        outBank->flush();
    }
    catch (Exception& e)
    {
        std::cerr << "EXCEPTION: " << e.getMessage() << std::endl;
    }
    return EXIT_SUCCESS;
}

<commit_msg>Latest version of code<commit_after>/*
	Optimal Read Normalization Algorithm:
	Developed by : Dilip A Durai and Marcel H Schulz
*/

//File last modified 28/11/2016

#include <gatb/gatb_core.hpp>
#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>

typedef Kmer<>::Type bloom;
int errorcorrection(Graph graph, Kmer<>::ModelCanonical::Iterator itKmer, Kmer<>::ModelCanonical model, int length, int kmer){

	int stretch=0;
	int startkmer = 0;
	int endkmer = 0;
	int flag=1;
	int position = 0;
	int numerror=0;
	for(itKmer.first(); !itKmer.isDone(); itKmer.next())
	{
		std::string ts = model.toString (itKmer->value());
		const char* tsq = ts.c_str();
		Node tnode = graph.buildNode(tsq);
		if(!(graph.contains(tnode)) && (startkmer==1))
		{
			stretch+=1;
			position+=1;
		}
		else
		{
			if(position==0)
			{
				startkmer=1;
			}
			if(position == (length-kmer))
			{
				endkmer=1;
			}
			if(stretch==kmer)
			{
				if((startkmer==1)){
					numerror=1;
				}
			}
			stretch=0;
			position+=1;
		}
	}
	if(numerror==1)
	{
		if(endkmer==1)
		{
			flag=0;
		}
	}
	return flag;
}

int readacceptance(Graph graph, Kmer<>::ModelCanonical::Iterator itKmer, Kmer<>::ModelCanonical model, long *counter, double t){
	int acceptance=0;
	for (itKmer.first(); !itKmer.isDone(); itKmer.next())
	{
		std::string s = model.toString (itKmer->value());
		const char* sq = s.c_str();
		Node node = graph.buildNode(sq);
		double threshold=0;
		//Checking whether the node exists.
		auto index = graph.nodeMPHFIndex(node);
		auto abund = graph.queryAbundance(node);
		threshold = ceil((log(abund)/log(t)));
		if(threshold>abund)
		{
			threshold=abund;
		}
		if(threshold<1)
		{
			threshold=1;
		}
		if(counter[index] < threshold)
		{
			__sync_fetch_and_add (&acceptance, 1);
			//__sync_fetch_and_add (&counter[index], 1);
	       	}
	}
	return acceptance;
}

int main (int argc, char* argv[])
{
    try
    {
        //Variables required by ORNA
        int count=0;
        double t=atof(argv[3]);
	std::cout << t << std::endl;
        int kmer = atoi(argv[4]);
        const char* filename = argv[1];
	const char* out_file= argv[2];

        //Multithreading variables test (last modified 23/11/2016)
        auto nbCores = atoi(argv[5]);
        Dispatcher dispatcher (nbCores);
	ISynchronizer* synchro = System::thread().newSynchronizer();	//Locking a section

        //Variables required for GATB
        IBank* bank = Bank::open (filename);
        ProgressIterator<Sequence> itSeq (*bank);
        IBank* outBank = new BankFasta (out_file);

        //Creating a graph and an iterator. from the parameters. The threshold value is kept as the minimum abundance parameter of the graph. kmer size is the actual kmer+1
        Graph graph = Graph::create (Bank::open(argv[1]), "-kmer-size %s -abundance-min 1", argv[4]);
        Graph::Iterator<Node> it = graph.iterator();

        long node_size= it.size();
        long *counter = new long[node_size];
        //Initializing the counter for each node in the de Bruijn graph
        for(int i=0;i<node_size;i++)
        {
            counter[i]=0;
        }

	//Iterating over sequences
        dispatcher.iterate (itSeq, [&] (Sequence& seq)
	{
		int length = seq.getDataSize();
		int flag=1;
		int gb = 1;
		int acceptance=0;

		Kmer<>::ModelCanonical model (kmer);
        	Kmer<>::ModelCanonical::Iterator itKmer (model);
		itKmer.setData (seq.getData());
		char* data = seq.getDataBuffer();
		//Error Correction
		if(gb==1){
			//flag=errorcorrection(graph, itKmer, model, length, kmer);
		}
		//checking the thresholding
		if(flag==1){
			acceptance=readacceptance(graph, itKmer, model, counter, t);
		}
		if(acceptance > 0)
		{
			for (itKmer.first(); !itKmer.isDone(); itKmer.next())
			{
				std::string s = model.toString (itKmer->value());
				const char* sq = s.c_str();
				Node node = graph.buildNode(sq);
				//Checking whether the node exists.
				if(graph.contains(node))
	       			{
					auto index = graph.nodeMPHFIndex(node);
					__sync_fetch_and_add (&counter[index], 1);
				}
			}
			synchro->lock();
			outBank->insert(seq);
			count++;
			synchro->unlock();
		}

	});
	std::cout << count << std::endl;

	//Free the memory
        delete [] counter;
        bank->flush();
        outBank->flush();
    }
    catch (Exception& e)
    {
        std::cerr << "EXCEPTION: " << e.getMessage() << std::endl;
    }
    return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/CallGraphSCCPass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/RegionPass.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/IRReader.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/LinkAllVMCore.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include <memory>
#include <algorithm>
#include "rampancy/Compiler.h"
#include "rampancy/CompilerManager.h"
#include "rampancy/CompilerRegistry.h"
#include "rampancy/Cortex.h"
#include "rampancy/ClangCompiler.h"
using namespace llvm;
extern "C" {
#include <stdio.h>
#include "setup.h"
#include "clips.h"
}

extern "C" void UserFunctions(void);
extern "C" void EnvUserFunctions(void *);
int main(int argc, char** argv) {

   //set argv[0] for clang
   rampancy::ClangCompiler::argv0 = argv[0];
   rampancy::Cortex* rampantCortex = rampancy::Cortex::getRampantCortex();
   rampancy::CompilerRegistry* compilerRegistry =
      rampancy::CompilerRegistry::getCompilerRegistry();
   PassRegistry &registry = *PassRegistry::getPassRegistry();
   initializeCore(registry);
   initializeScalarOpts(registry);
   initializeVectorization(registry);
   initializeIPO(registry);
   initializeAnalysis(registry);
   initializeIPA(registry);
   initializeTransformUtils(registry);
   initializeInstCombine(registry);
   initializeInstrumentation(registry);
   initializeTarget(registry);
   rampancy::initializeClangCompilerPass(registry);
   rampancy::ClangCompiler cc;
   //set the
   StringRef clangName("clang");
   compilerRegistry->registerCompiler(clangName, &cc);

   RerouteStdin(rampantCortex->getEnvironment()->getEnvironment(),argc,argv);
   CommandLoop(rampantCortex->getEnvironment()->getEnvironment());
}
<commit_msg>Disabled the call to initializeClangCompilerPass<commit_after>#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/CallGraphSCCPass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/RegionPass.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/IRReader.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/LinkAllVMCore.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include <memory>
#include <algorithm>
#include "rampancy/Compiler.h"
#include "rampancy/CompilerManager.h"
#include "rampancy/CompilerRegistry.h"
#include "rampancy/Cortex.h"
#include "rampancy/ClangCompiler.h"
using namespace llvm;
extern "C" {
#include <stdio.h>
#include "setup.h"
#include "clips.h"
}

extern "C" void UserFunctions(void);
extern "C" void EnvUserFunctions(void *);
int main(int argc, char** argv) {

   //set argv[0] for clang
   rampancy::ClangCompiler::argv0 = argv[0];
   rampancy::Cortex* rampantCortex = rampancy::Cortex::getRampantCortex();
   rampancy::CompilerRegistry* compilerRegistry =
      rampancy::CompilerRegistry::getCompilerRegistry();
   PassRegistry &registry = *PassRegistry::getPassRegistry();
   initializeCore(registry);
   initializeScalarOpts(registry);
   initializeVectorization(registry);
   initializeIPO(registry);
   initializeAnalysis(registry);
   initializeIPA(registry);
   initializeTransformUtils(registry);
   initializeInstCombine(registry);
   initializeInstrumentation(registry);
   initializeTarget(registry);
//   rampancy::initializeClangCompilerPass(registry);
   rampancy::ClangCompiler cc;
   //set the
   StringRef clangName("clang");
   compilerRegistry->registerCompiler(clangName, &cc);

   RerouteStdin(rampantCortex->getEnvironment()->getEnvironment(),argc,argv);
   CommandLoop(rampantCortex->getEnvironment()->getEnvironment());
}
<|endoftext|>


<commit_before>//===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the entry point to the clang driver; it is a thin wrapper
// for functionality in the Driver clang library.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Config/config.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
#include "llvm/System/Signals.h"
using namespace clang;
using namespace clang::driver;

class DriverDiagnosticPrinter : public DiagnosticClient {
  std::string ProgName;
  llvm::raw_ostream &OS;

public:
  DriverDiagnosticPrinter(const std::string _ProgName,
                          llvm::raw_ostream &_OS)
    : ProgName(_ProgName),
      OS(_OS) {}

  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
                                const DiagnosticInfo &Info);
};

void DriverDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
                                               const DiagnosticInfo &Info) {
  OS << ProgName << ": ";

  switch (Level) {
  case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
  case Diagnostic::Note:    OS << "note: "; break;
  case Diagnostic::Warning: OS << "warning: "; break;
  case Diagnostic::Error:   OS << "error: "; break;
  case Diagnostic::Fatal:   OS << "fatal error: "; break;
  }

  llvm::SmallString<100> OutStr;
  Info.FormatDiagnostic(OutStr);
  OS.write(OutStr.begin(), OutStr.size());
  OS << '\n';
}

llvm::sys::Path GetExecutablePath(const char *Argv0) {
  // This just needs to be some symbol in the binary; C++ doesn't
  // allow taking the address of ::main however.
  void *P = (void*) (intptr_t) GetExecutablePath;
  return llvm::sys::Path::GetMainExecutable(Argv0, P);
}

static const char *SaveStringInSet(std::set<std::string> &SavedStrings,
                                   const std::string &S) {
  return SavedStrings.insert(S).first->c_str();
}

/// ApplyQAOverride - Apply a list of edits to the input argument lists.
///
/// The input string is a space separate list of edits to perform,
/// they are applied in order to the input argument lists. Edits
/// should be one of the following forms:
///
///  '^': Add FOO as a new argument at the beginning of the command line.
///
///  '+': Add FOO as a new argument at the end of the command line.
///
///  's/XXX/YYY/': Replace the literal argument XXX by YYY in the
///  command line.
///
///  'xOPTION': Removes all instances of the literal argument OPTION.
///
///  'XOPTION': Removes all instances of the literal argument OPTION,
///  and the following argument.
///
///  'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
///  at the end of the command line.
void ApplyOneQAOverride(std::vector<const char*> &Args,
                        const std::string &Edit,
                        std::set<std::string> &SavedStrings) {
  // This does not need to be efficient.

   if (Edit[0] == '^') {
     const char *Str =
       SaveStringInSet(SavedStrings, Edit.substr(1, std::string::npos));
     llvm::errs() << "### Adding argument " << Str << " at beginning\n";
     Args.insert(Args.begin() + 1, Str);
   } else if (Edit[0] == '+') {
     const char *Str =
       SaveStringInSet(SavedStrings, Edit.substr(1, std::string::npos));
     llvm::errs() << "### Adding argument " << Str << " at end\n";
     Args.push_back(Str);
   } else if (Edit[0] == 'x' || Edit[0] == 'X') {
     std::string Option = Edit.substr(1, std::string::npos);
     for (unsigned i = 1; i < Args.size();) {
       if (Option == Args[i]) {
         llvm::errs() << "### Deleting argument " << Args[i] << '\n';
         Args.erase(Args.begin() + i);
         if (Edit[0] == 'X') {
           if (i < Args.size()) {
             llvm::errs() << "### Deleting argument " << Args[i] << '\n';
             Args.erase(Args.begin() + i);
           } else
             llvm::errs() << "### Invalid X edit, end of command line!\n";
         }
       } else
         ++i;
     }
   } else if (Edit[0] == 'O') {
     for (unsigned i = 1; i < Args.size();) {
       const char *A = Args[i];
       if (A[0] == '-' && A[1] == 'O' &&
           (A[2] == '\0' ||
            (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
                              ('0' <= A[2] && A[2] <= '9'))))) {
         llvm::errs() << "### Deleting argument " << Args[i] << '\n';
         Args.erase(Args.begin() + i);
       } else
         ++i;
     }
     llvm::errs() << "### Adding argument " << Edit << " at end\n";
     Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit));
   } else {
     llvm::errs() << "### Unrecognized edit: " << Edit << "\n";
   }
}

/// ApplyQAOverride - Apply a comma separate list of edits to the
/// input argument lists. See ApplyOneQAOverride.
void ApplyQAOverride(std::vector<const char*> &Args, const char *OverrideStr,
                     std::set<std::string> &SavedStrings) {
  llvm::errs() << "### QA_OVERRIDE_GCC3_OPTIONS: " << OverrideStr << "\n";

  // This does not need to be efficient.

  const char *S = OverrideStr;
  while (*S) {
    const char *End = ::strchr(S, ' ');
    if (!End)
      End = S + strlen(S);
    if (End != S)
      ApplyOneQAOverride(Args, std::string(S, End), SavedStrings);
    S = End;
    if (*S != '\0')
      ++S;
  }
}

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal();
  llvm::PrettyStackTraceProgram X(argc, argv);

  llvm::sys::Path Path = GetExecutablePath(argv[0]);
  llvm::OwningPtr<DiagnosticClient>
    DiagClient(new DriverDiagnosticPrinter(Path.getBasename(), llvm::errs()));

  Diagnostic Diags(DiagClient.get());

  llvm::OwningPtr<Driver>
    TheDriver(new Driver(Path.getBasename().c_str(), Path.getDirname().c_str(),
                         llvm::sys::getHostTriple().c_str(),
                         "a.out", Diags));

  llvm::OwningPtr<Compilation> C;

  // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
  // command line behind the scenes.
  std::set<std::string> SavedStrings;
  if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
    // FIXME: Driver shouldn't take extra initial argument.
    std::vector<const char*> StringPointers(argv, argv + argc);

    ApplyQAOverride(StringPointers, OverrideStr, SavedStrings);

    C.reset(TheDriver->BuildCompilation(StringPointers.size(),
                                        &StringPointers[0]));
  } else if (const char *Cur = ::getenv("CCC_ADD_ARGS")) {
    std::vector<const char*> StringPointers;

    // FIXME: Driver shouldn't take extra initial argument.
    StringPointers.push_back(argv[0]);

    for (;;) {
      const char *Next = strchr(Cur, ',');

      if (Next) {
        StringPointers.push_back(SaveStringInSet(SavedStrings,
                                                 std::string(Cur, Next)));
        Cur = Next + 1;
      } else {
        if (*Cur != '\0')
          StringPointers.push_back(SaveStringInSet(SavedStrings, Cur));
        break;
      }
    }

    StringPointers.insert(StringPointers.end(), argv + 1, argv + argc);

    C.reset(TheDriver->BuildCompilation(StringPointers.size(),
                                        &StringPointers[0]));
  } else
    C.reset(TheDriver->BuildCompilation(argc, argv));

  int Res = 0;
  if (C.get())
    Res = C->Execute();

  llvm::llvm_shutdown();

  return Res;
}

<commit_msg>The driver/diagnostic client don't need to be on the heap.<commit_after>//===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the entry point to the clang driver; it is a thin wrapper
// for functionality in the Driver clang library.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Config/config.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
#include "llvm/System/Signals.h"
using namespace clang;
using namespace clang::driver;

class DriverDiagnosticPrinter : public DiagnosticClient {
  std::string ProgName;
  llvm::raw_ostream &OS;

public:
  DriverDiagnosticPrinter(const std::string _ProgName,
                          llvm::raw_ostream &_OS)
    : ProgName(_ProgName),
      OS(_OS) {}

  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
                                const DiagnosticInfo &Info);
};

void DriverDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
                                               const DiagnosticInfo &Info) {
  OS << ProgName << ": ";

  switch (Level) {
  case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
  case Diagnostic::Note:    OS << "note: "; break;
  case Diagnostic::Warning: OS << "warning: "; break;
  case Diagnostic::Error:   OS << "error: "; break;
  case Diagnostic::Fatal:   OS << "fatal error: "; break;
  }

  llvm::SmallString<100> OutStr;
  Info.FormatDiagnostic(OutStr);
  OS.write(OutStr.begin(), OutStr.size());
  OS << '\n';
}

llvm::sys::Path GetExecutablePath(const char *Argv0) {
  // This just needs to be some symbol in the binary; C++ doesn't
  // allow taking the address of ::main however.
  void *P = (void*) (intptr_t) GetExecutablePath;
  return llvm::sys::Path::GetMainExecutable(Argv0, P);
}

static const char *SaveStringInSet(std::set<std::string> &SavedStrings,
                                   const std::string &S) {
  return SavedStrings.insert(S).first->c_str();
}

/// ApplyQAOverride - Apply a list of edits to the input argument lists.
///
/// The input string is a space separate list of edits to perform,
/// they are applied in order to the input argument lists. Edits
/// should be one of the following forms:
///
///  '^': Add FOO as a new argument at the beginning of the command line.
///
///  '+': Add FOO as a new argument at the end of the command line.
///
///  's/XXX/YYY/': Replace the literal argument XXX by YYY in the
///  command line.
///
///  'xOPTION': Removes all instances of the literal argument OPTION.
///
///  'XOPTION': Removes all instances of the literal argument OPTION,
///  and the following argument.
///
///  'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
///  at the end of the command line.
void ApplyOneQAOverride(std::vector<const char*> &Args,
                        const std::string &Edit,
                        std::set<std::string> &SavedStrings) {
  // This does not need to be efficient.

   if (Edit[0] == '^') {
     const char *Str =
       SaveStringInSet(SavedStrings, Edit.substr(1, std::string::npos));
     llvm::errs() << "### Adding argument " << Str << " at beginning\n";
     Args.insert(Args.begin() + 1, Str);
   } else if (Edit[0] == '+') {
     const char *Str =
       SaveStringInSet(SavedStrings, Edit.substr(1, std::string::npos));
     llvm::errs() << "### Adding argument " << Str << " at end\n";
     Args.push_back(Str);
   } else if (Edit[0] == 'x' || Edit[0] == 'X') {
     std::string Option = Edit.substr(1, std::string::npos);
     for (unsigned i = 1; i < Args.size();) {
       if (Option == Args[i]) {
         llvm::errs() << "### Deleting argument " << Args[i] << '\n';
         Args.erase(Args.begin() + i);
         if (Edit[0] == 'X') {
           if (i < Args.size()) {
             llvm::errs() << "### Deleting argument " << Args[i] << '\n';
             Args.erase(Args.begin() + i);
           } else
             llvm::errs() << "### Invalid X edit, end of command line!\n";
         }
       } else
         ++i;
     }
   } else if (Edit[0] == 'O') {
     for (unsigned i = 1; i < Args.size();) {
       const char *A = Args[i];
       if (A[0] == '-' && A[1] == 'O' &&
           (A[2] == '\0' ||
            (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
                              ('0' <= A[2] && A[2] <= '9'))))) {
         llvm::errs() << "### Deleting argument " << Args[i] << '\n';
         Args.erase(Args.begin() + i);
       } else
         ++i;
     }
     llvm::errs() << "### Adding argument " << Edit << " at end\n";
     Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit));
   } else {
     llvm::errs() << "### Unrecognized edit: " << Edit << "\n";
   }
}

/// ApplyQAOverride - Apply a comma separate list of edits to the
/// input argument lists. See ApplyOneQAOverride.
void ApplyQAOverride(std::vector<const char*> &Args, const char *OverrideStr,
                     std::set<std::string> &SavedStrings) {
  llvm::errs() << "### QA_OVERRIDE_GCC3_OPTIONS: " << OverrideStr << "\n";

  // This does not need to be efficient.

  const char *S = OverrideStr;
  while (*S) {
    const char *End = ::strchr(S, ' ');
    if (!End)
      End = S + strlen(S);
    if (End != S)
      ApplyOneQAOverride(Args, std::string(S, End), SavedStrings);
    S = End;
    if (*S != '\0')
      ++S;
  }
}

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal();
  llvm::PrettyStackTraceProgram X(argc, argv);

  llvm::sys::Path Path = GetExecutablePath(argv[0]);
  DriverDiagnosticPrinter DiagClient(Path.getBasename(), llvm::errs());

  Diagnostic Diags(&DiagClient);

  Driver TheDriver(Path.getBasename().c_str(), Path.getDirname().c_str(),
                   llvm::sys::getHostTriple().c_str(),
                   "a.out", Diags);

  llvm::OwningPtr<Compilation> C;

  // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
  // command line behind the scenes.
  std::set<std::string> SavedStrings;
  if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
    // FIXME: Driver shouldn't take extra initial argument.
    std::vector<const char*> StringPointers(argv, argv + argc);

    ApplyQAOverride(StringPointers, OverrideStr, SavedStrings);

    C.reset(TheDriver.BuildCompilation(StringPointers.size(),
                                       &StringPointers[0]));
  } else if (const char *Cur = ::getenv("CCC_ADD_ARGS")) {
    std::vector<const char*> StringPointers;

    // FIXME: Driver shouldn't take extra initial argument.
    StringPointers.push_back(argv[0]);

    for (;;) {
      const char *Next = strchr(Cur, ',');

      if (Next) {
        StringPointers.push_back(SaveStringInSet(SavedStrings,
                                                 std::string(Cur, Next)));
        Cur = Next + 1;
      } else {
        if (*Cur != '\0')
          StringPointers.push_back(SaveStringInSet(SavedStrings, Cur));
        break;
      }
    }

    StringPointers.insert(StringPointers.end(), argv + 1, argv + argc);

    C.reset(TheDriver.BuildCompilation(StringPointers.size(),
                                       &StringPointers[0]));
  } else
    C.reset(TheDriver.BuildCompilation(argc, argv));

  int Res = 0;
  if (C.get())
    Res = C->Execute();

  llvm::llvm_shutdown();

  return Res;
}

<|endoftext|>


<commit_before>/******************************************************************************
 *
 * Project:  integrating laszip into liblas - http://liblas.org -
 * Purpose:
 * Author:   Martin Isenburg
 *           isenburg at cs.unc.edu
 *
 ******************************************************************************
 * Copyright (c) 2010, Martin Isenburg
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Licence as published
 * by the Free Software Foundation.
 *
 * See the COPYING file for more information.
 *
 ****************************************************************************/

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

  FILE:  laszippertest.cpp

  CONTENTS:

    This tool reads and writes point data in the LAS 1.X format compressed
    or uncompressed to test the laszipper and lasunzipper interfaces.

  PROGRAMMERS:

    martin isenburg@cs.unc.edu

  COPYRIGHT:

    copyright (C) 2010 martin isenburg@cs.unc.edu

    This software 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.

  CHANGE HISTORY:

    13 December 2010 -- created to test the remodularized laszip compressor

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

#include "laszipper.hpp"
#include "lasunzipper.hpp"

#ifdef LZ_WIN32_VC6
    #include <fstream.h>
#else
    #include <istream>
    #include <fstream>
    using namespace std;
#endif

#include <time.h>
#include <stdio.h>

static double taketime()
{
  return (double)(clock())/CLOCKS_PER_SEC;
}

int main(int argc, char *argv[])
{
  unsigned char c;
  unsigned int i, j;
  unsigned int num_points = 1000000;
  unsigned int num_errors, num_bytes;
  filebuf ofb1;
  filebuf ofb2;
  filebuf ofb3;

#ifdef LZ_WIN32_VC6
  ostream* ostream1 = 0;
  ostream* ostream2 = 0;
  ostream* ostream3 = 0;
  istream* istream1 = 0;
  istream* istream2 = 0;
  istream* istream3 = 0;
#else
  ofstream* ostream1 = 0;
  ofstream* ostream2 = 0;
  ofstream* ostream3 = 0;
  ifstream* istream1 = 0;
  ifstream* istream2 = 0;
  ifstream* istream3 = 0;
#endif

  FILE* ofile1 = 0;
  FILE* ofile2 = 0;
  FILE* ofile3 = 0;
  filebuf ifb1;
  filebuf ifb2;
  filebuf ifb3;

  FILE* ifile1 = 0;
  FILE* ifile2 = 0;
  FILE* ifile3 = 0;
  double start_time, end_time;

  bool use_iostream = true;

  // describe the point structure

  unsigned int num_items = 4;
  LASitem items[4];

  items[0].type = LASitem::POINT10;
  items[0].size = 20;
  items[0].version = 0;

  items[1].type = LASitem::GPSTIME;
  items[1].size = 8;
  items[1].version = 0;

  items[2].type = LASitem::RGB;
  items[2].size = 6;
  items[2].version = 0;

  items[3].type = LASitem::BYTE;
  items[3].size = 7;
  items[3].version = 0;

  // compute the point size
  unsigned int point_size = 0;
  for (i = 0; i < num_items; i++) point_size += items[i].size;

  // create the point data
  unsigned int point_offset = 0;
  unsigned char** point = new unsigned char*[num_items];
  unsigned char* point_data = new unsigned char[point_size];
  for (i = 0; i < num_items; i++)
  {
    point[i] = &(point_data[point_offset]);
    point_offset += items[i].size;
  }

  LASzipper* laszipper1 = new LASzipper(); // without compression
  LASzipper* laszipper2 = new LASzipper(); // with arithmetic compression
  LASzipper* laszipper3 = new LASzipper(); // with range compression

  if (use_iostream)
  {

#ifdef LZ_WIN32_VC6
    ofb1.open("test1.lax", ios::out);
    ofb1.setmode(filebuf::binary);
    ostream1 = new ostream(&ofb1);
#else
    ostream1 = new ofstream();
    ostream1->open("test1.lax", std::ios::out | std::ios::binary );
#endif

    if (laszipper1->open(*ostream1, num_items, items, LASZIP_COMPRESSION_NONE) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper1\n");
      return 0;
    }

#ifdef LZ_WIN32_VC6
    ofb2.open("test2.lax", ios::out);
    ofb2.setmode(filebuf::binary);
    ostream2 = new ostream(&ofb2);
#else
    ostream2 = new ofstream();
    ostream2->open("test2.lax", std::ios::out | std::ios::binary );
#endif

    if (laszipper2->open(*ostream2, num_items, items, LASZIP_COMPRESSION_ARITHMETIC) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper2\n");
      return 0;
    }

#ifdef LZ_WIN32_VC6
    ofb3.open("test3.lax", ios::out);
    ofb3.setmode(filebuf::binary);
    ostream3 = new ostream(&ofb3);
#else
    ostream3 = new ofstream();
    ostream3->open("test3.lax", std::ios::out | std::ios::binary );
#endif

    if (laszipper3->open(*ostream3, num_items, items, LASZIP_COMPRESSION_RANGE) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper3\n");
      return 0;
    }
  }
  else
  {
    ofile1 = fopen("test1.lax", "wb");
    if (laszipper1->open(ofile1, num_items, items, LASZIP_COMPRESSION_NONE) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper1\n");
      return 0;
    }

    ofile2 = fopen("test2.lax", "wb");
    if (laszipper2->open(ofile2, num_items, items, LASZIP_COMPRESSION_ARITHMETIC) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper2\n");
      return 0;
    }

    ofile3 = fopen("test3.lax", "wb");
    if (laszipper3->open(ofile3, num_items, items, LASZIP_COMPRESSION_RANGE) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper3\n");
      return 0;
    }
  }

  // write / compress num_points with "random" data

  start_time = taketime();
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    for (j = 0; j < point_size; j++)
    {
      point_data[j] = c;
      c++;
    }
    laszipper1->write(point);
  }
  num_bytes = laszipper1->close();
  end_time = taketime();
  fprintf(stderr, "laszipper1 wrote %d bytes in %g seconds\n", num_bytes, end_time-start_time);

  start_time = taketime();
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    for (j = 0; j < point_size; j++)
    {
      point_data[j] = c;
      c++;
    }
    laszipper2->write(point);
  }
  num_bytes = laszipper2->close();
  end_time = taketime();
  fprintf(stderr, "laszipper2 wrote %d bytes in %g seconds\n", num_bytes, end_time-start_time);

  start_time = taketime();
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    for (j = 0; j < point_size; j++)
    {
      point_data[j] = c;
      c++;
    }
    laszipper3->write(point);
  }
  num_bytes = laszipper3->close();
  end_time = taketime();
  fprintf(stderr, "laszipper3 wrote %d bytes in %g seconds\n", num_bytes, end_time-start_time);

  delete laszipper1;
  delete laszipper2;
  delete laszipper3;

  if (use_iostream)
  {
    delete ostream1;
    delete ostream2;
    delete ostream3;
    ofb1.close();
    ofb2.close();
    ofb3.close();
  }
  else
  {
    fclose(ofile1);
    fclose(ofile2);
    fclose(ofile3);
  }

  LASunzipper* lasunzipper1 = new LASunzipper(); // without compression
  LASunzipper* lasunzipper2 = new LASunzipper(); // with arithmetic compression
  LASunzipper* lasunzipper3 = new LASunzipper(); // with range compression

  if (use_iostream)
  {

#ifdef LZ_WIN32_VC6
    ifb1.open("test1.lax", ios::in);
    ifb1.setmode(filebuf::binary);
    istream1 = new istream(&ifb1);
#else
    istream1 = new ifstream();
    istream1->open("test1.lax", std::ios::in | std::ios::binary );
#endif

    if (lasunzipper1->open(*istream1, num_items, items, LASZIP_COMPRESSION_NONE) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper1\n");
      return 0;
    }

#ifdef LZ_WIN32_VC6
    ifb2.open("test2.lax", ios::in);
    ifb2.setmode(filebuf::binary);
    istream2 = new istream(&ifb2);
#else
    istream2 = new ifstream();
    istream2->open("test2.lax", std::ios::in | std::ios::binary );
#endif

    if (lasunzipper2->open(*istream2, num_items, items, LASZIP_COMPRESSION_ARITHMETIC) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper2\n");
      return 0;
    }

#ifdef LZ_WIN32_VC6
    ifb3.open("test3.lax", ios::in);
    ifb3.setmode(filebuf::binary);
    istream3 = new istream(&ifb3);
#else
    istream3 = new ifstream();
    istream3->open("test3.lax", std::ios::in | std::ios::binary );
#endif

    if (lasunzipper3->open(*istream3, num_items, items, LASZIP_COMPRESSION_RANGE) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper3\n");
      return 0;
    }
  }
  else
  {
    ifile1 = fopen("test1.lax", "rb");
    if (lasunzipper1->open(ifile1, num_items, items, LASZIP_COMPRESSION_NONE) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper1\n");
      return 0;
    }
    ifile2 = fopen("test2.lax", "rb");
    if (lasunzipper2->open(ifile2, num_items, items, LASZIP_COMPRESSION_ARITHMETIC) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper2\n");
      return 0;
    }
    ifile3 = fopen("test3.lax", "rb");
    if (lasunzipper3->open(ifile3, num_items, items, LASZIP_COMPRESSION_RANGE) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper3\n");
      return 0;
    }
  }

  // read num_points with "random" data

  start_time = taketime();
  num_errors = 0;
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    lasunzipper1->read(point);
    for (j = 0; j < point_size; j++)
    {
      if (point_data[j] != c)
      {
        fprintf(stderr, "%d %d %d != %d\n", i, j, point_data[j], c);
        num_errors++;
        if (num_errors > 20) return -1;
      }
      c++;
    }
  }
  num_bytes = lasunzipper1->close();
  end_time = taketime();
  if (num_errors)
  {
    fprintf(stderr, "ERROR: with lasunzipper1 %d\n", num_errors);
  }
  else
  {
   fprintf(stderr, "SUCCESS: lasunzipper1 read %d bytes in %g seconds\n", num_bytes, end_time-start_time);
  }

  // decompress num_points with "random" data

  start_time = taketime();
  num_errors = 0;
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    lasunzipper2->read(point);
    for (j = 0; j < point_size; j++)
    {
      if (point_data[j] != c)
      {
        fprintf(stderr, "%d %d %d != %d\n", i, j, point_data[j], c);
        num_errors++;
        if (num_errors > 20) return -1;
      }
      c++;
    }
  }
  num_bytes = lasunzipper2->close();
  end_time = taketime();
  if (num_errors)
  {
    fprintf(stderr, "ERROR: with lasunzipper2 %d\n", num_errors);
  }
  else
  {
   fprintf(stderr, "SUCCESS: lasunzipper2 read %d bytes in %g seconds\n", num_bytes, end_time-start_time);
  }

  // decompress num_points with "random" data

  start_time = taketime();
  num_errors = 0;
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    lasunzipper3->read(point);
    for (j = 0; j < point_size; j++)
    {
      if (point_data[j] != c)
      {
        fprintf(stderr, "%d %d %d != %d\n", i, j, point_data[j], c);
        num_errors++;
        if (num_errors > 20) return -1;
      }
      c++;
    }
  }
  num_bytes = lasunzipper3->close();
  end_time = taketime();
  if (num_errors)
  {
    fprintf(stderr, "ERROR: with lasunzipper3 %d\n", num_errors);
  }
  else
  {
   fprintf(stderr, "SUCCESS: lasunzipper3 read %d bytes in %g seconds\n", num_bytes, end_time-start_time);
  }

  delete lasunzipper1;
  delete lasunzipper2;
  delete lasunzipper3;

  if (use_iostream)
  {
    ifb1.close();
    ifb2.close();
    ifb3.close();
    delete istream1;
    delete istream2;
    delete istream3;
  }
  else
  {
    fclose(ifile1);
    fclose(ifile2);
    fclose(ifile3);
  }

  return 0;
}
<commit_msg>sync w/ Martin's changes<commit_after>/******************************************************************************
 *
 * Project:  integrating laszip into liblas - http://liblas.org -
 * Purpose:
 * Author:   Martin Isenburg
 *           isenburg at cs.unc.edu
 *
 ******************************************************************************
 * Copyright (c) 2010, Martin Isenburg
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Licence as published
 * by the Free Software Foundation.
 *
 * See the COPYING file for more information.
 *
 ****************************************************************************/

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

  FILE:  laszippertest.cpp

  CONTENTS:

    This tool reads and writes point data in the LAS 1.X format compressed
    or uncompressed to test the laszipper and lasunzipper interfaces.

  PROGRAMMERS:

    martin isenburg@cs.unc.edu

  COPYRIGHT:

    copyright (C) 2010 martin isenburg@cs.unc.edu

    This software 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.

  CHANGE HISTORY:

    13 December 2010 -- created to test the remodularized laszip compressor

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

#include "laszipper.hpp"
#include "lasunzipper.hpp"

#ifdef LZ_WIN32_VC6
    #include <fstream.h>
#else
    #include <istream>
    #include <fstream>
    using namespace std;
#endif

#include <time.h>
#include <stdio.h>

static double taketime()
{
  return (double)(clock())/CLOCKS_PER_SEC;
}

int main(int argc, char *argv[])
{
  unsigned char c;
  unsigned int i, j;
  unsigned int num_points = 1000000;
  unsigned int num_errors, num_bytes;
  filebuf ofb1;
  filebuf ofb2;
  filebuf ofb3;

#ifdef LZ_WIN32_VC6
  ostream* ostream1 = 0;
  ostream* ostream2 = 0;
  ostream* ostream3 = 0;
  istream* istream1 = 0;
  istream* istream2 = 0;
  istream* istream3 = 0;
#else
  ofstream* ostream1 = 0;
  ofstream* ostream2 = 0;
  ofstream* ostream3 = 0;
  ifstream* istream1 = 0;
  ifstream* istream2 = 0;
  ifstream* istream3 = 0;
#endif

  FILE* ofile1 = 0;
  FILE* ofile2 = 0;
  FILE* ofile3 = 0;
  filebuf ifb1;
  filebuf ifb2;
  filebuf ifb3;

  FILE* ifile1 = 0;
  FILE* ifile2 = 0;
  FILE* ifile3 = 0;
  double start_time, end_time;

  bool use_iostream = true;

  // describe the point structure

  unsigned int num_items = 4;
  LASitem items[4];

  items[0].type = LASitem::POINT10;
  items[0].size = 20;
  items[0].version = 0;

  items[1].type = LASitem::GPSTIME11;
  items[1].size = 8;
  items[1].version = 0;

  items[2].type = LASitem::RGB12;
  items[2].size = 6;
  items[2].version = 0;

  items[3].type = LASitem::BYTE;
  items[3].size = 7;
  items[3].version = 0;

  // compute the point size
  unsigned int point_size = 0;
  for (i = 0; i < num_items; i++) point_size += items[i].size;

  // create the point data
  unsigned int point_offset = 0;
  unsigned char** point = new unsigned char*[num_items];
  unsigned char* point_data = new unsigned char[point_size];
  for (i = 0; i < num_items; i++)
  {
    point[i] = &(point_data[point_offset]);
    point_offset += items[i].size;
  }

  LASzipper* laszipper1 = new LASzipper(); // without compression
  LASzipper* laszipper2 = new LASzipper(); // with arithmetic compression
  LASzipper* laszipper3 = new LASzipper(); // with range compression

  if (use_iostream)
  {

#ifdef LZ_WIN32_VC6
    ofb1.open("test1.lax", ios::out);
    ofb1.setmode(filebuf::binary);
    ostream1 = new ostream(&ofb1);
#else
    ostream1 = new ofstream();
    ostream1->open("test1.lax", std::ios::out | std::ios::binary );
#endif

    if (laszipper1->open(*ostream1, num_items, items, LASZIP_COMPRESSION_NONE) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper1\n");
      return 0;
    }

#ifdef LZ_WIN32_VC6
    ofb2.open("test2.lax", ios::out);
    ofb2.setmode(filebuf::binary);
    ostream2 = new ostream(&ofb2);
#else
    ostream2 = new ofstream();
    ostream2->open("test2.lax", std::ios::out | std::ios::binary );
#endif

    if (laszipper2->open(*ostream2, num_items, items, LASZIP_COMPRESSION_ARITHMETIC) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper2\n");
      return 0;
    }

#ifdef LZ_WIN32_VC6
    ofb3.open("test3.lax", ios::out);
    ofb3.setmode(filebuf::binary);
    ostream3 = new ostream(&ofb3);
#else
    ostream3 = new ofstream();
    ostream3->open("test3.lax", std::ios::out | std::ios::binary );
#endif

    if (laszipper3->open(*ostream3, num_items, items, LASZIP_COMPRESSION_RANGE) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper3\n");
      return 0;
    }
  }
  else
  {
    ofile1 = fopen("test1.lax", "wb");
    if (laszipper1->open(ofile1, num_items, items, LASZIP_COMPRESSION_NONE) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper1\n");
      return 0;
    }

    ofile2 = fopen("test2.lax", "wb");
    if (laszipper2->open(ofile2, num_items, items, LASZIP_COMPRESSION_ARITHMETIC) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper2\n");
      return 0;
    }

    ofile3 = fopen("test3.lax", "wb");
    if (laszipper3->open(ofile3, num_items, items, LASZIP_COMPRESSION_RANGE) != 0)
    {
      fprintf(stderr, "ERROR: could not open laszipper3\n");
      return 0;
    }
  }

  // write / compress num_points with "random" data

  start_time = taketime();
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    for (j = 0; j < point_size; j++)
    {
      point_data[j] = c;
      c++;
    }
    laszipper1->write(point);
  }
  num_bytes = laszipper1->close();
  end_time = taketime();
  fprintf(stderr, "laszipper1 wrote %d bytes in %g seconds\n", num_bytes, end_time-start_time);

  start_time = taketime();
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    for (j = 0; j < point_size; j++)
    {
      point_data[j] = c;
      c++;
    }
    laszipper2->write(point);
  }
  num_bytes = laszipper2->close();
  end_time = taketime();
  fprintf(stderr, "laszipper2 wrote %d bytes in %g seconds\n", num_bytes, end_time-start_time);

  start_time = taketime();
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    for (j = 0; j < point_size; j++)
    {
      point_data[j] = c;
      c++;
    }
    laszipper3->write(point);
  }
  num_bytes = laszipper3->close();
  end_time = taketime();
  fprintf(stderr, "laszipper3 wrote %d bytes in %g seconds\n", num_bytes, end_time-start_time);

  delete laszipper1;
  delete laszipper2;
  delete laszipper3;

  if (use_iostream)
  {
    delete ostream1;
    delete ostream2;
    delete ostream3;
    ofb1.close();
    ofb2.close();
    ofb3.close();
  }
  else
  {
    fclose(ofile1);
    fclose(ofile2);
    fclose(ofile3);
  }

  LASunzipper* lasunzipper1 = new LASunzipper(); // without compression
  LASunzipper* lasunzipper2 = new LASunzipper(); // with arithmetic compression
  LASunzipper* lasunzipper3 = new LASunzipper(); // with range compression

  if (use_iostream)
  {

#ifdef LZ_WIN32_VC6
    ifb1.open("test1.lax", ios::in);
    ifb1.setmode(filebuf::binary);
    istream1 = new istream(&ifb1);
#else
    istream1 = new ifstream();
    istream1->open("test1.lax", std::ios::in | std::ios::binary );
#endif

    if (lasunzipper1->open(*istream1, num_items, items, LASZIP_COMPRESSION_NONE) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper1\n");
      return 0;
    }

#ifdef LZ_WIN32_VC6
    ifb2.open("test2.lax", ios::in);
    ifb2.setmode(filebuf::binary);
    istream2 = new istream(&ifb2);
#else
    istream2 = new ifstream();
    istream2->open("test2.lax", std::ios::in | std::ios::binary );
#endif

    if (lasunzipper2->open(*istream2, num_items, items, LASZIP_COMPRESSION_ARITHMETIC) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper2\n");
      return 0;
    }

#ifdef LZ_WIN32_VC6
    ifb3.open("test3.lax", ios::in);
    ifb3.setmode(filebuf::binary);
    istream3 = new istream(&ifb3);
#else
    istream3 = new ifstream();
    istream3->open("test3.lax", std::ios::in | std::ios::binary );
#endif

    if (lasunzipper3->open(*istream3, num_items, items, LASZIP_COMPRESSION_RANGE) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper3\n");
      return 0;
    }
  }
  else
  {
    ifile1 = fopen("test1.lax", "rb");
    if (lasunzipper1->open(ifile1, num_items, items, LASZIP_COMPRESSION_NONE) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper1\n");
      return 0;
    }
    ifile2 = fopen("test2.lax", "rb");
    if (lasunzipper2->open(ifile2, num_items, items, LASZIP_COMPRESSION_ARITHMETIC) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper2\n");
      return 0;
    }
    ifile3 = fopen("test3.lax", "rb");
    if (lasunzipper3->open(ifile3, num_items, items, LASZIP_COMPRESSION_RANGE) != 0)
    {
      fprintf(stderr, "ERROR: could not open lasunzipper3\n");
      return 0;
    }
  }

  // read num_points with "random" data

  start_time = taketime();
  num_errors = 0;
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    lasunzipper1->read(point);
    for (j = 0; j < point_size; j++)
    {
      if (point_data[j] != c)
      {
        fprintf(stderr, "%d %d %d != %d\n", i, j, point_data[j], c);
        num_errors++;
        if (num_errors > 20) return -1;
      }
      c++;
    }
  }
  num_bytes = lasunzipper1->close();
  end_time = taketime();
  if (num_errors)
  {
    fprintf(stderr, "ERROR: with lasunzipper1 %d\n", num_errors);
  }
  else
  {
   fprintf(stderr, "SUCCESS: lasunzipper1 read %d bytes in %g seconds\n", num_bytes, end_time-start_time);
  }

  // decompress num_points with "random" data

  start_time = taketime();
  num_errors = 0;
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    lasunzipper2->read(point);
    for (j = 0; j < point_size; j++)
    {
      if (point_data[j] != c)
      {
        fprintf(stderr, "%d %d %d != %d\n", i, j, point_data[j], c);
        num_errors++;
        if (num_errors > 20) return -1;
      }
      c++;
    }
  }
  num_bytes = lasunzipper2->close();
  end_time = taketime();
  if (num_errors)
  {
    fprintf(stderr, "ERROR: with lasunzipper2 %d\n", num_errors);
  }
  else
  {
   fprintf(stderr, "SUCCESS: lasunzipper2 read %d bytes in %g seconds\n", num_bytes, end_time-start_time);
  }

  // decompress num_points with "random" data

  start_time = taketime();
  num_errors = 0;
  c = 0;
  for (i = 0; i < num_points; i++)
  {
    lasunzipper3->read(point);
    for (j = 0; j < point_size; j++)
    {
      if (point_data[j] != c)
      {
        fprintf(stderr, "%d %d %d != %d\n", i, j, point_data[j], c);
        num_errors++;
        if (num_errors > 20) return -1;
      }
      c++;
    }
  }
  num_bytes = lasunzipper3->close();
  end_time = taketime();
  if (num_errors)
  {
    fprintf(stderr, "ERROR: with lasunzipper3 %d\n", num_errors);
  }
  else
  {
   fprintf(stderr, "SUCCESS: lasunzipper3 read %d bytes in %g seconds\n", num_bytes, end_time-start_time);
  }

  delete lasunzipper1;
  delete lasunzipper2;
  delete lasunzipper3;

  if (use_iostream)
  {
    ifb1.close();
    ifb2.close();
    ifb3.close();
    delete istream1;
    delete istream2;
    delete istream3;
  }
  else
  {
    fclose(ifile1);
    fclose(ifile2);
    fclose(ifile3);
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <openssl/hmac.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <openssl/md5.h>
#include <openssl/pem.h>
#include <arpa/inet.h>
#include <openssl/x509.h>
#include <endian.h>

#include "../../base/stdinc.h"
#include "../../base/dcutils.hpp"
#include "../../base/logger.h"
#include "../../base/msg_buffer.hpp"

#include "dcrsa.h"
//ASN.1
//PKCS2
//PKCS8
//PEM
//DER
//X509
//EVP

NS_BEGIN(dcs)
#define MAX_HASH_DIGEST_LENGTH	(4096)
struct rsa_t {
	RSA * rsa{ nullptr };
	msg_buffer_t	hashbuff;
	msg_buffer_t	signbuff;
};

static inline void * rsa_from_der(const char * buff, int ibuff, bool pubkey){
    if (!buff || !ibuff){
        GLOG_ERR("der buff:%p len:%d mode:%d error !", buff, ibuff, pubkey);
        return nullptr;
    }
    ///////////////////////////////////////////////////////////////////////////
    BIO *b = NULL;
    X509 *c = NULL;
    EVP_PKEY *k = NULL;

    b = BIO_new_mem_buf((char*)buff, ibuff);
    if (!b) {
        GLOG_ERR("BIO_new_mem_buf key get mem buffer error !");
        return nullptr;
    }

    c = d2i_X509_bio(b, NULL);
    if (!c) {
        GLOG_ERR("d2i_X509_bio key get mem buffer error ! %d", c);
        BIO_free(b);
        return nullptr;
    }

    k = X509_get_pubkey(c);
    if (!k) {
        GLOG_ERR("X509_get_pubkey key get mem buffer error ! ");
        BIO_free(b);
        return nullptr;
    }
    /* make sure that the public key from the cert is an RSA key */
    if (EVP_PKEY_RSA != EVP_PKEY_type(k->type)) {
        GLOG_ERR("EVP_PKEY_type type :%d not matched error !", EVP_PKEY_type(k->type));
        EVP_PKEY_free(k);
        BIO_free(b);
        return nullptr;
    }

    //////////////////////////////////////////////////////////////////////////
    RSA * rsa = EVP_PKEY_get1_RSA(k);
    EVP_PKEY_free(k);
    BIO_free(b);
    if (!rsa){
        GLOG_ERR("read rsa from der buff:%p len:%d mode:%d error !", buff, ibuff, pubkey);
        return nullptr;
    }
    rsa_t * r = new rsa_t;
    r->rsa = rsa;
    r->hashbuff.create(MAX_HASH_DIGEST_LENGTH);
    int rsa_size = RSA_size(rsa);
    r->signbuff.create(rsa_size + 16);
    r->signbuff.valid_size = rsa_size;
    return r;
}

static inline void * rsa_from_perm(const char * keyfile, bool pubkey){
    if (!keyfile) return nullptr;
    FILE * fp = fopen(keyfile, "r");
	if (!fp){
        GLOG_ERR("open rsa pubkey file:%s error !", keyfile);
		return nullptr;
	}
	RSA * rsa = nullptr;
	if (pubkey){
		rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
	}
	else {
		rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
	}
	fclose(fp);
	if (!rsa){
        GLOG_ERR("read rsa parsing from pubkey file:%s error !", keyfile);
		return nullptr;
	}
	rsa_t * r = new rsa_t;
	r->rsa = rsa;
	r->hashbuff.create(MAX_HASH_DIGEST_LENGTH);
    int rsa_size = RSA_size(rsa);
    r->signbuff.create(rsa_size + 16);
    r->signbuff.valid_size = rsa_size;
	return r;
}

void * rsa_from_perm_prvkey(const char * prikeyfile){
    return rsa_from_perm(prikeyfile, false);
}
void * rsa_from_perm_pubkey(const char * pubkeyfile){
    return rsa_from_perm(pubkeyfile, true);
}
void * rsa_from_der_pubkey(const char * buff, int ibuff){
    return rsa_from_der(buff, ibuff, true);
}
void * rsa_from_der_prvkey(const char * buff, int ibuff){
    return rsa_from_der(buff, ibuff, false);
}

void   rsa_free(void * rsa){
	if (rsa){
		rsa_t * r = (rsa_t*)rsa;
		RSA_free(r->rsa);
		r->hashbuff.destroy();
		r->signbuff.destroy();
	}
}
bool    rsa_sign(std::string & signature, void * r, RSASignAlgoType meth, const char * buff, int ibuff){
	unsigned char* hash = nullptr;
    rsa_t * rsa = (rsa_t*)r;
    signature.clear();
    rsa->signbuff.valid_size = rsa->signbuff.max_size;
	switch (meth){
	case RSA_SIGN_SHA1:
        hash = SHA256((unsigned char*)buff, ibuff, (unsigned char *)rsa->hashbuff.buffer);
		return RSA_sign(NID_sha256, hash, SHA256_DIGEST_LENGTH,
            (unsigned char*)rsa->signbuff.buffer, (unsigned int *)&rsa->signbuff.valid_size, rsa->rsa) == 1;
        break;
	case RSA_SIGN_SHA256:
        hash = SHA1((unsigned char*)buff, ibuff, (unsigned char *)rsa->hashbuff.buffer);
		return RSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH,
            (unsigned char*)rsa->signbuff.buffer, (unsigned int *)&rsa->signbuff.valid_size, rsa->rsa) == 1;
        break;
	default:
		GLOG_ERR("error method :%d not support yet !", meth);
		return false;
	}
    signature.append(rsa->signbuff.buffer, rsa->signbuff.valid_size);
	return false;
}
bool    rsa_verify(const std::string & signature, void * r, RSASignAlgoType meth, const char * buff, int ibuff){
	unsigned char* hash = nullptr;
    rsa_t * rsa = (rsa_t*)r;
    bool ret = false;
	switch (meth){
	case RSA_SIGN_SHA1:
        hash = SHA256((unsigned char*)buff, ibuff, (unsigned char *)rsa->hashbuff.buffer);
        ret = RSA_verify(NID_sha256, hash, SHA256_DIGEST_LENGTH,
            (const unsigned char*)signature.data(), signature.length(), rsa->rsa) == 1;
		break;
	case RSA_SIGN_SHA256:
        hash = SHA1((unsigned char*)buff, ibuff, (unsigned char *)rsa->hashbuff.buffer);
        ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
            (const unsigned char*)signature.data(), signature.length(), rsa->rsa) == 1;
		break;
	default:
		GLOG_ERR("error method :%d not support yet !", meth);
		return false;
	}
	return ret;
}

NS_END()<commit_msg>fixing rsa sign / verify<commit_after>#include <openssl/hmac.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <openssl/md5.h>
#include <openssl/pem.h>
#include <arpa/inet.h>
#include <openssl/x509.h>
#include <endian.h>

#include "../../base/stdinc.h"
#include "../../base/dcutils.hpp"
#include "../../base/logger.h"
#include "../../base/msg_buffer.hpp"

#include "dcrsa.h"
//ASN.1
//PKCS2
//PKCS8
//PEM
//DER
//X509
//EVP

NS_BEGIN(dcs)
#define MAX_HASH_DIGEST_LENGTH	(4096)
struct rsa_t {
	RSA * rsa{ nullptr };
	msg_buffer_t	hashbuff;
	msg_buffer_t	signbuff;
};

static inline void * rsa_from_der(const char * buff, int ibuff, bool pubkey){
    if (!buff || !ibuff){
        GLOG_ERR("der buff:%p len:%d mode:%d error !", buff, ibuff, pubkey);
        return nullptr;
    }
    ///////////////////////////////////////////////////////////////////////////
    BIO *b = NULL;
    X509 *c = NULL;
    EVP_PKEY *k = NULL;

    b = BIO_new_mem_buf((char*)buff, ibuff);
    if (!b) {
        GLOG_ERR("BIO_new_mem_buf key get mem buffer error !");
        return nullptr;
    }

    c = d2i_X509_bio(b, NULL);
    if (!c) {
        GLOG_ERR("d2i_X509_bio key get mem buffer error ! %d", c);
        BIO_free(b);
        return nullptr;
    }

    k = X509_get_pubkey(c);
    if (!k) {
        GLOG_ERR("X509_get_pubkey key get mem buffer error ! ");
        BIO_free(b);
        return nullptr;
    }
    /* make sure that the public key from the cert is an RSA key */
    if (EVP_PKEY_RSA != EVP_PKEY_type(k->type)) {
        GLOG_ERR("EVP_PKEY_type type :%d not matched error !", EVP_PKEY_type(k->type));
        EVP_PKEY_free(k);
        BIO_free(b);
        return nullptr;
    }

    //////////////////////////////////////////////////////////////////////////
    RSA * rsa = EVP_PKEY_get1_RSA(k);
    EVP_PKEY_free(k);
    BIO_free(b);
    if (!rsa){
        GLOG_ERR("read rsa from der buff:%p len:%d mode:%d error !", buff, ibuff, pubkey);
        return nullptr;
    }
    rsa_t * r = new rsa_t;
    r->rsa = rsa;
    r->hashbuff.create(MAX_HASH_DIGEST_LENGTH);
    int rsa_size = RSA_size(rsa);
    r->signbuff.create(rsa_size + 16);
    r->signbuff.valid_size = rsa_size;
    return r;
}

static inline void * rsa_from_perm(const char * keyfile, bool pubkey){
    if (!keyfile) return nullptr;
    FILE * fp = fopen(keyfile, "r");
	if (!fp){
        GLOG_ERR("open rsa pubkey file:%s error !", keyfile);
		return nullptr;
	}
	RSA * rsa = nullptr;
	if (pubkey){
		rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
	}
	else {
		rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
	}
	fclose(fp);
	if (!rsa){
        GLOG_ERR("read rsa parsing from pubkey file:%s error !", keyfile);
		return nullptr;
	}
	rsa_t * r = new rsa_t;
	r->rsa = rsa;
	r->hashbuff.create(MAX_HASH_DIGEST_LENGTH);
    int rsa_size = RSA_size(rsa);
    r->signbuff.create(rsa_size + 16);
    r->signbuff.valid_size = rsa_size;
	return r;
}

void * rsa_from_perm_prvkey(const char * prikeyfile){
    return rsa_from_perm(prikeyfile, false);
}
void * rsa_from_perm_pubkey(const char * pubkeyfile){
    return rsa_from_perm(pubkeyfile, true);
}
void * rsa_from_der_pubkey(const char * buff, int ibuff){
    return rsa_from_der(buff, ibuff, true);
}
void * rsa_from_der_prvkey(const char * buff, int ibuff){
    return rsa_from_der(buff, ibuff, false);
}

void   rsa_free(void * rsa){
	if (rsa){
		rsa_t * r = (rsa_t*)rsa;
		RSA_free(r->rsa);
		r->hashbuff.destroy();
		r->signbuff.destroy();
	}
}
bool    rsa_sign(std::string & signature, void * r, RSASignAlgoType meth, const char * buff, int ibuff){
	unsigned char* hash = nullptr;
    rsa_t * rsa = (rsa_t*)r;
    signature.clear();
    rsa->signbuff.valid_size = rsa->signbuff.max_size;
	switch (meth){
	case RSA_SIGN_SHA1:
        hash = SHA256((unsigned char*)buff, ibuff, (unsigned char *)rsa->hashbuff.buffer);
		return RSA_sign(NID_sha256, hash, SHA256_DIGEST_LENGTH,
            (unsigned char*)rsa->signbuff.buffer, (unsigned int *)&rsa->signbuff.valid_size, rsa->rsa) == 1;
        break;
	case RSA_SIGN_SHA256:
        hash = SHA1((unsigned char*)buff, ibuff, (unsigned char *)rsa->hashbuff.buffer);
		return RSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH,
            (unsigned char*)rsa->signbuff.buffer, (unsigned int *)&rsa->signbuff.valid_size, rsa->rsa) == 1;
        break;
	default:
		GLOG_ERR("error method :%d not support yet !", meth);
		return false;
	}
    signature.append(rsa->signbuff.buffer, rsa->signbuff.valid_size);
	return false;
}
bool    rsa_verify(const std::string & signature, void * r, RSASignAlgoType meth, const char * buff, int ibuff){
	unsigned char* hash = nullptr;
    rsa_t * rsa = (rsa_t*)r;
    bool ret = false;
	switch (meth){
	case RSA_SIGN_SHA1:
        hash = SHA1((unsigned char*)buff, ibuff, (unsigned char *)rsa->hashbuff.buffer);
        ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
            (const unsigned char*)signature.data(), signature.length(), rsa->rsa) == 1;
		break;
	case RSA_SIGN_SHA256:
		hash = SHA256((unsigned char*)buff, ibuff, (unsigned char *)rsa->hashbuff.buffer);
		ret = RSA_verify(NID_sha256, hash, SHA256_DIGEST_LENGTH,
			(const unsigned char*)signature.data(), signature.length(), rsa->rsa) == 1;
		break;
	default:
		GLOG_ERR("error method :%d not support yet !", meth);
		return false;
	}
	return ret;
}

NS_END()<|endoftext|>


<commit_before>#include "StdAfx.h"
#include "viewport.h"
#include "registry.h"
#include "illa/config.h"
#include "illa/surfacemgr.h"
#include "getevent.h"

const wchar_t* App::ViewPort::ClassName = TX("Pictus ViewPort");

namespace App {
	using namespace Reg::Keys;
	using Geom::RectInt;
	using Geom::PointInt;
	using Geom::SizeInt;

	ViewPort::ViewPort()
		:m_isCursorVisible(true),
		m_cursorMode(CursorShow),
		m_displayZoom(1.0f),
		m_imageZoom(1.0f),
		m_currentPanMonitor(nullptr),
		m_isPanning(false)
	{
		Img::SurfaceFactory(&m_renderTarget);
		OnMouseMove.connect([&](Win::MouseEvent e) { return HandleMouseMove(e); });
		OnMouseButtonDown.connect([&](Win::MouseEvent e) { return HandleMouseDown(e); });
		OnMouseButtonUp.connect([&](Win::MouseEvent e) { return HandleMouseUp(e); });

		m_hideTimer.OnTick.connect([&]() { CursorHideCallback(); });
		m_animationTimer.OnTick.connect([&]() { ImageRefreshCallback(); });
	}

	bool ViewPort::PerformOnCreate() {
		m_hParent = Parent()->Handle();

		// Register the window class (if possible)
		WNDCLASSEX wc;
		ZeroMemory(&wc, sizeof(wc));
		wc.cbSize			= sizeof(wc);					// Set structure size
		wc.hCursor			= LoadCursor(0, IDC_ARROW);
		wc.hInstance		= GetHINSTANCE();				// Current instance's handle
		wc.lpfnWndProc		= WndProcDelegate;				// Use "delegate" as the wndproc
		wc.lpszClassName	= ClassName;					// Class name
		wc.style			= CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;	// Register double clicks and window resizes
		RegisterClassEx(&wc);

		// Create window without any nifty features
		return ConstructWindow(RectInt(PointInt(0, 0), SizeInt(1, 1)), WS_EX_ACCEPTFILES, ClassName, TX(""), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN);
	}

	void ViewPort::setSurface() {
		m_renderTarget.SetSurface(m_image == 0 ? Img::Surface::Ptr() : m_image->CurrentSurface());
	}

	void ViewPort::Image(Img::Image::Ptr image) {
		m_animationTimer.Destroy();
		bool diff = (m_image != image);
		m_image = image;

		setSurface();

		if (m_image != nullptr) {
			m_pan.ResizeConstraints(image->GetSize());
			m_pan.ResizeViewport(m_renderTarget.TransformedSize());

			if (diff) {
				m_image->RestartAnimation();
			}

			if (diff && Reg::Key(DWResetPan)) {
				m_pan.Reset();
			}

			if (m_image->IsHeaderInformationValid() && m_image->Delay() != -1) {
				m_animationTimer.Create(m_image->Delay());	// It's animated, start timer and stuff
			}
			else if (m_image->IsFinished() == false) {
				m_animationTimer.Create(Img::RedrawDelay);	// Not animated or uncertain. Redraw periodically
			}

		}

		InvalidateRect(Handle(), 0, false);
		OnSize(GetSize());
	}

	Img::Image::Ptr ViewPort::Image() const {
		return m_image;
	}

	void ViewPort::BackgroundColor(const Img::Color& col) {
		m_props.BackgroundColor = col;
	}

	const Img::Color& ViewPort::BackgroundColor() const {
		return m_props.BackgroundColor;
	}

	void ViewPort::Rotate(Filter::RotationAngle r) {
		m_props.Angle = r;

		OnSize(GetSize());
	}

	void ViewPort::ActiveCursorMode(const CursorMode m) {
		m_cursorMode = m;
		updateCursor();
	}

	ViewPort::CursorMode ViewPort::ActiveCursorMode() const {
		return m_cursorMode;
	}

	void ViewPort::Pan(const SizeInt& deltaPan) {
		m_pan.Pan(deltaPan);

		Update();
	}

	void ViewPort::ImageRefreshCallback() {
		if (m_image->IsHeaderInformationValid() == false) return;

		if (m_image->Delay() != -1) {
			m_image->NextFrame();
			m_animationTimer.Create(m_image->Delay());
			Redraw();
		}
		else {
			if (m_image && m_image->IsHeaderInformationValid()) {
				ImageUpdated();
			}

			bool status = m_image->IsFinished();
			Redraw();
			if (status) {
				m_animationTimer.Destroy();
			}
		}
	}

	bool ViewPort::PerformOnPaint() {
		setSurface();

		// TODO: This may call BEFORE the surface is allocated, and will thus fail when attempting to lock.
		if (m_image && m_image->IsHeaderInformationValid() && AreaNonZero(ZoomedImageSize()) && (AreaNonZero(GetSize()))) {
			bool status = m_image->IsFinished();

			m_props.ResampleFilter = ActiveFilterMode();
			m_renderTarget.Render(m_pan.TopLeft(), m_props);

			if ((m_image->Delay() == -1) && status)
				m_animationTimer.Destroy();

			// Direct3D9 Ex (with FLIPEX) doesn't seem to validate the window the same way as vanilla D3D9.
			// Therefore we do it ourselves to prevent WM_PAINT spam.
			ValidateRect(Handle(), nullptr);

			return true;
		}
		else {
			m_renderTarget.Clear(m_props.BackgroundColor);
			return true;
		}
	}

	Filter::Mode ViewPort::ActiveFilterMode() const {
		if (m_minFilter == Filter::Mode::Undefined) {
			DO_THROW(Err::InvalidCall, TX("Minification filter not set."));
		}
		if (m_magFilter == Filter::Mode::Undefined) {
			DO_THROW(Err::InvalidCall, TX("Magnification filter not set."));
		}

		if (m_props.Zoom < 1.0) {
			return m_minFilter;
		}

		return m_magFilter;
	}

	bool ViewPort::PerformOnApp(int index, WPARAM wp, LPARAM lp) {
		if (Parent()) {
			return Parent()->OnApp(index, wp, lp);
		}
		return false;
	}

	bool ViewPort::HandleMouseDown(Win::MouseEvent e) {
		if (MouseStandardEvent(e) == MousePan) {
			m_isPanning = true;
			m_oldMousePosition = MouseCursorPos();
			m_currentPanMonitor = Win::FindMonitorAt(m_oldMousePosition);
			SetCapture(Handle());
			return true;
		}
		return false;
	}

	bool ViewPort::HandleMouseUp(Win::MouseEvent) {
		// Done panning, release mouse
		ReleaseCapture();

		m_isPanning = false;

		return false;
	}

	bool ViewPort::HandleMouseMove(Win::MouseEvent e) {
		updateCursor();

		if (!((MouseStandardEvent(e) == MousePan) && m_isPanning == true)) {
			return false;
		}

		if (m_currentPanMonitor == nullptr) {
			DO_THROW(Err::CriticalError, TX("Current panning monitor not set."));
		}

		auto globalPosition = MouseCursorPos();
		auto mousePosition = globalPosition;

		const Geom::RectInt& screen = m_currentPanMonitor->Region();

		if (mousePosition.X >= (screen.Right() - 1)) {
			mousePosition.X = screen.Left() + 1;
		}

		if (mousePosition.X <= screen.Left()) {
			mousePosition.X = screen.Right() - 2;
		}

		if (mousePosition.Y >= (screen.Bottom() - 1)) {
			mousePosition.Y = screen.Top() + 1;
		}

		if (mousePosition.Y <= screen.Top()) {
			mousePosition.Y = screen.Bottom() - 2;
		}

		if (globalPosition != mousePosition) {
			SetCursorPos(mousePosition.X, mousePosition.Y);
			// Fix for RDP and similar. Sometimes (often) SetCursorPos fails silently, so we need to check manually to
			// see if it had any effect.
			POINT p;
			GetCursorPos(&p);
			mousePosition.X = p.x; mousePosition.Y = p.y;

			m_oldMousePosition = mousePosition;
		}

		SizeInt dPos(mousePosition - m_oldMousePosition);
		if ((dPos.Width != 0) || (dPos.Height != 0)) {
			m_pan.Pan(-dPos);
			m_oldMousePosition = mousePosition;

			Update();
		}

		return true;
	}

	void ViewPort::CursorHideCallback() {
		if (GetForegroundWindow() == Parent()->Handle()) {
			ShowCursor(false);
		}
	}

	SizeInt ViewPort::OptimalViewportSize() {
		return Img::CalculateUnzoomedSize(m_image, m_props.Angle);
	}

	SizeInt ViewPort::ZoomedImageSize() {
		return RoundCast(Img::CalculateUnzoomedSize(m_image, m_props.Angle) * m_imageZoom);
	}

	bool ViewPort::PerformOnSize(const SizeInt& sz) {
		// Make sure that the image is in a useful state
		m_zoom.ResizeBehaviour(App::ResizeBehaviour(Reg::Key(DWResizeBehaviour)));
		auto r = m_zoom.CalculateViewAreaSize(
			GetSize(),
			Img::CalculateUnzoomedSize(m_renderTarget.CurrentSurface(), m_props.Angle),
			Img::CalculateUnzoomedSize(m_image, m_props.Angle));
		m_displayZoom = r.ZoomImage;

		Geom::RectInt newRect(Geom::PointInt(0, 0), r.ZoomedSize);

		if (r.ZoomedSize.Width < sz.Width)	{
			newRect.Left((sz.Width - r.ZoomedSize.Width) / 2);
		}

		if (r.ZoomedSize.Height < sz.Height) {
			newRect.Top((sz.Height - r.ZoomedSize.Height) / 2);
		}

		ZoomSet(r);

		return true;
	}

	void ViewPort::ZoomSet(const ZoomStrategy::Result& r) {
		m_props.Zoom = r.ZoomSurface;
		m_imageZoom = r.ZoomImage;

		m_pan.ResizeConstraints(ZoomedImageSize());
		m_pan.ResizeViewport(r.ZoomedSize);

		//UpdateCursor();

		if (Handle() != 0) {
			InvalidateRect(Handle(), 0, false);
		}
	}

	void ViewPort::updateCursor() {
		m_hideTimer.Destroy();

		switch(m_cursorMode) {
			case CursorHide:
				ShowCursor(false);
				break;

			case CursorShow:
				ShowCursor(true);
				break;

			case CursorHideAutomatic:
				if (MouseCursorPos() != m_oldMousePosition) {
					ShowCursor(true);
				}

				m_hideTimer.Create(HideDelay);
				break;
		}
	}

	void ViewPort::Brightness(int newLevel) {
		m_props.Brightness = newLevel;
	}

	int ViewPort::Brightness() const {
		return m_props.Brightness;
	}

	void ViewPort::Contrast(int newLevel) {
		m_props.Contrast = newLevel;
	}

	int ViewPort::Contrast() const {
		return m_props.Contrast;
	}

	void ViewPort::Gamma(int newLevel) {
		m_props.Gamma = newLevel;
	}

	int ViewPort::Gamma() const {
		return m_props.Gamma;
	}

	bool ViewPort::PerformOnDropFiles( const StringVector& files ) {
		auto parentWindow = dynamic_cast<Win::Window*>(Parent());
		if (parentWindow == nullptr) {
			DO_THROW(Err::CriticalError, TX("Parent window was not a proper window."));
		}

		return parentWindow->OnDropFiles(files);
	}

	bool ViewPort::SetRenderer( Win::Renderer::Ptr renderer ) {
		m_renderTarget.SetRenderer(renderer);
		return m_renderTarget.TargetWindow(Handle());
	}

	void ViewPort::SetRedrawStrategy(Win::RedrawStrategy::Ptr strategy) {
		m_renderTarget.SetRedrawStrategy(strategy);
	}

	void ViewPort::MagnificationFilter( Filter::Mode mode ) {
		m_magFilter = mode;
	}

	void ViewPort::MinificationFilter( Filter::Mode mode ) {
		m_minFilter = mode;
	}

	void ViewPort::ImageUpdated() {
		Image(Image());
	}

	void ViewPort::ZoomUpdated() {
		OnSize(GetSize());
	}

	void ViewPort::ZoomIn() {
		if (m_zoom.ZoomIn()) {
			ZoomUpdated();
		}
	}

	void ViewPort::ZoomOut() {
		if (m_zoom.ZoomOut()) {
			ZoomUpdated();
		}
	}

	void ViewPort::ZoomMode(App::ZoomMode mode) {
		m_zoom.ZoomMode(mode);
		ZoomUpdated();
	}

	App::ZoomMode ViewPort::ZoomMode() const {
		return m_zoom.ZoomMode();
	}

	float ViewPort::ZoomLevel() const {
		return m_displayZoom;
	}
}
<commit_msg>Avoid WM_PAINT spam when no image is being viewed.<commit_after>#include "StdAfx.h"
#include "viewport.h"
#include "registry.h"
#include "illa/config.h"
#include "illa/surfacemgr.h"
#include "getevent.h"

const wchar_t* App::ViewPort::ClassName = TX("Pictus ViewPort");

namespace App {
	using namespace Reg::Keys;
	using Geom::RectInt;
	using Geom::PointInt;
	using Geom::SizeInt;

	ViewPort::ViewPort()
		:m_isCursorVisible(true),
		m_cursorMode(CursorShow),
		m_displayZoom(1.0f),
		m_imageZoom(1.0f),
		m_currentPanMonitor(nullptr),
		m_isPanning(false)
	{
		Img::SurfaceFactory(&m_renderTarget);
		OnMouseMove.connect([&](Win::MouseEvent e) { return HandleMouseMove(e); });
		OnMouseButtonDown.connect([&](Win::MouseEvent e) { return HandleMouseDown(e); });
		OnMouseButtonUp.connect([&](Win::MouseEvent e) { return HandleMouseUp(e); });

		m_hideTimer.OnTick.connect([&]() { CursorHideCallback(); });
		m_animationTimer.OnTick.connect([&]() { ImageRefreshCallback(); });
	}

	bool ViewPort::PerformOnCreate() {
		m_hParent = Parent()->Handle();

		// Register the window class (if possible)
		WNDCLASSEX wc;
		ZeroMemory(&wc, sizeof(wc));
		wc.cbSize			= sizeof(wc);					// Set structure size
		wc.hCursor			= LoadCursor(0, IDC_ARROW);
		wc.hInstance		= GetHINSTANCE();				// Current instance's handle
		wc.lpfnWndProc		= WndProcDelegate;				// Use "delegate" as the wndproc
		wc.lpszClassName	= ClassName;					// Class name
		wc.style			= CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;	// Register double clicks and window resizes
		RegisterClassEx(&wc);

		// Create window without any nifty features
		return ConstructWindow(RectInt(PointInt(0, 0), SizeInt(1, 1)), WS_EX_ACCEPTFILES, ClassName, TX(""), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN);
	}

	void ViewPort::setSurface() {
		m_renderTarget.SetSurface(m_image == 0 ? Img::Surface::Ptr() : m_image->CurrentSurface());
	}

	void ViewPort::Image(Img::Image::Ptr image) {
		m_animationTimer.Destroy();
		bool diff = (m_image != image);
		m_image = image;

		setSurface();

		if (m_image != nullptr) {
			m_pan.ResizeConstraints(image->GetSize());
			m_pan.ResizeViewport(m_renderTarget.TransformedSize());

			if (diff) {
				m_image->RestartAnimation();
			}

			if (diff && Reg::Key(DWResetPan)) {
				m_pan.Reset();
			}

			if (m_image->IsHeaderInformationValid() && m_image->Delay() != -1) {
				m_animationTimer.Create(m_image->Delay());	// It's animated, start timer and stuff
			}
			else if (m_image->IsFinished() == false) {
				m_animationTimer.Create(Img::RedrawDelay);	// Not animated or uncertain. Redraw periodically
			}

		}

		InvalidateRect(Handle(), 0, false);
		OnSize(GetSize());
	}

	Img::Image::Ptr ViewPort::Image() const {
		return m_image;
	}

	void ViewPort::BackgroundColor(const Img::Color& col) {
		m_props.BackgroundColor = col;
	}

	const Img::Color& ViewPort::BackgroundColor() const {
		return m_props.BackgroundColor;
	}

	void ViewPort::Rotate(Filter::RotationAngle r) {
		m_props.Angle = r;

		OnSize(GetSize());
	}

	void ViewPort::ActiveCursorMode(const CursorMode m) {
		m_cursorMode = m;
		updateCursor();
	}

	ViewPort::CursorMode ViewPort::ActiveCursorMode() const {
		return m_cursorMode;
	}

	void ViewPort::Pan(const SizeInt& deltaPan) {
		m_pan.Pan(deltaPan);

		Update();
	}

	void ViewPort::ImageRefreshCallback() {
		if (m_image->IsHeaderInformationValid() == false) return;

		if (m_image->Delay() != -1) {
			m_image->NextFrame();
			m_animationTimer.Create(m_image->Delay());
			Redraw();
		}
		else {
			if (m_image && m_image->IsHeaderInformationValid()) {
				ImageUpdated();
			}

			bool status = m_image->IsFinished();
			Redraw();
			if (status) {
				m_animationTimer.Destroy();
			}
		}
	}

	bool ViewPort::PerformOnPaint() {
		setSurface();

		// TODO: This may call BEFORE the surface is allocated, and will thus fail when attempting to lock.
		if (m_image && m_image->IsHeaderInformationValid() && AreaNonZero(ZoomedImageSize()) && (AreaNonZero(GetSize()))) {
			bool status = m_image->IsFinished();

			m_props.ResampleFilter = ActiveFilterMode();
			m_renderTarget.Render(m_pan.TopLeft(), m_props);

			if ((m_image->Delay() == -1) && status)
				m_animationTimer.Destroy();

			// Direct3D9 Ex (with FLIPEX) doesn't seem to validate the window the same way as vanilla D3D9.
			// Therefore we do it ourselves to prevent WM_PAINT spam.
			ValidateRect(Handle(), nullptr);

			return true;
		}
		else {
			m_renderTarget.Clear(m_props.BackgroundColor);
			ValidateRect(Handle(), nullptr);
			return true;
		}
	}

	Filter::Mode ViewPort::ActiveFilterMode() const {
		if (m_minFilter == Filter::Mode::Undefined) {
			DO_THROW(Err::InvalidCall, TX("Minification filter not set."));
		}
		if (m_magFilter == Filter::Mode::Undefined) {
			DO_THROW(Err::InvalidCall, TX("Magnification filter not set."));
		}

		if (m_props.Zoom < 1.0) {
			return m_minFilter;
		}

		return m_magFilter;
	}

	bool ViewPort::PerformOnApp(int index, WPARAM wp, LPARAM lp) {
		if (Parent()) {
			return Parent()->OnApp(index, wp, lp);
		}
		return false;
	}

	bool ViewPort::HandleMouseDown(Win::MouseEvent e) {
		if (MouseStandardEvent(e) == MousePan) {
			m_isPanning = true;
			m_oldMousePosition = MouseCursorPos();
			m_currentPanMonitor = Win::FindMonitorAt(m_oldMousePosition);
			SetCapture(Handle());
			return true;
		}
		return false;
	}

	bool ViewPort::HandleMouseUp(Win::MouseEvent) {
		// Done panning, release mouse
		ReleaseCapture();

		m_isPanning = false;

		return false;
	}

	bool ViewPort::HandleMouseMove(Win::MouseEvent e) {
		updateCursor();

		if (!((MouseStandardEvent(e) == MousePan) && m_isPanning == true)) {
			return false;
		}

		if (m_currentPanMonitor == nullptr) {
			DO_THROW(Err::CriticalError, TX("Current panning monitor not set."));
		}

		auto globalPosition = MouseCursorPos();
		auto mousePosition = globalPosition;

		const Geom::RectInt& screen = m_currentPanMonitor->Region();

		if (mousePosition.X >= (screen.Right() - 1)) {
			mousePosition.X = screen.Left() + 1;
		}

		if (mousePosition.X <= screen.Left()) {
			mousePosition.X = screen.Right() - 2;
		}

		if (mousePosition.Y >= (screen.Bottom() - 1)) {
			mousePosition.Y = screen.Top() + 1;
		}

		if (mousePosition.Y <= screen.Top()) {
			mousePosition.Y = screen.Bottom() - 2;
		}

		if (globalPosition != mousePosition) {
			SetCursorPos(mousePosition.X, mousePosition.Y);
			// Fix for RDP and similar. Sometimes (often) SetCursorPos fails silently, so we need to check manually to
			// see if it had any effect.
			POINT p;
			GetCursorPos(&p);
			mousePosition.X = p.x; mousePosition.Y = p.y;

			m_oldMousePosition = mousePosition;
		}

		SizeInt dPos(mousePosition - m_oldMousePosition);
		if ((dPos.Width != 0) || (dPos.Height != 0)) {
			m_pan.Pan(-dPos);
			m_oldMousePosition = mousePosition;

			Update();
		}

		return true;
	}

	void ViewPort::CursorHideCallback() {
		if (GetForegroundWindow() == Parent()->Handle()) {
			ShowCursor(false);
		}
	}

	SizeInt ViewPort::OptimalViewportSize() {
		return Img::CalculateUnzoomedSize(m_image, m_props.Angle);
	}

	SizeInt ViewPort::ZoomedImageSize() {
		return RoundCast(Img::CalculateUnzoomedSize(m_image, m_props.Angle) * m_imageZoom);
	}

	bool ViewPort::PerformOnSize(const SizeInt& sz) {
		// Make sure that the image is in a useful state
		m_zoom.ResizeBehaviour(App::ResizeBehaviour(Reg::Key(DWResizeBehaviour)));
		auto r = m_zoom.CalculateViewAreaSize(
			GetSize(),
			Img::CalculateUnzoomedSize(m_renderTarget.CurrentSurface(), m_props.Angle),
			Img::CalculateUnzoomedSize(m_image, m_props.Angle));
		m_displayZoom = r.ZoomImage;

		Geom::RectInt newRect(Geom::PointInt(0, 0), r.ZoomedSize);

		if (r.ZoomedSize.Width < sz.Width)	{
			newRect.Left((sz.Width - r.ZoomedSize.Width) / 2);
		}

		if (r.ZoomedSize.Height < sz.Height) {
			newRect.Top((sz.Height - r.ZoomedSize.Height) / 2);
		}

		ZoomSet(r);

		return true;
	}

	void ViewPort::ZoomSet(const ZoomStrategy::Result& r) {
		m_props.Zoom = r.ZoomSurface;
		m_imageZoom = r.ZoomImage;

		m_pan.ResizeConstraints(ZoomedImageSize());
		m_pan.ResizeViewport(r.ZoomedSize);

		//UpdateCursor();

		if (Handle() != 0) {
			InvalidateRect(Handle(), 0, false);
		}
	}

	void ViewPort::updateCursor() {
		m_hideTimer.Destroy();

		switch(m_cursorMode) {
			case CursorHide:
				ShowCursor(false);
				break;

			case CursorShow:
				ShowCursor(true);
				break;

			case CursorHideAutomatic:
				if (MouseCursorPos() != m_oldMousePosition) {
					ShowCursor(true);
				}

				m_hideTimer.Create(HideDelay);
				break;
		}
	}

	void ViewPort::Brightness(int newLevel) {
		m_props.Brightness = newLevel;
	}

	int ViewPort::Brightness() const {
		return m_props.Brightness;
	}

	void ViewPort::Contrast(int newLevel) {
		m_props.Contrast = newLevel;
	}

	int ViewPort::Contrast() const {
		return m_props.Contrast;
	}

	void ViewPort::Gamma(int newLevel) {
		m_props.Gamma = newLevel;
	}

	int ViewPort::Gamma() const {
		return m_props.Gamma;
	}

	bool ViewPort::PerformOnDropFiles( const StringVector& files ) {
		auto parentWindow = dynamic_cast<Win::Window*>(Parent());
		if (parentWindow == nullptr) {
			DO_THROW(Err::CriticalError, TX("Parent window was not a proper window."));
		}

		return parentWindow->OnDropFiles(files);
	}

	bool ViewPort::SetRenderer( Win::Renderer::Ptr renderer ) {
		m_renderTarget.SetRenderer(renderer);
		return m_renderTarget.TargetWindow(Handle());
	}

	void ViewPort::SetRedrawStrategy(Win::RedrawStrategy::Ptr strategy) {
		m_renderTarget.SetRedrawStrategy(strategy);
	}

	void ViewPort::MagnificationFilter( Filter::Mode mode ) {
		m_magFilter = mode;
	}

	void ViewPort::MinificationFilter( Filter::Mode mode ) {
		m_minFilter = mode;
	}

	void ViewPort::ImageUpdated() {
		Image(Image());
	}

	void ViewPort::ZoomUpdated() {
		OnSize(GetSize());
	}

	void ViewPort::ZoomIn() {
		if (m_zoom.ZoomIn()) {
			ZoomUpdated();
		}
	}

	void ViewPort::ZoomOut() {
		if (m_zoom.ZoomOut()) {
			ZoomUpdated();
		}
	}

	void ViewPort::ZoomMode(App::ZoomMode mode) {
		m_zoom.ZoomMode(mode);
		ZoomUpdated();
	}

	App::ZoomMode ViewPort::ZoomMode() const {
		return m_zoom.ZoomMode();
	}

	float ViewPort::ZoomLevel() const {
		return m_displayZoom;
	}
}
<|endoftext|>