<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM 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) version 2.1 dated February 1999.

#ifndef MFEM_CUDA_HPP
#define MFEM_CUDA_HPP

#include <cstddef>

#ifdef MFEM_USE_CUDA
#include <cuda.h>
#endif

namespace mfem
{

#ifdef MFEM_USE_CUDA
#define MFEM_DEVICE __device__
#define MFEM_HOST_DEVICE __host__ __device__
inline void CuCheck(const unsigned int c)
{
   MFEM_ASSERT(c == cudaSuccess, cudaGetErrorString(cudaGetLastError()));
}
#if __CUDA_ARCH__ < 600
static __device__ double atomicAdd(double* address, double val)
{
   unsigned long long int* address_as_ull = (unsigned long long int*)address;
   unsigned long long int old = *address_as_ull, assumed;
   do
   {
      assumed = old;
      old =
         atomicCAS(address_as_ull, assumed,
                   __double_as_longlong(val +
                                        __longlong_as_double(assumed)));
      // Note: uses integer comparison to avoid hang in case of NaN
      // (since NaN != NaN)
   }
   while (assumed != old);
   return __longlong_as_double(old);
}
#endif // __CUDA_ARCH__ < 600
#else // MFEM_USE_CUDA
#define MFEM_DEVICE
#define MFEM_HOST_DEVICE
typedef int CUdevice;
typedef int CUcontext;
typedef void* CUstream;
#endif // MFEM_USE_CUDA

#ifdef __CUDA_ARCH__
template<typename T> MFEM_DEVICE
inline T AtomicAdd(T* address, T val)
{
   return atomicAdd(address, val);
}
#else
template<typename T> inline T AtomicAdd(T* address, T val)
{
#if defined(_OPENMP)
   #pragma omp atomic
#endif
   *address += val;
   return *address;
}
#endif

/// Allocates device memory
void* CuMemAlloc(void **d_ptr, size_t bytes);

/// Frees device memory
void* CuMemFree(void *d_ptr);

/// Copies memory from Host to Device
void* CuMemcpyHtoD(void *d_dst, const void *h_src, size_t bytes);

/// Copies memory from Host to Device
void* CuMemcpyHtoDAsync(void *d_dst, const void *h_src,
                        size_t bytes, void *stream);

/// Copies memory from Device to Device
void* CuMemcpyDtoD(void *d_dst, void *d_src, size_t bytes);

/// Copies memory from Device to Device
void* CuMemcpyDtoDAsync(void *d_dst, void *d_src, size_t bytes, void *stream);

/// Copies memory from Device to Host
void* CuMemcpyDtoH(void *h_dst, void *d_src, size_t bytes);

/// Copies memory from Device to Host
void* CuMemcpyDtoHAsync(void *h_dst, void *d_src, size_t bytes, void *stream);

} // namespace mfem

#endif // MFEM_CUDA_HPP
<commit_msg>__CUDA_ARCH__ to __NVCC__<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM 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) version 2.1 dated February 1999.

#ifndef MFEM_CUDA_HPP
#define MFEM_CUDA_HPP

#include <cstddef>

#ifdef MFEM_USE_CUDA
#include <cuda.h>
#endif

namespace mfem
{

#ifdef MFEM_USE_CUDA
#define MFEM_DEVICE __device__
#define MFEM_HOST_DEVICE __host__ __device__
inline void CuCheck(const unsigned int c)
{
   MFEM_ASSERT(c == cudaSuccess, cudaGetErrorString(cudaGetLastError()));
}
#if __CUDA_ARCH__ < 600
static __device__ double atomicAdd(double* address, double val)
{
   unsigned long long int* address_as_ull = (unsigned long long int*)address;
   unsigned long long int old = *address_as_ull, assumed;
   do
   {
      assumed = old;
      old =
         atomicCAS(address_as_ull, assumed,
                   __double_as_longlong(val +
                                        __longlong_as_double(assumed)));
      // Note: uses integer comparison to avoid hang in case of NaN
      // (since NaN != NaN)
   }
   while (assumed != old);
   return __longlong_as_double(old);
}
#endif // __CUDA_ARCH__ < 600
#else // MFEM_USE_CUDA
#define MFEM_DEVICE
#define MFEM_HOST_DEVICE
typedef int CUdevice;
typedef int CUcontext;
typedef void* CUstream;
#endif // MFEM_USE_CUDA

#ifdef __NVCC__
template<typename T> MFEM_DEVICE
inline T AtomicAdd(T* address, T val)
{
   return atomicAdd(address, val);
}
#else // __NVCC__
template<typename T> inline T AtomicAdd(T* address, T val)
{
#if defined(_OPENMP)
   #pragma omp atomic
#endif
   *address += val;
   return *address;
}
#endif // __NVCC__

/// Allocates device memory
void* CuMemAlloc(void **d_ptr, size_t bytes);

/// Frees device memory
void* CuMemFree(void *d_ptr);

/// Copies memory from Host to Device
void* CuMemcpyHtoD(void *d_dst, const void *h_src, size_t bytes);

/// Copies memory from Host to Device
void* CuMemcpyHtoDAsync(void *d_dst, const void *h_src,
                        size_t bytes, void *stream);

/// Copies memory from Device to Device
void* CuMemcpyDtoD(void *d_dst, void *d_src, size_t bytes);

/// Copies memory from Device to Device
void* CuMemcpyDtoDAsync(void *d_dst, void *d_src, size_t bytes, void *stream);

/// Copies memory from Device to Host
void* CuMemcpyDtoH(void *h_dst, void *d_src, size_t bytes);

/// Copies memory from Device to Host
void* CuMemcpyDtoHAsync(void *h_dst, void *d_src, size_t bytes, void *stream);

} // namespace mfem

#endif // MFEM_CUDA_HPP
<|endoftext|>


<commit_before>#include "ui_dock.h"
#include "core/alloc.h"
#include "core/math.h"
#include "ui_dock_private.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//const float g_splitPercentage = 0.5;	// TODO: Move to settings. Default split in middle (50/50)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockingGrid* UIDock_createGrid(Rect* rect)
{
	UIDockingGrid* grid = new UIDockingGrid;
	grid->rect = *rect;

	return grid;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDock* UIDock_addView(UIDockingGrid* grid, ViewPluginInstance* view)
{
	UIDock* dock = new UIDock(view);

	dock->view = view;
	dock->topSizer = &grid->topSizer;
	dock->bottomSizer = &grid->bottomSizer;
	dock->rightSizer = &grid->rightSizer;
	dock->leftSizer = &grid->leftSizer;

	// Add the dock to the sizers

	grid->topSizer.side1.push_back(dock);
	grid->bottomSizer.side0.push_back(dock);
	grid->rightSizer.side0.push_back(dock);
	grid->leftSizer.side1.push_back(dock);

	// If this is the first we we just set it as maximized

	if (grid->docks.size() == 0)
		dock->view->rect = grid->rect;

	// TODO: How should we really handle this case?

	grid->docks.push_back(dock);

	return dock;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void calcVerticalSizerSize(UIDockSizer* sizer, const Rect* rect)
{
	sizer->rect = *rect;

	sizer->rect.width = g_sizerSize;
	sizer->rect.height = rect->height;
	sizer->dir = UIDockSizerDir_Vert;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void calcHorizonalSizerSize(UIDockSizer* sizer, const Rect* rect)
{
	sizer->rect = *rect;

	sizer->rect.width = rect->width;
	sizer->rect.height = g_sizerSize;
	sizer->dir = UIDockSizerDir_Horz;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void dockSide(UIDockSide side, UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	UIDock* newDock = new UIDock(instance);
	UIDockSizer* sizer = new UIDockSizer;

	Rect rect = dock->view->rect;

	switch (side)
	{
		case UIDockSide_Top:
		case UIDockSide_Bottom:
		{
			rect.height /= 2;

			if (side == UIDockSide_Top)
				dock->view->rect.y += rect.height;
			else
				rect.y += rect.height;

			rect.height = int_min(rect.height - g_sizerSize, 0);
			calcHorizonalSizerSize(sizer, &rect);

			newDock->leftSizer = dock->leftSizer;
			newDock->rightSizer = dock->rightSizer;

			if (side == UIDockSide_Top)
			{
				newDock->topSizer = dock->topSizer;
				newDock->bottomSizer = sizer;
				dock->topSizer = sizer;

				sizer->side0.push_back(newDock);
				sizer->side1.push_back(dock);
			}
			else
			{
				newDock->bottomSizer = dock->bottomSizer;
				newDock->topSizer = sizer;
				dock->bottomSizer = sizer;

				sizer->side0.push_back(dock);
				sizer->side1.push_back(newDock);
			}

			break;
		}

		case UIDockSide_Right:
		case UIDockSide_Left:
		{
			rect.width /= 2;

			// if we connect on the left side we need to move the current view to the right
			// otherwise we move the new view to the side

			dock->view->rect.width = rect.width;

			if (side == UIDockSide_Left)
			{
				dock->view->rect.x += rect.width;
				rect.width = int_min(rect.width - g_sizerSize, 0);
			}
			else
			{
				rect.x += rect.width;
				dock->view->rect.x = int_min(dock->view->rect.x - g_sizerSize, 0);
				rect.width = int_min(rect.width - g_sizerSize, 0);
			}

			calcVerticalSizerSize(sizer, &rect);

			newDock->topSizer = dock->topSizer;
			newDock->bottomSizer = dock->bottomSizer;

			if (side == UIDockSide_Left)
			{
				newDock->leftSizer = dock->leftSizer;
				newDock->rightSizer = sizer;
				dock->leftSizer = sizer;

				sizer->side0.push_back(newDock);
				sizer->side1.push_back(dock);
			}
			else
			{
				newDock->rightSizer = dock->rightSizer;
				newDock->leftSizer = sizer;
				dock->rightSizer = sizer;

				sizer->side0.push_back(dock);
				sizer->side1.push_back(newDock);
			}

			// Add new dock to top/bottom sizer as both views now share it.

			dock->bottomSizer->side0.push_back(newDock);
			dock->topSizer->side1.push_back(newDock);

			break;
		}
	}

	newDock->view->rect = rect;

	grid->sizers.push_back(sizer);
	grid->docks.push_back(newDock);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static inline UIDockSizerDir isHoveringSizer(UIDockSizer* sizer, Vec2* size)
{
	UIDockSizerDir dir = sizer->dir;

	float x = sizer->rect.x;
	float y = sizer->rect.y;
	float w = x + sizer->rect.width;
	float h = y + sizer->rect.height;

	// resize the sizes with the snap area

	if (dir == UIDockSizerDir_Horz)
	{
		y -= g_sizerSnapSize;
		h += g_sizerSnapSize;
	}
	else
	{
		x -= g_sizerSnapSize;
		w += g_sizerSnapSize;
	}

	if ((size->x >= x && size->x < w) && (size->y >= y && size->y < h))
		return dir;

	return UIDockSizerDir_None;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_dockTop(UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	dockSide(UIDockSide_Top, grid, dock, instance);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_dockBottom(UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	dockSide(UIDockSide_Bottom, grid, dock, instance);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_dockLeft(UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	dockSide(UIDockSide_Left, grid, dock, instance);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_dockRight(UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	dockSide(UIDockSide_Right, grid, dock, instance);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockSizerDir UIDock_isHoveringSizer(UIDockingGrid* grid, Vec2* pos)
{
	for (UIDockSizer* sizer : grid->sizers)
	{
		UIDockSizerDir dir = isHoveringSizer(sizer, pos);

		if (dir != UIDockSizerDir_None)
			return dir;
	}

	return UIDockSizerDir_None;
}

/*

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_dockRight(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_dockBottom(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_dockTop(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_splitHorzUp(UIDock* dock, ViewPluginInstance* instance)
{

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_splitHorzDow(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_splitVertRight(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_splitVertLeft(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

*/

<commit_msg>Warning fixes<commit_after>#include "ui_dock.h"
#include "core/alloc.h"
#include "core/math.h"
#include "ui_dock_private.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//const float g_splitPercentage = 0.5;	// TODO: Move to settings. Default split in middle (50/50)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockingGrid* UIDock_createGrid(Rect* rect)
{
	UIDockingGrid* grid = new UIDockingGrid;
	grid->rect = *rect;

	return grid;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDock* UIDock_addView(UIDockingGrid* grid, ViewPluginInstance* view)
{
	UIDock* dock = new UIDock(view);

	dock->view = view;
	dock->topSizer = &grid->topSizer;
	dock->bottomSizer = &grid->bottomSizer;
	dock->rightSizer = &grid->rightSizer;
	dock->leftSizer = &grid->leftSizer;

	// Add the dock to the sizers

	grid->topSizer.side1.push_back(dock);
	grid->bottomSizer.side0.push_back(dock);
	grid->rightSizer.side0.push_back(dock);
	grid->leftSizer.side1.push_back(dock);

	// If this is the first we we just set it as maximized

	if (grid->docks.size() == 0)
		dock->view->rect = grid->rect;

	// TODO: How should we really handle this case?

	grid->docks.push_back(dock);

	return dock;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void calcVerticalSizerSize(UIDockSizer* sizer, const Rect* rect)
{
	sizer->rect = *rect;

	sizer->rect.width = g_sizerSize;
	sizer->rect.height = rect->height;
	sizer->dir = UIDockSizerDir_Vert;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void calcHorizonalSizerSize(UIDockSizer* sizer, const Rect* rect)
{
	sizer->rect = *rect;

	sizer->rect.width = rect->width;
	sizer->rect.height = g_sizerSize;
	sizer->dir = UIDockSizerDir_Horz;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void dockSide(UIDockSide side, UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	UIDock* newDock = new UIDock(instance);
	UIDockSizer* sizer = new UIDockSizer;

	Rect rect = dock->view->rect;

	switch (side)
	{
		case UIDockSide_Top:
		case UIDockSide_Bottom:
		{
			rect.height /= 2;

			if (side == UIDockSide_Top)
				dock->view->rect.y += rect.height;
			else
				rect.y += rect.height;

			rect.height = int_min(rect.height - g_sizerSize, 0);
			calcHorizonalSizerSize(sizer, &rect);

			newDock->leftSizer = dock->leftSizer;
			newDock->rightSizer = dock->rightSizer;

			if (side == UIDockSide_Top)
			{
				newDock->topSizer = dock->topSizer;
				newDock->bottomSizer = sizer;
				dock->topSizer = sizer;

				sizer->side0.push_back(newDock);
				sizer->side1.push_back(dock);
			}
			else
			{
				newDock->bottomSizer = dock->bottomSizer;
				newDock->topSizer = sizer;
				dock->bottomSizer = sizer;

				sizer->side0.push_back(dock);
				sizer->side1.push_back(newDock);
			}

			break;
		}

		case UIDockSide_Right:
		case UIDockSide_Left:
		{
			rect.width /= 2;

			// if we connect on the left side we need to move the current view to the right
			// otherwise we move the new view to the side

			dock->view->rect.width = rect.width;

			if (side == UIDockSide_Left)
			{
				dock->view->rect.x += rect.width;
				rect.width = int_min(rect.width - g_sizerSize, 0);
			}
			else
			{
				rect.x += rect.width;
				dock->view->rect.x = int_min(dock->view->rect.x - g_sizerSize, 0);
				rect.width = int_min(rect.width - g_sizerSize, 0);
			}

			calcVerticalSizerSize(sizer, &rect);

			newDock->topSizer = dock->topSizer;
			newDock->bottomSizer = dock->bottomSizer;

			if (side == UIDockSide_Left)
			{
				newDock->leftSizer = dock->leftSizer;
				newDock->rightSizer = sizer;
				dock->leftSizer = sizer;

				sizer->side0.push_back(newDock);
				sizer->side1.push_back(dock);
			}
			else
			{
				newDock->rightSizer = dock->rightSizer;
				newDock->leftSizer = sizer;
				dock->rightSizer = sizer;

				sizer->side0.push_back(dock);
				sizer->side1.push_back(newDock);
			}

			// Add new dock to top/bottom sizer as both views now share it.

			dock->bottomSizer->side0.push_back(newDock);
			dock->topSizer->side1.push_back(newDock);

			break;
		}
	}

	newDock->view->rect = rect;

	grid->sizers.push_back(sizer);
	grid->docks.push_back(newDock);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static inline UIDockSizerDir isHoveringSizer(UIDockSizer* sizer, Vec2* size)
{
	UIDockSizerDir dir = sizer->dir;

	float x = (float)sizer->rect.x;
	float y = (float)sizer->rect.y;
	float w = x + (float)sizer->rect.width;
	float h = y + (float)sizer->rect.height;

	// resize the sizes with the snap area

	if (dir == UIDockSizerDir_Horz)
	{
		y -= g_sizerSnapSize;
		h += g_sizerSnapSize;
	}
	else
	{
		x -= g_sizerSnapSize;
		w += g_sizerSnapSize;
	}

	if ((size->x >= x && size->x < w) && (size->y >= y && size->y < h))
		return dir;

	return UIDockSizerDir_None;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_dockTop(UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	dockSide(UIDockSide_Top, grid, dock, instance);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_dockBottom(UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	dockSide(UIDockSide_Bottom, grid, dock, instance);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_dockLeft(UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	dockSide(UIDockSide_Left, grid, dock, instance);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_dockRight(UIDockingGrid* grid, UIDock* dock, ViewPluginInstance* instance)
{
	dockSide(UIDockSide_Right, grid, dock, instance);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockSizerDir UIDock_isHoveringSizer(UIDockingGrid* grid, Vec2* pos)
{
	for (UIDockSizer* sizer : grid->sizers)
	{
		UIDockSizerDir dir = isHoveringSizer(sizer, pos);

		if (dir != UIDockSizerDir_None)
			return dir;
	}

	return UIDockSizerDir_None;
}

/*

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_dockRight(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_dockBottom(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_dockTop(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UIDock_splitHorzUp(UIDock* dock, ViewPluginInstance* instance)
{

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_splitHorzDow(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_splitVertRight(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UIDockStatus UIDock_splitVertLeft(UIDock* dock, ViewPluginInstance* instance)
{

	return UIDockStatus_ok;
}

*/

<|endoftext|>


<commit_before>/*
 * qca_securemessage.cpp - Qt Cryptographic Architecture
 * Copyright (C) 2003-2005  Justin Karneges <justin@affinix.com>
 * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
 *
 * This library 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 library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "qca_securemessage.h"

#include <qdatetime.h>
#include "qca_publickey.h"
#include "qca_cert.h"

namespace QCA {

//----------------------------------------------------------------------------
// SecureMessageKey
//----------------------------------------------------------------------------
SecureMessageKey::SecureMessageKey()
{
}

SecureMessageKey::SecureMessageKey(const SecureMessageKey &from)
{
	Q_UNUSED(from);
}

SecureMessageKey::~SecureMessageKey()
{
}

SecureMessageKey & SecureMessageKey::operator=(const SecureMessageKey &from)
{
	Q_UNUSED(from);
	return *this;
}

SecureMessageKey::Type SecureMessageKey::type() const
{
	return None;
}

QString SecureMessageKey::pgpPublicKey() const
{
	return QString();
}

QString SecureMessageKey::pgpSecretKey() const
{
	return QString();
}

void SecureMessageKey::setPGPPublicKey(const QString &id, const QString &name)
{
	Q_UNUSED(id);
	Q_UNUSED(name);
}

void SecureMessageKey::setPGPSecretKey(const QString &id)
{
	Q_UNUSED(id);
}

CertificateChain SecureMessageKey::x509CertificateChain() const
{
	return CertificateChain();
}

PrivateKey SecureMessageKey::x509PrivateKey() const
{
	return PrivateKey();
}

void SecureMessageKey::setX509CertificateChain(const CertificateChain &c)
{
	Q_UNUSED(c);
}

void SecureMessageKey::setX509PrivateKey(const PrivateKey &k)
{
	Q_UNUSED(k);
}

bool SecureMessageKey::havePrivate() const
{
	return false;
}

QString SecureMessageKey::id() const
{
	return QString();
}

QString SecureMessageKey::name() const
{
	return QString();
}

//----------------------------------------------------------------------------
// SecureMessage
//----------------------------------------------------------------------------
SecureMessage::SecureMessage(SecureMessageSystem *system)
{
	Q_UNUSED(system);
}

SecureMessage::~SecureMessage()
{
}

/*void SecureMessage::encrypt(const QSecureArray &in, const SecureMessageKey &key)
{
	Q_UNUSED(in);
	Q_UNUSED(key);
}

void SecureMessage::encrypt(const QSecureArray &in, const SecureMessageKeyList &keys)
{
	Q_UNUSED(in);
	Q_UNUSED(keys);
}

void SecureMessage::encryptAndSign(const QSecureArray &in, const SecureMessageKey &key, const SecureMessageKey &signer, Mode m)
{
	Q_UNUSED(in);
	Q_UNUSED(key);
	Q_UNUSED(signer);
	Q_UNUSED(m);
}

void SecureMessage::encryptAndSign(const QSecureArray &in, const SecureMessageKeyList &keys, const SecureMessageKey &signer, Mode m)
{
	Q_UNUSED(in);
	Q_UNUSED(keys);
	Q_UNUSED(signer);
	Q_UNUSED(m);
}

void SecureMessage::decrypt(const QString &in)
{
	Q_UNUSED(in);
}

void SecureMessage::sign(const QSecureArray &in, const SecureMessageKey &signer)
{
	Q_UNUSED(in);
	Q_UNUSED(signer);
}

void SecureMessage::verify(const QSecureArray &in, const QString &sig)
{
	Q_UNUSED(in);
	Q_UNUSED(sig);
}*/

bool SecureMessage::canSignMultiple() const
{
	return false;
}

void SecureMessage::setEnableBundleSigner(bool b)
{
	Q_UNUSED(b);
}

void SecureMessage::setFormat(Format f)
{
	Q_UNUSED(f);
}

void SecureMessage::setRecipient(const SecureMessageKey &key)
{
	Q_UNUSED(key);
}

void SecureMessage::setRecipients(const SecureMessageKeyList &keys)
{
	Q_UNUSED(keys);
}

void SecureMessage::setSigner(const SecureMessageKey &key)
{
	Q_UNUSED(key);
}

void SecureMessage::setSigners(const SecureMessageKeyList &keys)
{
	Q_UNUSED(keys);
}

void SecureMessage::startEncrypt()
{
}

void SecureMessage::startDecrypt()
{
}

void SecureMessage::startSign(bool detachedSignature)
{
	Q_UNUSED(detachedSignature);
}

void SecureMessage::startVerify(const QSecureArray &sig)
{
	Q_UNUSED(sig);
}

void SecureMessage::startEncryptAndSign(Order o)
{
	Q_UNUSED(o);
}

void SecureMessage::startDecryptAndVerify(Order o)
{
	Q_UNUSED(o);
}

void SecureMessage::update(const QSecureArray &in)
{
	Q_UNUSED(in);
}

QSecureArray SecureMessage::read(int size)
{
	Q_UNUSED(size);
	return QSecureArray();
}

int SecureMessage::bytesAvailable() const
{
	return 0;
}

void SecureMessage::end()
{
}

bool SecureMessage::waitForFinished()
{
	return false;
}

bool SecureMessage::success() const
{
	return false;
}

SecureMessage::Error SecureMessage::errorCode() const
{
	return ErrUnknown;
}

QSecureArray SecureMessage::signature() const
{
	return QSecureArray();
}

SecureMessage::VerifyResult SecureMessage::verifyResult() const
{
	return Invalid;
}

CertValidity SecureMessage::keyValidity() const
{
	return QCA::Valid;
}

SecureMessageKey SecureMessage::key() const
{
	return SecureMessageKey();
}

QDateTime SecureMessage::timestamp() const
{
	return QDateTime();
}

//----------------------------------------------------------------------------
// SecureMessageSystem
//----------------------------------------------------------------------------
SecureMessageSystem::SecureMessageSystem(QObject *parent, const char *name)
:QObject(parent, name)
{
}

SecureMessageSystem::~SecureMessageSystem()
{
}

//----------------------------------------------------------------------------
// OpenPGP
//----------------------------------------------------------------------------
OpenPGP::OpenPGP(QObject *parent, const char *name, const QString &provider)
:SecureMessageSystem(parent, name), Algorithm("openpgp", provider)
{
}

OpenPGP::~OpenPGP()
{
}

void OpenPGP::setAllowAgent(bool)
{
}

void OpenPGP::submitPassphrase(const QSecureArray &passphrase)
{
	Q_UNUSED(passphrase);
}

SecureMessageKeyList OpenPGP::secretKeys() const
{
	return SecureMessageKeyList();
}

SecureMessageKeyList OpenPGP::publicKeys() const
{
	return SecureMessageKeyList();
}

//----------------------------------------------------------------------------
// SMIME
//----------------------------------------------------------------------------
SMIME::SMIME(QObject *parent, const char *name, const QString &provider)
:SecureMessageSystem(parent, name), Algorithm("smime", provider)
{
}

SMIME::~SMIME()
{
}

void SMIME::setStore(const Store &store)
{
	Q_UNUSED(store);
}

void SMIME::setPrivateKeys(const QValueList<PrivateKey> &keys)
{
	Q_UNUSED(keys);
}

}
<commit_msg>Compile fix. I hope I went the right way.<commit_after>/*
 * qca_securemessage.cpp - Qt Cryptographic Architecture
 * Copyright (C) 2003-2005  Justin Karneges <justin@affinix.com>
 * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
 *
 * This library 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 library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "qca_securemessage.h"

#include <qdatetime.h>
#include "qca_publickey.h"
#include "qca_cert.h"

namespace QCA {

//----------------------------------------------------------------------------
// SecureMessageKey
//----------------------------------------------------------------------------
SecureMessageKey::SecureMessageKey()
{
}

SecureMessageKey::SecureMessageKey(const SecureMessageKey &from)
{
	Q_UNUSED(from);
}

SecureMessageKey::~SecureMessageKey()
{
}

SecureMessageKey & SecureMessageKey::operator=(const SecureMessageKey &from)
{
	Q_UNUSED(from);
	return *this;
}

SecureMessageKey::Type SecureMessageKey::type() const
{
	return None;
}

QString SecureMessageKey::pgpPublicKey() const
{
	return QString();
}

QString SecureMessageKey::pgpSecretKey() const
{
	return QString();
}

void SecureMessageKey::setPGPPublicKey(const QString &id, const QString &name)
{
	Q_UNUSED(id);
	Q_UNUSED(name);
}

void SecureMessageKey::setPGPSecretKey(const QString &id)
{
	Q_UNUSED(id);
}

CertificateChain SecureMessageKey::x509CertificateChain() const
{
	return CertificateChain();
}

PrivateKey SecureMessageKey::x509PrivateKey() const
{
	return PrivateKey();
}

void SecureMessageKey::setX509CertificateChain(const CertificateChain &c)
{
	Q_UNUSED(c);
}

void SecureMessageKey::setX509PrivateKey(const PrivateKey &k)
{
	Q_UNUSED(k);
}

bool SecureMessageKey::havePrivate() const
{
	return false;
}

QString SecureMessageKey::id() const
{
	return QString();
}

QString SecureMessageKey::name() const
{
	return QString();
}

//----------------------------------------------------------------------------
// SecureMessage
//----------------------------------------------------------------------------
SecureMessage::SecureMessage(SecureMessageSystem *system)
{
	Q_UNUSED(system);
}

SecureMessage::~SecureMessage()
{
}

/*void SecureMessage::encrypt(const QSecureArray &in, const SecureMessageKey &key)
{
	Q_UNUSED(in);
	Q_UNUSED(key);
}

void SecureMessage::encrypt(const QSecureArray &in, const SecureMessageKeyList &keys)
{
	Q_UNUSED(in);
	Q_UNUSED(keys);
}

void SecureMessage::encryptAndSign(const QSecureArray &in, const SecureMessageKey &key, const SecureMessageKey &signer, Mode m)
{
	Q_UNUSED(in);
	Q_UNUSED(key);
	Q_UNUSED(signer);
	Q_UNUSED(m);
}

void SecureMessage::encryptAndSign(const QSecureArray &in, const SecureMessageKeyList &keys, const SecureMessageKey &signer, Mode m)
{
	Q_UNUSED(in);
	Q_UNUSED(keys);
	Q_UNUSED(signer);
	Q_UNUSED(m);
}

void SecureMessage::decrypt(const QString &in)
{
	Q_UNUSED(in);
}

void SecureMessage::sign(const QSecureArray &in, const SecureMessageKey &signer)
{
	Q_UNUSED(in);
	Q_UNUSED(signer);
}

void SecureMessage::verify(const QSecureArray &in, const QString &sig)
{
	Q_UNUSED(in);
	Q_UNUSED(sig);
}*/

bool SecureMessage::canSignMultiple() const
{
	return false;
}

void SecureMessage::setEnableBundleSigner(bool b)
{
	Q_UNUSED(b);
}

void SecureMessage::setFormat(Format f)
{
	Q_UNUSED(f);
}

void SecureMessage::setRecipient(const SecureMessageKey &key)
{
	Q_UNUSED(key);
}

void SecureMessage::setRecipients(const SecureMessageKeyList &keys)
{
	Q_UNUSED(keys);
}

void SecureMessage::setSigner(const SecureMessageKey &key)
{
	Q_UNUSED(key);
}

void SecureMessage::setSigners(const SecureMessageKeyList &keys)
{
	Q_UNUSED(keys);
}

void SecureMessage::startEncrypt()
{
}

void SecureMessage::startDecrypt()
{
}

void SecureMessage::startSign(SignMode m = Message);
{
	Q_UNUSED(m);
}

void SecureMessage::startVerify(const QSecureArray &sig)
{
	Q_UNUSED(sig);
}

void SecureMessage::startEncryptAndSign(Order o)
{
	Q_UNUSED(o);
}

void SecureMessage::startDecryptAndVerify(Order o)
{
	Q_UNUSED(o);
}

void SecureMessage::update(const QSecureArray &in)
{
	Q_UNUSED(in);
}

QSecureArray SecureMessage::read(int size)
{
	Q_UNUSED(size);
	return QSecureArray();
}

int SecureMessage::bytesAvailable() const
{
	return 0;
}

void SecureMessage::end()
{
}

bool SecureMessage::waitForFinished()
{
	return false;
}

bool SecureMessage::success() const
{
	return false;
}

SecureMessage::Error SecureMessage::errorCode() const
{
	return ErrUnknown;
}

QSecureArray SecureMessage::signature() const
{
	return QSecureArray();
}

SecureMessage::VerifyResult SecureMessage::verifyResult() const
{
	return Invalid;
}

CertValidity SecureMessage::keyValidity() const
{
	return QCA::Valid;
}

SecureMessageKey SecureMessage::key() const
{
	return SecureMessageKey();
}

QDateTime SecureMessage::timestamp() const
{
	return QDateTime();
}

//----------------------------------------------------------------------------
// SecureMessageSystem
//----------------------------------------------------------------------------
SecureMessageSystem::SecureMessageSystem(QObject *parent, const char *name)
:QObject(parent, name)
{
}

SecureMessageSystem::~SecureMessageSystem()
{
}

//----------------------------------------------------------------------------
// OpenPGP
//----------------------------------------------------------------------------
OpenPGP::OpenPGP(QObject *parent, const char *name, const QString &provider)
:SecureMessageSystem(parent, name), Algorithm("openpgp", provider)
{
}

OpenPGP::~OpenPGP()
{
}

void OpenPGP::setAllowAgent(bool)
{
}

void OpenPGP::submitPassphrase(const QSecureArray &passphrase)
{
	Q_UNUSED(passphrase);
}

SecureMessageKeyList OpenPGP::secretKeys() const
{
	return SecureMessageKeyList();
}

SecureMessageKeyList OpenPGP::publicKeys() const
{
	return SecureMessageKeyList();
}

//----------------------------------------------------------------------------
// SMIME
//----------------------------------------------------------------------------
SMIME::SMIME(QObject *parent, const char *name, const QString &provider)
:SecureMessageSystem(parent, name), Algorithm("smime", provider)
{
}

SMIME::~SMIME()
{
}

void SMIME::setStore(const Store &store)
{
	Q_UNUSED(store);
}

void SMIME::setPrivateKeys(const QValueList<PrivateKey> &keys)
{
	Q_UNUSED(keys);
}

}
<|endoftext|>


<commit_before>#pragma once

#include <iterator>
#include <stdexcept>
#include <limits>
#include <functional>

#include "acmacs-base/throw.hh"
#include "acmacs-base/stream.hh"

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

namespace _acmacs_base_internal
{
    template <typename T, typename Increment> class input_iterator : public std::iterator<std::input_iterator_tag, T>
    {
     public:
        constexpr static const T End{std::numeric_limits<T>::max()};

        inline input_iterator() : current(End) {}
        inline input_iterator(T aFirst, const Increment& aIncrement) : current(aFirst), increment(aIncrement) { increment.find_valid(current); }
        inline input_iterator(T aFirst, Increment&& aIncrement) : current(aFirst), increment(std::move(aIncrement)) { increment.find_valid(current); }

        inline input_iterator& operator++() { increment(current); return *this;}
          // inline input_iterator operator++(int) { input_iterator result = *this; ++(*this); return result; }
        inline bool operator==(const input_iterator& other) const { return current == other.current; }
        inline bool operator!=(const input_iterator& other) const { return !(*this == other); }
        inline const T& operator*() const { return current; }
        inline T& operator*() { return current; }

     private:
        T current;
        Increment increment;

    }; // input_iterator<>

} // namespace _acmacs_base_internal

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

template <typename T> class Range
{
 private:
    class increment
    {
     public:
        inline increment() {}
        inline increment(T aStep, T aLast) : step(aStep), last(aLast) { if (step == T{0}) THROW_OR_VOID(std::runtime_error("Invalid range with step 0")); }
        inline void operator()(T& current)
            {
                if (current != _acmacs_base_internal::input_iterator<T, increment>::End) {
                    current += step;
                    if (step > 0) {
                        if (current >= last)
                            current = _acmacs_base_internal::input_iterator<T, increment>::End;
                    }
                    else {
                        if (current <= last)
                            current = _acmacs_base_internal::input_iterator<T, increment>::End;
                    }
                }
            }

        inline void find_valid(T&) {}

     private:
        T step;
        T last;
    };

    class iterator : public _acmacs_base_internal::input_iterator<T, increment>
    {
     public:
        inline iterator() : _acmacs_base_internal::input_iterator<T, increment>() {}
        inline iterator(T aFirst, T aLast, T aStep) : _acmacs_base_internal::input_iterator<T, increment>(aFirst, {aStep, aLast}) {}
    };

 public:
    static inline iterator begin(T first, T last, T step = T{1})
        {
            return {first, last, step};
        }

    static inline iterator begin(T last)
        {
            return {T{0}, last, T{1}};
        }

    static inline iterator end()
        {
            return {};
        }

}; // class Range

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

class IndexGenerator
{
 public:
    using Validator = std::function<bool (size_t)>;

 private:
    class increment
    {
     public:
        inline increment() {}
        inline increment(size_t aLast, Validator aValidator) : last(aLast), valid(aValidator) {}
        inline bool end(size_t current) const { return current == _acmacs_base_internal::input_iterator<size_t, increment>::End; }
        inline size_t end() const { return _acmacs_base_internal::input_iterator<size_t, increment>::End; }

        inline void operator()(size_t& current)
            {
                if (!end(current)) {
                    ++current;
                    while (current < last && !valid(current))
                        ++current;
                    if (current >= last)
                        current = end();
                }
            }

        inline void find_valid(size_t& current)
            {
                while (!end(current) && !valid(current))
                    operator()(current);
            }

        size_t last;
        Validator valid;
    };

 public:
    inline IndexGenerator(size_t aFirst, size_t aLast, Validator aValidator) : mFirst(aFirst), mIncrement(aLast, aValidator) {}
    inline IndexGenerator(size_t aLast, Validator aValidator) : mFirst(0), mIncrement(aLast, aValidator) {}

    using iterator = _acmacs_base_internal::input_iterator<size_t, IndexGenerator::increment>;

    inline iterator begin() const { return {mFirst, mIncrement}; }
    inline iterator end() const { return {}; }

 private:
    size_t mFirst;
    increment mIncrement;

}; // class IndexGenerator

#ifdef ACMACS_TARGET_OS
inline std::ostream& operator << (std::ostream& out, const IndexGenerator& aGen)
{
    return stream_internal::write_to_stream(out, aGen, "<", ">", ", ");
}
#endif

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>incrementer<commit_after>#pragma once

#include <iterator>
#include <stdexcept>
#include <limits>
#include <functional>

#include "acmacs-base/throw.hh"
#include "acmacs-base/stream.hh"

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

namespace _acmacs_base_internal
{
    template <typename T, typename Increment> class input_iterator : public std::iterator<std::input_iterator_tag, T>
    {
     public:
        constexpr static const T End{std::numeric_limits<T>::max()};

        inline input_iterator() : current(End) {}
        inline input_iterator(T aFirst, const Increment& aIncrement) : current(aFirst), increment(aIncrement) { increment.find_valid(current); }
        inline input_iterator(T aFirst, Increment&& aIncrement) : current(aFirst), increment(std::move(aIncrement)) { increment.find_valid(current); }

        inline input_iterator& operator++() { increment(current); return *this;}
          // inline input_iterator operator++(int) { input_iterator result = *this; ++(*this); return result; }
        inline bool operator==(const input_iterator& other) const { return current == other.current; }
        inline bool operator!=(const input_iterator& other) const { return !(*this == other); }
        inline const T& operator*() const { return current; }
        inline T& operator*() { return current; }

     private:
        T current;
        Increment increment;

    }; // input_iterator<>

} // namespace _acmacs_base_internal

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

// template <typename T> class Range
// {
//  private:
//     class increment
//     {
//      public:
//         inline increment() {}
//         inline increment(T aStep, T aLast) : step(aStep), last(aLast) { if (step == T{0}) THROW_OR_VOID(std::runtime_error("Invalid range with step 0")); }
//         inline void operator()(T& current)
//             {
//                 if (current != _acmacs_base_internal::input_iterator<T, increment>::End) {
//                     current += step;
//                     if (step > 0) {
//                         if (current >= last)
//                             current = _acmacs_base_internal::input_iterator<T, increment>::End;
//                     }
//                     else {
//                         if (current <= last)
//                             current = _acmacs_base_internal::input_iterator<T, increment>::End;
//                     }
//                 }
//             }

//         inline void find_valid(T&) {}

//      private:
//         T step;
//         T last;
//     };

//     class iterator : public _acmacs_base_internal::input_iterator<T, increment>
//     {
//      public:
//         inline iterator() : _acmacs_base_internal::input_iterator<T, increment>() {}
//         inline iterator(T aFirst, T aLast, T aStep) : _acmacs_base_internal::input_iterator<T, increment>(aFirst, {aStep, aLast}) {}
//     };

//  public:
//     static inline iterator begin(T first, T last, T step = T{1})
//         {
//             return {first, last, step};
//         }

//     static inline iterator begin(T last)
//         {
//             return {T{0}, last, T{1}};
//         }

//     static inline iterator end()
//         {
//             return {};
//         }

// }; // class Range

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

class IndexGenerator
{
 public:
    using Validator = std::function<bool (size_t)>;

 private:
    class increment
    {
     public:
        inline increment() {}
        inline increment(size_t aLast, Validator aValidator) : last(aLast), valid(aValidator) {}
        inline bool end(size_t current) const { return current == _acmacs_base_internal::input_iterator<size_t, increment>::End; }
        inline size_t end() const { return _acmacs_base_internal::input_iterator<size_t, increment>::End; }

        inline void operator()(size_t& current)
            {
                if (!end(current)) {
                    ++current;
                    while (current < last && !valid(current))
                        ++current;
                    if (current >= last)
                        current = end();
                }
            }

        inline void find_valid(size_t& current)
            {
                while (!end(current) && !valid(current))
                    operator()(current);
            }

        size_t last;
        Validator valid;
    };

 public:
    inline IndexGenerator(size_t aFirst, size_t aLast, Validator aValidator) : mFirst(aFirst), mIncrement(aLast, aValidator) {}
    inline IndexGenerator(size_t aLast, Validator aValidator) : mFirst(0), mIncrement(aLast, aValidator) {}

    using iterator = _acmacs_base_internal::input_iterator<size_t, IndexGenerator::increment>;

    inline iterator begin() const { return {mFirst, mIncrement}; }
    inline iterator end() const { return {}; }

 private:
    size_t mFirst;
    increment mIncrement;

}; // class IndexGenerator

#ifdef ACMACS_TARGET_OS
inline std::ostream& operator << (std::ostream& out, const IndexGenerator& aGen)
{
    return stream_internal::write_to_stream(out, aGen, "<", ">", ", ");
}
#endif

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

template <typename Index> class incrementer
{
 public:
    class iterator
    {
     public:
        using difference_type = long;
        using value_type = Index;
        using pointer = Index*;
        using reference = Index&;
        using iterator_category = std::random_access_iterator_tag;

        inline iterator& operator++() { ++value; return *this;}
        inline iterator operator++(int) { iterator retval = *this; ++(*this); return retval;}
        inline bool operator==(iterator other) const { return value == other.value; }
        inline bool operator!=(iterator other) const { return !(*this == other); }
        inline value_type operator*() { return value; }
        inline difference_type operator-(iterator other) const { return static_cast<difference_type>(value) - static_cast<difference_type>(other.value); }

     private:
        value_type value;
        inline iterator(value_type aValue) : value(aValue) {}

        friend class incrementer<Index>;
    };

    inline incrementer(Index aBegin, Index aEnd) : mBegin{aBegin}, mEnd{aEnd} {}

    static inline iterator begin(Index aValue = 0) { return iterator(aValue); }
    static inline iterator end(Index aValue) { return iterator(aValue); }

    inline iterator begin() { return begin(mBegin); }
    inline iterator end() { return end(mBegin); }

 private:
    Index mBegin, mEnd;

}; // class incrementer<>

template <typename Index> inline void fill_with_indexes(std::vector<Index>& aToFill, Index aBegin, Index aEnd)
{
    aToFill.resize(aEnd - aBegin);
    std::copy(incrementer<Index>::begin(aBegin), incrementer<Index>::end(aEnd), aToFill.begin());
}

template <typename Index> inline void fill_with_indexes(std::vector<Index>& aToFill, Index aSize)
{
    aToFill.resize(aSize);
    std::copy(incrementer<Index>::begin(0), incrementer<Index>::end(aSize), aToFill.begin());
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <typeinfo>
#include <string.h>
#include <stdarg.h>
#define intl int
#ifndef stringlength
#define stringlength 256
#endif
#define bufferlength 256
#define bufferlistsize 256
#define multilistlength 256
#define REGISTER_content the_template.possible_contents.add
struct stringstruct
{
	char a[stringlength+1];
	stringstruct(const char * in) {strcpy(a,in);}
	stringstruct(){};
};

char tagnamestring[stringlength+1];
char attstring[bufferlength+1];
intl tagnamestring_length;
intl attstring_length;

/*stringstruct operator = (char* input)
{
	stringstruct wert;
	strncpy(wert.a,input);
	return wert;
};*/
class basic_xml_element_set;
struct multilistlist_
{
	char names[multilistlength][stringlength+1];
	void * instances[multilistlength];

} multilistlist;
intl multilist_count = 0;
template <class whatabout> class  multilistreference;
class basicmultilist
{
	public:
	basicmultilist(){};
	~basicmultilist(){};
};
template <class whatabout> class multilist : basicmultilist
{
	public:
	whatabout * bufferlist;
	multilistreference<whatabout> * dependants[bufferlistsize];
	intl filllevel;
	intl ourcount;
	multilist()
	{
		filllevel=0;
		ourcount=0;
		bufferlist=(whatabout*)malloc(sizeof(whatabout)*bufferlistsize);
		return;
	}
	intl insert(whatabout input,intl position,intl mynumber)
	{
		for (int ilv1=filllevel;ilv1>position;ilv1--)
		{
			bufferlist[ilv1]=bufferlist[ilv1-1];
		}
		for (int ilv1=mynumber+1;ilv1<ourcount;ilv1++)
		{
			(*dependants[ilv1]).start_in_it++;
		}
		bufferlist[position]=input;
		filllevel++;
	}
	intl getme(multilistreference<whatabout> * input)
	{
		(*input).start_in_it=filllevel;
		(*input).count_in_it=0;
		return ourcount++;
	}
	~multilist()
	{
		free(bufferlist);
	};
};
multilist<stringstruct> stringlist=multilist<stringstruct>();
basic_xml_element_set* xml_set_register[bufferlistsize];
intl xml_set_register_count=0;

template <class whatabout> multilist<whatabout> * registermultilist(const char * thetypesname)
{
	for (int ilv1=0;ilv1<multilist_count;ilv1++)
	{
		if (strcmp(thetypesname,multilistlist.names[ilv1]))
		{
			return (multilist<whatabout> *) multilistlist.instances[ilv1];
		}
	}
	multilistlist.instances[multilist_count]=new(multilist<whatabout>);
	strcpy(multilistlist.names[multilist_count++],thetypesname);
}

class basicmultilistreference
{
	public:
	basicmultilistreference(){};
	~basicmultilistreference(){};
};

template <class whatabout> class multilistreference : basicmultilistreference
{
	public:
	multilist<whatabout> * instances;
	intl start_in_it;
	intl count_in_it;
	intl mynumber;
	void add(whatabout input)
	{
		(*instances).insert(input,start_in_it+count_in_it,mynumber);
	}
	multilistreference()
	{
		if (typeid(whatabout)==typeid(stringstruct))
		{
			instances=(multilist<whatabout>*)&stringlist;
		}
		else
		{
			instances=registermultilist<whatabout>(typeid(whatabout).name());
			/*multilistreference(backvalue);*/
			mynumber=(*instances).getme(this);
		}
	};
	void multilistreferenx(multilist<whatabout> * input)
	{
		instances=input;
		mynumber=(*instances).getme(this);
	};
	~multilistreference(){};
};

struct xml_template_element
{
	public:
	stringstruct name;
	multilistreference<stringstruct> possible_contents;
	basic_xml_element_set * content;
};

class basic_instance
{
	public:
	basic_instance * master;
	basic_instance * children;
	char myname[stringlength+1];
	basic_instance(){master=NULL;};
	~basic_instance(){};
};

class basic_xml_element_set
{
	public:
	xml_template_element the_template;
	basic_instance * instances;
	char name[stringlength+1];
	multilistreference<stringstruct> possible_contents;
	basic_xml_element_set()
	{
		possible_contents=multilistreference<stringstruct>();
	};
	~basic_xml_element_set() {};
};

template <class whatabout> class xml_element_set:basic_xml_element_set
{
	public:
	multilistreference<whatabout> instances;
	xml_element_set()
	{
		/*
		if (typeid(whatabout)==typeid(cdxml_instance))
		{
			REGISTER_content("page");
		}
		if (typeid(whatabout)==typeid(page_instance))
		{
			REGISTER_content("fragment");
			REGISTER_content("group");
		}
		if (typeid(whatabout)==typeid(group_instance))
		{
			REGISTER_content("fragment");
			REGISTER_content("group");
		}
		if (typeid(whatabout)==typeid(fragment_instance))
		{
			REGISTER_content("fragment");
			REGISTER_content("group");
		}
		*/
		strcpy(name,typeid(whatabout).name());
		name[strlen(name)-strlen("_instance")]=0;
		xml_set_register[xml_set_register_count++]=this;
	};
	xml_element_set(const char * first,...)
	{
		va_list inlist;
		const char * wert=first;
		va_start(inlist,first);
		back:
		REGISTER_content(wert);
		wert=va_arg(inlist,char *);
		if (wert!=0)
		{
			goto back;
		}
		va_end(inlist);
		strcpy(name,typeid(whatabout).name());
		name[strlen(name)-strlen("_instance")]=0;
		xml_set_register[xml_set_register_count++]=this;
	}
	~xml_element_set(){};
};

struct superconstellation
{
	char name[10];
	char * ref;
};
//This is a hack:
//1. Objects dependent on variables initalized out of code area
//2. Object stringlist which all depend on during initialization initialized out of code area
//3. Offsetof with inherited objects.
//4. Initialization of a static list members in order to obtain self-reflecting code.
struct page_instance:basic_instance
{
};
xml_element_set<page_instance> page_xml_element_set("fragment","group",NULL);

struct cdxml_instance:basic_instance
{
	multilistreference<page_instance> page;
	static superconstellation contents[];
};
superconstellation cdxml_instance::contents[]={{"name",(char*)offsetof(cdxml_instance,page)}};

xml_element_set<cdxml_instance> cdxml_xml_element_set("page",NULL);

struct group_instance:basic_instance
{
};
xml_element_set<group_instance> group_xml_element_set("fragment","group",NULL);

struct fragment_instance:basic_instance
{
};
xml_element_set<fragment_instance> fragment_xml_element_set("n","b",NULL);

char sentenumeric(char input)
{
	if ((input>='a') && (input<='z'))
	{
		return 1;
	}
	if ((input>='A') && (input<='Z'))
	{
		return 1;
	}
	if ((input>='0') && (input<='9'))
	{
		return 1;
	}
	if (input=='_')
	{
		return 1;
	}
	return 0;
}

void entertag()
{
	tagnamestring[tagnamestring_length]=0;
	printf("enter %s\n",tagnamestring);
};

void concludeattstring()
{
	attstring[tagnamestring_length]=0;
};

void exittag(){};
char spaciatic(char input)
{
	if (input==' ')
	{
		return 1;
	}
	if (input==10)
	{
		return 1;
	}
	if (input==13)
	{
		return 1;
	}
	return 0;
}

void input_fsm(FILE* infile)
{
	intl fsmint=0; //0: in_nothing. 1: bracket-opening 2: Tagreading 3: attstringreading 4: bracket-closing 5: Qmark-ignoring 7: waiting_for_tag_end 8: Addstring - Hyphenation
	char ichar='A';
	bool bexittag=0;
	#ifdef DEBUG
	intl debugcounter=0;
	#endif
	iback:
	fread(&ichar,1,1,infile);
	#ifdef DEBUG
	debugcounter++;
	#endif
	switch (fsmint)
	{
		case 0:
			if (ichar=='<')
			{
				fsmint=1;
				break;
			}
		break;
		case 1:
			if (bexittag==1)
			{
				if (ichar=='/')
				{
					printf("Error: The Tag to end was defined by another /");exit(1);
					break;
				}
				if (ichar=='>')
				{
					if (bexittag)
					{
						printf("Error: Only slash in Brackets!");exit(1);
						exittag();
					}
					break;
				}
				if (spaciatic(ichar))
				{
					break;
				}
			}
			if (spaciatic(ichar))
			{
				break;
			}
			if (sentenumeric(ichar))
			{
				tagnamestring[0]=ichar;
				tagnamestring_length=1;
				fsmint=2;
				break;
			}
			if (ichar=='?')
			{
				fsmint=5;
				break;
			}
			if (ichar=='!')
			{
				fsmint=5;
				break;
			}
			if (ichar=='/')
			{
				bexittag=1;
				break;
			}
			if (ichar=='>')
			{
				bexittag=0;
				fsmint=8;
			}
			printf("Error: invalid beginning of tag!");exit(1);
		break;
		case 2:
			if (sentenumeric(ichar))
			{
				tagnamestring[tagnamestring_length]=ichar;
				tagnamestring_length++;
			}
			else
			{
				entertag();
				fsmint=3;
			}
			if (ichar=='/')
			{
				exittag();
				fsmint=7;
				break;
			}
		break;
		case 3:
			if (ichar=='"')
			{
				fsmint=8;
			}
			if (ichar=='>')
			{
				bexittag=0;
				concludeattstring();
				fsmint=4;
			}
		break;
		case 8:
			if (ichar=='"')
			{
				fsmint=3;
				break;
			}
		break;
		case 4:
			if (ichar=='<')
			{
				printf("start ");
				fsmint=1;
			}
		break;
		case 5:
			if (ichar=='?')
			{
				fsmint=7;
				break;
			}
			if (ichar=='>')
			{
				fsmint=4;
				if (bexittag)
				{
					exittag();
					bexittag=0;
				}
				break;
			}
		break;
		case 7:
			if (spaciatic(ichar))
			{
				break;
			}
			if (ichar=='>')
			{
				fsmint=4;break;
			}
			printf("Error: \">\" expected at end of tag");
			for (int ilv1=0;ilv1<15;ilv1++)
			{
				#ifdef DEBUG
					printf("%%-> %llX <-i\n",debugcounter);
				#endif
				fread(&ichar,1,1,infile);
				printf("%c",ichar);
			}
			exit(1);
		break;
		default:
		printf("Invalid fsmint!!!!");
		exit(1);
	}
	if (!feof(infile))
	{
		goto iback;
	}
}

int main(int argc, char * * argv)
{
	xml_set_register_count=0;
	multilist_count=0;
	FILE * infile;
	infile=fopen(argv[1],"r+");
	input_fsm(infile);
	fclose(infile);
	return 0;
}
<commit_msg>Fiddling with multilistreference<commit_after>#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <typeinfo>
#include <string.h>
#include <stdarg.h>
#define intl int
#ifndef stringlength
#define stringlength 256
#endif
#define bufferlength 256
#define bufferlistsize 256
#define multilistlength 256
#define REGISTER_content the_template.possible_contents.add
struct stringstruct
{
	char a[stringlength+1];
	stringstruct(const char * in) {strcpy(a,in);}
	stringstruct(){};
};

char tagnamestring[stringlength+1];
char attstring[bufferlength+1];
intl tagnamestring_length;
intl attstring_length;

/*stringstruct operator = (char* input)
{
	stringstruct wert;
	strncpy(wert.a,input);
	return wert;
};*/
class basic_xml_element_set;
struct multilistlist_
{
	char names[multilistlength][stringlength+1];
	void * instances[multilistlength];

} multilistlist;
intl multilist_count = 0;
template <class whatabout> class  multilistreference;
class basicmultilist
{
	public:
	basicmultilist(){};
	~basicmultilist(){};
};
template <class whatabout> class multilist : basicmultilist
{
	public:
	whatabout * bufferlist;
	multilistreference<whatabout> * dependants[bufferlistsize];
	intl filllevel;
	intl ourcount;
	multilist()
	{
		filllevel=0;
		ourcount=0;
		bufferlist=(whatabout*)malloc(sizeof(whatabout)*bufferlistsize);
		return;
	}
	intl insert(whatabout input,intl position,intl mynumber)
	{
		for (int ilv1=filllevel;ilv1>position;ilv1--)
		{
			bufferlist[ilv1]=bufferlist[ilv1-1];
		}
		for (int ilv1=mynumber+1;ilv1<ourcount;ilv1++)
		{
			(*dependants[ilv1]).start_in_it++;
		}
		bufferlist[position]=input;
		filllevel++;
	}
	intl getme(multilistreference<whatabout> * input)
	{
		(*input).start_in_it=filllevel;
		(*input).count_in_it=0;
		return ourcount++;
	}
	~multilist()
	{
		free(bufferlist);
	};
};
multilist<stringstruct> stringlist=multilist<stringstruct>();
basic_xml_element_set* xml_set_register[bufferlistsize];
intl xml_set_register_count=0;

template <class whatabout> multilist<whatabout> * registermultilist(const char * thetypesname)
{
	for (int ilv1=0;ilv1<multilist_count;ilv1++)
	{
		if (strcmp(thetypesname,multilistlist.names[ilv1]))
		{
			return (multilist<whatabout> *) multilistlist.instances[ilv1];
		}
	}
	multilistlist.instances[multilist_count]=new(multilist<whatabout>);
	strcpy(multilistlist.names[multilist_count++],thetypesname);
}

class basicmultilistreference
{
	public:
	basicmultilistreference(){};
	~basicmultilistreference(){};
};

template <class whatabout> class multilistreference : basicmultilistreference
{
	public:
	basicmultilist * instances;
	intl start_in_it;
	intl count_in_it;
	intl mynumber;
	void add(whatabout input)
	{
		(*instances).insert(input,start_in_it+count_in_it,mynumber);
	}
	multilistreference()
	{
		if (typeid(whatabout)==typeid(stringstruct))
		{
			instances=(multilist<whatabout>*)&stringlist;
		}
		else
		{
			instances=registermultilist<whatabout>(typeid(whatabout).name());
			/*multilistreference(backvalue);*/
			mynumber=(*instances).getme(this);
		}
	};
	void multilistreferenx(multilist<whatabout> * input)
	{
		instances=input;
		mynumber=(*instances).getme(this);
	};
	~multilistreference(){};
};

struct xml_template_element
{
	public:
	stringstruct name;
	multilistreference<stringstruct> possible_contents;
	basic_xml_element_set * content;
};

struct superconstellation
{
	char name[10];
	char * ref;
};
struct basic_instance
{
	public:
	basic_instance * master;
	basic_instance * children;
	char myname[stringlength+1];
	basic_instance(){master=NULL;};
	~basic_instance(){};
};

class basic_xml_element_set
{
	public:
	xml_template_element the_template;
	basic_instance * instances;
	char name[stringlength+1];
	multilistreference<stringstruct> possible_contents;
	basic_xml_element_set()
	{
		possible_contents=multilistreference<stringstruct>();
	};
	~basic_xml_element_set() {};
};

template <class whatabout> class xml_element_set:basic_xml_element_set
{
	public:
	multilistreference<whatabout> instances;
	xml_element_set()
	{
		/*
		if (typeid(whatabout)==typeid(cdxml_instance))
		{
			REGISTER_content("page");
		}
		if (typeid(whatabout)==typeid(page_instance))
		{
			REGISTER_content("fragment");
			REGISTER_content("group");
		}
		if (typeid(whatabout)==typeid(group_instance))
		{
			REGISTER_content("fragment");
			REGISTER_content("group");
		}
		if (typeid(whatabout)==typeid(fragment_instance))
		{
			REGISTER_content("fragment");
			REGISTER_content("group");
		}
		*/
		strcpy(name,typeid(whatabout).name());
		name[strlen(name)-strlen("_instance")]=0;
		xml_set_register[xml_set_register_count++]=this;
	};
	xml_element_set(const char * first,...)
	{
		va_list inlist;
		const char * wert=first;
		va_start(inlist,first);
		back:
		REGISTER_content(wert);
		wert=va_arg(inlist,char *);
		if (wert!=0)
		{
			goto back;
		}
		va_end(inlist);
		strcpy(name,typeid(whatabout).name());
		name[strlen(name)-strlen("_instance")]=0;
		xml_set_register[xml_set_register_count++]=this;
	}
	~xml_element_set(){};
};

//This is a hack:
//1. Objects dependent on variables initalized out of code area
//2. Object stringlist which all depend on during initialization initialized out of code area
//3. Offsetof with inherited objects.
//4. Initialization of a static list members in order to obtain self-reflecting code.
//#include "filestructure.hxx"

struct cdxml_instance:basic_instance
{
	static superconstellation contents[];
	basicmultilistreference page;
};
superconstellation cdxml_instance::contents[]={{"page",(char*)offsetof(cdxml_instance,page)}};

struct page_instance:basic_instance
{
};
xml_element_set<page_instance> page_xml_element_set("fragment","group",NULL);

xml_element_set<cdxml_instance> cdxml_xml_element_set("page",NULL);

struct group_instance:basic_instance
{
};
xml_element_set<group_instance> group_xml_element_set("fragment","group",NULL);

struct fragment_instance:basic_instance
{
};
xml_element_set<fragment_instance> fragment_xml_element_set("n","b",NULL);

char sentenumeric(char input)
{
	if ((input>='a') && (input<='z'))
	{
		return 1;
	}
	if ((input>='A') && (input<='Z'))
	{
		return 1;
	}
	if ((input>='0') && (input<='9'))
	{
		return 1;
	}
	if (input=='_')
	{
		return 1;
	}
	return 0;
}

void entertag()
{
	tagnamestring[tagnamestring_length]=0;
	printf("enter %s\n",tagnamestring);
};

void concludeattstring()
{
	attstring[tagnamestring_length]=0;
};

void exittag(){};
char spaciatic(char input)
{
	if (input==' ')
	{
		return 1;
	}
	if (input==10)
	{
		return 1;
	}
	if (input==13)
	{
		return 1;
	}
	return 0;
}

void input_fsm(FILE* infile)
{
	intl fsmint=0; //0: in_nothing. 1: bracket-opening 2: Tagreading 3: attstringreading 4: bracket-closing 5: Qmark-ignoring 7: waiting_for_tag_end 8: Addstring - Hyphenation
	char ichar='A';
	bool bexittag=0;
	#ifdef DEBUG
	intl debugcounter=0;
	#endif
	iback:
	fread(&ichar,1,1,infile);
	#ifdef DEBUG
	debugcounter++;
	#endif
	switch (fsmint)
	{
		case 0:
			if (ichar=='<')
			{
				fsmint=1;
				break;
			}
		break;
		case 1:
			if (bexittag==1)
			{
				if (ichar=='/')
				{
					printf("Error: The Tag to end was defined by another /");exit(1);
					break;
				}
				if (ichar=='>')
				{
					if (bexittag)
					{
						printf("Error: Only slash in Brackets!");exit(1);
						exittag();
					}
					break;
				}
				if (spaciatic(ichar))
				{
					break;
				}
			}
			if (spaciatic(ichar))
			{
				break;
			}
			if (sentenumeric(ichar))
			{
				tagnamestring[0]=ichar;
				tagnamestring_length=1;
				fsmint=2;
				break;
			}
			if (ichar=='?')
			{
				fsmint=5;
				break;
			}
			if (ichar=='!')
			{
				fsmint=5;
				break;
			}
			if (ichar=='/')
			{
				bexittag=1;
				break;
			}
			if (ichar=='>')
			{
				bexittag=0;
				fsmint=8;
			}
			printf("Error: invalid beginning of tag!");exit(1);
		break;
		case 2:
			if (sentenumeric(ichar))
			{
				tagnamestring[tagnamestring_length]=ichar;
				tagnamestring_length++;
			}
			else
			{
				entertag();
				fsmint=3;
			}
			if (ichar=='/')
			{
				exittag();
				fsmint=7;
				break;
			}
		break;
		case 3:
			if (ichar=='"')
			{
				fsmint=8;
			}
			if (ichar=='>')
			{
				bexittag=0;
				concludeattstring();
				fsmint=4;
			}
		break;
		case 8:
			if (ichar=='"')
			{
				fsmint=3;
				break;
			}
		break;
		case 4:
			if (ichar=='<')
			{
				printf("start ");
				fsmint=1;
			}
		break;
		case 5:
			if (ichar=='?')
			{
				fsmint=7;
				break;
			}
			if (ichar=='>')
			{
				fsmint=4;
				if (bexittag)
				{
					exittag();
					bexittag=0;
				}
				break;
			}
		break;
		case 7:
			if (spaciatic(ichar))
			{
				break;
			}
			if (ichar=='>')
			{
				fsmint=4;break;
			}
			printf("Error: \">\" expected at end of tag");
			for (int ilv1=0;ilv1<15;ilv1++)
			{
				#ifdef DEBUG
					printf("%%-> %llX <-i\n",debugcounter);
				#endif
				fread(&ichar,1,1,infile);
				printf("%c",ichar);
			}
			exit(1);
		break;
		default:
		printf("Invalid fsmint!!!!");
		exit(1);
	}
	if (!feof(infile))
	{
		goto iback;
	}
}

int main(int argc, char * * argv)
{
	xml_set_register_count=0;
	multilist_count=0;
	FILE * infile;
	infile=fopen(argv[1],"r+");
	input_fsm(infile);
	fclose(infile);
	return 0;
}
<|endoftext|>


<commit_before>#include "csvmodelwriter.h"

#include <QAbstractItemModel>
#include <QFile>
#include <QTextStream>

CSVModelWriter::CSVModelWriter(const QString &filename, QObject *parent) :
    QObject(parent),
    filename(filename), model(0)
{
}

void CSVModelWriter::setModel(const QAbstractItemModel *model)
{
    this->model = model;
}

void CSVModelWriter::addColumn(const QString &title, int column, int role)
{
    Column col;
    col.title = title;
    col.column = column;
    col.role = role;

    columns.append(col);
}

static void writeValue(QTextStream &f, const QString &value)
{
    // TODO: quoting if " or \n in string
    f << "\"" << value << "\"";
}

static void writeSep(QTextStream &f)
{
    f << ",";
}

static void writeNewline(QTextStream &f)
{
    f << "\n";
}

bool CSVModelWriter::write()
{
    QFile file(filename);
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return false;
    QTextStream out(&file);

    int numRows = 0;
    if(model)
    {
        numRows = model->rowCount();
    }

    // Header row
    for(int i=0; i<columns.size(); ++i)
    {
        if(i!=0)
        {
            writeSep(out);
        }
        writeValue(out, columns[i].title);
    }
    writeNewline(out);

    // Data rows
    for(int j=0; j<numRows; ++j)
    {
        for(int i=0; i<columns.size(); ++i)
        {
            if(i!=0)
            {
                writeSep(out);
            }
            QVariant data = model->index(j, columns[i].column).data(columns[i].role);
            writeValue(out, data.toString());
        }
        writeNewline(out);
    }

    file.close();

    return file.error() == QFile::NoError;
}

<commit_msg>Properly escape " in strings when exporting CSV<commit_after>#include "csvmodelwriter.h"

#include <QAbstractItemModel>
#include <QFile>
#include <QTextStream>

CSVModelWriter::CSVModelWriter(const QString &filename, QObject *parent) :
    QObject(parent),
    filename(filename), model(0)
{
}

void CSVModelWriter::setModel(const QAbstractItemModel *model)
{
    this->model = model;
}

void CSVModelWriter::addColumn(const QString &title, int column, int role)
{
    Column col;
    col.title = title;
    col.column = column;
    col.role = role;

    columns.append(col);
}

static void writeValue(QTextStream &f, const QString &value)
{
    QString escaped = value;
    escaped.replace('"', "\"\"");
    f << "\"" << escaped << "\"";
}

static void writeSep(QTextStream &f)
{
    f << ",";
}

static void writeNewline(QTextStream &f)
{
    f << "\n";
}

bool CSVModelWriter::write()
{
    QFile file(filename);
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return false;
    QTextStream out(&file);

    int numRows = 0;
    if(model)
    {
        numRows = model->rowCount();
    }

    // Header row
    for(int i=0; i<columns.size(); ++i)
    {
        if(i!=0)
        {
            writeSep(out);
        }
        writeValue(out, columns[i].title);
    }
    writeNewline(out);

    // Data rows
    for(int j=0; j<numRows; ++j)
    {
        for(int i=0; i<columns.size(); ++i)
        {
            if(i!=0)
            {
                writeSep(out);
            }
            QVariant data = model->index(j, columns[i].column).data(columns[i].role);
            writeValue(out, data.toString());
        }
        writeNewline(out);
    }

    file.close();

    return file.error() == QFile::NoError;
}

<|endoftext|>


<commit_before>#define DEBUG_TYPE "enerc"
#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/BasicBlock.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/PassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/IRBuilder.h"

#include <sstream>
#include <set>
#include <cstdio>
#include <fstream>

#define ECQ_PRECISE 0
#define ECQ_APPROX 1

#define FUNC_TRACE "enerc_trace"

// I'm not sure why, but I can't seem to enable debug output in the usual way
// (with command line flags). Here's a hack.
#undef DEBUG
#define DEBUG(s) s

using namespace llvm;
namespace {

// Command-line flags.
cl::opt<bool> optInstrument ("accept-inst",
    cl::desc("ACCEPT: enable profiling instrumentation"));
cl::opt<bool> optRelax ("accept-relax",
    cl::desc("ACCEPT: enable relaxations"));

/**** HELPERS ****/

// Look at the qualifier metadata on the instruction and determine whether it
// has approximate semantics.
bool isApprox(Instruction *instr) {
  MDNode *md = instr->getMetadata("quals");
  if (!md)
    return false;

  Value *val = md->getOperand(0);
  ConstantInt *ci = cast<ConstantInt>(val);
  if (ci) {
    APInt intval = ci->getValue();
    return intval == ECQ_APPROX;
  } else {
    llvm::errs() << "INVALID METADATA";
    return false;
  }
}

// Is it legal to elide this instruction?
bool elidable_helper(Instruction *instr,
                     std::set<Instruction*> &seen) {
  // Check for cycles.
  if (seen.count(instr)) {
    llvm::errs() << "CYCLE DETECTED\n";
    return false;
  }
  seen.insert(instr);

  if (isApprox(instr)) {
    return true;
  } else if (isa<StoreInst>(instr) ||
             isa<ReturnInst>(instr) ||
             isa<BranchInst>(instr)) {
    // Precise stores, returns, branches: never elidable.
    return false;
  } else {
    // Recursive case: all consumers are elidable.
    for (Value::use_iterator ui = instr->use_begin();
          ui != instr->use_end(); ++ui) {
      Instruction *user = dyn_cast<Instruction>(*ui);
      if (user && !elidable_helper(user, seen)) {
        return false;
      }
    }
    return true; // No non-elidable consumers.
  }
}
// Start with an empty "seen" (cycle-detection) set.
bool elidable(Instruction *instr) {
  std::set<Instruction*> seen;
  return elidable_helper(instr, seen);
}

// Format a source position.
std::string srcPosDesc(const Module &mod, const DebugLoc &dl) {
  std::stringstream ss;
  ss << mod.getModuleIdentifier() << ":";
  ss << dl.getLine();
  if (dl.getCol())
    ss << "," << dl.getCol();
  return ss.str();
}

/**** THE MAIN LLVM PASS ****/

struct ACCEPTPass : public FunctionPass {
  static char ID;

  Constant *blockCountFunction;
  unsigned long gApproxInsts;
  unsigned long gElidableInsts;
  unsigned long gTotalInsts;
  Module *module;
  std::map<std::pair<int, int>, int> relaxConfig;  // kind, num -> param

  ACCEPTPass() : FunctionPass(ID) {
    gApproxInsts = 0;
    gElidableInsts = 0;
    gTotalInsts = 0;
    module = 0;
  }

  virtual void getAnalysisUsage(AnalysisUsage &Info) const {
    Info.addRequired<LoopInfo>();
  }

  virtual bool runOnFunction(Function &F) {
    countAndInstrument(F);
    return perforateLoops(F);
  }

  virtual bool doInitialization(Module &M) {
    module = &M;

    if (optInstrument)
      setUpInstrumentation();

    if (optRelax)
      loadRelaxConfig();

    return false;
  }

  virtual bool doFinalization(Module &M) {
    dumpStaticStats();
    if (!optRelax)
      dumpRelaxConfig();
    return false;
  }

  /**** TRACING AND STATISTICS ****/

  void countAndInstrument(Function &F) {
    for (Function::iterator bbi = F.begin(); bbi != F.end(); ++bbi) {
      unsigned int approxInsts = 0;
      unsigned int elidableInsts = 0;
      unsigned int totalInsts = 0;

      for (BasicBlock::iterator ii = bbi->begin(); ii != bbi->end();
            ++ii) {
        if ((Instruction*)ii == bbi->getTerminator()) {
          // Terminator instruction is not checked.
          continue;
        }

        // Record information about this instruction.
        bool iApprox = isApprox(ii);
        bool iElidable = elidable(ii);
        ++gTotalInsts;
        ++totalInsts;
        if (iApprox) {
          ++gApproxInsts;
          ++approxInsts;
        }
        if (iElidable) {
          ++gElidableInsts;
          ++elidableInsts;
        }
      }

      // Call the runtime profiling library for this block.
      if (optInstrument)
        insertTraceCall(F, bbi, approxInsts, elidableInsts, totalInsts);
    }
  }

  void setUpInstrumentation() {
    blockCountFunction = module->getOrInsertFunction(
      FUNC_TRACE,
      Type::getVoidTy(module->getContext()), // return type
      Type::getInt32Ty(module->getContext()), // approx
      Type::getInt32Ty(module->getContext()), // elidable
      Type::getInt32Ty(module->getContext()), // total
      NULL
    );
  }

  void insertTraceCall(Function &F, BasicBlock* bb,
                       unsigned int approx,
                       unsigned int elidable,
                       unsigned int total) {
    std::vector<Value *> args;
    args.push_back(
        ConstantInt::get(Type::getInt32Ty(F.getContext()), approx)
    );
    args.push_back(
        ConstantInt::get(Type::getInt32Ty(F.getContext()), elidable)
    );
    args.push_back(
        ConstantInt::get(Type::getInt32Ty(F.getContext()), total)
    );

    // For now, we're inserting calls at the end of basic blocks.
    CallInst::Create(
      blockCountFunction,
      args,
      "",
      bb->getTerminator()
    );
  }

  void dumpStaticStats() {
    FILE *results_file = fopen("enerc_static.txt", "w+");
    fprintf(results_file,
            "%lu %lu %lu\n", gApproxInsts, gElidableInsts, gTotalInsts);
    fclose(results_file);
  }

  /**** RELAXATION CONFIGURATION ***/

  typedef enum {
    rkPerforate
  } relaxKind;

  void dumpRelaxConfig() {
    std::ofstream configFile("accept_config.txt");;
    for (std::map<std::pair<int, int>, int>::iterator i = relaxConfig.begin();
         i != relaxConfig.end(); ++i) {
      configFile << i->first.first << " "
                 << i->first.second << " "
                 << i->second << "\n";
    }
    configFile.close();
  }

  void loadRelaxConfig() {
    std::ifstream configFile("accept_config.txt");;
    if (!configFile.good()) {
      errs() << "no config file; no optimizations will occur\n";
      return;
    }

    while (configFile.good()) {
      int kind;
      int ident;
      int param;
      configFile >> kind >> ident >> param;
      relaxConfig[std::pair<int, int>(kind, ident)] = param;
    }

    configFile.close();
  }

  /**** EXPERIMENT ****/

  bool perforateLoops(Function &F) {
    int perforatedLoops = 0;
    LoopInfo &loopInfo = getAnalysis<LoopInfo>();

    int loopId = 0;
    for (LoopInfo::iterator li = loopInfo.begin();
         li != loopInfo.end(); ++li, ++loopId) {
      Loop *loop = *li;

      // We only consider loops for which there is a header (condition), a
      // latch (increment, in "for"), and a preheader (initialization).
      if (!loop->getHeader() || !loop->getLoopLatch()
          || !loop->getLoopPreheader())
        continue;

      // Count elidable instructions in the loop.
      int cTotal = 0;
      int cElidable = 0;
      for (Loop::block_iterator bi = loop->block_begin();
           bi != loop->block_end(); ++bi) {
        BasicBlock *block = *bi;

        // Don't count the loop control.
        if (block == loop->getHeader() || block == loop->getLoopLatch())
          continue;

        for (BasicBlock::iterator ii = block->begin();
             ii != block->end(); ++ii) {
          if ((Instruction*)ii == block->getTerminator())
            continue;
          if (elidable(ii))
            ++cElidable;
          ++cTotal;
        }
      }

      // How elidable is the loop body as a whole?
      errs() << "loop at "
             << srcPosDesc(*module, loop->getHeader()->begin()->getDebugLoc())
             << " - " << cElidable << "/" << cTotal << "\n";

      /*
      #define DUMPNN(e) if (e) (e)->dump(); else errs() << "null\n";
      errs() << "header: ";
      DUMPNN(loop->getHeader())
      errs() << "preheader: ";
      DUMPNN(loop->getLoopPreheader())
      errs() << "predecessor: ";
      DUMPNN(loop->getLoopPredecessor())
      errs() << "latch: ";
      DUMPNN(loop->getLoopLatch())
      errs() << "exit: ";
      DUMPNN(loop->getExitBlock())
      errs() << "exiting: ";
      DUMPNN(loop->getExitingBlock())
      errs() << "all contained blocks: ";
      for (Loop::block_iterator bi = loop->block_begin();
           bi != loop->block_end(); ++bi) {
        BasicBlock *block = *bi;
        block->dump();
      }
      */

      if (cElidable == cTotal) {
        errs() << "can perforate.\n";
        if (optRelax) {
          int factor = relaxConfig[std::pair<int, int>(rkPerforate, loopId)];
          if (factor) {
            errs() << "perforating with factor " << factor << "\n";
            perforateLoop(loop);
            ++perforatedLoops;
          }
        } else {
          relaxConfig[std::pair<int, int>(rkPerforate, loopId)] = 0;
        }
      }
    }

    return perforatedLoops > 0;
  }

  void perforateLoop(Loop *loop, int mask=1) {
    // Check whether this loop is perforatable.
    // First, check for required blocks.
    if (!loop->getHeader() || !loop->getLoopLatch()
        || !loop->getLoopPreheader() || !loop->getExitBlock()) {
      llvm::errs() << "malformed loop\n";
      return;
    }
    // Next, make sure the header (condition block) ends with a body/exit
    // conditional branch.
    BranchInst *condBranch = dyn_cast<BranchInst>(
        loop->getHeader()->getTerminator()
    );
    if (!condBranch || condBranch->getNumSuccessors() != 2) {
      llvm::errs() << "malformed loop condition\n";
      return;
    }
    BasicBlock *bodyBlock;
    if (condBranch->getSuccessor(0) == loop->getExitBlock()) {
      bodyBlock = condBranch->getSuccessor(1);
    } else if (condBranch->getSuccessor(1) == loop->getExitBlock()) {
      bodyBlock = condBranch->getSuccessor(0);
    } else {
      llvm::errs() << "loop condition does not exit\n";
      return;
    }

    IRBuilder<> builder(module->getContext());
    Value *result;

    // Add our own counter to the preheader.
    builder.SetInsertPoint(loop->getLoopPreheader()->getTerminator());
    AllocaInst *counterAlloca = builder.CreateAlloca(
        builder.getInt32Ty(),
        0,
        "accept_counter"
    );
    builder.CreateStore(
        builder.getInt32(0),
        counterAlloca
    );

    // Increment the counter in the latch.
    builder.SetInsertPoint(loop->getLoopLatch()->getTerminator());
    result = builder.CreateLoad(
        counterAlloca,
        "accept_tmp"
    );
    result = builder.CreateAdd(
        result,
        builder.getInt32(1),
        "accept_inc"
    );
    builder.CreateStore(
        result,
        counterAlloca
    );

    // Get the first body block.

    // Check the counter before the loop's body.
    BasicBlock *checkBlock = BasicBlock::Create(
        module->getContext(),
        "accept_cond",
        bodyBlock->getParent(),
        bodyBlock
    );
    builder.SetInsertPoint(checkBlock);
    result = builder.CreateLoad(
        counterAlloca,
        "accept_tmp"
    );
    result = builder.CreateAnd(
        result,
        builder.getInt32(mask),
        "accept_and"
    );
    result = builder.CreateIsNull(
        result,
        "accept_cmp"
    );
    result = builder.CreateCondBr(
        result,
        bodyBlock,
        loop->getLoopLatch()
    );

    // Change the latch (condition block) to point to our new condition
    // instead of the body.
    condBranch->setSuccessor(0, checkBlock);
  }

};
char ACCEPTPass::ID = 0;

/**** PASS REGISTRATION FOOTNOTE ***/

// Register ACCEPT as a "standard pass". This allows the pass to run without
// running opt explicitly (e.g., as part of running `clang`).
static void registerACCEPTPass(const PassManagerBuilder &,
                               PassManagerBase &PM) {
  PM.add(new LoopInfo());
  PM.add(new ACCEPTPass());
}
static RegisterStandardPasses
    RegisterACCEPT(PassManagerBuilder::EP_EarlyAsPossible,
                   registerACCEPTPass);

}
<commit_msg>perforation parameter is now log(factor)<commit_after>#define DEBUG_TYPE "enerc"
#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/BasicBlock.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/PassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/IRBuilder.h"

#include <sstream>
#include <set>
#include <cstdio>
#include <fstream>

#define ECQ_PRECISE 0
#define ECQ_APPROX 1

#define FUNC_TRACE "enerc_trace"

// I'm not sure why, but I can't seem to enable debug output in the usual way
// (with command line flags). Here's a hack.
#undef DEBUG
#define DEBUG(s) s

using namespace llvm;
namespace {

// Command-line flags.
cl::opt<bool> optInstrument ("accept-inst",
    cl::desc("ACCEPT: enable profiling instrumentation"));
cl::opt<bool> optRelax ("accept-relax",
    cl::desc("ACCEPT: enable relaxations"));

/**** HELPERS ****/

// Look at the qualifier metadata on the instruction and determine whether it
// has approximate semantics.
bool isApprox(Instruction *instr) {
  MDNode *md = instr->getMetadata("quals");
  if (!md)
    return false;

  Value *val = md->getOperand(0);
  ConstantInt *ci = cast<ConstantInt>(val);
  if (ci) {
    APInt intval = ci->getValue();
    return intval == ECQ_APPROX;
  } else {
    llvm::errs() << "INVALID METADATA";
    return false;
  }
}

// Is it legal to elide this instruction?
bool elidable_helper(Instruction *instr,
                     std::set<Instruction*> &seen) {
  // Check for cycles.
  if (seen.count(instr)) {
    llvm::errs() << "CYCLE DETECTED\n";
    return false;
  }
  seen.insert(instr);

  if (isApprox(instr)) {
    return true;
  } else if (isa<StoreInst>(instr) ||
             isa<ReturnInst>(instr) ||
             isa<BranchInst>(instr)) {
    // Precise stores, returns, branches: never elidable.
    return false;
  } else {
    // Recursive case: all consumers are elidable.
    for (Value::use_iterator ui = instr->use_begin();
          ui != instr->use_end(); ++ui) {
      Instruction *user = dyn_cast<Instruction>(*ui);
      if (user && !elidable_helper(user, seen)) {
        return false;
      }
    }
    return true; // No non-elidable consumers.
  }
}
// Start with an empty "seen" (cycle-detection) set.
bool elidable(Instruction *instr) {
  std::set<Instruction*> seen;
  return elidable_helper(instr, seen);
}

// Format a source position.
std::string srcPosDesc(const Module &mod, const DebugLoc &dl) {
  std::stringstream ss;
  ss << mod.getModuleIdentifier() << ":";
  ss << dl.getLine();
  if (dl.getCol())
    ss << "," << dl.getCol();
  return ss.str();
}

/**** THE MAIN LLVM PASS ****/

struct ACCEPTPass : public FunctionPass {
  static char ID;

  Constant *blockCountFunction;
  unsigned long gApproxInsts;
  unsigned long gElidableInsts;
  unsigned long gTotalInsts;
  Module *module;
  std::map<std::pair<int, int>, int> relaxConfig;  // kind, num -> param

  ACCEPTPass() : FunctionPass(ID) {
    gApproxInsts = 0;
    gElidableInsts = 0;
    gTotalInsts = 0;
    module = 0;
  }

  virtual void getAnalysisUsage(AnalysisUsage &Info) const {
    Info.addRequired<LoopInfo>();
  }

  virtual bool runOnFunction(Function &F) {
    countAndInstrument(F);
    return perforateLoops(F);
  }

  virtual bool doInitialization(Module &M) {
    module = &M;

    if (optInstrument)
      setUpInstrumentation();

    if (optRelax)
      loadRelaxConfig();

    return false;
  }

  virtual bool doFinalization(Module &M) {
    dumpStaticStats();
    if (!optRelax)
      dumpRelaxConfig();
    return false;
  }

  /**** TRACING AND STATISTICS ****/

  void countAndInstrument(Function &F) {
    for (Function::iterator bbi = F.begin(); bbi != F.end(); ++bbi) {
      unsigned int approxInsts = 0;
      unsigned int elidableInsts = 0;
      unsigned int totalInsts = 0;

      for (BasicBlock::iterator ii = bbi->begin(); ii != bbi->end();
            ++ii) {
        if ((Instruction*)ii == bbi->getTerminator()) {
          // Terminator instruction is not checked.
          continue;
        }

        // Record information about this instruction.
        bool iApprox = isApprox(ii);
        bool iElidable = elidable(ii);
        ++gTotalInsts;
        ++totalInsts;
        if (iApprox) {
          ++gApproxInsts;
          ++approxInsts;
        }
        if (iElidable) {
          ++gElidableInsts;
          ++elidableInsts;
        }
      }

      // Call the runtime profiling library for this block.
      if (optInstrument)
        insertTraceCall(F, bbi, approxInsts, elidableInsts, totalInsts);
    }
  }

  void setUpInstrumentation() {
    blockCountFunction = module->getOrInsertFunction(
      FUNC_TRACE,
      Type::getVoidTy(module->getContext()), // return type
      Type::getInt32Ty(module->getContext()), // approx
      Type::getInt32Ty(module->getContext()), // elidable
      Type::getInt32Ty(module->getContext()), // total
      NULL
    );
  }

  void insertTraceCall(Function &F, BasicBlock* bb,
                       unsigned int approx,
                       unsigned int elidable,
                       unsigned int total) {
    std::vector<Value *> args;
    args.push_back(
        ConstantInt::get(Type::getInt32Ty(F.getContext()), approx)
    );
    args.push_back(
        ConstantInt::get(Type::getInt32Ty(F.getContext()), elidable)
    );
    args.push_back(
        ConstantInt::get(Type::getInt32Ty(F.getContext()), total)
    );

    // For now, we're inserting calls at the end of basic blocks.
    CallInst::Create(
      blockCountFunction,
      args,
      "",
      bb->getTerminator()
    );
  }

  void dumpStaticStats() {
    FILE *results_file = fopen("enerc_static.txt", "w+");
    fprintf(results_file,
            "%lu %lu %lu\n", gApproxInsts, gElidableInsts, gTotalInsts);
    fclose(results_file);
  }

  /**** RELAXATION CONFIGURATION ***/

  typedef enum {
    rkPerforate
  } relaxKind;

  void dumpRelaxConfig() {
    std::ofstream configFile("accept_config.txt");;
    for (std::map<std::pair<int, int>, int>::iterator i = relaxConfig.begin();
         i != relaxConfig.end(); ++i) {
      configFile << i->first.first << " "
                 << i->first.second << " "
                 << i->second << "\n";
    }
    configFile.close();
  }

  void loadRelaxConfig() {
    std::ifstream configFile("accept_config.txt");;
    if (!configFile.good()) {
      errs() << "no config file; no optimizations will occur\n";
      return;
    }

    while (configFile.good()) {
      int kind;
      int ident;
      int param;
      configFile >> kind >> ident >> param;
      relaxConfig[std::pair<int, int>(kind, ident)] = param;
    }

    configFile.close();
  }

  /**** EXPERIMENT ****/

  bool perforateLoops(Function &F) {
    int perforatedLoops = 0;
    LoopInfo &loopInfo = getAnalysis<LoopInfo>();

    int loopId = 0;
    for (LoopInfo::iterator li = loopInfo.begin();
         li != loopInfo.end(); ++li, ++loopId) {
      Loop *loop = *li;

      // We only consider loops for which there is a header (condition), a
      // latch (increment, in "for"), and a preheader (initialization).
      if (!loop->getHeader() || !loop->getLoopLatch()
          || !loop->getLoopPreheader())
        continue;

      // Count elidable instructions in the loop.
      int cTotal = 0;
      int cElidable = 0;
      for (Loop::block_iterator bi = loop->block_begin();
           bi != loop->block_end(); ++bi) {
        BasicBlock *block = *bi;

        // Don't count the loop control.
        if (block == loop->getHeader() || block == loop->getLoopLatch())
          continue;

        for (BasicBlock::iterator ii = block->begin();
             ii != block->end(); ++ii) {
          if ((Instruction*)ii == block->getTerminator())
            continue;
          if (elidable(ii))
            ++cElidable;
          ++cTotal;
        }
      }

      // How elidable is the loop body as a whole?
      errs() << "loop at "
             << srcPosDesc(*module, loop->getHeader()->begin()->getDebugLoc())
             << " - " << cElidable << "/" << cTotal << "\n";

      /*
      #define DUMPNN(e) if (e) (e)->dump(); else errs() << "null\n";
      errs() << "header: ";
      DUMPNN(loop->getHeader())
      errs() << "preheader: ";
      DUMPNN(loop->getLoopPreheader())
      errs() << "predecessor: ";
      DUMPNN(loop->getLoopPredecessor())
      errs() << "latch: ";
      DUMPNN(loop->getLoopLatch())
      errs() << "exit: ";
      DUMPNN(loop->getExitBlock())
      errs() << "exiting: ";
      DUMPNN(loop->getExitingBlock())
      errs() << "all contained blocks: ";
      for (Loop::block_iterator bi = loop->block_begin();
           bi != loop->block_end(); ++bi) {
        BasicBlock *block = *bi;
        block->dump();
      }
      */

      if (cElidable == cTotal) {
        errs() << "can perforate.\n";
        if (optRelax) {
          int param = relaxConfig[std::pair<int, int>(rkPerforate, loopId)];
          if (param) {
            errs() << "perforating with factor 2^" << param << "\n";
            perforateLoop(loop, param);
            ++perforatedLoops;
          }
        } else {
          relaxConfig[std::pair<int, int>(rkPerforate, loopId)] = 0;
        }
      }
    }

    return perforatedLoops > 0;
  }

  void perforateLoop(Loop *loop, int logfactor=1) {
    // Check whether this loop is perforatable.
    // First, check for required blocks.
    if (!loop->getHeader() || !loop->getLoopLatch()
        || !loop->getLoopPreheader() || !loop->getExitBlock()) {
      llvm::errs() << "malformed loop\n";
      return;
    }
    // Next, make sure the header (condition block) ends with a body/exit
    // conditional branch.
    BranchInst *condBranch = dyn_cast<BranchInst>(
        loop->getHeader()->getTerminator()
    );
    if (!condBranch || condBranch->getNumSuccessors() != 2) {
      llvm::errs() << "malformed loop condition\n";
      return;
    }
    BasicBlock *bodyBlock;
    if (condBranch->getSuccessor(0) == loop->getExitBlock()) {
      bodyBlock = condBranch->getSuccessor(1);
    } else if (condBranch->getSuccessor(1) == loop->getExitBlock()) {
      bodyBlock = condBranch->getSuccessor(0);
    } else {
      llvm::errs() << "loop condition does not exit\n";
      return;
    }

    IRBuilder<> builder(module->getContext());
    Value *result;

    // Add our own counter to the preheader.
    builder.SetInsertPoint(loop->getLoopPreheader()->getTerminator());
    AllocaInst *counterAlloca = builder.CreateAlloca(
        builder.getInt32Ty(),
        0,
        "accept_counter"
    );
    builder.CreateStore(
        builder.getInt32(0),
        counterAlloca
    );

    // Increment the counter in the latch.
    builder.SetInsertPoint(loop->getLoopLatch()->getTerminator());
    result = builder.CreateLoad(
        counterAlloca,
        "accept_tmp"
    );
    result = builder.CreateAdd(
        result,
        builder.getInt32(1),
        "accept_inc"
    );
    builder.CreateStore(
        result,
        counterAlloca
    );

    // Get the first body block.

    // Check the counter before the loop's body.
    BasicBlock *checkBlock = BasicBlock::Create(
        module->getContext(),
        "accept_cond",
        bodyBlock->getParent(),
        bodyBlock
    );
    builder.SetInsertPoint(checkBlock);
    result = builder.CreateLoad(
        counterAlloca,
        "accept_tmp"
    );
    // Check whether the low n bits of the counter are zero.
    result = builder.CreateTrunc(
        result,
        Type::getIntNTy(module->getContext(), logfactor),
        "accept_trunc"
    );
    result = builder.CreateIsNull(
        result,
        "accept_cmp"
    );
    result = builder.CreateCondBr(
        result,
        bodyBlock,
        loop->getLoopLatch()
    );

    // Change the latch (condition block) to point to our new condition
    // instead of the body.
    condBranch->setSuccessor(0, checkBlock);
  }

};
char ACCEPTPass::ID = 0;

/**** PASS REGISTRATION FOOTNOTE ***/

// Register ACCEPT as a "standard pass". This allows the pass to run without
// running opt explicitly (e.g., as part of running `clang`).
static void registerACCEPTPass(const PassManagerBuilder &,
                               PassManagerBase &PM) {
  PM.add(new LoopInfo());
  PM.add(new ACCEPTPass());
}
static RegisterStandardPasses
    RegisterACCEPT(PassManagerBuilder::EP_EarlyAsPossible,
                   registerACCEPTPass);

}
<|endoftext|>