<commit_before>/*
  This file is part of KOrganizer.

  Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>

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

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

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

// ArchiveDialog -- archive/delete past events.

#include "archivedialog.h"
#include "koprefs.h"
#include "eventarchiver.h"

#include <libkdepim/kdateedit.h>

#include <kdebug.h>
#include <klocale.h>
#include <knuminput.h>
#include <kurlrequester.h>
#include <kmessagebox.h>
#include <kfiledialog.h>
#include <kurl.h>
#include <klineedit.h>
#include <kvbox.h>
#include <KComboBox>
#include <KTextBrowser>

#include <QLabel>
#include <QLayout>
#include <QDateTime>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QFrame>
#include <QHBoxLayout>
#include <QButtonGroup>
#include <QRadioButton>

#include "archivedialog.moc"

ArchiveDialog::ArchiveDialog( Calendar *cal, QWidget *parent )
  : KDialog (parent)
{
  setCaption( i18nc( "@title:window", "Archive/Delete Past Events and To-dos" ) );
  setButtons( User1|Cancel );
  setDefaultButton( User1 );
  setModal( false );
  showButtonSeparator( true );
  setButtonText( User1, i18nc( "@action:button", "&Archive" ) );
  mCalendar = cal;

  QFrame *topFrame = new QFrame( this );
  setMainWidget( topFrame );
  QVBoxLayout *topLayout = new QVBoxLayout( topFrame );
  topLayout->setSpacing( spacingHint() );

  KTextBrowser *descLabel = new KTextBrowser( topFrame );
  descLabel->setText(
    i18nc( "@info:whatsthis",
           "Archiving saves old items into the given file and "
           "then deletes them in the current calendar. If the archive file "
           "already exists they will be added. "
           "(<link url=\"whatsthis:In order to add an archive "
           "to your calendar, use the "Merge Calendar" function. "
           "You can view an archive by opening it in KOrganizer like any "
           "other calendar. It is not saved in a special format, but as "
           "vCalendar.\">How to restore</link>)" ) );
  descLabel->setTextInteractionFlags(
    Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard |
    Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard );
  topLayout->addWidget( descLabel );

  QButtonGroup *radioBG = new QButtonGroup( this );
  connect( radioBG, SIGNAL(buttonClicked(int)), SLOT(slotActionChanged()) );

  QHBoxLayout *dateLayout = new QHBoxLayout();
  dateLayout->setMargin( 0 );
  mArchiveOnceRB =
    new QRadioButton( i18nc( "@option:radio", "Archive now items older than:" ),
                      topFrame );
  dateLayout->addWidget( mArchiveOnceRB );
  radioBG->addButton( mArchiveOnceRB );
  mDateEdit = new KPIM::KDateEdit( topFrame );
  mDateEdit->setWhatsThis(
    i18nc( "@info:whatsthis",
           "The date before which items should be archived. All older events "
           "and to-dos will be saved and deleted, the newer (and events "
           "exactly on that date) will be kept." ) );
  dateLayout->addWidget( mDateEdit );
  topLayout->addLayout( dateLayout );

  // Checkbox, numinput and combo for auto-archiving (similar to kmail's
  // mExpireFolderCheckBox/mReadExpiryTimeNumInput in kmfolderdia.cpp)
  KHBox *autoArchiveHBox = new KHBox( topFrame );
  topLayout->addWidget( autoArchiveHBox );
  mAutoArchiveRB =
    new QRadioButton( i18nc( "@option:radio", "Automaticall&y archive items older than:" ),
                      autoArchiveHBox );
  radioBG->addButton( mAutoArchiveRB );
  mAutoArchiveRB->setWhatsThis(
    i18nc( "@info:whatsthis",
           "If this feature is enabled, KOrganizer will regularly check if "
           "events and to-dos have to be archived; this means you will not "
           "need to use this dialog box again, except to change the settings." ) );

  mExpiryTimeNumInput = new KIntNumInput( autoArchiveHBox );
  mExpiryTimeNumInput->setRange( 1, 500, 1 );
  mExpiryTimeNumInput->setSliderEnabled( false );
  mExpiryTimeNumInput->setEnabled( false );
  mExpiryTimeNumInput->setValue( 7 );
  mExpiryTimeNumInput->setWhatsThis(
    i18nc( "@info:whatsthis",
           "The age of the events and to-dos to archive. All older items "
           "will be saved and deleted, the newer will be kept." ) );

  mExpiryUnitsComboBox = new KComboBox( autoArchiveHBox );
  // Those items must match the "Expiry Unit" enum in the kcfg file!
  mExpiryUnitsComboBox->addItem(
    i18nc( "@item:inlistbox expires in daily units", "Day(s)" ) );
  mExpiryUnitsComboBox->addItem(
    i18nc( "@item:inlistbox expiration in weekly units", "Week(s)" ) );
  mExpiryUnitsComboBox->addItem(
    i18nc( "@item:inlistbox expiration in monthly units", "Month(s)" ) );
  mExpiryUnitsComboBox->setEnabled( false );

  QHBoxLayout *fileLayout = new QHBoxLayout();
  fileLayout->setMargin( 0 );
  fileLayout->setSpacing( spacingHint() );
  QLabel *l = new QLabel( i18nc( "@label", "Archive &file:" ), topFrame );
  fileLayout->addWidget(l);
  mArchiveFile = new KUrlRequester( KOPrefs::instance()->mArchiveFile, topFrame );
  mArchiveFile->setMode( KFile::File );
  mArchiveFile->setFilter( i18nc( "@label filter for KUrlRequester", "*.ics|iCalendar Files" ) );
  mArchiveFile->setWhatsThis(
    i18nc( "@info:whatsthis",
           "The path of the archive. The events and to-dos will be added to "
           "the archive file, so any events that are already in the file "
           "will not be modified or deleted. You can later load or merge the "
           "file like any other calendar. It is not saved in a special "
           "format, it uses the iCalendar format." ) );
  l->setBuddy( mArchiveFile->lineEdit() );
  fileLayout->addWidget( mArchiveFile );
  topLayout->addLayout( fileLayout );

  QGroupBox *typeBox = new QGroupBox( i18nc( "@title:group", "Type of Items to Archive" ) );
  topLayout->addWidget( typeBox );

  QBoxLayout *typeLayout = new QVBoxLayout( typeBox );

  mEvents = new QCheckBox( i18nc( "@option:check", "&Events" ) );
  typeLayout->addWidget( mEvents );
  mTodos = new QCheckBox( i18nc( "@option:check", "&To-dos" ) );
  typeLayout->addWidget( mTodos );
  typeBox->setWhatsThis(
    i18nc( "@info:whatsthis",
           "Here you can select which items "
           "should be archived. Events are archived if they "
           "ended before the date given above; to-dos are archived if "
           "they were finished before the date." ) );

  mDeleteCb = new QCheckBox( i18nc( "@option:check", "&Delete only, do not save" ), topFrame );
  mDeleteCb->setWhatsThis(
    i18nc( "@info:whatsthis",
           "Select this option to delete old events and to-dos without saving "
           "them. It is not possible to recover the events later." ) );
  topLayout->addWidget(mDeleteCb);
  connect( mDeleteCb, SIGNAL(toggled(bool)), mArchiveFile, SLOT(setDisabled(bool)) );
  connect( mDeleteCb, SIGNAL(toggled(bool)), this, SLOT(slotEnableUser1()) );
  connect( mArchiveFile->lineEdit(), SIGNAL(textChanged(const QString &)),
           this, SLOT(slotEnableUser1()) );

  // Load settings from KOPrefs
  mExpiryTimeNumInput->setValue( KOPrefs::instance()->mExpiryTime );
  mExpiryUnitsComboBox->setCurrentIndex( KOPrefs::instance()->mExpiryUnit );
  mDeleteCb->setChecked( KOPrefs::instance()->mArchiveAction == KOPrefs::actionDelete );
  mEvents->setChecked( KOPrefs::instance()->mArchiveEvents );
  mTodos->setChecked( KOPrefs::instance()->mArchiveTodos );

  slotEnableUser1();

  // The focus should go to a useful field by default, not to the top richtext-label
  if ( KOPrefs::instance()->mAutoArchive ) {
    mAutoArchiveRB->setChecked( true );
    mAutoArchiveRB->setFocus();
  } else {
    mArchiveOnceRB->setChecked( true );
    mArchiveOnceRB->setFocus();
  }
  slotActionChanged();
  connect( this, SIGNAL(user1Clicked()), this, SLOT(slotUser1()) );
}

ArchiveDialog::~ArchiveDialog()
{
}

void ArchiveDialog::slotEnableUser1()
{
  bool state = ( mDeleteCb->isChecked() || !mArchiveFile->lineEdit()->text().isEmpty() );
  enableButton( KDialog::User1, state );
}

void ArchiveDialog::slotActionChanged()
{
  mDateEdit->setEnabled( mArchiveOnceRB->isChecked() );
  mExpiryTimeNumInput->setEnabled( mAutoArchiveRB->isChecked() );
  mExpiryUnitsComboBox->setEnabled( mAutoArchiveRB->isChecked() );
}

// Archive old events
void ArchiveDialog::slotUser1()
{
  EventArchiver archiver;
  connect( &archiver, SIGNAL(eventsDeleted()), this, SLOT(slotEventsDeleted()) );

  KOPrefs::instance()->mAutoArchive = mAutoArchiveRB->isChecked();
  KOPrefs::instance()->mExpiryTime = mExpiryTimeNumInput->value();
  KOPrefs::instance()->mExpiryUnit = mExpiryUnitsComboBox->currentIndex();

  if ( mDeleteCb->isChecked() ) {
    KOPrefs::instance()->mArchiveAction = KOPrefs::actionDelete;
  } else {
    KOPrefs::instance()->mArchiveAction = KOPrefs::actionArchive;

    // Get destination URL
    KUrl destUrl( mArchiveFile->url() );
    if ( !destUrl.isValid() ) {
      KMessageBox::sorry( this, i18nc( "@info", "The archive file name is not valid." ) );
      return;
    }
    // Force filename to be ending with vCalendar extension
    QString filename = destUrl.fileName();
    if ( !filename.endsWith( QLatin1String( ".vcs" ) ) &&
         !filename.endsWith( QLatin1String( ".ics" ) ) ) {
      filename.append( QLatin1String( ".ics" ) );
      destUrl.setFileName( filename );
    }

    KOPrefs::instance()->mArchiveFile = destUrl.url();
  }
  if ( KOPrefs::instance()->mAutoArchive ) {
    archiver.runAuto( mCalendar, this, true /*with gui*/);
    emit autoArchivingSettingsModified();
    accept();
  } else {
    archiver.runOnce( mCalendar, mDateEdit->date(), this );
  }
}

void ArchiveDialog::slotEventsDeleted()
{
  emit eventsDeleted();
  if ( !KOPrefs::instance()->mAutoArchive ) {
    accept();
  }
}
<commit_msg>" breaks tooltips<commit_after>/*
  This file is part of KOrganizer.

  Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>

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

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

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

// ArchiveDialog -- archive/delete past events.

#include "archivedialog.h"
#include "koprefs.h"
#include "eventarchiver.h"

#include <libkdepim/kdateedit.h>

#include <kdebug.h>
#include <klocale.h>
#include <knuminput.h>
#include <kurlrequester.h>
#include <kmessagebox.h>
#include <kfiledialog.h>
#include <kurl.h>
#include <klineedit.h>
#include <kvbox.h>
#include <KComboBox>
#include <KTextBrowser>

#include <QLabel>
#include <QLayout>
#include <QDateTime>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QFrame>
#include <QHBoxLayout>
#include <QButtonGroup>
#include <QRadioButton>

#include "archivedialog.moc"

ArchiveDialog::ArchiveDialog( Calendar *cal, QWidget *parent )
  : KDialog (parent)
{
  setCaption( i18nc( "@title:window", "Archive/Delete Past Events and To-dos" ) );
  setButtons( User1|Cancel );
  setDefaultButton( User1 );
  setModal( false );
  showButtonSeparator( true );
  setButtonText( User1, i18nc( "@action:button", "&Archive" ) );
  mCalendar = cal;

  QFrame *topFrame = new QFrame( this );
  setMainWidget( topFrame );
  QVBoxLayout *topLayout = new QVBoxLayout( topFrame );
  topLayout->setSpacing( spacingHint() );

  KTextBrowser *descLabel = new KTextBrowser( topFrame );
  descLabel->setText(
    i18nc( "@info:whatsthis",
           "Archiving saves old items into the given file and "
           "then deletes them in the current calendar. If the archive file "
           "already exists they will be added. "
           "(<link url=\"whatsthis:In order to add an archive "
           "to your calendar, use the Merge Calendar function. "
           "You can view an archive by opening it in KOrganizer like any "
           "other calendar. It is not saved in a special format, but as "
           "vCalendar.\">How to restore</link>)" ) );
  descLabel->setTextInteractionFlags(
    Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard |
    Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard );
  topLayout->addWidget( descLabel );

  QButtonGroup *radioBG = new QButtonGroup( this );
  connect( radioBG, SIGNAL(buttonClicked(int)), SLOT(slotActionChanged()) );

  QHBoxLayout *dateLayout = new QHBoxLayout();
  dateLayout->setMargin( 0 );
  mArchiveOnceRB =
    new QRadioButton( i18nc( "@option:radio", "Archive now items older than:" ),
                      topFrame );
  dateLayout->addWidget( mArchiveOnceRB );
  radioBG->addButton( mArchiveOnceRB );
  mDateEdit = new KPIM::KDateEdit( topFrame );
  mDateEdit->setWhatsThis(
    i18nc( "@info:whatsthis",
           "The date before which items should be archived. All older events "
           "and to-dos will be saved and deleted, the newer (and events "
           "exactly on that date) will be kept." ) );
  dateLayout->addWidget( mDateEdit );
  topLayout->addLayout( dateLayout );

  // Checkbox, numinput and combo for auto-archiving (similar to kmail's
  // mExpireFolderCheckBox/mReadExpiryTimeNumInput in kmfolderdia.cpp)
  KHBox *autoArchiveHBox = new KHBox( topFrame );
  topLayout->addWidget( autoArchiveHBox );
  mAutoArchiveRB =
    new QRadioButton( i18nc( "@option:radio", "Automaticall&y archive items older than:" ),
                      autoArchiveHBox );
  radioBG->addButton( mAutoArchiveRB );
  mAutoArchiveRB->setWhatsThis(
    i18nc( "@info:whatsthis",
           "If this feature is enabled, KOrganizer will regularly check if "
           "events and to-dos have to be archived; this means you will not "
           "need to use this dialog box again, except to change the settings." ) );

  mExpiryTimeNumInput = new KIntNumInput( autoArchiveHBox );
  mExpiryTimeNumInput->setRange( 1, 500, 1 );
  mExpiryTimeNumInput->setSliderEnabled( false );
  mExpiryTimeNumInput->setEnabled( false );
  mExpiryTimeNumInput->setValue( 7 );
  mExpiryTimeNumInput->setWhatsThis(
    i18nc( "@info:whatsthis",
           "The age of the events and to-dos to archive. All older items "
           "will be saved and deleted, the newer will be kept." ) );

  mExpiryUnitsComboBox = new KComboBox( autoArchiveHBox );
  // Those items must match the "Expiry Unit" enum in the kcfg file!
  mExpiryUnitsComboBox->addItem(
    i18nc( "@item:inlistbox expires in daily units", "Day(s)" ) );
  mExpiryUnitsComboBox->addItem(
    i18nc( "@item:inlistbox expiration in weekly units", "Week(s)" ) );
  mExpiryUnitsComboBox->addItem(
    i18nc( "@item:inlistbox expiration in monthly units", "Month(s)" ) );
  mExpiryUnitsComboBox->setEnabled( false );

  QHBoxLayout *fileLayout = new QHBoxLayout();
  fileLayout->setMargin( 0 );
  fileLayout->setSpacing( spacingHint() );
  QLabel *l = new QLabel( i18nc( "@label", "Archive &file:" ), topFrame );
  fileLayout->addWidget(l);
  mArchiveFile = new KUrlRequester( KOPrefs::instance()->mArchiveFile, topFrame );
  mArchiveFile->setMode( KFile::File );
  mArchiveFile->setFilter( i18nc( "@label filter for KUrlRequester", "*.ics|iCalendar Files" ) );
  mArchiveFile->setWhatsThis(
    i18nc( "@info:whatsthis",
           "The path of the archive. The events and to-dos will be added to "
           "the archive file, so any events that are already in the file "
           "will not be modified or deleted. You can later load or merge the "
           "file like any other calendar. It is not saved in a special "
           "format, it uses the iCalendar format." ) );
  l->setBuddy( mArchiveFile->lineEdit() );
  fileLayout->addWidget( mArchiveFile );
  topLayout->addLayout( fileLayout );

  QGroupBox *typeBox = new QGroupBox( i18nc( "@title:group", "Type of Items to Archive" ) );
  topLayout->addWidget( typeBox );

  QBoxLayout *typeLayout = new QVBoxLayout( typeBox );

  mEvents = new QCheckBox( i18nc( "@option:check", "&Events" ) );
  typeLayout->addWidget( mEvents );
  mTodos = new QCheckBox( i18nc( "@option:check", "&To-dos" ) );
  typeLayout->addWidget( mTodos );
  typeBox->setWhatsThis(
    i18nc( "@info:whatsthis",
           "Here you can select which items "
           "should be archived. Events are archived if they "
           "ended before the date given above; to-dos are archived if "
           "they were finished before the date." ) );

  mDeleteCb = new QCheckBox( i18nc( "@option:check", "&Delete only, do not save" ), topFrame );
  mDeleteCb->setWhatsThis(
    i18nc( "@info:whatsthis",
           "Select this option to delete old events and to-dos without saving "
           "them. It is not possible to recover the events later." ) );
  topLayout->addWidget(mDeleteCb);
  connect( mDeleteCb, SIGNAL(toggled(bool)), mArchiveFile, SLOT(setDisabled(bool)) );
  connect( mDeleteCb, SIGNAL(toggled(bool)), this, SLOT(slotEnableUser1()) );
  connect( mArchiveFile->lineEdit(), SIGNAL(textChanged(const QString &)),
           this, SLOT(slotEnableUser1()) );

  // Load settings from KOPrefs
  mExpiryTimeNumInput->setValue( KOPrefs::instance()->mExpiryTime );
  mExpiryUnitsComboBox->setCurrentIndex( KOPrefs::instance()->mExpiryUnit );
  mDeleteCb->setChecked( KOPrefs::instance()->mArchiveAction == KOPrefs::actionDelete );
  mEvents->setChecked( KOPrefs::instance()->mArchiveEvents );
  mTodos->setChecked( KOPrefs::instance()->mArchiveTodos );

  slotEnableUser1();

  // The focus should go to a useful field by default, not to the top richtext-label
  if ( KOPrefs::instance()->mAutoArchive ) {
    mAutoArchiveRB->setChecked( true );
    mAutoArchiveRB->setFocus();
  } else {
    mArchiveOnceRB->setChecked( true );
    mArchiveOnceRB->setFocus();
  }
  slotActionChanged();
  connect( this, SIGNAL(user1Clicked()), this, SLOT(slotUser1()) );
}

ArchiveDialog::~ArchiveDialog()
{
}

void ArchiveDialog::slotEnableUser1()
{
  bool state = ( mDeleteCb->isChecked() || !mArchiveFile->lineEdit()->text().isEmpty() );
  enableButton( KDialog::User1, state );
}

void ArchiveDialog::slotActionChanged()
{
  mDateEdit->setEnabled( mArchiveOnceRB->isChecked() );
  mExpiryTimeNumInput->setEnabled( mAutoArchiveRB->isChecked() );
  mExpiryUnitsComboBox->setEnabled( mAutoArchiveRB->isChecked() );
}

// Archive old events
void ArchiveDialog::slotUser1()
{
  EventArchiver archiver;
  connect( &archiver, SIGNAL(eventsDeleted()), this, SLOT(slotEventsDeleted()) );

  KOPrefs::instance()->mAutoArchive = mAutoArchiveRB->isChecked();
  KOPrefs::instance()->mExpiryTime = mExpiryTimeNumInput->value();
  KOPrefs::instance()->mExpiryUnit = mExpiryUnitsComboBox->currentIndex();

  if ( mDeleteCb->isChecked() ) {
    KOPrefs::instance()->mArchiveAction = KOPrefs::actionDelete;
  } else {
    KOPrefs::instance()->mArchiveAction = KOPrefs::actionArchive;

    // Get destination URL
    KUrl destUrl( mArchiveFile->url() );
    if ( !destUrl.isValid() ) {
      KMessageBox::sorry( this, i18nc( "@info", "The archive file name is not valid." ) );
      return;
    }
    // Force filename to be ending with vCalendar extension
    QString filename = destUrl.fileName();
    if ( !filename.endsWith( QLatin1String( ".vcs" ) ) &&
         !filename.endsWith( QLatin1String( ".ics" ) ) ) {
      filename.append( QLatin1String( ".ics" ) );
      destUrl.setFileName( filename );
    }

    KOPrefs::instance()->mArchiveFile = destUrl.url();
  }
  if ( KOPrefs::instance()->mAutoArchive ) {
    archiver.runAuto( mCalendar, this, true /*with gui*/);
    emit autoArchivingSettingsModified();
    accept();
  } else {
    archiver.runOnce( mCalendar, mDateEdit->date(), this );
  }
}

void ArchiveDialog::slotEventsDeleted()
{
  emit eventsDeleted();
  if ( !KOPrefs::instance()->mAutoArchive ) {
    accept();
  }
}
<|endoftext|>


<commit_before>/* KPilot
**
** Copyright (C) 1998-2001 by Dan Pilone <dan@kpilot.org>
** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
**
** This is a C++ wrapper for the Pilot's datebook structures.
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/
#include "pilotDateEntry.h"

#include <stdlib.h>

#include <QtCore/QDateTime>
#include <QtCore/QRegExp>

#include <kglobal.h>

#include <config-kpilot.h>

#include "options.h"

static const char *default_date_category_names[] = {
	"Unfiled",
	"Business",
	"Personal",
	0L
} ;

void PilotDateInfo::resetToDefault()
{
	FUNCTIONSETUP;
	// Reset to all 0s
	memset(&fInfo,0,sizeof(fInfo));
	// Fill up default categories
	for (unsigned int i=0; (i<4) && default_date_category_names[i]; ++i)
	{
		strncpy(fInfo.category.name[i],default_date_category_names[i],sizeof(fInfo.category.name[0]));
	}

	fInfo.startOfWeek = 0;

}

PilotDateEntry::PilotDateEntry():PilotRecordBase()
{
	::memset(&fAppointmentInfo, 0, sizeof(struct Appointment));
}

/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDateEntry()
*/
PilotDateEntry::PilotDateEntry(PilotRecord * rec) :
	PilotRecordBase(rec)
{
	::memset(&fAppointmentInfo, 0, sizeof(fAppointmentInfo));
	if (rec)
	{
		// Construct a fake pi_buffer for unpack_Appointment.
		// No ownership changes occur here.
		pi_buffer_t b = { (unsigned char *) rec->data(), rec->size(), rec->size() } ;
		unpack_Appointment(&fAppointmentInfo, &b, datebook_v1);
	}
	return;

}

void PilotDateEntry::_copyExceptions(const PilotDateEntry & e)
{
	if (e.fAppointmentInfo.exceptions > 0)
	{
		size_t blocksize = e.fAppointmentInfo.exceptions *
			sizeof(struct tm);

		fAppointmentInfo.exception = (struct tm *)::malloc(blocksize);

		if (fAppointmentInfo.exception)
		{
			fAppointmentInfo.exceptions =
				e.fAppointmentInfo.exceptions;
			::memcpy(fAppointmentInfo.exception,
				e.fAppointmentInfo.exception, blocksize);
		}
		else
		{
			WARNINGKPILOT << "malloc() failed, exceptions not copied";
			fAppointmentInfo.exceptions = 0;
		}
	}
	else
	{
		fAppointmentInfo.exceptions = 0;
		fAppointmentInfo.exception = 0L;
	}
}

PilotDateEntry::PilotDateEntry(const PilotDateEntry & e) :
	PilotRecordBase(e)
{
	::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
		sizeof(struct Appointment));
	// See operator = for explanation
	fAppointmentInfo.exception = 0L;
	fAppointmentInfo.description = 0L;
	fAppointmentInfo.note = 0L;

	_copyExceptions(e);
	setDescriptionP(e.fAppointmentInfo.description);
	setNoteP(e.fAppointmentInfo.note);
}

PilotDateEntry & PilotDateEntry::operator = (const PilotDateEntry & e)
{
	if (this != &e)		// Pointer equality!
	{
		KPILOT_FREE(fAppointmentInfo.exception);
		KPILOT_FREE(fAppointmentInfo.description);
		KPILOT_FREE(fAppointmentInfo.note);
		::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
			sizeof(fAppointmentInfo));

		// The original pointers were already freed; since we're now
		// got the pointers from the new structure and we're going
		// to use the standard set functions make sure that
		// we don't free() the copies-of-pointers from e, which
		// would be disastrous.
		//
		//
		fAppointmentInfo.exception = 0L;
		fAppointmentInfo.description = 0L;
		fAppointmentInfo.note = 0L;

		_copyExceptions(e);
		setDescriptionP(e.fAppointmentInfo.description);
		setNoteP(e.fAppointmentInfo.note);
	}

	return *this;
}				// end of assignment operator

QString PilotDateEntry::getTextRepresentation(Qt::TextFormat richText)
{
	QString text, tmp;
	QString par = (richText==Qt::RichText) ?CSL1("
"):QString();
	QString ps = (richText==Qt::RichText) ?CSL1("
"):CSL1("\n");
	QString br = (richText==Qt::RichText) ?CSL1("
"):CSL1("\n");

	// title + name
	text += par;
	tmp=richText?CSL1("<big>%1</big>"):CSL1("%1");
	text += tmp.arg(rtExpand(getDescription(), richText));
	text += ps;

	QDateTime dt(readTm(getEventStart()));
	QString startDate(dt.toString(Qt::LocalDate));
	text+=par;
	text+=i18n("Start date: %1",startDate);
	text+=ps;

	if (isEvent())
	{
		text+=par;
		text+=i18n("Whole-day event");
		text+=ps;
	}
	else
	{
		dt=readTm(getEventEnd());
		QString endDate(dt.toString(Qt::LocalDate));
		text+=par;
		text+=i18n("End date: %1",endDate);
		text+=ps;
	}

	if ( isAlarmEnabled() )
	{
		text+=par;
		QString tmpArg;
		switch (getAdvanceUnits())
		{
			case advMinutes: tmpArg = i18n("minutes"); break;
			case advHours: tmpArg = i18n("hours"); break;
			case advDays: tmpArg = i18n("days"); break;
			default: tmpArg.clear(); break;
		}
		tmp=i18nc("%1 is the duration, %2 is the time unit", "Alarm: %1 %2 before event starts",getAdvance(),tmpArg);
		text+=ps;
	}

	if (getRepeatType() != repeatNone)
	{
		text+=par;
		int freq = getRepeatFrequency();
		QString tmpStr;
		switch(getRepeatType())
		{
			case repeatDaily: tmpStr = i18n("day(s)"); break;
			case repeatWeekly: tmpStr = i18n("week(s)"); break;
			case repeatMonthlyByDay:
			case repeatMonthlyByDate: tmpStr = i18n("month(s)"); break;
			case repeatYearly: tmpStr = i18n("year(s)"); break;
			default: tmpStr.clear(); break;
		}
		tmp=i18n("Recurrence: every %1 %2",freq,tmpStr);
		text+=tmp;
		text+=br;

		bool repeatsForever = getRepeatForever();
		if (repeatsForever)
		{
			text+=i18n("Repeats indefinitely");
		}
		else
		{
			dt = readTm(getRepeatEnd())/*.date()*/;
			text+=i18n("Until %1",dt.toString(Qt::LocalDate));
		}
		text+=br;

		if (getRepeatType()==repeatMonthlyByDay) text+=i18n("Repeating on the i-th day of week j")+br;
		if (getRepeatType()==repeatMonthlyByDate) text+=i18n("Repeating on the n-th day of the month")+br;
		// TODO: show the dayArray when repeating weekly
		/*QBitArray dayArray(7);
		if (getRepeatType()==repeatWeekly) text+=i18n("Repeat day flags: %1").arg(getRepeatDays
		const int *days = dateEntry->getRepeatDays();
		// Rotate the days of the week, since day numbers on the Pilot and
		// in vCal / Events are different.
		if (days[0]) dayArray.setBit(6);
		for (int i = 1; i < 7; i++)
		{
			if (days[i]) dayArray.setBit(i-1);
		}*/
		text+=ps;
	}

	if (getExceptionCount()>0 )
	{
		text+=par;
		text+=i18n("Exceptions:")+br;
		for (int i = 0; i < getExceptionCount(); i++)
		{
			QDate exdt=readTm(getExceptions()[i]).date();
			text+=exdt.toString(Qt::LocalDate);
			text+=br;
		}
		text+=ps;
	}

	if (!getNote().isEmpty())
	{
		text += richText?CSL1("
"):CSL1("-------------------------\n");
		text+=par;
		text+=richText?i18n("Note:
"):i18n("Note:\n");
		text+=rtExpand(getNote(), richText);
		text+=ps;
	}

	return text;
}

QDateTime PilotDateEntry::dtStart() const
{
	FUNCTIONSETUP;
	return readTm( getEventStart() );
}

QDateTime PilotDateEntry::dtEnd() const
{
	FUNCTIONSETUP;
	return readTm( getEventEnd() );
}

QDateTime PilotDateEntry::dtRepeatEnd() const
{
	FUNCTIONSETUP;
	return readTm( getRepeatEnd() );
}

unsigned int PilotDateEntry::alarmLeadTime() const
{
	FUNCTIONSETUP;
	if (!isAlarmEnabled()) return 0;

	int adv = getAdvance();
	if ( adv < 0 )
	{
		return 0; // Not possible to enter on the pilot
	}
	unsigned int t = adv;
	int u = getAdvanceUnits();

	switch(u)
	{
	case advMinutes : t *= 60; break;
	case advHours : t *= 3600; break;
	case advDays : t *= 3600 * 24; break;
	default: t = 0;
	}

	return t;
}

PilotRecord *PilotDateEntry::pack() const
{
	int i;

	pi_buffer_t *b = pi_buffer_new( sizeof(fAppointmentInfo) );
	i = pack_Appointment(const_cast<Appointment_t *>(&fAppointmentInfo), b, datebook_v1);
	if (i<0)
	{
		// Generic error from the pack_*() functions.
		return 0;
	}

	// pack_Appointment sets b->used
	return new PilotRecord( b, this );
}

/* setExceptions sets a new set of exceptions. Note that
	PilotDateEntry assumes ownership of the array and will
	delete the old one. */
void PilotDateEntry::setExceptions(struct tm *e) {
	if (fAppointmentInfo.exception != e)
	{
		KPILOT_FREE(fAppointmentInfo.exception);
	}
	fAppointmentInfo.exception=e;
}

void PilotDateEntry::setDescriptionP(const char *desc, int l)
{
	FUNCTIONSETUP;
	KPILOT_FREE(fAppointmentInfo.description);

	if (desc && *desc)
	{
		if (-1 == l) l=::strlen(desc);
		fAppointmentInfo.description =
			(char *) ::malloc(l + 1);
		if (fAppointmentInfo.description)
		{
			strlcpy(fAppointmentInfo.description, desc, l+1);
		}
		else
		{
			WARNINGKPILOT << "malloc() failed, description not set";
		}
	}
	else
	{
		fAppointmentInfo.description = 0L;
	}
}

void PilotDateEntry::setNoteP(const char *note, int l)
{
	FUNCTIONSETUP;
	KPILOT_FREE(fAppointmentInfo.note);

	if (note && *note)
	{
		if (-1 == l) l=::strlen(note);
		fAppointmentInfo.note = (char *)::malloc(l + 1);
		if (fAppointmentInfo.note)
		{
			strlcpy(fAppointmentInfo.note, note,l+1);
		}
		else
		{
			WARNINGKPILOT << "malloc() failed, note not set";
		}
	}
	else
	{
		fAppointmentInfo.note = 0L;
	}
}

void PilotDateEntry::setNote(const QString &s)
{
	QByteArray t = Pilot::toPilot(s);
	setNoteP( t.data(),t.length() );
}

void PilotDateEntry::setLocation(const QString &s)
{
	QString note = Pilot::fromPilot(getNoteP());
	QRegExp rxp = QRegExp("^[Ll]ocation:[^\n]+\n");

	// per QString docs, this covers null and 0 length
	if( s.isEmpty() )
	{
		note.remove( rxp );
	}
	else
	{
		QString location = "Location: " + s + '\n';
		int pos = note.indexOf(rxp);

		if(pos >= 0)
		{
			note.replace( rxp, location );
		}
		else
		{
			note = location + note;
			setNote( note );
		}
	}
}

QString PilotDateEntry::getLocation() const
{
	// Read the complete note here and not the filtered
	// one from PilotDateEntry::getNote();
	QString note = Pilot::fromPilot(getNoteP());
	QRegExp rxp = QRegExp("^[Ll]ocation:[^\n]+\n");
	int pos = note.indexOf(rxp, 0);

	if(pos >= 0)
	{
		QString location = rxp.capturedTexts().first();
		rxp = QRegExp("^[Ll]ocation:[\\s|\t]*");
		location.remove( rxp );
		location.remove( "\n" );
		return location;
	}
	else
	{
		return "";
	}
}

void PilotDateEntry::setDescription(const QString &s)
{
	QByteArray t = Pilot::toPilot(s);
	setDescriptionP( t.data(),t.length() );
}

QString PilotDateEntry::getNote() const
{
	QString note = Pilot::fromPilot(getNoteP());
	QRegExp rxp = QRegExp("^[Ll]ocation:[^\n]+\n");
	note.remove( rxp );
	return note;
}

QString PilotDateEntry::getDescription() const
{
	return Pilot::fromPilot(getDescriptionP());
}

<commit_msg>EBN Fixes++ - single-char QString operations.<commit_after>/* KPilot
**
** Copyright (C) 1998-2001 by Dan Pilone <dan@kpilot.org>
** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
**
** This is a C++ wrapper for the Pilot's datebook structures.
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/
#include "pilotDateEntry.h"

#include <stdlib.h>

#include <QtCore/QDateTime>
#include <QtCore/QRegExp>

#include <kglobal.h>

#include <config-kpilot.h>

#include "options.h"

static const char *default_date_category_names[] = {
	"Unfiled",
	"Business",
	"Personal",
	0L
} ;

void PilotDateInfo::resetToDefault()
{
	FUNCTIONSETUP;
	// Reset to all 0s
	memset(&fInfo,0,sizeof(fInfo));
	// Fill up default categories
	for (unsigned int i=0; (i<4) && default_date_category_names[i]; ++i)
	{
		strncpy(fInfo.category.name[i],default_date_category_names[i],sizeof(fInfo.category.name[0]));
	}

	fInfo.startOfWeek = 0;

}

PilotDateEntry::PilotDateEntry():PilotRecordBase()
{
	::memset(&fAppointmentInfo, 0, sizeof(struct Appointment));
}

/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDateEntry()
*/
PilotDateEntry::PilotDateEntry(PilotRecord * rec) :
	PilotRecordBase(rec)
{
	::memset(&fAppointmentInfo, 0, sizeof(fAppointmentInfo));
	if (rec)
	{
		// Construct a fake pi_buffer for unpack_Appointment.
		// No ownership changes occur here.
		pi_buffer_t b = { (unsigned char *) rec->data(), rec->size(), rec->size() } ;
		unpack_Appointment(&fAppointmentInfo, &b, datebook_v1);
	}
	return;

}

void PilotDateEntry::_copyExceptions(const PilotDateEntry & e)
{
	if (e.fAppointmentInfo.exceptions > 0)
	{
		size_t blocksize = e.fAppointmentInfo.exceptions *
			sizeof(struct tm);

		fAppointmentInfo.exception = (struct tm *)::malloc(blocksize);

		if (fAppointmentInfo.exception)
		{
			fAppointmentInfo.exceptions =
				e.fAppointmentInfo.exceptions;
			::memcpy(fAppointmentInfo.exception,
				e.fAppointmentInfo.exception, blocksize);
		}
		else
		{
			WARNINGKPILOT << "malloc() failed, exceptions not copied";
			fAppointmentInfo.exceptions = 0;
		}
	}
	else
	{
		fAppointmentInfo.exceptions = 0;
		fAppointmentInfo.exception = 0L;
	}
}

PilotDateEntry::PilotDateEntry(const PilotDateEntry & e) :
	PilotRecordBase(e)
{
	::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
		sizeof(struct Appointment));
	// See operator = for explanation
	fAppointmentInfo.exception = 0L;
	fAppointmentInfo.description = 0L;
	fAppointmentInfo.note = 0L;

	_copyExceptions(e);
	setDescriptionP(e.fAppointmentInfo.description);
	setNoteP(e.fAppointmentInfo.note);
}

PilotDateEntry & PilotDateEntry::operator = (const PilotDateEntry & e)
{
	if (this != &e)		// Pointer equality!
	{
		KPILOT_FREE(fAppointmentInfo.exception);
		KPILOT_FREE(fAppointmentInfo.description);
		KPILOT_FREE(fAppointmentInfo.note);
		::memcpy(&fAppointmentInfo, &e.fAppointmentInfo,
			sizeof(fAppointmentInfo));

		// The original pointers were already freed; since we're now
		// got the pointers from the new structure and we're going
		// to use the standard set functions make sure that
		// we don't free() the copies-of-pointers from e, which
		// would be disastrous.
		//
		//
		fAppointmentInfo.exception = 0L;
		fAppointmentInfo.description = 0L;
		fAppointmentInfo.note = 0L;

		_copyExceptions(e);
		setDescriptionP(e.fAppointmentInfo.description);
		setNoteP(e.fAppointmentInfo.note);
	}

	return *this;
}				// end of assignment operator

QString PilotDateEntry::getTextRepresentation(Qt::TextFormat richText)
{
	QString text, tmp;
	QString par = (richText==Qt::RichText) ?CSL1("
"):QString();
	QString ps = (richText==Qt::RichText) ?CSL1("
"):CSL1("\n");
	QString br = (richText==Qt::RichText) ?CSL1("
"):CSL1("\n");

	// title + name
	text += par;
	tmp=richText?CSL1("<big>%1</big>"):CSL1("%1");
	text += tmp.arg(rtExpand(getDescription(), richText));
	text += ps;

	QDateTime dt(readTm(getEventStart()));
	QString startDate(dt.toString(Qt::LocalDate));
	text+=par;
	text+=i18n("Start date: %1",startDate);
	text+=ps;

	if (isEvent())
	{
		text+=par;
		text+=i18n("Whole-day event");
		text+=ps;
	}
	else
	{
		dt=readTm(getEventEnd());
		QString endDate(dt.toString(Qt::LocalDate));
		text+=par;
		text+=i18n("End date: %1",endDate);
		text+=ps;
	}

	if ( isAlarmEnabled() )
	{
		text+=par;
		QString tmpArg;
		switch (getAdvanceUnits())
		{
			case advMinutes: tmpArg = i18n("minutes"); break;
			case advHours: tmpArg = i18n("hours"); break;
			case advDays: tmpArg = i18n("days"); break;
			default: tmpArg.clear(); break;
		}
		tmp=i18nc("%1 is the duration, %2 is the time unit", "Alarm: %1 %2 before event starts",getAdvance(),tmpArg);
		text+=ps;
	}

	if (getRepeatType() != repeatNone)
	{
		text+=par;
		int freq = getRepeatFrequency();
		QString tmpStr;
		switch(getRepeatType())
		{
			case repeatDaily: tmpStr = i18n("day(s)"); break;
			case repeatWeekly: tmpStr = i18n("week(s)"); break;
			case repeatMonthlyByDay:
			case repeatMonthlyByDate: tmpStr = i18n("month(s)"); break;
			case repeatYearly: tmpStr = i18n("year(s)"); break;
			default: tmpStr.clear(); break;
		}
		tmp=i18n("Recurrence: every %1 %2",freq,tmpStr);
		text+=tmp;
		text+=br;

		bool repeatsForever = getRepeatForever();
		if (repeatsForever)
		{
			text+=i18n("Repeats indefinitely");
		}
		else
		{
			dt = readTm(getRepeatEnd())/*.date()*/;
			text+=i18n("Until %1",dt.toString(Qt::LocalDate));
		}
		text+=br;

		if (getRepeatType()==repeatMonthlyByDay) text+=i18n("Repeating on the i-th day of week j")+br;
		if (getRepeatType()==repeatMonthlyByDate) text+=i18n("Repeating on the n-th day of the month")+br;
		// TODO: show the dayArray when repeating weekly
		/*QBitArray dayArray(7);
		if (getRepeatType()==repeatWeekly) text+=i18n("Repeat day flags: %1").arg(getRepeatDays
		const int *days = dateEntry->getRepeatDays();
		// Rotate the days of the week, since day numbers on the Pilot and
		// in vCal / Events are different.
		if (days[0]) dayArray.setBit(6);
		for (int i = 1; i < 7; i++)
		{
			if (days[i]) dayArray.setBit(i-1);
		}*/
		text+=ps;
	}

	if (getExceptionCount()>0 )
	{
		text+=par;
		text+=i18n("Exceptions:")+br;
		for (int i = 0; i < getExceptionCount(); i++)
		{
			QDate exdt=readTm(getExceptions()[i]).date();
			text+=exdt.toString(Qt::LocalDate);
			text+=br;
		}
		text+=ps;
	}

	if (!getNote().isEmpty())
	{
		text += richText?CSL1("
"):CSL1("-------------------------\n");
		text+=par;
		text+=richText?i18n("Note:
"):i18n("Note:\n");
		text+=rtExpand(getNote(), richText);
		text+=ps;
	}

	return text;
}

QDateTime PilotDateEntry::dtStart() const
{
	FUNCTIONSETUP;
	return readTm( getEventStart() );
}

QDateTime PilotDateEntry::dtEnd() const
{
	FUNCTIONSETUP;
	return readTm( getEventEnd() );
}

QDateTime PilotDateEntry::dtRepeatEnd() const
{
	FUNCTIONSETUP;
	return readTm( getRepeatEnd() );
}

unsigned int PilotDateEntry::alarmLeadTime() const
{
	FUNCTIONSETUP;
	if (!isAlarmEnabled()) return 0;

	int adv = getAdvance();
	if ( adv < 0 )
	{
		return 0; // Not possible to enter on the pilot
	}
	unsigned int t = adv;
	int u = getAdvanceUnits();

	switch(u)
	{
	case advMinutes : t *= 60; break;
	case advHours : t *= 3600; break;
	case advDays : t *= 3600 * 24; break;
	default: t = 0;
	}

	return t;
}

PilotRecord *PilotDateEntry::pack() const
{
	int i;

	pi_buffer_t *b = pi_buffer_new( sizeof(fAppointmentInfo) );
	i = pack_Appointment(const_cast<Appointment_t *>(&fAppointmentInfo), b, datebook_v1);
	if (i<0)
	{
		// Generic error from the pack_*() functions.
		return 0;
	}

	// pack_Appointment sets b->used
	return new PilotRecord( b, this );
}

/* setExceptions sets a new set of exceptions. Note that
	PilotDateEntry assumes ownership of the array and will
	delete the old one. */
void PilotDateEntry::setExceptions(struct tm *e) {
	if (fAppointmentInfo.exception != e)
	{
		KPILOT_FREE(fAppointmentInfo.exception);
	}
	fAppointmentInfo.exception=e;
}

void PilotDateEntry::setDescriptionP(const char *desc, int l)
{
	FUNCTIONSETUP;
	KPILOT_FREE(fAppointmentInfo.description);

	if (desc && *desc)
	{
		if (-1 == l) l=::strlen(desc);
		fAppointmentInfo.description =
			(char *) ::malloc(l + 1);
		if (fAppointmentInfo.description)
		{
			strlcpy(fAppointmentInfo.description, desc, l+1);
		}
		else
		{
			WARNINGKPILOT << "malloc() failed, description not set";
		}
	}
	else
	{
		fAppointmentInfo.description = 0L;
	}
}

void PilotDateEntry::setNoteP(const char *note, int l)
{
	FUNCTIONSETUP;
	KPILOT_FREE(fAppointmentInfo.note);

	if (note && *note)
	{
		if (-1 == l) l=::strlen(note);
		fAppointmentInfo.note = (char *)::malloc(l + 1);
		if (fAppointmentInfo.note)
		{
			strlcpy(fAppointmentInfo.note, note,l+1);
		}
		else
		{
			WARNINGKPILOT << "malloc() failed, note not set";
		}
	}
	else
	{
		fAppointmentInfo.note = 0L;
	}
}

void PilotDateEntry::setNote(const QString &s)
{
	QByteArray t = Pilot::toPilot(s);
	setNoteP( t.data(),t.length() );
}

void PilotDateEntry::setLocation(const QString &s)
{
	QString note = Pilot::fromPilot(getNoteP());
	QRegExp rxp = QRegExp("^[Ll]ocation:[^\n]+\n");

	// per QString docs, this covers null and 0 length
	if( s.isEmpty() )
	{
		note.remove( rxp );
	}
	else
	{
		QString location = "Location: " + s + '\n';
		int pos = note.indexOf(rxp);

		if(pos >= 0)
		{
			note.replace( rxp, location );
		}
		else
		{
			note = location + note;
			setNote( note );
		}
	}
}

QString PilotDateEntry::getLocation() const
{
	// Read the complete note here and not the filtered
	// one from PilotDateEntry::getNote();
	QString note = Pilot::fromPilot(getNoteP());
	QRegExp rxp = QRegExp("^[Ll]ocation:[^\n]+\n");
	int pos = note.indexOf(rxp, 0);

	if(pos >= 0)
	{
		QString location = rxp.capturedTexts().first();
		rxp = QRegExp("^[Ll]ocation:[\\s|\t]*");
		location.remove( rxp );
		location.remove( '\n' );
		return location;
	}
	else
	{
		return "";
	}
}

void PilotDateEntry::setDescription(const QString &s)
{
	QByteArray t = Pilot::toPilot(s);
	setDescriptionP( t.data(),t.length() );
}

QString PilotDateEntry::getNote() const
{
	QString note = Pilot::fromPilot(getNoteP());
	QRegExp rxp = QRegExp("^[Ll]ocation:[^\n]+\n");
	note.remove( rxp );
	return note;
}

QString PilotDateEntry::getDescription() const
{
	return Pilot::fromPilot(getDescriptionP());
}

<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/hwpf/hwp/sbe_centaur_init/sbe_centaur_init.C $        */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2012,2014              */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 *  @file sbe_centaur_init.C
 *
 *  Support file for IStep:
 *      sbe_centaur_init
 *
 *
 *
 *  HWP_IGNORE_VERSION_CHECK
 *
 */

/******************************************************************************/
// Includes
/******************************************************************************/
#include    <stdint.h>

#include <trace/interface.H>
#include <initservice/taskargs.H>
#include <errl/errlentry.H>
#include <initservice/isteps_trace.H>
#include <targeting/common/commontargeting.H>
#include <targeting/common/utilFilter.H>
#include <fapi.H>
#include <fapiPoreVeArg.H>
#include <fapiTarget.H>
#include <fapi.H>
#include <fapiPlatHwpInvoker.H>
#include <vfs/vfs.H>
#include "sbe_centaur_init.H"
#include <hwpisteperror.H>
#include <errl/errludtarget.H>
#include <sbe/sbeif.H>
#include "cen_xip_customize.H"

extern fapi::ReturnCode fapiPoreVe(const fapi::Target i_target,
           std::list<uint64_t> & io_sharedObjectArgs);

const uint64_t REPAIR_LOADER_RETRY_CTR_MASK = 0x000007FC00000000ull;

// Constants
// Memory Relocation Register for Centaur SBE image
const uint64_t CENTAUR_SBE_PNOR_MRR = 0;

// Max SBE image buffer size
const uint32_t MAX_SBE_IMG_SIZE = 48 * 1024;

namespace   SBE_CENTAUR_INIT
{

using   namespace   ISTEP;
using   namespace   ISTEP_ERROR;
using   namespace   ERRORLOG;
using   namespace   TARGETING;
using   namespace   fapi;
using   namespace   vsbe;

//
//  Wrapper function to call step 10
//
void*    call_sbe_centaur_init( void *io_pArgs )
{

    TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
              "call_sbe_centaur_init entry");

    // Get target list to pass in procedure
    TARGETING::TargetHandleList l_membufTargetList;
    getAllChips(l_membufTargetList, TYPE_MEMBUF);

    size_t l_sbePnorSize = 0;
    void* l_sbePnorAddr = NULL;
    errlHndl_t  l_errl = NULL;

    IStepError  l_StepError;

    // Loop thru all Centaurs in list
    for (TargetHandleList::const_iterator
         l_membuf_iter = l_membufTargetList.begin();
         l_membuf_iter != l_membufTargetList.end();
         ++l_membuf_iter)
    {

        TARGETING::Target* l_membuf_target = *l_membuf_iter;
        HwasState l_hwasState = l_membuf_target->getAttr<ATTR_HWAS_STATE>();

        TARGETING::ATTR_MSS_INIT_STATE_type  l_attr_mss_init_state=
                l_membuf_target->getAttr<TARGETING::ATTR_MSS_INIT_STATE>();

        //run SBE init on functional OR previously functional centaurs
        if ( l_hwasState.functional ||
            (l_hwasState.present &&
            (l_attr_mss_init_state != ENUM_ATTR_MSS_INIT_STATE_COLD)) )
        {
            l_membuf_target->setAttr<TARGETING::ATTR_MSS_INIT_STATE>(
                                 ENUM_ATTR_MSS_INIT_STATE_COLD);
        }
        else
        {
            //go to the next membuf in the list because this present  membuf is
            //not functional or has not gone through an IPL once
            continue;
        }
        //find SBE image in PNOR
        uint8_t cur_ec = (*l_membuf_iter)->getAttr<TARGETING::ATTR_EC>();

        TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, INFO_MRK,
                   "call_sbe_centaur_init() - Find SBE image in PNOR");

        l_errl = SBE::findSBEInPnor(l_membuf_target,
                                 l_sbePnorAddr,
                                 l_sbePnorSize,
                                 NULL);
        if (l_errl)
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK,
           "call_sbe_centaur_init() - Error getting image from PNOR. "
           "Target 0x%.8X, EC=0x%.2X",
           TARGETING::get_huid(l_membuf_target), cur_ec );

            // capture the target data in the elog
            ErrlUserDetailsTarget(l_membuf_target).addToLog( l_errl );

            // Create IStep error log and cross reference error that occurred
            l_StepError.addErrorDetails( l_errl );

            // Commit Error
            errlCommit( l_errl, HWPF_COMP_ID );
            continue;
        }

        char l_header[10];
        memcpy (l_header, l_sbePnorAddr, 9);
        l_header[9] = '\0';

        TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                     "call_sbe_centaur_init - Loading "
                     "centaur sbe from pnor, Addr 0x%llX, Size %d, Header %s",
                     l_sbePnorAddr, l_sbePnorSize, l_header);

        // Create a FAPI Target
        const fapi::Target l_fapiTarget( fapi::TARGET_TYPE_MEMBUF_CHIP,
                     (const_cast<TARGETING::Target*>(l_membuf_target)));

        // Expand buffer for new image size
        const uint32_t l_customizedMaxSize = MAX_SBE_IMG_SIZE;
        const uint32_t l_buf1Size = MAX_SBE_IMG_SIZE;
        const uint32_t l_buf2Size = MAX_SBE_IMG_SIZE;

        uint32_t l_customizedSize = l_customizedMaxSize;
        char * l_pCustomizedImage = (char *)malloc(l_customizedMaxSize);
        void * l_pBuf1 = malloc(l_buf1Size);
        void * l_pBuf2 = malloc(l_buf2Size);

        // Setup args
        std::list<uint64_t> myArgs;

        // Set FapiPoreVeOtherArg: run unlimited instructions
        FapiPoreVeOtherArg *l_otherArg =
                new FapiPoreVeOtherArg(vsbe::RUN_UNLIMITED, vsbe::PORE_SBE);
        // Entry point
        l_otherArg->iv_entryPoint = const_cast<char*>("pnor::_sbe_pnor_start");
        l_otherArg->iv_mrr = CENTAUR_SBE_PNOR_MRR;
        myArgs.push_back(reinterpret_cast<uint64_t>(l_otherArg));

        // Set FapiPoreVeMemArg for pnor option, base address = 0
        uint32_t base_addr = 0;
        char* l_dataPnor = const_cast<char*>(l_pCustomizedImage);
        FapiPoreVeMemArg* l_memArg = new FapiPoreVeMemArg(ARG_PNOR,
                                               base_addr, l_customizedSize,
                                               static_cast<void*>(l_dataPnor));
        myArgs.push_back(reinterpret_cast<uint64_t>(l_memArg));

        // Create state argument to dump out state for debugging purpose
        FapiPoreVeStateArg *l_stateArg = new FapiPoreVeStateArg(NULL);
        l_stateArg->iv_installState = false;
        l_stateArg->iv_extractState = true;
        myArgs.push_back(reinterpret_cast<uint64_t>(l_stateArg));

        //  Put out info on target
        TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
            "Running call_sbe_centaur_init on Centaur "
            " target HUID %.8X", TARGETING::get_huid(l_membuf_target));

        // XIP customize is going to look for a PLL ring with a "stub"
        // mem freq -- so set to a default, then clear it (so as not
        // to mess up MSS HWP later
        l_membuf_target->setAttr<TARGETING::ATTR_MSS_FREQ>(1600);

        FAPI_INVOKE_HWP( l_errl, cen_xip_customize,
                         l_fapiTarget, l_sbePnorAddr,
                         l_pCustomizedImage, l_customizedSize,
                         l_pBuf1, l_buf1Size,
                         l_pBuf2, l_buf2Size );

        l_membuf_target->setAttr<TARGETING::ATTR_MSS_FREQ>(0);

        if (l_errl)
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
               "ERROR 0x%.8X call_sbe_centaur_init - Error returned from"
               " cen_xip_customize, l_rc 0x%llX", l_errl->reasonCode());
        }
        else
        {
            // Run the engine
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                      "call_sbe_centaur_init - Start VSBE engine...");

            FAPI_INVOKE_HWP(l_errl, fapiPoreVe, l_fapiTarget, myArgs);

            if (l_errl)
            {
                TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                   "ERROR 0x%.8X call_sbe_centaur_init - Error returned from"
                   " VSBE engine on this Centaur, l_rc 0x%llX",
                   l_errl->reasonCode());
                l_errl->collectTrace(FAPI_IMP_TRACE_NAME, 1024);
                l_errl->collectTrace("ISTEPS_TRACE", 512);
            }

            // Remove 0x0104000A reading, per Joe, the IPL procedures are no
            // longer writing information related to the repair loader into
            // this register

        }

        // Freeing memory
        delete l_otherArg;
        delete l_memArg;
        delete l_stateArg;
        free( l_pCustomizedImage );
        free( l_pBuf1 );
        free( l_pBuf2 );

        if (l_errl )
        {
            // capture the target data in the elog
            ErrlUserDetailsTarget(l_membuf_target).addToLog( l_errl );

            // Create IStep error log and cross reference error that occurred
            l_StepError.addErrorDetails( l_errl );

            // Commit Error
            errlCommit( l_errl, HWPF_COMP_ID );
        }
        else
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                 "call_sbe_centaur_init - VSBE engine runs successfully "
                 "on this Centaur");
        }

    }   // end for

    TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
               "call_sbe_centaur_init exit" );

    return l_StepError.getErrorHandle();
}

};   // end namespace

<commit_msg>Increase memory allocation during centuar SBE init<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/hwpf/hwp/sbe_centaur_init/sbe_centaur_init.C $        */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2015                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 *  @file sbe_centaur_init.C
 *
 *  Support file for IStep:
 *      sbe_centaur_init
 *
 *
 *
 *  HWP_IGNORE_VERSION_CHECK
 *
 */

/******************************************************************************/
// Includes
/******************************************************************************/
#include    <stdint.h>

#include <trace/interface.H>
#include <initservice/taskargs.H>
#include <errl/errlentry.H>
#include <initservice/isteps_trace.H>
#include <targeting/common/commontargeting.H>
#include <targeting/common/utilFilter.H>
#include <fapi.H>
#include <fapiPoreVeArg.H>
#include <fapiTarget.H>
#include <fapi.H>
#include <fapiPlatHwpInvoker.H>
#include <vfs/vfs.H>
#include "sbe_centaur_init.H"
#include <hwpisteperror.H>
#include <errl/errludtarget.H>
#include <sbe/sbeif.H>
#include "cen_xip_customize.H"
#include <util/align.H>

extern fapi::ReturnCode fapiPoreVe(const fapi::Target i_target,
           std::list<uint64_t> & io_sharedObjectArgs);

const uint64_t REPAIR_LOADER_RETRY_CTR_MASK = 0x000007FC00000000ull;

// Constants
// Memory Relocation Register for Centaur SBE image
const uint64_t CENTAUR_SBE_PNOR_MRR = 0;

// Max SBE image buffer size
const uint32_t MAX_SBE_IMG_SIZE = 48 * 1024;

namespace   SBE_CENTAUR_INIT
{

using   namespace   ISTEP;
using   namespace   ISTEP_ERROR;
using   namespace   ERRORLOG;
using   namespace   TARGETING;
using   namespace   fapi;
using   namespace   vsbe;

//
//  Wrapper function to call step 10
//
void*    call_sbe_centaur_init( void *io_pArgs )
{

    TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
              "call_sbe_centaur_init entry");

    // Get target list to pass in procedure
    TARGETING::TargetHandleList l_membufTargetList;
    getAllChips(l_membufTargetList, TYPE_MEMBUF);

    size_t l_sbePnorSize = 0;
    void* l_sbePnorAddr = NULL;
    errlHndl_t  l_errl = NULL;

    IStepError  l_StepError;

    // Loop thru all Centaurs in list
    for (TargetHandleList::const_iterator
         l_membuf_iter = l_membufTargetList.begin();
         l_membuf_iter != l_membufTargetList.end();
         ++l_membuf_iter)
    {

        TARGETING::Target* l_membuf_target = *l_membuf_iter;
        HwasState l_hwasState = l_membuf_target->getAttr<ATTR_HWAS_STATE>();

        TARGETING::ATTR_MSS_INIT_STATE_type  l_attr_mss_init_state=
                l_membuf_target->getAttr<TARGETING::ATTR_MSS_INIT_STATE>();

        //run SBE init on functional OR previously functional centaurs
        if ( l_hwasState.functional ||
            (l_hwasState.present &&
            (l_attr_mss_init_state != ENUM_ATTR_MSS_INIT_STATE_COLD)) )
        {
            l_membuf_target->setAttr<TARGETING::ATTR_MSS_INIT_STATE>(
                                 ENUM_ATTR_MSS_INIT_STATE_COLD);
        }
        else
        {
            //go to the next membuf in the list because this present  membuf is
            //not functional or has not gone through an IPL once
            continue;
        }
        //find SBE image in PNOR
        uint8_t cur_ec = (*l_membuf_iter)->getAttr<TARGETING::ATTR_EC>();

        TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, INFO_MRK,
                   "call_sbe_centaur_init() - Find SBE image in PNOR");

        l_errl = SBE::findSBEInPnor(l_membuf_target,
                                 l_sbePnorAddr,
                                 l_sbePnorSize,
                                 NULL);
        if (l_errl)
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK,
           "call_sbe_centaur_init() - Error getting image from PNOR. "
           "Target 0x%.8X, EC=0x%.2X",
           TARGETING::get_huid(l_membuf_target), cur_ec );

            // capture the target data in the elog
            ErrlUserDetailsTarget(l_membuf_target).addToLog( l_errl );

            // Create IStep error log and cross reference error that occurred
            l_StepError.addErrorDetails( l_errl );

            // Commit Error
            errlCommit( l_errl, HWPF_COMP_ID );
            continue;
        }

        char l_header[10];
        memcpy (l_header, l_sbePnorAddr, 9);
        l_header[9] = '\0';

        TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                     "call_sbe_centaur_init - Loading "
                     "centaur sbe from pnor, Addr 0x%llX, Size %d, Header %s",
                     l_sbePnorAddr, l_sbePnorSize, l_header);

        // Create a FAPI Target
        const fapi::Target l_fapiTarget( fapi::TARGET_TYPE_MEMBUF_CHIP,
                     (const_cast<TARGETING::Target*>(l_membuf_target)));

        // Expand buffer for new image size
        const uint32_t l_customizedMaxSize = ALIGN_POW2(MAX_SBE_IMG_SIZE);
        const uint32_t l_buf1Size = ALIGN_POW2(MAX_SBE_IMG_SIZE);
        const uint32_t l_buf2Size = ALIGN_POW2(MAX_SBE_IMG_SIZE);

        uint32_t l_customizedSize = l_customizedMaxSize;
        char * l_pCustomizedImage = (char *)malloc(l_customizedMaxSize);
        void * l_pBuf1 = malloc(l_buf1Size);
        void * l_pBuf2 = malloc(l_buf2Size);

        // Setup args
        std::list<uint64_t> myArgs;

        // Set FapiPoreVeOtherArg: run unlimited instructions
        FapiPoreVeOtherArg *l_otherArg =
                new FapiPoreVeOtherArg(vsbe::RUN_UNLIMITED, vsbe::PORE_SBE);
        // Entry point
        l_otherArg->iv_entryPoint = const_cast<char*>("pnor::_sbe_pnor_start");
        l_otherArg->iv_mrr = CENTAUR_SBE_PNOR_MRR;
        myArgs.push_back(reinterpret_cast<uint64_t>(l_otherArg));

        // Set FapiPoreVeMemArg for pnor option, base address = 0
        uint32_t base_addr = 0;
        char* l_dataPnor = const_cast<char*>(l_pCustomizedImage);
        FapiPoreVeMemArg* l_memArg = new FapiPoreVeMemArg(ARG_PNOR,
                                               base_addr, l_customizedSize,
                                               static_cast<void*>(l_dataPnor));
        myArgs.push_back(reinterpret_cast<uint64_t>(l_memArg));

        // Create state argument to dump out state for debugging purpose
        FapiPoreVeStateArg *l_stateArg = new FapiPoreVeStateArg(NULL);
        l_stateArg->iv_installState = false;
        l_stateArg->iv_extractState = true;
        myArgs.push_back(reinterpret_cast<uint64_t>(l_stateArg));

        //  Put out info on target
        TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
            "Running call_sbe_centaur_init on Centaur "
            " target HUID %.8X", TARGETING::get_huid(l_membuf_target));

        // XIP customize is going to look for a PLL ring with a "stub"
        // mem freq -- so set to a default, then clear it (so as not
        // to mess up MSS HWP later
        l_membuf_target->setAttr<TARGETING::ATTR_MSS_FREQ>(1600);

        FAPI_INVOKE_HWP( l_errl, cen_xip_customize,
                         l_fapiTarget, l_sbePnorAddr,
                         l_pCustomizedImage, l_customizedSize,
                         l_pBuf1, l_buf1Size,
                         l_pBuf2, l_buf2Size );

        l_membuf_target->setAttr<TARGETING::ATTR_MSS_FREQ>(0);

        if (l_errl)
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
               "ERROR 0x%.8X call_sbe_centaur_init - Error returned from"
               " cen_xip_customize, l_rc 0x%llX", l_errl->reasonCode());
        }
        else
        {
            // Run the engine
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                      "call_sbe_centaur_init - Start VSBE engine...");

            FAPI_INVOKE_HWP(l_errl, fapiPoreVe, l_fapiTarget, myArgs);

            if (l_errl)
            {
                TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                   "ERROR 0x%.8X call_sbe_centaur_init - Error returned from"
                   " VSBE engine on this Centaur, l_rc 0x%llX",
                   l_errl->reasonCode());
                l_errl->collectTrace(FAPI_IMP_TRACE_NAME, 1024);
                l_errl->collectTrace("ISTEPS_TRACE", 512);
            }

            // Remove 0x0104000A reading, per Joe, the IPL procedures are no
            // longer writing information related to the repair loader into
            // this register

        }

        // Freeing memory
        delete l_otherArg;
        delete l_memArg;
        delete l_stateArg;
        free( l_pCustomizedImage );
        free( l_pBuf1 );
        free( l_pBuf2 );

        if (l_errl )
        {
            // capture the target data in the elog
            ErrlUserDetailsTarget(l_membuf_target).addToLog( l_errl );

            // Create IStep error log and cross reference error that occurred
            l_StepError.addErrorDetails( l_errl );

            // Commit Error
            errlCommit( l_errl, HWPF_COMP_ID );
        }
        else
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                 "call_sbe_centaur_init - VSBE engine runs successfully "
                 "on this Centaur");
        }

    }   // end for

    TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
               "call_sbe_centaur_init exit" );

    return l_StepError.getErrorHandle();
}

};   // end namespace

<|endoftext|>


<commit_before>/**
 * \file  calibration.cc
 * \brief
 *
 * \author  Piyush Khandelwal (piyushk@cs.utexas.edu)
 * Copyright (C) 2012, Austin Robot Technology,
 *                     The University of Texas at Austin
 *
 * License: Modified BSD License
 *
 * $ Id: 02/14/2012 11:36:36 AM piyushk $
 */

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <limits>
#include <yaml-cpp/yaml.h>

#ifdef HAVE_NEW_YAMLCPP
namespace YAML {

  // The >> operator disappeared in yaml-cpp 0.5, so this function is
  // added to provide support for code written under the yaml-cpp 0.3 API.
  template<typename T>
  void operator >> (const YAML::Node& node, T& i) {
    i = node.as<T>();
  }
} /* YAML */
#endif // HAVE_NEW_YAMLCPP

#include <ros/ros.h>
#include <velodyne_pointcloud/calibration.h>

namespace velodyne_pointcloud
{

  const std::string NUM_LASERS = "num_lasers";
  const std::string LASERS = "lasers";
  const std::string LASER_ID = "laser_id";
  const std::string ROT_CORRECTION = "rot_correction";
  const std::string VERT_CORRECTION = "vert_correction";
   const std::string DIST_CORRECTION = "dist_correction";
  const std::string TWO_PT_CORRECTION_AVAILABLE =
    "two_pt_correction_available";
  const std::string DIST_CORRECTION_X = "dist_correction_x";
  const std::string DIST_CORRECTION_Y = "dist_correction_y";
  const std::string VERT_OFFSET_CORRECTION = "vert_offset_correction";
  const std::string HORIZ_OFFSET_CORRECTION = "horiz_offset_correction";
  const std::string MAX_INTENSITY = "max_intensity";
  const std::string MIN_INTENSITY = "min_intensity";
  const std::string FOCAL_DISTANCE = "focal_distance";
  const std::string FOCAL_SLOPE = "focal_slope";

  /** Read calibration for a single laser. */
  void operator >> (const YAML::Node& node,
                    std::pair<int, LaserCorrection>& correction)
  {
    node[LASER_ID] >> correction.first;
    node[ROT_CORRECTION] >> correction.second.rot_correction;
    node[VERT_CORRECTION] >> correction.second.vert_correction;
    node[DIST_CORRECTION] >> correction.second.dist_correction;
#ifdef HAVE_NEW_YAMLCPP
    if (node[TWO_PT_CORRECTION_AVAILABLE])
      node[TWO_PT_CORRECTION_AVAILABLE] >>
        correction.second.two_pt_correction_available;
#else
    if (const YAML::Node *pName = node.FindValue(TWO_PT_CORRECTION_AVAILABLE))
      *pName >> correction.second.two_pt_correction_available;
#endif
    else
      correction.second.two_pt_correction_available = false;
    node[DIST_CORRECTION_X] >> correction.second.dist_correction_x;
    node[DIST_CORRECTION_Y] >> correction.second.dist_correction_y;
    node[VERT_OFFSET_CORRECTION] >> correction.second.vert_offset_correction;
#ifdef HAVE_NEW_YAMLCPP
    if (node[HORIZ_OFFSET_CORRECTION])
      node[HORIZ_OFFSET_CORRECTION] >>
        correction.second.horiz_offset_correction;
#else
    if (const YAML::Node *pName = node.FindValue(HORIZ_OFFSET_CORRECTION))
      *pName >> correction.second.horiz_offset_correction;
#endif
    else
      correction.second.horiz_offset_correction = 0;

    const YAML::Node * max_intensity_node = NULL;
#ifdef HAVE_NEW_YAMLCPP
    if (node[MAX_INTENSITY]) {
      const YAML::Node max_intensity_node_ref = node[MAX_INTENSITY];
      max_intensity_node = &max_intensity_node_ref;
    }
#else
    if (const YAML::Node *pName = node.FindValue(MAX_INTENSITY))
      max_intensity_node = pName;
#endif
    if (max_intensity_node) {
      try {
        *max_intensity_node >> correction.second.max_intensity;
      } catch(const YAML::InvalidScalar & exc) {
        float max_intensity_float;
        *max_intensity_node >> max_intensity_float;
        correction.second.max_intensity = floor(max_intensity_float);
        ROS_WARN_ONCE("Implicitly converting 'max_intensity' values from floats to ints.");
      }
    }
    else {
      correction.second.max_intensity = 255;
    }

    const YAML::Node * min_intensity_node = NULL;
#ifdef HAVE_NEW_YAMLCPP
    if (node[MIN_INTENSITY]) {
      const YAML::Node min_intensity_node_ref = node[MIN_INTENSITY];
      min_intensity_node = &min_intensity_node_ref;
    }
#else
    if (const YAML::Node *pName = node.FindValue(MIN_INTENSITY))
      min_intensity_node = pName;
#endif
    if (min_intensity_node) {
      try {
        *min_intensity_node >> correction.second.min_intensity;
      } catch(const YAML::InvalidScalar & exc) {
        float min_intensity_float;
        *min_intensity_node >> min_intensity_float;
        correction.second.min_intensity = floor(min_intensity_float);
        ROS_WARN_ONCE("Implicitly converting 'min_intensity' values from floats to ints.");
      }
    }
    else {
      correction.second.min_intensity = 0;
    }
    node[FOCAL_DISTANCE] >> correction.second.focal_distance;
    node[FOCAL_SLOPE] >> correction.second.focal_slope;

    // Calculate cached values
    correction.second.cos_rot_correction =
      cosf(correction.second.rot_correction);
    correction.second.sin_rot_correction =
      sinf(correction.second.rot_correction);
    correction.second.cos_vert_correction =
      cosf(correction.second.vert_correction);
    correction.second.sin_vert_correction =
      sinf(correction.second.vert_correction);

    correction.second.laser_ring = 0;   // clear initially (set later)
  }

  /** Read entire calibration file. */
  void operator >> (const YAML::Node& node, Calibration& calibration)
  {
    int num_lasers;
    node[NUM_LASERS] >> num_lasers;
    const YAML::Node& lasers = node[LASERS];
    calibration.laser_corrections.clear();
    calibration.num_lasers = num_lasers;
    for (int i = 0; i < num_lasers; i++) {
      std::pair<int, LaserCorrection> correction;
      lasers[i] >> correction;
      calibration.laser_corrections.insert(correction);
    }

    // For each laser ring, find the next-smallest vertical angle.
    //
    // This implementation is simple, but not efficient.  That is OK,
    // since it only runs while starting up.
    double next_angle = -std::numeric_limits<double>::infinity();
    for (int ring = 0; ring < num_lasers; ++ring) {

      // find minimum remaining vertical offset correction
      double min_seen = std::numeric_limits<double>::infinity();
      int next_index = num_lasers;
      for (int j = 0; j < num_lasers; ++j) {

        double angle = calibration.laser_corrections[j].vert_correction;
        if (next_angle < angle && angle < min_seen) {
          min_seen = angle;
          next_index = j;
        }
      }

      if (next_index < num_lasers) {    // anything found in this ring?

        // store this ring number with its corresponding laser number
        calibration.laser_corrections[next_index].laser_ring = ring;
        next_angle = min_seen;
        ROS_INFO("laser_ring[%2u] = %2u, angle = %+.6f",
                 next_index, ring, next_angle);
      }
    }
  }

  YAML::Emitter& operator << (YAML::Emitter& out,
                              const std::pair<int, LaserCorrection> correction)
  {
    out << YAML::BeginMap;
    out << YAML::Key << LASER_ID << YAML::Value << correction.first;
    out << YAML::Key << ROT_CORRECTION <<
      YAML::Value << correction.second.rot_correction;
    out << YAML::Key << VERT_CORRECTION <<
      YAML::Value << correction.second.vert_correction;
    out << YAML::Key << DIST_CORRECTION <<
      YAML::Value << correction.second.dist_correction;
    out << YAML::Key << TWO_PT_CORRECTION_AVAILABLE <<
      YAML::Value << correction.second.two_pt_correction_available;
    out << YAML::Key << DIST_CORRECTION_X <<
      YAML::Value << correction.second.dist_correction_x;
    out << YAML::Key << DIST_CORRECTION_Y <<
      YAML::Value << correction.second.dist_correction_y;
    out << YAML::Key << VERT_OFFSET_CORRECTION <<
      YAML::Value << correction.second.vert_offset_correction;
    out << YAML::Key << HORIZ_OFFSET_CORRECTION <<
      YAML::Value << correction.second.horiz_offset_correction;
    out << YAML::Key << MAX_INTENSITY <<
      YAML::Value << correction.second.max_intensity;
    out << YAML::Key << MIN_INTENSITY <<
      YAML::Value << correction.second.min_intensity;
    out << YAML::Key << FOCAL_DISTANCE <<
      YAML::Value << correction.second.focal_distance;
    out << YAML::Key << FOCAL_SLOPE <<
      YAML::Value << correction.second.focal_slope;
    out << YAML::EndMap;
    return out;
  }

  YAML::Emitter& operator <<
  (YAML::Emitter& out, const Calibration& calibration)
  {
    out << YAML::BeginMap;
    out << YAML::Key << NUM_LASERS <<
      YAML::Value << calibration.laser_corrections.size();
    out << YAML::Key << LASERS << YAML::Value << YAML::BeginSeq;
    for (std::map<int, LaserCorrection>::const_iterator
           it = calibration.laser_corrections.begin();
         it != calibration.laser_corrections.end(); it++)
      {
        out << *it;
      }
    out << YAML::EndSeq;
    out << YAML::EndMap;
    return out;
  }

  void Calibration::read(const std::string& calibration_file) {
    std::ifstream fin(calibration_file.c_str());
    if (!fin.is_open()) {
      initialized = false;
      return;
    }
    initialized = true;
    try {
      YAML::Node doc;
#ifdef HAVE_NEW_YAMLCPP
      fin.close();
      doc = YAML::LoadFile(calibration_file);
#else
      YAML::Parser parser(fin);
      parser.GetNextDocument(doc);
#endif
      doc >> *this;
    } catch (YAML::Exception &e) {
      std::cerr << "YAML Exception: " << e.what() << std::endl;
      initialized = false;
    }
    fin.close();
  }

  void Calibration::write(const std::string& calibration_file) {
    std::ofstream fout(calibration_file.c_str());
    YAML::Emitter out;
    out << *this;
    fout << out.c_str();
    fout.close();
  }

} /* velodyne_pointcloud */
<commit_msg>calibration: read all intensities as float, then convert (#84)<commit_after>/**
 * \file  calibration.cc
 * \brief
 *
 * \author  Piyush Khandelwal (piyushk@cs.utexas.edu)
 * Copyright (C) 2012, Austin Robot Technology,
 *                     The University of Texas at Austin
 *
 * License: Modified BSD License
 *
 * $ Id: 02/14/2012 11:36:36 AM piyushk $
 */

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <limits>
#include <yaml-cpp/yaml.h>

#ifdef HAVE_NEW_YAMLCPP
namespace YAML {

  // The >> operator disappeared in yaml-cpp 0.5, so this function is
  // added to provide support for code written under the yaml-cpp 0.3 API.
  template<typename T>
  void operator >> (const YAML::Node& node, T& i) {
    i = node.as<T>();
  }
} /* YAML */
#endif // HAVE_NEW_YAMLCPP

#include <ros/ros.h>
#include <velodyne_pointcloud/calibration.h>

namespace velodyne_pointcloud
{

  const std::string NUM_LASERS = "num_lasers";
  const std::string LASERS = "lasers";
  const std::string LASER_ID = "laser_id";
  const std::string ROT_CORRECTION = "rot_correction";
  const std::string VERT_CORRECTION = "vert_correction";
   const std::string DIST_CORRECTION = "dist_correction";
  const std::string TWO_PT_CORRECTION_AVAILABLE =
    "two_pt_correction_available";
  const std::string DIST_CORRECTION_X = "dist_correction_x";
  const std::string DIST_CORRECTION_Y = "dist_correction_y";
  const std::string VERT_OFFSET_CORRECTION = "vert_offset_correction";
  const std::string HORIZ_OFFSET_CORRECTION = "horiz_offset_correction";
  const std::string MAX_INTENSITY = "max_intensity";
  const std::string MIN_INTENSITY = "min_intensity";
  const std::string FOCAL_DISTANCE = "focal_distance";
  const std::string FOCAL_SLOPE = "focal_slope";

  /** Read calibration for a single laser. */
  void operator >> (const YAML::Node& node,
                    std::pair<int, LaserCorrection>& correction)
  {
    node[LASER_ID] >> correction.first;
    node[ROT_CORRECTION] >> correction.second.rot_correction;
    node[VERT_CORRECTION] >> correction.second.vert_correction;
    node[DIST_CORRECTION] >> correction.second.dist_correction;
#ifdef HAVE_NEW_YAMLCPP
    if (node[TWO_PT_CORRECTION_AVAILABLE])
      node[TWO_PT_CORRECTION_AVAILABLE] >>
        correction.second.two_pt_correction_available;
#else
    if (const YAML::Node *pName = node.FindValue(TWO_PT_CORRECTION_AVAILABLE))
      *pName >> correction.second.two_pt_correction_available;
#endif
    else
      correction.second.two_pt_correction_available = false;
    node[DIST_CORRECTION_X] >> correction.second.dist_correction_x;
    node[DIST_CORRECTION_Y] >> correction.second.dist_correction_y;
    node[VERT_OFFSET_CORRECTION] >> correction.second.vert_offset_correction;
#ifdef HAVE_NEW_YAMLCPP
    if (node[HORIZ_OFFSET_CORRECTION])
      node[HORIZ_OFFSET_CORRECTION] >>
        correction.second.horiz_offset_correction;
#else
    if (const YAML::Node *pName = node.FindValue(HORIZ_OFFSET_CORRECTION))
      *pName >> correction.second.horiz_offset_correction;
#endif
    else
      correction.second.horiz_offset_correction = 0;

    const YAML::Node * max_intensity_node = NULL;
#ifdef HAVE_NEW_YAMLCPP
    if (node[MAX_INTENSITY]) {
      const YAML::Node max_intensity_node_ref = node[MAX_INTENSITY];
      max_intensity_node = &max_intensity_node_ref;
    }
#else
    if (const YAML::Node *pName = node.FindValue(MAX_INTENSITY))
      max_intensity_node = pName;
#endif
    if (max_intensity_node) {
      float max_intensity_float;
      *max_intensity_node >> max_intensity_float;
      correction.second.max_intensity = floor(max_intensity_float);
    }
    else {
      correction.second.max_intensity = 255;
    }

    const YAML::Node * min_intensity_node = NULL;
#ifdef HAVE_NEW_YAMLCPP
    if (node[MIN_INTENSITY]) {
      const YAML::Node min_intensity_node_ref = node[MIN_INTENSITY];
      min_intensity_node = &min_intensity_node_ref;
    }
#else
    if (const YAML::Node *pName = node.FindValue(MIN_INTENSITY))
      min_intensity_node = pName;
#endif
    if (min_intensity_node) {
      float min_intensity_float;
      *min_intensity_node >> min_intensity_float;
      correction.second.min_intensity = floor(min_intensity_float);
    }
    else {
      correction.second.min_intensity = 0;
    }
    node[FOCAL_DISTANCE] >> correction.second.focal_distance;
    node[FOCAL_SLOPE] >> correction.second.focal_slope;

    // Calculate cached values
    correction.second.cos_rot_correction =
      cosf(correction.second.rot_correction);
    correction.second.sin_rot_correction =
      sinf(correction.second.rot_correction);
    correction.second.cos_vert_correction =
      cosf(correction.second.vert_correction);
    correction.second.sin_vert_correction =
      sinf(correction.second.vert_correction);

    correction.second.laser_ring = 0;   // clear initially (set later)
  }

  /** Read entire calibration file. */
  void operator >> (const YAML::Node& node, Calibration& calibration)
  {
    int num_lasers;
    node[NUM_LASERS] >> num_lasers;
    const YAML::Node& lasers = node[LASERS];
    calibration.laser_corrections.clear();
    calibration.num_lasers = num_lasers;
    for (int i = 0; i < num_lasers; i++) {
      std::pair<int, LaserCorrection> correction;
      lasers[i] >> correction;
      calibration.laser_corrections.insert(correction);
    }

    // For each laser ring, find the next-smallest vertical angle.
    //
    // This implementation is simple, but not efficient.  That is OK,
    // since it only runs while starting up.
    double next_angle = -std::numeric_limits<double>::infinity();
    for (int ring = 0; ring < num_lasers; ++ring) {

      // find minimum remaining vertical offset correction
      double min_seen = std::numeric_limits<double>::infinity();
      int next_index = num_lasers;
      for (int j = 0; j < num_lasers; ++j) {

        double angle = calibration.laser_corrections[j].vert_correction;
        if (next_angle < angle && angle < min_seen) {
          min_seen = angle;
          next_index = j;
        }
      }

      if (next_index < num_lasers) {    // anything found in this ring?

        // store this ring number with its corresponding laser number
        calibration.laser_corrections[next_index].laser_ring = ring;
        next_angle = min_seen;
        ROS_INFO("laser_ring[%2u] = %2u, angle = %+.6f",
                 next_index, ring, next_angle);
      }
    }
  }

  YAML::Emitter& operator << (YAML::Emitter& out,
                              const std::pair<int, LaserCorrection> correction)
  {
    out << YAML::BeginMap;
    out << YAML::Key << LASER_ID << YAML::Value << correction.first;
    out << YAML::Key << ROT_CORRECTION <<
      YAML::Value << correction.second.rot_correction;
    out << YAML::Key << VERT_CORRECTION <<
      YAML::Value << correction.second.vert_correction;
    out << YAML::Key << DIST_CORRECTION <<
      YAML::Value << correction.second.dist_correction;
    out << YAML::Key << TWO_PT_CORRECTION_AVAILABLE <<
      YAML::Value << correction.second.two_pt_correction_available;
    out << YAML::Key << DIST_CORRECTION_X <<
      YAML::Value << correction.second.dist_correction_x;
    out << YAML::Key << DIST_CORRECTION_Y <<
      YAML::Value << correction.second.dist_correction_y;
    out << YAML::Key << VERT_OFFSET_CORRECTION <<
      YAML::Value << correction.second.vert_offset_correction;
    out << YAML::Key << HORIZ_OFFSET_CORRECTION <<
      YAML::Value << correction.second.horiz_offset_correction;
    out << YAML::Key << MAX_INTENSITY <<
      YAML::Value << correction.second.max_intensity;
    out << YAML::Key << MIN_INTENSITY <<
      YAML::Value << correction.second.min_intensity;
    out << YAML::Key << FOCAL_DISTANCE <<
      YAML::Value << correction.second.focal_distance;
    out << YAML::Key << FOCAL_SLOPE <<
      YAML::Value << correction.second.focal_slope;
    out << YAML::EndMap;
    return out;
  }

  YAML::Emitter& operator <<
  (YAML::Emitter& out, const Calibration& calibration)
  {
    out << YAML::BeginMap;
    out << YAML::Key << NUM_LASERS <<
      YAML::Value << calibration.laser_corrections.size();
    out << YAML::Key << LASERS << YAML::Value << YAML::BeginSeq;
    for (std::map<int, LaserCorrection>::const_iterator
           it = calibration.laser_corrections.begin();
         it != calibration.laser_corrections.end(); it++)
      {
        out << *it;
      }
    out << YAML::EndSeq;
    out << YAML::EndMap;
    return out;
  }

  void Calibration::read(const std::string& calibration_file) {
    std::ifstream fin(calibration_file.c_str());
    if (!fin.is_open()) {
      initialized = false;
      return;
    }
    initialized = true;
    try {
      YAML::Node doc;
#ifdef HAVE_NEW_YAMLCPP
      fin.close();
      doc = YAML::LoadFile(calibration_file);
#else
      YAML::Parser parser(fin);
      parser.GetNextDocument(doc);
#endif
      doc >> *this;
    } catch (YAML::Exception &e) {
      std::cerr << "YAML Exception: " << e.what() << std::endl;
      initialized = false;
    }
    fin.close();
  }

  void Calibration::write(const std::string& calibration_file) {
    std::ofstream fout(calibration_file.c_str());
    YAML::Emitter out;
    out << *this;
    fout << out.c_str();
    fout.close();
  }

} /* velodyne_pointcloud */
<|endoftext|>


<commit_before>//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "ToolChains.h"

#include "Tools.h"

using namespace swift;
using namespace swift::driver;
using namespace swift::driver::toolchains;
using namespace llvm::opt;

/// Darwin

std::unique_ptr<Tool> Darwin::buildLinker() const {
  return std::unique_ptr<Tool>(new tools::darwin::Linker(*this));
}

StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
  switch (getTriple().getArch()) {
  default:
    return getArchName();
  case llvm::Triple::thumb:
  case llvm::Triple::arm:
    // FIXME: need to handle -march, -mcpu (if necessary)
    return "arm";
  }
}
<commit_msg>Don't use architecture "arm". The linker and other tools don't accept it.<commit_after>//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "ToolChains.h"

#include "Tools.h"

using namespace swift;
using namespace swift::driver;
using namespace swift::driver::toolchains;
using namespace llvm::opt;

/// Darwin

std::unique_ptr<Tool> Darwin::buildLinker() const {
  return std::unique_ptr<Tool>(new tools::darwin::Linker(*this));
}

StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
  return getArchName();
}
<|endoftext|>


<commit_before>//===--- GenCoverage.cpp - IR Generation for coverage ---------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR generation for the initialization of
//  coverage related variables.
//
//===----------------------------------------------------------------------===//

#include "IRGenModule.h"

#include "swift/SIL/SILModule.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/ProfileData/CoverageMappingWriter.h"
#include "llvm/Support/FileSystem.h"

using namespace swift;
using namespace irgen;

using llvm::coverage::CounterMappingRegion;

void IRGenModule::emitCoverageMapping() {
  const auto &Mappings = SILMod->getCoverageMapList();
  // If there aren't any coverage maps, there's nothing to emit.
  if (Mappings.empty())
    return;

  std::vector<StringRef> Files;
  for (const auto &M : Mappings)
    if (std::find(Files.begin(), Files.end(), M.getFile()) == Files.end())
      Files.push_back(M.getFile());

  // Awkwardly munge absolute filenames into a vector of StringRefs.
  // TODO: This is heinous - the same thing is happening in clang, but the API
  // really needs to be cleaned up for both.
  llvm::SmallVector<std::string, 8> FilenameStrs;
  llvm::SmallVector<StringRef, 8> FilenameRefs;
  for (StringRef Name : Files) {
    llvm::SmallString<256> Path(Name);
    llvm::sys::fs::make_absolute(Path);
    FilenameStrs.push_back(std::string(Path.begin(), Path.end()));
    FilenameRefs.push_back(FilenameStrs.back());
  }

  // Encode the filenames first.
  std::string EncodedDataBuf;
  llvm::raw_string_ostream OS(EncodedDataBuf);
  llvm::coverage::CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
  size_t FilenamesSize = OS.str().size();
  size_t CurrentSize, PrevSize = FilenamesSize;

  // Now we need to build up the list of function records.
  auto *Int32Ty = llvm::Type::getInt32Ty(LLVMContext);
  auto *Int64Ty = llvm::Type::getInt64Ty(LLVMContext);
  auto *Int8PtrTy = llvm::Type::getInt8PtrTy(LLVMContext);
  auto *FunctionRecordTy = llvm::StructType::get(
      LLVMContext, {Int8PtrTy, Int32Ty, Int32Ty, Int64Ty}, /*isPacked=*/true);

  std::vector<llvm::Constant *> FunctionRecords;
  std::vector<CounterMappingRegion> Regions;
  for (const auto &M : Mappings) {
    unsigned FileID =
        std::find(Files.begin(), Files.end(), M.getFile()) - Files.begin();
    Regions.clear();
    for (const auto &MR : M.getMappedRegions())
      Regions.emplace_back(CounterMappingRegion::makeRegion(
          MR.Counter, /*FileID=*/0, MR.StartLine, MR.StartCol, MR.EndLine,
          MR.EndCol));
    // Append each function's regions into the encoded buffer.
    llvm::coverage::CoverageMappingWriter W({FileID}, M.getExpressions(),
                                            Regions);
    W.write(OS);

    auto *NameVal =
        llvm::ConstantDataArray::getString(LLVMContext, M.getName(), false);
    auto *NameVar =
        new llvm::GlobalVariable(*getModule(), NameVal->getType(), true,
                                 llvm::GlobalValue::LinkOnceAnyLinkage, NameVal,
                                 "__llvm_profile_name_" + M.getName());

    CurrentSize = OS.str().size();
    // Create a record for this function.
    llvm::Constant *FunctionRecordVals[] = {
        llvm::ConstantExpr::getBitCast(NameVar, Int8PtrTy),
        // TODO: We're including the null to match the profile, but we should
        // really skip the null in the profile instead.
        llvm::ConstantInt::get(Int32Ty, M.getName().size()),
        llvm::ConstantInt::get(Int32Ty, CurrentSize - PrevSize),
        llvm::ConstantInt::get(Int64Ty, M.getHash())};
    FunctionRecords.push_back(llvm::ConstantStruct::get(
        FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
    PrevSize = CurrentSize;
  }
  size_t CoverageMappingSize = PrevSize - FilenamesSize;

  // Append extra zeroes if necessary to ensure that the size of the filenames
  // and coverage mappings is a multiple of 8.
  if (size_t Rem = OS.str().size() % 8) {
    CoverageMappingSize += 8 - Rem;
    for (size_t I = 0, S = 8 - Rem; I < S; ++I)
      OS << '\0';
  }
  auto *EncodedData =
      llvm::ConstantDataArray::getString(LLVMContext, OS.str(), false);

  auto *RecordsTy =
      llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
  auto *RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);

  // Now we embed everything into a constant with a well-known name.
  auto *CovDataTy =
      llvm::StructType::get(LLVMContext, {Int32Ty, Int32Ty, Int32Ty, Int32Ty,
                                          RecordsTy, EncodedData->getType()});
  llvm::Constant *TUDataVals[] = {
      llvm::ConstantInt::get(Int32Ty, FunctionRecords.size()),
      llvm::ConstantInt::get(Int32Ty, FilenamesSize),
      llvm::ConstantInt::get(Int32Ty, CoverageMappingSize),
      llvm::ConstantInt::get(Int32Ty, llvm::coverage::CoverageMappingVersion1),
      RecordsVal, EncodedData};
  auto CovDataVal =
      llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
  auto CovData = new llvm::GlobalVariable(
      *getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage,
      CovDataVal, "__llvm_coverage_mapping");

  addUsedGlobal(CovData);
}
<commit_msg>[Coverage] Use new definitions from InstrProf.h<commit_after>//===--- GenCoverage.cpp - IR Generation for coverage ---------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR generation for the initialization of
//  coverage related variables.
//
//===----------------------------------------------------------------------===//

#include "IRGenModule.h"
#include "SwiftTargetInfo.h"

#include "swift/SIL/SILModule.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/ProfileData/CoverageMappingWriter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/ProfileData/InstrProf.h"

using namespace swift;
using namespace irgen;

using llvm::coverage::CounterMappingRegion;

static bool isMachO(IRGenModule &IGM) {
  return SwiftTargetInfo::get(IGM).OutputObjectFormat == llvm::Triple::MachO;
}

static StringRef getCoverageSection(IRGenModule &IGM) {
  return llvm::getInstrProfCoverageSectionName(isMachO(IGM));
}

void IRGenModule::emitCoverageMapping() {
  const auto &Mappings = SILMod->getCoverageMapList();
  // If there aren't any coverage maps, there's nothing to emit.
  if (Mappings.empty())
    return;

  std::vector<StringRef> Files;
  for (const auto &M : Mappings)
    if (std::find(Files.begin(), Files.end(), M.getFile()) == Files.end())
      Files.push_back(M.getFile());

  // Awkwardly munge absolute filenames into a vector of StringRefs.
  // TODO: This is heinous - the same thing is happening in clang, but the API
  // really needs to be cleaned up for both.
  llvm::SmallVector<std::string, 8> FilenameStrs;
  llvm::SmallVector<StringRef, 8> FilenameRefs;
  for (StringRef Name : Files) {
    llvm::SmallString<256> Path(Name);
    llvm::sys::fs::make_absolute(Path);
    FilenameStrs.push_back(std::string(Path.begin(), Path.end()));
    FilenameRefs.push_back(FilenameStrs.back());
  }

  // Encode the filenames first.
  std::string EncodedDataBuf;
  llvm::raw_string_ostream OS(EncodedDataBuf);
  llvm::coverage::CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
  size_t FilenamesSize = OS.str().size();
  size_t CurrentSize, PrevSize = FilenamesSize;

  // Now we need to build up the list of function records.
  llvm::LLVMContext &Ctx = LLVMContext;
  auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
  auto *Int64Ty = llvm::Type::getInt64Ty(Ctx);
  auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);

#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
  llvm::Type *FunctionRecordTypes[] = {
#include "llvm/ProfileData/InstrProfData.inc"
  };

  auto FunctionRecordTy =
      llvm::StructType::get(Ctx, llvm::makeArrayRef(FunctionRecordTypes),
                            /*isPacked=*/true);

  std::vector<llvm::Constant *> FunctionRecords;
  std::vector<CounterMappingRegion> Regions;
  for (const auto &M : Mappings) {
    unsigned FileID =
        std::find(Files.begin(), Files.end(), M.getFile()) - Files.begin();
    Regions.clear();
    for (const auto &MR : M.getMappedRegions())
      Regions.emplace_back(CounterMappingRegion::makeRegion(
          MR.Counter, /*FileID=*/0, MR.StartLine, MR.StartCol, MR.EndLine,
          MR.EndCol));
    // Append each function's regions into the encoded buffer.
    llvm::coverage::CoverageMappingWriter W({FileID}, M.getExpressions(),
                                            Regions);
    W.write(OS);

    auto *NameVal = llvm::ConstantDataArray::getString(Ctx, M.getName(), false);
    auto *NameVar = new llvm::GlobalVariable(
        *getModule(), NameVal->getType(), true,
        llvm::GlobalValue::LinkOnceAnyLinkage, NameVal,
        llvm::getInstrProfNameVarPrefix() + M.getName());

    CurrentSize = OS.str().size();
    // Create a record for this function.
    llvm::Constant *FunctionRecordVals[] = {
        llvm::ConstantExpr::getBitCast(NameVar, Int8PtrTy),
        llvm::ConstantInt::get(Int32Ty, M.getName().size()),
        llvm::ConstantInt::get(Int32Ty, CurrentSize - PrevSize),
        llvm::ConstantInt::get(Int64Ty, M.getHash())};
    FunctionRecords.push_back(llvm::ConstantStruct::get(
        FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
    PrevSize = CurrentSize;
  }
  size_t CoverageMappingSize = PrevSize - FilenamesSize;

  // Append extra zeroes if necessary to ensure that the size of the filenames
  // and coverage mappings is a multiple of 8.
  if (size_t Rem = OS.str().size() % 8) {
    CoverageMappingSize += 8 - Rem;
    for (size_t I = 0, S = 8 - Rem; I < S; ++I)
      OS << '\0';
  }
  auto *EncodedData =
      llvm::ConstantDataArray::getString(Ctx, OS.str(), false);

  auto *RecordsTy =
      llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
  auto *RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);

  // Now we embed everything into a constant with a well-known name.
  auto *CovDataTy =
      llvm::StructType::get(Ctx, {Int32Ty, Int32Ty, Int32Ty, Int32Ty, RecordsTy,
                                  EncodedData->getType()});
  llvm::Constant *TUDataVals[] = {
      llvm::ConstantInt::get(Int32Ty, FunctionRecords.size()),
      llvm::ConstantInt::get(Int32Ty, FilenamesSize),
      llvm::ConstantInt::get(Int32Ty, CoverageMappingSize),
      llvm::ConstantInt::get(Int32Ty, llvm::coverage::CoverageMappingVersion1),
      RecordsVal,
      EncodedData};
  auto CovDataVal =
      llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
  auto CovData = new llvm::GlobalVariable(
      *getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage,
      CovDataVal, llvm::getCoverageMappingVarName());
  CovData->setSection(getCoverageSection(*this));
  CovData->setAlignment(8);

  addUsedGlobal(CovData);
}
<|endoftext|>