<commit_before>//===- Symbols.cpp --------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Symbols.h"
#include "InputFiles.h"
#include "InputSection.h"
#include "OutputSections.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "Writer.h"

#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Path.h"
#include <cstring>

using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF;

using namespace lld;
using namespace lld::elf;

Defined *ElfSym::Bss;
Defined *ElfSym::Etext1;
Defined *ElfSym::Etext2;
Defined *ElfSym::Edata1;
Defined *ElfSym::Edata2;
Defined *ElfSym::End1;
Defined *ElfSym::End2;
Defined *ElfSym::GlobalOffsetTable;
Defined *ElfSym::MipsGp;
Defined *ElfSym::MipsGpDisp;
Defined *ElfSym::MipsLocalGp;

static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
  switch (Sym.kind()) {
  case Symbol::DefinedKind: {
    auto &D = cast<Defined>(Sym);
    SectionBase *IS = D.Section;
    if (auto *ISB = dyn_cast_or_null<InputSectionBase>(IS))
      IS = ISB->Repl;

    // According to the ELF spec reference to a local symbol from outside
    // the group are not allowed. Unfortunately .eh_frame breaks that rule
    // and must be treated specially. For now we just replace the symbol with
    // 0.
    if (IS == &InputSection::Discarded)
      return 0;

    // This is an absolute symbol.
    if (!IS)
      return D.Value;

    uint64_t Offset = D.Value;

    // An object in an SHF_MERGE section might be referenced via a
    // section symbol (as a hack for reducing the number of local
    // symbols).
    // Depending on the addend, the reference via a section symbol
    // refers to a different object in the merge section.
    // Since the objects in the merge section are not necessarily
    // contiguous in the output, the addend can thus affect the final
    // VA in a non-linear way.
    // To make this work, we incorporate the addend into the section
    // offset (and zero out the addend for later processing) so that
    // we find the right object in the section.
    if (D.isSection()) {
      Offset += Addend;
      Addend = 0;
    }

    const OutputSection *OutSec = IS->getOutputSection();

    // In the typical case, this is actually very simple and boils
    // down to adding together 3 numbers:
    // 1. The address of the output section.
    // 2. The offset of the input section within the output section.
    // 3. The offset within the input section (this addition happens
    //    inside InputSection::getOffset).
    //
    // If you understand the data structures involved with this next
    // line (and how they get built), then you have a pretty good
    // understanding of the linker.
    uint64_t VA = (OutSec ? OutSec->Addr : 0) + IS->getOffset(Offset);

    if (D.isTls() && !Config->Relocatable) {
      if (!Out::TlsPhdr)
        fatal(toString(D.File) +
              " has an STT_TLS symbol but doesn't have an SHF_TLS section");
      return VA - Out::TlsPhdr->p_vaddr;
    }
    return VA;
  }
  case Symbol::SharedKind: {
    auto &SS = cast<SharedSymbol>(Sym);
    if (SS.CopyRelSec)
      return SS.CopyRelSec->getParent()->Addr + SS.CopyRelSec->OutSecOff;
    if (SS.NeedsPltAddr)
      return Sym.getPltVA();
    return 0;
  }
  case Symbol::UndefinedKind:
    return 0;
  case Symbol::LazyArchiveKind:
  case Symbol::LazyObjectKind:
    assert(Sym.IsUsedInRegularObj && "lazy symbol reached writer");
    return 0;
  }
  llvm_unreachable("invalid symbol kind");
}

// Returns true if this is a weak undefined symbol.
bool Symbol::isUndefWeak() const {
  // See comment on Lazy in Symbols.h for the details.
  return !isLocal() && isWeak() && (isUndefined() || isLazy());
}

uint64_t Symbol::getVA(int64_t Addend) const {
  uint64_t OutVA = getSymVA(*this, Addend);
  return OutVA + Addend;
}

uint64_t Symbol::getGotVA() const { return InX::Got->getVA() + getGotOffset(); }

uint64_t Symbol::getGotOffset() const {
  return GotIndex * Target->GotEntrySize;
}

uint64_t Symbol::getGotPltVA() const {
  if (this->IsInIgot)
    return InX::IgotPlt->getVA() + getGotPltOffset();
  return InX::GotPlt->getVA() + getGotPltOffset();
}

uint64_t Symbol::getGotPltOffset() const {
  return GotPltIndex * Target->GotPltEntrySize;
}

uint64_t Symbol::getPltVA() const {
  if (this->IsInIplt)
    return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize;
  return InX::Plt->getVA() + Target->PltHeaderSize +
         PltIndex * Target->PltEntrySize;
}

uint64_t Symbol::getSize() const {
  if (const auto *DR = dyn_cast<Defined>(this))
    return DR->Size;
  if (const auto *S = dyn_cast<SharedSymbol>(this))
    return S->Size;
  return 0;
}

OutputSection *Symbol::getOutputSection() const {
  if (auto *S = dyn_cast<Defined>(this)) {
    if (S->Section)
      return S->Section->getOutputSection();
    return nullptr;
  }

  if (auto *S = dyn_cast<SharedSymbol>(this)) {
    if (S->CopyRelSec)
      return S->CopyRelSec->getParent();
    return nullptr;
  }

  return nullptr;
}

// If a symbol name contains '@', the characters after that is
// a symbol version name. This function parses that.
void Symbol::parseSymbolVersion() {
  StringRef S = getName();
  size_t Pos = S.find('@');
  if (Pos == 0 || Pos == StringRef::npos)
    return;
  StringRef Verstr = S.substr(Pos + 1);
  if (Verstr.empty())
    return;

  // Truncate the symbol name so that it doesn't include the version string.
  Name = {S.data(), Pos};

  // If this is not in this DSO, it is not a definition.
  if (!isDefined())
    return;

  // '@@' in a symbol name means the default version.
  // It is usually the most recent one.
  bool IsDefault = (Verstr[0] == '@');
  if (IsDefault)
    Verstr = Verstr.substr(1);

  for (VersionDefinition &Ver : Config->VersionDefinitions) {
    if (Ver.Name != Verstr)
      continue;

    if (IsDefault)
      VersionId = Ver.Id;
    else
      VersionId = Ver.Id | VERSYM_HIDDEN;
    return;
  }

  // It is an error if the specified version is not defined.
  // Usually version script is not provided when linking executable,
  // but we may still want to override a versioned symbol from DSO,
  // so we do not report error in this case.
  if (Config->Shared)
    error(toString(File) + ": symbol " + S + " has undefined version " +
          Verstr);
}

InputFile *Lazy::fetch() {
  if (auto *S = dyn_cast<LazyArchive>(this))
    return S->fetch();
  return cast<LazyObject>(this)->fetch();
}

ArchiveFile *LazyArchive::getFile() { return cast<ArchiveFile>(File); }

InputFile *LazyArchive::fetch() {
  std::pair<MemoryBufferRef, uint64_t> MBInfo = getFile()->getMember(&Sym);

  // getMember returns an empty buffer if the member was already
  // read from the library.
  if (MBInfo.first.getBuffer().empty())
    return nullptr;
  return createObjectFile(MBInfo.first, getFile()->getName(), MBInfo.second);
}

LazyObjFile *LazyObject::getFile() { return cast<LazyObjFile>(File); }

InputFile *LazyObject::fetch() { return getFile()->fetch(); }

uint8_t Symbol::computeBinding() const {
  if (Config->Relocatable)
    return Binding;
  if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
    return STB_LOCAL;
  if (VersionId == VER_NDX_LOCAL && isDefined())
    return STB_LOCAL;
  if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE)
    return STB_GLOBAL;
  return Binding;
}

bool Symbol::includeInDynsym() const {
  if (!Config->HasDynSymTab)
    return false;
  if (computeBinding() == STB_LOCAL)
    return false;
  if (!isDefined())
    return true;
  return ExportDynamic;
}

// Print out a log message for --trace-symbol.
void elf::printTraceSymbol(Symbol *Sym) {
  std::string S;
  if (Sym->isUndefined())
    S = ": reference to ";
  else if (Sym->isLazy())
    S = ": lazy definition of ";
  else if (Sym->isShared())
    S = ": shared definition of ";
  else if (dyn_cast_or_null<BssSection>(cast<Defined>(Sym)->Section))
    S = ": common definition of ";
  else
    S = ": definition of ";

  message(toString(Sym->File) + S + Sym->getName());
}

// Returns a symbol for an error message.
std::string lld::toString(const Symbol &B) {
  if (Config->Demangle)
    if (Optional<std::string> S = demangleItanium(B.getName()))
      return *S;
  return B.getName();
}
<commit_msg>Remove unused condition.<commit_after>//===- Symbols.cpp --------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Symbols.h"
#include "InputFiles.h"
#include "InputSection.h"
#include "OutputSections.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "Writer.h"

#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Path.h"
#include <cstring>

using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF;

using namespace lld;
using namespace lld::elf;

Defined *ElfSym::Bss;
Defined *ElfSym::Etext1;
Defined *ElfSym::Etext2;
Defined *ElfSym::Edata1;
Defined *ElfSym::Edata2;
Defined *ElfSym::End1;
Defined *ElfSym::End2;
Defined *ElfSym::GlobalOffsetTable;
Defined *ElfSym::MipsGp;
Defined *ElfSym::MipsGpDisp;
Defined *ElfSym::MipsLocalGp;

static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
  switch (Sym.kind()) {
  case Symbol::DefinedKind: {
    auto &D = cast<Defined>(Sym);
    SectionBase *IS = D.Section;
    if (auto *ISB = dyn_cast_or_null<InputSectionBase>(IS))
      IS = ISB->Repl;

    // According to the ELF spec reference to a local symbol from outside
    // the group are not allowed. Unfortunately .eh_frame breaks that rule
    // and must be treated specially. For now we just replace the symbol with
    // 0.
    if (IS == &InputSection::Discarded)
      return 0;

    // This is an absolute symbol.
    if (!IS)
      return D.Value;

    uint64_t Offset = D.Value;

    // An object in an SHF_MERGE section might be referenced via a
    // section symbol (as a hack for reducing the number of local
    // symbols).
    // Depending on the addend, the reference via a section symbol
    // refers to a different object in the merge section.
    // Since the objects in the merge section are not necessarily
    // contiguous in the output, the addend can thus affect the final
    // VA in a non-linear way.
    // To make this work, we incorporate the addend into the section
    // offset (and zero out the addend for later processing) so that
    // we find the right object in the section.
    if (D.isSection()) {
      Offset += Addend;
      Addend = 0;
    }

    const OutputSection *OutSec = IS->getOutputSection();

    // In the typical case, this is actually very simple and boils
    // down to adding together 3 numbers:
    // 1. The address of the output section.
    // 2. The offset of the input section within the output section.
    // 3. The offset within the input section (this addition happens
    //    inside InputSection::getOffset).
    //
    // If you understand the data structures involved with this next
    // line (and how they get built), then you have a pretty good
    // understanding of the linker.
    uint64_t VA = (OutSec ? OutSec->Addr : 0) + IS->getOffset(Offset);

    if (D.isTls() && !Config->Relocatable) {
      if (!Out::TlsPhdr)
        fatal(toString(D.File) +
              " has an STT_TLS symbol but doesn't have an SHF_TLS section");
      return VA - Out::TlsPhdr->p_vaddr;
    }
    return VA;
  }
  case Symbol::SharedKind: {
    auto &SS = cast<SharedSymbol>(Sym);
    if (SS.CopyRelSec)
      return SS.CopyRelSec->getParent()->Addr + SS.CopyRelSec->OutSecOff;
    if (SS.NeedsPltAddr)
      return Sym.getPltVA();
    return 0;
  }
  case Symbol::UndefinedKind:
    return 0;
  case Symbol::LazyArchiveKind:
  case Symbol::LazyObjectKind:
    assert(Sym.IsUsedInRegularObj && "lazy symbol reached writer");
    return 0;
  }
  llvm_unreachable("invalid symbol kind");
}

// Returns true if this is a weak undefined symbol.
bool Symbol::isUndefWeak() const {
  // See comment on Lazy in Symbols.h for the details.
  return isWeak() && (isUndefined() || isLazy());
}

uint64_t Symbol::getVA(int64_t Addend) const {
  uint64_t OutVA = getSymVA(*this, Addend);
  return OutVA + Addend;
}

uint64_t Symbol::getGotVA() const { return InX::Got->getVA() + getGotOffset(); }

uint64_t Symbol::getGotOffset() const {
  return GotIndex * Target->GotEntrySize;
}

uint64_t Symbol::getGotPltVA() const {
  if (this->IsInIgot)
    return InX::IgotPlt->getVA() + getGotPltOffset();
  return InX::GotPlt->getVA() + getGotPltOffset();
}

uint64_t Symbol::getGotPltOffset() const {
  return GotPltIndex * Target->GotPltEntrySize;
}

uint64_t Symbol::getPltVA() const {
  if (this->IsInIplt)
    return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize;
  return InX::Plt->getVA() + Target->PltHeaderSize +
         PltIndex * Target->PltEntrySize;
}

uint64_t Symbol::getSize() const {
  if (const auto *DR = dyn_cast<Defined>(this))
    return DR->Size;
  if (const auto *S = dyn_cast<SharedSymbol>(this))
    return S->Size;
  return 0;
}

OutputSection *Symbol::getOutputSection() const {
  if (auto *S = dyn_cast<Defined>(this)) {
    if (S->Section)
      return S->Section->getOutputSection();
    return nullptr;
  }

  if (auto *S = dyn_cast<SharedSymbol>(this)) {
    if (S->CopyRelSec)
      return S->CopyRelSec->getParent();
    return nullptr;
  }

  return nullptr;
}

// If a symbol name contains '@', the characters after that is
// a symbol version name. This function parses that.
void Symbol::parseSymbolVersion() {
  StringRef S = getName();
  size_t Pos = S.find('@');
  if (Pos == 0 || Pos == StringRef::npos)
    return;
  StringRef Verstr = S.substr(Pos + 1);
  if (Verstr.empty())
    return;

  // Truncate the symbol name so that it doesn't include the version string.
  Name = {S.data(), Pos};

  // If this is not in this DSO, it is not a definition.
  if (!isDefined())
    return;

  // '@@' in a symbol name means the default version.
  // It is usually the most recent one.
  bool IsDefault = (Verstr[0] == '@');
  if (IsDefault)
    Verstr = Verstr.substr(1);

  for (VersionDefinition &Ver : Config->VersionDefinitions) {
    if (Ver.Name != Verstr)
      continue;

    if (IsDefault)
      VersionId = Ver.Id;
    else
      VersionId = Ver.Id | VERSYM_HIDDEN;
    return;
  }

  // It is an error if the specified version is not defined.
  // Usually version script is not provided when linking executable,
  // but we may still want to override a versioned symbol from DSO,
  // so we do not report error in this case.
  if (Config->Shared)
    error(toString(File) + ": symbol " + S + " has undefined version " +
          Verstr);
}

InputFile *Lazy::fetch() {
  if (auto *S = dyn_cast<LazyArchive>(this))
    return S->fetch();
  return cast<LazyObject>(this)->fetch();
}

ArchiveFile *LazyArchive::getFile() { return cast<ArchiveFile>(File); }

InputFile *LazyArchive::fetch() {
  std::pair<MemoryBufferRef, uint64_t> MBInfo = getFile()->getMember(&Sym);

  // getMember returns an empty buffer if the member was already
  // read from the library.
  if (MBInfo.first.getBuffer().empty())
    return nullptr;
  return createObjectFile(MBInfo.first, getFile()->getName(), MBInfo.second);
}

LazyObjFile *LazyObject::getFile() { return cast<LazyObjFile>(File); }

InputFile *LazyObject::fetch() { return getFile()->fetch(); }

uint8_t Symbol::computeBinding() const {
  if (Config->Relocatable)
    return Binding;
  if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
    return STB_LOCAL;
  if (VersionId == VER_NDX_LOCAL && isDefined())
    return STB_LOCAL;
  if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE)
    return STB_GLOBAL;
  return Binding;
}

bool Symbol::includeInDynsym() const {
  if (!Config->HasDynSymTab)
    return false;
  if (computeBinding() == STB_LOCAL)
    return false;
  if (!isDefined())
    return true;
  return ExportDynamic;
}

// Print out a log message for --trace-symbol.
void elf::printTraceSymbol(Symbol *Sym) {
  std::string S;
  if (Sym->isUndefined())
    S = ": reference to ";
  else if (Sym->isLazy())
    S = ": lazy definition of ";
  else if (Sym->isShared())
    S = ": shared definition of ";
  else if (dyn_cast_or_null<BssSection>(cast<Defined>(Sym)->Section))
    S = ": common definition of ";
  else
    S = ": definition of ";

  message(toString(Sym->File) + S + Sym->getName());
}

// Returns a symbol for an error message.
std::string lld::toString(const Symbol &B) {
  if (Config->Demangle)
    if (Optional<std::string> S = demangleItanium(B.getName()))
      return *S;
  return B.getName();
}
<|endoftext|>


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

// Standard C++ library includes

// 3rd party library includes
#include <cegui-0/CEGUI/CEGUI.h>

// FIFE includes
// These includes are split up in two parts, separated by one empty line
// First block: files included from the FIFE root src directory
// Second block: files included from the same folder

#include "ceguiinputprocessor.h"

namespace FIFE {
	CEGuiInputProcessor::CEGuiInputProcessor() {
		initializeKeyMap();
	}

	CEGuiInputProcessor::~CEGuiInputProcessor() {
	}

	bool CEGuiInputProcessor::onSdlEvent(SDL_Event& event) {
		bool consumed = false;

		switch(event.type) {

			case SDL_KEYUP:
			case SDL_KEYDOWN:
				consumed = processKeyInput(event);
				break;

			case SDL_TEXTINPUT:
				consumed = processTextInput(event);
				break;

			case SDL_MOUSEWHEEL:
			case SDL_MOUSEBUTTONUP:
			case SDL_MOUSEBUTTONDOWN:
				consumed = processMouseInput(event);
				break;

			case SDL_MOUSEMOTION:
				consumed = processMouseMotion(event);
				break;

			default:
				;
		}

		return consumed;
	}

	bool CEGuiInputProcessor::processKeyInput(SDL_Event& event) {
		bool consumed = false;

		switch(event.type) {
			case SDL_KEYDOWN:
				if (m_keymap.find(event.key.keysym.sym) != m_keymap.end())
					consumed |= CEGUI::System::getSingleton().getDefaultGUIContext().injectKeyDown(m_keymap[event.key.keysym.sym]);
				break;

			case SDL_KEYUP:
				if (m_keymap.find(event.key.keysym.sym) != m_keymap.end())
					consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectKeyUp(m_keymap[event.key.keysym.sym]);
				break;

			default:
				;
		}

		return consumed;
	}

	bool CEGuiInputProcessor::processTextInput(SDL_Event& event) {
		CEGUI::String character(event.text.text);
		bool consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectChar(character[0]);

		return consumed;
	}

	bool CEGuiInputProcessor::processMouseInput(SDL_Event& event) {
		bool consumed = false;

		switch(event.type) {
			case SDL_MOUSEBUTTONDOWN:
			{
				switch(event.button.button) {
					case SDL_BUTTON_LEFT:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(CEGUI::LeftButton);
						break;

					case SDL_BUTTON_RIGHT:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(CEGUI::RightButton);
						break;

					case SDL_BUTTON_MIDDLE:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(CEGUI::MiddleButton) ;
						break;

					default:
						;
				}
				break;
			}

			case SDL_MOUSEBUTTONUP:
			{
				switch(event.button.button) {
					case SDL_BUTTON_LEFT:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(CEGUI::LeftButton);
						break;

					case SDL_BUTTON_RIGHT:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(CEGUI::RightButton);
						break;

					case SDL_BUTTON_MIDDLE:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(CEGUI::MiddleButton) ;
						break;

					default:
						;
				}
				break;
			}

			case SDL_MOUSEWHEEL:
			{
				// mousewheel up or down
				int32_t wheelChange = event.wheel.y;
				if (wheelChange != 0) {
					/*if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
						wheelChange *= -1;
					}*/
					consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseWheelChange(wheelChange);
				}
				break;
			}

			default:
				;
		}

		return consumed;
	}

	bool CEGuiInputProcessor::processMouseMotion(SDL_Event& event) {
	    return CEGUI::System::getSingleton().getDefaultGUIContext().injectMousePosition(static_cast<float>(event.motion.x), static_cast<float>(event.motion.y));
	}

	void CEGuiInputProcessor::initializeKeyMap() {
		m_keymap[SDLK_1] = CEGUI::Key::One;
		m_keymap[SDLK_2] = CEGUI::Key::Two;
		m_keymap[SDLK_3] = CEGUI::Key::Three;
		m_keymap[SDLK_4] = CEGUI::Key::Four;
		m_keymap[SDLK_5] = CEGUI::Key::Five;
		m_keymap[SDLK_6] = CEGUI::Key::Six;
		m_keymap[SDLK_7] = CEGUI::Key::Seven;
		m_keymap[SDLK_8] = CEGUI::Key::Eight;
		m_keymap[SDLK_9] = CEGUI::Key::Nine;
		m_keymap[SDLK_0] = CEGUI::Key::Zero;

		m_keymap[SDLK_q] = CEGUI::Key::Q;
		m_keymap[SDLK_w] = CEGUI::Key::W;
		m_keymap[SDLK_e] = CEGUI::Key::E;
		m_keymap[SDLK_r] = CEGUI::Key::R;
		m_keymap[SDLK_t] = CEGUI::Key::T;
		m_keymap[SDLK_y] = CEGUI::Key::Y;
		m_keymap[SDLK_u] = CEGUI::Key::U;
		m_keymap[SDLK_i] = CEGUI::Key::I;
		m_keymap[SDLK_o] = CEGUI::Key::O;
		m_keymap[SDLK_p] = CEGUI::Key::P;
		m_keymap[SDLK_a] = CEGUI::Key::A;
		m_keymap[SDLK_s] = CEGUI::Key::S;
		m_keymap[SDLK_d] = CEGUI::Key::D;
		m_keymap[SDLK_f] = CEGUI::Key::F;
		m_keymap[SDLK_g] = CEGUI::Key::G;
		m_keymap[SDLK_h] = CEGUI::Key::H;
		m_keymap[SDLK_j] = CEGUI::Key::J;
		m_keymap[SDLK_k] = CEGUI::Key::K;
		m_keymap[SDLK_l] = CEGUI::Key::L;
		m_keymap[SDLK_z] = CEGUI::Key::Z;
		m_keymap[SDLK_x] = CEGUI::Key::X;
		m_keymap[SDLK_c] = CEGUI::Key::C;
		m_keymap[SDLK_v] = CEGUI::Key::V;
		m_keymap[SDLK_b] = CEGUI::Key::B;
		m_keymap[SDLK_n] = CEGUI::Key::N;
		m_keymap[SDLK_m] = CEGUI::Key::M;

		m_keymap[SDLK_COMMA] = CEGUI::Key::Comma;
		m_keymap[SDLK_PERIOD] = CEGUI::Key::Period;
		m_keymap[SDLK_SLASH] = CEGUI::Key::Slash;
		m_keymap[SDLK_BACKSLASH] = CEGUI::Key::Backslash;
		m_keymap[SDLK_MINUS] = CEGUI::Key::Minus;
		m_keymap[SDLK_EQUALS] = CEGUI::Key::Equals;
		m_keymap[SDLK_SEMICOLON] = CEGUI::Key::Semicolon;
		m_keymap[SDLK_LEFTBRACKET] = CEGUI::Key::LeftBracket;
		m_keymap[SDLK_RIGHTBRACKET] = CEGUI::Key::RightBracket;
		m_keymap[SDLK_QUOTE] = CEGUI::Key::Apostrophe;
		m_keymap[SDLK_BACKQUOTE] = CEGUI::Key::Grave;

		m_keymap[SDLK_RETURN] = CEGUI::Key::Return;
		m_keymap[SDLK_SPACE] = CEGUI::Key::Space;
		m_keymap[SDLK_BACKSPACE] = CEGUI::Key::Backspace;
		m_keymap[SDLK_TAB] = CEGUI::Key::Tab;

		m_keymap[SDLK_ESCAPE] = CEGUI::Key::Escape;
		m_keymap[SDLK_PAUSE] = CEGUI::Key::Pause;
		m_keymap[SDLK_SYSREQ] = CEGUI::Key::SysRq;
		m_keymap[SDLK_POWER] = CEGUI::Key::Power;

		m_keymap[SDLK_NUMLOCKCLEAR] = CEGUI::Key::NumLock;
		m_keymap[SDLK_SCROLLLOCK] = CEGUI::Key::ScrollLock;

		m_keymap[SDLK_F1] = CEGUI::Key::F1;
		m_keymap[SDLK_F2] = CEGUI::Key::F2;
		m_keymap[SDLK_F3] = CEGUI::Key::F3;
		m_keymap[SDLK_F4] = CEGUI::Key::F4;
		m_keymap[SDLK_F5] = CEGUI::Key::F5;
		m_keymap[SDLK_F6] = CEGUI::Key::F6;
		m_keymap[SDLK_F7] = CEGUI::Key::F7;
		m_keymap[SDLK_F8] = CEGUI::Key::F8;
		m_keymap[SDLK_F9] = CEGUI::Key::F9;
		m_keymap[SDLK_F10] = CEGUI::Key::F10;
		m_keymap[SDLK_F11] = CEGUI::Key::F11;
		m_keymap[SDLK_F12] = CEGUI::Key::F12;
		m_keymap[SDLK_F13] = CEGUI::Key::F13;
		m_keymap[SDLK_F14] = CEGUI::Key::F14;
		m_keymap[SDLK_F15] = CEGUI::Key::F15;

		m_keymap[SDLK_LCTRL] = CEGUI::Key::LeftControl;
		m_keymap[SDLK_LALT] = CEGUI::Key::LeftAlt;
		m_keymap[SDLK_LSHIFT] = CEGUI::Key::LeftShift;
		m_keymap[SDLK_LGUI] = CEGUI::Key::LeftWindows;
		m_keymap[SDLK_RCTRL] = CEGUI::Key::RightControl;
		m_keymap[SDLK_RALT] = CEGUI::Key::RightAlt;
		m_keymap[SDLK_RSHIFT] = CEGUI::Key::RightShift;
		m_keymap[SDLK_RGUI] = CEGUI::Key::RightWindows;
		m_keymap[SDLK_MENU] = CEGUI::Key::AppMenu;

		m_keymap[SDLK_KP_0] = CEGUI::Key::Numpad0;
		m_keymap[SDLK_KP_1] = CEGUI::Key::Numpad1;
		m_keymap[SDLK_KP_2] = CEGUI::Key::Numpad2;
		m_keymap[SDLK_KP_3] = CEGUI::Key::Numpad3;
		m_keymap[SDLK_KP_4] = CEGUI::Key::Numpad4;
		m_keymap[SDLK_KP_5] = CEGUI::Key::Numpad5;
		m_keymap[SDLK_KP_6] = CEGUI::Key::Numpad6;
		m_keymap[SDLK_KP_7] = CEGUI::Key::Numpad7;
		m_keymap[SDLK_KP_8] = CEGUI::Key::Numpad8;
		m_keymap[SDLK_KP_9] = CEGUI::Key::Numpad9;
		m_keymap[SDLK_KP_PERIOD] = CEGUI::Key::Decimal;
		m_keymap[SDLK_KP_PLUS] = CEGUI::Key::Add;
		m_keymap[SDLK_KP_MINUS] = CEGUI::Key::Subtract;
		m_keymap[SDLK_KP_MULTIPLY] = CEGUI::Key::Multiply;
		m_keymap[SDLK_KP_DIVIDE] = CEGUI::Key::Divide;
		m_keymap[SDLK_KP_ENTER] = CEGUI::Key::NumpadEnter;

		m_keymap[SDLK_UP] = CEGUI::Key::ArrowUp;
		m_keymap[SDLK_LEFT] = CEGUI::Key::ArrowLeft;
		m_keymap[SDLK_RIGHT] = CEGUI::Key::ArrowRight;
		m_keymap[SDLK_DOWN] = CEGUI::Key::ArrowDown;

		m_keymap[SDLK_HOME] = CEGUI::Key::Home;
		m_keymap[SDLK_END] = CEGUI::Key::End;
		m_keymap[SDLK_PAGEUP] = CEGUI::Key::PageUp;
		m_keymap[SDLK_PAGEDOWN] = CEGUI::Key::PageDown;
		m_keymap[SDLK_INSERT] = CEGUI::Key::Insert;
		m_keymap[SDLK_DELETE] = CEGUI::Key::Delete;
	}
}
<commit_msg>Map more SDL keys to CEGUI keys<commit_after>/***************************************************************************
 *   Copyright (C) 2005-2017 by the FIFE team                              *
 *   http://www.fifengine.net                                              *
 *   This file is part of FIFE.                                            *
 *                                                                         *
 *   FIFE is free software; you can redistribute it and/or                 *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 of the License, or (at your option) any later version.    *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
 ***************************************************************************/

// Standard C++ library includes

// 3rd party library includes
#include <cegui-0/CEGUI/CEGUI.h>

// FIFE includes
// These includes are split up in two parts, separated by one empty line
// First block: files included from the FIFE root src directory
// Second block: files included from the same folder

#include "ceguiinputprocessor.h"

namespace FIFE {
	CEGuiInputProcessor::CEGuiInputProcessor() {
		initializeKeyMap();
	}

	CEGuiInputProcessor::~CEGuiInputProcessor() {
	}

	bool CEGuiInputProcessor::onSdlEvent(SDL_Event& event) {
		bool consumed = false;

		switch(event.type) {

			case SDL_KEYUP:
			case SDL_KEYDOWN:
				consumed = processKeyInput(event);
				break;

			case SDL_TEXTINPUT:
				consumed = processTextInput(event);
				break;

			case SDL_MOUSEWHEEL:
			case SDL_MOUSEBUTTONUP:
			case SDL_MOUSEBUTTONDOWN:
				consumed = processMouseInput(event);
				break;

			case SDL_MOUSEMOTION:
				consumed = processMouseMotion(event);
				break;

			default:
				;
		}

		return consumed;
	}

	bool CEGuiInputProcessor::processKeyInput(SDL_Event& event) {
		bool consumed = false;

		switch(event.type) {
			case SDL_KEYDOWN:
				if (m_keymap.find(event.key.keysym.sym) != m_keymap.end())
					consumed |= CEGUI::System::getSingleton().getDefaultGUIContext().injectKeyDown(m_keymap[event.key.keysym.sym]);
				break;

			case SDL_KEYUP:
				if (m_keymap.find(event.key.keysym.sym) != m_keymap.end())
					consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectKeyUp(m_keymap[event.key.keysym.sym]);
				break;

			default:
				;
		}

		return consumed;
	}

	bool CEGuiInputProcessor::processTextInput(SDL_Event& event) {
		CEGUI::String character(event.text.text);
		bool consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectChar(character[0]);

		return consumed;
	}

	bool CEGuiInputProcessor::processMouseInput(SDL_Event& event) {
		bool consumed = false;

		switch(event.type) {
			case SDL_MOUSEBUTTONDOWN:
			{
				switch(event.button.button) {
					case SDL_BUTTON_LEFT:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(CEGUI::LeftButton);
						break;

					case SDL_BUTTON_RIGHT:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(CEGUI::RightButton);
						break;

					case SDL_BUTTON_MIDDLE:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(CEGUI::MiddleButton) ;
						break;

					default:
						;
				}
				break;
			}

			case SDL_MOUSEBUTTONUP:
			{
				switch(event.button.button) {
					case SDL_BUTTON_LEFT:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(CEGUI::LeftButton);
						break;

					case SDL_BUTTON_RIGHT:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(CEGUI::RightButton);
						break;

					case SDL_BUTTON_MIDDLE:
						consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(CEGUI::MiddleButton) ;
						break;

					default:
						;
				}
				break;
			}

			case SDL_MOUSEWHEEL:
			{
				// mousewheel up or down
				int32_t wheelChange = event.wheel.y;
				if (wheelChange != 0) {
					/*if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
						wheelChange *= -1;
					}*/
					consumed = CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseWheelChange(wheelChange);
				}
				break;
			}

			default:
				;
		}

		return consumed;
	}

	bool CEGuiInputProcessor::processMouseMotion(SDL_Event& event) {
	    return CEGUI::System::getSingleton().getDefaultGUIContext().injectMousePosition(static_cast<float>(event.motion.x), static_cast<float>(event.motion.y));
	}

	void CEGuiInputProcessor::initializeKeyMap() {
		m_keymap[SDLK_1] = CEGUI::Key::One;
		m_keymap[SDLK_2] = CEGUI::Key::Two;
		m_keymap[SDLK_3] = CEGUI::Key::Three;
		m_keymap[SDLK_4] = CEGUI::Key::Four;
		m_keymap[SDLK_5] = CEGUI::Key::Five;
		m_keymap[SDLK_6] = CEGUI::Key::Six;
		m_keymap[SDLK_7] = CEGUI::Key::Seven;
		m_keymap[SDLK_8] = CEGUI::Key::Eight;
		m_keymap[SDLK_9] = CEGUI::Key::Nine;
		m_keymap[SDLK_0] = CEGUI::Key::Zero;

		m_keymap[SDLK_q] = CEGUI::Key::Q;
		m_keymap[SDLK_w] = CEGUI::Key::W;
		m_keymap[SDLK_e] = CEGUI::Key::E;
		m_keymap[SDLK_r] = CEGUI::Key::R;
		m_keymap[SDLK_t] = CEGUI::Key::T;
		m_keymap[SDLK_y] = CEGUI::Key::Y;
		m_keymap[SDLK_u] = CEGUI::Key::U;
		m_keymap[SDLK_i] = CEGUI::Key::I;
		m_keymap[SDLK_o] = CEGUI::Key::O;
		m_keymap[SDLK_p] = CEGUI::Key::P;
		m_keymap[SDLK_a] = CEGUI::Key::A;
		m_keymap[SDLK_s] = CEGUI::Key::S;
		m_keymap[SDLK_d] = CEGUI::Key::D;
		m_keymap[SDLK_f] = CEGUI::Key::F;
		m_keymap[SDLK_g] = CEGUI::Key::G;
		m_keymap[SDLK_h] = CEGUI::Key::H;
		m_keymap[SDLK_j] = CEGUI::Key::J;
		m_keymap[SDLK_k] = CEGUI::Key::K;
		m_keymap[SDLK_l] = CEGUI::Key::L;
		m_keymap[SDLK_z] = CEGUI::Key::Z;
		m_keymap[SDLK_x] = CEGUI::Key::X;
		m_keymap[SDLK_c] = CEGUI::Key::C;
		m_keymap[SDLK_v] = CEGUI::Key::V;
		m_keymap[SDLK_b] = CEGUI::Key::B;
		m_keymap[SDLK_n] = CEGUI::Key::N;
		m_keymap[SDLK_m] = CEGUI::Key::M;

		m_keymap[SDLK_COMMA] = CEGUI::Key::Comma;
		m_keymap[SDLK_PERIOD] = CEGUI::Key::Period;
		m_keymap[SDLK_SLASH] = CEGUI::Key::Slash;
		m_keymap[SDLK_BACKSLASH] = CEGUI::Key::Backslash;
		m_keymap[SDLK_MINUS] = CEGUI::Key::Minus;
		m_keymap[SDLK_EQUALS] = CEGUI::Key::Equals;
		m_keymap[SDLK_SEMICOLON] = CEGUI::Key::Semicolon;
		m_keymap[SDLK_COLON] = CEGUI::Key::Colon;
		m_keymap[SDLK_LEFTBRACKET] = CEGUI::Key::LeftBracket;
		m_keymap[SDLK_RIGHTBRACKET] = CEGUI::Key::RightBracket;
		m_keymap[SDLK_QUOTE] = CEGUI::Key::Apostrophe;
		m_keymap[SDLK_BACKQUOTE] = CEGUI::Key::Grave;
		m_keymap[SDLK_AT] = CEGUI::Key::At;
		m_keymap[SDLK_UNDERSCORE] = CEGUI::Key::Underline;

		m_keymap[SDLK_RETURN] = CEGUI::Key::Return;
		m_keymap[SDLK_SPACE] = CEGUI::Key::Space;
		m_keymap[SDLK_BACKSPACE] = CEGUI::Key::Backspace;
		m_keymap[SDLK_TAB] = CEGUI::Key::Tab;

		m_keymap[SDLK_ESCAPE] = CEGUI::Key::Escape;
		m_keymap[SDLK_PAUSE] = CEGUI::Key::Pause;
		m_keymap[SDLK_SYSREQ] = CEGUI::Key::SysRq;
		m_keymap[SDLK_POWER] = CEGUI::Key::Power;
		m_keymap[SDLK_SLEEP] = CEGUI::Key::Sleep;

		m_keymap[SDLK_CALCULATOR] = CEGUI::Key::Calculator;
		m_keymap[SDLK_MAIL] = CEGUI::Key::Mail;
		m_keymap[SDLK_COMPUTER] = CEGUI::Key::MyComputer;
		m_keymap[SDLK_MEDIASELECT] = CEGUI::Key::MediaSelect;
		m_keymap[SDLK_AC_STOP] = CEGUI::Key::Stop;

		m_keymap[SDLK_AUDIOPLAY] = CEGUI::Key::PlayPause;
		m_keymap[SDLK_AUDIOSTOP] = CEGUI::Key::MediaStop;
		m_keymap[SDLK_AUDIOPREV] = CEGUI::Key::PrevTrack;
		m_keymap[SDLK_AUDIONEXT] = CEGUI::Key::NextTrack;
		m_keymap[SDLK_AUDIOMUTE] = CEGUI::Key::Mute;
		m_keymap[SDLK_VOLUMEUP] = CEGUI::Key::VolumeUp;
		m_keymap[SDLK_VOLUMEDOWN] = CEGUI::Key::VolumeDown;

		m_keymap[SDLK_AC_BACK] = CEGUI::Key::WebBack;
		m_keymap[SDLK_AC_FORWARD] = CEGUI::Key::WebForward;
		m_keymap[SDLK_AC_HOME] = CEGUI::Key::WebHome;
		m_keymap[SDLK_AC_BOOKMARKS] = CEGUI::Key::WebFavorites;
		m_keymap[SDLK_AC_SEARCH] = CEGUI::Key::WebSearch;
		m_keymap[SDLK_AC_REFRESH] = CEGUI::Key::WebRefresh;
		m_keymap[SDLK_AC_STOP] = CEGUI::Key::WebStop;

		m_keymap[SDLK_NUMLOCKCLEAR] = CEGUI::Key::NumLock;
		m_keymap[SDLK_SCROLLLOCK] = CEGUI::Key::ScrollLock;
		m_keymap[SDLK_CAPSLOCK] = CEGUI::Key::Capital;

		m_keymap[SDLK_F1] = CEGUI::Key::F1;
		m_keymap[SDLK_F2] = CEGUI::Key::F2;
		m_keymap[SDLK_F3] = CEGUI::Key::F3;
		m_keymap[SDLK_F4] = CEGUI::Key::F4;
		m_keymap[SDLK_F5] = CEGUI::Key::F5;
		m_keymap[SDLK_F6] = CEGUI::Key::F6;
		m_keymap[SDLK_F7] = CEGUI::Key::F7;
		m_keymap[SDLK_F8] = CEGUI::Key::F8;
		m_keymap[SDLK_F9] = CEGUI::Key::F9;
		m_keymap[SDLK_F10] = CEGUI::Key::F10;
		m_keymap[SDLK_F11] = CEGUI::Key::F11;
		m_keymap[SDLK_F12] = CEGUI::Key::F12;
		m_keymap[SDLK_F13] = CEGUI::Key::F13;
		m_keymap[SDLK_F14] = CEGUI::Key::F14;
		m_keymap[SDLK_F15] = CEGUI::Key::F15;

		m_keymap[SDLK_LCTRL] = CEGUI::Key::LeftControl;
		m_keymap[SDLK_LALT] = CEGUI::Key::LeftAlt;
		m_keymap[SDLK_LSHIFT] = CEGUI::Key::LeftShift;
		m_keymap[SDLK_LGUI] = CEGUI::Key::LeftWindows;
		m_keymap[SDLK_RCTRL] = CEGUI::Key::RightControl;
		m_keymap[SDLK_RALT] = CEGUI::Key::RightAlt;
		m_keymap[SDLK_RSHIFT] = CEGUI::Key::RightShift;
		m_keymap[SDLK_RGUI] = CEGUI::Key::RightWindows;
		m_keymap[SDLK_MENU] = CEGUI::Key::AppMenu;

		m_keymap[SDLK_KP_0] = CEGUI::Key::Numpad0;
		m_keymap[SDLK_KP_1] = CEGUI::Key::Numpad1;
		m_keymap[SDLK_KP_2] = CEGUI::Key::Numpad2;
		m_keymap[SDLK_KP_3] = CEGUI::Key::Numpad3;
		m_keymap[SDLK_KP_4] = CEGUI::Key::Numpad4;
		m_keymap[SDLK_KP_5] = CEGUI::Key::Numpad5;
		m_keymap[SDLK_KP_6] = CEGUI::Key::Numpad6;
		m_keymap[SDLK_KP_7] = CEGUI::Key::Numpad7;
		m_keymap[SDLK_KP_8] = CEGUI::Key::Numpad8;
		m_keymap[SDLK_KP_9] = CEGUI::Key::Numpad9;
		m_keymap[SDLK_KP_PERIOD] = CEGUI::Key::Decimal;
		m_keymap[SDLK_KP_PLUS] = CEGUI::Key::Add;
		m_keymap[SDLK_KP_MINUS] = CEGUI::Key::Subtract;
		m_keymap[SDLK_KP_MULTIPLY] = CEGUI::Key::Multiply;
		m_keymap[SDLK_KP_DIVIDE] = CEGUI::Key::Divide;
		m_keymap[SDLK_KP_ENTER] = CEGUI::Key::NumpadEnter;
		m_keymap[SDLK_KP_COMMA] = CEGUI::Key::NumpadComma;
		m_keymap[SDLK_KP_EQUALS] = CEGUI::Key::NumpadEquals;

		m_keymap[SDLK_UP] = CEGUI::Key::ArrowUp;
		m_keymap[SDLK_LEFT] = CEGUI::Key::ArrowLeft;
		m_keymap[SDLK_RIGHT] = CEGUI::Key::ArrowRight;
		m_keymap[SDLK_DOWN] = CEGUI::Key::ArrowDown;

		m_keymap[SDLK_HOME] = CEGUI::Key::Home;
		m_keymap[SDLK_END] = CEGUI::Key::End;
		m_keymap[SDLK_PAGEUP] = CEGUI::Key::PageUp;
		m_keymap[SDLK_PAGEDOWN] = CEGUI::Key::PageDown;
		m_keymap[SDLK_INSERT] = CEGUI::Key::Insert;
		m_keymap[SDLK_DELETE] = CEGUI::Key::Delete;
	}
}
<|endoftext|>


<commit_before>// Copyright 2015-2018 Elviss Strazdins. All rights reserved.

#include "core/Setup.h"

#if defined(_WIN32) && OUZEL_COMPILE_OPENGL

#include <sstream>
#include <system_error>
#include "GL/glcorearb.h"
#include "GL/glext.h"
#include "GL/wglext.h"
#include "OGLRenderDeviceWin.hpp"
#include "core/Engine.hpp"
#include "core/Window.hpp"
#include "core/windows/NativeWindowWin.hpp"
#include "utils/Log.hpp"
#include "utils/Utils.hpp"

static constexpr LPCWSTR TEMP_WINDOW_CLASS_NAME = L"TempWindow";

static LRESULT CALLBACK windowProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc(window, msg, wParam, lParam);
}

namespace ouzel
{
    namespace graphics
    {
        class TempContext final
        {
        public:
            TempContext()
            {
                HINSTANCE instance = GetModuleHandleW(nullptr);
                if (!instance)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to get module handle");

                WNDCLASSW wc;
                wc.style = CS_OWNDC;
                wc.lpfnWndProc = windowProc;
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hInstance = instance;
                wc.hIcon = 0;
                wc.hCursor = 0;
                wc.hbrBackground = 0;
                wc.lpszMenuName = nullptr;
                wc.lpszClassName = TEMP_WINDOW_CLASS_NAME;

                windowClass = RegisterClassW(&wc);

                if (!windowClass)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to register window class");

                window = CreateWindowW(TEMP_WINDOW_CLASS_NAME, L"TempWindow", 0,
                                       CW_USEDEFAULT, CW_USEDEFAULT,
                                       CW_USEDEFAULT, CW_USEDEFAULT,
                                       0, 0, instance, 0);

                if (!window)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create window");

                deviceContext = GetDC(window);

                PIXELFORMATDESCRIPTOR pixelFormatDesc;
                pixelFormatDesc.nSize = sizeof(pixelFormatDesc);
                pixelFormatDesc.nVersion = 1;
                pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
                pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
                pixelFormatDesc.cColorBits = 24;
                pixelFormatDesc.cRedBits = 0;
                pixelFormatDesc.cRedShift = 0;
                pixelFormatDesc.cGreenBits = 0;
                pixelFormatDesc.cGreenShift = 0;
                pixelFormatDesc.cBlueBits = 0;
                pixelFormatDesc.cBlueShift = 0;
                pixelFormatDesc.cAlphaBits = 0;
                pixelFormatDesc.cAlphaShift = 0;
                pixelFormatDesc.cAccumBits = 0;
                pixelFormatDesc.cAccumRedBits = 0;
                pixelFormatDesc.cAccumGreenBits = 0;
                pixelFormatDesc.cAccumBlueBits = 0;
                pixelFormatDesc.cAccumAlphaBits = 0;
                pixelFormatDesc.cDepthBits = 0;
                pixelFormatDesc.cStencilBits = 0;
                pixelFormatDesc.cAuxBuffers = 0;
                pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
                pixelFormatDesc.bReserved = 0;
                pixelFormatDesc.dwLayerMask = 0;
                pixelFormatDesc.dwVisibleMask = 0;
                pixelFormatDesc.dwDamageMask = 0;

                int pixelFormat = ChoosePixelFormat(deviceContext, &pixelFormatDesc);

                if (!pixelFormat)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to choose pixel format");

                if (!SetPixelFormat(deviceContext, pixelFormat, &pixelFormatDesc))
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to set pixel format");

                renderContext = wglCreateContext(deviceContext);

                if (!renderContext)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create OpenGL context");

                if (!wglMakeCurrent(deviceContext, renderContext))
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to set current OpenGL context");
            }

            ~TempContext()
            {
                if (renderContext)
                {
                    wglMakeCurrent(deviceContext, nullptr);
                    wglDeleteContext(renderContext);
                }

                if (window)
                    DestroyWindow(window);

                if (windowClass)
                    UnregisterClassW(TEMP_WINDOW_CLASS_NAME, GetModuleHandleW(nullptr));
            }

        private:
            ATOM windowClass = 0;
            HWND window = 0;
            HDC deviceContext = 0;
            HGLRC renderContext = 0;
        };

        OGLRenderDeviceWin::OGLRenderDeviceWin(const std::function<void(const Event&)>& initCallback):
            OGLRenderDevice(initCallback)
        {
        }

        OGLRenderDeviceWin::~OGLRenderDeviceWin()
        {
            running = false;
            CommandBuffer commandBuffer;
            commandBuffer.pushCommand(std::unique_ptr<Command>(new PresentCommand()));
            submitCommandBuffer(std::move(commandBuffer));

            if (renderThread.joinable()) renderThread.join();

            if (renderContext)
            {
                wglMakeCurrent(deviceContext, nullptr);
                wglDeleteContext(renderContext);
            }
        }

        void OGLRenderDeviceWin::init(Window* newWindow,
                                      const Size2<uint32_t>& newSize,
                                      uint32_t newSampleCount,
                                      Texture::Filter newTextureFilter,
                                      uint32_t newMaxAnisotropy,
                                      bool newVerticalSync,
                                      bool newDepth,
                                      bool newStencil,
                                      bool newDebugRenderer)
        {
            TempContext tempContext;

            NativeWindowWin* windowWin = static_cast<NativeWindowWin*>(newWindow->getNativeWindow());

            deviceContext = GetDC(windowWin->getNativeWindow());
            if (!deviceContext)
                throw std::runtime_error("Failed to get window's device context");

            PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringProc = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGARBPROC>(wglGetProcAddress("wglGetExtensionsStringARB"));

            std::vector<std::string> extensions;

            if (wglGetExtensionsStringProc)
            {
                if (const char* extensionPtr = wglGetExtensionsStringProc(deviceContext))
                {
                    std::istringstream extensionStringStream(reinterpret_cast<const char*>(extensionPtr));

                    for (std::string extension; extensionStringStream >> extension;)
                        extensions.push_back(extension);

                    engine->log(Log::Level::ALL) << "Supported WGL extensions: " << extensions;
                }
            }

            PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatProc = nullptr;

            for (const std::string& extension : extensions)
            {
                if (extension == "WGL_ARB_pixel_format")
                    wglChoosePixelFormatProc = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
            }

            int pixelFormat = 0;

            PIXELFORMATDESCRIPTOR pixelFormatDesc;
            pixelFormatDesc.nSize = sizeof(pixelFormatDesc);
            pixelFormatDesc.nVersion = 1;
            pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED;
            pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
            pixelFormatDesc.cColorBits = 24;
            pixelFormatDesc.cRedBits = 0;
            pixelFormatDesc.cRedShift = 0;
            pixelFormatDesc.cGreenBits = 0;
            pixelFormatDesc.cGreenShift = 0;
            pixelFormatDesc.cBlueBits = 0;
            pixelFormatDesc.cBlueShift = 0;
            pixelFormatDesc.cAlphaBits = 0;
            pixelFormatDesc.cAlphaShift = 0;
            pixelFormatDesc.cAccumBits = 0;
            pixelFormatDesc.cAccumRedBits = 0;
            pixelFormatDesc.cAccumGreenBits = 0;
            pixelFormatDesc.cAccumBlueBits = 0;
            pixelFormatDesc.cAccumAlphaBits = 0;
            pixelFormatDesc.cDepthBits = newDepth ? 24 : 0;
            pixelFormatDesc.cStencilBits = 0;
            pixelFormatDesc.cAuxBuffers = 0;
            pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
            pixelFormatDesc.bReserved = 0;
            pixelFormatDesc.dwLayerMask = 0;
            pixelFormatDesc.dwVisibleMask = 0;
            pixelFormatDesc.dwDamageMask = 0;

            if (wglChoosePixelFormatProc)
            {
                const int attributeList[] =
                {
                    WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
                    WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
                    WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
                    WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
                    WGL_COLOR_BITS_ARB, 24,
                    WGL_ALPHA_BITS_ARB, 8,
                    WGL_DEPTH_BITS_ARB, newDepth ? 24 : 0,
                    WGL_STENCIL_BITS_ARB, newStencil ? 8 : 0,
                    WGL_SAMPLE_BUFFERS_ARB, newSampleCount > 0 ? 1 : 0,
                    WGL_SAMPLES_ARB, static_cast<int>(newSampleCount),
                    0,
                };

                UINT numFormats;

                if (!wglChoosePixelFormatProc(deviceContext, attributeList, nullptr, 1, &pixelFormat, &numFormats))
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to choose pixel format");
            }
            else
            {
                pixelFormat = ChoosePixelFormat(deviceContext, &pixelFormatDesc);
                if (!pixelFormat)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to choose pixel format");
            }

            if (!SetPixelFormat(deviceContext, pixelFormat, &pixelFormatDesc))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to set pixel format");

            PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsProc = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(wglGetProcAddress("wglCreateContextAttribsARB"));

            if (wglCreateContextAttribsProc)
            {
                for (int openGLVersion = 4; openGLVersion >= 2; --openGLVersion)
                {
                    std::vector<int> contextAttribs = {
                        WGL_CONTEXT_MAJOR_VERSION_ARB, openGLVersion,
                        WGL_CONTEXT_MINOR_VERSION_ARB, 0,
                    };

                    if (newDebugRenderer)
                    {
                        contextAttribs.push_back(WGL_CONTEXT_FLAGS_ARB);
                        contextAttribs.push_back(WGL_CONTEXT_DEBUG_BIT_ARB);
                    }

                    contextAttribs.push_back(0);

                    renderContext = wglCreateContextAttribsProc(deviceContext, 0, contextAttribs.data());

                    if (renderContext)
                    {
                        engine->log(Log::Level::INFO) << "OpenGL " << openGLVersion << " context created";
                        break;
                    }
                }
            }
            else
                renderContext = wglCreateContext(deviceContext);

            if (!renderContext)
                throw std::runtime_error("Failed to create OpenGL context");

            if (!wglMakeCurrent(deviceContext, renderContext))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to set current OpenGL context");

            OGLRenderDevice::init(newWindow,
                                  newSize,
                                  newSampleCount,
                                  newTextureFilter,
                                  newMaxAnisotropy,
                                  newVerticalSync,
                                  newDepth,
                                  newStencil,
                                  newDebugRenderer);

            if (!wglMakeCurrent(deviceContext, nullptr))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to unset OpenGL context");

            running = true;
            renderThread = std::thread(&OGLRenderDeviceWin::main, this);
        }

        void OGLRenderDeviceWin::present()
        {
            if (!SwapBuffers(deviceContext))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to swap buffers");
        }

        void OGLRenderDeviceWin::main()
        {
            setCurrentThreadName("Render");

            if (!wglMakeCurrent(deviceContext, renderContext))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to set current OpenGL context");

            while (running)
            {
                try
                {
                    process();
                }
                catch (const std::exception& e)
                {
                    engine->log(Log::Level::ERR) << e.what();
                }
            }
        }
    } // namespace graphics
} // namespace ouzel

#endif
<commit_msg>Check the WGL extensions also for wglCreateContextAttribsARB<commit_after>// Copyright 2015-2018 Elviss Strazdins. All rights reserved.

#include "core/Setup.h"

#if defined(_WIN32) && OUZEL_COMPILE_OPENGL

#include <sstream>
#include <system_error>
#include "GL/glcorearb.h"
#include "GL/glext.h"
#include "GL/wglext.h"
#include "OGLRenderDeviceWin.hpp"
#include "core/Engine.hpp"
#include "core/Window.hpp"
#include "core/windows/NativeWindowWin.hpp"
#include "utils/Log.hpp"
#include "utils/Utils.hpp"

static constexpr LPCWSTR TEMP_WINDOW_CLASS_NAME = L"TempWindow";

static LRESULT CALLBACK windowProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc(window, msg, wParam, lParam);
}

namespace ouzel
{
    namespace graphics
    {
        class TempContext final
        {
        public:
            TempContext()
            {
                HINSTANCE instance = GetModuleHandleW(nullptr);
                if (!instance)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to get module handle");

                WNDCLASSW wc;
                wc.style = CS_OWNDC;
                wc.lpfnWndProc = windowProc;
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hInstance = instance;
                wc.hIcon = 0;
                wc.hCursor = 0;
                wc.hbrBackground = 0;
                wc.lpszMenuName = nullptr;
                wc.lpszClassName = TEMP_WINDOW_CLASS_NAME;

                windowClass = RegisterClassW(&wc);

                if (!windowClass)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to register window class");

                window = CreateWindowW(TEMP_WINDOW_CLASS_NAME, L"TempWindow", 0,
                                       CW_USEDEFAULT, CW_USEDEFAULT,
                                       CW_USEDEFAULT, CW_USEDEFAULT,
                                       0, 0, instance, 0);

                if (!window)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create window");

                deviceContext = GetDC(window);

                PIXELFORMATDESCRIPTOR pixelFormatDesc;
                pixelFormatDesc.nSize = sizeof(pixelFormatDesc);
                pixelFormatDesc.nVersion = 1;
                pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
                pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
                pixelFormatDesc.cColorBits = 24;
                pixelFormatDesc.cRedBits = 0;
                pixelFormatDesc.cRedShift = 0;
                pixelFormatDesc.cGreenBits = 0;
                pixelFormatDesc.cGreenShift = 0;
                pixelFormatDesc.cBlueBits = 0;
                pixelFormatDesc.cBlueShift = 0;
                pixelFormatDesc.cAlphaBits = 0;
                pixelFormatDesc.cAlphaShift = 0;
                pixelFormatDesc.cAccumBits = 0;
                pixelFormatDesc.cAccumRedBits = 0;
                pixelFormatDesc.cAccumGreenBits = 0;
                pixelFormatDesc.cAccumBlueBits = 0;
                pixelFormatDesc.cAccumAlphaBits = 0;
                pixelFormatDesc.cDepthBits = 0;
                pixelFormatDesc.cStencilBits = 0;
                pixelFormatDesc.cAuxBuffers = 0;
                pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
                pixelFormatDesc.bReserved = 0;
                pixelFormatDesc.dwLayerMask = 0;
                pixelFormatDesc.dwVisibleMask = 0;
                pixelFormatDesc.dwDamageMask = 0;

                int pixelFormat = ChoosePixelFormat(deviceContext, &pixelFormatDesc);

                if (!pixelFormat)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to choose pixel format");

                if (!SetPixelFormat(deviceContext, pixelFormat, &pixelFormatDesc))
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to set pixel format");

                renderContext = wglCreateContext(deviceContext);

                if (!renderContext)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create OpenGL context");

                if (!wglMakeCurrent(deviceContext, renderContext))
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to set current OpenGL context");
            }

            ~TempContext()
            {
                if (renderContext)
                {
                    wglMakeCurrent(deviceContext, nullptr);
                    wglDeleteContext(renderContext);
                }

                if (window)
                    DestroyWindow(window);

                if (windowClass)
                    UnregisterClassW(TEMP_WINDOW_CLASS_NAME, GetModuleHandleW(nullptr));
            }

        private:
            ATOM windowClass = 0;
            HWND window = 0;
            HDC deviceContext = 0;
            HGLRC renderContext = 0;
        };

        OGLRenderDeviceWin::OGLRenderDeviceWin(const std::function<void(const Event&)>& initCallback):
            OGLRenderDevice(initCallback)
        {
        }

        OGLRenderDeviceWin::~OGLRenderDeviceWin()
        {
            running = false;
            CommandBuffer commandBuffer;
            commandBuffer.pushCommand(std::unique_ptr<Command>(new PresentCommand()));
            submitCommandBuffer(std::move(commandBuffer));

            if (renderThread.joinable()) renderThread.join();

            if (renderContext)
            {
                wglMakeCurrent(deviceContext, nullptr);
                wglDeleteContext(renderContext);
            }
        }

        void OGLRenderDeviceWin::init(Window* newWindow,
                                      const Size2<uint32_t>& newSize,
                                      uint32_t newSampleCount,
                                      Texture::Filter newTextureFilter,
                                      uint32_t newMaxAnisotropy,
                                      bool newVerticalSync,
                                      bool newDepth,
                                      bool newStencil,
                                      bool newDebugRenderer)
        {
            TempContext tempContext;

            NativeWindowWin* windowWin = static_cast<NativeWindowWin*>(newWindow->getNativeWindow());

            deviceContext = GetDC(windowWin->getNativeWindow());
            if (!deviceContext)
                throw std::runtime_error("Failed to get window's device context");

            std::vector<std::string> extensions;

            if (PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringProc = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGARBPROC>(wglGetProcAddress("wglGetExtensionsStringARB")))
            {
                if (const char* extensionPtr = wglGetExtensionsStringProc(deviceContext))
                {
                    std::istringstream extensionStringStream(reinterpret_cast<const char*>(extensionPtr));

                    for (std::string extension; extensionStringStream >> extension;)
                        extensions.push_back(extension);

                    engine->log(Log::Level::ALL) << "Supported WGL extensions: " << extensions;
                }
            }

            PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatProc = nullptr;
            PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsProc = nullptr;

            for (const std::string& extension : extensions)
            {
                if (extension == "WGL_ARB_pixel_format")
                    wglChoosePixelFormatProc = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
                else if (extension == "WGL_ARB_create_context")
                    wglCreateContextAttribsProc = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(wglGetProcAddress("wglCreateContextAttribsARB"));
            }

            int pixelFormat = 0;

            PIXELFORMATDESCRIPTOR pixelFormatDesc;
            pixelFormatDesc.nSize = sizeof(pixelFormatDesc);
            pixelFormatDesc.nVersion = 1;
            pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED;
            pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
            pixelFormatDesc.cColorBits = 24;
            pixelFormatDesc.cRedBits = 0;
            pixelFormatDesc.cRedShift = 0;
            pixelFormatDesc.cGreenBits = 0;
            pixelFormatDesc.cGreenShift = 0;
            pixelFormatDesc.cBlueBits = 0;
            pixelFormatDesc.cBlueShift = 0;
            pixelFormatDesc.cAlphaBits = 0;
            pixelFormatDesc.cAlphaShift = 0;
            pixelFormatDesc.cAccumBits = 0;
            pixelFormatDesc.cAccumRedBits = 0;
            pixelFormatDesc.cAccumGreenBits = 0;
            pixelFormatDesc.cAccumBlueBits = 0;
            pixelFormatDesc.cAccumAlphaBits = 0;
            pixelFormatDesc.cDepthBits = newDepth ? 24 : 0;
            pixelFormatDesc.cStencilBits = 0;
            pixelFormatDesc.cAuxBuffers = 0;
            pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
            pixelFormatDesc.bReserved = 0;
            pixelFormatDesc.dwLayerMask = 0;
            pixelFormatDesc.dwVisibleMask = 0;
            pixelFormatDesc.dwDamageMask = 0;

            if (wglChoosePixelFormatProc)
            {
                const int attributeList[] =
                {
                    WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
                    WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
                    WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
                    WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
                    WGL_COLOR_BITS_ARB, 24,
                    WGL_ALPHA_BITS_ARB, 8,
                    WGL_DEPTH_BITS_ARB, newDepth ? 24 : 0,
                    WGL_STENCIL_BITS_ARB, newStencil ? 8 : 0,
                    WGL_SAMPLE_BUFFERS_ARB, newSampleCount > 0 ? 1 : 0,
                    WGL_SAMPLES_ARB, static_cast<int>(newSampleCount),
                    0,
                };

                UINT numFormats;

                if (!wglChoosePixelFormatProc(deviceContext, attributeList, nullptr, 1, &pixelFormat, &numFormats))
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to choose pixel format");
            }
            else
            {
                pixelFormat = ChoosePixelFormat(deviceContext, &pixelFormatDesc);
                if (!pixelFormat)
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to choose pixel format");
            }

            if (!SetPixelFormat(deviceContext, pixelFormat, &pixelFormatDesc))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to set pixel format");

            if (wglCreateContextAttribsProc)
            {
                for (int openGLVersion = 4; openGLVersion >= 2; --openGLVersion)
                {
                    std::vector<int> contextAttribs = {
                        WGL_CONTEXT_MAJOR_VERSION_ARB, openGLVersion,
                        WGL_CONTEXT_MINOR_VERSION_ARB, 0,
                    };

                    if (newDebugRenderer)
                    {
                        contextAttribs.push_back(WGL_CONTEXT_FLAGS_ARB);
                        contextAttribs.push_back(WGL_CONTEXT_DEBUG_BIT_ARB);
                    }

                    contextAttribs.push_back(0);

                    renderContext = wglCreateContextAttribsProc(deviceContext, 0, contextAttribs.data());

                    if (renderContext)
                    {
                        engine->log(Log::Level::INFO) << "OpenGL " << openGLVersion << " context created";
                        break;
                    }
                }
            }
            else
                renderContext = wglCreateContext(deviceContext);

            if (!renderContext)
                throw std::runtime_error("Failed to create OpenGL context");

            if (!wglMakeCurrent(deviceContext, renderContext))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to set current OpenGL context");

            OGLRenderDevice::init(newWindow,
                                  newSize,
                                  newSampleCount,
                                  newTextureFilter,
                                  newMaxAnisotropy,
                                  newVerticalSync,
                                  newDepth,
                                  newStencil,
                                  newDebugRenderer);

            if (!wglMakeCurrent(deviceContext, nullptr))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to unset OpenGL context");

            running = true;
            renderThread = std::thread(&OGLRenderDeviceWin::main, this);
        }

        void OGLRenderDeviceWin::present()
        {
            if (!SwapBuffers(deviceContext))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to swap buffers");
        }

        void OGLRenderDeviceWin::main()
        {
            setCurrentThreadName("Render");

            if (!wglMakeCurrent(deviceContext, renderContext))
                throw std::system_error(GetLastError(), std::system_category(), "Failed to set current OpenGL context");

            while (running)
            {
                try
                {
                    process();
                }
                catch (const std::exception& e)
                {
                    engine->log(Log::Level::ERR) << e.what();
                }
            }
        }
    } // namespace graphics
} // namespace ouzel

#endif
<|endoftext|>


<commit_before>#include <MicroMag.h>

MicroMag::MicroMag(uint8_t ssPin, uint8_t drdyPin, uint8_t resetPin,
		   uint8_t axes)
  : _axes(axes), _ssPin(ssPin), _drdyPin(drdyPin), _resetPin(resetPin)
{
  ;
}

MicroMag::MicroMag(const MicroMag& mm) \
  : _axes(mm._axes), _ssPin(mm._ssPin), _drdyPin(mm._drdyPin), _resetPin(mm._resetPin)
{
  ;
}

uint8_t MicroMag::begin(void) const
{
  pinMode(_ssPin, OUTPUT);
  if (_drdyPin != 0xff)
    pinMode(_drdyPin, INPUT);
  pinMode(_resetPin, OUTPUT);
  digitalWrite(_ssPin, HIGH);
  digitalWrite(_resetPin, LOW);
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);

  // Make one reading to switch device into low power mode
  int16_t tmp;
  return read(0, MM_PERIOD_32, tmp);
}

uint8_t MicroMag::convert(uint8_t axis, uint8_t period) const
{
  if (axis > _axes)
    return errorBadAxis;

  if (period > MM_PERIOD_4096)
    return errorBadPeriod;

  uint8_t cmd = 0;
  cmd |= (axis + 1);
  cmd |= (period << 4);

  // Select the device
  digitalWrite(_ssPin, LOW);

  // Reset
  digitalWrite(_resetPin, HIGH);
  delayMicroseconds(1);
  digitalWrite(_resetPin, LOW);

  SPI.transfer(cmd); // Send the command byte
  return errorNoError;
}

int16_t MicroMag::getResult(void) const
{
  // Read 2 bytes
  int16_t result = SPI.transfer(0);
  result <<= 8;
  result |= SPI.transfer(0);

  // De-select the device
  digitalWrite(_ssPin, HIGH);

  return result;
}

uint8_t MicroMag::read(uint8_t axis, uint8_t period, int16_t& result,
		      uint16_t timeout_us) const
{
  int8_t ret = convert(axis, period);
  if (ret != errorNoError)
    return ret;

  // Wait for ready signal
  if (timeout_us == 0)
    // Set a default timeout which is approriate for the selected
    // period. See data sheet for details. Values used are 1us larger
    // to account for +/-1 jitter.
    switch (period) {
    case MM_PERIOD_32:
      timeout_us = 501;
      break;
    case MM_PERIOD_64:
      timeout_us = 1001;
      break;
    case MM_PERIOD_128:
      timeout_us = 2001;
      break;
    case MM_PERIOD_256:
      timeout_us = 4001;
      break;
    case MM_PERIOD_512:
      timeout_us = 7501;
      break;
    case MM_PERIOD_1024:
      timeout_us = 15001;
      break;
    case MM_PERIOD_2048:
      timeout_us = 35501;
      break;
    case MM_PERIOD_4096:
      timeout_us = 60001;
      break;
    default:
      return errorBadPeriod;
    }

  if (_drdyPin == 0xff)
    // Cannot monitor if device is ready just so wait
    delayMicroseconds(timeout_us);
  else {
    // Wait until device reports it is ready, or timeout is reached
    unsigned long t = micros();
    while (!digitalRead(_drdyPin)) {
      if (micros() - t > timeout_us)
	return errorTimeout;
    }
  }

  result = getResult();
  return errorNoError;
}

uint8_t MicroMag::readHighPrec(uint8_t axis, int32_t& result,
			      uint16_t timeout_us) const
{
  int8_t r;
  int16_t dLow, dHigh;
  if ((r = read(axis, MM_PERIOD_2048, dLow, timeout_us)) != 0)
    return r;

  if ((r = read(axis, MM_PERIOD_4096, dHigh, timeout_us)) != 0)
    return r;

  if (dLow <= -16000 || dLow >= 16000) {
    // Assume high precision version has overflowed
    result = dLow * 2;
    result += (dHigh % 2); // try to keep extra precision
  }
  else
    result = dHigh;

  return errorNoError;
}
<commit_msg>De-select the device between intiating a conversion and reading the results back.<commit_after>#include <MicroMag.h>

MicroMag::MicroMag(uint8_t ssPin, uint8_t drdyPin, uint8_t resetPin,
		   uint8_t axes)
  : _axes(axes), _ssPin(ssPin), _drdyPin(drdyPin), _resetPin(resetPin)
{
  ;
}

MicroMag::MicroMag(const MicroMag& mm) \
  : _axes(mm._axes), _ssPin(mm._ssPin), _drdyPin(mm._drdyPin), _resetPin(mm._resetPin)
{
  ;
}

uint8_t MicroMag::begin(void) const
{
  pinMode(_ssPin, OUTPUT);
  if (_drdyPin != 0xff)
    pinMode(_drdyPin, INPUT);
  pinMode(_resetPin, OUTPUT);
  digitalWrite(_ssPin, HIGH);
  digitalWrite(_resetPin, LOW);
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);

  // Make one reading to switch device into low power mode
  int16_t tmp;
  return read(0, MM_PERIOD_32, tmp);
}

uint8_t MicroMag::convert(uint8_t axis, uint8_t period) const
{
  if (axis > _axes)
    return errorBadAxis;

  if (period > MM_PERIOD_4096)
    return errorBadPeriod;

  uint8_t cmd = 0;
  cmd |= (axis + 1);
  cmd |= (period << 4);

  // Select the device
  digitalWrite(_ssPin, LOW);

  // Reset the device
  digitalWrite(_resetPin, HIGH);
  delayMicroseconds(1);
  digitalWrite(_resetPin, LOW);

  // Send the command byte
  SPI.transfer(cmd);

  // De-select the device
  digitalWrite(_ssPin, HIGH);

  return errorNoError;
}

int16_t MicroMag::getResult(void) const
{
  // Select the device
  digitalWrite(_ssPin, LOW);

  // Read 2 bytes
  int16_t result = SPI.transfer(0);
  result <<= 8;
  result |= SPI.transfer(0);

  // De-select the device
  digitalWrite(_ssPin, HIGH);

  return result;
}

uint8_t MicroMag::read(uint8_t axis, uint8_t period, int16_t& result,
		      uint16_t timeout_us) const
{
  int8_t ret = convert(axis, period);
  if (ret != errorNoError)
    return ret;

  // Wait for ready signal
  if (timeout_us == 0)
    // Set a default timeout which is approriate for the selected
    // period. See data sheet for details. Values used are 1us larger
    // to account for +/-1 jitter.
    switch (period) {
    case MM_PERIOD_32:
      timeout_us = 501;
      break;
    case MM_PERIOD_64:
      timeout_us = 1001;
      break;
    case MM_PERIOD_128:
      timeout_us = 2001;
      break;
    case MM_PERIOD_256:
      timeout_us = 4001;
      break;
    case MM_PERIOD_512:
      timeout_us = 7501;
      break;
    case MM_PERIOD_1024:
      timeout_us = 15001;
      break;
    case MM_PERIOD_2048:
      timeout_us = 35501;
      break;
    case MM_PERIOD_4096:
      timeout_us = 60001;
      break;
    default:
      return errorBadPeriod;
    }

  if (_drdyPin == 0xff)
    // Cannot monitor if device is ready just so wait
    delayMicroseconds(timeout_us);
  else {
    // Wait until device reports it is ready, or timeout is reached
    unsigned long t = micros();
    while (!digitalRead(_drdyPin)) {
      if (micros() - t > timeout_us)
	return errorTimeout;
    }
  }

  result = getResult();
  return errorNoError;
}

uint8_t MicroMag::readHighPrec(uint8_t axis, int32_t& result,
			      uint16_t timeout_us) const
{
  int8_t r;
  int16_t dLow, dHigh;
  if ((r = read(axis, MM_PERIOD_2048, dLow, timeout_us)) != 0)
    return r;

  if ((r = read(axis, MM_PERIOD_4096, dHigh, timeout_us)) != 0)
    return r;

  if (dLow <= -16000 || dLow >= 16000) {
    // Assume high precision version has overflowed
    result = dLow * 2;
    result += (dHigh % 2); // try to keep extra precision
  }
  else
    result = dHigh;

  return errorNoError;
}
<|endoftext|>


<commit_before>//
//  Exponent.cpp
//  Calculator
//
//  Created by Gavin Scheele on 3/27/14.
//  Copyright (c) 2014 Gavin Scheele. All rights reserved.
//

#include "Exponential.h"

Exponential::Exponential(Expression* base, Rational* exponent){
    this->type = "exponential";
    this->base = base;
    this->exponent = exponent;
    this->exde = new Integer(exponent->getDenominator());
    if (exde->getValue() != 1) {
    	//if the denominator of the exponent is not 1, make the base a root of the denominator, then setting the denominator equal to 1
    	Integer* baseAsInteger = (Integer *) base;
        base = new nthRoot(exde->getValue(), baseAsInteger->getValue(), 1);
        Integer* one = new Integer(1);
        exponent->setDenominator(one);
    }
    this->exnu = new Integer(exponent->getNumerator());
    if (canExponentiate()) {
    	exponentiate();
    }
}
Exponential::~Exponential(){

}

bool Exponential::canExponentiate() {
    if(base->type == "euler"){
        return false;

    }else if(base->type == "exponential"){
	Exponential* ex = (Exponential *) base;
	this->exponent->multiply(ex->getExponent());
	Integer* numSum = new Integer (1);
	ex->getExponent()->setNumerator(numSum);
        return false;
        // false is returned because the base itself would have already been exponentiated if it were possible

    }else if(base->type == "integer"){
        return true;

    }else if(base->type == "logarithm"){
        return false;

    }else if(base->type == "nthRoot"){
	nthRoot* nr = (nthRoot *) base;
	Rational* r = new Rational(this->exponent->getNumerator(), nr->getRoot()*this->exponent->getDenominator());
	//makes a new exponent, multiplying the denominator by the root, allowing the root to be simplified to one
	this->exponent = r;
	nr->setRoot(1);
	return false;

    }else if(base->type == "pi"){
        return false;

    }else if(base->type == "rational"){
        Rational* r = (Rational *) base;
        if (r->geteNumerator()->type == "integer" && r->geteDenominator()->type == "integer") {
          Exponential* nu = new Exponential(r->geteNumerator(), this->exponent);
          r->setNumerator(nu);
          Exponential* de = new Exponential(r->geteDenominator(), this->exponent);
          r->setDenominator(de);
        }

    }else{
        cout << "type not recognized" << endl;
    }
    return false;
}

void Exponential::exponentiate(){

    if (this->exponent->getNumerator()==0) {
        Integer* oneInt = new Integer(1);
        Rational* oneRat = new Rational(1, 1);
       this->exponent=oneRat;
       this->base=oneInt;

    }
    bool toFlip = false;
    if (exnu->getValue()<0) {
	    exnu->setValue(exnu->getValue()*-1);
            toFlip = true;
            //handles negative exponents
    }
    Expression* constantBase = 0;
    if (base->type == "integer") {              //fixed the problem for integers but nothing else
        Integer *a = (Integer *)base;
        constantBase = new Integer(a->getValue());
    }

    while (exponent->getNumerator()>1)
    	{
        base->multiply(constantBase);
        Integer* one = new Integer(1);
        exponent->setNumerator(exponent->geteNumerator()->subtract(one));
    }
    if (toFlip) {
        Integer* one = new Integer(1);
        Rational* mouse = new Rational(one, base);
    	base = mouse;
    }

}

Expression* Exponential::add(Expression* a){
    if(a->type == "euler"){

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if (ex->getBase()==this->base) {
		if (ex->getExponent()==this->exponent) {
			Integer* two = new Integer(2);
			this->multiply(two);
		}
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){

    }else if(a->type == "rational"){

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::subtract(Expression* a){
    if(a->type == "euler"){

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if (ex->getBase()==this->base) {
		if (ex->getExponent()==this->exponent) {
			Integer* zero = new Integer(0);
			this->multiply(zero);
		}
	}
    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){

    }else if(a->type == "rational"){

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::multiply(Expression* a){
	if(a->type == "euler"){
    		if (this->base->type == "euler") {
    			Rational* oneRat = new Rational(1, 1);
			this->exponent->add(oneRat);

    	}

    }else if(a->type == "exponential"){
		Exponential* ex = (Exponential *) a;
	if (this->base == ex->getBase()) {
		this->exponent->add(ex->getExponent());
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){
    	if (this->base->type == "pi") {
    			Rational* oneRat = new Rational(1, 1);
			this->exponent->add(oneRat);
    	}

    }else if(a->type == "rational"){
	Rational* r = (Rational *) a;
	r->setNumerator(r->geteNumerator()->multiply(this));        //Error: expected expression
	return r;

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::divide(Expression* a){
	if(a->type == "euler"){
		if (this->base->type == "euler") {
    				Rational* oneRat = new Rational(1, 1);
				this->exponent->subtract(oneRat);
    		}

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if (this->base == ex->getBase()) {
		this->exponent->subtract(ex->getExponent());
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){
    	if (this->base->type == "pi") {
    				Rational* oneRat = new Rational(1, 1);
				this->exponent->subtract(oneRat);
    		}

    }else if(a->type == "rational"){
	Rational* r = (Rational *) a;
	r->setDenominator(r->geteDenominator()->multiply(this));      //Error: member reference type 'int' is not a pointer
	return r;

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}

Rational* Exponential::getExponent() {
    return exponent;
}

Expression* Exponential::getBase() {
    return base;
}

Integer* Exponential::getExnu() {
	return exnu;
}

Integer* Exponential::getExde() {
	return exde;
}

void Exponential::setExnu(Integer* n) {
	exnu = n;
}

void Exponential::setExde(Integer* n) {
	exde = n;
}

void Exponential::setExponent(Rational* e) {
    exponent = e;
}

void Exponential::setBase(Expression* e) {
    base = e;
}

string Exponential::toString() {
    stringstream str;
    if(exponent->getDenominator() == 1){
        str << *base << "^" << *exponent->geteNumerator();
    }else{
        str << *base << "^" << *exponent;
    }
    return str.str();
}

ostream& Exponential::print(std::ostream& output) const{
    output << *base << "^" << "("<< *exponent << ")";
    return output;
}

bool Exponential::canAdd(Expression* b){     //use "this" as comparison. Solver will call someExpression.canAdd(&someOtherExpression)

    if (this->type == b->type && this->type != "logarithm") {
        if (this->type == "nthRoot") {
        }
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool Exponential::canSubtract(Expression* b){
    if (this->type == b->type) {
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool Exponential::canMultiply(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if(this->type == "integer" && b->type == "rational") return true;
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;

}
bool Exponential::canDivide(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if(this->type == "integer"){
        if( b->type == "rational") return true;
    }
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
<commit_msg>exponential print changes<commit_after>//
//  Exponent.cpp
//  Calculator
//
//  Created by Gavin Scheele on 3/27/14.
//  Copyright (c) 2014 Gavin Scheele. All rights reserved.
//

#include "Exponential.h"

Exponential::Exponential(Expression* base, Rational* exponent){
    this->type = "exponential";
    this->base = base;
    this->exponent = exponent;
    this->exde = new Integer(exponent->getDenominator());
    if (exde->getValue() != 1) {
    	//if the denominator of the exponent is not 1, make the base a root of the denominator, then setting the denominator equal to 1
    	Integer* baseAsInteger = (Integer *) base;
        base = new nthRoot(exde->getValue(), baseAsInteger->getValue(), 1);
        Integer* one = new Integer(1);
        exponent->setDenominator(one);
    }
    this->exnu = new Integer(exponent->getNumerator());
    if (canExponentiate()) {
    	exponentiate();
    }
}
Exponential::~Exponential(){

}

bool Exponential::canExponentiate() {
    if(base->type == "euler"){
        return false;

    }else if(base->type == "exponential"){
	Exponential* ex = (Exponential *) base;
	this->exponent->multiply(ex->getExponent());
	Integer* numSum = new Integer (1);
	ex->getExponent()->setNumerator(numSum);
        return false;
        // false is returned because the base itself would have already been exponentiated if it were possible

    }else if(base->type == "integer"){
        return true;

    }else if(base->type == "logarithm"){
        return false;

    }else if(base->type == "nthRoot"){
	nthRoot* nr = (nthRoot *) base;
	Rational* r = new Rational(this->exponent->getNumerator(), nr->getRoot()*this->exponent->getDenominator());
	//makes a new exponent, multiplying the denominator by the root, allowing the root to be simplified to one
	this->exponent = r;
	nr->setRoot(1);
	return false;

    }else if(base->type == "pi"){
        return false;

    }else if(base->type == "rational"){
        Rational* r = (Rational *) base;
        if (r->geteNumerator()->type == "integer" && r->geteDenominator()->type == "integer") {
          Exponential* nu = new Exponential(r->geteNumerator(), this->exponent);
          r->setNumerator(nu);
          Exponential* de = new Exponential(r->geteDenominator(), this->exponent);
          r->setDenominator(de);
        }

    }else{
        cout << "type not recognized" << endl;
    }
    return false;
}

void Exponential::exponentiate(){

    if (this->exponent->getNumerator()==0) {
        Integer* oneInt = new Integer(1);
        Rational* oneRat = new Rational(1, 1);
       this->exponent=oneRat;
       this->base=oneInt;

    }
    bool toFlip = false;
    if (exnu->getValue()<0) {
	    exnu->setValue(exnu->getValue()*-1);
            toFlip = true;
            //handles negative exponents
    }
    Expression* constantBase = 0;
    if (base->type == "integer") {              //fixed the problem for integers but nothing else
        Integer *a = (Integer *)base;
        constantBase = new Integer(a->getValue());
    }

    while (exponent->getNumerator()>1)
    	{
        base->multiply(constantBase);
        Integer* one = new Integer(1);
        exponent->setNumerator(exponent->geteNumerator()->subtract(one));
    }
    if (toFlip) {
        Integer* one = new Integer(1);
        Rational* mouse = new Rational(one, base);
    	base = mouse;
    }

}

Expression* Exponential::add(Expression* a){
    if(a->type == "euler"){

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if (ex->getBase()==this->base) {
		if (ex->getExponent()==this->exponent) {
			Integer* two = new Integer(2);
			this->multiply(two);
		}
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){

    }else if(a->type == "rational"){

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::subtract(Expression* a){
    if(a->type == "euler"){

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if (ex->getBase()==this->base) {
		if (ex->getExponent()==this->exponent) {
			Integer* zero = new Integer(0);
			this->multiply(zero);
		}
	}
    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){

    }else if(a->type == "rational"){

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::multiply(Expression* a){
	if(a->type == "euler"){
    		if (this->base->type == "euler") {
    			Rational* oneRat = new Rational(1, 1);
			this->exponent->add(oneRat);

    	}

    }else if(a->type == "exponential"){
		Exponential* ex = (Exponential *) a;
	if (this->base == ex->getBase()) {
		this->exponent->add(ex->getExponent());
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){
    	if (this->base->type == "pi") {
    			Rational* oneRat = new Rational(1, 1);
			this->exponent->add(oneRat);
    	}

    }else if(a->type == "rational"){
	Rational* r = (Rational *) a;
	r->setNumerator(r->geteNumerator()->multiply(this));        //Error: expected expression
	return r;

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}
Expression* Exponential::divide(Expression* a){
	if(a->type == "euler"){
		if (this->base->type == "euler") {
    				Rational* oneRat = new Rational(1, 1);
				this->exponent->subtract(oneRat);
    		}

    }else if(a->type == "exponential"){
	Exponential* ex = (Exponential *) a;
	if (this->base == ex->getBase()) {
		this->exponent->subtract(ex->getExponent());
	}

    }else if(a->type == "integer"){

    }else if(a->type == "logarithm"){

    }else if(a->type == "nthRoot"){

    }else if(a->type == "pi"){
    	if (this->base->type == "pi") {
    				Rational* oneRat = new Rational(1, 1);
				this->exponent->subtract(oneRat);
    		}

    }else if(a->type == "rational"){
	Rational* r = (Rational *) a;
	r->setDenominator(r->geteDenominator()->multiply(this));      //Error: member reference type 'int' is not a pointer
	return r;

    }else{
        cout << "type not recognized" << endl;
    }
    return this;
}

Rational* Exponential::getExponent() {
    return exponent;
}

Expression* Exponential::getBase() {
    return base;
}

Integer* Exponential::getExnu() {
	return exnu;
}

Integer* Exponential::getExde() {
	return exde;
}

void Exponential::setExnu(Integer* n) {
	exnu = n;
}

void Exponential::setExde(Integer* n) {
	exde = n;
}

void Exponential::setExponent(Rational* e) {
    exponent = e;
}

void Exponential::setBase(Expression* e) {
    base = e;
}

string Exponential::toString() {
    stringstream str;
    if(exponent->getNumerator() == 1 && exponent->getDenominator() == 1){
        str << *base;
    }
    else if(exponent->getDenominator() == 1){
        str << *base << "^" << *exponent->geteNumerator();
    }else{
        str << *base << "^" << *exponent;
    }
    return str.str();
}

ostream& Exponential::print(std::ostream& output) const{
    Exponential *a = (Exponential *)this;
    output << a->toString();
    return output;
}

bool Exponential::canAdd(Expression* b){     //use "this" as comparison. Solver will call someExpression.canAdd(&someOtherExpression)

    if (this->type == b->type && this->type != "logarithm") {
        if (this->type == "nthRoot") {
        }
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool Exponential::canSubtract(Expression* b){
    if (this->type == b->type) {
        return true;
    }else if((this->type == "integer" && b->type == "rational") || (this->type == "rational" && b->type == "integer")){
        return true;
    }else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
bool Exponential::canMultiply(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if(this->type == "integer" && b->type == "rational") return true;
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;

}
bool Exponential::canDivide(Expression* b){
    if (this->type == b->type) {
        return true;
    }
    else if(this->type == "integer"){
        if( b->type == "rational") return true;
    }
    else if(this->type == "rational" && b->type == "integer") return true;
    else if(this->type == "multiple" && b->type == "multiple"){
        MultipleExpressions *t = (MultipleExpressions *)this;
        MultipleExpressions *m = (MultipleExpressions *)b;
        if ((t->meType == "as" && m->meType == "as") || (t->meType == "md" && m->meType == "md")) {
            return true;
        }
    }else if(this->type == "multiple" || b->type == "multiple") return true;
    return false;
}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                       Simbody(tm): SimTKcommon                             *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK biosimulation toolkit originating from           *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
 *                                                                            *
 * Portions copyright (c) 2010-14 Stanford University and the Authors.        *
 * Authors: Chris Dembia, Michael Sherman                                     *
 * Contributors:                                                              *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

#if defined(__GNUG__)
// https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
    #include <cxxabi.h>
    #include <string>
#endif

namespace SimTK {

std::string demangle(const char* name) {
    #if defined(__GNUG__)
        int status;
        char* ret = abi::__cxa_demangle(name, NULL, NULL, &status);
        const char* const demangled_name = (status == 0) ? ret : name;
        std::string demangled_string(demangled_name);
        std::free(ret);
        return demangled_string;
    #else
        // On other platforms, we hope the typeid name is not mangled.
        return name;
    #endif
}

}
<commit_msg>Only free demangling output if demangling succeeds<commit_after>/* -------------------------------------------------------------------------- *
 *                       Simbody(tm): SimTKcommon                             *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK biosimulation toolkit originating from           *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
 *                                                                            *
 * Portions copyright (c) 2010-14 Stanford University and the Authors.        *
 * Authors: Chris Dembia, Michael Sherman                                     *
 * Contributors:                                                              *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

#if defined(__GNUG__)
// https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
    #include <cxxabi.h>
    #include <string>
#endif

namespace SimTK {

std::string demangle(const char* name) {
    #if defined(__GNUG__)
        int status;
        char* ret = abi::__cxa_demangle(name, NULL, NULL, &status);
        const char* const demangled_name = (status == 0) ? ret : name;
        std::string demangled_string(demangled_name);
        if (ret) std::free(ret);
        return demangled_string;
    #else
        // On other platforms, we hope the typeid name is not mangled.
        return name;
    #endif
}

}
<|endoftext|>