<commit_before>/* -*- c-basic-offset: 2 -*- */
/* Copyright(C) 2011 Brazil

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License version 2.1 as published by the Free Software Foundation.

  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 <groonga_in.h>

#include "file-impl.hpp"

#include <sys/types.h>
#include <sys/stat.h>

#ifdef WIN32
# ifdef min
#  undef min
# endif  // min
# ifdef max
#  undef max
# endif  // max
#else  // WIN32
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#endif  // WIN32

#include <algorithm>
#include <limits>

namespace grn {
namespace dat {

#ifdef WIN32

FileImpl::FileImpl()
    : ptr_(NULL),
      size_(0),
      file_(INVALID_HANDLE_VALUE),
      map_(INVALID_HANDLE_VALUE),
      addr_(NULL) {}

FileImpl::~FileImpl() {
  if (addr_ != NULL) {
    ::UnmapViewOfFile(addr_);
  }

  if (map_ != INVALID_HANDLE_VALUE) {
    ::CloseHandle(map_);
  }

  if (file_ != INVALID_HANDLE_VALUE) {
    ::CloseHandle(file_);
  }
}

#else  // WIN32

FileImpl::FileImpl()
    : ptr_(NULL),
      size_(0),
      fd_(-1),
      addr_(MAP_FAILED),
      length_(0) {}

FileImpl::~FileImpl() {
  if (addr_ != MAP_FAILED) {
    ::munmap(addr_, length_);
  }

  if (fd_ != -1) {
    ::close(fd_);
  }
}

#endif  // WIN32

void FileImpl::create(const char *path, UInt64 size) {
  GRN_DAT_THROW_IF(PARAM_ERROR, size == 0);
  GRN_DAT_THROW_IF(PARAM_ERROR,
      size > static_cast<UInt64>(std::numeric_limits< ::size_t>::max()));

  FileImpl new_impl;
  new_impl.create_(path, size);
  new_impl.swap(this);
}

void FileImpl::open(const char *path) {
  GRN_DAT_THROW_IF(PARAM_ERROR, path == NULL);
  GRN_DAT_THROW_IF(PARAM_ERROR, path[0] == '\0');

  FileImpl new_impl;
  new_impl.open_(path);
  new_impl.swap(this);
}

void FileImpl::close() {
  FileImpl new_impl;
  new_impl.swap(this);
}

#ifdef WIN32

void FileImpl::swap(FileImpl *rhs) {
  std::swap(ptr_, rhs->ptr_);
  std::swap(size_, rhs->size_);
  std::swap(file_, rhs->file_);
  std::swap(map_, rhs->map_);
  std::swap(addr_, rhs->addr_);
}

void FileImpl::create_(const char *path, UInt64 size) {
  if ((path != NULL) && (path[0] != '\0')) {
    file_ = ::CreateFileA(path, GENERIC_READ | GENERIC_WRITE,
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
                          NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    GRN_DAT_THROW_IF(IO_ERROR, file_ == INVALID_HANDLE_VALUE);

    const LONG size_low = static_cast<LONG>(size & 0xFFFFFFFFU);
    LONG size_high = static_cast<LONG>(size >> 32);
    const DWORD file_pos = ::SetFilePointer(file_, size_low, &size_high,
                                            FILE_BEGIN);
    GRN_DAT_THROW_IF(IO_ERROR, (file_pos == INVALID_SET_FILE_POINTER) &&
                               (::GetLastError() != 0));
    GRN_DAT_THROW_IF(IO_ERROR, ::SetEndOfFile(file_) == 0);

    map_ = ::CreateFileMapping(file_, NULL, PAGE_READWRITE, 0, 0, NULL);
    GRN_DAT_THROW_IF(IO_ERROR, map_ == INVALID_HANDLE_VALUE);
  } else {
    const DWORD size_low = static_cast<DWORD>(size & 0xFFFFFFFFU);
    const DWORD size_high = static_cast<DWORD>(size >> 32);

    map_ = ::CreateFileMapping(file_, NULL, PAGE_READWRITE,
                               size_high, size_low, NULL);
    GRN_DAT_THROW_IF(IO_ERROR, map_ == INVALID_HANDLE_VALUE);
  }

  addr_ = ::MapViewOfFile(map_, FILE_MAP_WRITE, 0, 0, 0);
  GRN_DAT_THROW_IF(IO_ERROR, addr_ == NULL);

  ptr_ = addr_;
  size_ = static_cast< ::size_t>(size);
}

void FileImpl::open_(const char *path) {
  struct __stat64 st;
  GRN_DAT_THROW_IF(IO_ERROR, ::_stat64(path, &st) == -1);
  GRN_DAT_THROW_IF(IO_ERROR, st.st_size == 0);
  GRN_DAT_THROW_IF(IO_ERROR,
      static_cast<UInt64>(st.st_size) > std::numeric_limits< ::size_t>::max());

  file_ = ::CreateFileA(path, GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  GRN_DAT_THROW_IF(IO_ERROR, file_ == NULL);

  map_ = ::CreateFileMapping(file_, NULL, PAGE_READWRITE, 0, 0, NULL);
  GRN_DAT_THROW_IF(IO_ERROR, map_ == NULL);

  addr_ = ::MapViewOfFile(map_, FILE_MAP_WRITE, 0, 0, 0);
  GRN_DAT_THROW_IF(IO_ERROR, addr_ == NULL);

  ptr_ = addr_;
  size_ = static_cast< ::size_t>(st.st_size);
}

#else  // WIN32

void FileImpl::swap(FileImpl *rhs) {
  std::swap(ptr_, rhs->ptr_);
  std::swap(size_, rhs->size_);
  std::swap(fd_, rhs->fd_);
  std::swap(addr_, rhs->addr_);
  std::swap(length_, rhs->length_);
}

void FileImpl::create_(const char *path, UInt64 size) {
  GRN_DAT_THROW_IF(PARAM_ERROR,
      size > static_cast<UInt64>(std::numeric_limits< ::off_t>::max()));

  if ((path != NULL) && (path[0] != '\0')) {
    fd_ = ::open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
    GRN_DAT_THROW_IF(IO_ERROR, fd_ == -1);

    const ::off_t file_size = static_cast< ::off_t>(size);
    GRN_DAT_THROW_IF(IO_ERROR, ::ftruncate(fd_, file_size) == -1);
  }

#ifdef MAP_ANONYMOUS
  const int flags = (fd_ == -1) ? (MAP_PRIVATE | MAP_ANONYMOUS) : MAP_SHARED;
#else  // MAP_ANONYMOUS
  const int flags = (fd_ == -1) ? (MAP_PRIVATE | MAP_ANON) : MAP_SHARED;
#endif  // MAP_ANONYMOUS

  length_ = static_cast< ::size_t>(size);
#ifdef GROONGA_USE_MAP_HUGETLB
  addr_ = ::mmap(NULL, length_, PROT_READ | PROT_WRITE,
                 flags | MAP_HUGETLB, fd_, 0);
#endif  // GROONGA_USE_MAP_HUGETLB
  if (addr_ == MAP_FAILED) {
    addr_ = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, flags, fd_, 0);
    GRN_DAT_THROW_IF(IO_ERROR, addr_ == MAP_FAILED);
  }

  ptr_ = addr_;
  size_ = length_;
}

void FileImpl::open_(const char *path) {
  struct stat st;
  GRN_DAT_THROW_IF(IO_ERROR, ::stat(path, &st) == -1);
  GRN_DAT_THROW_IF(IO_ERROR, (st.st_mode & S_IFMT) != S_IFREG);
  GRN_DAT_THROW_IF(IO_ERROR, st.st_size == 0);
  GRN_DAT_THROW_IF(IO_ERROR,
      static_cast<UInt64>(st.st_size) > std::numeric_limits< ::size_t>::max());

  fd_ = ::open(path, O_RDWR);
  GRN_DAT_THROW_IF(IO_ERROR, fd_ == -1);

  length_ = static_cast<std::size_t>(st.st_size);
  addr_ = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0);
  GRN_DAT_THROW_IF(IO_ERROR, addr_ == MAP_FAILED);

  ptr_ = addr_;
  size_ = length_;
}

#endif  // WIN32

}  // namespace dat
}  // namespace grn
<commit_msg>use struct _stat and _stat() instead of struct __stat64 and _stat64() for MinGW. Thanks to Toshihisa Tashiro.<commit_after>/* -*- c-basic-offset: 2 -*- */
/* Copyright(C) 2011 Brazil

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License version 2.1 as published by the Free Software Foundation.

  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 <groonga_in.h>

#include "file-impl.hpp"

#include <sys/types.h>
#include <sys/stat.h>

#ifdef WIN32
# ifdef min
#  undef min
# endif  // min
# ifdef max
#  undef max
# endif  // max
#else  // WIN32
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#endif  // WIN32

#include <algorithm>
#include <limits>

namespace grn {
namespace dat {

#ifdef WIN32

FileImpl::FileImpl()
    : ptr_(NULL),
      size_(0),
      file_(INVALID_HANDLE_VALUE),
      map_(INVALID_HANDLE_VALUE),
      addr_(NULL) {}

FileImpl::~FileImpl() {
  if (addr_ != NULL) {
    ::UnmapViewOfFile(addr_);
  }

  if (map_ != INVALID_HANDLE_VALUE) {
    ::CloseHandle(map_);
  }

  if (file_ != INVALID_HANDLE_VALUE) {
    ::CloseHandle(file_);
  }
}

#else  // WIN32

FileImpl::FileImpl()
    : ptr_(NULL),
      size_(0),
      fd_(-1),
      addr_(MAP_FAILED),
      length_(0) {}

FileImpl::~FileImpl() {
  if (addr_ != MAP_FAILED) {
    ::munmap(addr_, length_);
  }

  if (fd_ != -1) {
    ::close(fd_);
  }
}

#endif  // WIN32

void FileImpl::create(const char *path, UInt64 size) {
  GRN_DAT_THROW_IF(PARAM_ERROR, size == 0);
  GRN_DAT_THROW_IF(PARAM_ERROR,
      size > static_cast<UInt64>(std::numeric_limits< ::size_t>::max()));

  FileImpl new_impl;
  new_impl.create_(path, size);
  new_impl.swap(this);
}

void FileImpl::open(const char *path) {
  GRN_DAT_THROW_IF(PARAM_ERROR, path == NULL);
  GRN_DAT_THROW_IF(PARAM_ERROR, path[0] == '\0');

  FileImpl new_impl;
  new_impl.open_(path);
  new_impl.swap(this);
}

void FileImpl::close() {
  FileImpl new_impl;
  new_impl.swap(this);
}

#ifdef WIN32

void FileImpl::swap(FileImpl *rhs) {
  std::swap(ptr_, rhs->ptr_);
  std::swap(size_, rhs->size_);
  std::swap(file_, rhs->file_);
  std::swap(map_, rhs->map_);
  std::swap(addr_, rhs->addr_);
}

void FileImpl::create_(const char *path, UInt64 size) {
  if ((path != NULL) && (path[0] != '\0')) {
    file_ = ::CreateFileA(path, GENERIC_READ | GENERIC_WRITE,
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
                          NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    GRN_DAT_THROW_IF(IO_ERROR, file_ == INVALID_HANDLE_VALUE);

    const LONG size_low = static_cast<LONG>(size & 0xFFFFFFFFU);
    LONG size_high = static_cast<LONG>(size >> 32);
    const DWORD file_pos = ::SetFilePointer(file_, size_low, &size_high,
                                            FILE_BEGIN);
    GRN_DAT_THROW_IF(IO_ERROR, (file_pos == INVALID_SET_FILE_POINTER) &&
                               (::GetLastError() != 0));
    GRN_DAT_THROW_IF(IO_ERROR, ::SetEndOfFile(file_) == 0);

    map_ = ::CreateFileMapping(file_, NULL, PAGE_READWRITE, 0, 0, NULL);
    GRN_DAT_THROW_IF(IO_ERROR, map_ == INVALID_HANDLE_VALUE);
  } else {
    const DWORD size_low = static_cast<DWORD>(size & 0xFFFFFFFFU);
    const DWORD size_high = static_cast<DWORD>(size >> 32);

    map_ = ::CreateFileMapping(file_, NULL, PAGE_READWRITE,
                               size_high, size_low, NULL);
    GRN_DAT_THROW_IF(IO_ERROR, map_ == INVALID_HANDLE_VALUE);
  }

  addr_ = ::MapViewOfFile(map_, FILE_MAP_WRITE, 0, 0, 0);
  GRN_DAT_THROW_IF(IO_ERROR, addr_ == NULL);

  ptr_ = addr_;
  size_ = static_cast< ::size_t>(size);
}

void FileImpl::open_(const char *path) {
#ifdef _MSC_VER
  struct __stat64 st;
  GRN_DAT_THROW_IF(IO_ERROR, ::_stat64(path, &st) == -1);
#else  // _MSC_VER
  struct _stat st;
  GRN_DAT_THROW_IF(IO_ERROR, ::_stat(path, &st) == -1);
#endif  // _MSC_VER
  GRN_DAT_THROW_IF(IO_ERROR, st.st_size == 0);
  GRN_DAT_THROW_IF(IO_ERROR,
      static_cast<UInt64>(st.st_size) > std::numeric_limits< ::size_t>::max());

  file_ = ::CreateFileA(path, GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  GRN_DAT_THROW_IF(IO_ERROR, file_ == NULL);

  map_ = ::CreateFileMapping(file_, NULL, PAGE_READWRITE, 0, 0, NULL);
  GRN_DAT_THROW_IF(IO_ERROR, map_ == NULL);

  addr_ = ::MapViewOfFile(map_, FILE_MAP_WRITE, 0, 0, 0);
  GRN_DAT_THROW_IF(IO_ERROR, addr_ == NULL);

  ptr_ = addr_;
  size_ = static_cast< ::size_t>(st.st_size);
}

#else  // WIN32

void FileImpl::swap(FileImpl *rhs) {
  std::swap(ptr_, rhs->ptr_);
  std::swap(size_, rhs->size_);
  std::swap(fd_, rhs->fd_);
  std::swap(addr_, rhs->addr_);
  std::swap(length_, rhs->length_);
}

void FileImpl::create_(const char *path, UInt64 size) {
  GRN_DAT_THROW_IF(PARAM_ERROR,
      size > static_cast<UInt64>(std::numeric_limits< ::off_t>::max()));

  if ((path != NULL) && (path[0] != '\0')) {
    fd_ = ::open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
    GRN_DAT_THROW_IF(IO_ERROR, fd_ == -1);

    const ::off_t file_size = static_cast< ::off_t>(size);
    GRN_DAT_THROW_IF(IO_ERROR, ::ftruncate(fd_, file_size) == -1);
  }

#ifdef MAP_ANONYMOUS
  const int flags = (fd_ == -1) ? (MAP_PRIVATE | MAP_ANONYMOUS) : MAP_SHARED;
#else  // MAP_ANONYMOUS
  const int flags = (fd_ == -1) ? (MAP_PRIVATE | MAP_ANON) : MAP_SHARED;
#endif  // MAP_ANONYMOUS

  length_ = static_cast< ::size_t>(size);
#ifdef GROONGA_USE_MAP_HUGETLB
  addr_ = ::mmap(NULL, length_, PROT_READ | PROT_WRITE,
                 flags | MAP_HUGETLB, fd_, 0);
#endif  // GROONGA_USE_MAP_HUGETLB
  if (addr_ == MAP_FAILED) {
    addr_ = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, flags, fd_, 0);
    GRN_DAT_THROW_IF(IO_ERROR, addr_ == MAP_FAILED);
  }

  ptr_ = addr_;
  size_ = length_;
}

void FileImpl::open_(const char *path) {
  struct stat st;
  GRN_DAT_THROW_IF(IO_ERROR, ::stat(path, &st) == -1);
  GRN_DAT_THROW_IF(IO_ERROR, (st.st_mode & S_IFMT) != S_IFREG);
  GRN_DAT_THROW_IF(IO_ERROR, st.st_size == 0);
  GRN_DAT_THROW_IF(IO_ERROR,
      static_cast<UInt64>(st.st_size) > std::numeric_limits< ::size_t>::max());

  fd_ = ::open(path, O_RDWR);
  GRN_DAT_THROW_IF(IO_ERROR, fd_ == -1);

  length_ = static_cast<std::size_t>(st.st_size);
  addr_ = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0);
  GRN_DAT_THROW_IF(IO_ERROR, addr_ == MAP_FAILED);

  ptr_ = addr_;
  size_ = length_;
}

#endif  // WIN32

}  // namespace dat
}  // namespace grn
<|endoftext|>


<commit_before>/*
 * $Id$
 *
 * Copyright(C) 1998-2005 Satoshi Nakamura
 * All rights reserved.
 *
 */

#include <qsconv.h>
#include <qsdevicecontext.h>
#include <qsdialog.h>
#include <qsinit.h>
#include <qsosutil.h>
#include <qsprofile.h>
#include <qstheme.h>
#include <qsuiutil.h>

#include <commdlg.h>
#ifndef _WIN32_WCE
#	include <shlobj.h>
#endif
#ifdef _WIN32_WCE_PSPC
#	include <aygshell.h>
#endif

using namespace qs;

/****************************************************************************
 *
 * UIUtil
 *
 */

HFONT qs::UIUtil::createFontFromProfile(Profile* pProfile,
										const WCHAR* pwszSection,
										bool bDefaultFixedWidth)
{
	LOGFONT lf;
	getLogFontFromProfile(pProfile, pwszSection, bDefaultFixedWidth, &lf);
	return ::CreateFontIndirect(&lf);
}

void qs::UIUtil::getLogFontFromProfile(Profile* pProfile,
									   const WCHAR* pwszSection,
									   bool bDefaultFixedWidth,
									   LOGFONT* pLogFont)
{
	assert(pProfile);
	assert(pwszSection);
	assert(pLogFont);

	const WCHAR* pwszDefaultFace = 0;
	if (bDefaultFixedWidth)
		pwszDefaultFace = Init::getInit().getDefaultFixedWidthFont();
	else
		pwszDefaultFace = Init::getInit().getDefaultProportionalFont();

	wstring_ptr wstrFontFace(pProfile->getString(
		pwszSection, L"FontFace", pwszDefaultFace));
	wstring_ptr wstrFontSize(pProfile->getString(
		pwszSection, L"FontSize", L"9"));
	WCHAR* pEnd = 0;
	double dFontSize = wcstod(wstrFontSize.get(), &pEnd);
	if (*pEnd)
		dFontSize = 9;
	int nFontStyle = pProfile->getInt(pwszSection, L"FontStyle", 0);
	int nFontCharset = pProfile->getInt(pwszSection, L"FontCharset", 0);

	ClientDeviceContext dc(0);
	FontHelper::createLogFont(dc, wstrFontFace.get(),
		dFontSize, nFontStyle, nFontCharset, pLogFont);
}

void qs::UIUtil::setLogFontToProfile(Profile* pProfile,
									 const WCHAR* pwszSection,
									 const LOGFONT& lf)
{
	assert(pProfile);
	assert(pwszSection);

	T2W(lf.lfFaceName, pwszFaceName);
	pProfile->setString(pwszSection, L"FontFace", pwszFaceName);

	ClientDeviceContext dc(0);
	double dPointSize = -lf.lfHeight*72.0/dc.getDeviceCaps(LOGPIXELSY);
	WCHAR wszSize[64];
	swprintf(wszSize, L"%.1lf", dPointSize);
	pProfile->setString(pwszSection, L"FontSize", wszSize);

	int nFontStyle = 0;
	if (lf.lfWeight >= FW_BOLD)
		nFontStyle |= FontHelper::STYLE_BOLD;
	if (lf.lfItalic)
		nFontStyle |= FontHelper::STYLE_ITALIC;
	if (lf.lfUnderline)
		nFontStyle |= FontHelper::STYLE_UNDERLINE;
	if (lf.lfStrikeOut)
		nFontStyle |= FontHelper::STYLE_STRIKEOUT;
	pProfile->setInt(pwszSection, L"FontStyle", nFontStyle);

	if (lf.lfCharSet != 0)
		pProfile->setInt(pwszSection, L"FontCharset", lf.lfCharSet);
}

bool qs::UIUtil::browseFont(HWND hwnd,
							LOGFONT* pLogFont)
{
#if 0//!defined _WIN32_WCE || (_WIN32_WCE >= 400 && !defined _WIN32_WCE_PSPC)
	CHOOSEFONT cf = {
		sizeof(cf),
		hwnd,
		0,
		pLogFont,
		0,
		CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS,
	};
	return ::ChooseFont(&cf) != 0;
#else
	FontDialog dialog(*pLogFont);
	if (dialog.doModal(hwnd) != IDOK)
		return false;

	*pLogFont = dialog.getLogFont();

	return true;
#endif
}

#ifndef _WIN32_WCE
static int CALLBACK browseCallbackProc(HWND hwnd,
									   UINT uMsg,
									   LPARAM lParam,
									   LPARAM lpData)
{
	switch (uMsg) {
	case BFFM_INITIALIZED:
		::SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
		break;
	}
	return 0;
}
#endif

wstring_ptr qs::UIUtil::browseFolder(HWND hwnd,
									 const WCHAR* pwszTitle,
									 const WCHAR* pwszInitialPath)
{
	wstring_ptr wstrPath;

#ifdef _WIN32_WCE
	BrowseFolderDialog dialog(pwszTitle, pwszInitialPath);
	int nRet = dialog.doModal(hwnd);
	if (nRet == IDOK)
		wstrPath = allocWString(dialog.getPath());
#else
	W2T(pwszTitle, ptszTitle);
	W2T(pwszInitialPath, ptszInitialPath);
	TCHAR tszDisplayName[MAX_PATH];
	BROWSEINFO info = {
		hwnd,
		0,
		tszDisplayName,
		ptszTitle,
		BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE,
		&browseCallbackProc,
		reinterpret_cast<LPARAM>(ptszInitialPath),
		0
	};
	LPITEMIDLIST pList = ::SHBrowseForFolder(&info);
	if (pList) {
		TCHAR tszPath[MAX_PATH];
		if (::SHGetPathFromIDList(pList, tszPath))
			wstrPath = tcs2wcs(tszPath);

		ComPtr<IMalloc> pMalloc;
		::SHGetMalloc(&pMalloc);
		pMalloc->Free(pList);
	}
#endif

	return wstrPath;
}

#ifndef _WIN32_WCE
bool qs::UIUtil::drawThemeBorder(Theme* pTheme,
								 HWND hwnd,
								 int nPartId,
								 int nStateId,
								 COLORREF crBackground)
{
	RECT rect;
	::GetWindowRect(hwnd, &rect);
	rect.right -= rect.left;
	rect.left = 0;
	rect.bottom -= rect.top;
	rect.top = 0;

	WindowDeviceContext dc(hwnd);
	int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE);
	int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE);
	dc.excludeClipRect(nEdgeWidth, nEdgeHeight,
		rect.right - nEdgeWidth, rect.bottom - nEdgeHeight);
	dc.fillSolidRect(rect, crBackground);

	int nBorderWidth = pTheme->getSysSize(SM_CXBORDER);
	int nBorderHeight = pTheme->getSysSize(SM_CYBORDER);
	dc.excludeClipRect(nBorderWidth, nBorderHeight,
		rect.right - nBorderWidth, rect.bottom - nBorderHeight);
	return pTheme->drawBackground(dc.getHandle(), nPartId, nStateId, rect, 0);
}
#endif

int qs::UIUtil::getLogPixel()
{
	ClientDeviceContext dc(0);
	return dc.getDeviceCaps(LOGPIXELSY);
}

#if defined _WIN32_WCE && _WIN32_WCE >= 300 && defined _WIN32_WCE_PSPC
void qs::UIUtil::getWorkArea(RECT* pRect)
{
	assert(pRect);

	const int nDefaultMenuHeight = 26;
	ClientDeviceContext dc(0);
	int nMenuHeight = static_cast<int>(nDefaultMenuHeight*(getLogPixel()/96.0));

	SIPINFO si = { sizeof(si) };
	::SHSipInfo(SPI_GETSIPINFO, 0, &si, 0);

	*pRect = si.rcVisibleDesktop;
	if ((si.fdwFlags & SIPF_ON) == 0)
		pRect->bottom -= nMenuHeight;
}
#endif
<commit_msg>Strip tailing .0 when save font size to a profile.<commit_after>/*
 * $Id$
 *
 * Copyright(C) 1998-2005 Satoshi Nakamura
 * All rights reserved.
 *
 */

#include <qsconv.h>
#include <qsdevicecontext.h>
#include <qsdialog.h>
#include <qsinit.h>
#include <qsosutil.h>
#include <qsprofile.h>
#include <qstheme.h>
#include <qsuiutil.h>

#include <commdlg.h>
#ifndef _WIN32_WCE
#	include <shlobj.h>
#endif
#ifdef _WIN32_WCE_PSPC
#	include <aygshell.h>
#endif

using namespace qs;

/****************************************************************************
 *
 * UIUtil
 *
 */

HFONT qs::UIUtil::createFontFromProfile(Profile* pProfile,
										const WCHAR* pwszSection,
										bool bDefaultFixedWidth)
{
	LOGFONT lf;
	getLogFontFromProfile(pProfile, pwszSection, bDefaultFixedWidth, &lf);
	return ::CreateFontIndirect(&lf);
}

void qs::UIUtil::getLogFontFromProfile(Profile* pProfile,
									   const WCHAR* pwszSection,
									   bool bDefaultFixedWidth,
									   LOGFONT* pLogFont)
{
	assert(pProfile);
	assert(pwszSection);
	assert(pLogFont);

	const WCHAR* pwszDefaultFace = 0;
	if (bDefaultFixedWidth)
		pwszDefaultFace = Init::getInit().getDefaultFixedWidthFont();
	else
		pwszDefaultFace = Init::getInit().getDefaultProportionalFont();

	wstring_ptr wstrFontFace(pProfile->getString(
		pwszSection, L"FontFace", pwszDefaultFace));
	wstring_ptr wstrFontSize(pProfile->getString(
		pwszSection, L"FontSize", L"9"));
	WCHAR* pEnd = 0;
	double dFontSize = wcstod(wstrFontSize.get(), &pEnd);
	if (*pEnd)
		dFontSize = 9;
	int nFontStyle = pProfile->getInt(pwszSection, L"FontStyle", 0);
	int nFontCharset = pProfile->getInt(pwszSection, L"FontCharset", 0);

	ClientDeviceContext dc(0);
	FontHelper::createLogFont(dc, wstrFontFace.get(),
		dFontSize, nFontStyle, nFontCharset, pLogFont);
}

void qs::UIUtil::setLogFontToProfile(Profile* pProfile,
									 const WCHAR* pwszSection,
									 const LOGFONT& lf)
{
	assert(pProfile);
	assert(pwszSection);

	T2W(lf.lfFaceName, pwszFaceName);
	pProfile->setString(pwszSection, L"FontFace", pwszFaceName);

	ClientDeviceContext dc(0);
	double dPointSize = -lf.lfHeight*72.0/dc.getDeviceCaps(LOGPIXELSY);
	WCHAR wszSize[64];
	swprintf(wszSize, L"%.1lf", dPointSize);
	size_t nLen = wcslen(wszSize);
	if (nLen > 2 && wcscmp(wszSize + nLen - 2, L".0") == 0)
		wszSize[nLen - 2] = L'\0';
	pProfile->setString(pwszSection, L"FontSize", wszSize);

	int nFontStyle = 0;
	if (lf.lfWeight >= FW_BOLD)
		nFontStyle |= FontHelper::STYLE_BOLD;
	if (lf.lfItalic)
		nFontStyle |= FontHelper::STYLE_ITALIC;
	if (lf.lfUnderline)
		nFontStyle |= FontHelper::STYLE_UNDERLINE;
	if (lf.lfStrikeOut)
		nFontStyle |= FontHelper::STYLE_STRIKEOUT;
	pProfile->setInt(pwszSection, L"FontStyle", nFontStyle);

	if (lf.lfCharSet != 0)
		pProfile->setInt(pwszSection, L"FontCharset", lf.lfCharSet);
}

bool qs::UIUtil::browseFont(HWND hwnd,
							LOGFONT* pLogFont)
{
#if 0//!defined _WIN32_WCE || (_WIN32_WCE >= 400 && !defined _WIN32_WCE_PSPC)
	CHOOSEFONT cf = {
		sizeof(cf),
		hwnd,
		0,
		pLogFont,
		0,
		CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS,
	};
	return ::ChooseFont(&cf) != 0;
#else
	FontDialog dialog(*pLogFont);
	if (dialog.doModal(hwnd) != IDOK)
		return false;

	*pLogFont = dialog.getLogFont();

	return true;
#endif
}

#ifndef _WIN32_WCE
static int CALLBACK browseCallbackProc(HWND hwnd,
									   UINT uMsg,
									   LPARAM lParam,
									   LPARAM lpData)
{
	switch (uMsg) {
	case BFFM_INITIALIZED:
		::SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
		break;
	}
	return 0;
}
#endif

wstring_ptr qs::UIUtil::browseFolder(HWND hwnd,
									 const WCHAR* pwszTitle,
									 const WCHAR* pwszInitialPath)
{
	wstring_ptr wstrPath;

#ifdef _WIN32_WCE
	BrowseFolderDialog dialog(pwszTitle, pwszInitialPath);
	int nRet = dialog.doModal(hwnd);
	if (nRet == IDOK)
		wstrPath = allocWString(dialog.getPath());
#else
	W2T(pwszTitle, ptszTitle);
	W2T(pwszInitialPath, ptszInitialPath);
	TCHAR tszDisplayName[MAX_PATH];
	BROWSEINFO info = {
		hwnd,
		0,
		tszDisplayName,
		ptszTitle,
		BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE,
		&browseCallbackProc,
		reinterpret_cast<LPARAM>(ptszInitialPath),
		0
	};
	LPITEMIDLIST pList = ::SHBrowseForFolder(&info);
	if (pList) {
		TCHAR tszPath[MAX_PATH];
		if (::SHGetPathFromIDList(pList, tszPath))
			wstrPath = tcs2wcs(tszPath);

		ComPtr<IMalloc> pMalloc;
		::SHGetMalloc(&pMalloc);
		pMalloc->Free(pList);
	}
#endif

	return wstrPath;
}

#ifndef _WIN32_WCE
bool qs::UIUtil::drawThemeBorder(Theme* pTheme,
								 HWND hwnd,
								 int nPartId,
								 int nStateId,
								 COLORREF crBackground)
{
	RECT rect;
	::GetWindowRect(hwnd, &rect);
	rect.right -= rect.left;
	rect.left = 0;
	rect.bottom -= rect.top;
	rect.top = 0;

	WindowDeviceContext dc(hwnd);
	int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE);
	int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE);
	dc.excludeClipRect(nEdgeWidth, nEdgeHeight,
		rect.right - nEdgeWidth, rect.bottom - nEdgeHeight);
	dc.fillSolidRect(rect, crBackground);

	int nBorderWidth = pTheme->getSysSize(SM_CXBORDER);
	int nBorderHeight = pTheme->getSysSize(SM_CYBORDER);
	dc.excludeClipRect(nBorderWidth, nBorderHeight,
		rect.right - nBorderWidth, rect.bottom - nBorderHeight);
	return pTheme->drawBackground(dc.getHandle(), nPartId, nStateId, rect, 0);
}
#endif

int qs::UIUtil::getLogPixel()
{
	ClientDeviceContext dc(0);
	return dc.getDeviceCaps(LOGPIXELSY);
}

#if defined _WIN32_WCE && _WIN32_WCE >= 300 && defined _WIN32_WCE_PSPC
void qs::UIUtil::getWorkArea(RECT* pRect)
{
	assert(pRect);

	const int nDefaultMenuHeight = 26;
	ClientDeviceContext dc(0);
	int nMenuHeight = static_cast<int>(nDefaultMenuHeight*(getLogPixel()/96.0));

	SIPINFO si = { sizeof(si) };
	::SHSipInfo(SPI_GETSIPINFO, 0, &si, 0);

	*pRect = si.rcVisibleDesktop;
	if ((si.fdwFlags & SIPF_ON) == 0)
		pRect->bottom -= nMenuHeight;
}
#endif
<|endoftext|>


<commit_before>#ifndef __STOUT_PROTOBUF_HPP__
#define __STOUT_PROTOBUF_HPP__

#include <errno.h>
#include <stdint.h>
#include <unistd.h>

#include <sys/types.h>

#include <glog/logging.h>

#include <google/protobuf/message.h>

#include <google/protobuf/io/zero_copy_stream_impl.h>

#include <string>

#include <boost/lexical_cast.hpp>

#include "os.hpp"
#include "result.hpp"
#include "try.hpp"

namespace protobuf {

// Write out the given protobuf to the specified file descriptor by
// first writing out the length of the protobuf followed by the contents.
// NOTE: On error, this may have written partial data to the file.
inline Try<Nothing> write(int fd, const google::protobuf::Message& message)
{
  if (!message.IsInitialized()) {
    return Try<Nothing>::error("protocol buffer is not initialized");
  }

  // First write the size of the protobuf.
  uint32_t size = message.ByteSize();
  std::string bytes = std::string((char*) &size, sizeof(size));

  Try<Nothing> result = os::write(fd, bytes);
  if (result.isError()) {
    return Try<Nothing>::error(
        "Failed to write protobuf size: " + result.error());
  }

  // NOTE: It appears that SerializeToFileDescriptor will keep
  // errno intact on failure, but this may change.
  if (!message.SerializeToFileDescriptor(fd)) {
    return Try<Nothing>::error(
        "Failed to SerializeToFileDescriptor, possible strerror: " +
        std::string(strerror(errno)));
  }

  return Nothing();
}

// A wrapper function that wraps the above write with open and closing the file.
inline Try<Nothing> write(
    const std::string& path,
    const google::protobuf::Message& message)
{
  Try<int> fd = os::open(
      path,
      O_WRONLY | O_CREAT | O_TRUNC,
      S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);

  if (fd.isError()) {
    return Try<Nothing>::error(
        "Failed to open file " + path + ": " + fd.error());
  }

  Try<Nothing> result = write(fd.get(), message);

  // NOTE: We ignore the return value of close(). This is because users calling
  // this function are interested in the return value of write(). Also an
  // unsuccessful close() doesn't affect the write.
  os::close(fd.get());

  return result;
}

// Read the next protobuf of type T from the file by first reading the "size"
// followed by the contents (as written by 'write' above).
template <typename T>
inline Result<T> read(int fd)
{
  // Save the offset so we can re-adjust if something goes wrong.
  off_t offset = lseek(fd, 0, SEEK_CUR);
  if (offset == -1) {
    return Result<T>::error(
        "Failed to lseek to SEEK_CUR: " + std::string(strerror(errno)));
  }

  uint32_t size;
  Result<std::string> result = os::read(fd, sizeof(size));

  if (result.isNone()) {
    return Result<T>::none(); // No more protobufs to read.
  } else if (result.isError()) {
    return Result<T>::error("Failed to read protobuf size: " + result.error());
  }

  // Parse the size from the bytes.
  memcpy((void*) &size, (void*) result.get().data(), sizeof(size));

  // NOTE: Instead of specifically checking for corruption in 'size', we simply
  // try to read 'size' bytes. If we hit EOF early, it is an indication of
  // corruption.
  result = os::read(fd, size);

  if (result.isNone()) {
    // Hit EOF unexpectedly. Restore the offset to before the size read.
    lseek(fd, offset, SEEK_SET);
    return Result<T>::error(
        "Failed to read protobuf of size " + stringify(size) + " bytes: "
        "hit EOF unexpectedly, possible corruption");
  } else if (result.isError()) {
    // Restore the offset to before the size read.
    lseek(fd, offset, SEEK_SET);
    return Result<T>::error("Failed to read protobuf: " + result.error());
  }

  // Parse the protobuf from the string.
  T message;
  google::protobuf::io::ArrayInputStream stream(
      result.get().data(), result.get().size());
  bool parsed = message.ParseFromZeroCopyStream(&stream);

  if (!parsed) {
    // Restore the offset to before the size read.
    lseek(fd, offset, SEEK_SET);
    // NOTE: It appears that ParseFromZeroCopyStream will keep
    // errno intact on failure, but this may change.
    return Result<T>::error(
        "Failed to ParseFromZeroCopyStream, possible strerror: " +
        std::string(strerror(errno)));
  }

  return message;
}

// A wrapper function that wraps the above read() with
// open and closing the file.
template <typename T>
inline Result<T> read(const std::string& path)
{
  Try<int> fd = os::open(
      path, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);

  if (fd.isError()) {
    return Result<bool>::error("Failed to open file " + path);
  }

  Result<T> result = read<T>(fd.get());

  // NOTE: We ignore the return value of close(). This is because users calling
  // this function are interested in the return value of read(). Also an
  // unsuccessful close() doesn't affect the read.
  os::close(fd.get());

  return result;
}

} // namespace protobuf {

#endif // __STOUT_PROTOBUF_HPP__
<commit_msg>Fixed a bug in protobuf read() for non-bool template instantiation.<commit_after>#ifndef __STOUT_PROTOBUF_HPP__
#define __STOUT_PROTOBUF_HPP__

#include <errno.h>
#include <stdint.h>
#include <unistd.h>

#include <sys/types.h>

#include <glog/logging.h>

#include <google/protobuf/message.h>

#include <google/protobuf/io/zero_copy_stream_impl.h>

#include <string>

#include <boost/lexical_cast.hpp>

#include "os.hpp"
#include "result.hpp"
#include "try.hpp"

namespace protobuf {

// Write out the given protobuf to the specified file descriptor by
// first writing out the length of the protobuf followed by the contents.
// NOTE: On error, this may have written partial data to the file.
inline Try<Nothing> write(int fd, const google::protobuf::Message& message)
{
  if (!message.IsInitialized()) {
    return Try<Nothing>::error("protocol buffer is not initialized");
  }

  // First write the size of the protobuf.
  uint32_t size = message.ByteSize();
  std::string bytes = std::string((char*) &size, sizeof(size));

  Try<Nothing> result = os::write(fd, bytes);
  if (result.isError()) {
    return Try<Nothing>::error(
        "Failed to write protobuf size: " + result.error());
  }

  // NOTE: It appears that SerializeToFileDescriptor will keep
  // errno intact on failure, but this may change.
  if (!message.SerializeToFileDescriptor(fd)) {
    return Try<Nothing>::error(
        "Failed to SerializeToFileDescriptor, possible strerror: " +
        std::string(strerror(errno)));
  }

  return Nothing();
}

// A wrapper function that wraps the above write with open and closing the file.
inline Try<Nothing> write(
    const std::string& path,
    const google::protobuf::Message& message)
{
  Try<int> fd = os::open(
      path,
      O_WRONLY | O_CREAT | O_TRUNC,
      S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);

  if (fd.isError()) {
    return Try<Nothing>::error(
        "Failed to open file '" + path + "': " + fd.error());
  }

  Try<Nothing> result = write(fd.get(), message);

  // NOTE: We ignore the return value of close(). This is because users calling
  // this function are interested in the return value of write(). Also an
  // unsuccessful close() doesn't affect the write.
  os::close(fd.get());

  return result;
}

// Read the next protobuf of type T from the file by first reading the "size"
// followed by the contents (as written by 'write' above).
template <typename T>
inline Result<T> read(int fd)
{
  // Save the offset so we can re-adjust if something goes wrong.
  off_t offset = lseek(fd, 0, SEEK_CUR);
  if (offset == -1) {
    return Result<T>::error(
        "Failed to lseek to SEEK_CUR: " + std::string(strerror(errno)));
  }

  uint32_t size;
  Result<std::string> result = os::read(fd, sizeof(size));

  if (result.isNone()) {
    return Result<T>::none(); // No more protobufs to read.
  } else if (result.isError()) {
    return Result<T>::error("Failed to read protobuf size: " + result.error());
  }

  // Parse the size from the bytes.
  memcpy((void*) &size, (void*) result.get().data(), sizeof(size));

  // NOTE: Instead of specifically checking for corruption in 'size', we simply
  // try to read 'size' bytes. If we hit EOF early, it is an indication of
  // corruption.
  result = os::read(fd, size);

  if (result.isNone()) {
    // Hit EOF unexpectedly. Restore the offset to before the size read.
    lseek(fd, offset, SEEK_SET);
    return Result<T>::error(
        "Failed to read protobuf of size " + stringify(size) + " bytes: "
        "hit EOF unexpectedly, possible corruption");
  } else if (result.isError()) {
    // Restore the offset to before the size read.
    lseek(fd, offset, SEEK_SET);
    return Result<T>::error("Failed to read protobuf: " + result.error());
  }

  // Parse the protobuf from the string.
  T message;
  google::protobuf::io::ArrayInputStream stream(
      result.get().data(), result.get().size());
  bool parsed = message.ParseFromZeroCopyStream(&stream);

  if (!parsed) {
    // Restore the offset to before the size read.
    lseek(fd, offset, SEEK_SET);
    // NOTE: It appears that ParseFromZeroCopyStream will keep
    // errno intact on failure, but this may change.
    return Result<T>::error(
        "Failed to ParseFromZeroCopyStream, possible strerror: " +
        std::string(strerror(errno)));
  }

  return message;
}

// A wrapper function that wraps the above read() with
// open and closing the file.
template <typename T>
inline Result<T> read(const std::string& path)
{
  Try<int> fd = os::open(
      path, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO);

  if (fd.isError()) {
    return Result<T>::error(
        "Failed to open file '" + path + "': " + fd.error());
  }

  Result<T> result = read<T>(fd.get());

  // NOTE: We ignore the return value of close(). This is because users calling
  // this function are interested in the return value of read(). Also an
  // unsuccessful close() doesn't affect the read.
  os::close(fd.get());

  return result;
}

} // namespace protobuf {

#endif // __STOUT_PROTOBUF_HPP__
<|endoftext|>


<commit_before>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by Robert E. Smith, 04/08/14.

    This file is part of MRtrix.

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

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

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "file/ofstream.h"

#include "file/utils.h"

namespace MR
{
  namespace File
  {

  void OFStream::open (const std::string& path, const std::ios_base::openmode mode)
  {
    if (!(mode & std::ios_base::app) && !(mode & std::ios_base::ate) && !(mode & std::ios_base::in))
      if (!File::is_tempfile (path))
        File::output_file_check (path);

    std::ofstream::open (path.c_str(), mode);
    if (std::ofstream::operator!())
      throw Exception ("error opening output file \"" + path + "\": " + std::strerror (errno));
  }

  }
}

<commit_msg>File::OFStream: Use File::create() instead of File::output_file_check()<commit_after>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by Robert E. Smith, 04/08/14.

    This file is part of MRtrix.

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

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

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "file/ofstream.h"

#include "file/utils.h"

namespace MR
{
  namespace File
  {

  void OFStream::open (const std::string& path, const std::ios_base::openmode mode)
  {
    if (!(mode & std::ios_base::app) && !(mode & std::ios_base::ate) && !(mode & std::ios_base::in)) {
      if (!File::is_tempfile (path))
        File::create (path);
    }

    std::ofstream::open (path.c_str(), mode);
    if (std::ofstream::operator!())
      throw Exception ("error opening output file \"" + path + "\": " + std::strerror (errno));
  }

  }
}

<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *  Copyright (C) 2012  Martin Schmölzer <martin@schmoelzer.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/consteval.h"
#include "kernel/celltypes.h"
#include "fsmdata.h"
#include <string>
#include <iostream>
#include <fstream>

/**
 * Convert a signal into a KISS-compatible textual representation.
 */
std::string kiss_convert_signal(const RTLIL::SigSpec &sig) {
	if (!sig.is_fully_const()) {
		throw 0;
	}

	return sig.as_const().as_string();
}

/**
 * Create a KISS2 file from a cell.
 *
 * The destination file name is taken from the fsm_export attribute if present,
 * e.g. (* fsm_export="filename.kiss2" *). If this attribute is not present,
 * the file name will be assembled from the module and cell names.
 *
 * @param module pointer to module which contains the FSM cell.
 * @param cell pointer to the FSM cell which should be exported.
 */
void write_kiss2(struct RTLIL::Module *module, struct RTLIL::Cell *cell, std::string filename) {
	std::map<RTLIL::IdString, RTLIL::Const>::iterator attr_it;
	FsmData fsm_data;
	FsmData::transition_t tr;
	std::ofstream kiss_file;
	std::string kiss_name;
	size_t i;

	attr_it = cell->attributes.find("\\fsm_export");
	if (!filename.empty()) {
	  kiss_name.assign(filename);
	} else if (attr_it != cell->attributes.end() && attr_it->second.str != "") {
		kiss_name.assign(attr_it->second.str);
	}
	else {
		kiss_name.assign(module->name);
		kiss_name.append('-' + cell->name + ".kiss2");
	}

	log("\n");
	log("Exporting FSM `%s' from module `%s' to file `%s'.\n",
			cell->name.c_str(),
			module->name.c_str(),
			kiss_name.c_str());

	kiss_file.open(kiss_name, std::ios::out | std::ios::trunc);

	if (!kiss_file.is_open()) {
		log_error("Could not open file \"%s\" with write access.\n", kiss_name.c_str());
	}

	fsm_data.copy_from_cell(cell);

	kiss_file << ".i "  << std::dec << fsm_data.num_inputs << std::endl;
	kiss_file << ".o "  << std::dec << fsm_data.num_outputs << std::endl;
	kiss_file << ".p "  << std::dec << fsm_data.transition_table.size() << std::endl;
	kiss_file << ".s "  << std::dec << fsm_data.state_table.size() << std::endl;
	kiss_file << ".r s" << std::dec << fsm_data.reset_state << std::endl;

	for (i = 0; i < fsm_data.transition_table.size(); i++) {
		tr = fsm_data.transition_table[i];

		try {
			kiss_file << kiss_convert_signal(tr.ctrl_in) << ' ';
			kiss_file << 's' << tr.state_in << ' ';
			kiss_file << 's' << tr.state_out << ' ';
			kiss_file << kiss_convert_signal(tr.ctrl_out) << std::endl;
		}
		catch (int) {
			kiss_file.close();
			log_error("exporting an FSM input or output signal failed.\n");
		}
	}

	kiss_file.close();
}

/**
 * Exports Finite State Machines in the design to one file per FSM. Currently,
 * only the KISS2 file format is supported.
 */
struct FsmExportPass : public Pass {
	FsmExportPass() : Pass("fsm_export", "exporting FSMs to KISS2 files") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    fsm_export [-noauto] [-o filename] [selection]\n");
		log("\n");
		log("This pass creates a KISS2 file for every selected FSM. For FSMs with the\n");
		log("'fsm_export' attribute set, the attribute value is used as filename, otherwise\n");
		log("the module and cell name is used as filename. If the parameter '-o' is given,\n");
		log("the first exported FSM is written to the specified filename. This overwrites\n");
		log("the setting as specified with the 'fsm_export' attribute. All other FSMs are\n");
		log("exported to the default name as mentioned above.\n");
		log("\n");
		log("    -noauto\n");
		log("        only export FSMs that have the 'fsm_export' attribute set\n");
		log("\n");
		log("    -o filename\n");
		log("        filename of the first exported FSM\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		std::map<RTLIL::IdString, RTLIL::Const>::iterator attr_it;
		std::string arg;
		bool flag_noauto = false;
		std::string filename;
		size_t argidx;

		log_header("Executing FSM_EXPORT pass (exporting FSMs in KISS2 file format).\n");

		for (argidx = 1; argidx < args.size(); argidx++) {
			arg = args[argidx];
			if (arg == "-noauto") {
				flag_noauto = true;
				continue;
			}
			if (arg == "-o") {
				argidx++;
				filename = args[argidx];
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		for (auto &mod_it : design->modules)
			if (design->selected(mod_it.second))
				for (auto &cell_it : mod_it.second->cells)
					if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second)) {
						attr_it = cell_it.second->attributes.find("\\fsm_export");
						if (!flag_noauto || (attr_it != cell_it.second->attributes.end())) {
							write_kiss2(mod_it.second, cell_it.second, filename);
							filename.clear();
						}
					}
	}
} FsmExportPass;
<commit_msg>fsm_export: optionally use binary state encoding as state names instead of s0, s1, ...<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *  Copyright (C) 2012  Martin Schmölzer <martin@schmoelzer.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/consteval.h"
#include "kernel/celltypes.h"
#include "fsmdata.h"
#include <string>
#include <iostream>
#include <fstream>

/**
 * Convert a signal into a KISS-compatible textual representation.
 */
std::string kiss_convert_signal(const RTLIL::SigSpec &sig) {
	if (!sig.is_fully_const()) {
		throw 0;
	}

	return sig.as_const().as_string();
}

/**
 * Create a KISS2 file from a cell.
 *
 * The destination file name is taken from the fsm_export attribute if present,
 * e.g. (* fsm_export="filename.kiss2" *). If this attribute is not present,
 * the file name will be assembled from the module and cell names.
 *
 * @param module pointer to module which contains the FSM cell.
 * @param cell pointer to the FSM cell which should be exported.
 */
void write_kiss2(struct RTLIL::Module *module, struct RTLIL::Cell *cell, std::string filename, bool origenc) {
	std::map<RTLIL::IdString, RTLIL::Const>::iterator attr_it;
	FsmData fsm_data;
	FsmData::transition_t tr;
	std::ofstream kiss_file;
	std::string kiss_name;
	size_t i;

	attr_it = cell->attributes.find("\\fsm_export");
	if (!filename.empty()) {
	  kiss_name.assign(filename);
	} else if (attr_it != cell->attributes.end() && attr_it->second.str != "") {
		kiss_name.assign(attr_it->second.str);
	}
	else {
		kiss_name.assign(module->name);
		kiss_name.append('-' + cell->name + ".kiss2");
	}

	log("\n");
	log("Exporting FSM `%s' from module `%s' to file `%s'.\n",
			cell->name.c_str(),
			module->name.c_str(),
			kiss_name.c_str());

	kiss_file.open(kiss_name, std::ios::out | std::ios::trunc);

	if (!kiss_file.is_open()) {
		log_error("Could not open file \"%s\" with write access.\n", kiss_name.c_str());
	}

	fsm_data.copy_from_cell(cell);

	kiss_file << ".i "  << std::dec << fsm_data.num_inputs << std::endl;
	kiss_file << ".o "  << std::dec << fsm_data.num_outputs << std::endl;
	kiss_file << ".p "  << std::dec << fsm_data.transition_table.size() << std::endl;
	kiss_file << ".s "  << std::dec << fsm_data.state_table.size() << std::endl;
	if (origenc) {
		kiss_file << ".r " << kiss_convert_signal(fsm_data.state_table[fsm_data.reset_state]) << std::endl;
	} else {
		kiss_file << ".r s" << std::dec << fsm_data.reset_state << std::endl;
	}

	for (i = 0; i < fsm_data.transition_table.size(); i++) {
		tr = fsm_data.transition_table[i];

		try {
			kiss_file << kiss_convert_signal(tr.ctrl_in) << ' ';
			if (origenc) {
				kiss_file << kiss_convert_signal(fsm_data.state_table[tr.state_in])  << ' ';
				kiss_file << kiss_convert_signal(fsm_data.state_table[tr.state_out]) << ' ';
			} else {
				kiss_file << 's' << tr.state_in << ' ';
				kiss_file << 's' << tr.state_out << ' ';
			}
			kiss_file << kiss_convert_signal(tr.ctrl_out) << std::endl;
		}
		catch (int) {
			kiss_file.close();
			log_error("exporting an FSM input or output signal failed.\n");
		}
	}

	kiss_file.close();
}

/**
 * Exports Finite State Machines in the design to one file per FSM. Currently,
 * only the KISS2 file format is supported.
 */
struct FsmExportPass : public Pass {
	FsmExportPass() : Pass("fsm_export", "exporting FSMs to KISS2 files") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    fsm_export [-noauto] [-o filename] [-origenc] [selection]\n");
		log("\n");
		log("This pass creates a KISS2 file for every selected FSM. For FSMs with the\n");
		log("'fsm_export' attribute set, the attribute value is used as filename, otherwise\n");
		log("the module and cell name is used as filename. If the parameter '-o' is given,\n");
		log("the first exported FSM is written to the specified filename. This overwrites\n");
		log("the setting as specified with the 'fsm_export' attribute. All other FSMs are\n");
		log("exported to the default name as mentioned above.\n");
		log("\n");
		log("    -noauto\n");
		log("        only export FSMs that have the 'fsm_export' attribute set\n");
		log("\n");
		log("    -o filename\n");
		log("        filename of the first exported FSM\n");
		log("\n");
		log("    -origenc\n");
		log("        use binary state encoding as state names instead of s0, s1, ...\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		std::map<RTLIL::IdString, RTLIL::Const>::iterator attr_it;
		std::string arg;
		bool flag_noauto = false;
		std::string filename;
		bool flag_origenc = false;
		size_t argidx;

		log_header("Executing FSM_EXPORT pass (exporting FSMs in KISS2 file format).\n");

		for (argidx = 1; argidx < args.size(); argidx++) {
			arg = args[argidx];
			if (arg == "-noauto") {
				flag_noauto = true;
				continue;
			}
			if (arg == "-o") {
				argidx++;
				filename = args[argidx];
				continue;
			}
			if (arg == "-origenc") {
				flag_origenc = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		for (auto &mod_it : design->modules)
			if (design->selected(mod_it.second))
				for (auto &cell_it : mod_it.second->cells)
					if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second)) {
						attr_it = cell_it.second->attributes.find("\\fsm_export");
						if (!flag_noauto || (attr_it != cell_it.second->attributes.end())) {
							write_kiss2(mod_it.second, cell_it.second, filename, flag_origenc);
							filename.clear();
						}
					}
	}
} FsmExportPass;
<|endoftext|>


<commit_before>// Author: Enrico Guiraud CERN 09/2020

/*************************************************************************
 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RDF_COLUMNREADERUTILS
#define ROOT_RDF_COLUMNREADERUTILS

#include "RColumnReaderBase.hxx"
#include "RDefineBase.hxx"
#include "RDefineReader.hxx"
#include "RDSColumnReader.hxx"
#include "RTreeColumnReader.hxx"

#include <ROOT/RDataSource.hxx>
#include <ROOT/TypeTraits.hxx>
#include <TError.h> // R__ASSERT
#include <TTreeReader.h>

#include <array>
#include <map>
#include <memory>
#include <string>
#include <typeinfo> // for typeid
#include <vector>

namespace ROOT {
namespace Internal {
namespace RDF {

using namespace ROOT::TypeTraits;
namespace RDFDetail = ROOT::Detail::RDF;

template <typename T>
std::unique_ptr<RDFDetail::RColumnReaderBase>
MakeColumnReader(unsigned int slot, RDFDetail::RDefineBase *define, TTreeReader *r, ROOT::RDF::RDataSource *ds,
                 const std::vector<void *> *DSValuePtrsPtr, const std::string &colName)
{
   using Ret_t = std::unique_ptr<RDFDetail::RColumnReaderBase>;

   // this check must come first!
   // so that Redefine'd columns have precedence over the original columns
   if (define != nullptr)
      return Ret_t(new RDefineReader(slot, *define, typeid(T)));

   if (DSValuePtrsPtr != nullptr) {
      // reading from a RDataSource with the old column reader interface
      auto &DSValuePtrs = *DSValuePtrsPtr;
      return Ret_t(new RDSColumnReader<T>(DSValuePtrs[slot]));
   }

   if (ds != nullptr) {
      // reading from a RDataSource with the new column reader interface
      return ds->GetColumnReaders(slot, colName, typeid(T));
   }

   // reading from a TTree
   return Ret_t(new RTreeColumnReader<T>(*r, colName));
}

template <typename T>
std::unique_ptr<RDFDetail::RColumnReaderBase>
MakeColumnReadersHelper(unsigned int slot, RDFDetail::RDefineBase *define,
                        const std::map<std::string, std::vector<void *>> &DSValuePtrsMap, TTreeReader *r,
                        ROOT::RDF::RDataSource *ds, const std::string &colName)
{
   const auto DSValuePtrsIt = DSValuePtrsMap.find(colName);
   const std::vector<void *> *DSValuePtrsPtr = DSValuePtrsIt != DSValuePtrsMap.end() ? &DSValuePtrsIt->second : nullptr;
   R__ASSERT(define != nullptr || r != nullptr || DSValuePtrsPtr != nullptr || ds != nullptr);
   return MakeColumnReader<T>(slot, define, r, ds, DSValuePtrsPtr, colName);
}

/// This type aggregates some of the arguments passed to InitColumnReaders.
/// We need to pass a single RColumnReadersInfo object rather than each argument separately because with too many
/// arguments passed, gcc 7.5.0 and cling disagree on the ABI, which leads to the last function argument being read
/// incorrectly from a compiled InitColumnReaders symbols when invoked from a jitted symbol.
struct RColumnReadersInfo {
   const std::vector<std::string> &fColNames;
   const RBookedDefines &fCustomCols;
   const bool *fIsDefine;
   const std::map<std::string, std::vector<void *>> &fDSValuePtrsMap;
   ROOT::RDF::RDataSource *fDataSource;
};

/// Create a group of column readers, one per type in the parameter pack.
/// colInfo.fColNames and colInfo.fIsDefine are expected to have size equal to the parameter pack, and elements ordered
/// accordingly, i.e. fIsDefine[0] refers to fColNames[0] which is of type "ColTypes[0]".
template <typename... ColTypes>
std::array<std::unique_ptr<RDFDetail::RColumnReaderBase>, sizeof...(ColTypes)>
MakeColumnReaders(unsigned int slot, TTreeReader *r, TypeList<ColTypes...>, const RColumnReadersInfo &colInfo)
{
   // see RColumnReadersInfo for why we pass these arguments like this rather than directly as function arguments
   const auto &colNames = colInfo.fColNames;
   const auto &customCols = colInfo.fCustomCols;
   const bool *isDefine = colInfo.fIsDefine;
   const auto &DSValuePtrsMap = colInfo.fDSValuePtrsMap;
   auto *ds = colInfo.fDataSource;

   const auto &customColMap = customCols.GetColumns();

   int i = -1;
   std::array<std::unique_ptr<RDFDetail::RColumnReaderBase>, sizeof...(ColTypes)> ret{
      {{(++i, MakeColumnReadersHelper<ColTypes>(slot, isDefine[i] ? customColMap.at(colNames[i]).get() : nullptr,
                                                DSValuePtrsMap, r, ds, colNames[i]))}...}};
   return ret;

   // avoid bogus "unused variable" warnings
   (void)ds;
   (void)slot;
   (void)r;
}

} // namespace RDF
} // namespace Internal
} // namespace ROOT

#endif // ROOT_RDF_COLUMNREADERS
<commit_msg>[NFC][DF] Fix function name in comments<commit_after>// Author: Enrico Guiraud CERN 09/2020

/*************************************************************************
 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RDF_COLUMNREADERUTILS
#define ROOT_RDF_COLUMNREADERUTILS

#include "RColumnReaderBase.hxx"
#include "RDefineBase.hxx"
#include "RDefineReader.hxx"
#include "RDSColumnReader.hxx"
#include "RTreeColumnReader.hxx"

#include <ROOT/RDataSource.hxx>
#include <ROOT/TypeTraits.hxx>
#include <TError.h> // R__ASSERT
#include <TTreeReader.h>

#include <array>
#include <map>
#include <memory>
#include <string>
#include <typeinfo> // for typeid
#include <vector>

namespace ROOT {
namespace Internal {
namespace RDF {

using namespace ROOT::TypeTraits;
namespace RDFDetail = ROOT::Detail::RDF;

template <typename T>
std::unique_ptr<RDFDetail::RColumnReaderBase>
MakeColumnReader(unsigned int slot, RDFDetail::RDefineBase *define, TTreeReader *r, ROOT::RDF::RDataSource *ds,
                 const std::vector<void *> *DSValuePtrsPtr, const std::string &colName)
{
   using Ret_t = std::unique_ptr<RDFDetail::RColumnReaderBase>;

   // this check must come first!
   // so that Redefine'd columns have precedence over the original columns
   if (define != nullptr)
      return Ret_t(new RDefineReader(slot, *define, typeid(T)));

   if (DSValuePtrsPtr != nullptr) {
      // reading from a RDataSource with the old column reader interface
      auto &DSValuePtrs = *DSValuePtrsPtr;
      return Ret_t(new RDSColumnReader<T>(DSValuePtrs[slot]));
   }

   if (ds != nullptr) {
      // reading from a RDataSource with the new column reader interface
      return ds->GetColumnReaders(slot, colName, typeid(T));
   }

   // reading from a TTree
   return Ret_t(new RTreeColumnReader<T>(*r, colName));
}

template <typename T>
std::unique_ptr<RDFDetail::RColumnReaderBase>
MakeColumnReadersHelper(unsigned int slot, RDFDetail::RDefineBase *define,
                        const std::map<std::string, std::vector<void *>> &DSValuePtrsMap, TTreeReader *r,
                        ROOT::RDF::RDataSource *ds, const std::string &colName)
{
   const auto DSValuePtrsIt = DSValuePtrsMap.find(colName);
   const std::vector<void *> *DSValuePtrsPtr = DSValuePtrsIt != DSValuePtrsMap.end() ? &DSValuePtrsIt->second : nullptr;
   R__ASSERT(define != nullptr || r != nullptr || DSValuePtrsPtr != nullptr || ds != nullptr);
   return MakeColumnReader<T>(slot, define, r, ds, DSValuePtrsPtr, colName);
}

/// This type aggregates some of the arguments passed to MakeColumnReaders.
/// We need to pass a single RColumnReadersInfo object rather than each argument separately because with too many
/// arguments passed, gcc 7.5.0 and cling disagree on the ABI, which leads to the last function argument being read
/// incorrectly from a compiled MakeColumnReaders symbols when invoked from a jitted symbol.
struct RColumnReadersInfo {
   const std::vector<std::string> &fColNames;
   const RBookedDefines &fCustomCols;
   const bool *fIsDefine;
   const std::map<std::string, std::vector<void *>> &fDSValuePtrsMap;
   ROOT::RDF::RDataSource *fDataSource;
};

/// Create a group of column readers, one per type in the parameter pack.
/// colInfo.fColNames and colInfo.fIsDefine are expected to have size equal to the parameter pack, and elements ordered
/// accordingly, i.e. fIsDefine[0] refers to fColNames[0] which is of type "ColTypes[0]".
template <typename... ColTypes>
std::array<std::unique_ptr<RDFDetail::RColumnReaderBase>, sizeof...(ColTypes)>
MakeColumnReaders(unsigned int slot, TTreeReader *r, TypeList<ColTypes...>, const RColumnReadersInfo &colInfo)
{
   // see RColumnReadersInfo for why we pass these arguments like this rather than directly as function arguments
   const auto &colNames = colInfo.fColNames;
   const auto &customCols = colInfo.fCustomCols;
   const bool *isDefine = colInfo.fIsDefine;
   const auto &DSValuePtrsMap = colInfo.fDSValuePtrsMap;
   auto *ds = colInfo.fDataSource;

   const auto &customColMap = customCols.GetColumns();

   int i = -1;
   std::array<std::unique_ptr<RDFDetail::RColumnReaderBase>, sizeof...(ColTypes)> ret{
      {{(++i, MakeColumnReadersHelper<ColTypes>(slot, isDefine[i] ? customColMap.at(colNames[i]).get() : nullptr,
                                                DSValuePtrsMap, r, ds, colNames[i]))}...}};
   return ret;

   // avoid bogus "unused variable" warnings
   (void)ds;
   (void)slot;
   (void)r;
}

} // namespace RDF
} // namespace Internal
} // namespace ROOT

#endif // ROOT_RDF_COLUMNREADERS
<|endoftext|>


<commit_before>#include <cmath>
#include "sphere.h"

namespace pt {

Sphere::Sphere(const glm::vec3 &center, const float radius) : center(center), radius(radius) {}
bool Sphere::intersect(Ray &ray, DifferentialGeometry &dg) const {
	const float a = glm::dot(ray.dir, ray.dir);
	const float b = 2.0 * glm::dot(ray.dir, ray.origin);
	const float c = glm::dot(ray.origin, ray.origin) - radius * radius;
	const float discrim = b * b - 4.0 * a * c;
	if (discrim > 0.f){
		float t = (-b - std::sqrt(discrim)) / (2.0 * a);
		if (t > ray.t_min && t < ray.t_max){
			ray.t_max = t;
			dg.point = ray.origin + ray.dir * t;
			dg.normal = glm::normalize(dg.point - center);
			return true;
		} else {
			t = (-b + std::sqrt(discrim)) / (2.0 * a);
			if (t > ray.t_min && t < ray.t_max){
				ray.t_max = t;
				dg.point = ray.origin + ray.dir * t;
				dg.normal = glm::normalize(dg.point - center);
				return true;
			}
		}
	}
	return false;
}

}

<commit_msg>Actually account for sphere center pos<commit_after>#include <cmath>
#include <glm/ext.hpp>
#include "sphere.h"

namespace pt {

Sphere::Sphere(const glm::vec3 &center, const float radius) : center(center), radius(radius) {}
bool Sphere::intersect(Ray &ray, DifferentialGeometry &dg) const {
	const float a = glm::length2(ray.dir);
	const glm::vec3 oc = ray.origin - center;
	const float b = 2.0 * glm::dot(ray.dir, oc);
	const float c = glm::length2(oc) - radius * radius;
	const float discrim = b * b - 4.0 * a * c;
	if (discrim > 0.f){
		float t = (-b - std::sqrt(discrim)) / (2.0 * a);
		if (t > ray.t_min && t < ray.t_max){
			ray.t_max = t;
			dg.point = ray.origin + ray.dir * t;
			dg.normal = glm::normalize(dg.point - center);
			return true;
		} else {
			t = (-b + std::sqrt(discrim)) / (2.0 * a);
			if (t > ray.t_min && t < ray.t_max){
				ray.t_max = t;
				dg.point = ray.origin + ray.dir * t;
				dg.normal = glm::normalize(dg.point - center);
				return true;
			}
		}
	}
	return false;
}

}

<|endoftext|>


<commit_before>// C++ headers
#include <iostream>
#include <vector>

// Lib headers
#include <apr.h>
#include <sys/time.h>

// App headers
#include "storage_engine/blockstore.h"
#include "storage_engine/volume.h"
#include "storage_engine/nbtree.h"
#include "log_iface.h"
#include "util.h"

using namespace Akumuli::StorageEngine;

class Timer
{
public:
    Timer() { gettimeofday(&_start_time, nullptr); }
    void   restart() { gettimeofday(&_start_time, nullptr); }
    double elapsed() const {
        timeval curr;
        gettimeofday(&curr, nullptr);
        return double(curr.tv_sec - _start_time.tv_sec) +
               double(curr.tv_usec - _start_time.tv_usec)/1000000.0;
    }
private:
    timeval _start_time;
};

static void console_logger(aku_LogLevel lvl, const char* msg) {
    switch(lvl) {
    case AKU_LOG_ERROR:
        std::cerr << "ERROR: " << msg << std::endl;
        break;
    case AKU_LOG_INFO:
        std::cout << "INFO: " << msg << std::endl;
        break;
    case AKU_LOG_TRACE:
        //std::cerr << "trace: " << msg << std::endl;
        break;
    };
}

int main() {
    apr_initialize();

    Akumuli::Logger::set_logger(console_logger);

    const double start = 0.0;
    const double inc = 0.1;
    const double factor = 1.1;
    const int N = 1000000;

    std::cout << "NBTree[w,r]\tIOVec[w,r]" << std::endl;
    double t[4];
    for (int o = 0; o < 10; o++)
    {
        {
            std::unique_ptr<NBTreeLeaf> leaf(new NBTreeLeaf(42, EMPTY_ADDR, 0));
            int leaf_append_cnt = 0;
            LogicAddr last_addr = EMPTY_ADDR;
            LogicAddr first_addr = EMPTY_ADDR;
            auto bstore = BlockStoreBuilder::create_memstore([&](LogicAddr a) {
                if (first_addr == EMPTY_ADDR) {
                    first_addr = a;
                }
                leaf_append_cnt++;
                last_addr = a;
            });
            Timer tm;
            double x = start;
            for (int i = 0; i < N; i++) {
                x += inc;
                x *= factor;
                auto status = leaf->append(i, x);
                if (status == AKU_EOVERFLOW) {
                    LogicAddr addr;
                    std::tie(status, addr) = leaf->commit(bstore);
                    if (status != AKU_SUCCESS) {
                        std::cout << "Failed to commit leaf" << std::endl;
                        std::abort();
                    }
                    if (addr != last_addr) {
                        std::cout << "Unexpected address " << addr << " returned, " << last_addr << " expected" << std::endl;
                        std::abort();
                    }
                    leaf.reset(new NBTreeLeaf(42, EMPTY_ADDR, 0));
                }
            }
            t[0] = tm.elapsed();

            // Read back
            std::vector<aku_Timestamp> ts;
            std::vector<double> xs;
            ts.reserve(5000);
            xs.reserve(5000);

            tm.restart();

            for (LogicAddr addr = first_addr; addr < last_addr; addr++) {
                NBTreeLeaf rdleaf(bstore, addr);
                auto status = rdleaf.read_all(&ts, &xs);
                if(status != AKU_SUCCESS) {
                    std::cout << "Failed to read block " << addr << std::endl;
                    std::abort();
                }
            }

            t[1] = tm.elapsed();
        }
        {
            std::unique_ptr<IOVecLeaf> leaf(new IOVecLeaf(42, EMPTY_ADDR, 0));
            int leaf_append_cnt = 0;
            LogicAddr last_addr = EMPTY_ADDR;
            LogicAddr first_addr = EMPTY_ADDR;
            auto bstore = BlockStoreBuilder::create_memstore([&](LogicAddr a) {
                if (first_addr == EMPTY_ADDR) {
                    first_addr = a;
                }
                leaf_append_cnt++;
                last_addr = a;
            });
            Timer tm;
            double x = start;
            for (int i = 0; i < N; i++) {
                x += inc;
                x *= factor;
                auto status = leaf->append(i, x);
                if (status == AKU_EOVERFLOW) {
                    LogicAddr addr;
                    std::tie(status, addr) = leaf->commit(bstore);
                    if (status != AKU_SUCCESS) {
                        std::cout << "Failed to commit leaf" << std::endl;
                        std::abort();
                    }
                    if (addr != last_addr) {
                        std::cout << "Unexpected address " << addr << " returned, " << last_addr << " expected" << std::endl;
                        std::abort();
                    }
                    leaf.reset(new IOVecLeaf(42, EMPTY_ADDR, 0));
                }
            }
            t[2] = tm.elapsed();

            // Read back
            std::vector<aku_Timestamp> ts;
            std::vector<double> xs;
            ts.reserve(5000);
            xs.reserve(5000);

            tm.restart();

            for (LogicAddr addr = first_addr; addr < last_addr; addr++) {
                NBTreeLeaf rdleaf(bstore, addr);
                auto status = rdleaf.read_all(&ts, &xs);
                if(status != AKU_SUCCESS) {
                    std::cout << "Failed to read block " << addr << std::endl;
                    std::abort();
                }
            }

            t[3] = tm.elapsed();
        }
        std::cout << t[0] << ", " << t[1] << "\t" << t[2] << ", " << t[3] << std::endl;
    }
    return 0;
}
<commit_msg>Check superblock implementation in perf_iovec<commit_after>// C++ headers
#include <iostream>
#include <vector>

// Lib headers
#include <apr.h>
#include <sys/time.h>

// App headers
#include "storage_engine/blockstore.h"
#include "storage_engine/volume.h"
#include "storage_engine/nbtree.h"
#include "log_iface.h"
#include "util.h"

using namespace Akumuli::StorageEngine;

class Timer
{
public:
    Timer() { gettimeofday(&_start_time, nullptr); }
    void   restart() { gettimeofday(&_start_time, nullptr); }
    double elapsed() const {
        timeval curr;
        gettimeofday(&curr, nullptr);
        return double(curr.tv_sec - _start_time.tv_sec) +
               double(curr.tv_usec - _start_time.tv_usec)/1000000.0;
    }
private:
    timeval _start_time;
};

static void console_logger(aku_LogLevel lvl, const char* msg) {
    switch(lvl) {
    case AKU_LOG_ERROR:
        std::cerr << "ERROR: " << msg << std::endl;
        break;
    case AKU_LOG_INFO:
        std::cout << "INFO: " << msg << std::endl;
        break;
    case AKU_LOG_TRACE:
        //std::cerr << "trace: " << msg << std::endl;
        break;
    };
}

int main() {
    apr_initialize();

    Akumuli::Logger::set_logger(console_logger);

    const double start = 0.0;
    const double inc = 0.1;
    const double factor = 1.1;
    const int N = 1000000;

    std::cout << "NBTree[w,r]\tIOVec[w,r]" << std::endl;
    double t[4];
    for (int o = 0; o < 10; o++)
    {
        {
            std::unique_ptr<NBTreeLeaf> leaf(new NBTreeLeaf(42, EMPTY_ADDR, 0));
            int leaf_append_cnt = 0;
            LogicAddr last_addr = EMPTY_ADDR;
            LogicAddr first_addr = EMPTY_ADDR;
            auto bstore = BlockStoreBuilder::create_memstore([&](LogicAddr a) {
                if (first_addr == EMPTY_ADDR) {
                    first_addr = a;
                }
                leaf_append_cnt++;
                last_addr = a;
            });
            Timer tm;
            double x = start;
            for (int i = 0; i < N; i++) {
                x += inc;
                x *= factor;
                auto status = leaf->append(i, x);
                if (status == AKU_EOVERFLOW) {
                    LogicAddr addr;
                    std::tie(status, addr) = leaf->commit(bstore);
                    if (status != AKU_SUCCESS) {
                        std::cout << "Failed to commit leaf" << std::endl;
                        std::abort();
                    }
                    if (addr != last_addr) {
                        std::cout << "Unexpected address " << addr << " returned, " << last_addr << " expected" << std::endl;
                        std::abort();
                    }
                    leaf.reset(new NBTreeLeaf(42, EMPTY_ADDR, 0));
                }
            }
            t[0] = tm.elapsed();

            // Read back
            std::vector<aku_Timestamp> ts;
            std::vector<double> xs;
            ts.reserve(5000);
            xs.reserve(5000);

            tm.restart();

            for (LogicAddr addr = first_addr; addr < last_addr; addr++) {
                NBTreeLeaf rdleaf(bstore, addr);
                auto status = rdleaf.read_all(&ts, &xs);
                if(status != AKU_SUCCESS) {
                    std::cout << "Failed to read block " << addr << std::endl;
                    std::abort();
                }
            }

            t[1] = tm.elapsed();
        }
        {
            std::unique_ptr<IOVecLeaf> leaf(new IOVecLeaf(42, EMPTY_ADDR, 0));
            int leaf_append_cnt = 0;
            LogicAddr last_addr = EMPTY_ADDR;
            LogicAddr first_addr = EMPTY_ADDR;
            auto bstore = BlockStoreBuilder::create_memstore([&](LogicAddr a) {
                if (first_addr == EMPTY_ADDR) {
                    first_addr = a;
                }
                leaf_append_cnt++;
                last_addr = a;
            });
            Timer tm;
            double x = start;
            for (int i = 0; i < N; i++) {
                x += inc;
                x *= factor;
                auto status = leaf->append(i, x);
                if (status == AKU_EOVERFLOW) {
                    LogicAddr addr;
                    std::tie(status, addr) = leaf->commit(bstore);
                    if (status != AKU_SUCCESS) {
                        std::cout << "Failed to commit leaf" << std::endl;
                        std::abort();
                    }
                    if (addr != last_addr) {
                        std::cout << "Unexpected address " << addr << " returned, " << last_addr << " expected" << std::endl;
                        std::abort();
                    }
                    leaf.reset(new IOVecLeaf(42, EMPTY_ADDR, 0));
                }
            }
            t[2] = tm.elapsed();

            // Read back
            std::vector<aku_Timestamp> ts;
            std::vector<double> xs;
            ts.reserve(5000);
            xs.reserve(5000);

            tm.restart();

            for (LogicAddr addr = first_addr; addr < last_addr; addr++) {
                NBTreeLeaf rdleaf(bstore, addr);
                auto status = rdleaf.read_all(&ts, &xs);
                if(status != AKU_SUCCESS) {
                    std::cout << "Failed to read block " << addr << std::endl;
                    std::abort();
                }
            }

            t[3] = tm.elapsed();
        }
        std::cout << t[0] << ", " << t[1] << "\t" << t[2] << ", " << t[3] << std::endl;
    }

    // Check superblock

    std::cout << "SBlock[w,r]\tIOVec[w,r]" << std::endl;
    for (int o = 0; o < 10; o++)
    {
        {
            std::unique_ptr<NBTreeSuperblock> inner(new NBTreeSuperblock(42, EMPTY_ADDR, 0, 1));
            int leaf_append_cnt = 0;
            LogicAddr last_addr = EMPTY_ADDR;
            LogicAddr first_addr = EMPTY_ADDR;
            auto bstore = BlockStoreBuilder::create_memstore([&](LogicAddr a) {
                if (first_addr == EMPTY_ADDR) {
                    first_addr = a;
                }
                leaf_append_cnt++;
                last_addr = a;
            });
            Timer tm;
            const auto btype = NBTreeBlockType::INNER;
            SubtreeRef ref =  {
                1003,           // count
                42,             // id
                400,            // begin
                500,            // end
                114,            // addr
                start,          // min
                341,            // min time
                210.4,          // max
                311,            // max time
                21320.0,        // sum
                4.4,            // first
                4.1,            // last
                btype,          // block type
                1,              // level
                4000,           // payload size
                1,              // version
                0,              // fanout index
                0,              // checksum
            };
            for (int i = 0; i < N; i++) {
                ref.min += inc;
                ref.min *= factor;
                auto status = inner->append(ref);
                if (status == AKU_EOVERFLOW) {
                    LogicAddr addr;
                    std::tie(status, addr) = inner->commit(bstore);
                    if (status != AKU_SUCCESS) {
                        std::cout << "Failed to commit superblock" << std::endl;
                        std::abort();
                    }
                    if (addr != last_addr) {
                        std::cout << "Unexpected superblock address " << addr << " returned, " << last_addr << " expected" << std::endl;
                        std::abort();
                    }
                    inner.reset(new NBTreeSuperblock(42, EMPTY_ADDR, 0, 1));
                }
            }
            t[0] = tm.elapsed();

            // Read back
            std::vector<aku_Timestamp> ts;
            std::vector<SubtreeRef> xs;
            ts.reserve(5000);
            xs.reserve(5000);

            tm.restart();

            for (LogicAddr addr = first_addr; addr < last_addr; addr++) {
                NBTreeSuperblock rdleaf(addr, bstore);
                auto status = rdleaf.read_all(&xs);
                if(status != AKU_SUCCESS) {
                    std::cout << "Failed to read block " << addr << std::endl;
                    std::abort();
                }
            }

            t[1] = tm.elapsed();
        }
        {
            std::unique_ptr<IOVecSuperblock> inner(new IOVecSuperblock(42, EMPTY_ADDR, 0, 1));
            int leaf_append_cnt = 0;
            LogicAddr last_addr = EMPTY_ADDR;
            LogicAddr first_addr = EMPTY_ADDR;
            auto bstore = BlockStoreBuilder::create_memstore([&](LogicAddr a) {
                if (first_addr == EMPTY_ADDR) {
                    first_addr = a;
                }
                leaf_append_cnt++;
                last_addr = a;
            });
            Timer tm;
            const auto btype = NBTreeBlockType::INNER;
            SubtreeRef ref =  {
                1003,           // count
                42,             // id
                400,            // begin
                500,            // end
                114,            // addr
                start,          // min
                341,            // min time
                210.4,          // max
                311,            // max time
                21320.0,        // sum
                4.4,            // first
                4.1,            // last
                btype,          // block type
                1,              // level
                4000,           // payload size
                1,              // version
                0,              // fanout index
                0,              // checksum
            };
            for (int i = 0; i < N; i++) {
                ref.min += inc;
                ref.min *= factor;
                auto status = inner->append(ref);
                if (status == AKU_EOVERFLOW) {
                    LogicAddr addr;
                    std::tie(status, addr) = inner->commit(bstore);
                    if (status != AKU_SUCCESS) {
                        std::cout << "Failed to commit superblock" << std::endl;
                        std::abort();
                    }
                    if (addr != last_addr) {
                        std::cout << "Unexpected superblock address " << addr << " returned, " << last_addr << " expected" << std::endl;
                        std::abort();
                    }
                    inner.reset(new IOVecSuperblock(42, EMPTY_ADDR, 0, 1));
                }
            }
            t[2] = tm.elapsed();

            // Read back
            std::vector<aku_Timestamp> ts;
            std::vector<SubtreeRef> xs;
            ts.reserve(5000);
            xs.reserve(5000);

            tm.restart();

            for (LogicAddr addr = first_addr; addr < last_addr; addr++) {
                IOVecSuperblock rdleaf(addr, bstore);
                auto status = rdleaf.read_all(&xs);
                if(status != AKU_SUCCESS) {
                    std::cout << "Failed to read block " << addr << std::endl;
                    std::abort();
                }
            }

            t[3] = tm.elapsed();
        }
        std::cout << t[0] << ", " << t[1] << "\t" << t[2] << ", " << t[3] << std::endl;
    }
    return 0;
}
<|endoftext|>