<commit_before>//===-- UnixSignals.cpp -----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/UnixSignals.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Host/StringConvert.h"

#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "Plugins/Process/Utility/LinuxSignals.h"
#include "Plugins/Process/Utility/MipsLinuxSignals.h"
#include "Plugins/Process/Utility/NetBSDSignals.h"

using namespace lldb_private;

UnixSignals::Signal::Signal
(
    const char *name,
    bool default_suppress,
    bool default_stop,
    bool default_notify,
    const char *description,
    const char *alias
) :
    m_name (name),
    m_alias (alias),
    m_description (),
    m_suppress (default_suppress),
    m_stop (default_stop),
    m_notify (default_notify)
{
    if (description)
        m_description.assign (description);
}

lldb::UnixSignalsSP
UnixSignals::Create(const ArchSpec &arch)
{
    const auto &triple = arch.GetTriple();
    switch (triple.getOS())
    {
        case llvm::Triple::Linux:
        {
            switch (triple.getArch())
            {
                case llvm::Triple::mips:
                case llvm::Triple::mipsel:
                case llvm::Triple::mips64:
                case llvm::Triple::mips64el:
                    return std::make_shared<MipsLinuxSignals>();
                default:
                    return std::make_shared<LinuxSignals>();
            }
        }
        case llvm::Triple::FreeBSD:
        case llvm::Triple::OpenBSD:
            return std::make_shared<FreeBSDSignals>();
        case llvm::Triple::NetBSD:
            return std::make_shared<NetBSDSignals>();
        default:
            return std::make_shared<UnixSignals>();
    }
}

//----------------------------------------------------------------------
// UnixSignals constructor
//----------------------------------------------------------------------
UnixSignals::UnixSignals ()
{
    Reset ();
}

UnixSignals::UnixSignals(const UnixSignals &rhs)
    : m_signals(rhs.m_signals)
{
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
UnixSignals::~UnixSignals ()
{
}

void
UnixSignals::Reset ()
{
    // This builds one standard set of Unix Signals.  If yours aren't quite in this
    // order, you can either subclass this class, and use Add & Remove to change them
    // or you can subclass and build them afresh in your constructor;
    m_signals.clear();
    //        SIGNO  NAME          SUPPRESS STOP   NOTIFY DESCRIPTION
    //        ====== ============  ======== ====== ====== ===================================================
    AddSignal (1,    "SIGHUP",     false,   true , true , "hangup");
    AddSignal (2,    "SIGINT",     true ,   true , true , "interrupt");
    AddSignal (3,    "SIGQUIT",    false,   true , true , "quit");
    AddSignal (4,    "SIGILL",     false,   true , true , "illegal instruction");
    AddSignal (5,    "SIGTRAP",    true ,   true , true , "trace trap (not reset when caught)");
    AddSignal (6,    "SIGABRT",    false,   true , true , "abort()");
    AddSignal (7,    "SIGEMT",     false,   true , true , "pollable event");
    AddSignal (8,    "SIGFPE",     false,   true , true , "floating point exception");
    AddSignal (9,    "SIGKILL",    false,   true , true , "kill");
    AddSignal (10,   "SIGBUS",     false,   true , true , "bus error");
    AddSignal (11,   "SIGSEGV",    false,   true , true , "segmentation violation");
    AddSignal (12,   "SIGSYS",     false,   true , true , "bad argument to system call");
    AddSignal (13,   "SIGPIPE",    false,   true , true , "write on a pipe with no one to read it");
    AddSignal (14,   "SIGALRM",    false,   false, false, "alarm clock");
    AddSignal (15,   "SIGTERM",    false,   true , true , "software termination signal from kill");
    AddSignal (16,   "SIGURG",     false,   false, false, "urgent condition on IO channel");
    AddSignal (17,   "SIGSTOP",    true ,   true , true , "sendable stop signal not from tty");
    AddSignal (18,   "SIGTSTP",    false,   true , true , "stop signal from tty");
    AddSignal (19,   "SIGCONT",    false,   true , true , "continue a stopped process");
    AddSignal (20,   "SIGCHLD",    false,   false, false, "to parent on child stop or exit");
    AddSignal (21,   "SIGTTIN",    false,   true , true , "to readers process group upon background tty read");
    AddSignal (22,   "SIGTTOU",    false,   true , true , "to readers process group upon background tty write");
    AddSignal (23,   "SIGIO",      false,   false, false, "input/output possible signal");
    AddSignal (24,   "SIGXCPU",    false,   true , true , "exceeded CPU time limit");
    AddSignal (25,   "SIGXFSZ",    false,   true , true , "exceeded file size limit");
    AddSignal (26,   "SIGVTALRM",  false,   false, false, "virtual time alarm");
    AddSignal (27,   "SIGPROF",    false,   false, false, "profiling time alarm");
    AddSignal (28,   "SIGWINCH",   false,   false, false, "window size changes");
    AddSignal (29,   "SIGINFO",    false,   true , true , "information request");
    AddSignal (30,   "SIGUSR1",    false,   true , true , "user defined signal 1");
    AddSignal (31,   "SIGUSR2",    false,   true , true , "user defined signal 2");
}

void
UnixSignals::AddSignal
(
    int signo,
    const char *name,
    bool default_suppress,
    bool default_stop,
    bool default_notify,
    const char *description,
    const char *alias
)
{
    Signal new_signal (name, default_suppress, default_stop, default_notify, description, alias);
    m_signals.insert (std::make_pair(signo, new_signal));
}

void
UnixSignals::RemoveSignal (int signo)
{
    collection::iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
        m_signals.erase (pos);
}

const char *
UnixSignals::GetSignalAsCString (int signo) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos == m_signals.end())
        return NULL;
    else
        return pos->second.m_name.GetCString ();
}

bool
UnixSignals::SignalIsValid (int32_t signo) const
{
    return m_signals.find (signo) != m_signals.end();
}

ConstString
UnixSignals::GetShortName(ConstString name) const
{
    if (name)
    {
      char* signame = (char*)(name.AsCString());
      return ConstString(signame + 3); // Remove "SIG" from name
    }
    return name;
}

int32_t
UnixSignals::GetSignalNumberFromName (const char *name) const
{
    ConstString const_name (name);

    collection::const_iterator pos, end = m_signals.end ();
    for (pos = m_signals.begin (); pos != end; pos++)
    {
        if ((const_name == pos->second.m_name) || (const_name == pos->second.m_alias) ||
            (const_name == GetShortName(pos->second.m_name)) || (const_name == GetShortName(pos->second.m_alias)))
            return pos->first;
    }

    const int32_t signo = StringConvert::ToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0);
    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        return signo;
    return LLDB_INVALID_SIGNAL_NUMBER;
}

int32_t
UnixSignals::GetFirstSignalNumber () const
{
    if (m_signals.empty())
        return LLDB_INVALID_SIGNAL_NUMBER;

    return (*m_signals.begin ()).first;
}

int32_t
UnixSignals::GetNextSignalNumber (int32_t current_signal) const
{
    collection::const_iterator pos = m_signals.find (current_signal);
    collection::const_iterator end = m_signals.end();
    if (pos == end)
        return LLDB_INVALID_SIGNAL_NUMBER;
    else
    {
        pos++;
        if (pos == end)
            return LLDB_INVALID_SIGNAL_NUMBER;
        else
            return pos->first;
    }
}

const char *
UnixSignals::GetSignalInfo
(
    int32_t signo,
    bool &should_suppress,
    bool &should_stop,
    bool &should_notify
) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos == m_signals.end())
        return NULL;
    else
    {
        const Signal &signal = pos->second;
        should_suppress = signal.m_suppress;
        should_stop     = signal.m_stop;
        should_notify   = signal.m_notify;
        return signal.m_name.AsCString("");
    }
}

bool
UnixSignals::GetShouldSuppress (int signo) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
        return pos->second.m_suppress;
    return false;
}

bool
UnixSignals::SetShouldSuppress (int signo, bool value)
{
    collection::iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
    {
        pos->second.m_suppress = value;
        return true;
    }
    return false;
}

bool
UnixSignals::SetShouldSuppress (const char *signal_name, bool value)
{
    const int32_t signo = GetSignalNumberFromName (signal_name);
    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        return SetShouldSuppress (signo, value);
    return false;
}

bool
UnixSignals::GetShouldStop (int signo) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
        return pos->second.m_stop;
    return false;
}

bool
UnixSignals::SetShouldStop (int signo, bool value)
{
    collection::iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
    {
        pos->second.m_stop = value;
        return true;
    }
    return false;
}

bool
UnixSignals::SetShouldStop (const char *signal_name, bool value)
{
    const int32_t signo = GetSignalNumberFromName (signal_name);
    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        return SetShouldStop (signo, value);
    return false;
}

bool
UnixSignals::GetShouldNotify (int signo) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
        return pos->second.m_notify;
    return false;
}

bool
UnixSignals::SetShouldNotify (int signo, bool value)
{
    collection::iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
    {
        pos->second.m_notify = value;
        return true;
    }
    return false;
}

bool
UnixSignals::SetShouldNotify (const char *signal_name, bool value)
{
    const int32_t signo = GetSignalNumberFromName (signal_name);
    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        return SetShouldNotify (signo, value);
    return false;
}

int32_t
UnixSignals::GetNumSignals() const
{
    return m_signals.size();
}

int32_t
UnixSignals::GetSignalAtIndex(int32_t index) const
{
    if (index < 0 || m_signals.size() <= static_cast<size_t>(index))
        return LLDB_INVALID_SIGNAL_NUMBER;
    auto it = m_signals.begin();
    std::advance(it, index);
    return it->first;
}
<commit_msg>Target: fix -Wcast-qual warning<commit_after>//===-- UnixSignals.cpp -----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/UnixSignals.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Host/StringConvert.h"

#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "Plugins/Process/Utility/LinuxSignals.h"
#include "Plugins/Process/Utility/MipsLinuxSignals.h"
#include "Plugins/Process/Utility/NetBSDSignals.h"

using namespace lldb_private;

UnixSignals::Signal::Signal
(
    const char *name,
    bool default_suppress,
    bool default_stop,
    bool default_notify,
    const char *description,
    const char *alias
) :
    m_name (name),
    m_alias (alias),
    m_description (),
    m_suppress (default_suppress),
    m_stop (default_stop),
    m_notify (default_notify)
{
    if (description)
        m_description.assign (description);
}

lldb::UnixSignalsSP
UnixSignals::Create(const ArchSpec &arch)
{
    const auto &triple = arch.GetTriple();
    switch (triple.getOS())
    {
        case llvm::Triple::Linux:
        {
            switch (triple.getArch())
            {
                case llvm::Triple::mips:
                case llvm::Triple::mipsel:
                case llvm::Triple::mips64:
                case llvm::Triple::mips64el:
                    return std::make_shared<MipsLinuxSignals>();
                default:
                    return std::make_shared<LinuxSignals>();
            }
        }
        case llvm::Triple::FreeBSD:
        case llvm::Triple::OpenBSD:
            return std::make_shared<FreeBSDSignals>();
        case llvm::Triple::NetBSD:
            return std::make_shared<NetBSDSignals>();
        default:
            return std::make_shared<UnixSignals>();
    }
}

//----------------------------------------------------------------------
// UnixSignals constructor
//----------------------------------------------------------------------
UnixSignals::UnixSignals ()
{
    Reset ();
}

UnixSignals::UnixSignals(const UnixSignals &rhs)
    : m_signals(rhs.m_signals)
{
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
UnixSignals::~UnixSignals ()
{
}

void
UnixSignals::Reset ()
{
    // This builds one standard set of Unix Signals.  If yours aren't quite in this
    // order, you can either subclass this class, and use Add & Remove to change them
    // or you can subclass and build them afresh in your constructor;
    m_signals.clear();
    //        SIGNO  NAME          SUPPRESS STOP   NOTIFY DESCRIPTION
    //        ====== ============  ======== ====== ====== ===================================================
    AddSignal (1,    "SIGHUP",     false,   true , true , "hangup");
    AddSignal (2,    "SIGINT",     true ,   true , true , "interrupt");
    AddSignal (3,    "SIGQUIT",    false,   true , true , "quit");
    AddSignal (4,    "SIGILL",     false,   true , true , "illegal instruction");
    AddSignal (5,    "SIGTRAP",    true ,   true , true , "trace trap (not reset when caught)");
    AddSignal (6,    "SIGABRT",    false,   true , true , "abort()");
    AddSignal (7,    "SIGEMT",     false,   true , true , "pollable event");
    AddSignal (8,    "SIGFPE",     false,   true , true , "floating point exception");
    AddSignal (9,    "SIGKILL",    false,   true , true , "kill");
    AddSignal (10,   "SIGBUS",     false,   true , true , "bus error");
    AddSignal (11,   "SIGSEGV",    false,   true , true , "segmentation violation");
    AddSignal (12,   "SIGSYS",     false,   true , true , "bad argument to system call");
    AddSignal (13,   "SIGPIPE",    false,   true , true , "write on a pipe with no one to read it");
    AddSignal (14,   "SIGALRM",    false,   false, false, "alarm clock");
    AddSignal (15,   "SIGTERM",    false,   true , true , "software termination signal from kill");
    AddSignal (16,   "SIGURG",     false,   false, false, "urgent condition on IO channel");
    AddSignal (17,   "SIGSTOP",    true ,   true , true , "sendable stop signal not from tty");
    AddSignal (18,   "SIGTSTP",    false,   true , true , "stop signal from tty");
    AddSignal (19,   "SIGCONT",    false,   true , true , "continue a stopped process");
    AddSignal (20,   "SIGCHLD",    false,   false, false, "to parent on child stop or exit");
    AddSignal (21,   "SIGTTIN",    false,   true , true , "to readers process group upon background tty read");
    AddSignal (22,   "SIGTTOU",    false,   true , true , "to readers process group upon background tty write");
    AddSignal (23,   "SIGIO",      false,   false, false, "input/output possible signal");
    AddSignal (24,   "SIGXCPU",    false,   true , true , "exceeded CPU time limit");
    AddSignal (25,   "SIGXFSZ",    false,   true , true , "exceeded file size limit");
    AddSignal (26,   "SIGVTALRM",  false,   false, false, "virtual time alarm");
    AddSignal (27,   "SIGPROF",    false,   false, false, "profiling time alarm");
    AddSignal (28,   "SIGWINCH",   false,   false, false, "window size changes");
    AddSignal (29,   "SIGINFO",    false,   true , true , "information request");
    AddSignal (30,   "SIGUSR1",    false,   true , true , "user defined signal 1");
    AddSignal (31,   "SIGUSR2",    false,   true , true , "user defined signal 2");
}

void
UnixSignals::AddSignal
(
    int signo,
    const char *name,
    bool default_suppress,
    bool default_stop,
    bool default_notify,
    const char *description,
    const char *alias
)
{
    Signal new_signal (name, default_suppress, default_stop, default_notify, description, alias);
    m_signals.insert (std::make_pair(signo, new_signal));
}

void
UnixSignals::RemoveSignal (int signo)
{
    collection::iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
        m_signals.erase (pos);
}

const char *
UnixSignals::GetSignalAsCString (int signo) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos == m_signals.end())
        return NULL;
    else
        return pos->second.m_name.GetCString ();
}

bool
UnixSignals::SignalIsValid (int32_t signo) const
{
    return m_signals.find (signo) != m_signals.end();
}

ConstString
UnixSignals::GetShortName(ConstString name) const
{
    if (name)
    {
      const char* signame = name.AsCString();
      return ConstString(signame + 3); // Remove "SIG" from name
    }
    return name;
}

int32_t
UnixSignals::GetSignalNumberFromName (const char *name) const
{
    ConstString const_name (name);

    collection::const_iterator pos, end = m_signals.end ();
    for (pos = m_signals.begin (); pos != end; pos++)
    {
        if ((const_name == pos->second.m_name) || (const_name == pos->second.m_alias) ||
            (const_name == GetShortName(pos->second.m_name)) || (const_name == GetShortName(pos->second.m_alias)))
            return pos->first;
    }

    const int32_t signo = StringConvert::ToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0);
    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        return signo;
    return LLDB_INVALID_SIGNAL_NUMBER;
}

int32_t
UnixSignals::GetFirstSignalNumber () const
{
    if (m_signals.empty())
        return LLDB_INVALID_SIGNAL_NUMBER;

    return (*m_signals.begin ()).first;
}

int32_t
UnixSignals::GetNextSignalNumber (int32_t current_signal) const
{
    collection::const_iterator pos = m_signals.find (current_signal);
    collection::const_iterator end = m_signals.end();
    if (pos == end)
        return LLDB_INVALID_SIGNAL_NUMBER;
    else
    {
        pos++;
        if (pos == end)
            return LLDB_INVALID_SIGNAL_NUMBER;
        else
            return pos->first;
    }
}

const char *
UnixSignals::GetSignalInfo
(
    int32_t signo,
    bool &should_suppress,
    bool &should_stop,
    bool &should_notify
) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos == m_signals.end())
        return NULL;
    else
    {
        const Signal &signal = pos->second;
        should_suppress = signal.m_suppress;
        should_stop     = signal.m_stop;
        should_notify   = signal.m_notify;
        return signal.m_name.AsCString("");
    }
}

bool
UnixSignals::GetShouldSuppress (int signo) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
        return pos->second.m_suppress;
    return false;
}

bool
UnixSignals::SetShouldSuppress (int signo, bool value)
{
    collection::iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
    {
        pos->second.m_suppress = value;
        return true;
    }
    return false;
}

bool
UnixSignals::SetShouldSuppress (const char *signal_name, bool value)
{
    const int32_t signo = GetSignalNumberFromName (signal_name);
    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        return SetShouldSuppress (signo, value);
    return false;
}

bool
UnixSignals::GetShouldStop (int signo) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
        return pos->second.m_stop;
    return false;
}

bool
UnixSignals::SetShouldStop (int signo, bool value)
{
    collection::iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
    {
        pos->second.m_stop = value;
        return true;
    }
    return false;
}

bool
UnixSignals::SetShouldStop (const char *signal_name, bool value)
{
    const int32_t signo = GetSignalNumberFromName (signal_name);
    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        return SetShouldStop (signo, value);
    return false;
}

bool
UnixSignals::GetShouldNotify (int signo) const
{
    collection::const_iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
        return pos->second.m_notify;
    return false;
}

bool
UnixSignals::SetShouldNotify (int signo, bool value)
{
    collection::iterator pos = m_signals.find (signo);
    if (pos != m_signals.end())
    {
        pos->second.m_notify = value;
        return true;
    }
    return false;
}

bool
UnixSignals::SetShouldNotify (const char *signal_name, bool value)
{
    const int32_t signo = GetSignalNumberFromName (signal_name);
    if (signo != LLDB_INVALID_SIGNAL_NUMBER)
        return SetShouldNotify (signo, value);
    return false;
}

int32_t
UnixSignals::GetNumSignals() const
{
    return m_signals.size();
}

int32_t
UnixSignals::GetSignalAtIndex(int32_t index) const
{
    if (index < 0 || m_signals.size() <= static_cast<size_t>(index))
        return LLDB_INVALID_SIGNAL_NUMBER;
    auto it = m_signals.begin();
    std::advance(it, index);
    return it->first;
}
<|endoftext|>


<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2006 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: noding/ScaledNoder.java rev. 1.3 (JTS-1.7.1)
 *
 **********************************************************************/

#include <functional>
#include <vector>
#include <cassert>

#include "geos/geom/Coordinate.h"
#include "geos/geom/CoordinateSequence.h" // for apply
#include "geos/noding/ScaledNoder.h"
#include "geos/noding/SegmentString.h"
#include "geos/util/math.h"

using namespace geos::geom;

namespace geos {
namespace noding { // geos.noding

class ScaledNoder::Scaler: public geom::CoordinateFilter {
public:
	const ScaledNoder& sn;
	Scaler(const ScaledNoder&n): sn(n) {}
	void filter_ro(const geom::Coordinate* c) { assert(0); }

	void filter_rw(geom::Coordinate* c) const {
		c->x = util::java_math_round( ( c->x - sn.offsetX ) * sn.scaleFactor );
		c->y = util::java_math_round( ( c->y - sn.offsetY ) * sn.scaleFactor );
	}
};

class ScaledNoder::ReScaler: public geom::CoordinateFilter {
public:
	const ScaledNoder& sn;
	ReScaler(const ScaledNoder&n): sn(n) {}
	void filter_ro(const geom::Coordinate* c) { assert(0); }
	void filter_rw(geom::Coordinate* c) const {
		c->x = c->x / sn.scaleFactor + sn.offsetX;
		c->y = c->y / sn.scaleFactor + sn.offsetY;
	}
};

/*private*/
void
ScaledNoder::rescale(SegmentString::NonConstVect& segStrings) const
{
	ReScaler rescaler(*this);
	for (SegmentString::NonConstVect::const_iterator
		i0=segStrings.begin(), i0End=segStrings.end();
			i0!=i0End; ++i0)
	{
		//(*i0)->getCoordinates()->applyCoordinateFilter(*this);
		(*i0)->getCoordinates()->apply_rw(&rescaler);
	}
}

/*private*/
void
ScaledNoder::scale(SegmentString::NonConstVect& segStrings) const
{
	Scaler scaler(*this);
	for (SegmentString::NonConstVect::const_iterator
		i0=segStrings.begin(), i0End=segStrings.end();
			i0!=i0End; ++i0)
	{
		//(*i0)->getCoordinates()->applyCoordinateFilter(*this);
		CoordinateSequence* cs=(*i0)->getCoordinates();
		cs->apply_rw(&scaler);
		cs->removeRepeatedPoints();
	}
}

/*public*/
SegmentString::NonConstVect*
ScaledNoder::getNodedSubstrings() const
{
	SegmentString::NonConstVect* splitSS = noder.getNodedSubstrings();
	if ( isScaled ) rescale(*splitSS);
	return splitSS;

}

/*public*/
void
ScaledNoder::computeNodes(SegmentString::NonConstVect* inputSegStr)
{
	if (isScaled) scale(*inputSegStr);
	noder.computeNodes(inputSegStr);
}

} // namespace geos.noding
} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.9  2006/05/03 15:12:35  strk
 * Oops, uninitialized value fix
 *
 * Revision 1.8  2006/05/03 15:00:43  strk
 * Fixed scale() function to remove repeated points *after* rounding. Added brief doxygen class description.
 *
 * Revision 1.7  2006/05/03 09:14:22  strk
 * * source/operation/buffer/OffsetCurveSetBuilder.cpp: used auto_ptr to protect leaks of CoordinateSequence
 * * source/noding/ScaledNoder.cpp, source/headers/geos/noding/ScaledNoder.h: ported JTS bugfix in scale method.
 *
 * Revision 1.6  2006/05/02 16:22:18  strk
 * * source/noding/ScaledNoder.cpp: use java_math_round instead of sym_round.
 *
 * Revision 1.5  2006/03/15 09:51:12  strk
 * streamlined headers usage
 *
 * Revision 1.4  2006/03/13 21:19:51  strk
 * Fixed bug in ScaledNoder scaling mechanism (hugly code, due to CoordinateSequence visitor pattern design). Tests are still failing so this possibly needs some other fix. Streamlined includes by implementation file.
 *
 * Revision 1.3  2006/02/23 11:54:20  strk
 * - MCIndexPointSnapper
 * - MCIndexSnapRounder
 * - SnapRounding BufferOp
 * - ScaledNoder
 * - GEOSException hierarchy cleanups
 * - SpatialIndex memory-friendly query interface
 * - GeometryGraph::getBoundaryNodes memory-friendly
 * - NodeMap::getBoundaryNodes memory-friendly
 * - Cleanups in geomgraph::Edge
 * - Added an XML test for snaprounding buffer (shows leaks, working on it)
 *
 * Revision 1.2  2006/02/19 19:46:49  strk
 * Packages <-> namespaces mapping for most GEOS internal code (uncomplete, but working). Dir-level libs for index/ subdirs.
 *
 * Revision 1.1  2006/02/18 21:08:09  strk
 * - new CoordinateSequence::applyCoordinateFilter method (slow but useful)
 * - SegmentString::getCoordinates() doesn't return a clone anymore.
 * - SegmentString::getCoordinatesRO() obsoleted.
 * - SegmentString constructor does not promises constness of passed
 *   CoordinateSequence anymore.
 * - NEW ScaledNoder class
 * - Stubs for MCIndexPointSnapper and  MCIndexSnapRounder
 * - Simplified internal interaces of OffsetCurveBuilder and OffsetCurveSetBuilder
 *
 **********************************************************************/
<commit_msg>test SegmentString invariant before and after scaling<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2006 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: noding/ScaledNoder.java rev. 1.3 (JTS-1.7.1)
 *
 **********************************************************************/

#include "geos/geom/Coordinate.h"
#include "geos/geom/CoordinateSequence.h" // for apply
#include "geos/noding/ScaledNoder.h"
#include "geos/noding/SegmentString.h"
#include "geos/util/math.h"

#include <functional>
#include <vector>
#include <cassert>

#ifndef GEOS_DEBUG
#define GEOS_DEBUG 0
#endif

#ifdef GEOS_DEBUG
#include <iostream>
#endif

using namespace geos::geom;

namespace geos {
namespace noding { // geos.noding

class ScaledNoder::Scaler: public geom::CoordinateFilter {
public:
	const ScaledNoder& sn;
	Scaler(const ScaledNoder&n): sn(n)
	{
#ifdef GEOS_DEBUG
		std::cerr << "Scaler: offsetX,Y: " << sn.offsetX << ","
			<< sn.offsetY << " scaleFactor: " << sn.scaleFactor
			<< std::endl;
#endif
	}

	void filter_ro(const geom::Coordinate* c) { assert(0); }

	void filter_rw(geom::Coordinate* c) const {
		c->x = util::java_math_round( ( c->x - sn.offsetX ) * sn.scaleFactor );
		c->y = util::java_math_round( ( c->y - sn.offsetY ) * sn.scaleFactor );
	}
};

class ScaledNoder::ReScaler: public geom::CoordinateFilter {
public:
	const ScaledNoder& sn;
	ReScaler(const ScaledNoder&n): sn(n)
	{
#ifdef GEOS_DEBUG
		std::cerr << "ReScaler: offsetX,Y: " << sn.offsetX << ","
			<< sn.offsetY << " scaleFactor: " << sn.scaleFactor
			<< std::endl;
#endif
	}

	void filter_ro(const geom::Coordinate* c) { assert(0); }
	void filter_rw(geom::Coordinate* c) const {
		c->x = c->x / sn.scaleFactor + sn.offsetX;
		c->y = c->y / sn.scaleFactor + sn.offsetY;
	}
};

/*private*/
void
ScaledNoder::rescale(SegmentString::NonConstVect& segStrings) const
{
	ReScaler rescaler(*this);
	for (SegmentString::NonConstVect::const_iterator
		i0=segStrings.begin(), i0End=segStrings.end();
			i0!=i0End; ++i0)
	{

		SegmentString* ss=*i0;

		ss->getCoordinates()->apply_rw(&rescaler);

	}
}

/*private*/
void
ScaledNoder::scale(SegmentString::NonConstVect& segStrings) const
{
	Scaler scaler(*this);
	for (SegmentString::NonConstVect::const_iterator
		i0=segStrings.begin(), i0End=segStrings.end();
			i0!=i0End; ++i0)
	{
		SegmentString* ss=*i0;

		ss->testInvariant();

		CoordinateSequence* cs=ss->getCoordinates();
		cs->apply_rw(&scaler);
		cs->removeRepeatedPoints();

		ss->testInvariant();
	}
}

/*public*/
SegmentString::NonConstVect*
ScaledNoder::getNodedSubstrings() const
{
	SegmentString::NonConstVect* splitSS = noder.getNodedSubstrings();
	if ( isScaled ) rescale(*splitSS);
	return splitSS;

}

/*public*/
void
ScaledNoder::computeNodes(SegmentString::NonConstVect* inputSegStr)
{
	if (isScaled) scale(*inputSegStr);
	noder.computeNodes(inputSegStr);
}

} // namespace geos.noding
} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.10  2006/05/03 15:40:14  strk
 * test SegmentString invariant before and after scaling
 *
 * Revision 1.9  2006/05/03 15:12:35  strk
 * Oops, uninitialized value fix
 *
 * Revision 1.8  2006/05/03 15:00:43  strk
 * Fixed scale() function to remove repeated points *after* rounding. Added brief doxygen class description.
 *
 * Revision 1.7  2006/05/03 09:14:22  strk
 * * source/operation/buffer/OffsetCurveSetBuilder.cpp: used auto_ptr to protect leaks of CoordinateSequence
 * * source/noding/ScaledNoder.cpp, source/headers/geos/noding/ScaledNoder.h: ported JTS bugfix in scale method.
 *
 * Revision 1.6  2006/05/02 16:22:18  strk
 * * source/noding/ScaledNoder.cpp: use java_math_round instead of sym_round.
 *
 * Revision 1.5  2006/03/15 09:51:12  strk
 * streamlined headers usage
 *
 * Revision 1.4  2006/03/13 21:19:51  strk
 * Fixed bug in ScaledNoder scaling mechanism (hugly code, due to CoordinateSequence visitor pattern design). Tests are still failing so this possibly needs some other fix. Streamlined includes by implementation file.
 *
 * Revision 1.3  2006/02/23 11:54:20  strk
 * - MCIndexPointSnapper
 * - MCIndexSnapRounder
 * - SnapRounding BufferOp
 * - ScaledNoder
 * - GEOSException hierarchy cleanups
 * - SpatialIndex memory-friendly query interface
 * - GeometryGraph::getBoundaryNodes memory-friendly
 * - NodeMap::getBoundaryNodes memory-friendly
 * - Cleanups in geomgraph::Edge
 * - Added an XML test for snaprounding buffer (shows leaks, working on it)
 *
 * Revision 1.2  2006/02/19 19:46:49  strk
 * Packages <-> namespaces mapping for most GEOS internal code (uncomplete, but working). Dir-level libs for index/ subdirs.
 *
 * Revision 1.1  2006/02/18 21:08:09  strk
 * - new CoordinateSequence::applyCoordinateFilter method (slow but useful)
 * - SegmentString::getCoordinates() doesn't return a clone anymore.
 * - SegmentString::getCoordinatesRO() obsoleted.
 * - SegmentString constructor does not promises constness of passed
 *   CoordinateSequence anymore.
 * - NEW ScaledNoder class
 * - Stubs for MCIndexPointSnapper and  MCIndexSnapRounder
 * - Simplified internal interaces of OffsetCurveBuilder and OffsetCurveSetBuilder
 *
 **********************************************************************/
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// DeclaredType.cpp
// Glue logic between symbols and their declared types
//
// File is under the MIT license; see LICENSE for details
//------------------------------------------------------------------------------
#include "slang/types/DeclaredType.h"

#include "slang/binding/Expression.h"
#include "slang/compilation/Compilation.h"
#include "slang/diagnostics/DeclarationsDiags.h"
#include "slang/symbols/ClassSymbols.h"
#include "slang/symbols/Scope.h"
#include "slang/symbols/SubroutineSymbols.h"
#include "slang/symbols/Symbol.h"
#include "slang/symbols/VariableSymbols.h"
#include "slang/syntax/AllSyntax.h"
#include "slang/types/AllTypes.h"
#include "slang/types/NetType.h"
#include "slang/util/ScopeGuard.h"

namespace slang {

DeclaredType::DeclaredType(const Symbol& parent, bitmask<DeclaredTypeFlags> flags) :
    parent(parent), flags(flags) {
    // If this assert fires you need to update Symbol::getDeclaredType
    ASSERT(parent.getDeclaredType() == this);
}

const Type& DeclaredType::getType() const {
    if (!type)
        resolveType(getBindContext());
    return *type;
}

void DeclaredType::setDimensionSyntax(const SyntaxList<VariableDimensionSyntax>& newDimensions) {
    dimensions = &newDimensions;
    type = nullptr;
}

void DeclaredType::copyTypeFrom(const DeclaredType& source) {
    if (auto ts = source.getTypeSyntax()) {
        setTypeSyntax(*ts);
        if (auto dims = source.getDimensionSyntax())
            setDimensionSyntax(*dims);
    }

    type = source.type;
}

void DeclaredType::mergeImplicitPort(
    const ImplicitTypeSyntax& implicit, SourceLocation location,
    span<const VariableDimensionSyntax* const> unpackedDimensions) {
    mergePortTypes(getBindContext(), parent.as<ValueSymbol>(), implicit, location,
                   unpackedDimensions);
}

const Scope& DeclaredType::getScope() const {
    const Scope* scope = parent.getParentScope();
    ASSERT(scope);
    return *scope;
}

void DeclaredType::resolveType(const BindContext& initializerContext) const {
    auto& scope = getScope();
    auto& comp = scope.getCompilation();
    if (!typeSyntax) {
        type = &comp.getErrorType();
        return;
    }

    ASSERT(!evaluating);
    evaluating = true;
    auto guard = ScopeGuard([this] { evaluating = false; });

    // If we are configured to infer implicit types, bind the initializer expression
    // first so that we can derive our type from whatever that happens to be.
    if (typeSyntax->kind == SyntaxKind::ImplicitType &&
        (flags & DeclaredTypeFlags::InferImplicit) != 0) {
        if (dimensions) {
            scope.addDiag(diag::UnpackedArrayParamType, dimensions->sourceRange());
            type = &comp.getErrorType();
        }
        else if (!initializerSyntax) {
            type = &comp.getErrorType();
        }
        else {
            initializer = &Expression::bindImplicitParam(*typeSyntax, *initializerSyntax,
                                                         initializerLocation, initializerContext);
            type = initializer->type;
        }
    }
    else {
        const Type* typedefTarget = nullptr;
        if (flags.has(DeclaredTypeFlags::TypedefTarget))
            typedefTarget = &parent.as<Type>();

        BindContext typeContext = getBindContext();
        type = &comp.getType(*typeSyntax, typeContext.lookupLocation, scope, typedefTarget);
        if (dimensions)
            type = &comp.getType(*type, *dimensions, typeContext.lookupLocation, scope);
    }

    if (flags.has(DeclaredTypeFlags::NeedsTypeCheck) && !type->isError())
        checkType(initializerContext);
}

static bool isValidForNet(const Type& type) {
    auto& ct = type.getCanonicalType();
    if (ct.isIntegral())
        return ct.isFourState();

    if (ct.kind == SymbolKind::FixedSizeUnpackedArrayType)
        return isValidForNet(ct.as<FixedSizeUnpackedArrayType>().elementType);

    if (ct.isUnpackedStruct()) {
        for (auto& field : ct.as<UnpackedStructType>().membersOfType<FieldSymbol>()) {
            if (!isValidForNet(field.getType()))
                return false;
        }
        return true;
    }

    return false;
}

static bool isValidForUserDefinedNet(const Type& type) {
    auto& ct = type.getCanonicalType();
    if (ct.isIntegral() || ct.isFloating())
        return true;

    if (ct.kind == SymbolKind::FixedSizeUnpackedArrayType)
        return isValidForUserDefinedNet(ct.as<FixedSizeUnpackedArrayType>().elementType);

    if (ct.isUnpackedStruct()) {
        for (auto& field : ct.as<UnpackedStructType>().membersOfType<FieldSymbol>()) {
            if (!isValidForUserDefinedNet(field.getType()))
                return false;
        }
        return true;
    }

    if (ct.isUnpackedUnion()) {
        for (auto& field : ct.as<UnpackedUnionType>().membersOfType<FieldSymbol>()) {
            if (!isValidForUserDefinedNet(field.getType()))
                return false;
        }
        return true;
    }

    return false;
}

void DeclaredType::checkType(const BindContext& context) const {
    int masked = (flags & DeclaredTypeFlags::NeedsTypeCheck).bits();
    ASSERT(countPopulation64(masked) == 1);

    switch (masked) {
        case int(DeclaredTypeFlags::Port):
            // Ports cannot be chandles.
            if (type->isCHandle())
                context.addDiag(diag::InvalidPortType, parent.location) << *type;
            break;
        case int(DeclaredTypeFlags::NetType): {
            auto& net = parent.as<NetSymbol>();
            if (net.netType.netKind != NetType::UserDefined && !isValidForNet(*type))
                context.addDiag(diag::InvalidNetType, parent.location) << *type;
            else if (type->getBitWidth() == 1 && net.expansionHint != NetSymbol::None)
                context.addDiag(diag::SingleBitVectored, parent.location);
            break;
        }
        case int(DeclaredTypeFlags::UserDefinedNetType):
            if (!isValidForUserDefinedNet(*type))
                context.addDiag(diag::InvalidUserDefinedNetType, parent.location) << *type;
            break;
        case int(DeclaredTypeFlags::FormalArgMergeVar):
            if (auto var = parent.as<FormalArgumentSymbol>().getMergedVariable()) {
                ASSERT(typeSyntax);
                mergePortTypes(context, *var, typeSyntax->as<ImplicitTypeSyntax>(), parent.location,
                               dimensions ? *dimensions
                                          : span<const VariableDimensionSyntax* const>{});
            }
            break;
        case int(DeclaredTypeFlags::Rand): {
            RandMode mode = parent.getRandMode();
            if (!type->isValidForRand(mode)) {
                auto& diag = context.addDiag(diag::InvalidRandType, parent.location) << *type;
                if (mode == RandMode::Rand)
                    diag << "rand"sv;
                else
                    diag << "randc"sv;
            }
            break;
        }
        case int(DeclaredTypeFlags::DPIReturnType): {
            if (!type->isValidForDPIReturn())
                context.addDiag(diag::InvalidDPIReturnType, parent.location) << *type;
            else if (parent.as<SubroutineSymbol>().flags.has(MethodFlags::Pure) && type->isVoid())
                context.addDiag(diag::DPIPureReturn, parent.location);
            break;
        }
        case int(DeclaredTypeFlags::DPIArg):
            if (!type->isValidForDPIArg())
                context.addDiag(diag::InvalidDPIArgType, parent.location) << *type;
            break;
        default:
            THROW_UNREACHABLE;
    }
}

static const Type* makeSigned(Compilation& compilation, const Type& type) {
    // This deliberately does not look at the canonical type; type aliases
    // are not convertible to a different signedness.
    SmallVectorSized<ConstantRange, 4> dims;
    const Type* curr = &type;
    while (curr->kind == SymbolKind::PackedArrayType) {
        dims.append(curr->getFixedRange());
        curr = curr->getArrayElementType();
    }

    if (curr->kind != SymbolKind::ScalarType)
        return &type;

    auto flags = curr->getIntegralFlags() | IntegralFlags::Signed;
    if (dims.size() == 1)
        return &compilation.getType(type.getBitWidth(), flags);

    curr = &compilation.getScalarType(flags);
    size_t count = dims.size();
    for (size_t i = 0; i < count; i++)
        curr = compilation.emplace<PackedArrayType>(*curr, dims[count - i - 1]);

    return curr;
}

void DeclaredType::mergePortTypes(
    const BindContext& context, const ValueSymbol& sourceSymbol, const ImplicitTypeSyntax& implicit,
    SourceLocation location, span<const VariableDimensionSyntax* const> unpackedDimensions) const {

    // There's this really terrible "feature" where the port declaration can influence the type
    // of the actual symbol somewhere else in the tree. This is ugly but should be safe since
    // nobody else can look at that symbol's type until we've gone through elaboration.
    //
    // In this context, the sourceSymbol is the actual variable declaration with, presumably,
    // a full type declared. The implicit syntax is from the port I/O declaration, which needs
    // to be merged. For example:
    //
    //   input signed [1:0] foo;    // implicit + unpackedDimensions + location
    //   logic foo;                 // sourceSymbol
    const Type* destType = &sourceSymbol.getType();

    if (implicit.signing) {
        // Drill past any unpacked arrays to figure out if this thing is even integral.
        SmallVectorSized<ConstantRange, 4> destDims;
        const Type* sourceType = destType;
        while (sourceType->getCanonicalType().kind == SymbolKind::FixedSizeUnpackedArrayType) {
            destDims.append(sourceType->getFixedRange());
            sourceType = sourceType->getArrayElementType();
        }

        if (sourceType->isError())
            return;

        if (!sourceType->isIntegral()) {
            auto& diag = context.addDiag(diag::CantDeclarePortSigned, location);
            diag << sourceSymbol.name << implicit.signing.valueText() << *destType;
            diag.addNote(diag::NoteDeclarationHere, sourceSymbol.location);
            return;
        }

        auto warnSignedness = [&] {
            auto& diag = context.addDiag(diag::SignednessNoEffect, implicit.signing.range());
            diag << implicit.signing.valueText() << *destType;
            diag.addNote(diag::NoteDeclarationHere, sourceSymbol.location);
        };

        bool shouldBeSigned = implicit.signing.kind == TokenKind::SignedKeyword;
        if (shouldBeSigned && !sourceType->isSigned()) {
            sourceType = makeSigned(context.getCompilation(), *sourceType);
            if (!sourceType->isSigned()) {
                warnSignedness();
            }
            else {
                // Put the unpacked dimensions back on the type now that it
                // has been made signed.
                destType = &FixedSizeUnpackedArrayType::fromDims(context.getCompilation(),
                                                                 *sourceType, destDims);
            }
        }
        else if (!shouldBeSigned && sourceType->isSigned()) {
            warnSignedness();
        }
    }

    // Our declared type takes on the merged type from the variable definition.
    this->type = destType;

    auto errorDims = [&](auto& dims) {
        auto& diag = context.addDiag(diag::PortDeclDimensionsMismatch, dims.sourceRange());
        diag << sourceSymbol.name;
        diag.addNote(diag::NoteDeclarationHere, sourceSymbol.location);
    };

    auto checkDims = [&](auto& dims, SymbolKind arrayKind, bool isPacked) {
        if (!dims.empty()) {
            auto it = dims.begin();
            while (destType->getCanonicalType().kind == arrayKind) {
                if (it == dims.end()) {
                    errorDims(*dims.back());
                    return;
                }

                auto dim = isPacked ? context.evalPackedDimension(**it)
                                    : context.evalUnpackedDimension(**it);
                if (!dim || destType->getFixedRange() != *dim) {
                    errorDims(**it);
                    return;
                }

                destType = destType->getArrayElementType();
                it++;
            }

            if (it != dims.end()) {
                errorDims(**it);
                return;
            }
        }
    };

    // Unpacked dim checks have to come first because it unwraps the destType
    // for the packed one to look at.
    checkDims(unpackedDimensions, SymbolKind::FixedSizeUnpackedArrayType, false);
    checkDims(implicit.dimensions, SymbolKind::PackedArrayType, true);
}

void DeclaredType::resolveAt(const BindContext& context) const {
    if (!initializerSyntax)
        return;

    if (!type) {
        resolveType(context);
        if (initializer)
            return;
    }

    // Enums are special in that their initializers target the base type of the enum
    // instead of the actual enum type (which doesn't allow implicit conversions from
    // normal integral values).
    auto& scope = context.scope;
    bitmask<BindFlags> bindFlags = context.flags;
    const Type* targetType = type;
    if (targetType->isEnum() && scope.asSymbol().kind == SymbolKind::EnumType) {
        targetType = &targetType->as<EnumType>().baseType;
        bindFlags |= BindFlags::EnumInitializer;
    }

    initializer = &Expression::bindRValue(*targetType, *initializerSyntax, initializerLocation,
                                          context.resetFlags(bindFlags));
}

const Expression* DeclaredType::getInitializer() const {
    if (initializer)
        return initializer;

    resolveAt(getBindContext());
    return initializer;
}

void DeclaredType::setFromDeclarator(const DeclaratorSyntax& decl) {
    if (!decl.dimensions.empty())
        setDimensionSyntax(decl.dimensions);
    if (decl.initializer)
        setInitializerSyntax(*decl.initializer->expr, decl.initializer->equals.location());
}

template<typename T>
T DeclaredType::getBindContext() const {
    bitmask<BindFlags> bindFlags;
    if (flags & DeclaredTypeFlags::RequireConstant)
        bindFlags = BindFlags::Constant;
    if (flags & DeclaredTypeFlags::InProceduralContext)
        bindFlags |= BindFlags::ProceduralStatement;
    if ((flags & DeclaredTypeFlags::AutomaticInitializer) == 0)
        bindFlags |= BindFlags::StaticInitializer;

    LookupLocation location;
    if (flags & DeclaredTypeFlags::LookupMax)
        location = LookupLocation::max;
    else
        location = LookupLocation::after(parent);

    return BindContext(getScope(), location, bindFlags);
}

} // namespace slang
<commit_msg>Fix clang warning<commit_after>//------------------------------------------------------------------------------
// DeclaredType.cpp
// Glue logic between symbols and their declared types
//
// File is under the MIT license; see LICENSE for details
//------------------------------------------------------------------------------
#include "slang/types/DeclaredType.h"

#include "slang/binding/Expression.h"
#include "slang/compilation/Compilation.h"
#include "slang/diagnostics/DeclarationsDiags.h"
#include "slang/symbols/ClassSymbols.h"
#include "slang/symbols/Scope.h"
#include "slang/symbols/SubroutineSymbols.h"
#include "slang/symbols/Symbol.h"
#include "slang/symbols/VariableSymbols.h"
#include "slang/syntax/AllSyntax.h"
#include "slang/types/AllTypes.h"
#include "slang/types/NetType.h"
#include "slang/util/ScopeGuard.h"

namespace slang {

DeclaredType::DeclaredType(const Symbol& parent, bitmask<DeclaredTypeFlags> flags) :
    parent(parent), flags(flags) {
    // If this assert fires you need to update Symbol::getDeclaredType
    ASSERT(parent.getDeclaredType() == this);
}

const Type& DeclaredType::getType() const {
    if (!type)
        resolveType(getBindContext());
    return *type;
}

void DeclaredType::setDimensionSyntax(const SyntaxList<VariableDimensionSyntax>& newDimensions) {
    dimensions = &newDimensions;
    type = nullptr;
}

void DeclaredType::copyTypeFrom(const DeclaredType& source) {
    if (auto ts = source.getTypeSyntax()) {
        setTypeSyntax(*ts);
        if (auto dims = source.getDimensionSyntax())
            setDimensionSyntax(*dims);
    }

    type = source.type;
}

void DeclaredType::mergeImplicitPort(
    const ImplicitTypeSyntax& implicit, SourceLocation location,
    span<const VariableDimensionSyntax* const> unpackedDimensions) {
    mergePortTypes(getBindContext(), parent.as<ValueSymbol>(), implicit, location,
                   unpackedDimensions);
}

const Scope& DeclaredType::getScope() const {
    const Scope* scope = parent.getParentScope();
    ASSERT(scope);
    return *scope;
}

void DeclaredType::resolveType(const BindContext& initializerContext) const {
    auto& scope = getScope();
    auto& comp = scope.getCompilation();
    if (!typeSyntax) {
        type = &comp.getErrorType();
        return;
    }

    ASSERT(!evaluating);
    evaluating = true;
    auto guard = ScopeGuard([this] { evaluating = false; });

    // If we are configured to infer implicit types, bind the initializer expression
    // first so that we can derive our type from whatever that happens to be.
    if (typeSyntax->kind == SyntaxKind::ImplicitType &&
        (flags & DeclaredTypeFlags::InferImplicit) != 0) {
        if (dimensions) {
            scope.addDiag(diag::UnpackedArrayParamType, dimensions->sourceRange());
            type = &comp.getErrorType();
        }
        else if (!initializerSyntax) {
            type = &comp.getErrorType();
        }
        else {
            initializer = &Expression::bindImplicitParam(*typeSyntax, *initializerSyntax,
                                                         initializerLocation, initializerContext);
            type = initializer->type;
        }
    }
    else {
        const Type* typedefTarget = nullptr;
        if (flags.has(DeclaredTypeFlags::TypedefTarget))
            typedefTarget = &parent.as<Type>();

        BindContext typeContext = getBindContext();
        type = &comp.getType(*typeSyntax, typeContext.lookupLocation, scope, typedefTarget);
        if (dimensions)
            type = &comp.getType(*type, *dimensions, typeContext.lookupLocation, scope);
    }

    if (flags.has(DeclaredTypeFlags::NeedsTypeCheck) && !type->isError())
        checkType(initializerContext);
}

static bool isValidForNet(const Type& type) {
    auto& ct = type.getCanonicalType();
    if (ct.isIntegral())
        return ct.isFourState();

    if (ct.kind == SymbolKind::FixedSizeUnpackedArrayType)
        return isValidForNet(ct.as<FixedSizeUnpackedArrayType>().elementType);

    if (ct.isUnpackedStruct()) {
        for (auto& field : ct.as<UnpackedStructType>().membersOfType<FieldSymbol>()) {
            if (!isValidForNet(field.getType()))
                return false;
        }
        return true;
    }

    return false;
}

static bool isValidForUserDefinedNet(const Type& type) {
    auto& ct = type.getCanonicalType();
    if (ct.isIntegral() || ct.isFloating())
        return true;

    if (ct.kind == SymbolKind::FixedSizeUnpackedArrayType)
        return isValidForUserDefinedNet(ct.as<FixedSizeUnpackedArrayType>().elementType);

    if (ct.isUnpackedStruct()) {
        for (auto& field : ct.as<UnpackedStructType>().membersOfType<FieldSymbol>()) {
            if (!isValidForUserDefinedNet(field.getType()))
                return false;
        }
        return true;
    }

    if (ct.isUnpackedUnion()) {
        for (auto& field : ct.as<UnpackedUnionType>().membersOfType<FieldSymbol>()) {
            if (!isValidForUserDefinedNet(field.getType()))
                return false;
        }
        return true;
    }

    return false;
}

void DeclaredType::checkType(const BindContext& context) const {
    uint32_t masked = (flags & DeclaredTypeFlags::NeedsTypeCheck).bits();
    ASSERT(countPopulation64(masked) == 1);

    switch (masked) {
        case uint32_t(DeclaredTypeFlags::Port):
            // Ports cannot be chandles.
            if (type->isCHandle())
                context.addDiag(diag::InvalidPortType, parent.location) << *type;
            break;
        case uint32_t(DeclaredTypeFlags::NetType): {
            auto& net = parent.as<NetSymbol>();
            if (net.netType.netKind != NetType::UserDefined && !isValidForNet(*type))
                context.addDiag(diag::InvalidNetType, parent.location) << *type;
            else if (type->getBitWidth() == 1 && net.expansionHint != NetSymbol::None)
                context.addDiag(diag::SingleBitVectored, parent.location);
            break;
        }
        case uint32_t(DeclaredTypeFlags::UserDefinedNetType):
            if (!isValidForUserDefinedNet(*type))
                context.addDiag(diag::InvalidUserDefinedNetType, parent.location) << *type;
            break;
        case uint32_t(DeclaredTypeFlags::FormalArgMergeVar):
            if (auto var = parent.as<FormalArgumentSymbol>().getMergedVariable()) {
                ASSERT(typeSyntax);
                mergePortTypes(context, *var, typeSyntax->as<ImplicitTypeSyntax>(), parent.location,
                               dimensions ? *dimensions
                                          : span<const VariableDimensionSyntax* const>{});
            }
            break;
        case uint32_t(DeclaredTypeFlags::Rand): {
            RandMode mode = parent.getRandMode();
            if (!type->isValidForRand(mode)) {
                auto& diag = context.addDiag(diag::InvalidRandType, parent.location) << *type;
                if (mode == RandMode::Rand)
                    diag << "rand"sv;
                else
                    diag << "randc"sv;
            }
            break;
        }
        case uint32_t(DeclaredTypeFlags::DPIReturnType): {
            if (!type->isValidForDPIReturn())
                context.addDiag(diag::InvalidDPIReturnType, parent.location) << *type;
            else if (parent.as<SubroutineSymbol>().flags.has(MethodFlags::Pure) && type->isVoid())
                context.addDiag(diag::DPIPureReturn, parent.location);
            break;
        }
        case uint32_t(DeclaredTypeFlags::DPIArg):
            if (!type->isValidForDPIArg())
                context.addDiag(diag::InvalidDPIArgType, parent.location) << *type;
            break;
        default:
            THROW_UNREACHABLE;
    }
}

static const Type* makeSigned(Compilation& compilation, const Type& type) {
    // This deliberately does not look at the canonical type; type aliases
    // are not convertible to a different signedness.
    SmallVectorSized<ConstantRange, 4> dims;
    const Type* curr = &type;
    while (curr->kind == SymbolKind::PackedArrayType) {
        dims.append(curr->getFixedRange());
        curr = curr->getArrayElementType();
    }

    if (curr->kind != SymbolKind::ScalarType)
        return &type;

    auto flags = curr->getIntegralFlags() | IntegralFlags::Signed;
    if (dims.size() == 1)
        return &compilation.getType(type.getBitWidth(), flags);

    curr = &compilation.getScalarType(flags);
    size_t count = dims.size();
    for (size_t i = 0; i < count; i++)
        curr = compilation.emplace<PackedArrayType>(*curr, dims[count - i - 1]);

    return curr;
}

void DeclaredType::mergePortTypes(
    const BindContext& context, const ValueSymbol& sourceSymbol, const ImplicitTypeSyntax& implicit,
    SourceLocation location, span<const VariableDimensionSyntax* const> unpackedDimensions) const {

    // There's this really terrible "feature" where the port declaration can influence the type
    // of the actual symbol somewhere else in the tree. This is ugly but should be safe since
    // nobody else can look at that symbol's type until we've gone through elaboration.
    //
    // In this context, the sourceSymbol is the actual variable declaration with, presumably,
    // a full type declared. The implicit syntax is from the port I/O declaration, which needs
    // to be merged. For example:
    //
    //   input signed [1:0] foo;    // implicit + unpackedDimensions + location
    //   logic foo;                 // sourceSymbol
    const Type* destType = &sourceSymbol.getType();

    if (implicit.signing) {
        // Drill past any unpacked arrays to figure out if this thing is even integral.
        SmallVectorSized<ConstantRange, 4> destDims;
        const Type* sourceType = destType;
        while (sourceType->getCanonicalType().kind == SymbolKind::FixedSizeUnpackedArrayType) {
            destDims.append(sourceType->getFixedRange());
            sourceType = sourceType->getArrayElementType();
        }

        if (sourceType->isError())
            return;

        if (!sourceType->isIntegral()) {
            auto& diag = context.addDiag(diag::CantDeclarePortSigned, location);
            diag << sourceSymbol.name << implicit.signing.valueText() << *destType;
            diag.addNote(diag::NoteDeclarationHere, sourceSymbol.location);
            return;
        }

        auto warnSignedness = [&] {
            auto& diag = context.addDiag(diag::SignednessNoEffect, implicit.signing.range());
            diag << implicit.signing.valueText() << *destType;
            diag.addNote(diag::NoteDeclarationHere, sourceSymbol.location);
        };

        bool shouldBeSigned = implicit.signing.kind == TokenKind::SignedKeyword;
        if (shouldBeSigned && !sourceType->isSigned()) {
            sourceType = makeSigned(context.getCompilation(), *sourceType);
            if (!sourceType->isSigned()) {
                warnSignedness();
            }
            else {
                // Put the unpacked dimensions back on the type now that it
                // has been made signed.
                destType = &FixedSizeUnpackedArrayType::fromDims(context.getCompilation(),
                                                                 *sourceType, destDims);
            }
        }
        else if (!shouldBeSigned && sourceType->isSigned()) {
            warnSignedness();
        }
    }

    // Our declared type takes on the merged type from the variable definition.
    this->type = destType;

    auto errorDims = [&](auto& dims) {
        auto& diag = context.addDiag(diag::PortDeclDimensionsMismatch, dims.sourceRange());
        diag << sourceSymbol.name;
        diag.addNote(diag::NoteDeclarationHere, sourceSymbol.location);
    };

    auto checkDims = [&](auto& dims, SymbolKind arrayKind, bool isPacked) {
        if (!dims.empty()) {
            auto it = dims.begin();
            while (destType->getCanonicalType().kind == arrayKind) {
                if (it == dims.end()) {
                    errorDims(*dims.back());
                    return;
                }

                auto dim = isPacked ? context.evalPackedDimension(**it)
                                    : context.evalUnpackedDimension(**it);
                if (!dim || destType->getFixedRange() != *dim) {
                    errorDims(**it);
                    return;
                }

                destType = destType->getArrayElementType();
                it++;
            }

            if (it != dims.end()) {
                errorDims(**it);
                return;
            }
        }
    };

    // Unpacked dim checks have to come first because it unwraps the destType
    // for the packed one to look at.
    checkDims(unpackedDimensions, SymbolKind::FixedSizeUnpackedArrayType, false);
    checkDims(implicit.dimensions, SymbolKind::PackedArrayType, true);
}

void DeclaredType::resolveAt(const BindContext& context) const {
    if (!initializerSyntax)
        return;

    if (!type) {
        resolveType(context);
        if (initializer)
            return;
    }

    // Enums are special in that their initializers target the base type of the enum
    // instead of the actual enum type (which doesn't allow implicit conversions from
    // normal integral values).
    auto& scope = context.scope;
    bitmask<BindFlags> bindFlags = context.flags;
    const Type* targetType = type;
    if (targetType->isEnum() && scope.asSymbol().kind == SymbolKind::EnumType) {
        targetType = &targetType->as<EnumType>().baseType;
        bindFlags |= BindFlags::EnumInitializer;
    }

    initializer = &Expression::bindRValue(*targetType, *initializerSyntax, initializerLocation,
                                          context.resetFlags(bindFlags));
}

const Expression* DeclaredType::getInitializer() const {
    if (initializer)
        return initializer;

    resolveAt(getBindContext());
    return initializer;
}

void DeclaredType::setFromDeclarator(const DeclaratorSyntax& decl) {
    if (!decl.dimensions.empty())
        setDimensionSyntax(decl.dimensions);
    if (decl.initializer)
        setInitializerSyntax(*decl.initializer->expr, decl.initializer->equals.location());
}

template<typename T>
T DeclaredType::getBindContext() const {
    bitmask<BindFlags> bindFlags;
    if (flags & DeclaredTypeFlags::RequireConstant)
        bindFlags = BindFlags::Constant;
    if (flags & DeclaredTypeFlags::InProceduralContext)
        bindFlags |= BindFlags::ProceduralStatement;
    if ((flags & DeclaredTypeFlags::AutomaticInitializer) == 0)
        bindFlags |= BindFlags::StaticInitializer;

    LookupLocation location;
    if (flags & DeclaredTypeFlags::LookupMax)
        location = LookupLocation::max;
    else
        location = LookupLocation::after(parent);

    return BindContext(getScope(), location, bindFlags);
}

} // namespace slang
<|endoftext|>


<commit_before>// win32_handmade.cpp
// compiles with -doc -FC -Zi win32_handmade.cpp user32.lib gdi32.lib
// see: build.bat for switches used in compilation
/* ========================================================================
$File: $
$Date: $
$Revision: 0.1.d4.b(build#) $
$Creator: Sebastian Meier zu Biesen $
$Notice: (C) Copyright 2000-2016 by Joker Solutions, All Rights Reserved. $
======================================================================== */

#include <Windows.h>
#include <stdint.h>
#include "win32_handmade.h"

win32_window_dimensions Win32GetWindowDimensions(HWND WindowHandle) {
	win32_window_dimensions Result;
	RECT WindowRect;
	GetClientRect(WindowHandle, &WindowRect);
	Result.Width = WindowRect.right - WindowRect.left;
	Result.Height = WindowRect.bottom - WindowRect.top;
	return Result;
}

internal void Win32RenderGradient(win32_offscreen_buffer Buffer, int XOffset, int YOffset) {
	uint8 *Row = (uint8 *)Buffer.Memory;
	for (int Y = 0; Y < Buffer.Height; ++Y) {
		uint32 *Pixel = (uint32 *)Row;
		for (int X = 0; X < Buffer.Width; ++X) {
			uint8 Blue = (X + XOffset);
			uint8 Green = (Y + YOffset);
			uint8 Red = (X + XOffset);
			*Pixel++ = ((Red << 16) | (Green << 8) | (Blue));
		}
		Row += Buffer.Pitch;
	}
}

internal void Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height) {
	if (Buffer->Memory) {
		VirtualFree(Buffer->Memory,0,MEM_RELEASE);
	}
	Buffer->Width = Width;
	Buffer->Height = Height;
	Buffer->BytesPerPixel = 4;
	Buffer->Info.bmiHeader.biSize = sizeof(Buffer->Info.bmiHeader);
	Buffer->Info.bmiHeader.biWidth = Buffer->Width;
	Buffer->Info.bmiHeader.biHeight = -Buffer->Height;
	Buffer->Info.bmiHeader.biPlanes = 1;
	Buffer->Info.bmiHeader.biBitCount = 32;
	Buffer->Info.bmiHeader.biCompression = BI_RGB;

	int BitmapMemorySize = (Buffer->Width*Buffer->Height)*Buffer->BytesPerPixel;
	Buffer->Memory = VirtualAlloc(0, BitmapMemorySize, MEM_COMMIT, PAGE_READWRITE);
	Buffer->Pitch = Buffer->Width*Buffer->BytesPerPixel;
}

internal void Win32DisplayBufferInWindow(HDC DeviceContext, int WindowWidth, int WindowHeight, win32_offscreen_buffer Buffer, int X, int Y, int Width, int Height) {
	StretchDIBits(DeviceContext, 0, 0, Buffer.Width, Buffer.Height, 0, 0, WindowWidth, WindowHeight, Buffer.Memory, &Buffer.Info, DIB_RGB_COLORS, SRCCOPY);
}

LRESULT CALLBACK Win32MainWindowCallback(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
	LRESULT Result = 0;
	switch (Message) {
		case WM_SIZE:
		{
			win32_window_dimensions Dimensions = Win32GetWindowDimensions(Window);
			Win32ResizeDIBSection(&GlobalBackBuffer, Dimensions.Width, Dimensions.Height);
			if (Debug) { OutputDebugStringA("WM_SIZE\n"); }
		} break;
		case WM_DESTROY:
		{
			Running = false;
			if (Debug) { OutputDebugStringA("WM_DESTROY\n"); }
		} break;
		case WM_CLOSE:
		{
			Running = false;
			if (Debug) { OutputDebugStringA("WM_CLOSE\n"); }
		} break;
		case WM_QUIT:
		{
			if (Debug) { OutputDebugStringA("WM_QUIT\n"); }
		} break;
		case WM_ACTIVATEAPP:
		{
			if (Debug) { OutputDebugStringA("WM_ACTIVATEAPP\n"); }
		} break;
		case WM_PAINT:
		{
			PAINTSTRUCT Paint;
			HDC DeviceContext = BeginPaint(Window, &Paint);
			int X = Paint.rcPaint.left;
			int Y = Paint.rcPaint.top;
			int Width = Paint.rcPaint.right - Paint.rcPaint.left;
			int Height = Paint.rcPaint.bottom - Paint.rcPaint.top;
			win32_window_dimensions Dimensions = Win32GetWindowDimensions(Window);
			Win32DisplayBufferInWindow(DeviceContext, Dimensions.Width, Dimensions.Height, GlobalBackBuffer , X, Y, Width, Height);
			EndPaint(Window,&Paint);
			if (Debug) { OutputDebugStringA("WM_PAINT\n"); }
		} break;
		default:
		{
			Result = DefWindowProc(Window,Message,WParam,LParam);
			//OutputDebugStringA("default\n");
		} break;
	}

	return(Result);
}

int CALLBACK WinMain(HINSTANCE Instance, HINSTANCE hPrevInstance, LPSTR CommandLine, int ShowCode) {
	WNDCLASS WindowClass = {};
	WindowClass.style = CS_HREDRAW|CS_VREDRAW;
	WindowClass.lpfnWndProc = Win32MainWindowCallback;
	WindowClass.hInstance = Instance;
	//WindowClass.hIcon = ;
	//WindowClass.hCursor = ;
	WindowClass.lpszClassName = "hmhWindowClass";
	if (RegisterClass(&WindowClass))
	{
		HWND WindowHandle = CreateWindowEx(
			0,
			WindowClass.lpszClassName,
			"Handmade Hero v0.1",
			WS_OVERLAPPEDWINDOW|WS_VISIBLE,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			0,
			0,
			Instance,
			0);
		if (WindowHandle)
		{
			int XOffset = 0;
			int YOffset = 0;
			Running = true;
			while(Running)
			{
				MSG Message;
				while (PeekMessage(&Message, 0, 0, 0, PM_REMOVE)) {
					if (Message.message == WM_QUIT) {
						Running = false;
					}
					TranslateMessage(&Message);
					DispatchMessage(&Message);
				}
				Win32RenderGradient(GlobalBackBuffer, XOffset, YOffset);

				HDC DeviceContext = GetDC(WindowHandle);
				win32_window_dimensions Dimensions = Win32GetWindowDimensions(WindowHandle);
				Win32DisplayBufferInWindow(DeviceContext, Dimensions.Width, Dimensions.Height, GlobalBackBuffer, 0, 0, Dimensions.Width, Dimensions.Height);
				ReleaseDC(WindowHandle, DeviceContext);
				++XOffset;
			}

		}
		else
		{
			//TODO(smzb): Log this event
		}
	}
	else {
		//TODO(smzb): log this event
	}
	if (Debug) { MessageBox(0, "This is Handmade Hero", "Handmade Hero v0.1", MB_OK | MB_ICONINFORMATION); }
	return 0;
}
<commit_msg>we are now using a fixed backbuffer of 1280x720<commit_after>// win32_handmade.cpp
// compiles with -doc -FC -Zi win32_handmade.cpp user32.lib gdi32.lib
// see: build.bat for switches used in compilation
/* ========================================================================
$File: $
$Date: $
$Revision: 0.1.d4.b(build#) $
$Creator: Sebastian Meier zu Biesen $
$Notice: (C) Copyright 2000-2016 by Joker Solutions, All Rights Reserved. $
======================================================================== */

#include <Windows.h>
#include <stdint.h>
#include "win32_handmade.h"

win32_window_dimensions Win32GetWindowDimensions(HWND WindowHandle) {
	win32_window_dimensions Result;
	RECT WindowRect;
	GetClientRect(WindowHandle, &WindowRect);
	Result.Width = WindowRect.right - WindowRect.left;
	Result.Height = WindowRect.bottom - WindowRect.top;
	return Result;
}

internal void Win32RenderGradient(win32_offscreen_buffer Buffer, int XOffset, int YOffset) {
	uint8 *Row = (uint8 *)Buffer.Memory;
	for (int Y = 0; Y < Buffer.Height; ++Y) {
		uint32 *Pixel = (uint32 *)Row;
		for (int X = 0; X < Buffer.Width; ++X) {
			uint8 Blue = (X + XOffset);
			uint8 Green = (Y + YOffset);
			uint8 Red = (X + XOffset);
			*Pixel++ = ((Red << 16) | (Green << 8) | (Blue));
		}
		Row += Buffer.Pitch;
	}
}

internal void Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height) {
	if (Buffer->Memory) {
		VirtualFree(Buffer->Memory,0,MEM_RELEASE);
	}
	Buffer->Width = Width;
	Buffer->Height = Height;
	Buffer->BytesPerPixel = 4;
	Buffer->Info.bmiHeader.biSize = sizeof(Buffer->Info.bmiHeader);
	Buffer->Info.bmiHeader.biWidth = Buffer->Width;
	Buffer->Info.bmiHeader.biHeight = -Buffer->Height;
	Buffer->Info.bmiHeader.biPlanes = 1;
	Buffer->Info.bmiHeader.biBitCount = 32;
	Buffer->Info.bmiHeader.biCompression = BI_RGB;

	int BitmapMemorySize = (Buffer->Width*Buffer->Height)*Buffer->BytesPerPixel;
	Buffer->Memory = VirtualAlloc(0, BitmapMemorySize, MEM_COMMIT, PAGE_READWRITE);
	Buffer->Pitch = Buffer->Width*Buffer->BytesPerPixel;
}

internal void Win32DisplayBufferInWindow(HDC DeviceContext, int WindowWidth, int WindowHeight, win32_offscreen_buffer Buffer, int X, int Y, int Width, int Height) {
	StretchDIBits(DeviceContext, 0, 0, WindowWidth, WindowHeight, 0, 0, Buffer.Width, Buffer.Height, Buffer.Memory, &Buffer.Info, DIB_RGB_COLORS, SRCCOPY);
}

LRESULT CALLBACK Win32MainWindowCallback(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
	LRESULT Result = 0;
	switch (Message) {
		case WM_SIZE:
		{
			if (Debug) { OutputDebugStringA("WM_SIZE\n"); }
		} break;
		case WM_DESTROY:
		{
			Running = false;
			if (Debug) { OutputDebugStringA("WM_DESTROY\n"); }
		} break;
		case WM_CLOSE:
		{
			Running = false;
			if (Debug) { OutputDebugStringA("WM_CLOSE\n"); }
		} break;
		case WM_QUIT:
		{
			if (Debug) { OutputDebugStringA("WM_QUIT\n"); }
		} break;
		case WM_ACTIVATEAPP:
		{
			if (Debug) { OutputDebugStringA("WM_ACTIVATEAPP\n"); }
		} break;
		case WM_PAINT:
		{
			PAINTSTRUCT Paint;
			HDC DeviceContext = BeginPaint(Window, &Paint);
			int X = Paint.rcPaint.left;
			int Y = Paint.rcPaint.top;
			int Width = Paint.rcPaint.right - Paint.rcPaint.left;
			int Height = Paint.rcPaint.bottom - Paint.rcPaint.top;
			win32_window_dimensions Dimensions = Win32GetWindowDimensions(Window);
			Win32DisplayBufferInWindow(DeviceContext, Dimensions.Width, Dimensions.Height, GlobalBackBuffer , X, Y, Width, Height);
			EndPaint(Window,&Paint);
			if (Debug) { OutputDebugStringA("WM_PAINT\n"); }
		} break;
		default:
		{
			Result = DefWindowProc(Window,Message,WParam,LParam);
			//OutputDebugStringA("default\n");
		} break;
	}

	return(Result);
}

int CALLBACK WinMain(HINSTANCE Instance, HINSTANCE hPrevInstance, LPSTR CommandLine, int ShowCode) {
	WNDCLASS WindowClass = {};
	Win32ResizeDIBSection(&GlobalBackBuffer, 1280, 720);
	WindowClass.style = CS_HREDRAW|CS_VREDRAW;
	WindowClass.lpfnWndProc = Win32MainWindowCallback;
	WindowClass.hInstance = Instance;
	//WindowClass.hIcon = ;
	//WindowClass.hCursor = ;
	WindowClass.lpszClassName = "hmhWindowClass";
	if (RegisterClass(&WindowClass))
	{
		HWND WindowHandle = CreateWindowEx(
			0,
			WindowClass.lpszClassName,
			"Handmade Hero v0.1",
			WS_OVERLAPPEDWINDOW|WS_VISIBLE,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			0,
			0,
			Instance,
			0);
		if (WindowHandle)
		{
			int XOffset = 0;
			int YOffset = 0;
			Running = true;
			while(Running)
			{
				MSG Message;
				while (PeekMessage(&Message, 0, 0, 0, PM_REMOVE)) {
					if (Message.message == WM_QUIT) {
						Running = false;
					}
					TranslateMessage(&Message);
					DispatchMessage(&Message);
				}
				Win32RenderGradient(GlobalBackBuffer, XOffset, YOffset);

				HDC DeviceContext = GetDC(WindowHandle);
				win32_window_dimensions Dimensions = Win32GetWindowDimensions(WindowHandle);
				Win32DisplayBufferInWindow(DeviceContext, Dimensions.Width, Dimensions.Height, GlobalBackBuffer, 0, 0, Dimensions.Width, Dimensions.Height);
				ReleaseDC(WindowHandle, DeviceContext);
				++XOffset;
			}

		}
		else
		{
			//TODO(smzb): Log this event
		}
	}
	else {
		//TODO(smzb): log this event
	}
	if (Debug) { MessageBox(0, "This is Handmade Hero", "Handmade Hero v0.1", MB_OK | MB_ICONINFORMATION); }
	return 0;
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_FV_DEFAULT_HH
#define DUNE_GDT_SPACES_FV_DEFAULT_HH

#include <dune/common/deprecated.hh>

#include <dune/stuff/common/type_utils.hh>

#include <dune/gdt/basefunctionset/default/fv.hh>
#include <dune/gdt/mapper/default/fv.hh>
#include <dune/gdt/spaces/parallel.hh>

#include "interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {
namespace FV {

// forward, to be used in the traits and to allow for specialization
template< class GridViewImp, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols = 1 >
class Default
{
  static_assert(Dune::AlwaysFalse< GridViewImp >::value, "Untested for these dimensions!");
};

namespace internal {

/**
 *  \brief Traits class for Spaces::CG::FemBased.
 */
template< class GridViewImp, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols >
class DefaultTraits
{
public:
  typedef Default< GridViewImp, RangeFieldImp, rangeDim, rangeDimCols > derived_type;
  static const int  polOrder = 0;
  typedef GridViewImp                     GridViewType;
  typedef typename GridViewType::IndexSet BackendType;
  typedef typename GridViewType::template Codim< 0 >::Entity EntityType;
  typedef RangeFieldImp     RangeFieldType;
  typedef Mapper::FiniteVolume< GridViewType, rangeDim, rangeDimCols > MapperType;
  typedef BaseFunctionSet::FiniteVolume< typename GridViewType::template Codim< 0 >::Entity
                                       , typename GridViewType::ctype, GridViewType::dimension
                                       , RangeFieldType, rangeDim, rangeDimCols > BaseFunctionSetType;
  static const Stuff::Grid::ChoosePartView part_view_type = Stuff::Grid::ChoosePartView::view;
  static const bool                        needs_grid_view = true;
  typedef CommunicationChooser< GridViewType >    CommunicationChooserType;
  typedef typename CommunicationChooserType::Type CommunicatorType;
}; // class DefaultTraits

} // namespace internal

template< class GridViewImp, class RangeFieldImp, size_t rangeDim >
class Default< GridViewImp, RangeFieldImp, rangeDim, 1 >
  : public FVInterface< internal::DefaultTraits< GridViewImp, RangeFieldImp, rangeDim, 1 >,
                        GridViewImp::dimension, rangeDim, 1 >
{
  typedef Default< GridViewImp, RangeFieldImp, rangeDim, 1 > ThisType;
  typedef FVInterface< internal::DefaultTraits< GridViewImp, RangeFieldImp, rangeDim, 1 >,
                       GridViewImp::dimension, rangeDim, 1 > BaseType;
public:
  using typename BaseType::Traits;
  using typename BaseType::GridViewType;
  using typename BaseType::BackendType;
  using typename BaseType::MapperType;
  using typename BaseType::EntityType;
  using typename BaseType::BaseFunctionSetType;
private:
  typedef typename Traits::CommunicationChooserType CommunicationChooserType;
public:
  using typename BaseType::CommunicatorType;

  Default(GridViewType gv)
    : grid_view_(gv)
    , mapper_(grid_view_)
    , communicator_(CommunicationChooserType::create(grid_view_))
  {}

  Default(const ThisType& other)
    : grid_view_(other.grid_view_)
    , mapper_(other.mapper_)
    , communicator_(CommunicationChooserType::create(grid_view_))
  {}

  Default(ThisType&& source) = default;

  ThisType& operator=(const ThisType& other) = delete;

  ThisType& operator=(ThisType&& source) = delete;

  const GridViewType& grid_view() const
  {
    return grid_view_;
  }

  const BackendType& backend() const
  {
    return grid_view_.indexSet();
  }

  const MapperType& mapper() const
  {
    return mapper_;
  }

  BaseFunctionSetType base_function_set(const EntityType& entity) const
  {
    return BaseFunctionSetType(entity);
  }

  CommunicatorType& communicator() const
  {
    // no need to prepare the communicator, since we are not pdelab based
    return *communicator_;
  }

private:
  const GridViewType grid_view_;
  const MapperType mapper_;
  const std::unique_ptr< CommunicatorType > communicator_;
}; // class Default< ..., 1, 1 >

} // namespace FV
} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_FV_DEFAULT_HH
<commit_msg>[spaces.fv.default] add make_fv(...)<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_FV_DEFAULT_HH
#define DUNE_GDT_SPACES_FV_DEFAULT_HH

#include <dune/common/deprecated.hh>

#include <dune/stuff/common/type_utils.hh>

#include <dune/gdt/basefunctionset/default/fv.hh>
#include <dune/gdt/mapper/default/fv.hh>
#include <dune/gdt/spaces/parallel.hh>

#include "interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {
namespace FV {

// forward, to be used in the traits and to allow for specialization
template< class GridViewImp, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols = 1 >
class Default
{
  static_assert(Dune::AlwaysFalse< GridViewImp >::value, "Untested for these dimensions!");
};

namespace internal {

/**
 *  \brief Traits class for Spaces::CG::FemBased.
 */
template< class GridViewImp, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols >
class DefaultTraits
{
public:
  typedef Default< GridViewImp, RangeFieldImp, rangeDim, rangeDimCols > derived_type;
  static const int  polOrder = 0;
  typedef GridViewImp                     GridViewType;
  typedef typename GridViewType::IndexSet BackendType;
  typedef typename GridViewType::template Codim< 0 >::Entity EntityType;
  typedef RangeFieldImp     RangeFieldType;
  typedef Mapper::FiniteVolume< GridViewType, rangeDim, rangeDimCols > MapperType;
  typedef BaseFunctionSet::FiniteVolume< typename GridViewType::template Codim< 0 >::Entity
                                       , typename GridViewType::ctype, GridViewType::dimension
                                       , RangeFieldType, rangeDim, rangeDimCols > BaseFunctionSetType;
  static const Stuff::Grid::ChoosePartView part_view_type = Stuff::Grid::ChoosePartView::view;
  static const bool                        needs_grid_view = true;
  typedef CommunicationChooser< GridViewType >    CommunicationChooserType;
  typedef typename CommunicationChooserType::Type CommunicatorType;
}; // class DefaultTraits

} // namespace internal

template< class GridViewImp, class RangeFieldImp, size_t rangeDim >
class Default< GridViewImp, RangeFieldImp, rangeDim, 1 >
  : public FVInterface< internal::DefaultTraits< GridViewImp, RangeFieldImp, rangeDim, 1 >,
                        GridViewImp::dimension, rangeDim, 1 >
{
  typedef Default< GridViewImp, RangeFieldImp, rangeDim, 1 > ThisType;
  typedef FVInterface< internal::DefaultTraits< GridViewImp, RangeFieldImp, rangeDim, 1 >,
                       GridViewImp::dimension, rangeDim, 1 > BaseType;
public:
  using typename BaseType::Traits;
  using typename BaseType::GridViewType;
  using typename BaseType::BackendType;
  using typename BaseType::MapperType;
  using typename BaseType::EntityType;
  using typename BaseType::BaseFunctionSetType;
private:
  typedef typename Traits::CommunicationChooserType CommunicationChooserType;
public:
  using typename BaseType::CommunicatorType;

  Default(GridViewType gv)
    : grid_view_(gv)
    , mapper_(grid_view_)
    , communicator_(CommunicationChooserType::create(grid_view_))
  {}

  Default(const ThisType& other)
    : grid_view_(other.grid_view_)
    , mapper_(other.mapper_)
    , communicator_(CommunicationChooserType::create(grid_view_))
  {}

  Default(ThisType&& source) = default;

  ThisType& operator=(const ThisType& other) = delete;

  ThisType& operator=(ThisType&& source) = delete;

  const GridViewType& grid_view() const
  {
    return grid_view_;
  }

  const BackendType& backend() const
  {
    return grid_view_.indexSet();
  }

  const MapperType& mapper() const
  {
    return mapper_;
  }

  BaseFunctionSetType base_function_set(const EntityType& entity) const
  {
    return BaseFunctionSetType(entity);
  }

  CommunicatorType& communicator() const
  {
    // no need to prepare the communicator, since we are not pdelab based
    return *communicator_;
  }

private:
  const GridViewType grid_view_;
  const MapperType mapper_;
  const std::unique_ptr< CommunicatorType > communicator_;
}; // class Default< ..., 1, 1 >

} // namespace FV

template< class R, size_t r, size_t rC, class GV >
FV::Default< GV, R, r, rC > make_fv(const GV& grid_view)
{
  return FV::Default< GV, R, r, rC >(grid_view);
}

template< class R, size_t r, class GV >
FV::Default< GV, R, r, 1 > make_fv(const GV& grid_view)
{
  return FV::Default< GV, R, r, 1 >(grid_view);
}

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_FV_DEFAULT_HH
<|endoftext|>


<commit_before>#pragma once

#include <atomic>
#include <boost/iostreams/concepts.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <condition_variable>
#include <mutex>
#include <nano/lib/timer.hpp>
#include <string>

#define GTEST_TEST_ERROR_CODE(expression, text, actual, expected, fail)                       \
	GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                             \
	if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult (expression)) \
		;                                                                                \
	else                                                                                \
		fail (::testing::internal::GetBoolAssertionFailureMessage (                           \
		gtest_ar_, text, actual, expected)                                                    \
		      .c_str ())

/** Extends gtest with a std::error_code assert that prints the error code message when non-zero */
#define ASSERT_NO_ERROR(condition)                                                      \
	GTEST_TEST_ERROR_CODE (!(condition), #condition, condition.message ().c_str (), "", \
	GTEST_FATAL_FAILURE_)

/** Extends gtest with a std::error_code assert that expects an error */
#define ASSERT_IS_ERROR(condition)                                                            \
	GTEST_TEST_ERROR_CODE ((condition.value () > 0), #condition, "An error was expected", "", \
	GTEST_FATAL_FAILURE_)

/* Convenience globals for core_test */
namespace nano
{
using uint128_t = boost::multiprecision::uint128_t;
class keypair;
union uint256_union;
extern nano::keypair const & zero_key;
extern nano::keypair const & test_genesis_key;
extern std::string const & nano_test_genesis;
extern std::string const & genesis_block;
extern nano::uint256_union const & nano_test_account;
extern nano::uint256_union const & genesis_account;
extern nano::uint256_union const & burn_account;
extern nano::uint128_t const & genesis_amount;

class stringstream_mt_sink : public boost::iostreams::sink
{
public:
	stringstream_mt_sink () = default;
	stringstream_mt_sink (const stringstream_mt_sink & sink)
	{
		std::lock_guard<std::mutex> guard (mutex);
		ss << sink.ss.str ();
	}

	std::streamsize write (const char * string_to_write, std::streamsize size)
	{
		std::lock_guard<std::mutex> guard (mutex);
		ss << string_to_write;
		return size;
	}

	std::string str ()
	{
		std::lock_guard<std::mutex> guard (mutex);
		return ss.str ();
	}

private:
	mutable std::mutex mutex;
	std::stringstream ss;
};

class boost_log_cerr_redirect
{
public:
	boost_log_cerr_redirect (std::streambuf * new_buffer) :
	old (std::cerr.rdbuf (new_buffer))
	{
		console_sink = (boost::log::add_console_log (std::cerr, boost::log::keywords::format = "%Message%"));
	}

	~boost_log_cerr_redirect ()
	{
		std::cerr.rdbuf (old);
		boost::log::core::get ()->remove_sink (console_sink);
	}

private:
	std::streambuf * old;
	boost::shared_ptr<boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend>> console_sink;
};

namespace util
{
	/**
	 * Helper to signal completion of async handlers in tests.
	 * Subclasses implement specific conditions for completion.
	 */
	class completion_signal
	{
	public:
		virtual ~completion_signal ()
		{
			notify ();
		}

		/** Explicitly notify the completion */
		void notify ()
		{
			cv.notify_all ();
		}

	protected:
		std::condition_variable cv;
		std::mutex mutex;
	};

	/**
	 * Signals completion when a count is reached.
	 */
	class counted_completion : public completion_signal
	{
	public:
		/**
		 * Constructor
		 * @param required_count_a When increment() reaches this count within the deadline, await_count_for() will return false.
		 */
		counted_completion (unsigned required_count_a) :
		required_count (required_count_a)
		{
		}

		/**
		 * Wait for increment() to signal completion, or reaching the deadline.
		 * @param deadline_duration_a Deadline as a std::chrono duration
		 * @return true if the count is reached within the deadline
		 */
		template <typename UNIT>
		bool await_count_for (UNIT deadline_duration_a)
		{
			nano::timer<UNIT> timer (nano::timer_state::started);
			bool error = true;
			while (error && timer.before_deadline (deadline_duration_a))
			{
				error = count < required_count;
				if (error)
				{
					std::unique_lock<std::mutex> lock (mutex);
					cv.wait_for (lock, std::chrono::milliseconds (1));
				}
			}
			return error;
		}

		/** Increments the current count. If the required count is reached, await_count_for() waiters are notified. */
		unsigned increment ()
		{
			auto val (count.fetch_add (1));
			if (val >= required_count)
			{
				notify ();
			}
			return val;
		}

	private:
		std::atomic<unsigned> count{ 0 };
		unsigned required_count;
	};
}
}
<commit_msg>stringstream_mt_sink to bounds check the buffer (#2016)<commit_after>#pragma once

#include <atomic>
#include <boost/iostreams/concepts.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <condition_variable>
#include <mutex>
#include <nano/lib/timer.hpp>
#include <string>

#define GTEST_TEST_ERROR_CODE(expression, text, actual, expected, fail)                       \
	GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                             \
	if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult (expression)) \
		;                                                                                \
	else                                                                                \
		fail (::testing::internal::GetBoolAssertionFailureMessage (                           \
		gtest_ar_, text, actual, expected)                                                    \
		      .c_str ())

/** Extends gtest with a std::error_code assert that prints the error code message when non-zero */
#define ASSERT_NO_ERROR(condition)                                                      \
	GTEST_TEST_ERROR_CODE (!(condition), #condition, condition.message ().c_str (), "", \
	GTEST_FATAL_FAILURE_)

/** Extends gtest with a std::error_code assert that expects an error */
#define ASSERT_IS_ERROR(condition)                                                            \
	GTEST_TEST_ERROR_CODE ((condition.value () > 0), #condition, "An error was expected", "", \
	GTEST_FATAL_FAILURE_)

/* Convenience globals for core_test */
namespace nano
{
using uint128_t = boost::multiprecision::uint128_t;
class keypair;
union uint256_union;
extern nano::keypair const & zero_key;
extern nano::keypair const & test_genesis_key;
extern std::string const & nano_test_genesis;
extern std::string const & genesis_block;
extern nano::uint256_union const & nano_test_account;
extern nano::uint256_union const & genesis_account;
extern nano::uint256_union const & burn_account;
extern nano::uint128_t const & genesis_amount;

class stringstream_mt_sink : public boost::iostreams::sink
{
public:
	stringstream_mt_sink () = default;
	stringstream_mt_sink (const stringstream_mt_sink & sink)
	{
		std::lock_guard<std::mutex> guard (mutex);
		ss << sink.ss.str ();
	}

	std::streamsize write (const char * string_to_write, std::streamsize size)
	{
		std::lock_guard<std::mutex> guard (mutex);
		ss << std::string (string_to_write, size);
		return size;
	}

	std::string str ()
	{
		std::lock_guard<std::mutex> guard (mutex);
		return ss.str ();
	}

private:
	mutable std::mutex mutex;
	std::stringstream ss;
};

class boost_log_cerr_redirect
{
public:
	boost_log_cerr_redirect (std::streambuf * new_buffer) :
	old (std::cerr.rdbuf (new_buffer))
	{
		console_sink = (boost::log::add_console_log (std::cerr, boost::log::keywords::format = "%Message%"));
	}

	~boost_log_cerr_redirect ()
	{
		std::cerr.rdbuf (old);
		boost::log::core::get ()->remove_sink (console_sink);
	}

private:
	std::streambuf * old;
	boost::shared_ptr<boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend>> console_sink;
};

namespace util
{
	/**
	 * Helper to signal completion of async handlers in tests.
	 * Subclasses implement specific conditions for completion.
	 */
	class completion_signal
	{
	public:
		virtual ~completion_signal ()
		{
			notify ();
		}

		/** Explicitly notify the completion */
		void notify ()
		{
			cv.notify_all ();
		}

	protected:
		std::condition_variable cv;
		std::mutex mutex;
	};

	/**
	 * Signals completion when a count is reached.
	 */
	class counted_completion : public completion_signal
	{
	public:
		/**
		 * Constructor
		 * @param required_count_a When increment() reaches this count within the deadline, await_count_for() will return false.
		 */
		counted_completion (unsigned required_count_a) :
		required_count (required_count_a)
		{
		}

		/**
		 * Wait for increment() to signal completion, or reaching the deadline.
		 * @param deadline_duration_a Deadline as a std::chrono duration
		 * @return true if the count is reached within the deadline
		 */
		template <typename UNIT>
		bool await_count_for (UNIT deadline_duration_a)
		{
			nano::timer<UNIT> timer (nano::timer_state::started);
			bool error = true;
			while (error && timer.before_deadline (deadline_duration_a))
			{
				error = count < required_count;
				if (error)
				{
					std::unique_lock<std::mutex> lock (mutex);
					cv.wait_for (lock, std::chrono::milliseconds (1));
				}
			}
			return error;
		}

		/** Increments the current count. If the required count is reached, await_count_for() waiters are notified. */
		unsigned increment ()
		{
			auto val (count.fetch_add (1));
			if (val >= required_count)
			{
				notify ();
			}
			return val;
		}

	private:
		std::atomic<unsigned> count{ 0 };
		unsigned required_count;
	};
}
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <istream>

// template<class charT, class traits>
//   basic_istream<charT,traits>& operator>>(basic_istream<charT,traits>&& in, charT& c);

#include <istream>
#include <cassert>

template <class CharT>
struct testbuf
    : public std::basic_streambuf<CharT>
{
    typedef std::basic_string<CharT> string_type;
    typedef std::basic_streambuf<CharT> base;
private:
    string_type str_;
public:

    testbuf() {}
    testbuf(const string_type& str)
        : str_(str)
    {
        base::setg(const_cast<CharT*>(str_.data()),
                   const_cast<CharT*>(str_.data()),
                   const_cast<CharT*>(str_.data()) + str_.size());
    }

    CharT* eback() const {return base::eback();}
    CharT* gptr() const {return base::gptr();}
    CharT* egptr() const {return base::egptr();}
};

int main()
{
    {
        testbuf<char> sb("          ");
        std::istream is(&sb);
        char c = 'z';
        is >> c;
        assert( is.eof());
        assert( is.fail());
        assert(c == 'z');
    }
    {
        testbuf<char> sb("   abcdefghijk    ");
        std::istream is(&sb);
        char c;
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == 'a');
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == 'b');
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == 'c');
    }
    {
        testbuf<wchar_t> sb(L"   abc");
        std::wistream is(&sb);
        wchar_t c;
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == L'a');
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == L'b');
        is >> c;
        assert( is.eof());
        assert(!is.fail());
        assert(c == L'c');
    }
}
<commit_msg>Fix test bug.<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <istream>

// template<class charT, class traits>
//   basic_istream<charT,traits>& operator>>(basic_istream<charT,traits>&& in, charT& c);

#include <istream>
#include <cassert>

template <class CharT>
struct testbuf
    : public std::basic_streambuf<CharT>
{
    typedef std::basic_string<CharT> string_type;
    typedef std::basic_streambuf<CharT> base;
private:
    string_type str_;
public:

    testbuf() {}
    testbuf(const string_type& str)
        : str_(str)
    {
        base::setg(const_cast<CharT*>(str_.data()),
                   const_cast<CharT*>(str_.data()),
                   const_cast<CharT*>(str_.data()) + str_.size());
    }

    CharT* eback() const {return base::eback();}
    CharT* gptr() const {return base::gptr();}
    CharT* egptr() const {return base::egptr();}
};

int main()
{
    {
        testbuf<char> sb("          ");
        std::istream is(&sb);
        char c = 'z';
        is >> c;
        assert( is.eof());
        assert( is.fail());
        assert(c == 'z');
    }
    {
        testbuf<char> sb("   abcdefghijk    ");
        std::istream is(&sb);
        char c;
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == 'a');
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == 'b');
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == 'c');
    }
    {
        testbuf<wchar_t> sb(L"   abc");
        std::wistream is(&sb);
        wchar_t c;
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == L'a');
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == L'b');
        is >> c;
        assert(!is.eof());
        assert(!is.fail());
        assert(c == L'c');
    }
}
<|endoftext|>