<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
///
/// This is a class for reading raw data from a date file or event.
///
/// The AliRawReaderDate is constructed either with a pointer to a
/// date event or with a file name and an event number.
///
///////////////////////////////////////////////////////////////////////////////

#include "AliRawReaderDate.h"
#ifdef ALI_DATE
#include "event.h"
#endif

ClassImp(AliRawReaderDate)

AliRawReaderDate::AliRawReaderDate(
#ifdef ALI_DATE
				   void* event
#else
				   void* /* event */
#endif
				   ) :
  fRequireHeader(kTRUE),
  fEvent(NULL),
  fSubEvent(NULL),
  fEquipment(NULL),
  fIsOwner(kFALSE),
  fPosition(NULL),
  fEnd(NULL)
{
// create an object to read digits from the given date event

#ifdef ALI_DATE
  fEvent = (eventHeaderStruct*) event;
#else
  Fatal("AliRawReaderDate", "this class was compiled without DATE");
#endif
}

AliRawReaderDate::AliRawReaderDate(
#ifdef ALI_DATE
				   const char* fileName, Int_t eventNumber
#else
				   const char* /*fileName*/,
				   Int_t /*eventNumber*/
#endif
				   ) :
  fRequireHeader(kTRUE),
  fEvent(NULL),
  fSubEvent(NULL),
  fEquipment(NULL),
  fIsOwner(kFALSE),
  fPosition(NULL),
  fEnd(NULL)
{
// create an object to read digits from the given date event

#ifdef ALI_DATE
  FILE* file = fopen(fileName, "rb");
  if (!file) {
    Error("AliRawReaderDate", "could not open file %s", fileName);
    return;
  }
  eventHeaderStruct header;
  UInt_t headerSize = sizeof(eventHeaderStruct);
  while (fread(&header, 1, headerSize, file) == headerSize) {
    if (eventNumber == 0) {
      UChar_t* buffer = new UChar_t[header.eventSize];
      fseek(file, -headerSize, SEEK_CUR);
      if (fread(buffer, 1, header.eventSize, file) != header.eventSize) break;
      fEvent = (eventHeaderStruct*) buffer;
      fIsOwner = kTRUE;
      break;
    }
    fseek(file, header.eventSize-headerSize, SEEK_CUR);
    eventNumber--;
  }
  fclose(file);

#else
  Fatal("AliRawReaderDate", "this class was compiled without DATE");
#endif
}

AliRawReaderDate::AliRawReaderDate(const AliRawReaderDate& rawReader) :
  AliRawReader(rawReader),
  fRequireHeader(rawReader.fRequireHeader),
  fEvent(rawReader.fEvent),
  fSubEvent(rawReader.fSubEvent),
  fEquipment(rawReader.fEquipment),
  fIsOwner(kFALSE),
  fPosition(rawReader.fPosition),
  fEnd(rawReader.fEnd)

{
// copy constructor

}

AliRawReaderDate& AliRawReaderDate::operator = (const AliRawReaderDate&
						rawReader)
{
// assignment operator

  this->~AliRawReaderDate();
  new(this) AliRawReaderDate(rawReader);
  return *this;
}

AliRawReaderDate::~AliRawReaderDate()
{
// destructor

#ifdef ALI_DATE
  if (fIsOwner) delete[] fEvent;
#endif
}

UInt_t AliRawReaderDate::GetType() const
{
// get the type from the event header

#ifdef ALI_DATE
  if (!fEvent) return 0;
  return fEvent->eventType;
#else
  return 0;
#endif
}

UInt_t AliRawReaderDate::GetRunNumber() const
{
// get the run number from the event header

#ifdef ALI_DATE
  if (!fEvent) return 0;
  return fEvent->eventRunNb;
#else
  return 0;
#endif
}

const UInt_t* AliRawReaderDate::GetEventId() const
{
// get the event id from the event header

#ifdef ALI_DATE
  if (!fEvent) return NULL;
  return fEvent->eventId;
#else
  return NULL;
#endif
}

const UInt_t* AliRawReaderDate::GetTriggerPattern() const
{
// get the trigger pattern from the event header

#ifdef ALI_DATE
  if (!fEvent) return NULL;
  return fEvent->eventTriggerPattern;
#else
  return NULL;
#endif
}

const UInt_t* AliRawReaderDate::GetDetectorPattern() const
{
// get the detector pattern from the event header

#ifdef ALI_DATE
  if (!fEvent) return NULL;
  return fEvent->eventDetectorPattern;
#else
  return NULL;
#endif
}

const UInt_t* AliRawReaderDate::GetAttributes() const
{
// get the type attributes from the event header

#ifdef ALI_DATE
  if (!fEvent) return NULL;
  return fEvent->eventTypeAttribute;
#else
  return NULL;
#endif
}

UInt_t AliRawReaderDate::GetLDCId() const
{
// get the LDC Id from the event header

#ifdef ALI_DATE
  if (!fSubEvent) return 0;
  return fSubEvent->eventLdcId;
#else
  return 0;
#endif
}

UInt_t AliRawReaderDate::GetGDCId() const
{
// get the GDC Id from the event header

#ifdef ALI_DATE
  if (!fEvent) return 0;
  return fEvent->eventGdcId;
#else
  return 0;
#endif
}

Int_t AliRawReaderDate::GetEquipmentSize() const
{
// get the size of the equipment

#ifdef ALI_DATE
  if (!fEquipment) return 0;
  return fEquipment->equipmentSize;
#else
  return 0;
#endif
}

Int_t AliRawReaderDate::GetEquipmentType() const
{
// get the type from the equipment header

#ifdef ALI_DATE
  if (!fEquipment) return -1;
  return fEquipment->equipmentType;
#else
  return 0;
#endif
}

Int_t AliRawReaderDate::GetEquipmentId() const
{
// get the ID from the equipment header

#ifdef ALI_DATE
  if (!fEquipment) return -1;
  return fEquipment->equipmentId;
#else
  return 0;
#endif
}

const UInt_t* AliRawReaderDate::GetEquipmentAttributes() const
{
// get the attributes from the equipment header

#ifdef ALI_DATE
  if (!fEquipment) return NULL;
  return fEquipment->equipmentTypeAttribute;
#else
  return 0;
#endif
}

Int_t AliRawReaderDate::GetEquipmentElementSize() const
{
// get the basic element size from the equipment header

#ifdef ALI_DATE
  if (!fEquipment) return 0;
  return fEquipment->equipmentBasicElementSize;
#else
  return 0;
#endif
}

Bool_t AliRawReaderDate::ReadHeader()
{
// read a data header at the current position
// returns kFALSE if the data header could not be read

  fErrorCode = 0;

#ifdef ALI_DATE
  if (!fEvent) return kFALSE;
  // check whether there are sub events
  if (fEvent->eventSize <= fEvent->eventHeadSize) return kFALSE;

  do {
    // skip payload (if event was not selected)
    if (fCount > 0) fPosition += fCount;

    // get the first or the next equipment if at the end of an equipment
    if (!fEquipment || (fPosition >= fEnd)) {

      // get the first or the next sub event if at the end of a sub event
      if (!fSubEvent ||
	  (fPosition >= ((UChar_t*)fSubEvent) + fSubEvent->eventSize)) {

	// check for end of event data
	if (fPosition >= ((UChar_t*)fEvent)+fEvent->eventSize) return kFALSE;
	if (fSubEvent) {
	  fSubEvent = (eventHeaderStruct*) (((UChar_t*)fSubEvent) +
					    fSubEvent->eventSize);
	} else {
	  fSubEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) +
					    fEvent->eventHeadSize);
	}

	// check the magic word of the sub event
	if (fSubEvent->eventMagic != EVENT_MAGIC_NUMBER) {
	  Error("ReadHeader", "wrong magic number in sub event!\n"
		" run: %d  event: %d %d  LDC: %d  GDC: %d\n",
		fSubEvent->eventRunNb,
		fSubEvent->eventId[0], fSubEvent->eventId[1],
		fSubEvent->eventLdcId, fSubEvent->eventGdcId);
	  fErrorCode = kErrMagic;
	  return kFALSE;
	}

	fEquipment = (equipmentHeaderStruct*)
	  (((UChar_t*)fSubEvent) + fSubEvent->eventHeadSize);

      } else {
	fEquipment = (equipmentHeaderStruct*) fEnd;
      }

      fCount = 0;
      fPosition = ((UChar_t*)fEquipment) + sizeof(equipmentHeaderStruct);
      fEnd = fPosition + fEquipment->equipmentSize;
    }

    // continue with the next sub event if no data left in the payload
    if (fPosition >= fEnd) continue;

    fHeader = NULL;
    if (fRequireHeader) {
      // check that there are enough bytes left for the data header
      if (fPosition + sizeof(AliRawDataHeader) > fEnd) {
	Error("ReadHeader", "could not read data header data!");
	Warning("ReadHeader", "skipping %d bytes\n"
		" run: %d  event: %d %d  LDC: %d  GDC: %d\n",
		fEnd - fPosition, fSubEvent->eventRunNb,
		fSubEvent->eventId[0], fSubEvent->eventId[1],
		fSubEvent->eventLdcId, fSubEvent->eventGdcId);
	fCount = 0;
	fPosition = fEnd;
	fErrorCode = kErrNoDataHeader;
	continue;
      }

      // "read" the data header
      fHeader = (AliRawDataHeader*) fPosition;
      fPosition += sizeof(AliRawDataHeader);
    }

    if (fHeader && (fHeader->fSize != 0xFFFFFFFF)) {
      fCount = fHeader->fSize - sizeof(AliRawDataHeader);

      // check consistency of data size in the header and in the sub event
      if (fPosition + fCount > fEnd) {
	Error("ReadHeader", "size in data header exceeds event size!");
	Warning("ReadHeader", "skipping %d bytes\n"
		" run: %d  event: %d %d  LDC: %d  GDC: %d\n",
		fEnd - fPosition, fSubEvent->eventRunNb,
		fSubEvent->eventId[0], fSubEvent->eventId[1],
		fSubEvent->eventLdcId, fSubEvent->eventGdcId);
	fCount = 0;
	fPosition = fEnd;
	fErrorCode = kErrSize;
	continue;
      }

    } else {
      fCount = fEnd - fPosition;
    }

  } while (!IsSelected());

  return kTRUE;
#else
  return kFALSE;
#endif
}

Bool_t AliRawReaderDate::ReadNextData(UChar_t*& data)
{
// reads the next payload at the current position
// returns kFALSE if the data could not be read

  fErrorCode = 0;
  while (fCount == 0) {
    if (!ReadHeader()) return kFALSE;
  }
  data = fPosition;
  fPosition += fCount;
  fCount = 0;
  return kTRUE;
}

Bool_t AliRawReaderDate::ReadNext(UChar_t* data, Int_t size)
{
// reads the next block of data at the current position
// returns kFALSE if the data could not be read

  fErrorCode = 0;
  if (fPosition + size > fEnd) {
    Error("ReadNext", "could not read data!");
    fErrorCode = kErrOutOfBounds;
    return kFALSE;
  }
  memcpy(data, fPosition, size);
  fPosition += size;
  fCount -= size;
  return kTRUE;
}

Bool_t AliRawReaderDate::Reset()
{
// reset the current position to the beginning of the event

#ifdef ALI_DATE
  fSubEvent = NULL;
#endif
  fCount = 0;
  fPosition = fEnd = NULL;
  return kTRUE;
}

Int_t AliRawReaderDate::CheckData() const
{
// check the consistency of the data

#ifdef ALI_DATE
  if (!fEvent) return 0;
  // check whether there are sub events
  if (fEvent->eventSize <= fEvent->eventHeadSize) return 0;

  eventHeaderStruct* subEvent = NULL;
  UChar_t* position = 0;
  UChar_t* end = 0;
  Int_t result = 0;

  while (kTRUE) {
    // get the first or the next sub event if at the end of a sub event
    if (!subEvent || (position >= end)) {

      // check for end of event data
      if (position >= ((UChar_t*)fEvent)+fEvent->eventSize) return result;
      if (subEvent) {
	subEvent = (eventHeaderStruct*) (((UChar_t*)subEvent) +
					 subEvent->eventSize);
      } else {
	subEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) +
					 fEvent->eventHeadSize);
      }

      // check the magic word of the sub event
      if (subEvent->eventMagic != EVENT_MAGIC_NUMBER) {
	result |= kErrMagic;
	return result;
      }

      position = ((UChar_t*)subEvent) + subEvent->eventHeadSize +
	sizeof(equipmentHeaderStruct);
      end = ((UChar_t*)subEvent) + subEvent->eventSize;
    }

    // continue with the next sub event if no data left in the payload
    if (position >= end) continue;

    // check that there are enough bytes left for the data header
    if (position + sizeof(AliRawDataHeader) > end) {
      result |= kErrNoDataHeader;
      position = end;
      continue;
    }

    // check consistency of data size in the data header and in the sub event
    AliRawDataHeader* header = (AliRawDataHeader*) position;
    if (fHeader->fSize != 0xFFFFFFFF) {
      if (position + header->fSize > end) {
	result |= kErrSize;
	position = end;
      } else {
	position += header->fSize;
      }
    } else {
      position = end;
    }
  };

#endif
  return 0;
}
<commit_msg>bugfix<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
///
/// This is a class for reading raw data from a date file or event.
///
/// The AliRawReaderDate is constructed either with a pointer to a
/// date event or with a file name and an event number.
///
///////////////////////////////////////////////////////////////////////////////

#include "AliRawReaderDate.h"
#ifdef ALI_DATE
#include "event.h"
#endif

ClassImp(AliRawReaderDate)

AliRawReaderDate::AliRawReaderDate(
#ifdef ALI_DATE
				   void* event
#else
				   void* /* event */
#endif
				   ) :
  fRequireHeader(kTRUE),
  fEvent(NULL),
  fSubEvent(NULL),
  fEquipment(NULL),
  fIsOwner(kFALSE),
  fPosition(NULL),
  fEnd(NULL)
{
// create an object to read digits from the given date event

#ifdef ALI_DATE
  fEvent = (eventHeaderStruct*) event;
#else
  Fatal("AliRawReaderDate", "this class was compiled without DATE");
#endif
}

AliRawReaderDate::AliRawReaderDate(
#ifdef ALI_DATE
				   const char* fileName, Int_t eventNumber
#else
				   const char* /*fileName*/,
				   Int_t /*eventNumber*/
#endif
				   ) :
  fRequireHeader(kTRUE),
  fEvent(NULL),
  fSubEvent(NULL),
  fEquipment(NULL),
  fIsOwner(kFALSE),
  fPosition(NULL),
  fEnd(NULL)
{
// create an object to read digits from the given date event

#ifdef ALI_DATE
  FILE* file = fopen(fileName, "rb");
  if (!file) {
    Error("AliRawReaderDate", "could not open file %s", fileName);
    return;
  }
  eventHeaderStruct header;
  UInt_t headerSize = sizeof(eventHeaderStruct);
  while (fread(&header, 1, headerSize, file) == headerSize) {
    if (eventNumber == 0) {
      UChar_t* buffer = new UChar_t[header.eventSize];
      fseek(file, -headerSize, SEEK_CUR);
      if (fread(buffer, 1, header.eventSize, file) != header.eventSize) break;
      fEvent = (eventHeaderStruct*) buffer;
      fIsOwner = kTRUE;
      break;
    }
    fseek(file, header.eventSize-headerSize, SEEK_CUR);
    eventNumber--;
  }
  fclose(file);

#else
  Fatal("AliRawReaderDate", "this class was compiled without DATE");
#endif
}

AliRawReaderDate::AliRawReaderDate(const AliRawReaderDate& rawReader) :
  AliRawReader(rawReader),
  fRequireHeader(rawReader.fRequireHeader),
  fEvent(rawReader.fEvent),
  fSubEvent(rawReader.fSubEvent),
  fEquipment(rawReader.fEquipment),
  fIsOwner(kFALSE),
  fPosition(rawReader.fPosition),
  fEnd(rawReader.fEnd)

{
// copy constructor

}

AliRawReaderDate& AliRawReaderDate::operator = (const AliRawReaderDate&
						rawReader)
{
// assignment operator

  this->~AliRawReaderDate();
  new(this) AliRawReaderDate(rawReader);
  return *this;
}

AliRawReaderDate::~AliRawReaderDate()
{
// destructor

#ifdef ALI_DATE
  if (fIsOwner) delete[] fEvent;
#endif
}

UInt_t AliRawReaderDate::GetType() const
{
// get the type from the event header

#ifdef ALI_DATE
  if (!fEvent) return 0;
  return fEvent->eventType;
#else
  return 0;
#endif
}

UInt_t AliRawReaderDate::GetRunNumber() const
{
// get the run number from the event header

#ifdef ALI_DATE
  if (!fEvent) return 0;
  return fEvent->eventRunNb;
#else
  return 0;
#endif
}

const UInt_t* AliRawReaderDate::GetEventId() const
{
// get the event id from the event header

#ifdef ALI_DATE
  if (!fEvent) return NULL;
  return fEvent->eventId;
#else
  return NULL;
#endif
}

const UInt_t* AliRawReaderDate::GetTriggerPattern() const
{
// get the trigger pattern from the event header

#ifdef ALI_DATE
  if (!fEvent) return NULL;
  return fEvent->eventTriggerPattern;
#else
  return NULL;
#endif
}

const UInt_t* AliRawReaderDate::GetDetectorPattern() const
{
// get the detector pattern from the event header

#ifdef ALI_DATE
  if (!fEvent) return NULL;
  return fEvent->eventDetectorPattern;
#else
  return NULL;
#endif
}

const UInt_t* AliRawReaderDate::GetAttributes() const
{
// get the type attributes from the event header

#ifdef ALI_DATE
  if (!fEvent) return NULL;
  return fEvent->eventTypeAttribute;
#else
  return NULL;
#endif
}

UInt_t AliRawReaderDate::GetLDCId() const
{
// get the LDC Id from the event header

#ifdef ALI_DATE
  if (!fSubEvent) return 0;
  return fSubEvent->eventLdcId;
#else
  return 0;
#endif
}

UInt_t AliRawReaderDate::GetGDCId() const
{
// get the GDC Id from the event header

#ifdef ALI_DATE
  if (!fEvent) return 0;
  return fEvent->eventGdcId;
#else
  return 0;
#endif
}

Int_t AliRawReaderDate::GetEquipmentSize() const
{
// get the size of the equipment

#ifdef ALI_DATE
  if (!fEquipment) return 0;
  return fEquipment->equipmentSize;
#else
  return 0;
#endif
}

Int_t AliRawReaderDate::GetEquipmentType() const
{
// get the type from the equipment header

#ifdef ALI_DATE
  if (!fEquipment) return -1;
  return fEquipment->equipmentType;
#else
  return 0;
#endif
}

Int_t AliRawReaderDate::GetEquipmentId() const
{
// get the ID from the equipment header

#ifdef ALI_DATE
  if (!fEquipment) return -1;
  return fEquipment->equipmentId;
#else
  return 0;
#endif
}

const UInt_t* AliRawReaderDate::GetEquipmentAttributes() const
{
// get the attributes from the equipment header

#ifdef ALI_DATE
  if (!fEquipment) return NULL;
  return fEquipment->equipmentTypeAttribute;
#else
  return 0;
#endif
}

Int_t AliRawReaderDate::GetEquipmentElementSize() const
{
// get the basic element size from the equipment header

#ifdef ALI_DATE
  if (!fEquipment) return 0;
  return fEquipment->equipmentBasicElementSize;
#else
  return 0;
#endif
}

Bool_t AliRawReaderDate::ReadHeader()
{
// read a data header at the current position
// returns kFALSE if the data header could not be read

  fErrorCode = 0;

#ifdef ALI_DATE
  if (!fEvent) return kFALSE;
  // check whether there are sub events
  if (fEvent->eventSize <= fEvent->eventHeadSize) return kFALSE;

  do {
    // skip payload (if event was not selected)
    if (fCount > 0) fPosition += fCount;

    // get the first or the next equipment if at the end of an equipment
    if (!fEquipment || (fPosition >= fEnd)) {

      // get the first or the next sub event if at the end of a sub event
      if (!fSubEvent ||
	  (fPosition >= ((UChar_t*)fSubEvent) + fSubEvent->eventSize)) {

	// check for end of event data
	if (fPosition >= ((UChar_t*)fEvent)+fEvent->eventSize) return kFALSE;
	if (fSubEvent) {
	  fSubEvent = (eventHeaderStruct*) (((UChar_t*)fSubEvent) +
					    fSubEvent->eventSize);
	} else {
	  fSubEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) +
					    fEvent->eventHeadSize);
	}

	// check the magic word of the sub event
	if (fSubEvent->eventMagic != EVENT_MAGIC_NUMBER) {
	  Error("ReadHeader", "wrong magic number in sub event!\n"
		" run: %d  event: %d %d  LDC: %d  GDC: %d\n",
		fSubEvent->eventRunNb,
		fSubEvent->eventId[0], fSubEvent->eventId[1],
		fSubEvent->eventLdcId, fSubEvent->eventGdcId);
	  fErrorCode = kErrMagic;
	  return kFALSE;
	}

	fEquipment = (equipmentHeaderStruct*)
	  (((UChar_t*)fSubEvent) + fSubEvent->eventHeadSize);

      } else {
	fEquipment = (equipmentHeaderStruct*) fEnd;
      }

      fCount = 0;
      fPosition = ((UChar_t*)fEquipment) + sizeof(equipmentHeaderStruct);
      fEnd = fPosition + fEquipment->equipmentSize;
    }

    // continue with the next sub event if no data left in the payload
    if (fPosition >= fEnd) continue;

    fHeader = NULL;
    if (fRequireHeader) {
      // check that there are enough bytes left for the data header
      if (fPosition + sizeof(AliRawDataHeader) > fEnd) {
	Error("ReadHeader", "could not read data header data!");
	Warning("ReadHeader", "skipping %d bytes\n"
		" run: %d  event: %d %d  LDC: %d  GDC: %d\n",
		fEnd - fPosition, fSubEvent->eventRunNb,
		fSubEvent->eventId[0], fSubEvent->eventId[1],
		fSubEvent->eventLdcId, fSubEvent->eventGdcId);
	fCount = 0;
	fPosition = fEnd;
	fErrorCode = kErrNoDataHeader;
	continue;
      }

      // "read" the data header
      fHeader = (AliRawDataHeader*) fPosition;
      fPosition += sizeof(AliRawDataHeader);
    }

    if (fHeader && (fHeader->fSize != 0xFFFFFFFF)) {
      fCount = fHeader->fSize - sizeof(AliRawDataHeader);

      // check consistency of data size in the header and in the sub event
      if (fPosition + fCount > fEnd) {
	Error("ReadHeader", "size in data header exceeds event size!");
	Warning("ReadHeader", "skipping %d bytes\n"
		" run: %d  event: %d %d  LDC: %d  GDC: %d\n",
		fEnd - fPosition, fSubEvent->eventRunNb,
		fSubEvent->eventId[0], fSubEvent->eventId[1],
		fSubEvent->eventLdcId, fSubEvent->eventGdcId);
	fCount = 0;
	fPosition = fEnd;
	fErrorCode = kErrSize;
	continue;
      }

    } else {
      fCount = fEnd - fPosition;
    }

  } while (!IsSelected());

  return kTRUE;
#else
  return kFALSE;
#endif
}

Bool_t AliRawReaderDate::ReadNextData(UChar_t*& data)
{
// reads the next payload at the current position
// returns kFALSE if the data could not be read

  fErrorCode = 0;
  while (fCount == 0) {
    if (!ReadHeader()) return kFALSE;
  }
  data = fPosition;
  fPosition += fCount;
  fCount = 0;
  return kTRUE;
}

Bool_t AliRawReaderDate::ReadNext(UChar_t* data, Int_t size)
{
// reads the next block of data at the current position
// returns kFALSE if the data could not be read

  fErrorCode = 0;
  if (fPosition + size > fEnd) {
    Error("ReadNext", "could not read data!");
    fErrorCode = kErrOutOfBounds;
    return kFALSE;
  }
  memcpy(data, fPosition, size);
  fPosition += size;
  fCount -= size;
  return kTRUE;
}

Bool_t AliRawReaderDate::Reset()
{
// reset the current position to the beginning of the event

#ifdef ALI_DATE
  fSubEvent = NULL;
#endif
  fCount = 0;
  fPosition = fEnd = NULL;
  return kTRUE;
}

Int_t AliRawReaderDate::CheckData() const
{
// check the consistency of the data

#ifdef ALI_DATE
  if (!fEvent) return 0;
  // check whether there are sub events
  if (fEvent->eventSize <= fEvent->eventHeadSize) return 0;

  eventHeaderStruct* subEvent = NULL;
  UChar_t* position = 0;
  UChar_t* end = 0;
  Int_t result = 0;

  while (kTRUE) {
    // get the first or the next sub event if at the end of a sub event
    if (!subEvent || (position >= end)) {

      // check for end of event data
      if (position >= ((UChar_t*)fEvent)+fEvent->eventSize) return result;
      if (subEvent) {
	subEvent = (eventHeaderStruct*) (((UChar_t*)subEvent) +
					 subEvent->eventSize);
      } else {
	subEvent = (eventHeaderStruct*) (((UChar_t*)fEvent) +
					 fEvent->eventHeadSize);
      }

      // check the magic word of the sub event
      if (subEvent->eventMagic != EVENT_MAGIC_NUMBER) {
	result |= kErrMagic;
	return result;
      }

      position = ((UChar_t*)subEvent) + subEvent->eventHeadSize +
	sizeof(equipmentHeaderStruct);
      end = ((UChar_t*)subEvent) + subEvent->eventSize;
    }

    // continue with the next sub event if no data left in the payload
    if (position >= end) continue;

    // check that there are enough bytes left for the data header
    if (position + sizeof(AliRawDataHeader) > end) {
      result |= kErrNoDataHeader;
      position = end;
      continue;
    }

    // check consistency of data size in the data header and in the sub event
    AliRawDataHeader* header = (AliRawDataHeader*) position;
    if (header->fSize != 0xFFFFFFFF) {
      if (position + header->fSize > end) {
	result |= kErrSize;
	position = end;
      } else {
	position += header->fSize;
      }
    } else {
      position = end;
    }
  };

#endif
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, 2016, 2017, 2018, 2019, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "FrequencyGovernorImp.hpp"

#include <cmath>
#include <unistd.h>

#include <vector>

#include "Exception.hpp"
#include "Helper.hpp"
#include "PlatformIO.hpp"
#include "PlatformTopo.hpp"
#include "config.h"

namespace geopm
{
    std::unique_ptr<FrequencyGovernor> FrequencyGovernor::make_unique(void)
    {
        return geopm::make_unique<FrequencyGovernorImp>();
    }

    std::shared_ptr<FrequencyGovernor> FrequencyGovernor::make_shared(void)
    {
        return std::make_shared<FrequencyGovernorImp>();
    }

    FrequencyGovernorImp::FrequencyGovernorImp()
        : FrequencyGovernorImp(platform_io(), platform_topo())
    {

    }

    FrequencyGovernorImp::FrequencyGovernorImp(PlatformIO &platform_io, const PlatformTopo &platform_topo)
        : m_platform_io(platform_io)
        , m_platform_topo(platform_topo)
        , M_FREQ_STEP(get_limit("CPUINFO::FREQ_STEP"))
        , M_PLAT_FREQ_MIN(get_limit("CPUINFO::FREQ_MIN"))
        , M_PLAT_FREQ_MAX(get_limit("FREQUENCY_MAX"))
        , m_freq_min(M_PLAT_FREQ_MIN)
        , m_freq_max(M_PLAT_FREQ_MAX)
        , m_do_write_batch(false)
        , m_freq_ctl_domain_type(m_platform_io.control_domain_type("FREQUENCY"))
    {

    }

    FrequencyGovernorImp::~FrequencyGovernorImp()
    {

    }

    double FrequencyGovernorImp::get_limit(const std::string &sig_name) const
    {
        const int domain_type = m_platform_io.signal_domain_type(sig_name);
        double result = NAN;
        if (sig_name == "CPUINFO::FREQ_MIN") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "FREQUENCY_MAX") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "CPUINFO::FREQ_STEP") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
#ifdef GEOPM_DEBUG
        else {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) + "(): requested invalid signal name.",
                            GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
        }
#endif
        return result;
    }

    void FrequencyGovernorImp::init_platform_io(void)
    {
        m_last_freq = std::vector<double>(m_freq_ctl_domain_type, NAN);
        const int num_freq_ctl_domain = m_platform_topo.num_domain(m_freq_ctl_domain_type);
        for (int ctl_dom_idx = 0; ctl_dom_idx != num_freq_ctl_domain; ++ctl_dom_idx) {
            m_control_idx.push_back(m_platform_io.push_control("FREQUENCY",
                                                               m_freq_ctl_domain_type,
                                                               ctl_dom_idx));
        }
    }

    int FrequencyGovernorImp::frequency_domain_type(void) const
    {
        return m_freq_ctl_domain_type;
    }

    void FrequencyGovernorImp::adjust_platform(const std::vector<double> &frequency_request)
    {
        if (frequency_request.size() != m_control_idx.size()) {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) +
                            "(): size of request vector does not match size of control domain.",
                            GEOPM_ERROR_INVALID, __FILE__, __LINE__);
        }

        m_do_write_batch = !std::equal(m_last_freq.begin(), m_last_freq.end(), frequency_request.begin());
        std::vector<double> frequency_actual;
        for (size_t idx = 0; idx < m_control_idx.size(); ++idx) {
            double clamp_freq = NAN;
            if (frequency_request[idx] > m_freq_max) {
                clamp_freq = m_freq_max;
            }
            else if (frequency_request[idx] < m_freq_min) {
                clamp_freq = m_freq_min;
            }
            else {
                clamp_freq = frequency_request[idx];
            }
            frequency_actual.push_back(clamp_freq);
            m_platform_io.adjust(m_control_idx[idx], frequency_actual[idx]);
        }
        m_last_freq = frequency_actual;
    }

    bool FrequencyGovernorImp::do_write_batch(void) const
    {
        return m_do_write_batch;
    }

    bool FrequencyGovernorImp::set_frequency_bounds(double freq_min, double freq_max)
    {
        if (freq_min < M_PLAT_FREQ_MIN || freq_max > M_PLAT_FREQ_MAX ||
            freq_min > freq_max) {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) + "(): invalid frequency bounds.",
                            GEOPM_ERROR_INVALID, __FILE__, __LINE__);

        }
        bool result = false;
        if (m_freq_min != freq_min ||
            m_freq_max != freq_max) {
            m_freq_min = freq_min;
            m_freq_max = freq_max;
            result = true;
        }
        return result;
    }

    double FrequencyGovernorImp::get_frequency_min()  const
    {
        return m_freq_min;
    }

    double FrequencyGovernorImp::get_frequency_max()  const
    {
        return m_freq_max;
    }

    double FrequencyGovernorImp::get_frequency_step()  const
    {
        return M_FREQ_STEP;
    }

    void FrequencyGovernorImp::validate_policy(double &freq_min, double &freq_max) const
    {
        double target_freq_min = std::isnan(freq_min) ? get_limit("CPUINFO::FREQ_MIN") : freq_min;
        double target_freq_max = std::isnan(freq_max) ? get_limit("FREQUENCY_MAX") : freq_max;
        freq_min = target_freq_min;
        freq_max = target_freq_max;
    }
}
<commit_msg>Use sticker when passing NaN in the policy.<commit_after>/*
 * Copyright (c) 2015, 2016, 2017, 2018, 2019, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "FrequencyGovernorImp.hpp"

#include <cmath>
#include <unistd.h>

#include <vector>

#include "Exception.hpp"
#include "Helper.hpp"
#include "PlatformIO.hpp"
#include "PlatformTopo.hpp"
#include "config.h"

namespace geopm
{
    std::unique_ptr<FrequencyGovernor> FrequencyGovernor::make_unique(void)
    {
        return geopm::make_unique<FrequencyGovernorImp>();
    }

    std::shared_ptr<FrequencyGovernor> FrequencyGovernor::make_shared(void)
    {
        return std::make_shared<FrequencyGovernorImp>();
    }

    FrequencyGovernorImp::FrequencyGovernorImp()
        : FrequencyGovernorImp(platform_io(), platform_topo())
    {

    }

    FrequencyGovernorImp::FrequencyGovernorImp(PlatformIO &platform_io, const PlatformTopo &platform_topo)
        : m_platform_io(platform_io)
        , m_platform_topo(platform_topo)
        , M_FREQ_STEP(get_limit("CPUINFO::FREQ_STEP"))
        , M_PLAT_FREQ_MIN(get_limit("CPUINFO::FREQ_MIN"))
        , M_PLAT_FREQ_MAX(get_limit("FREQUENCY_MAX"))
        , m_freq_min(M_PLAT_FREQ_MIN)
        , m_freq_max(M_PLAT_FREQ_MAX)
        , m_do_write_batch(false)
        , m_freq_ctl_domain_type(m_platform_io.control_domain_type("FREQUENCY"))
    {

    }

    FrequencyGovernorImp::~FrequencyGovernorImp()
    {

    }

    double FrequencyGovernorImp::get_limit(const std::string &sig_name) const
    {
        const int domain_type = m_platform_io.signal_domain_type(sig_name);
        double result = NAN;
        if (sig_name == "CPUINFO::FREQ_MIN") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "CPUINFO::FREQ_STICKER") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "CPUINFO::FREQ_STEP") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
        else if (sig_name == "FREQUENCY_MAX") {
            result = m_platform_io.read_signal(sig_name, domain_type, 0);
        }
#ifdef GEOPM_DEBUG
        else {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) + "(): requested invalid signal name.",
                            GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
        }
#endif
        return result;
    }

    void FrequencyGovernorImp::init_platform_io(void)
    {
        m_last_freq = std::vector<double>(m_freq_ctl_domain_type, NAN);
        const int num_freq_ctl_domain = m_platform_topo.num_domain(m_freq_ctl_domain_type);
        for (int ctl_dom_idx = 0; ctl_dom_idx != num_freq_ctl_domain; ++ctl_dom_idx) {
            m_control_idx.push_back(m_platform_io.push_control("FREQUENCY",
                                                               m_freq_ctl_domain_type,
                                                               ctl_dom_idx));
        }
    }

    int FrequencyGovernorImp::frequency_domain_type(void) const
    {
        return m_freq_ctl_domain_type;
    }

    void FrequencyGovernorImp::adjust_platform(const std::vector<double> &frequency_request)
    {
        if (frequency_request.size() != m_control_idx.size()) {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) +
                            "(): size of request vector does not match size of control domain.",
                            GEOPM_ERROR_INVALID, __FILE__, __LINE__);
        }

        m_do_write_batch = !std::equal(m_last_freq.begin(), m_last_freq.end(), frequency_request.begin());
        std::vector<double> frequency_actual;
        for (size_t idx = 0; idx < m_control_idx.size(); ++idx) {
            double clamp_freq = NAN;
            if (frequency_request[idx] > m_freq_max) {
                clamp_freq = m_freq_max;
            }
            else if (frequency_request[idx] < m_freq_min) {
                clamp_freq = m_freq_min;
            }
            else {
                clamp_freq = frequency_request[idx];
            }
            frequency_actual.push_back(clamp_freq);
            m_platform_io.adjust(m_control_idx[idx], frequency_actual[idx]);
        }
        m_last_freq = frequency_actual;
    }

    bool FrequencyGovernorImp::do_write_batch(void) const
    {
        return m_do_write_batch;
    }

    bool FrequencyGovernorImp::set_frequency_bounds(double freq_min, double freq_max)
    {
        if (freq_min < M_PLAT_FREQ_MIN || freq_max > M_PLAT_FREQ_MAX ||
            freq_min > freq_max) {
            throw Exception("FrequencyGovernorImp::" + std::string(__func__) + "(): invalid frequency bounds.",
                            GEOPM_ERROR_INVALID, __FILE__, __LINE__);

        }
        bool result = false;
        if (m_freq_min != freq_min ||
            m_freq_max != freq_max) {
            m_freq_min = freq_min;
            m_freq_max = freq_max;
            result = true;
        }
        return result;
    }

    double FrequencyGovernorImp::get_frequency_min()  const
    {
        return m_freq_min;
    }

    double FrequencyGovernorImp::get_frequency_max()  const
    {
        return m_freq_max;
    }

    double FrequencyGovernorImp::get_frequency_step()  const
    {
        return M_FREQ_STEP;
    }

    void FrequencyGovernorImp::validate_policy(double &freq_min, double &freq_max) const
    {
        double target_freq_min = std::isnan(freq_min) ? get_limit("CPUINFO::FREQ_MIN") : freq_min;
        double target_freq_max = std::isnan(freq_max) ? get_limit("CPUINFO::FREQ_STICKER") : freq_max;
        freq_min = target_freq_min;
        freq_max = target_freq_max;
    }
}
<|endoftext|>


<commit_before>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2010 Emmanuel Benazera, ebenazer@seeks-project.info
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "rank_estimators.h"
#include "cf.h"
#include "cf_configuration.h"
#include "qprocess.h"
#include "query_capture.h"
#include "uri_capture.h"
#include "db_uri_record.h"
#include "urlmatch.h"

#include <assert.h>
#include <math.h>
#include <iostream>

using lsh::qprocess;
using sp::urlmatch;

namespace seeks_plugins
{

   /*- rank_estimator -*/
   void rank_estimator::fetch_user_db_record(const std::string &query,
					     std::vector<db_record*> &records)
     {
	static std::string qc_str = "query-capture";

	// strip query.
	std::string q = query_capture_element::no_command_query(query);

	// generate query fragments.
	hash_multimap<uint32_t,DHTKey,id_hash_uint> features;
	qprocess::generate_query_hashes(q,0,5,features); //TODO: from configuration (5).

	// fetch records from the user DB.
	hash_multimap<uint32_t,DHTKey,id_hash_uint>::const_iterator hit = features.begin();
	while(hit!=features.end())
	  {
	     std::string key_str = (*hit).second.to_rstring();
	     db_record *dbr = seeks_proxy::_user_db->find_dbr(key_str,qc_str);
	     if (dbr)
	       records.push_back(dbr);
	     ++hit;
	  }
     }

   /*- simple_re -*/
   simple_re::simple_re()
     :rank_estimator()
       {
       }

   simple_re::~simple_re()
     {
     }

   void simple_re::extract_queries(const std::vector<db_record*> &records,
				   hash_map<const char*,query_data*,hash<const char*>,eqstr> &qdata)
     {
	static std::string qc_str = "query-capture";

	// iterate records and gather queries and data.
	hash_map<const char*,query_data*,hash<const char*>,eqstr>::const_iterator hit;
	std::vector<db_record*>::const_iterator vit = records.begin();
	while(vit!=records.end())
	  {
	     db_query_record *dbqr = static_cast<db_query_record*>((*vit));
	     hash_map<const char*,query_data*,hash<const char*>,eqstr>::const_iterator qit
	       = dbqr->_related_queries.begin();
	     while(qit!=dbqr->_related_queries.end())
	       {
		  query_data *qd = (*qit).second;
		  if ((hit=qdata.find(qd->_query.c_str()))==qdata.end())
		    {
		       if (qd->_radius == 0) // contains the data.
			 qdata.insert(std::pair<const char*,query_data*>(qd->_query.c_str(),
									 new query_data(qd)));
		       else
			 {
			    // data are in lower radius records.
			    hash_multimap<uint32_t,DHTKey,id_hash_uint> features;
			    qprocess::generate_query_hashes(qd->_query,0,0,features);

			    // XXX: when the query contains > 8 words there are many features generated
			    // for the same radius. The original query data can be fetched from any
			    // of the generated features, so we take the first one.
			    assert(features.size()>=1);
			    std::string key_str = (*features.begin()).second.to_rstring();
			    db_record *dbr_data = seeks_proxy::_user_db->find_dbr(key_str,qc_str);
			    assert(dbr_data != NULL); // beware.
			    db_query_record *dbqr_data = static_cast<db_query_record*>(dbr_data);
			    hash_map<const char*,query_data*,hash<const char*>,eqstr>::const_iterator qit2
			      = dbqr_data->_related_queries.begin();
			    while(qit2!=dbqr_data->_related_queries.end())
			      {
				 if ((*qit2).second->_radius == 0
				     && (*qit2).second->_query == qd->_query)
				   {
				      query_data *dbqrc = new query_data((*qit2).second);
				      qdata.insert(std::pair<const char*,query_data*>(dbqrc->_query.c_str(),
										      dbqrc));
				      break;
				   }
				 ++qit2;
			      }
			    delete dbqr_data;
			 }
		    }
		  ++qit;
	       }
	     ++vit;
	  }
     }

   void simple_re::estimate_ranks(const std::string &query,
				  std::vector<search_snippet*> &snippets)
     {
	// fetch records from user DB.
	std::vector<db_record*> records;
	fetch_user_db_record(query,records);

	//std::cerr << "[estimate_ranks]: number of fetched records: " << records.size() << std::endl;

	// extract queries.
	hash_map<const char*,query_data*,hash<const char*>,eqstr> qdata;
	extract_queries(records,qdata);

	//std::cerr << "[estimate_ranks]: number of extracted queries: " << qdata.size() << std::endl;

	// destroy records.
	std::vector<db_record*>::iterator rit = records.begin();
	while(rit!=records.end())
	  {
	     db_record *dbr = (*rit);
	     rit = records.erase(rit);
	     delete dbr;
	  }

	// gather normalizing values.
	int i = 0;
	hash_map<const char*,query_data*,hash<const char*>,eqstr>::const_iterator hit
	  = qdata.begin();
	float q_vurl_hits[qdata.size()];
	while(hit!=qdata.end())
	  {
	     q_vurl_hits[i++] = (*hit).second->vurls_total_hits();
	     ++hit;
	  }
	float sum_se_ranks = 0.0;
	std::vector<search_snippet*>::iterator vit = snippets.begin();
	while(vit!=snippets.end())
	  {
	     sum_se_ranks += (*vit)->_seeks_rank;
	     ++vit;
	  }

	// get number of captured URIs.
	uint64_t nuri = 0;
	if (cf::_uc_plugin)
	  nuri = static_cast<uri_capture*>(cf::_uc_plugin)->_nr;

	// estimate each URL's rank.
	int j = 0;
	size_t ns = snippets.size();
	float posteriors[ns];
	float sum_posteriors = 0.0;
	vit = snippets.begin();
	while(vit!=snippets.end())
	  {
	     std::string url = (*vit)->_url;
	     std::transform(url.begin(),url.end(),url.begin(),tolower);
	     std::string surl = urlmatch::strip_url(url);
	     std::string host, path;
	     urlmatch::parse_url_host_and_path(url,host,path);
	     host = urlmatch::strip_url(host);

	     i = 0;
	     posteriors[j] = 0.0;
	     hit = qdata.begin();
	     while(hit!=qdata.end())
	       {
		  float qpost = estimate_rank((*vit),ns,(*hit).second,q_vurl_hits[i++],
					     surl,host,path);
		  //qpost *= (*vit)->_seeks_rank / sum_se_ranks; // account for URL rank in results from search engines.
		  qpost *= 1.0/static_cast<float>(((*hit).second->_radius + 1.0)); // account for distance to original query.
		  posteriors[j] += qpost; // boosting over similar queries.
		  ++hit;
	       }

	     // estimate the url prior.
	     bool personalized = false;
	     float prior = 1.0;
	     if (nuri != 0)
	       prior = estimate_prior(surl,host,nuri,personalized);
	     if (personalized)
	       (*vit)->_personalized = true;

	     posteriors[j] *= prior;
	     //std::cerr << "url: " << (*vit)->_url << " -- prior: " << prior << " -- posterior: " << posteriors[j] << std::endl;

	     sum_posteriors += posteriors[j++];
	     ++vit;
	  }

	// wrapup.
	if (sum_posteriors > 0.0)
	  {
	     for (size_t k=0;k<ns;k++)
	       {
		  posteriors[k] /= sum_posteriors; // normalize.
		  snippets.at(k)->_seeks_rank = posteriors[k];
		  //std::cerr << "url: " << snippets.at(k)->_url << " -- seeks_rank: " << snippets.at(k)->_seeks_rank << std::endl;
	       }
	  }

	// destroy query data.
	hash_map<const char*,query_data*,hash<const char*>,eqstr>::iterator hit2;
	hash_map<const char*,query_data*,hash<const char*>,eqstr>::iterator chit;
	hit2 = qdata.begin();
	while(hit2!=qdata.end())
	  {
	     query_data *qd = (*hit2).second;
	     chit = hit2;
	     ++hit2;
	     delete qd;
	  }
     }

   float simple_re::estimate_rank(search_snippet *s, const int &ns,
				  const query_data *qd,
				  const float &total_hits,
				  const std::string &surl,
				  const std::string &host, const std::string &path)
     {
	float posterior = 0.0;

	// URL.
	vurl_data *vd = qd->find_vurl(surl);
	if (!vd)
	  posterior =  1.0 / (log(static_cast<float>(ns) + 1.0) + 1.0); // XXX: may replace ns with a less discriminative value.
	else
	  {
	     posterior = (log(vd->_hits + 1.0) + 1.0)/ (log(total_hits + 1.0) + ns);
	     s->_personalized = true;
	  }

	// host.
	vd = qd->find_vurl(host);
	if (!vd)
	  posterior *= cf_configuration::_config->_domain_name_weight
	  / static_cast<float>(ns); // XXX: may replace ns with a less discriminative value.
	else
	  {
	     posterior *= cf_configuration::_config->_domain_name_weight
	       * (log(vd->_hits + 1.0) + 1.0)
		 / (log(total_hits + 1.0) + ns); // with domain-name weight factor.
	     s->_personalized = true;
	  }
	//std::cerr << "posterior: " << posterior << std::endl;

	return posterior;
     }

   float simple_re::estimate_prior(const std::string &surl,
				   const std::string &host,
				   const uint64_t &nuri,
				   bool &personalized)
     {
	static std::string uc_str = "uri-capture";
	float prior = 0.0;
	float furi = static_cast<float>(nuri);
	db_record *dbr = seeks_proxy::_user_db->find_dbr(surl,uc_str);
	if (!dbr)
	  prior = 1.0 / log(furi + 1.0);
	else
	  {
	     db_uri_record *uc_dbr = static_cast<db_uri_record*>(dbr);
	     prior = (log(uc_dbr->_hits + 1.0) + 1.0)/ log(furi + 1.0);
	     delete uc_dbr;
	     personalized = true;
	  }
	dbr = seeks_proxy::_user_db->find_dbr(host,uc_str);
	if (!dbr)
	  prior *= 1.0 / log(furi + 1.0);
	else
	  {
	     db_uri_record *uc_dbr = static_cast<db_uri_record*>(dbr);
	     prior *= (log(uc_dbr->_hits + 1.0) + 1.0) / log(furi + 1.0);
	     delete uc_dbr;
	     personalized = true;
	  }
	return prior;
     }

} /* end of namespace. */

<commit_msg>fixed nasty URL comparison bug in personalization and cancels domain name effect on videos and tweets<commit_after>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2010 Emmanuel Benazera, ebenazer@seeks-project.info
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "rank_estimators.h"
#include "cf.h"
#include "cf_configuration.h"
#include "qprocess.h"
#include "query_capture.h"
#include "uri_capture.h"
#include "db_uri_record.h"
#include "urlmatch.h"

#include <assert.h>
#include <math.h>
#include <iostream>

using lsh::qprocess;
using sp::urlmatch;

namespace seeks_plugins
{

   /*- rank_estimator -*/
   void rank_estimator::fetch_user_db_record(const std::string &query,
					     std::vector<db_record*> &records)
     {
	static std::string qc_str = "query-capture";

	// strip query.
	std::string q = query_capture_element::no_command_query(query);

	// generate query fragments.
	hash_multimap<uint32_t,DHTKey,id_hash_uint> features;
	qprocess::generate_query_hashes(q,0,5,features); //TODO: from configuration (5).

	// fetch records from the user DB.
	hash_multimap<uint32_t,DHTKey,id_hash_uint>::const_iterator hit = features.begin();
	while(hit!=features.end())
	  {
	     std::string key_str = (*hit).second.to_rstring();
	     db_record *dbr = seeks_proxy::_user_db->find_dbr(key_str,qc_str);
	     if (dbr)
	       records.push_back(dbr);
	     ++hit;
	  }
     }

   /*- simple_re -*/
   simple_re::simple_re()
     :rank_estimator()
       {
       }

   simple_re::~simple_re()
     {
     }

   void simple_re::extract_queries(const std::vector<db_record*> &records,
				   hash_map<const char*,query_data*,hash<const char*>,eqstr> &qdata)
     {
	static std::string qc_str = "query-capture";

	// iterate records and gather queries and data.
	hash_map<const char*,query_data*,hash<const char*>,eqstr>::const_iterator hit;
	std::vector<db_record*>::const_iterator vit = records.begin();
	while(vit!=records.end())
	  {
	     db_query_record *dbqr = static_cast<db_query_record*>((*vit));
	     hash_map<const char*,query_data*,hash<const char*>,eqstr>::const_iterator qit
	       = dbqr->_related_queries.begin();
	     while(qit!=dbqr->_related_queries.end())
	       {
		  query_data *qd = (*qit).second;
		  if ((hit=qdata.find(qd->_query.c_str()))==qdata.end())
		    {
		       if (qd->_radius == 0) // contains the data.
			 qdata.insert(std::pair<const char*,query_data*>(qd->_query.c_str(),
									 new query_data(qd)));
		       else
			 {
			    // data are in lower radius records.
			    hash_multimap<uint32_t,DHTKey,id_hash_uint> features;
			    qprocess::generate_query_hashes(qd->_query,0,0,features);

			    // XXX: when the query contains > 8 words there are many features generated
			    // for the same radius. The original query data can be fetched from any
			    // of the generated features, so we take the first one.
			    assert(features.size()>=1);
			    std::string key_str = (*features.begin()).second.to_rstring();
			    db_record *dbr_data = seeks_proxy::_user_db->find_dbr(key_str,qc_str);
			    assert(dbr_data != NULL); // beware.
			    db_query_record *dbqr_data = static_cast<db_query_record*>(dbr_data);
			    hash_map<const char*,query_data*,hash<const char*>,eqstr>::const_iterator qit2
			      = dbqr_data->_related_queries.begin();
			    while(qit2!=dbqr_data->_related_queries.end())
			      {
				 if ((*qit2).second->_radius == 0
				     && (*qit2).second->_query == qd->_query)
				   {
				      query_data *dbqrc = new query_data((*qit2).second);
				      qdata.insert(std::pair<const char*,query_data*>(dbqrc->_query.c_str(),
										      dbqrc));
				      break;
				   }
				 ++qit2;
			      }
			    delete dbqr_data;
			 }
		    }
		  ++qit;
	       }
	     ++vit;
	  }
     }

   void simple_re::estimate_ranks(const std::string &query,
				  std::vector<search_snippet*> &snippets)
     {
	// fetch records from user DB.
	std::vector<db_record*> records;
	fetch_user_db_record(query,records);

	//std::cerr << "[estimate_ranks]: number of fetched records: " << records.size() << std::endl;

	// extract queries.
	hash_map<const char*,query_data*,hash<const char*>,eqstr> qdata;
	extract_queries(records,qdata);

	//std::cerr << "[estimate_ranks]: number of extracted queries: " << qdata.size() << std::endl;

	// destroy records.
	std::vector<db_record*>::iterator rit = records.begin();
	while(rit!=records.end())
	  {
	     db_record *dbr = (*rit);
	     rit = records.erase(rit);
	     delete dbr;
	  }

	// gather normalizing values.
	int i = 0;
	hash_map<const char*,query_data*,hash<const char*>,eqstr>::const_iterator hit
	  = qdata.begin();
	float q_vurl_hits[qdata.size()];
	while(hit!=qdata.end())
	  {
	     q_vurl_hits[i++] = (*hit).second->vurls_total_hits();
	     ++hit;
	  }
	float sum_se_ranks = 0.0;
	std::vector<search_snippet*>::iterator vit = snippets.begin();
	while(vit!=snippets.end())
	  {
	     sum_se_ranks += (*vit)->_seeks_rank;
	     ++vit;
	  }

	// get number of captured URIs.
	uint64_t nuri = 0;
	if (cf::_uc_plugin)
	  nuri = static_cast<uri_capture*>(cf::_uc_plugin)->_nr;

	// estimate each URL's rank.
	int j = 0;
	size_t ns = snippets.size();
	float posteriors[ns];
	float sum_posteriors = 0.0;
	vit = snippets.begin();
	while(vit!=snippets.end())
	  {
	     std::string url = (*vit)->_url;
	     std::transform(url.begin(),url.end(),url.begin(),tolower);
	     //std::string surl = urlmatch::strip_url(url);
	     std::string host, path;
	     urlmatch::parse_url_host_and_path(url,host,path);
	     host = urlmatch::strip_url(host);

	     i = 0;
	     posteriors[j] = 0.0;
	     hit = qdata.begin();
	     while(hit!=qdata.end())
	       {
		  float qpost = estimate_rank((*vit),ns,(*hit).second,q_vurl_hits[i++],
					     url,host,path);
		  //qpost *= (*vit)->_seeks_rank / sum_se_ranks; // account for URL rank in results from search engines.
		  qpost *= 1.0/static_cast<float>(((*hit).second->_radius + 1.0)); // account for distance to original query.
		  posteriors[j] += qpost; // boosting over similar queries.

		  //std::cerr << "url: " << (*vit)->_url << " -- qpost: " << qpost << std::endl;

		  ++hit;
	       }

	     // estimate the url prior.
	     bool personalized = false;
	     float prior = 1.0;
	     if (nuri != 0 && (*vit)->_doc_type != VIDEO_THUMB && (*vit)->_doc_type != TWEET) // not empty or not type with not enought competition on domains.
	       prior = estimate_prior(url,host,nuri,personalized);
	     if (personalized)
	       (*vit)->_personalized = true;
	     posteriors[j] *= prior;

	     //std::cerr << "url: " << (*vit)->_url << " -- prior: " << prior << " -- posterior: " << posteriors[j] << std::endl;

	     sum_posteriors += posteriors[j++];
	     ++vit;
	  }

	// wrapup.
	if (sum_posteriors > 0.0)
	  {
	     for (size_t k=0;k<ns;k++)
	       {
		  posteriors[k] /= sum_posteriors; // normalize.
		  snippets.at(k)->_seeks_rank = posteriors[k];
		  //std::cerr << "url: " << snippets.at(k)->_url << " -- seeks_rank: " << snippets.at(k)->_seeks_rank << std::endl;
	       }
	  }

	// destroy query data.
	hash_map<const char*,query_data*,hash<const char*>,eqstr>::iterator hit2;
	hash_map<const char*,query_data*,hash<const char*>,eqstr>::iterator chit;
	hit2 = qdata.begin();
	while(hit2!=qdata.end())
	  {
	     query_data *qd = (*hit2).second;
	     chit = hit2;
	     ++hit2;
	     delete qd;
	  }
     }

   float simple_re::estimate_rank(search_snippet *s, const int &ns,
				  const query_data *qd,
				  const float &total_hits,
				  const std::string &surl,
				  const std::string &host, const std::string &path)
     {
	float posterior = 0.0;

	// URL.
	vurl_data *vd = qd->find_vurl(surl);

	if (!vd)
	  //posterior =  1.0 / (log(static_cast<float>(ns) + 1.0) + 1.0); // XXX: may replace ns with a less discriminative value.
	  posterior = 1.0 / (log(total_hits + 1.0) + ns);
	else
	  {
	     posterior = (log(vd->_hits + 1.0) + 1.0)/ (log(total_hits + 1.0) + ns);
	     s->_personalized = true;
	  }

	// host.
	vd = qd->find_vurl(host);
	if (!vd || s->_doc_type == VIDEO_THUMB || s->_doc_type == TWEET)  // empty or type with not enough competition on domains.
	  posterior *= cf_configuration::_config->_domain_name_weight
	  / static_cast<float>(ns); // XXX: may replace ns with a less discriminative value.
	else
	  {
	     posterior *= cf_configuration::_config->_domain_name_weight
	       * (log(vd->_hits + 1.0) + 1.0)
		 / (log(total_hits + 1.0) + ns); // with domain-name weight factor.
	     s->_personalized = true;
	  }
	//std::cerr << "posterior: " << posterior << std::endl;

	return posterior;
     }

   float simple_re::estimate_prior(const std::string &surl,
				   const std::string &host,
				   const uint64_t &nuri,
				   bool &personalized)
     {
	static std::string uc_str = "uri-capture";
	float prior = 0.0;
	float furi = static_cast<float>(nuri);
	db_record *dbr = seeks_proxy::_user_db->find_dbr(surl,uc_str);
	if (!dbr)
	  prior = 1.0 / log(furi + 1.0);
	else
	  {
	     db_uri_record *uc_dbr = static_cast<db_uri_record*>(dbr);
	     prior = (log(uc_dbr->_hits + 1.0) + 1.0)/ log(furi + 1.0);
	     delete uc_dbr;
	     personalized = true;
	  }
	dbr = seeks_proxy::_user_db->find_dbr(host,uc_str);
	if (!dbr)
	  prior *= 1.0 / log(furi + 1.0);
	else
	  {
	     db_uri_record *uc_dbr = static_cast<db_uri_record*>(dbr);
	     prior *= (log(uc_dbr->_hits + 1.0) + 1.0) / log(furi + 1.0);
	     delete uc_dbr;
	     personalized = true;
	  }
	return prior;
     }

} /* end of namespace. */

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#include <svl/szitem.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/awt/Size.hpp>
#include <tools/stream.hxx>
#include <tools/gen.hxx>

#include <svl/poolitem.hxx>
#include <svl/memberid.hrc>

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

DBG_NAME(SfxSizeItem)

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

TYPEINIT1_AUTOFACTORY(SfxSizeItem, SfxPoolItem);

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

SfxSizeItem::SfxSizeItem()
{
    DBG_CTOR(SfxSizeItem, 0);
}

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

SfxSizeItem::SfxSizeItem( sal_uInt16 nW, const Size& rVal ) :
    SfxPoolItem( nW ),
    aVal( rVal )
{
    DBG_CTOR(SfxSizeItem, 0);
}

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

SfxSizeItem::SfxSizeItem( const SfxSizeItem& rItem ) :
    SfxPoolItem( rItem ),
    aVal( rItem.aVal )
{
    DBG_CTOR(SfxSizeItem, 0);
}

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

SfxItemPresentation SfxSizeItem::GetPresentation
(
    SfxItemPresentation     /*ePresentation*/,
    SfxMapUnit              /*eCoreMetric*/,
    SfxMapUnit              /*ePresentationMetric*/,
    XubString&              rText,
    const IntlWrapper *
)   const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    rText = UniString::CreateFromInt32(aVal.Width());
    rText.AppendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
    rText += UniString::CreateFromInt32(aVal.Height());
    rText.AppendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
    return SFX_ITEM_PRESENTATION_NAMELESS;
}

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

int SfxSizeItem::operator==( const SfxPoolItem& rItem ) const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    DBG_ASSERT( SfxPoolItem::operator==( rItem ), "unequal type" );
    return ((SfxSizeItem&)rItem).aVal == aVal;
}

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

SfxPoolItem* SfxSizeItem::Clone(SfxItemPool *) const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    return new SfxSizeItem( *this );
}

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

SfxPoolItem* SfxSizeItem::Create(SvStream &rStream, sal_uInt16 ) const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    Size aStr;
    rStream >> aStr;
    return new SfxSizeItem(Which(), aStr);
}

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

SvStream& SfxSizeItem::Store(SvStream &rStream, sal_uInt16 ) const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    rStream << aVal;
    return rStream;
}

// -----------------------------------------------------------------------
bool  SfxSizeItem::QueryValue( com::sun::star::uno::Any& rVal,
                               sal_uInt8 nMemberId ) const
{
    sal_Bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
    nMemberId &= ~CONVERT_TWIPS;

    Size aTmp(aVal);
    if( bConvert )
    {
        aTmp.Height() = ( aTmp.Height() * 127 + 36) / 72;
        aTmp.Width() = ( aTmp.Width() * 127 + 36) / 72;
    }

    switch ( nMemberId )
    {
        case 0:
        {
            rVal <<= com::sun::star::awt::Size( aTmp.getWidth(), aTmp.getHeight() );
            break;
        }
        case MID_WIDTH:
            rVal <<= aTmp.getWidth(); break;
        case MID_HEIGHT:
            rVal <<= aTmp.getHeight(); break;
    default: OSL_FAIL("Wrong MemberId!"); return false;
    }

    return true;
}

// -----------------------------------------------------------------------
bool SfxSizeItem::PutValue( const com::sun::star::uno::Any& rVal,
                            sal_uInt8 nMemberId )
{
    sal_Bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
    nMemberId &= ~CONVERT_TWIPS;

    bool bRet = false;
    com::sun::star::awt::Size aValue;
    sal_Int32 nVal = 0;
    if ( !nMemberId )
        bRet = ( rVal >>= aValue );
    else
    {
        bRet = ( rVal >>= nVal );
        if ( nMemberId == MID_WIDTH )
        {
            aValue.Width = nVal;
            aValue.Height = aVal.Height();
        }
        else
        {
            aValue.Height = nVal;
            aValue.Width = aVal.Width();
        }
    }

    if ( bRet )
    {
        Size aTmp( aValue.Width, aValue.Height );
        if( bConvert )
        {
            aTmp.Height() = ( aTmp.Height() * 72 + 63) / 127;
            aTmp.Width() = ( aTmp.Width() * 72 + 63) / 127;
        }

        aVal = aTmp;
    }

    return bRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>cppcheck scope reduction in svl/szitem.cxx<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#include <svl/szitem.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/awt/Size.hpp>
#include <tools/stream.hxx>
#include <tools/gen.hxx>

#include <svl/poolitem.hxx>
#include <svl/memberid.hrc>

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

DBG_NAME(SfxSizeItem)

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

TYPEINIT1_AUTOFACTORY(SfxSizeItem, SfxPoolItem);

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

SfxSizeItem::SfxSizeItem()
{
    DBG_CTOR(SfxSizeItem, 0);
}

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

SfxSizeItem::SfxSizeItem( sal_uInt16 nW, const Size& rVal ) :
    SfxPoolItem( nW ),
    aVal( rVal )
{
    DBG_CTOR(SfxSizeItem, 0);
}

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

SfxSizeItem::SfxSizeItem( const SfxSizeItem& rItem ) :
    SfxPoolItem( rItem ),
    aVal( rItem.aVal )
{
    DBG_CTOR(SfxSizeItem, 0);
}

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

SfxItemPresentation SfxSizeItem::GetPresentation
(
    SfxItemPresentation     /*ePresentation*/,
    SfxMapUnit              /*eCoreMetric*/,
    SfxMapUnit              /*ePresentationMetric*/,
    XubString&              rText,
    const IntlWrapper *
)   const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    rText = UniString::CreateFromInt32(aVal.Width());
    rText.AppendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
    rText += UniString::CreateFromInt32(aVal.Height());
    rText.AppendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
    return SFX_ITEM_PRESENTATION_NAMELESS;
}

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

int SfxSizeItem::operator==( const SfxPoolItem& rItem ) const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    DBG_ASSERT( SfxPoolItem::operator==( rItem ), "unequal type" );
    return ((SfxSizeItem&)rItem).aVal == aVal;
}

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

SfxPoolItem* SfxSizeItem::Clone(SfxItemPool *) const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    return new SfxSizeItem( *this );
}

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

SfxPoolItem* SfxSizeItem::Create(SvStream &rStream, sal_uInt16 ) const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    Size aStr;
    rStream >> aStr;
    return new SfxSizeItem(Which(), aStr);
}

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

SvStream& SfxSizeItem::Store(SvStream &rStream, sal_uInt16 ) const
{
    DBG_CHKTHIS(SfxSizeItem, 0);
    rStream << aVal;
    return rStream;
}

// -----------------------------------------------------------------------
bool  SfxSizeItem::QueryValue( com::sun::star::uno::Any& rVal,
                               sal_uInt8 nMemberId ) const
{
    sal_Bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
    nMemberId &= ~CONVERT_TWIPS;

    Size aTmp(aVal);
    if( bConvert )
    {
        aTmp.Height() = ( aTmp.Height() * 127 + 36) / 72;
        aTmp.Width() = ( aTmp.Width() * 127 + 36) / 72;
    }

    switch ( nMemberId )
    {
        case 0:
        {
            rVal <<= com::sun::star::awt::Size( aTmp.getWidth(), aTmp.getHeight() );
            break;
        }
        case MID_WIDTH:
            rVal <<= aTmp.getWidth(); break;
        case MID_HEIGHT:
            rVal <<= aTmp.getHeight(); break;
    default: OSL_FAIL("Wrong MemberId!"); return false;
    }

    return true;
}

// -----------------------------------------------------------------------
bool SfxSizeItem::PutValue( const com::sun::star::uno::Any& rVal,
                            sal_uInt8 nMemberId )
{
    sal_Bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
    nMemberId &= ~CONVERT_TWIPS;

    bool bRet = false;
    com::sun::star::awt::Size aValue;
    if ( !nMemberId )
        bRet = ( rVal >>= aValue );
    else
    {
        sal_Int32 nVal = 0;
        bRet = ( rVal >>= nVal );
        if ( nMemberId == MID_WIDTH )
        {
            aValue.Width = nVal;
            aValue.Height = aVal.Height();
        }
        else
        {
            aValue.Height = nVal;
            aValue.Width = aVal.Width();
        }
    }

    if ( bRet )
    {
        Size aTmp( aValue.Width, aValue.Height );
        if( bConvert )
        {
            aTmp.Height() = ( aTmp.Height() * 72 + 63) / 127;
            aTmp.Width() = ( aTmp.Width() * 72 + 63) / 127;
        }

        aVal = aTmp;
    }

    return bRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/******************************************************************************
* Copyright (c) 2012, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Consulting LLC nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#include <pdal/GlobalEnvironment.hpp>

#ifdef PDAL_HAVE_PYTHON
#include <pdal/plang/PythonEnvironment.hpp>
#endif

#ifdef PDAL_HAVE_GDAL
#include <pdal/GDALUtils.hpp>
#endif

namespace pdal
{

//
// static functions
//

static GlobalEnvironment* t = 0;
static boost::once_flag flag = BOOST_ONCE_INIT;

GlobalEnvironment& GlobalEnvironment::get()
{
    boost::call_once(init, flag);
    return *t;
}

void GlobalEnvironment::startup()
{
    if (t != 0) // sanity check
    {
        throw pdal_error("attempt to reinitialize global environment");
    }

    get();
}

void GlobalEnvironment::shutdown()
{
    if (t == 0) // sanity check
    {
        throw pdal_error("bad global shutdown call -- was called more than once or was called without corresponding startup");
    }

    delete t;
    t = 0;

    return;
}

void GlobalEnvironment::init()
{
    t = new GlobalEnvironment();
}

//
// regular member functions
//

GlobalEnvironment::GlobalEnvironment()
: m_pythonEnvironment(0)
, m_bIsGDALInitialized(false)
, m_gdal_debug(0)
{
    // this should be the not-a-thread thread environment
    (void) createThreadEnvironment(boost::thread::id());

    return;
}

void GlobalEnvironment::getGDALEnvironment()
{
#ifdef PDAL_HAVE_GDAL
    if (!m_bIsGDALInitialized)
    {
        (void) GDALAllRegister();
        m_bIsGDALInitialized = true;
    }
#endif
}

GlobalEnvironment::~GlobalEnvironment()
{
    while (m_threadMap.size())
    {
        thread_map::iterator iter = m_threadMap.begin();
        ThreadEnvironment* env = iter->second;
        delete env;
        m_threadMap.erase(iter);
    }

#ifdef PDAL_HAVE_PYTHON
    if (m_pythonEnvironment)
        delete m_pythonEnvironment;
    m_pythonEnvironment = 0;
#endif

#ifdef PDAL_HAVE_GDAL
    if (m_bIsGDALInitialized)
    {
        if (m_gdal_debug)
            delete m_gdal_debug;

        (void) GDALDestroyDriverManager();
        m_bIsGDALInitialized = false;
    }
#endif

    return;
}

#ifdef PDAL_HAVE_PYTHON
void GlobalEnvironment::createPythonEnvironment()
{
    m_pythonEnvironment = new pdal::plang::PythonEnvironment();
}
#endif

void GlobalEnvironment::createThreadEnvironment(boost::thread::id id)
{
    ThreadEnvironment* threadEnv = new ThreadEnvironment(id);

    if (m_threadMap.find(id) != m_threadMap.end())
    {
        throw pdal_error("thread already registered");
    }

    m_threadMap.insert( std::make_pair(id, threadEnv ) );
}

ThreadEnvironment& GlobalEnvironment::getThreadEnvironment(boost::thread::id id)
{
    thread_map::iterator iter =  m_threadMap.find(id);
    if (iter == m_threadMap.end())
        throw pdal_error("bad thread id!");

    ThreadEnvironment* threadEnv = iter->second;

    return *threadEnv;
}

plang::PythonEnvironment& GlobalEnvironment::getPythonEnvironment()
{
#ifdef PDAL_HAVE_PYTHON
    if (!m_pythonEnvironment)
        (void) createPythonEnvironment();
#endif

    if (m_pythonEnvironment)
        return *m_pythonEnvironment;
    else
        throw pdal_error("Unable to initialize the Python environment!");
}

pdal::gdal::GlobalDebug* GlobalEnvironment::getGDALDebug()
{
    getGDALEnvironment();

    if (m_gdal_debug == 0)
        m_gdal_debug = new pdal::gdal::GlobalDebug();

    return m_gdal_debug;
}

boost::random::mt19937* GlobalEnvironment::getRNG()
{
    return getThreadEnvironment().getRNG();
}

} //namespaces
<commit_msg>check that the RNG being returned exists<commit_after>/******************************************************************************
* Copyright (c) 2012, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Consulting LLC nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#include <pdal/GlobalEnvironment.hpp>

#ifdef PDAL_HAVE_PYTHON
#include <pdal/plang/PythonEnvironment.hpp>
#endif

#ifdef PDAL_HAVE_GDAL
#include <pdal/GDALUtils.hpp>
#endif

namespace pdal
{

//
// static functions
//

static GlobalEnvironment* t = 0;
static boost::once_flag flag = BOOST_ONCE_INIT;

GlobalEnvironment& GlobalEnvironment::get()
{
    boost::call_once(init, flag);
    return *t;
}

void GlobalEnvironment::startup()
{
    if (t != 0) // sanity check
    {
        throw pdal_error("attempt to reinitialize global environment");
    }

    get();
}

void GlobalEnvironment::shutdown()
{
    if (t == 0) // sanity check
    {
        throw pdal_error("bad global shutdown call -- was called more than once or was called without corresponding startup");
    }

    delete t;
    t = 0;

    return;
}

void GlobalEnvironment::init()
{
    t = new GlobalEnvironment();
}

//
// regular member functions
//

GlobalEnvironment::GlobalEnvironment()
: m_pythonEnvironment(0)
, m_bIsGDALInitialized(false)
, m_gdal_debug(0)
{
    // this should be the not-a-thread thread environment
    (void) createThreadEnvironment(boost::thread::id());

    return;
}

void GlobalEnvironment::getGDALEnvironment()
{
#ifdef PDAL_HAVE_GDAL
    if (!m_bIsGDALInitialized)
    {
        (void) GDALAllRegister();
        m_bIsGDALInitialized = true;
    }
#endif
}

GlobalEnvironment::~GlobalEnvironment()
{
    while (m_threadMap.size())
    {
        thread_map::iterator iter = m_threadMap.begin();
        ThreadEnvironment* env = iter->second;
        delete env;
        m_threadMap.erase(iter);
    }

#ifdef PDAL_HAVE_PYTHON
    if (m_pythonEnvironment)
        delete m_pythonEnvironment;
    m_pythonEnvironment = 0;
#endif

#ifdef PDAL_HAVE_GDAL
    if (m_bIsGDALInitialized)
    {
        if (m_gdal_debug)
            delete m_gdal_debug;

        (void) GDALDestroyDriverManager();
        m_bIsGDALInitialized = false;
    }
#endif

    return;
}

#ifdef PDAL_HAVE_PYTHON
void GlobalEnvironment::createPythonEnvironment()
{
    m_pythonEnvironment = new pdal::plang::PythonEnvironment();
}
#endif

void GlobalEnvironment::createThreadEnvironment(boost::thread::id id)
{
    ThreadEnvironment* threadEnv = new ThreadEnvironment(id);

    if (m_threadMap.find(id) != m_threadMap.end())
    {
        throw pdal_error("thread already registered");
    }

    m_threadMap.insert( std::make_pair(id, threadEnv ) );
}

ThreadEnvironment& GlobalEnvironment::getThreadEnvironment(boost::thread::id id)
{
    thread_map::iterator iter =  m_threadMap.find(id);
    if (iter == m_threadMap.end())
        throw pdal_error("bad thread id!");

    ThreadEnvironment* threadEnv = iter->second;

    return *threadEnv;
}

plang::PythonEnvironment& GlobalEnvironment::getPythonEnvironment()
{
#ifdef PDAL_HAVE_PYTHON
    if (!m_pythonEnvironment)
        (void) createPythonEnvironment();
#endif

    if (m_pythonEnvironment)
        return *m_pythonEnvironment;
    else
        throw pdal_error("Unable to initialize the Python environment!");
}

pdal::gdal::GlobalDebug* GlobalEnvironment::getGDALDebug()
{
    getGDALEnvironment();

    if (m_gdal_debug == 0)
        m_gdal_debug = new pdal::gdal::GlobalDebug();

    return m_gdal_debug;
}

boost::random::mt19937* GlobalEnvironment::getRNG()
{
    boost::random::mt19937* rng = getThreadEnvironment().getRNG();
    if (!rng)
        throw pdal_error("ThreadEnvironment RNG was null!");

    return rng;
}

} //namespaces
<|endoftext|>