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

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2007-12-11 14:46:19 +0100 (Di, 11 Dez 2007) $
Version:   $Revision: 13129 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 "mitkNavigationDataRecorder.h"
#include <fstream>

#include <mitkTimeStamp.h>
#include <tinyxml.h>

#include <itksys/SystemTools.hxx>

mitk::NavigationDataRecorder::NavigationDataRecorder()
{
  m_NumberOfInputs = 0;
  m_RecordingMode = NormalFile;
  m_Recording = false;
  m_NumberOfRecordedFiles = 0;
  m_Stream = NULL;
  m_FileName = "";
  m_SystemTimeClock = RealTimeClock::New();
  m_OutputFormat = mitk::NavigationDataRecorder::xml;

  //To get a start time
  mitk::TimeStamp::GetInstance()->Start(this);

}

mitk::NavigationDataRecorder::~NavigationDataRecorder()
{
}

void mitk::NavigationDataRecorder::GenerateData()
{

}

void mitk::NavigationDataRecorder::AddNavigationData( const NavigationData* nd )
{
  // Process object is not const-correct so the const_cast is required here
  this->SetNthInput(m_NumberOfInputs,
    const_cast< mitk::NavigationData * >( nd ) );

  m_NumberOfInputs++;

  this->Modified();
}

void mitk::NavigationDataRecorder::SetRecordingMode( RecordingMode mode )
{
  m_RecordingMode = mode;
  this->Modified();
}

void mitk::NavigationDataRecorder::Update()
{
  if (m_Recording)
  {
    DataObjectPointerArray inputs = this->GetInputs(); //get all inputs
    mitk::NavigationData::TimeStampType timestamp=0.0; // timestamp for mitk time
    timestamp = mitk::TimeStamp::GetInstance()->GetElapsed();

    mitk::NavigationData::TimeStampType sysTimestamp = 0.0; // timestamp for system time
    sysTimestamp = m_SystemTimeClock->GetCurrentStamp();

    // cast system time double value to stringstream to avoid low precision rounding
    std::ostringstream strs;
    strs.precision(15); // rounding precision for system time double value
    strs << sysTimestamp;
    std::string sysTimeStr = strs.str();

    //write csv header if first line
    if ((m_OutputFormat == mitk::NavigationDataRecorder::csv) && m_firstLine)
      {
      m_firstLine = false;
      *m_Stream << "TimeStamp";
      for (unsigned int index = 0; index < inputs.size(); index++){ *m_Stream << ";Valid_Tool" << index <<
                                                                                ";X_Tool" << index <<
                                                                                ";Y_Tool" << index <<
                                                                                ";Z_Tool" << index <<
                                                                                ";QX_Tool" << index <<
                                                                                ";QY_Tool" << index <<
                                                                                ";QZ_Tool" << index <<
                                                                                ";QR_Tool" << index;}
      *m_Stream << "\n";
      }

    *m_Stream << timestamp;
    for (unsigned int index = 0; index < inputs.size(); index++)
    {
      mitk::NavigationData* nd = dynamic_cast<mitk::NavigationData*>(inputs[index].GetPointer());
      nd->Update(); // call update to propagate update to previous filters

      mitk::NavigationData::PositionType position;
      mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0);
      mitk::NavigationData::CovarianceMatrixType matrix;

      bool hasPosition = true;
      bool hasOrientation = true;
      bool dataValid = false;

      position.Fill(0.0);
      matrix.SetIdentity();

      position = nd->GetPosition();
      orientation = nd->GetOrientation();
      matrix = nd->GetCovErrorMatrix();

      hasPosition = nd->GetHasPosition();
      hasOrientation = nd->GetHasOrientation();
      dataValid = nd->IsDataValid();

      //use this one if you want the timestamps of the source
      //timestamp = nd->GetTimeStamp();

      //a timestamp is never < 0! this case happens only if you are using the timestamp of the nd object instead of getting a new one
      if (timestamp >= 0)
      {
        if (this->m_OutputFormat = mitk::NavigationDataRecorder::xml)
          {
          TiXmlElement* elem = new TiXmlElement("ND");

          elem->SetDoubleAttribute("Time", timestamp);
          elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time
          elem->SetDoubleAttribute("Tool", index);
          elem->SetDoubleAttribute("X", position[0]);
          elem->SetDoubleAttribute("Y", position[1]);
          elem->SetDoubleAttribute("Z", position[2]);

          elem->SetDoubleAttribute("QX", orientation[0]);
          elem->SetDoubleAttribute("QY", orientation[1]);
          elem->SetDoubleAttribute("QZ", orientation[2]);
          elem->SetDoubleAttribute("QR", orientation[3]);

          elem->SetDoubleAttribute("C00", matrix[0][0]);
          elem->SetDoubleAttribute("C01", matrix[0][1]);
          elem->SetDoubleAttribute("C02", matrix[0][2]);
          elem->SetDoubleAttribute("C03", matrix[0][3]);
          elem->SetDoubleAttribute("C04", matrix[0][4]);
          elem->SetDoubleAttribute("C05", matrix[0][5]);
          elem->SetDoubleAttribute("C10", matrix[1][0]);
          elem->SetDoubleAttribute("C11", matrix[1][1]);
          elem->SetDoubleAttribute("C12", matrix[1][2]);
          elem->SetDoubleAttribute("C13", matrix[1][3]);
          elem->SetDoubleAttribute("C14", matrix[1][4]);
          elem->SetDoubleAttribute("C15", matrix[1][5]);

          if (dataValid)
            elem->SetAttribute("Valid",1);
          else
            elem->SetAttribute("Valid",0);

          if (hasOrientation)
            elem->SetAttribute("hO",1);
          else
            elem->SetAttribute("hO",0);

          if (hasPosition)
            elem->SetAttribute("hP",1);
          else
            elem->SetAttribute("hP",0);

          *m_Stream << "        " << *elem << std::endl;

          delete elem;
          }
        else if (this->m_OutputFormat = mitk::NavigationDataRecorder::csv)
          {
          *m_Stream << ";" << dataValid << ";" << position[0] << ";" << position[1] << ";" << position[2] << ";" << orientation[0] << ";" << orientation[1] << ";" << orientation[2] << ";" << orientation[3];
          }
      }
    }
    if (this->m_OutputFormat = mitk::NavigationDataRecorder::csv) *m_Stream << "\n";
  }
}

void mitk::NavigationDataRecorder::StartRecording()
{
  if (m_Recording)
  {
    std::cout << "Already recording please stop before start new recording session" << std::endl;
    return;
  }
  if (m_Stream == NULL)
  {
    std::stringstream ss;
    std::ostream* stream;

    //An existing extension will be cut and replaced with .xml
    std::string tmpPath = itksys::SystemTools::GetFilenamePath(m_FileName);
    m_FileName = itksys::SystemTools::GetFilenameWithoutExtension(m_FileName);
    if (m_OutputFormat == mitk::NavigationDataRecorder::csv) ss << tmpPath << "/" <<  m_FileName << "-" << m_NumberOfRecordedFiles << ".csv";
    else ss << tmpPath << "/" <<  m_FileName << "-" << m_NumberOfRecordedFiles << ".xml";
    switch(m_RecordingMode)
    {
      case Console:
        stream = &std::cout;
        break;
      case NormalFile:

        //Check if there is a file name and path
        if (m_FileName == "")
        {
          stream = &std::cout;
          std::cout << "No file name or file path set the output is redirected to the console";
        }
        else
        {
          stream = new std::ofstream(ss.str().c_str());
        }

        break;
      case ZipFile:
        stream = &std::cout;
        std::cout << "Sorry no ZipFile support yet";
        break;
      default:
        stream = &std::cout;
        break;
    }
    m_firstLine = true;
    StartRecording(stream);
  }

}
void mitk::NavigationDataRecorder::StartRecording(std::ostream* stream)
{
  if (m_Recording)
  {
    std::cout << "Already recording please stop before start new recording session" << std::endl;
    return;
  }

  m_Stream = stream;
  m_Stream->precision(10);

  //TODO store date and GMT time
  if (m_Stream)
  {
    if (m_OutputFormat == mitk::NavigationDataRecorder::xml)
      {
      *m_Stream << "<?xml version=\"1.0\" ?>" << std::endl;
      /**m_Stream << "<Version Ver=\"1\" />" << std::endl;*/
      // should be a generic version, meaning a member variable, which has the actual version
      *m_Stream << "    " << "<Data ToolCount=\"" << (m_NumberOfInputs) << "\" version=\"1.0\">" << std::endl;
      }
    m_Recording = true;
  }
}
void mitk::NavigationDataRecorder::StopRecording()
{
  if (!m_Recording)
  {
    std::cout << "You have to start a recording first" << std::endl;
    return;
  }
  if (m_Stream)
  {
    *m_Stream << "</Data>" << std::endl;
  }

  m_NumberOfRecordedFiles++;
  m_Stream = NULL;
  m_Recording = false;
}<commit_msg>fixed a bug in csv-mode of navigationDataRecorder<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2007-12-11 14:46:19 +0100 (Di, 11 Dez 2007) $
Version:   $Revision: 13129 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 "mitkNavigationDataRecorder.h"
#include <fstream>

#include <mitkTimeStamp.h>
#include <tinyxml.h>

#include <itksys/SystemTools.hxx>

mitk::NavigationDataRecorder::NavigationDataRecorder()
{
  m_NumberOfInputs = 0;
  m_RecordingMode = NormalFile;
  m_Recording = false;
  m_NumberOfRecordedFiles = 0;
  m_Stream = NULL;
  m_FileName = "";
  m_SystemTimeClock = RealTimeClock::New();
  m_OutputFormat = mitk::NavigationDataRecorder::xml;

  //To get a start time
  mitk::TimeStamp::GetInstance()->Start(this);

}

mitk::NavigationDataRecorder::~NavigationDataRecorder()
{
}

void mitk::NavigationDataRecorder::GenerateData()
{

}

void mitk::NavigationDataRecorder::AddNavigationData( const NavigationData* nd )
{
  // Process object is not const-correct so the const_cast is required here
  this->SetNthInput(m_NumberOfInputs,
    const_cast< mitk::NavigationData * >( nd ) );

  m_NumberOfInputs++;

  this->Modified();
}

void mitk::NavigationDataRecorder::SetRecordingMode( RecordingMode mode )
{
  m_RecordingMode = mode;
  this->Modified();
}

void mitk::NavigationDataRecorder::Update()
{
  if (m_Recording)
  {
    DataObjectPointerArray inputs = this->GetInputs(); //get all inputs
    mitk::NavigationData::TimeStampType timestamp=0.0; // timestamp for mitk time
    timestamp = mitk::TimeStamp::GetInstance()->GetElapsed();

    mitk::NavigationData::TimeStampType sysTimestamp = 0.0; // timestamp for system time
    sysTimestamp = m_SystemTimeClock->GetCurrentStamp();

    // cast system time double value to stringstream to avoid low precision rounding
    std::ostringstream strs;
    strs.precision(15); // rounding precision for system time double value
    strs << sysTimestamp;
    std::string sysTimeStr = strs.str();

    //write csv header if first line
    if ((m_OutputFormat == mitk::NavigationDataRecorder::csv) && m_firstLine)
      {
      m_firstLine = false;
      *m_Stream << "TimeStamp";
      for (unsigned int index = 0; index < inputs.size(); index++){ *m_Stream << ";Valid_Tool" << index <<
                                                                                ";X_Tool" << index <<
                                                                                ";Y_Tool" << index <<
                                                                                ";Z_Tool" << index <<
                                                                                ";QX_Tool" << index <<
                                                                                ";QY_Tool" << index <<
                                                                                ";QZ_Tool" << index <<
                                                                                ";QR_Tool" << index;}
      *m_Stream << "\n";
      }

    *m_Stream << timestamp;
    for (unsigned int index = 0; index < inputs.size(); index++)
    {
      mitk::NavigationData* nd = dynamic_cast<mitk::NavigationData*>(inputs[index].GetPointer());
      nd->Update(); // call update to propagate update to previous filters

      mitk::NavigationData::PositionType position;
      mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0);
      mitk::NavigationData::CovarianceMatrixType matrix;

      bool hasPosition = true;
      bool hasOrientation = true;
      bool dataValid = false;

      position.Fill(0.0);
      matrix.SetIdentity();

      position = nd->GetPosition();
      orientation = nd->GetOrientation();
      matrix = nd->GetCovErrorMatrix();

      hasPosition = nd->GetHasPosition();
      hasOrientation = nd->GetHasOrientation();
      dataValid = nd->IsDataValid();

      //use this one if you want the timestamps of the source
      //timestamp = nd->GetTimeStamp();

      //a timestamp is never < 0! this case happens only if you are using the timestamp of the nd object instead of getting a new one
      if (timestamp >= 0)
      {
        if (this->m_OutputFormat = mitk::NavigationDataRecorder::xml)
          {
          TiXmlElement* elem = new TiXmlElement("ND");

          elem->SetDoubleAttribute("Time", timestamp);
          elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time
          elem->SetDoubleAttribute("Tool", index);
          elem->SetDoubleAttribute("X", position[0]);
          elem->SetDoubleAttribute("Y", position[1]);
          elem->SetDoubleAttribute("Z", position[2]);

          elem->SetDoubleAttribute("QX", orientation[0]);
          elem->SetDoubleAttribute("QY", orientation[1]);
          elem->SetDoubleAttribute("QZ", orientation[2]);
          elem->SetDoubleAttribute("QR", orientation[3]);

          elem->SetDoubleAttribute("C00", matrix[0][0]);
          elem->SetDoubleAttribute("C01", matrix[0][1]);
          elem->SetDoubleAttribute("C02", matrix[0][2]);
          elem->SetDoubleAttribute("C03", matrix[0][3]);
          elem->SetDoubleAttribute("C04", matrix[0][4]);
          elem->SetDoubleAttribute("C05", matrix[0][5]);
          elem->SetDoubleAttribute("C10", matrix[1][0]);
          elem->SetDoubleAttribute("C11", matrix[1][1]);
          elem->SetDoubleAttribute("C12", matrix[1][2]);
          elem->SetDoubleAttribute("C13", matrix[1][3]);
          elem->SetDoubleAttribute("C14", matrix[1][4]);
          elem->SetDoubleAttribute("C15", matrix[1][5]);

          if (dataValid)
            elem->SetAttribute("Valid",1);
          else
            elem->SetAttribute("Valid",0);

          if (hasOrientation)
            elem->SetAttribute("hO",1);
          else
            elem->SetAttribute("hO",0);

          if (hasPosition)
            elem->SetAttribute("hP",1);
          else
            elem->SetAttribute("hP",0);

          *m_Stream << "        " << *elem << std::endl;

          delete elem;
          }
        else if (this->m_OutputFormat = mitk::NavigationDataRecorder::csv)
          {
          *m_Stream << ";" << dataValid << ";" << position[0] << ";" << position[1] << ";" << position[2] << ";" << orientation[0] << ";" << orientation[1] << ";" << orientation[2] << ";" << orientation[3];
          }
      }
    }
    if (this->m_OutputFormat = mitk::NavigationDataRecorder::csv) *m_Stream << "\n";
  }
}

void mitk::NavigationDataRecorder::StartRecording()
{
  if (m_Recording)
  {
    std::cout << "Already recording please stop before start new recording session" << std::endl;
    return;
  }
  if (m_Stream == NULL)
  {
    std::stringstream ss;
    std::ostream* stream;

    //An existing extension will be cut and replaced with .xml
    std::string tmpPath = itksys::SystemTools::GetFilenamePath(m_FileName);
    m_FileName = itksys::SystemTools::GetFilenameWithoutExtension(m_FileName);
    if (m_OutputFormat == mitk::NavigationDataRecorder::csv) ss << tmpPath << "/" <<  m_FileName << "-" << m_NumberOfRecordedFiles << ".csv";
    else ss << tmpPath << "/" <<  m_FileName << "-" << m_NumberOfRecordedFiles << ".xml";
    switch(m_RecordingMode)
    {
      case Console:
        stream = &std::cout;
        break;
      case NormalFile:

        //Check if there is a file name and path
        if (m_FileName == "")
        {
          stream = &std::cout;
          std::cout << "No file name or file path set the output is redirected to the console";
        }
        else
        {
          stream = new std::ofstream(ss.str().c_str());
        }

        break;
      case ZipFile:
        stream = &std::cout;
        std::cout << "Sorry no ZipFile support yet";
        break;
      default:
        stream = &std::cout;
        break;
    }
    m_firstLine = true;
    StartRecording(stream);
  }

}
void mitk::NavigationDataRecorder::StartRecording(std::ostream* stream)
{
  if (m_Recording)
  {
    std::cout << "Already recording please stop before start new recording session" << std::endl;
    return;
  }

  m_Stream = stream;
  m_Stream->precision(10);

  //TODO store date and GMT time
  if (m_Stream)
  {
    if (m_OutputFormat == mitk::NavigationDataRecorder::xml)
      {
      *m_Stream << "<?xml version=\"1.0\" ?>" << std::endl;
      /**m_Stream << "<Version Ver=\"1\" />" << std::endl;*/
      // should be a generic version, meaning a member variable, which has the actual version
      *m_Stream << "    " << "<Data ToolCount=\"" << (m_NumberOfInputs) << "\" version=\"1.0\">" << std::endl;
      }
    m_Recording = true;
  }
}
void mitk::NavigationDataRecorder::StopRecording()
{
  if (!m_Recording)
  {
    std::cout << "You have to start a recording first" << std::endl;
    return;
  }

  if (m_Stream && m_OutputFormat == mitk::NavigationDataRecorder::xml)
  {
    *m_Stream << "</Data>" << std::endl;
  }

  m_NumberOfRecordedFiles++;
  m_Stream = NULL;
  m_Recording = false;
}<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Compute the absolute value of each element in `X` and assign the result to an element in `Y`.
*/
#include <nan.h>
#include "stdlib_strided_dabs.h"

/**
* Add-on namespace.
*/
namespace addon_strided_dabs {

	using Nan::FunctionCallbackInfo;
	using Nan::TypedArrayContents;
	using Nan::ThrowTypeError;
	using Nan::ThrowError;
	using v8::Number;
	using v8::Local;
	using v8::Value;

	/**
	* Computes the absolute value of each element in `X` and assigns the result to an element in `Y`.
	*
	* When called from JavaScript, the function expects the following arguments:
	*
	* * __N__: number of elements.
	* * __X__: input `Float64Array`.
	* * __strideX__: `X` stride length.
	* * __Y__: destination `Float64Array`.
	* * __strideY__: `Y` stride length.
	*
	* @param info   arguments
	*/
	void node_dabs( const FunctionCallbackInfo<Value>& info ) {
		if ( info.Length() != 5 ) {
			ThrowError( "invalid invocation. Must provide 5 arguments." );
			return;
		}
		if ( !info[ 0 ]->IsNumber() ) {
			ThrowTypeError( "invalid input argument. First argument must be a number." );
			return;
		}
		if ( !info[ 2 ]->IsNumber() ) {
			ThrowTypeError( "invalid input argument. Third argument must be a number." );
			return;
		}
		if ( !info[ 4 ]->IsNumber() ) {
			ThrowTypeError( "invalid input argument. Firth argument must be a number." );
			return;
		}
		const int N = info[ 0 ]->Uint32Value();
		const int strideX = info[ 2 ]->Uint32Value();
		const int strideY = info[ 4 ]->Uint32Value();

		// We assume we were given Float64Arrays. In Node v0.10, typed arrays required special access and construction.
		TypedArrayContents<double> X( info[ 1 ] );
		TypedArrayContents<double> Y( info[ 3 ] );

		stdlib_strided_dabs( N, *X, strideX, *Y, strideY );
	}

	NAN_MODULE_INIT( Init ) {
		Nan::Export( target, "dabs", node_dabs );
	}

	NODE_MODULE( addon, Init )
} // end namespace addon_strided_dabs
<commit_msg>Remove unused namespaces<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Compute the absolute value of each element in `X` and assign the result to an element in `Y`.
*/
#include <nan.h>
#include "stdlib_strided_dabs.h"

/**
* Add-on namespace.
*/
namespace addon_strided_dabs {

	using Nan::FunctionCallbackInfo;
	using Nan::TypedArrayContents;
	using Nan::ThrowTypeError;
	using Nan::ThrowError;
	using v8::Value;

	/**
	* Computes the absolute value of each element in `X` and assigns the result to an element in `Y`.
	*
	* When called from JavaScript, the function expects the following arguments:
	*
	* * __N__: number of elements.
	* * __X__: input `Float64Array`.
	* * __strideX__: `X` stride length.
	* * __Y__: destination `Float64Array`.
	* * __strideY__: `Y` stride length.
	*
	* @param info   arguments
	*/
	void node_dabs( const FunctionCallbackInfo<Value>& info ) {
		if ( info.Length() != 5 ) {
			ThrowError( "invalid invocation. Must provide 5 arguments." );
			return;
		}
		if ( !info[ 0 ]->IsNumber() ) {
			ThrowTypeError( "invalid input argument. First argument must be a number." );
			return;
		}
		if ( !info[ 2 ]->IsNumber() ) {
			ThrowTypeError( "invalid input argument. Third argument must be a number." );
			return;
		}
		if ( !info[ 4 ]->IsNumber() ) {
			ThrowTypeError( "invalid input argument. Firth argument must be a number." );
			return;
		}
		const int N = info[ 0 ]->Uint32Value();
		const int strideX = info[ 2 ]->Uint32Value();
		const int strideY = info[ 4 ]->Uint32Value();

		// We assume we were given Float64Arrays. In Node v0.10, typed arrays required special access and construction.
		TypedArrayContents<double> X( info[ 1 ] );
		TypedArrayContents<double> Y( info[ 3 ] );

		stdlib_strided_dabs( N, *X, strideX, *Y, strideY );
	}

	NAN_MODULE_INIT( Init ) {
		Nan::Export( target, "dabs", node_dabs );
	}

	NODE_MODULE( addon, Init )
} // end namespace addon_strided_dabs
<|endoftext|>


<commit_before>#include <node.h>
#include <node_buffer.h>
#include <string.h>
#include <v8.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#ifdef __APPLE__
#include <malloc/malloc.h>
#endif
#include <zlib.h>

// zlib magic something
#define WBITS 16+MAX_WBITS
#define WBITS_RAW -15

#define CHUNK 1024*100
#define HEADER_SIZE 10
#define FOOTER_SIZE 8
#define SPACER_SIZE 6

using namespace v8;
using namespace node;

static Persistent<String> SYM_BODY;
static Persistent<String> SYM_LEFT;
static Persistent<String> SYM_RIGHT;
static Persistent<String> SYM_LAST;
static Persistent<String> SYM_TYPE;
static Persistent<String> SYM_OFFSETS;
static Persistent<String> SYM_LENGTH;
static Persistent<String> SYM_RAW_LENGTH;
static Persistent<String> SYM_CRC;
static Persistent<String> SYM_META;
static Persistent<String> SYM_BUFFERS;
static Persistent<String> SYM_HEADER;
static Persistent<String> SYM_ODD;

static Handle<Value> ThrowNodeError (const char* what = NULL) {
    return ThrowException(Exception::Error(String::New(what)));
}

static int meta_uncompress (char *dataIn, size_t bytesIn, int *dataType) {
    z_stream strmUncompress;

    strmUncompress.zalloc = Z_NULL;
    strmUncompress.zfree = Z_NULL;
    strmUncompress.opaque = Z_NULL;
    strmUncompress.avail_in = 0;
    strmUncompress.next_in = Z_NULL;

    //this can be further improved!
    //we should only do inflate if the the stream is compressed
    //and header skip should be done earlier
    if (inflateInit2(&strmUncompress, WBITS_RAW) != Z_OK) {
        return -1;
    }

    unsigned char *tmp = (unsigned char *) malloc(CHUNK);

    //skipping header
    strmUncompress.next_in = ((unsigned char *) dataIn) + HEADER_SIZE;
    strmUncompress.avail_in = bytesIn - HEADER_SIZE;

    //checking if stream is compressed, first byte - binary:
    //xxxxx001 - stream is NOT compressed
    //xxxxx011 - stream is compressed (using fixed huffman codes)
    //xxxxx111 - stream is compressed (using dynamic huffman codes)
    if ((*strmUncompress.next_in & 3) == 3 || (*strmUncompress.next_in & 5) == 5) {
        for (;;) {
            strmUncompress.avail_out = CHUNK;
            strmUncompress.next_out = tmp;

            int ret = inflate(&strmUncompress, Z_BLOCK);

            assert(ret != Z_STREAM_ERROR);

            switch (ret) {
                case Z_NEED_DICT:
                    ret = Z_DATA_ERROR;     /* and fall through */
                case Z_DATA_ERROR:
                case Z_MEM_ERROR:
                    inflateEnd(&strmUncompress);
                    if (tmp != NULL) {
                        free(tmp);
                    }

                    return -2;
            }

            if (strmUncompress.data_type & 128) {
                break;
            }
        }
        *dataType = strmUncompress.data_type;
    } else {
        *dataType = 128;
    }

    inflateEnd(&strmUncompress);

    return 0;

}

static int compress (char *dataIn, size_t bytesIn, int compressionLevel, char **dataOut, size_t *bytesOut) {
    size_t bytesDeflated = 0;

    if (compressionLevel < 0 || compressionLevel > 9) {
        compressionLevel = Z_DEFAULT_COMPRESSION;
    }

    z_stream strmCompress;
    strmCompress.zalloc = Z_NULL;
    strmCompress.zfree = Z_NULL;
    strmCompress.opaque = Z_NULL;

    if (deflateInit2(&strmCompress, compressionLevel, Z_DEFLATED, WBITS, 8L, Z_DEFAULT_STRATEGY) != Z_OK) {
        return -1;
    }

    bytesDeflated = deflateBound(&strmCompress, bytesIn);

    if (bytesDeflated < 1024) {
        bytesDeflated = 1024;
    }

    *dataOut = (char *) malloc(bytesDeflated);

    strmCompress.next_in = (Bytef *) dataIn;
    strmCompress.avail_in = bytesIn;
    strmCompress.next_out = (Bytef *) *dataOut;
    strmCompress.avail_out = bytesDeflated;

    if (deflate(&strmCompress, Z_NO_FLUSH) < Z_OK) {
        deflateReset(&strmCompress);
        return -2;
    }

    deflate(&strmCompress, Z_FINISH);

    *bytesOut = strmCompress.total_out;

    deflateReset(&strmCompress);

    return 0;
}

static Handle<Value> onet_compress (const Arguments &args) {
    HandleScope scope;

    int compressionLevel = Z_DEFAULT_COMPRESSION;

    if (args.Length() < 1) {
        return Undefined();
    }

    if (!Buffer::HasInstance(args[0])) {
        ThrowNodeError("First argument must be a Buffer");
        return Undefined();
    }

    Local<Object> bufferIn = args[0]->ToObject();

    if (args.Length() > 1) {
        compressionLevel = args[1]->IntegerValue();
    }

    char *dataIn = Buffer::Data(bufferIn);
    size_t bytesIn = Buffer::Length(bufferIn);
    char *dataOut = 0;
    size_t bytesOut = 0;
    int dataType = 0;
    int status = compress(dataIn, bytesIn, compressionLevel, &dataOut, &bytesOut);

    if (status != 0) {
        char msg[30];
        sprintf(msg, "Unable to compress: %d", status);
        ThrowNodeError(msg);
        return Undefined();
    }

    status = meta_uncompress(dataOut, bytesOut, &dataType);

    if (status != 0) {
        char msg[30];
        sprintf(msg, "Unable to uncompress: %d", status);
        ThrowNodeError(msg);
        return Undefined();
    }

    unsigned int dataLength = bytesOut - HEADER_SIZE - FOOTER_SIZE - 1;

    Local<Object> result = Object::New();

    Buffer *body = Buffer::New((char *) dataOut, bytesOut);
    result->Set(SYM_BODY, body->handle_);

    Local<Object> dataOffsets = Object::New();
    dataOffsets->Set(SYM_LEFT, Integer::New(HEADER_SIZE));
    dataOffsets->Set(SYM_RIGHT, Integer::New(HEADER_SIZE + dataLength));
    dataOffsets->Set(SYM_LAST, Integer::New(HEADER_SIZE + dataLength));

    Buffer *crc = Buffer::New((char *) dataOut + (bytesOut - FOOTER_SIZE), 4);

    Local<Object> meta = Object::New();
    meta->Set(SYM_TYPE, Integer::New(dataType));
    meta->Set(SYM_OFFSETS, dataOffsets);
    meta->Set(SYM_LENGTH, Integer::New(bytesIn));
    meta->Set(SYM_RAW_LENGTH, Integer::New(bytesOut - HEADER_SIZE - FOOTER_SIZE));
    meta->Set(SYM_CRC, crc->handle_);

    result->Set(SYM_META, meta);

    free(dataOut);

    return scope.Close(result);
}

static Handle<Value> compress (const Arguments& args) {
    HandleScope scope;

    int compressionLevel = Z_DEFAULT_COMPRESSION;

    if (args.Length() < 1) {
        return Undefined();
    }

    if (!Buffer::HasInstance(args[0])) {
        ThrowNodeError("First argument must be a Buffer");
        return Undefined();
    }

    Local<Object> bufferIn = args[0]->ToObject();

    if (args.Length() > 1) {
        compressionLevel = args[1]->IntegerValue();
    }

    char *dataIn = Buffer::Data(bufferIn);
    size_t bytesIn = Buffer::Length(bufferIn);
    char *dataOut = 0;
    size_t bytesOut = 0;
    int status = compress(dataIn, bytesIn, compressionLevel, &dataOut, &bytesOut);

    if (status != 0) {
        ThrowNodeError("Unable to compress");
        return Undefined();
    }

    Buffer *buff = Buffer::New(dataOut, bytesOut);

    return scope.Close(buff->handle_);
}

static Handle<Value> estimate (const Arguments &args) {
    HandleScope scope;

    Local<Array> arr = Local<Array>::Cast(args[0]);
    int i = 0;
    int l = arr->Length();
    int sum = HEADER_SIZE + FOOTER_SIZE + ((l - 1) * SPACER_SIZE);

    for(; i < l; i++) {
        Local<Object> obj = arr->Get(i)->ToObject();
        Local<Object> meta = obj->Get(SYM_META)->ToObject();

        sum += meta->Get(SYM_RAW_LENGTH)->Uint32Value();
    }

    return scope.Close(Integer::New(sum));
}

static unsigned long reverseBytes (unsigned char *buf) {
    unsigned long v;

    v = *buf;
    v += (unsigned long) *(buf + 1) << 8;
    v += (unsigned long) *(buf + 2) << 16;
    v += (unsigned long) *(buf + 3) << 24;

    return v;
}

static Handle<Value> getCrc (const Arguments &args) {
    HandleScope scope;

    unsigned long crc = crc32(0L, Z_NULL, 0);
    unsigned long tot = 0;

    Local<Array> arr = Local<Array>::Cast(args[0]);

    int l = arr->Length();
    int i = 0;

    for (; i < l; i++) {
        Local<Object> obj = arr->Get(i)->ToObject();
        Local<Object> meta = obj->Get(SYM_META)->ToObject();

        Local<Object> bufCrc = meta->Get(SYM_CRC)->ToObject();

        unsigned long tmpCrc = reverseBytes((unsigned char *) Buffer::Data(bufCrc));
        unsigned long tmpLen = meta->Get(SYM_LENGTH)->Uint32Value();

        crc = crc32_combine(crc, tmpCrc, tmpLen);
        tot += tmpLen;
    }

    Local<Object> data = Object::New();
    data->Set(SYM_CRC, Buffer::New((char *) &crc, 4)->handle_);
    data->Set(SYM_LENGTH, Buffer::New((char *) &tot, 4)->handle_);

    return scope.Close(data);
}

static Handle<Value> uncompress (const Arguments &args) {
    HandleScope scope;

    if (args.Length() < 1) {
        return Undefined();
    }

    if (!Buffer::HasInstance(args[0])) {
        ThrowNodeError("First argument must be a Buffer");
        return Undefined();
    }

    z_stream strmUncompress;

    strmUncompress.zalloc=Z_NULL;
    strmUncompress.zfree=Z_NULL;
    strmUncompress.opaque=Z_NULL;
    strmUncompress.avail_in = 0;
    strmUncompress.next_in = Z_NULL;

    int rci = inflateInit2(&strmUncompress, WBITS);

    if (rci != Z_OK) {
        ThrowNodeError("zlib initialization error.");
        return Undefined();
    }

    Local<Object> bufferIn=args[0]->ToObject();

    strmUncompress.next_in = (Bytef*) Buffer::Data(bufferIn);
    strmUncompress.avail_in = Buffer::Length(bufferIn);

    Bytef  *bufferOut = NULL;
    uint32_t malloc_size=0;
    uint32_t currentPosition=0;

    int ret;

    do {
        Bytef *tmp = (Bytef*)malloc(CHUNK);
        strmUncompress.avail_out = CHUNK;
        strmUncompress.next_out = tmp;

        ret = inflate(&strmUncompress, Z_NO_FLUSH);
        assert(ret != Z_STREAM_ERROR);
        switch (ret) {
            case Z_NEED_DICT:
                ret = Z_DATA_ERROR;     /* and fall through */
            case Z_DATA_ERROR:
            case Z_MEM_ERROR:
                (void)inflateEnd(&strmUncompress);
                if (bufferOut!=NULL) {
                    free(bufferOut);
                }
                if (tmp!=NULL) {
                    free(tmp);
                }
                return Undefined();
        }

        uint32_t have = CHUNK - strmUncompress.avail_out;
        if (have>0) {
            bufferOut = (Bytef *) realloc(bufferOut, malloc_size+have);
            malloc_size=malloc_size+have;
        }

        memcpy(bufferOut+currentPosition, tmp, have);
        currentPosition+=have;
        free(tmp);
    } while (strmUncompress.avail_out == 0 && ret != Z_STREAM_END);

    inflateEnd(&strmUncompress);

    if (ret != Z_STREAM_END) {
        if (bufferOut!=NULL) {
            free(bufferOut);
        }
        return Undefined();
    }

    Buffer *BufferOut=Buffer::New((char *)bufferOut, malloc_size);
    free(bufferOut);

    return scope.Close(BufferOut->handle_);
}

extern "C" void init (Handle<Object> target) {
    SYM_BODY = NODE_PSYMBOL("body");
    SYM_LEFT = NODE_PSYMBOL("left");
    SYM_RIGHT = NODE_PSYMBOL("right");
    SYM_LAST = NODE_PSYMBOL("last");
    SYM_TYPE = NODE_PSYMBOL("type");
    SYM_OFFSETS = NODE_PSYMBOL("offsets");
    SYM_LENGTH = NODE_PSYMBOL("length");
    SYM_RAW_LENGTH = NODE_PSYMBOL("rawLength");
    SYM_CRC = NODE_PSYMBOL("crc");
    SYM_META = NODE_PSYMBOL("meta");
    SYM_BUFFERS = NODE_PSYMBOL("buffers");
    SYM_HEADER = NODE_PSYMBOL("header");
    SYM_ODD = NODE_PSYMBOL("odd");

    char header[] = {0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
    Buffer *headerBuffer = Buffer::New(header, 10);

    char odd[] = {0x00, 0x00, 0xff, 0xff};
    Buffer *oddBuffer = Buffer::New(odd, 4);

    Handle<Object> buffers = Object::New();
    buffers->Set(SYM_HEADER, headerBuffer->handle_);
    buffers->Set(SYM_ODD, oddBuffer->handle_);

    target->Set(SYM_BUFFERS, buffers);

    NODE_SET_METHOD(target, "compress", compress);
    NODE_SET_METHOD(target, "uncompress", uncompress);
    NODE_SET_METHOD(target, "metaCompress", onet_compress);
    NODE_SET_METHOD(target, "getCrc", getCrc);
    NODE_SET_METHOD(target, "estimate", estimate);

}

NODE_MODULE(compress_buffer_bindings, init);

<commit_msg>faster version of meta_uncompress<commit_after>#include <node.h>
#include <node_buffer.h>
#include <string.h>
#include <v8.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#ifdef __APPLE__
#include <malloc/malloc.h>
#endif
#include <zlib.h>

// zlib magic something
#define WBITS 16+MAX_WBITS
#define WBITS_RAW -15

#define CHUNK 1024*100
#define HEADER_SIZE 10
#define FOOTER_SIZE 8
#define SPACER_SIZE 6

using namespace v8;
using namespace node;

static Persistent<String> SYM_BODY;
static Persistent<String> SYM_LEFT;
static Persistent<String> SYM_RIGHT;
static Persistent<String> SYM_LAST;
static Persistent<String> SYM_TYPE;
static Persistent<String> SYM_OFFSETS;
static Persistent<String> SYM_LENGTH;
static Persistent<String> SYM_RAW_LENGTH;
static Persistent<String> SYM_CRC;
static Persistent<String> SYM_META;
static Persistent<String> SYM_BUFFERS;
static Persistent<String> SYM_HEADER;
static Persistent<String> SYM_ODD;
unsigned char *tmpBody;

static Handle<Value> ThrowNodeError (const char* what = NULL) {
    return ThrowException(Exception::Error(String::New(what)));
}

static int meta_uncompress (char *dataIn, size_t bytesIn, int *dataType) {
    unsigned char *bodyDataIn = ((unsigned char *) dataIn) + HEADER_SIZE;

    //checking if stream is compressed, first byte - binary:
    //xxxxx001 - stream is NOT compressed
    //xxxxx011 - stream is compressed (using fixed huffman codes)
    //xxxxx111 - stream is compressed (using dynamic huffman codes)
    if ((*bodyDataIn & 3) == 3 || (*bodyDataIn & 5) == 5) {
        z_stream strmUncompress;

        strmUncompress.zalloc = Z_NULL;
        strmUncompress.zfree = Z_NULL;
        strmUncompress.opaque = Z_NULL;
        strmUncompress.avail_in = 0;
        strmUncompress.next_in = Z_NULL;

        if (inflateInit2(&strmUncompress, WBITS_RAW) != Z_OK) {
            return -1;
        }

        //skipping header
        strmUncompress.next_in = bodyDataIn;
        strmUncompress.avail_in = bytesIn - HEADER_SIZE;

        for (;;) {
            strmUncompress.avail_out = CHUNK;
            strmUncompress.next_out = tmpBody;

            int ret = inflate(&strmUncompress, Z_BLOCK);

            assert(ret != Z_STREAM_ERROR);

            switch (ret) {
                case Z_NEED_DICT:
                    ret = Z_DATA_ERROR;     /* and fall through */
                case Z_DATA_ERROR:
                case Z_MEM_ERROR:
                    inflateEnd(&strmUncompress);
                    return -2;
            }

            if (strmUncompress.data_type & 128) {
                break;
            }
        }
        *dataType = strmUncompress.data_type;

        inflateEnd(&strmUncompress);
    } else {
        *dataType = 128;
    }

    return 0;

}

static int compress (char *dataIn, size_t bytesIn, int compressionLevel, char **dataOut, size_t *bytesOut) {
    size_t bytesDeflated = 0;

    if (compressionLevel < 0 || compressionLevel > 9) {
        compressionLevel = Z_DEFAULT_COMPRESSION;
    }

    z_stream strmCompress;
    strmCompress.zalloc = Z_NULL;
    strmCompress.zfree = Z_NULL;
    strmCompress.opaque = Z_NULL;

    if (deflateInit2(&strmCompress, compressionLevel, Z_DEFLATED, WBITS, 8L, Z_DEFAULT_STRATEGY) != Z_OK) {
        return -1;
    }

    bytesDeflated = deflateBound(&strmCompress, bytesIn);

    if (bytesDeflated < 1024) {
        bytesDeflated = 1024;
    }

    *dataOut = (char *) malloc(bytesDeflated);

    strmCompress.next_in = (Bytef *) dataIn;
    strmCompress.avail_in = bytesIn;
    strmCompress.next_out = (Bytef *) *dataOut;
    strmCompress.avail_out = bytesDeflated;

    if (deflate(&strmCompress, Z_NO_FLUSH) < Z_OK) {
        deflateReset(&strmCompress);
        return -2;
    }

    deflate(&strmCompress, Z_FINISH);

    *bytesOut = strmCompress.total_out;

    deflateReset(&strmCompress);

    return 0;
}

static Handle<Value> onet_compress (const Arguments &args) {
    HandleScope scope;

    int compressionLevel = Z_DEFAULT_COMPRESSION;

    if (args.Length() < 1) {
        return Undefined();
    }

    if (!Buffer::HasInstance(args[0])) {
        ThrowNodeError("First argument must be a Buffer");
        return Undefined();
    }

    Local<Object> bufferIn = args[0]->ToObject();

    if (args.Length() > 1) {
        compressionLevel = args[1]->IntegerValue();
    }

    char *dataIn = Buffer::Data(bufferIn);
    size_t bytesIn = Buffer::Length(bufferIn);
    char *dataOut = 0;
    size_t bytesOut = 0;
    int dataType = 0;
    int status = compress(dataIn, bytesIn, compressionLevel, &dataOut, &bytesOut);

    if (status != 0) {
        char msg[30];
        sprintf(msg, "Unable to compress: %d", status);
        ThrowNodeError(msg);
        return Undefined();
    }

    status = meta_uncompress(dataOut, bytesOut, &dataType);

    if (status != 0) {
        char msg[30];
        sprintf(msg, "Unable to uncompress: %d", status);
        ThrowNodeError(msg);
        return Undefined();
    }

    unsigned int dataLength = bytesOut - HEADER_SIZE - FOOTER_SIZE - 1;

    Local<Object> result = Object::New();

    Buffer *body = Buffer::New((char *) dataOut, bytesOut);
    result->Set(SYM_BODY, body->handle_);

    Local<Object> dataOffsets = Object::New();
    dataOffsets->Set(SYM_LEFT, Integer::New(HEADER_SIZE));
    dataOffsets->Set(SYM_RIGHT, Integer::New(HEADER_SIZE + dataLength));
    dataOffsets->Set(SYM_LAST, Integer::New(HEADER_SIZE + dataLength));

    Buffer *crc = Buffer::New((char *) dataOut + (bytesOut - FOOTER_SIZE), 4);

    Local<Object> meta = Object::New();
    meta->Set(SYM_TYPE, Integer::New(dataType));
    meta->Set(SYM_OFFSETS, dataOffsets);
    meta->Set(SYM_LENGTH, Integer::New(bytesIn));
    meta->Set(SYM_RAW_LENGTH, Integer::New(bytesOut - HEADER_SIZE - FOOTER_SIZE));
    meta->Set(SYM_CRC, crc->handle_);

    result->Set(SYM_META, meta);

    free(dataOut);

    return scope.Close(result);
}

static Handle<Value> compress (const Arguments& args) {
    HandleScope scope;

    int compressionLevel = Z_DEFAULT_COMPRESSION;

    if (args.Length() < 1) {
        return Undefined();
    }

    if (!Buffer::HasInstance(args[0])) {
        ThrowNodeError("First argument must be a Buffer");
        return Undefined();
    }

    Local<Object> bufferIn = args[0]->ToObject();

    if (args.Length() > 1) {
        compressionLevel = args[1]->IntegerValue();
    }

    char *dataIn = Buffer::Data(bufferIn);
    size_t bytesIn = Buffer::Length(bufferIn);
    char *dataOut = 0;
    size_t bytesOut = 0;
    int status = compress(dataIn, bytesIn, compressionLevel, &dataOut, &bytesOut);

    if (status != 0) {
        ThrowNodeError("Unable to compress");
        return Undefined();
    }

    Buffer *buff = Buffer::New(dataOut, bytesOut);

    return scope.Close(buff->handle_);
}

static Handle<Value> estimate (const Arguments &args) {
    HandleScope scope;

    Local<Array> arr = Local<Array>::Cast(args[0]);
    int i = 0;
    int l = arr->Length();
    int sum = HEADER_SIZE + FOOTER_SIZE + ((l - 1) * SPACER_SIZE);

    for(; i < l; i++) {
        Local<Object> obj = arr->Get(i)->ToObject();
        Local<Object> meta = obj->Get(SYM_META)->ToObject();

        sum += meta->Get(SYM_RAW_LENGTH)->Uint32Value();
    }

    return scope.Close(Integer::New(sum));
}

static unsigned long reverseBytes (unsigned char *buf) {
    unsigned long v;

    v = *buf;
    v += (unsigned long) *(buf + 1) << 8;
    v += (unsigned long) *(buf + 2) << 16;
    v += (unsigned long) *(buf + 3) << 24;

    return v;
}

static Handle<Value> getCrc (const Arguments &args) {
    HandleScope scope;

    unsigned long crc = crc32(0L, Z_NULL, 0);
    unsigned long tot = 0;

    Local<Array> arr = Local<Array>::Cast(args[0]);

    int l = arr->Length();
    int i = 0;

    for (; i < l; i++) {
        Local<Object> obj = arr->Get(i)->ToObject();
        Local<Object> meta = obj->Get(SYM_META)->ToObject();

        Local<Object> bufCrc = meta->Get(SYM_CRC)->ToObject();

        unsigned long tmpCrc = reverseBytes((unsigned char *) Buffer::Data(bufCrc));
        unsigned long tmpLen = meta->Get(SYM_LENGTH)->Uint32Value();

        crc = crc32_combine(crc, tmpCrc, tmpLen);
        tot += tmpLen;
    }

    Local<Object> data = Object::New();
    data->Set(SYM_CRC, Buffer::New((char *) &crc, 4)->handle_);
    data->Set(SYM_LENGTH, Buffer::New((char *) &tot, 4)->handle_);

    return scope.Close(data);
}

static Handle<Value> uncompress (const Arguments &args) {
    HandleScope scope;

    if (args.Length() < 1) {
        return Undefined();
    }

    if (!Buffer::HasInstance(args[0])) {
        ThrowNodeError("First argument must be a Buffer");
        return Undefined();
    }

    z_stream strmUncompress;

    strmUncompress.zalloc=Z_NULL;
    strmUncompress.zfree=Z_NULL;
    strmUncompress.opaque=Z_NULL;
    strmUncompress.avail_in = 0;
    strmUncompress.next_in = Z_NULL;

    int rci = inflateInit2(&strmUncompress, WBITS);

    if (rci != Z_OK) {
        ThrowNodeError("zlib initialization error.");
        return Undefined();
    }

    Local<Object> bufferIn=args[0]->ToObject();

    strmUncompress.next_in = (Bytef*) Buffer::Data(bufferIn);
    strmUncompress.avail_in = Buffer::Length(bufferIn);

    Bytef  *bufferOut = NULL;
    uint32_t malloc_size=0;
    uint32_t currentPosition=0;

    int ret;

    do {
        Bytef *tmp = (Bytef*)malloc(CHUNK);
        strmUncompress.avail_out = CHUNK;
        strmUncompress.next_out = tmp;

        ret = inflate(&strmUncompress, Z_NO_FLUSH);
        assert(ret != Z_STREAM_ERROR);
        switch (ret) {
            case Z_NEED_DICT:
                ret = Z_DATA_ERROR;     /* and fall through */
            case Z_DATA_ERROR:
            case Z_MEM_ERROR:
                (void)inflateEnd(&strmUncompress);
                if (bufferOut!=NULL) {
                    free(bufferOut);
                }
                if (tmp!=NULL) {
                    free(tmp);
                }
                return Undefined();
        }

        uint32_t have = CHUNK - strmUncompress.avail_out;
        if (have>0) {
            bufferOut = (Bytef *) realloc(bufferOut, malloc_size+have);
            malloc_size=malloc_size+have;
        }

        memcpy(bufferOut+currentPosition, tmp, have);
        currentPosition+=have;
        free(tmp);
    } while (strmUncompress.avail_out == 0 && ret != Z_STREAM_END);

    inflateEnd(&strmUncompress);

    if (ret != Z_STREAM_END) {
        if (bufferOut!=NULL) {
            free(bufferOut);
        }
        return Undefined();
    }

    Buffer *BufferOut=Buffer::New((char *)bufferOut, malloc_size);
    free(bufferOut);

    return scope.Close(BufferOut->handle_);
}

extern "C" void init (Handle<Object> target) {
    SYM_BODY = NODE_PSYMBOL("body");
    SYM_LEFT = NODE_PSYMBOL("left");
    SYM_RIGHT = NODE_PSYMBOL("right");
    SYM_LAST = NODE_PSYMBOL("last");
    SYM_TYPE = NODE_PSYMBOL("type");
    SYM_OFFSETS = NODE_PSYMBOL("offsets");
    SYM_LENGTH = NODE_PSYMBOL("length");
    SYM_RAW_LENGTH = NODE_PSYMBOL("rawLength");
    SYM_CRC = NODE_PSYMBOL("crc");
    SYM_META = NODE_PSYMBOL("meta");
    SYM_BUFFERS = NODE_PSYMBOL("buffers");
    SYM_HEADER = NODE_PSYMBOL("header");
    SYM_ODD = NODE_PSYMBOL("odd");
    tmpBody = (unsigned char *) malloc(CHUNK);

    char header[] = {0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
    Buffer *headerBuffer = Buffer::New(header, 10);

    char odd[] = {0x00, 0x00, 0xff, 0xff};
    Buffer *oddBuffer = Buffer::New(odd, 4);

    Handle<Object> buffers = Object::New();
    buffers->Set(SYM_HEADER, headerBuffer->handle_);
    buffers->Set(SYM_ODD, oddBuffer->handle_);

    target->Set(SYM_BUFFERS, buffers);

    NODE_SET_METHOD(target, "compress", compress);
    NODE_SET_METHOD(target, "uncompress", uncompress);
    NODE_SET_METHOD(target, "metaCompress", onet_compress);
    NODE_SET_METHOD(target, "getCrc", getCrc);
    NODE_SET_METHOD(target, "estimate", estimate);

}

NODE_MODULE(compress_buffer_bindings, init);

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSCriptTools module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "jsdebuggeragent.h"

#include <QtCore/qcoreapplication.h>
#include <QtCore/qset.h>
#include <QtScript/qscriptengine.h>
#include <QtScript/QScriptContextInfo>
#include <QtCore/QDebug>
#include <QtCore/QUrl>

QT_BEGIN_NAMESPACE

/*!
  Constructs a new agent for the given \a engine. The agent will
  report debugging-related events (e.g. step completion) to the given
  \a backend.
*/
JSDebuggerAgent::JSDebuggerAgent(QScriptEngine *engine)
    : QDeclarativeDebugService("JSDebugger"), QScriptEngineAgent(engine)
{}

/*!
  Destroys this QScriptDebuggerAgent.
*/
JSDebuggerAgent::~JSDebuggerAgent()
{}

/*!
  \reimp
*/
void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
                                      const QString &fileName, int )
{
    Q_UNUSED(program);
    filenames.insert(id, QUrl(fileName).toLocalFile());
}

/*!
  \reimp
*/
void JSDebuggerAgent::scriptUnload(qint64 id)
{
    filenames.remove(id);
}

/*!
  \reimp
*/
void JSDebuggerAgent::contextPush()
{
}

/*!
  \reimp
*/
void JSDebuggerAgent::contextPop()
{
}

/*!
  \reimp
*/
void JSDebuggerAgent::functionEntry(qint64 scriptId)
{
    Q_UNUSED(scriptId);
    stepDepth++;
}

/*!
  \reimp
*/
void JSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(returnValue);
    stepDepth--;
}

/*!
  \reimp
*/
void JSDebuggerAgent::positionChange(qint64 scriptId,
                                   int lineNumber, int columnNumber)
{
    Q_UNUSED(columnNumber);

    if(state == Stopped)
        return; //no re-entrency

    // check breakpoints
    if (!breakpointList.isEmpty()) {
        QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
        if (it != filenames.constEnd()) {
            QPair<QString, qint32> key = qMakePair(*it, lineNumber);
            if (breakpointList.contains(key)) {
                stopped();
                return;
            }
        }
    }

    switch (state) {
    case NoState:
    case Stopped:
        // Do nothing
        break;

    case SteppingOutState:
        if (stepDepth >= 0)
            break;
        //fallthough
    case SteppingOverState:
        if (stepDepth > 0)
            break;
        //fallthough
    case SteppingIntoState:
        stopped();
        break;
    }

}

/*!
  \reimp
*/
void JSDebuggerAgent::exceptionThrow(qint64 scriptId,
                                   const QScriptValue &exception,
                                   bool hasHandler)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(exception);
    Q_UNUSED(hasHandler);
/* ... */
}

/*!
  \reimp
*/
void JSDebuggerAgent::exceptionCatch(qint64 scriptId,
                                          const QScriptValue &exception)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(exception);
}

void JSDebuggerAgent::messageReceived(const QByteArray& message)
{
    QDataStream ds(message);
    QByteArray command;
    ds >> command;
    if (command == "BREAKPOINTS") {
        ds >> breakpointList;
    } else if (command == "WATCH_EXPRESSIONS") {
        ds >> watchExpressions;
    } else if (command == "STEPOVER") {
        stepDepth = 0;
        state = SteppingOverState;
        continueExec();
    } else if (command == "STEPINTO" || command == "INTERRUPT") {
        stepDepth = 0;
        state = SteppingIntoState;
        continueExec();
    } else if (command == "STEPOUT") {
        stepDepth = 0;
        state = SteppingOutState;
        continueExec();
    } else if (command == "CONTINUE") {
        state = NoState;
        continueExec();
    } else if (command == "EXEC") {
        State oldState = state;
        state = Stopped;
        QByteArray id;
        QString expr;
        ds >> id >> expr;

        QVariant val = engine()->evaluate(expr).toVariant();
        // Clear any exceptions occurred during locals evaluation.
        engine()->clearExceptions();

        QByteArray reply;
        QDataStream rs(&reply, QIODevice::WriteOnly);
        rs << QByteArray("RESULT") << id << expr << val;
        sendMessage(reply);
        state = oldState;

    } else {
        qDebug() << Q_FUNC_INFO << "Unknown command" << command;
    }

    QDeclarativeDebugService::messageReceived(message);
}

void JSDebuggerAgent::stopped()
{
    state = Stopped;
    QList<QPair<QString, QPair<QString, qint32> > > backtrace;

    for (QScriptContext* ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
        QScriptContextInfo info(ctx);

        QString functionName = info.functionName();
        if (functionName.isEmpty()) {
            if (ctx->parentContext()) {
                switch (info.functionType()) {
                case QScriptContextInfo::ScriptFunction:
                    functionName = QLatin1String("<anonymous>");
                    break;
                case QScriptContextInfo::NativeFunction:
                    functionName = QLatin1String("<native>");
                    break;
                case QScriptContextInfo::QtFunction:
                case QScriptContextInfo::QtPropertyFunction:
                    functionName = QLatin1String("<native slot>");
                    break;
                }
            } else {
                functionName = QLatin1String("<global>");
            }
        }
        backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), info.lineNumber() ) ) );
    }
    QList<QPair<QString, QVariant> > watches;
    foreach (const QString &expr, watchExpressions) {
        watches << qMakePair(expr,  engine()->evaluate(expr).toVariant());
    }

    // Clear any exceptions occurred during locals evaluation.
    engine()->clearExceptions();

    QByteArray reply;
    QDataStream rs(&reply, QIODevice::WriteOnly);
    rs << QByteArray("STOPPED") << backtrace << watches;
    sendMessage(reply);

    loop.exec(QEventLoop::ExcludeUserInputEvents);
}

void JSDebuggerAgent::continueExec()
{
    loop.quit();
}

void JSDebuggerAgent::enabledChanged(bool on)
{
    engine()->setAgent(on ? this : 0);
    QDeclarativeDebugService::enabledChanged(on);
}

QT_END_NAMESPACE
<commit_msg>QML Debugger: Restore the ability to set breakpoint on all files.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSCriptTools module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "jsdebuggeragent.h"

#include <QtCore/qcoreapplication.h>
#include <QtCore/qset.h>
#include <QtScript/qscriptengine.h>
#include <QtScript/QScriptContextInfo>
#include <QtCore/QDebug>
#include <QtCore/QUrl>

QT_BEGIN_NAMESPACE

/*!
  Constructs a new agent for the given \a engine. The agent will
  report debugging-related events (e.g. step completion) to the given
  \a backend.
*/
JSDebuggerAgent::JSDebuggerAgent(QScriptEngine *engine)
    : QDeclarativeDebugService("JSDebugger"), QScriptEngineAgent(engine)
{}

/*!
  Destroys this QScriptDebuggerAgent.
*/
JSDebuggerAgent::~JSDebuggerAgent()
{}

/*!
  \reimp
*/
void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
                                      const QString &fileName, int )
{
    Q_UNUSED(program);
    filenames.insert(id, QUrl(fileName).toLocalFile());
}

/*!
  \reimp
*/
void JSDebuggerAgent::scriptUnload(qint64 id)
{
    filenames.remove(id);
}

/*!
  \reimp
*/
void JSDebuggerAgent::contextPush()
{
}

/*!
  \reimp
*/
void JSDebuggerAgent::contextPop()
{
}

/*!
  \reimp
*/
void JSDebuggerAgent::functionEntry(qint64 scriptId)
{
    Q_UNUSED(scriptId);
    stepDepth++;
}

/*!
  \reimp
*/
void JSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(returnValue);
    stepDepth--;
}

/*!
  \reimp
*/
void JSDebuggerAgent::positionChange(qint64 scriptId,
                                   int lineNumber, int columnNumber)
{
    Q_UNUSED(columnNumber);

    if(state == Stopped)
        return; //no re-entrency

    // check breakpoints
    if (!breakpointList.isEmpty()) {
        QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
        if (it == filenames.constEnd()) {
            // It is possible that the scripts are loaded before the agent is attached
            QString filename = QUrl(QScriptContextInfo(engine()->currentContext()).fileName()).toLocalFile();
            QPair<QString, qint32> key = qMakePair(filename, lineNumber);
            it = filenames.insert(scriptId, filename);
        }
        QPair<QString, qint32> key = qMakePair(*it, lineNumber);
        if (breakpointList.contains(key)) {
            stopped();
            return;
        }
    }

    switch (state) {
    case NoState:
    case Stopped:
        // Do nothing
        break;

    case SteppingOutState:
        if (stepDepth >= 0)
            break;
        //fallthough
    case SteppingOverState:
        if (stepDepth > 0)
            break;
        //fallthough
    case SteppingIntoState:
        stopped();
        break;
    }

}

/*!
  \reimp
*/
void JSDebuggerAgent::exceptionThrow(qint64 scriptId,
                                   const QScriptValue &exception,
                                   bool hasHandler)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(exception);
    Q_UNUSED(hasHandler);
/* ... */
}

/*!
  \reimp
*/
void JSDebuggerAgent::exceptionCatch(qint64 scriptId,
                                          const QScriptValue &exception)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(exception);
}

void JSDebuggerAgent::messageReceived(const QByteArray& message)
{
    QDataStream ds(message);
    QByteArray command;
    ds >> command;
    if (command == "BREAKPOINTS") {
        ds >> breakpointList;
    } else if (command == "WATCH_EXPRESSIONS") {
        ds >> watchExpressions;
    } else if (command == "STEPOVER") {
        stepDepth = 0;
        state = SteppingOverState;
        continueExec();
    } else if (command == "STEPINTO" || command == "INTERRUPT") {
        stepDepth = 0;
        state = SteppingIntoState;
        continueExec();
    } else if (command == "STEPOUT") {
        stepDepth = 0;
        state = SteppingOutState;
        continueExec();
    } else if (command == "CONTINUE") {
        state = NoState;
        continueExec();
    } else if (command == "EXEC") {
        State oldState = state;
        state = Stopped;
        QByteArray id;
        QString expr;
        ds >> id >> expr;

        QVariant val = engine()->evaluate(expr).toVariant();
        // Clear any exceptions occurred during locals evaluation.
        engine()->clearExceptions();

        QByteArray reply;
        QDataStream rs(&reply, QIODevice::WriteOnly);
        rs << QByteArray("RESULT") << id << expr << val;
        sendMessage(reply);
        state = oldState;

    } else {
        qDebug() << Q_FUNC_INFO << "Unknown command" << command;
    }

    QDeclarativeDebugService::messageReceived(message);
}

void JSDebuggerAgent::stopped()
{
    state = Stopped;
    QList<QPair<QString, QPair<QString, qint32> > > backtrace;

    for (QScriptContext* ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
        QScriptContextInfo info(ctx);

        QString functionName = info.functionName();
        if (functionName.isEmpty()) {
            if (ctx->parentContext()) {
                switch (info.functionType()) {
                case QScriptContextInfo::ScriptFunction:
                    functionName = QLatin1String("<anonymous>");
                    break;
                case QScriptContextInfo::NativeFunction:
                    functionName = QLatin1String("<native>");
                    break;
                case QScriptContextInfo::QtFunction:
                case QScriptContextInfo::QtPropertyFunction:
                    functionName = QLatin1String("<native slot>");
                    break;
                }
            } else {
                functionName = QLatin1String("<global>");
            }
        }
        backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), info.lineNumber() ) ) );
    }
    QList<QPair<QString, QVariant> > watches;
    foreach (const QString &expr, watchExpressions) {
        watches << qMakePair(expr,  engine()->evaluate(expr).toVariant());
    }

    // Clear any exceptions occurred during locals evaluation.
    engine()->clearExceptions();

    QByteArray reply;
    QDataStream rs(&reply, QIODevice::WriteOnly);
    rs << QByteArray("STOPPED") << backtrace << watches;
    sendMessage(reply);

    loop.exec(QEventLoop::ExcludeUserInputEvents);
}

void JSDebuggerAgent::continueExec()
{
    loop.quit();
}

void JSDebuggerAgent::enabledChanged(bool on)
{
    engine()->setAgent(on ? this : 0);
    QDeclarativeDebugService::enabledChanged(on);
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>//====================================================================
//
// Base class for classes that calculate the multiplicity in the
// forward regions event-by-event
//
// Inputs:
//   - AliESDEvent
//
// Outputs:
//   - AliAODForwardMult
//
// Histograms
//
// Corrections used
#include "AliForwardMultiplicityBase.h"
#include "AliForwardCorrectionManager.h"
#include "AliForwardUtil.h"
#include "AliLog.h"
#include "AliAODHandler.h"
#include "AliInputEventHandler.h"
#include "AliAnalysisManager.h"
#include "AliFMDEventInspector.h"
#include "AliFMDEnergyFitter.h"
#include "AliFMDSharingFilter.h"
#include "AliFMDDensityCalculator.h"
#include "AliFMDCorrector.h"
#include "AliFMDHistCollector.h"
#include "AliESDEvent.h"
#include <TROOT.h>
#include <TAxis.h>
#include <iostream>
#include <iomanip>

//====================================================================
AliForwardMultiplicityBase::AliForwardMultiplicityBase(const char* name)
  : AliAnalysisTaskSE(name),
    fEnableLowFlux(false),
    fFirstEvent(true),
    fCorrManager(0)
{
  // Set our persistent pointer
  fCorrManager = &AliForwardCorrectionManager::Instance();
}

//____________________________________________________________________
AliForwardMultiplicityBase&
AliForwardMultiplicityBase::operator=(const AliForwardMultiplicityBase& o)
{
  fEnableLowFlux = o.fEnableLowFlux;
  fFirstEvent    = o.fFirstEvent;
  fCorrManager   = o.fCorrManager;
  return *this;
}

//____________________________________________________________________
Bool_t
AliForwardMultiplicityBase::CheckCorrections(UInt_t what) const
{
  //
  // Check if all needed corrections are there and accounted for.  If not,
  // do a Fatal exit
  //
  // Parameters:
  //    what Which corrections is needed
  //
  // Return:
  //    true if all present, false otherwise
  //

  AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
  // Check that we have the energy loss fits, needed by
  //   AliFMDSharingFilter
  //   AliFMDDensityCalculator
  if (what & AliForwardCorrectionManager::kELossFits && !fcm.GetELossFit()) {
    AliFatal(Form("No energy loss fits"));
    return false;
  }
  // Check that we have the double hit correction - (optionally) used by
  //  AliFMDDensityCalculator
  if (what & AliForwardCorrectionManager::kDoubleHit && !fcm.GetDoubleHit()) {
    AliFatal("No double hit corrections");
    return false;
  }
  // Check that we have the secondary maps, needed by
  //   AliFMDCorrector
  //   AliFMDHistCollector
  if (what & AliForwardCorrectionManager::kSecondaryMap &&
      !fcm.GetSecondaryMap()) {
    AliFatal("No secondary corrections");
    return false;
  }
  // Check that we have the vertex bias correction, needed by
  //   AliFMDCorrector
  if (what & AliForwardCorrectionManager::kVertexBias &&
      !fcm.GetVertexBias()) {
    AliFatal("No event vertex bias corrections");
    return false;
  }
  // Check that we have the merging efficiencies, optionally used by
  //   AliFMDCorrector
  if (what & AliForwardCorrectionManager::kMergingEfficiency &&
      !fcm.GetMergingEfficiency()) {
    AliFatal("No merging efficiencies");
    return false;
  }
  // Check that we have the acceptance correction, needed by
  //   AliFMDCorrector
  if (what & AliForwardCorrectionManager::kAcceptance &&
      !fcm.GetAcceptance()) {
    AliFatal("No acceptance corrections");
    return false;
  }
  return true;
}
//____________________________________________________________________
Bool_t
AliForwardMultiplicityBase::ReadCorrections(const TAxis*& pe,
					    const TAxis*& pv,
					    Bool_t        mc)
{
  //
  // Read corrections
  //
  //
  UInt_t what = AliForwardCorrectionManager::kAll;
  if (!fEnableLowFlux)
    what ^= AliForwardCorrectionManager::kDoubleHit;
  if (!GetCorrections().IsUseVertexBias())
    what ^= AliForwardCorrectionManager::kVertexBias;
  if (!GetCorrections().IsUseAcceptance())
    what ^= AliForwardCorrectionManager::kAcceptance;
  if (!GetCorrections().IsUseMergingEfficiency())
    what ^= AliForwardCorrectionManager::kMergingEfficiency;

  AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
  if (!fcm.Init(GetEventInspector().GetCollisionSystem(),
		GetEventInspector().GetEnergy(),
		GetEventInspector().GetField(),
		mc,
		what)) return false;
  if (!CheckCorrections(what)) return false;

  // Sett our persistency pointer
  // fCorrManager = &fcm;

  // Get the eta axis from the secondary maps - if read in
  if (!pe) {
    pe = fcm.GetEtaAxis();
    if (!pe) AliFatal("No eta axis defined");
  }
  // Get the vertex axis from the secondary maps - if read in
  if (!pv) {
    pv = fcm.GetVertexAxis();
    if (!pv) AliFatal("No vertex axis defined");
  }

  return true;
}
//____________________________________________________________________
AliESDEvent*
AliForwardMultiplicityBase::GetESDEvent()
{
  //
  // Get the ESD event. IF this is the first event, initialise
  //
  AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
  if (!esd) {
    AliWarning("No ESD event found for input event");
    return 0;
  }

  // On the first event, initialize the parameters
  if (fFirstEvent && esd->GetESDRun()) {
    GetEventInspector().ReadRunDetails(esd);

    AliInfo(Form("Initializing with parameters from the ESD:\n"
                 "         AliESDEvent::GetBeamEnergy()   ->%f\n"
                 "         AliESDEvent::GetBeamType()     ->%s\n"
                 "         AliESDEvent::GetCurrentL3()    ->%f\n"
                 "         AliESDEvent::GetMagneticField()->%f\n"
                 "         AliESDEvent::GetRunNumber()    ->%d\n",
                 esd->GetBeamEnergy(),
                 esd->GetBeamType(),
                 esd->GetCurrentL3(),
                 esd->GetMagneticField(),
                 esd->GetRunNumber()));

    fFirstEvent = false;

    InitializeSubs();
  }
  return esd;
}
//____________________________________________________________________
void
AliForwardMultiplicityBase::MarkEventForStore() const
{
  // Make sure the AOD tree is filled
  AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
  AliAODHandler*      ah =
    dynamic_cast<AliAODHandler*>(am->GetOutputEventHandler());
  if (!ah)
    AliFatal("No AOD output handler set in analysis manager");

  ah->SetFillAOD(kTRUE);
}

//____________________________________________________________________
void
AliForwardMultiplicityBase::Print(Option_t* option) const
{
  //
  // Print information
  //
  // Parameters:
  //    option Not used
  //

  std::cout << "AliForwardMultiplicityBase: " << GetName() << "\n"
	    << "  Enable low flux code:   " << (fEnableLowFlux ? "yes" : "no")
	    << "\n"
	    << "  Off-line trigger mask:  0x"
	    << std::hex     << std::setfill('0')
	    << std::setw (8) << fOfflineTriggerMask
	    << std::dec     << std::setfill (' ') << std::endl;
  gROOT->IncreaseDirLevel();
  if (fCorrManager) fCorrManager->Print();
  else
    std::cout << "  Correction manager not set yet" << std::endl;
  GetEventInspector()   .Print(option);
  GetEnergyFitter()     .Print(option);
  GetSharingFilter()    .Print(option);
  GetDensityCalculator().Print(option);
  GetCorrections()      .Print(option);
  GetHistCollector()    .Print(option);
  gROOT->DecreaseDirLevel();
}

//
// EOF
//
<commit_msg>Declare needed branches<commit_after>//====================================================================
//
// Base class for classes that calculate the multiplicity in the
// forward regions event-by-event
//
// Inputs:
//   - AliESDEvent
//
// Outputs:
//   - AliAODForwardMult
//
// Histograms
//
// Corrections used
#include "AliForwardMultiplicityBase.h"
#include "AliForwardCorrectionManager.h"
#include "AliForwardUtil.h"
#include "AliLog.h"
#include "AliAODHandler.h"
#include "AliInputEventHandler.h"
#include "AliAnalysisManager.h"
#include "AliFMDEventInspector.h"
#include "AliFMDEnergyFitter.h"
#include "AliFMDSharingFilter.h"
#include "AliFMDDensityCalculator.h"
#include "AliFMDCorrector.h"
#include "AliFMDHistCollector.h"
#include "AliESDEvent.h"
#include <TROOT.h>
#include <TAxis.h>
#include <iostream>
#include <iomanip>

//====================================================================
AliForwardMultiplicityBase::AliForwardMultiplicityBase(const char* name)
  : AliAnalysisTaskSE(name),
    fEnableLowFlux(false),
    fFirstEvent(true),
    fCorrManager(0)
{
  // Set our persistent pointer
  fCorrManager = &AliForwardCorrectionManager::Instance();
  fBranchNames =
    "ESD:AliESDRun.,AliESDHeader.,AliMultiplicity.,"
    "AliESDFMD.,SPDVertex.,PrimaryVertex.";
}

//____________________________________________________________________
AliForwardMultiplicityBase&
AliForwardMultiplicityBase::operator=(const AliForwardMultiplicityBase& o)
{
  fEnableLowFlux = o.fEnableLowFlux;
  fFirstEvent    = o.fFirstEvent;
  fCorrManager   = o.fCorrManager;
  return *this;
}

//____________________________________________________________________
Bool_t
AliForwardMultiplicityBase::CheckCorrections(UInt_t what) const
{
  //
  // Check if all needed corrections are there and accounted for.  If not,
  // do a Fatal exit
  //
  // Parameters:
  //    what Which corrections is needed
  //
  // Return:
  //    true if all present, false otherwise
  //

  AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
  // Check that we have the energy loss fits, needed by
  //   AliFMDSharingFilter
  //   AliFMDDensityCalculator
  if (what & AliForwardCorrectionManager::kELossFits && !fcm.GetELossFit()) {
    AliFatal(Form("No energy loss fits"));
    return false;
  }
  // Check that we have the double hit correction - (optionally) used by
  //  AliFMDDensityCalculator
  if (what & AliForwardCorrectionManager::kDoubleHit && !fcm.GetDoubleHit()) {
    AliFatal("No double hit corrections");
    return false;
  }
  // Check that we have the secondary maps, needed by
  //   AliFMDCorrector
  //   AliFMDHistCollector
  if (what & AliForwardCorrectionManager::kSecondaryMap &&
      !fcm.GetSecondaryMap()) {
    AliFatal("No secondary corrections");
    return false;
  }
  // Check that we have the vertex bias correction, needed by
  //   AliFMDCorrector
  if (what & AliForwardCorrectionManager::kVertexBias &&
      !fcm.GetVertexBias()) {
    AliFatal("No event vertex bias corrections");
    return false;
  }
  // Check that we have the merging efficiencies, optionally used by
  //   AliFMDCorrector
  if (what & AliForwardCorrectionManager::kMergingEfficiency &&
      !fcm.GetMergingEfficiency()) {
    AliFatal("No merging efficiencies");
    return false;
  }
  // Check that we have the acceptance correction, needed by
  //   AliFMDCorrector
  if (what & AliForwardCorrectionManager::kAcceptance &&
      !fcm.GetAcceptance()) {
    AliFatal("No acceptance corrections");
    return false;
  }
  return true;
}
//____________________________________________________________________
Bool_t
AliForwardMultiplicityBase::ReadCorrections(const TAxis*& pe,
					    const TAxis*& pv,
					    Bool_t        mc)
{
  //
  // Read corrections
  //
  //
  UInt_t what = AliForwardCorrectionManager::kAll;
  if (!fEnableLowFlux)
    what ^= AliForwardCorrectionManager::kDoubleHit;
  if (!GetCorrections().IsUseVertexBias())
    what ^= AliForwardCorrectionManager::kVertexBias;
  if (!GetCorrections().IsUseAcceptance())
    what ^= AliForwardCorrectionManager::kAcceptance;
  if (!GetCorrections().IsUseMergingEfficiency())
    what ^= AliForwardCorrectionManager::kMergingEfficiency;

  AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
  if (!fcm.Init(GetEventInspector().GetCollisionSystem(),
		GetEventInspector().GetEnergy(),
		GetEventInspector().GetField(),
		mc,
		what)) return false;
  if (!CheckCorrections(what)) return false;

  // Sett our persistency pointer
  // fCorrManager = &fcm;

  // Get the eta axis from the secondary maps - if read in
  if (!pe) {
    pe = fcm.GetEtaAxis();
    if (!pe) AliFatal("No eta axis defined");
  }
  // Get the vertex axis from the secondary maps - if read in
  if (!pv) {
    pv = fcm.GetVertexAxis();
    if (!pv) AliFatal("No vertex axis defined");
  }

  return true;
}
//____________________________________________________________________
AliESDEvent*
AliForwardMultiplicityBase::GetESDEvent()
{
  //
  // Get the ESD event. IF this is the first event, initialise
  //
  AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
  if (!esd) {
    AliWarning("No ESD event found for input event");
    return 0;
  }

  // On the first event, initialize the parameters
  if (fFirstEvent && esd->GetESDRun()) {
    GetEventInspector().ReadRunDetails(esd);

    AliInfo(Form("Initializing with parameters from the ESD:\n"
                 "         AliESDEvent::GetBeamEnergy()   ->%f\n"
                 "         AliESDEvent::GetBeamType()     ->%s\n"
                 "         AliESDEvent::GetCurrentL3()    ->%f\n"
                 "         AliESDEvent::GetMagneticField()->%f\n"
                 "         AliESDEvent::GetRunNumber()    ->%d\n",
                 esd->GetBeamEnergy(),
                 esd->GetBeamType(),
                 esd->GetCurrentL3(),
                 esd->GetMagneticField(),
                 esd->GetRunNumber()));

    fFirstEvent = false;

    InitializeSubs();
  }
  return esd;
}
//____________________________________________________________________
void
AliForwardMultiplicityBase::MarkEventForStore() const
{
  // Make sure the AOD tree is filled
  AliAnalysisManager* am = AliAnalysisManager::GetAnalysisManager();
  AliAODHandler*      ah =
    dynamic_cast<AliAODHandler*>(am->GetOutputEventHandler());
  if (!ah)
    AliFatal("No AOD output handler set in analysis manager");

  ah->SetFillAOD(kTRUE);
}

//____________________________________________________________________
void
AliForwardMultiplicityBase::Print(Option_t* option) const
{
  //
  // Print information
  //
  // Parameters:
  //    option Not used
  //

  std::cout << "AliForwardMultiplicityBase: " << GetName() << "\n"
	    << "  Enable low flux code:   " << (fEnableLowFlux ? "yes" : "no")
	    << "\n"
	    << "  Off-line trigger mask:  0x"
	    << std::hex     << std::setfill('0')
	    << std::setw (8) << fOfflineTriggerMask
	    << std::dec     << std::setfill (' ') << std::endl;
  gROOT->IncreaseDirLevel();
  if (fCorrManager) fCorrManager->Print();
  else
    std::cout << "  Correction manager not set yet" << std::endl;
  GetEventInspector()   .Print(option);
  GetEnergyFitter()     .Print(option);
  GetSharingFilter()    .Print(option);
  GetDensityCalculator().Print(option);
  GetCorrections()      .Print(option);
  GetHistCollector()    .Print(option);
  gROOT->DecreaseDirLevel();
}

//
// EOF
//
<|endoftext|>