<commit_before>//===--- LangOptions.cpp - Language & configuration options ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file defines the LangOptions class, which provides various
//  language and configuration flags.
//
//===----------------------------------------------------------------------===//

#include "swift/Basic/LangOptions.h"
#include "swift/Basic/Platform.h"
#include "swift/Basic/Range.h"
#include "swift/Config.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
#include <limits.h>

using namespace swift;

struct SupportedConditionalValue {
  StringRef value;

  /// If the value has been deprecated, the new value to replace it with.
  StringRef replacement = "";

  SupportedConditionalValue(const char *value) : value(value) {}
  SupportedConditionalValue(const char *value, const char *replacement)
    : value(value), replacement(replacement) {}
};

static const SupportedConditionalValue SupportedConditionalCompilationOSs[] = {
  "OSX",
  "macOS",
  "tvOS",
  "watchOS",
  "iOS",
  "Linux",
  "FreeBSD",
  "OpenBSD",
  "Windows",
  "Android",
  "PS4",
  "Cygwin",
  "Haiku",
  "WASI",
};

static const SupportedConditionalValue SupportedConditionalCompilationArches[] = {
  "arm",
  "arm64",
  "i386",
  "x86_64",
  "powerpc64",
  "powerpc64le",
  "s390x",
  "wasm32",
};

static const SupportedConditionalValue SupportedConditionalCompilationEndianness[] = {
  "little",
  "big"
};

static const SupportedConditionalValue SupportedConditionalCompilationRuntimes[] = {
  "_ObjC",
  "_Native",
};

static const SupportedConditionalValue SupportedConditionalCompilationTargetEnvironments[] = {
  "simulator",
  { "macabi", "macCatalyst" },
  "macCatalyst", // A synonym for "macabi" when compiling for iOS
};

static const SupportedConditionalValue SupportedConditionalCompilationPtrAuthSchemes[] = {
  "_none",
  "_arm64e",
};

static const PlatformConditionKind AllPublicPlatformConditionKinds[] = {
#define PLATFORM_CONDITION(LABEL, IDENTIFIER) PlatformConditionKind::LABEL,
#define PLATFORM_CONDITION_(LABEL, IDENTIFIER)
#include "swift/AST/PlatformConditionKinds.def"
};

ArrayRef<SupportedConditionalValue> getSupportedConditionalCompilationValues(const PlatformConditionKind &Kind) {
  switch (Kind) {
  case PlatformConditionKind::OS:
    return SupportedConditionalCompilationOSs;
  case PlatformConditionKind::Arch:
    return SupportedConditionalCompilationArches;
  case PlatformConditionKind::Endianness:
    return SupportedConditionalCompilationEndianness;
  case PlatformConditionKind::Runtime:
    return SupportedConditionalCompilationRuntimes;
  case PlatformConditionKind::CanImport:
    return { };
  case PlatformConditionKind::TargetEnvironment:
    return SupportedConditionalCompilationTargetEnvironments;
  case PlatformConditionKind::PtrAuth:
    return SupportedConditionalCompilationPtrAuthSchemes;
  }
  llvm_unreachable("Unhandled PlatformConditionKind in switch");
}

PlatformConditionKind suggestedPlatformConditionKind(PlatformConditionKind Kind, const StringRef &V,
                                                     std::vector<StringRef> &suggestedValues) {
  std::string lower = V.lower();
  for (const PlatformConditionKind& candidateKind : AllPublicPlatformConditionKinds) {
    if (candidateKind != Kind) {
      auto supportedValues = getSupportedConditionalCompilationValues(candidateKind);
      for (const SupportedConditionalValue& candidateValue : supportedValues) {
        if (candidateValue.value.lower() == lower) {
          suggestedValues.clear();
          if (candidateValue.value != V) {
            suggestedValues.emplace_back(candidateValue.value);
          }
          return candidateKind;
        }
      }
    }
  }
  return Kind;
}

bool isMatching(PlatformConditionKind Kind, const StringRef &V,
                PlatformConditionKind &suggestedKind, std::vector<StringRef> &suggestions) {
  // Compare against known values, ignoring case to avoid penalizing
  // characters with incorrect case.
  unsigned minDistance = std::numeric_limits<unsigned>::max();
  std::string lower = V.lower();
  auto supportedValues = getSupportedConditionalCompilationValues(Kind);
  for (const SupportedConditionalValue& candidate : supportedValues) {
    if (candidate.value == V) {
      suggestedKind = Kind;
      suggestions.clear();
      if (!candidate.replacement.empty())
        suggestions.push_back(candidate.replacement);
      return true;
    }
    unsigned distance = StringRef(lower).edit_distance(candidate.value.lower());
    if (distance < minDistance) {
      suggestions.clear();
      minDistance = distance;
    }
    if (distance == minDistance)
      suggestions.emplace_back(candidate.value);
  }
  suggestedKind = suggestedPlatformConditionKind(Kind, V, suggestions);
  return false;
}

bool LangOptions::
checkPlatformConditionSupported(PlatformConditionKind Kind, StringRef Value,
                                PlatformConditionKind &suggestedKind,
                                std::vector<StringRef> &suggestedValues) {
  switch (Kind) {
  case PlatformConditionKind::OS:
  case PlatformConditionKind::Arch:
  case PlatformConditionKind::Endianness:
  case PlatformConditionKind::Runtime:
  case PlatformConditionKind::TargetEnvironment:
  case PlatformConditionKind::PtrAuth:
    return isMatching(Kind, Value, suggestedKind, suggestedValues);
  case PlatformConditionKind::CanImport:
    // All importable names are valid.
    // FIXME: Perform some kind of validation of the string?
    return true;
  }
  llvm_unreachable("Unhandled enum value");
}

StringRef
LangOptions::getPlatformConditionValue(PlatformConditionKind Kind) const {
  // Last one wins.
  for (auto &Opt : llvm::reverse(PlatformConditionValues)) {
    if (Opt.first == Kind)
      return Opt.second;
  }
  return StringRef();
}

bool LangOptions::
checkPlatformCondition(PlatformConditionKind Kind, StringRef Value) const {
  // Check a special case that "macOS" is an alias of "OSX".
  if (Kind == PlatformConditionKind::OS && Value == "macOS")
    return checkPlatformCondition(Kind, "OSX");

  // When compiling for iOS we consider "macCatalyst" to be a
  // synonym of "macabi". This enables the use of
  // #if targetEnvironment(macCatalyst) as a compilation
  // condition for macCatalyst.

  if (Kind == PlatformConditionKind::TargetEnvironment &&
      Value == "macCatalyst" && Target.isiOS()) {
    return checkPlatformCondition(Kind, "macabi");
  }

  for (auto &Opt : llvm::reverse(PlatformConditionValues)) {
    if (Opt.first == Kind)
      if (Opt.second == Value)
        return true;
  }

  return false;
}

bool LangOptions::isCustomConditionalCompilationFlagSet(StringRef Name) const {
  return std::find(CustomConditionalCompilationFlags.begin(),
                   CustomConditionalCompilationFlags.end(), Name)
      != CustomConditionalCompilationFlags.end();
}

std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
  clearAllPlatformConditionValues();

  if (triple.getOS() == llvm::Triple::Darwin &&
      triple.getVendor() == llvm::Triple::Apple) {
    // Rewrite darwinX.Y triples to macosx10.X'.Y ones.
    // It affects code generation on our platform.
    llvm::SmallString<16> osxBuf;
    llvm::raw_svector_ostream osx(osxBuf);
    osx << llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);

    unsigned major, minor, micro;
    triple.getMacOSXVersion(major, minor, micro);
    osx << major << "." << minor;
    if (micro != 0)
      osx << "." << micro;

    triple.setOSName(osx.str());
  }
  Target = std::move(triple);

  bool UnsupportedOS = false;

  // Set the "os" platform condition.
  switch (Target.getOS()) {
  case llvm::Triple::Darwin:
  case llvm::Triple::MacOSX:
    addPlatformConditionValue(PlatformConditionKind::OS, "OSX");
    break;
  case llvm::Triple::TvOS:
    addPlatformConditionValue(PlatformConditionKind::OS, "tvOS");
    break;
  case llvm::Triple::WatchOS:
    addPlatformConditionValue(PlatformConditionKind::OS, "watchOS");
    break;
  case llvm::Triple::IOS:
    addPlatformConditionValue(PlatformConditionKind::OS, "iOS");
    break;
  case llvm::Triple::Linux:
    if (Target.getEnvironment() == llvm::Triple::Android)
      addPlatformConditionValue(PlatformConditionKind::OS, "Android");
    else
      addPlatformConditionValue(PlatformConditionKind::OS, "Linux");
    break;
  case llvm::Triple::FreeBSD:
    addPlatformConditionValue(PlatformConditionKind::OS, "FreeBSD");
    break;
  case llvm::Triple::OpenBSD:
    addPlatformConditionValue(PlatformConditionKind::OS, "OpenBSD");
    break;
  case llvm::Triple::Win32:
    if (Target.getEnvironment() == llvm::Triple::Cygnus)
      addPlatformConditionValue(PlatformConditionKind::OS, "Cygwin");
    else
      addPlatformConditionValue(PlatformConditionKind::OS, "Windows");
    break;
  case llvm::Triple::PS4:
    if (Target.getVendor() == llvm::Triple::SCEI)
      addPlatformConditionValue(PlatformConditionKind::OS, "PS4");
    else
      UnsupportedOS = false;
    break;
  case llvm::Triple::Haiku:
    addPlatformConditionValue(PlatformConditionKind::OS, "Haiku");
    break;
  case llvm::Triple::WASI:
    addPlatformConditionValue(PlatformConditionKind::OS, "WASI");
    break;
  default:
    UnsupportedOS = true;
    break;
  }

  bool UnsupportedArch = false;

  // Set the "arch" platform condition.
  switch (Target.getArch()) {
  case llvm::Triple::ArchType::arm:
  case llvm::Triple::ArchType::thumb:
    addPlatformConditionValue(PlatformConditionKind::Arch, "arm");
    break;
  case llvm::Triple::ArchType::aarch64:
    addPlatformConditionValue(PlatformConditionKind::Arch, "arm64");
    break;
  case llvm::Triple::ArchType::ppc64:
    addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64");
    break;
  case llvm::Triple::ArchType::ppc64le:
    addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64le");
    break;
  case llvm::Triple::ArchType::x86:
    addPlatformConditionValue(PlatformConditionKind::Arch, "i386");
    break;
  case llvm::Triple::ArchType::x86_64:
    addPlatformConditionValue(PlatformConditionKind::Arch, "x86_64");
    break;
  case llvm::Triple::ArchType::systemz:
    addPlatformConditionValue(PlatformConditionKind::Arch, "s390x");
    break;
  case llvm::Triple::ArchType::wasm32:
    addPlatformConditionValue(PlatformConditionKind::Arch, "wasm32");
    break;
  default:
    UnsupportedArch = true;
  }

  if (UnsupportedOS || UnsupportedArch)
    return { UnsupportedOS, UnsupportedArch };

  // Set the "_endian" platform condition.
  switch (Target.getArch()) {
  default: llvm_unreachable("undefined architecture endianness");
  case llvm::Triple::ArchType::arm:
  case llvm::Triple::ArchType::thumb:
  case llvm::Triple::ArchType::aarch64:
  case llvm::Triple::ArchType::ppc64le:
  case llvm::Triple::ArchType::wasm32:
  case llvm::Triple::ArchType::x86:
  case llvm::Triple::ArchType::x86_64:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
    break;
  case llvm::Triple::ArchType::ppc64:
  case llvm::Triple::ArchType::systemz:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
    break;
  }

  // Set the "runtime" platform condition.
  addPlatformConditionValue(PlatformConditionKind::Runtime,
                            EnableObjCInterop ? "_ObjC" : "_Native");

  // Set the pointer authentication scheme.
  if (Target.getArchName() == "arm64e") {
    addPlatformConditionValue(PlatformConditionKind::PtrAuth, "_arm64e");
  } else {
    addPlatformConditionValue(PlatformConditionKind::PtrAuth, "_none");
  }

  // Set the "targetEnvironment" platform condition if targeting a simulator
  // environment. Otherwise _no_ value is present for targetEnvironment; it's
  // an optional disambiguating refinement of the triple.
  if (swift::tripleIsAnySimulator(Target))
    addPlatformConditionValue(PlatformConditionKind::TargetEnvironment,
                              "simulator");

  if (tripleIsMacCatalystEnvironment(Target))
    addPlatformConditionValue(PlatformConditionKind::TargetEnvironment,
                              "macabi");

  // If you add anything to this list, change the default size of
  // PlatformConditionValues to not require an extra allocation
  // in the common case.

  return { false, false };
}

bool LangOptions::doesTargetSupportObjCMetadataUpdateCallback() const {
  if (Target.getArchName() == "arm64e")
    return true;
  if (Target.isMacOSX())
    return !Target.isMacOSXVersionLT(10, 14, 4);
  if (Target.isiOS()) // also returns true on tvOS
    return !Target.isOSVersionLT(12, 2);
  if (Target.isWatchOS())
    return !Target.isOSVersionLT(5, 2);

  // Don't assert if we're running on a non-Apple platform; we still
  // want to allow running tests that -enable-objc-interop.
  return false;
}

bool LangOptions::doesTargetSupportObjCGetClassHook() const {
  return doesTargetSupportObjCMetadataUpdateCallback();
}

bool LangOptions::doesTargetSupportObjCClassStubs() const {
  if (Target.getArchName() == "arm64e")
    return true;
  if (Target.isMacOSX())
    return !Target.isMacOSXVersionLT(10, 15);
  if (Target.isiOS()) // also returns true on tvOS
    return !Target.isOSVersionLT(13);
  if (Target.isWatchOS())
    return !Target.isOSVersionLT(6);

  // Don't assert if we're running on a non-Apple platform; we still
  // want to allow running tests that -enable-objc-interop.
  return false;
}
<commit_msg>Fixup for 3904fe83f (AST: Centralize ABI-related deployment target checks)<commit_after>//===--- LangOptions.cpp - Language & configuration options ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file defines the LangOptions class, which provides various
//  language and configuration flags.
//
//===----------------------------------------------------------------------===//

#include "swift/Basic/LangOptions.h"
#include "swift/Basic/Platform.h"
#include "swift/Basic/Range.h"
#include "swift/Config.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
#include <limits.h>

using namespace swift;

struct SupportedConditionalValue {
  StringRef value;

  /// If the value has been deprecated, the new value to replace it with.
  StringRef replacement = "";

  SupportedConditionalValue(const char *value) : value(value) {}
  SupportedConditionalValue(const char *value, const char *replacement)
    : value(value), replacement(replacement) {}
};

static const SupportedConditionalValue SupportedConditionalCompilationOSs[] = {
  "OSX",
  "macOS",
  "tvOS",
  "watchOS",
  "iOS",
  "Linux",
  "FreeBSD",
  "OpenBSD",
  "Windows",
  "Android",
  "PS4",
  "Cygwin",
  "Haiku",
  "WASI",
};

static const SupportedConditionalValue SupportedConditionalCompilationArches[] = {
  "arm",
  "arm64",
  "i386",
  "x86_64",
  "powerpc64",
  "powerpc64le",
  "s390x",
  "wasm32",
};

static const SupportedConditionalValue SupportedConditionalCompilationEndianness[] = {
  "little",
  "big"
};

static const SupportedConditionalValue SupportedConditionalCompilationRuntimes[] = {
  "_ObjC",
  "_Native",
};

static const SupportedConditionalValue SupportedConditionalCompilationTargetEnvironments[] = {
  "simulator",
  { "macabi", "macCatalyst" },
  "macCatalyst", // A synonym for "macabi" when compiling for iOS
};

static const SupportedConditionalValue SupportedConditionalCompilationPtrAuthSchemes[] = {
  "_none",
  "_arm64e",
};

static const PlatformConditionKind AllPublicPlatformConditionKinds[] = {
#define PLATFORM_CONDITION(LABEL, IDENTIFIER) PlatformConditionKind::LABEL,
#define PLATFORM_CONDITION_(LABEL, IDENTIFIER)
#include "swift/AST/PlatformConditionKinds.def"
};

ArrayRef<SupportedConditionalValue> getSupportedConditionalCompilationValues(const PlatformConditionKind &Kind) {
  switch (Kind) {
  case PlatformConditionKind::OS:
    return SupportedConditionalCompilationOSs;
  case PlatformConditionKind::Arch:
    return SupportedConditionalCompilationArches;
  case PlatformConditionKind::Endianness:
    return SupportedConditionalCompilationEndianness;
  case PlatformConditionKind::Runtime:
    return SupportedConditionalCompilationRuntimes;
  case PlatformConditionKind::CanImport:
    return { };
  case PlatformConditionKind::TargetEnvironment:
    return SupportedConditionalCompilationTargetEnvironments;
  case PlatformConditionKind::PtrAuth:
    return SupportedConditionalCompilationPtrAuthSchemes;
  }
  llvm_unreachable("Unhandled PlatformConditionKind in switch");
}

PlatformConditionKind suggestedPlatformConditionKind(PlatformConditionKind Kind, const StringRef &V,
                                                     std::vector<StringRef> &suggestedValues) {
  std::string lower = V.lower();
  for (const PlatformConditionKind& candidateKind : AllPublicPlatformConditionKinds) {
    if (candidateKind != Kind) {
      auto supportedValues = getSupportedConditionalCompilationValues(candidateKind);
      for (const SupportedConditionalValue& candidateValue : supportedValues) {
        if (candidateValue.value.lower() == lower) {
          suggestedValues.clear();
          if (candidateValue.value != V) {
            suggestedValues.emplace_back(candidateValue.value);
          }
          return candidateKind;
        }
      }
    }
  }
  return Kind;
}

bool isMatching(PlatformConditionKind Kind, const StringRef &V,
                PlatformConditionKind &suggestedKind, std::vector<StringRef> &suggestions) {
  // Compare against known values, ignoring case to avoid penalizing
  // characters with incorrect case.
  unsigned minDistance = std::numeric_limits<unsigned>::max();
  std::string lower = V.lower();
  auto supportedValues = getSupportedConditionalCompilationValues(Kind);
  for (const SupportedConditionalValue& candidate : supportedValues) {
    if (candidate.value == V) {
      suggestedKind = Kind;
      suggestions.clear();
      if (!candidate.replacement.empty())
        suggestions.push_back(candidate.replacement);
      return true;
    }
    unsigned distance = StringRef(lower).edit_distance(candidate.value.lower());
    if (distance < minDistance) {
      suggestions.clear();
      minDistance = distance;
    }
    if (distance == minDistance)
      suggestions.emplace_back(candidate.value);
  }
  suggestedKind = suggestedPlatformConditionKind(Kind, V, suggestions);
  return false;
}

bool LangOptions::
checkPlatformConditionSupported(PlatformConditionKind Kind, StringRef Value,
                                PlatformConditionKind &suggestedKind,
                                std::vector<StringRef> &suggestedValues) {
  switch (Kind) {
  case PlatformConditionKind::OS:
  case PlatformConditionKind::Arch:
  case PlatformConditionKind::Endianness:
  case PlatformConditionKind::Runtime:
  case PlatformConditionKind::TargetEnvironment:
  case PlatformConditionKind::PtrAuth:
    return isMatching(Kind, Value, suggestedKind, suggestedValues);
  case PlatformConditionKind::CanImport:
    // All importable names are valid.
    // FIXME: Perform some kind of validation of the string?
    return true;
  }
  llvm_unreachable("Unhandled enum value");
}

StringRef
LangOptions::getPlatformConditionValue(PlatformConditionKind Kind) const {
  // Last one wins.
  for (auto &Opt : llvm::reverse(PlatformConditionValues)) {
    if (Opt.first == Kind)
      return Opt.second;
  }
  return StringRef();
}

bool LangOptions::
checkPlatformCondition(PlatformConditionKind Kind, StringRef Value) const {
  // Check a special case that "macOS" is an alias of "OSX".
  if (Kind == PlatformConditionKind::OS && Value == "macOS")
    return checkPlatformCondition(Kind, "OSX");

  // When compiling for iOS we consider "macCatalyst" to be a
  // synonym of "macabi". This enables the use of
  // #if targetEnvironment(macCatalyst) as a compilation
  // condition for macCatalyst.

  if (Kind == PlatformConditionKind::TargetEnvironment &&
      Value == "macCatalyst" && Target.isiOS()) {
    return checkPlatformCondition(Kind, "macabi");
  }

  for (auto &Opt : llvm::reverse(PlatformConditionValues)) {
    if (Opt.first == Kind)
      if (Opt.second == Value)
        return true;
  }

  return false;
}

bool LangOptions::isCustomConditionalCompilationFlagSet(StringRef Name) const {
  return std::find(CustomConditionalCompilationFlags.begin(),
                   CustomConditionalCompilationFlags.end(), Name)
      != CustomConditionalCompilationFlags.end();
}

std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
  clearAllPlatformConditionValues();

  if (triple.getOS() == llvm::Triple::Darwin &&
      triple.getVendor() == llvm::Triple::Apple) {
    // Rewrite darwinX.Y triples to macosx10.X'.Y ones.
    // It affects code generation on our platform.
    llvm::SmallString<16> osxBuf;
    llvm::raw_svector_ostream osx(osxBuf);
    osx << llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);

    unsigned major, minor, micro;
    triple.getMacOSXVersion(major, minor, micro);
    osx << major << "." << minor;
    if (micro != 0)
      osx << "." << micro;

    triple.setOSName(osx.str());
  }
  Target = std::move(triple);

  bool UnsupportedOS = false;

  // Set the "os" platform condition.
  switch (Target.getOS()) {
  case llvm::Triple::Darwin:
  case llvm::Triple::MacOSX:
    addPlatformConditionValue(PlatformConditionKind::OS, "OSX");
    break;
  case llvm::Triple::TvOS:
    addPlatformConditionValue(PlatformConditionKind::OS, "tvOS");
    break;
  case llvm::Triple::WatchOS:
    addPlatformConditionValue(PlatformConditionKind::OS, "watchOS");
    break;
  case llvm::Triple::IOS:
    addPlatformConditionValue(PlatformConditionKind::OS, "iOS");
    break;
  case llvm::Triple::Linux:
    if (Target.getEnvironment() == llvm::Triple::Android)
      addPlatformConditionValue(PlatformConditionKind::OS, "Android");
    else
      addPlatformConditionValue(PlatformConditionKind::OS, "Linux");
    break;
  case llvm::Triple::FreeBSD:
    addPlatformConditionValue(PlatformConditionKind::OS, "FreeBSD");
    break;
  case llvm::Triple::OpenBSD:
    addPlatformConditionValue(PlatformConditionKind::OS, "OpenBSD");
    break;
  case llvm::Triple::Win32:
    if (Target.getEnvironment() == llvm::Triple::Cygnus)
      addPlatformConditionValue(PlatformConditionKind::OS, "Cygwin");
    else
      addPlatformConditionValue(PlatformConditionKind::OS, "Windows");
    break;
  case llvm::Triple::PS4:
    if (Target.getVendor() == llvm::Triple::SCEI)
      addPlatformConditionValue(PlatformConditionKind::OS, "PS4");
    else
      UnsupportedOS = false;
    break;
  case llvm::Triple::Haiku:
    addPlatformConditionValue(PlatformConditionKind::OS, "Haiku");
    break;
  case llvm::Triple::WASI:
    addPlatformConditionValue(PlatformConditionKind::OS, "WASI");
    break;
  default:
    UnsupportedOS = true;
    break;
  }

  bool UnsupportedArch = false;

  // Set the "arch" platform condition.
  switch (Target.getArch()) {
  case llvm::Triple::ArchType::arm:
  case llvm::Triple::ArchType::thumb:
    addPlatformConditionValue(PlatformConditionKind::Arch, "arm");
    break;
  case llvm::Triple::ArchType::aarch64:
    addPlatformConditionValue(PlatformConditionKind::Arch, "arm64");
    break;
  case llvm::Triple::ArchType::ppc64:
    addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64");
    break;
  case llvm::Triple::ArchType::ppc64le:
    addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64le");
    break;
  case llvm::Triple::ArchType::x86:
    addPlatformConditionValue(PlatformConditionKind::Arch, "i386");
    break;
  case llvm::Triple::ArchType::x86_64:
    addPlatformConditionValue(PlatformConditionKind::Arch, "x86_64");
    break;
  case llvm::Triple::ArchType::systemz:
    addPlatformConditionValue(PlatformConditionKind::Arch, "s390x");
    break;
  case llvm::Triple::ArchType::wasm32:
    addPlatformConditionValue(PlatformConditionKind::Arch, "wasm32");
    break;
  default:
    UnsupportedArch = true;
  }

  if (UnsupportedOS || UnsupportedArch)
    return { UnsupportedOS, UnsupportedArch };

  // Set the "_endian" platform condition.
  switch (Target.getArch()) {
  default: llvm_unreachable("undefined architecture endianness");
  case llvm::Triple::ArchType::arm:
  case llvm::Triple::ArchType::thumb:
  case llvm::Triple::ArchType::aarch64:
  case llvm::Triple::ArchType::ppc64le:
  case llvm::Triple::ArchType::wasm32:
  case llvm::Triple::ArchType::x86:
  case llvm::Triple::ArchType::x86_64:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
    break;
  case llvm::Triple::ArchType::ppc64:
  case llvm::Triple::ArchType::systemz:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
    break;
  }

  // Set the "runtime" platform condition.
  addPlatformConditionValue(PlatformConditionKind::Runtime,
                            EnableObjCInterop ? "_ObjC" : "_Native");

  // Set the pointer authentication scheme.
  if (Target.getArchName() == "arm64e") {
    addPlatformConditionValue(PlatformConditionKind::PtrAuth, "_arm64e");
  } else {
    addPlatformConditionValue(PlatformConditionKind::PtrAuth, "_none");
  }

  // Set the "targetEnvironment" platform condition if targeting a simulator
  // environment. Otherwise _no_ value is present for targetEnvironment; it's
  // an optional disambiguating refinement of the triple.
  if (swift::tripleIsAnySimulator(Target))
    addPlatformConditionValue(PlatformConditionKind::TargetEnvironment,
                              "simulator");

  if (tripleIsMacCatalystEnvironment(Target))
    addPlatformConditionValue(PlatformConditionKind::TargetEnvironment,
                              "macabi");

  // If you add anything to this list, change the default size of
  // PlatformConditionValues to not require an extra allocation
  // in the common case.

  return { false, false };
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief json helper functions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/JsonHelper.h"

#include "BasicsC/conversions.h"
#include "BasicsC/string-buffer.h"

using namespace triagens::basics;

// -----------------------------------------------------------------------------
// --SECTION--                                                  class JsonHelper
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                             public static methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a uint64 into a JSON string
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::uint64String (TRI_memory_zone_t* zone,
                                      uint64_t value) {
  char buffer[21];
  size_t len;

  len = TRI_StringUInt64InPlace(value, (char*) &buffer);

  return TRI_CreateString2CopyJson(zone, buffer, len);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a uint64 into a JSON string
////////////////////////////////////////////////////////////////////////////////

uint64_t JsonHelper::stringUInt64 (TRI_json_t const* json) {
  if (json != 0) {
    if (json->_type == TRI_JSON_STRING) {
      return TRI_UInt64String2(json->_value._string.data, json->_value._string.length - 1);
    }
    else if (json->_type == TRI_JSON_NUMBER) {
      return (uint64_t) json->_value._number;
    }
  }

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a uint64 into a JSON string
////////////////////////////////////////////////////////////////////////////////

uint64_t JsonHelper::stringUInt64 (TRI_json_t const* json,
                                   char const* name) {

  if (json == 0) {
    return 0;
  }

  TRI_json_t const* element = TRI_LookupArrayJson(json, name);
  return stringUInt64(element);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a JSON key/value object from a list of strings
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::stringObject (TRI_memory_zone_t* zone,
                                      std::map<std::string, std::string> const& values) {
  TRI_json_t* json = TRI_CreateArray2Json(zone, values.size());

  if (json == 0) {
    return 0;
  }

  std::map<std::string, std::string>::const_iterator it;
  for (it = values.begin(); it != values.end(); ++it) {
    const std::string key = (*it).first;
    const std::string value = (*it).second;

    TRI_json_t* v = TRI_CreateString2CopyJson(zone, value.c_str(), value.size());
    if (v != 0) {
      TRI_Insert3ArrayJson(zone, json, key.c_str(), v);
    }
  }

  return json;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a key/value object of strings from a JSON (sub-) object
////////////////////////////////////////////////////////////////////////////////

std::map<std::string, std::string> JsonHelper::stringObject (TRI_json_t const* json) {
  std::map<std::string, std::string> result;

  if (isArray(json)) {
    for (size_t i = 0, n = json->_value._objects._length; i < n; i += 2) {
      TRI_json_t const* k = (TRI_json_t const*) TRI_AtVector(&json->_value._objects, i);
      TRI_json_t const* v = (TRI_json_t const*) TRI_AtVector(&json->_value._objects, i + 1);

      if (isString(k) && isString(v)) {
        const std::string key = std::string(k->_value._string.data, k->_value._string.length - 1);
        const std::string value = std::string(v->_value._string.data, v->_value._string.length - 1);
        result.insert(std::pair<std::string, std::string>(key, value));
      }
    }
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a JSON object from a list of strings
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::stringList (TRI_memory_zone_t* zone,
                                    std::vector<std::string> const& values) {
  TRI_json_t* json = TRI_CreateList2Json(zone, values.size());

  if (json == 0) {
    return 0;
  }

  for (size_t i = 0, n = values.size(); i < n; ++i) {
    TRI_json_t* v = TRI_CreateString2CopyJson(zone, values[i].c_str(), values[i].size());
    if (v != 0) {
      TRI_PushBack3ListJson(zone, json, v);
    }
  }

  return json;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a list of strings from a JSON (sub-) object
////////////////////////////////////////////////////////////////////////////////

std::vector<std::string> JsonHelper::stringList (TRI_json_t const* json) {
  std::vector<std::string> result;

  if (isList(json)) {
    for (size_t i = 0, n = json->_value._objects._length; i < n; ++i) {
      TRI_json_t const* v = (TRI_json_t const*) TRI_AtVector(&json->_value._objects, i);

      if (isString(v)) {
        result.push_back(std::string(v->_value._string.data, v->_value._string.length - 1));
      }
    }
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief create JSON from string
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::fromString (std::string const& data) {
  TRI_json_t* json = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, data.c_str());

  return json;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief create JSON from string
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::fromString (char const* data,
                                    size_t length) {
  TRI_json_t* json = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, data);

  return json;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief stringify json
////////////////////////////////////////////////////////////////////////////////

std::string JsonHelper::toString (TRI_json_t const* json) {
  TRI_string_buffer_t buffer;

  TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);
  int res = TRI_StringifyJson(&buffer, json);

  if (res != TRI_ERROR_NO_ERROR) {
    return "";
  }

  string out(TRI_BeginStringBuffer(&buffer), TRI_LengthStringBuffer(&buffer));
  TRI_DestroyStringBuffer(&buffer);

  return out;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns an array sub-element
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::getArrayElement (TRI_json_t const* json,
                                         const char* name) {
  if (! isArray(json)) {
    return 0;
  }

  return TRI_LookupArrayJson(json, name);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns a string element, or a default it is does not exist
////////////////////////////////////////////////////////////////////////////////

std::string JsonHelper::getStringValue (TRI_json_t const* json,
                                        const std::string& defaultValue) {
  if (isString(json)) {
    return string(json->_value._string.data, json->_value._string.length - 1);
  }
  return defaultValue;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns a string sub-element, or a default it is does not exist
////////////////////////////////////////////////////////////////////////////////

std::string JsonHelper::getStringValue (TRI_json_t const* json,
                                        const char* name,
                                        const std::string& defaultValue) {
  TRI_json_t const* sub = getArrayElement(json, name);

  if (isString(sub)) {
    return string(sub->_value._string.data, sub->_value._string.length - 1);
  }
  return defaultValue;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns a boolean sub-element, or a default it is does not exist
////////////////////////////////////////////////////////////////////////////////

bool JsonHelper::getBooleanValue (TRI_json_t const* json,
                                  const char* name,
                                  bool defaultValue) {
  TRI_json_t const* sub = getArrayElement(json, name);

  if (isBoolean(sub)) {
    return sub->_value._boolean;
  }

  return defaultValue;
}

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>Fix a description of two methods.<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief json helper functions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/JsonHelper.h"

#include "BasicsC/conversions.h"
#include "BasicsC/string-buffer.h"

using namespace triagens::basics;

// -----------------------------------------------------------------------------
// --SECTION--                                                  class JsonHelper
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                             public static methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a uint64 into a JSON string
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::uint64String (TRI_memory_zone_t* zone,
                                      uint64_t value) {
  char buffer[21];
  size_t len;

  len = TRI_StringUInt64InPlace(value, (char*) &buffer);

  return TRI_CreateString2CopyJson(zone, buffer, len);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a JSON strong or number into a uint64
////////////////////////////////////////////////////////////////////////////////

uint64_t JsonHelper::stringUInt64 (TRI_json_t const* json) {
  if (json != 0) {
    if (json->_type == TRI_JSON_STRING) {
      return TRI_UInt64String2(json->_value._string.data, json->_value._string.length - 1);
    }
    else if (json->_type == TRI_JSON_NUMBER) {
      return (uint64_t) json->_value._number;
    }
  }

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a JSON strong or number into a uint64
////////////////////////////////////////////////////////////////////////////////

uint64_t JsonHelper::stringUInt64 (TRI_json_t const* json,
                                   char const* name) {

  if (json == 0) {
    return 0;
  }

  TRI_json_t const* element = TRI_LookupArrayJson(json, name);
  return stringUInt64(element);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a JSON key/value object from a list of strings
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::stringObject (TRI_memory_zone_t* zone,
                                      std::map<std::string, std::string> const& values) {
  TRI_json_t* json = TRI_CreateArray2Json(zone, values.size());

  if (json == 0) {
    return 0;
  }

  std::map<std::string, std::string>::const_iterator it;
  for (it = values.begin(); it != values.end(); ++it) {
    const std::string key = (*it).first;
    const std::string value = (*it).second;

    TRI_json_t* v = TRI_CreateString2CopyJson(zone, value.c_str(), value.size());
    if (v != 0) {
      TRI_Insert3ArrayJson(zone, json, key.c_str(), v);
    }
  }

  return json;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a key/value object of strings from a JSON (sub-) object
////////////////////////////////////////////////////////////////////////////////

std::map<std::string, std::string> JsonHelper::stringObject (TRI_json_t const* json) {
  std::map<std::string, std::string> result;

  if (isArray(json)) {
    for (size_t i = 0, n = json->_value._objects._length; i < n; i += 2) {
      TRI_json_t const* k = (TRI_json_t const*) TRI_AtVector(&json->_value._objects, i);
      TRI_json_t const* v = (TRI_json_t const*) TRI_AtVector(&json->_value._objects, i + 1);

      if (isString(k) && isString(v)) {
        const std::string key = std::string(k->_value._string.data, k->_value._string.length - 1);
        const std::string value = std::string(v->_value._string.data, v->_value._string.length - 1);
        result.insert(std::pair<std::string, std::string>(key, value));
      }
    }
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a JSON object from a list of strings
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::stringList (TRI_memory_zone_t* zone,
                                    std::vector<std::string> const& values) {
  TRI_json_t* json = TRI_CreateList2Json(zone, values.size());

  if (json == 0) {
    return 0;
  }

  for (size_t i = 0, n = values.size(); i < n; ++i) {
    TRI_json_t* v = TRI_CreateString2CopyJson(zone, values[i].c_str(), values[i].size());
    if (v != 0) {
      TRI_PushBack3ListJson(zone, json, v);
    }
  }

  return json;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a list of strings from a JSON (sub-) object
////////////////////////////////////////////////////////////////////////////////

std::vector<std::string> JsonHelper::stringList (TRI_json_t const* json) {
  std::vector<std::string> result;

  if (isList(json)) {
    for (size_t i = 0, n = json->_value._objects._length; i < n; ++i) {
      TRI_json_t const* v = (TRI_json_t const*) TRI_AtVector(&json->_value._objects, i);

      if (isString(v)) {
        result.push_back(std::string(v->_value._string.data, v->_value._string.length - 1));
      }
    }
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief create JSON from string
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::fromString (std::string const& data) {
  TRI_json_t* json = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, data.c_str());

  return json;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief create JSON from string
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::fromString (char const* data,
                                    size_t length) {
  TRI_json_t* json = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, data);

  return json;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief stringify json
////////////////////////////////////////////////////////////////////////////////

std::string JsonHelper::toString (TRI_json_t const* json) {
  TRI_string_buffer_t buffer;

  TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);
  int res = TRI_StringifyJson(&buffer, json);

  if (res != TRI_ERROR_NO_ERROR) {
    return "";
  }

  string out(TRI_BeginStringBuffer(&buffer), TRI_LengthStringBuffer(&buffer));
  TRI_DestroyStringBuffer(&buffer);

  return out;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns an array sub-element
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* JsonHelper::getArrayElement (TRI_json_t const* json,
                                         const char* name) {
  if (! isArray(json)) {
    return 0;
  }

  return TRI_LookupArrayJson(json, name);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns a string element, or a default it is does not exist
////////////////////////////////////////////////////////////////////////////////

std::string JsonHelper::getStringValue (TRI_json_t const* json,
                                        const std::string& defaultValue) {
  if (isString(json)) {
    return string(json->_value._string.data, json->_value._string.length - 1);
  }
  return defaultValue;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns a string sub-element, or a default it is does not exist
////////////////////////////////////////////////////////////////////////////////

std::string JsonHelper::getStringValue (TRI_json_t const* json,
                                        const char* name,
                                        const std::string& defaultValue) {
  TRI_json_t const* sub = getArrayElement(json, name);

  if (isString(sub)) {
    return string(sub->_value._string.data, sub->_value._string.length - 1);
  }
  return defaultValue;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns a boolean sub-element, or a default it is does not exist
////////////////////////////////////////////////////////////////////////////////

bool JsonHelper::getBooleanValue (TRI_json_t const* json,
                                  const char* name,
                                  bool defaultValue) {
  TRI_json_t const* sub = getArrayElement(json, name);

  if (isBoolean(sub)) {
    return sub->_value._boolean;
  }

  return defaultValue;
}

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>


<commit_before>#include <utility>
#include <cstdlib>

#include "number.hh"

using namespace std;

// number class definitions.
template <>
Number::complex_type Number::coerce() const{
  switch(type_){
  case Type::complex:
    return z_;
  case Type::real:
    return complex_type{f_};
  case Type::integer:
    return complex_type{static_cast<real_type>(i_)};
  case Type::uninitialized:
  default:
    UNEXP_CONVERSION("complex");
  }
}

template <>
Number::real_type Number::coerce() const{
  switch(type_){
  case Type::real:
    return f_;
  case Type::integer:
    return static_cast<real_type>(i_);
  case Type::complex:
  case Type::uninitialized:
  default:
    UNEXP_CONVERSION("real");
  }
}

template <>
Number::integer_type Number::coerce() const{
  switch(type_){
  case Type::integer:
    return i_;
  case Type::complex:
  case Type::real:
  case Type::uninitialized:
  default:
    UNEXP_CONVERSION("integer");
  }
}

// number parsers
namespace {

enum class Exactness{
  exact, inexact, unspecified
    };

struct PrefixValue {
  const int radix;
  const Exactness ex;

  constexpr PrefixValue() // error value
    : radix(0), ex(Exactness::unspecified){}

  constexpr PrefixValue(int r, Exactness e)
    : radix(r), ex(e){}

  explicit operator bool() const {
    return (radix != 0);
  }
};

PrefixValue parse_number_prefix(FILE* f){
  int r = 10;
  Exactness e = Exactness::unspecified;
  bool r_appeared = false, e_appeared = false;

  for(int loop = 0; loop < 2; ++loop){
    decltype(fgetc(f)) c = fgetc(f);

    if(c != '#'){
      ungetc(c, f);
      return {r, e};
    }

    switch(c = fgetc(f)){
    case 'i': case 'e':
      if(e_appeared) return {};
      e_appeared = true;
      e = (c == 'i') ? Exactness::inexact
        : Exactness::exact;
      break;
    case 'b': case 'o': case 'd': case 'x':
      if(r_appeared) return {};
      r_appeared = true;
      r = (c == 'b') ? 2
        : (c == 'o') ? 8
        : (c == 'd') ? 10
        : 16;
      break;
    default:
      fprintf(stderr, "reader error: unknown number prefix '%c' appeared!\n", c);
      return {};
    }
  }

  return {r, e};
}

inline
bool is_number_char(int radix, char c){
  switch(radix){
  case 16:
    return isxdigit(c);

  case 10:
    return isdigit(c);

  case 8:
    switch(c){
    case '0': case '1':
    case '2': case '3': case '4':
    case '5': case '6': case '7':
      return true;
    default:
      return false;
    }

  case 2:
    switch(c){
    case '0': case '1':
      return true;
    default:
      return false;
    }

  default:
    UNEXP_DEFAULT();
  }
}

int eat_sharp(FILE* f, string& o){
  decltype(fgetc(f)) c;
  int sharps = 0;

  while((c = fgetc(f)) == '#'){
    o.push_back('0');
    ++sharps;
  }
  ungetc(c, f);

  return sharps;
}

struct ParserRet {
  const Number number;
  const Exactness ex;

  constexpr ParserRet() // error value
    : number(), ex(Exactness::unspecified){}

  constexpr ParserRet(const Number& n, Exactness e)
    : number(n), ex(e){}

  explicit operator bool() const {
    return static_cast<bool>(number);
  }
};

ParserRet parse_unsigned(int radix, FILE* f, string& s){
  decltype(fgetc(f)) c;

  while(is_number_char(radix, c = fgetc(f)))
    s.push_back(c);
  ungetc(c, f);

  if(s.empty()){
    return {};
  }

  Exactness e;

  if(eat_sharp(f, s) > 0){
    e = Exactness::inexact;
  }else{
    e = Exactness::exact;
  }

  errno = 0;
  long l = strtol(s.c_str(), nullptr, radix);
  if(errno) return {};

  return {Number{l}, e};
}

inline
bool check_decimal_suffix(char c){
  switch(c){
  case 'e': case 's': case 'f': case 'd': case 'l':
    return true;
  default:
    return false;
  }
}

ParserRet parse_decimal(FILE* f, string& s){
  decltype(fgetc(f)) c;
  bool dot_start = false;
  int sharps_before_dot = 0;

  if(s.empty()){
    if((c = fgetc(f)) == '.'){
      ungetc(c, f);
      dot_start = true;
    }else{
      return {};
    }
  }else{
    sharps_before_dot = eat_sharp(f, s);
  }

  if((c = fgetc(f)) != '.'){
    goto end; // 1. no frac part
  }
  s.push_back('.');

  if(sharps_before_dot > 0){
    eat_sharp(f, s);
    goto end; // 4. only sharps after dot
  }

  {
    bool digits_after_dot = false;

    while(is_number_char(10, c = fgetc(f))){
      digits_after_dot = true;
      s.push_back(c);
    }
    ungetc(c, f);

    if(dot_start && !digits_after_dot)
      return {}; // 2. dot start should have digits

    eat_sharp(f, s);
  }

 end:
  if(check_decimal_suffix(c = fgetc(f))){
    s.push_back('e');

    switch(c = fgetc(f)){
    case '+': case '-':
      s.push_back(c); break;
    default:
      ungetc(c, f); break;
    }

    {
      bool exp_digits = false;

      while(is_number_char(10, c = fgetc(f))){
        exp_digits = true;
        s.push_back(c);
      }
      ungetc(c, f);

      if(!exp_digits)
        return {}; // no number on exp. part
    }
  }else{
    ungetc(c, f);
  }

  return {Number{strtod(s.c_str(), nullptr)},
      Exactness::inexact};
}

ParserRet parse_real_number(int radix, FILE* f){
  decltype(fgetc(f)) c;
  int sign = 1;

  switch(c = fgetc(f)){
  case '+':
    sign = 1;
    break;
  case '-':
    sign = -1;
    break;
  default:
    sign = 1;
    ungetc(c, f);
    break;
  }

  string s;

  auto u1 = parse_unsigned(radix, f, s);
  c = fgetc(f);

  if((c == '.') || (u1 && check_decimal_suffix(c))){
    // decimal float
    if(radix == 10){
      ungetc(c, f);
      auto n = parse_decimal(f, s);

      if(n.number.type() == Number::Type::real){
        return {Number{n.number.coerce<double>() * sign},
            Exactness::inexact};
      }
    }
    return {};
  }else if(!u1){
    return {};
  }else if(c == '/'){
    // rational
    string s2;
    auto u2 = parse_unsigned(radix, f, s2);
    if(!u2) return {};

    return {Number(sign * u1.number.coerce<double>() / u2.number.coerce<double>()),
        Exactness::inexact};
  }else{
    // integer?
    ungetc(c, f);
    // FIXME: inexact or super-big integer can be fall into float.
    return {Number(sign * u1.number.coerce<long>()), u1.ex};
  }
}

ParserRet parse_complex(int radix, FILE* f){
  const auto first_char = fgetc(f);
  ungetc(first_char, f);

  // has real part
  auto real = parse_real_number(radix, f);
  if(!real) return {};

  switch(auto c = fgetc(f)){
  case '@': {// polar literal
    auto deg = parse_real_number(radix, f);
    if(!deg) return {};

    return {Number{polar(real.number.coerce<double>(), deg.number.coerce<double>())},
        Exactness::inexact};
  }
  case '+': case '-': {
    const int sign = (c == '+') ? 1 : -1;

    if((c = fgetc(f)) == 'i'){
      return {Number{real.number.coerce<double>(), static_cast<double>(sign)},
          Exactness::inexact};
    }
    ungetc(c, f);

    auto imag = parse_real_number(radix, f);
    if(!imag || fgetc(f) != 'i')
      return {};

    return {Number{real.number.coerce<double>(), imag.number.coerce<double>() * sign},
        Exactness::inexact};
  }
  case 'i':
    if(first_char == '+' || first_char == '-'){
      return {Number{0, real.number.coerce<double>()},
          Exactness::inexact};
    }else{
      return {};
    }
  default:
    ungetc(c, f);
    return real;
  }
}

} // namespace

Number parse_number(FILE* f){
  const auto prefix_info = parse_number_prefix(f);
  if(!prefix_info) return {};

  const auto r = parse_complex(prefix_info.radix, f);
  if(!r) return {};

  if(prefix_info.ex == Exactness::unspecified
     || prefix_info.ex == r.ex){
    return r.number;
  }else if(prefix_info.ex == Exactness::exact){
    return to_exact(r.number);
  }else{
    return to_inexact(r.number);
  }
}

bool eql(const Number& n, const Number& m){
  if(n.type() != m.type()) return false;

  switch(n.type()){
  case Number::Type::uninitialized:
    return false;
  case Number::Type::complex:
    return n.get<Number::complex_type>() == m.get<Number::complex_type>();
  case Number::Type::real:
    return n.get<Number::real_type>() == m.get<Number::real_type>();
  case Number::Type::integer:
    return n.get<Number::integer_type>() == m.get<Number::integer_type>();
  default:
    UNEXP_DEFAULT();
  }
}

void print(FILE* f, const Number& n){
  switch(n.type()){
  case Number::Type::uninitialized:
    fprintf(f, "(uninitialied number)");
    break;
  case Number::Type::complex: {
    auto&& z = n.get<Number::complex_type>();
    fprintf(f, "%g+%gi", z.real(), z.imag());
  }
    break;
  case Number::Type::real:
    fprintf(f, "%g", n.get<Number::real_type>());
    break;
  case Number::Type::integer:
    fprintf(f, "%ld", n.get<Number::integer_type>());
    break;
  default:
    UNEXP_DEFAULT();
  }
}

Number to_exact(const Number& n){
  switch(n.type()){
  case Number::Type::complex:
    return {}; // not supported
  case Number::Type::real:
    return {}; // not supported
  case Number::Type::integer:
    return n;
  case Number::Type::uninitialized:
  default:
    return {};
  }
}

Number to_inexact(const Number& n){
  switch(n.type()){
  case Number::Type::complex:
    return n;
  case Number::Type::real:
    return n;
  case Number::Type::integer:
    return Number{static_cast<Number::real_type>
        (n.get<Number::integer_type>())};
  case Number::Type::uninitialized:
  default:
    return {};
  }
}

const char* stringify(Number::Type t){
  switch(t){
  case Number::Type::uninitialized:
    return "uninitialized";
  case Number::Type::complex:
    return "complex";
  case Number::Type::real:
    return "real";
  case Number::Type::integer:
    return "integer";
  default:
    return "(unknown number type)";
  }
}

void describe(FILE* f, Number::Type t){
  fputs(stringify(t), f);
}

void describe(FILE* f, const Number& n){
  const auto t = n.type();

  fprintf(f, "Number: %s(", stringify(t));
  print(f, n);
  fputc(')', f);
}

<commit_msg>bitly number parser change<commit_after>#include <utility>
#include <cstdlib>

#include "number.hh"

using namespace std;

// number class definitions.
template <>
Number::complex_type Number::coerce() const{
  switch(type_){
  case Type::complex:
    return z_;
  case Type::real:
    return complex_type{f_};
  case Type::integer:
    return complex_type{static_cast<real_type>(i_)};
  case Type::uninitialized:
  default:
    UNEXP_CONVERSION("complex");
  }
}

template <>
Number::real_type Number::coerce() const{
  switch(type_){
  case Type::real:
    return f_;
  case Type::integer:
    return static_cast<real_type>(i_);
  case Type::complex:
  case Type::uninitialized:
  default:
    UNEXP_CONVERSION("real");
  }
}

template <>
Number::integer_type Number::coerce() const{
  switch(type_){
  case Type::integer:
    return i_;
  case Type::complex:
  case Type::real:
  case Type::uninitialized:
  default:
    UNEXP_CONVERSION("integer");
  }
}

// number parsers
namespace {

enum class Exactness{
  exact, inexact, unspecified
    };

struct PrefixValue {
  const int radix;
  const Exactness ex;

  constexpr PrefixValue() // error value
    : radix(0), ex(Exactness::unspecified){}

  constexpr PrefixValue(int r, Exactness e)
    : radix(r), ex(e){}

  explicit operator bool() const {
    return (radix != 0);
  }
};

PrefixValue parse_number_prefix(FILE* f){
  int r = 10;
  Exactness e = Exactness::unspecified;
  bool r_appeared = false, e_appeared = false;

  for(int loop = 0; loop < 2; ++loop){
    decltype(fgetc(f)) c = fgetc(f);

    if(c != '#'){
      ungetc(c, f);
      return {r, e};
    }

    switch(c = fgetc(f)){
    case 'i': case 'e':
      if(e_appeared) return {};
      e_appeared = true;
      e = (c == 'i') ? Exactness::inexact
        : Exactness::exact;
      break;
    case 'b': case 'o': case 'd': case 'x':
      if(r_appeared) return {};
      r_appeared = true;
      r = (c == 'b') ? 2
        : (c == 'o') ? 8
        : (c == 'd') ? 10
        : 16;
      break;
    default:
      fprintf(stderr, "reader error: unknown number prefix '%c' appeared!\n", c);
      return {};
    }
  }

  return {r, e};
}

inline
bool is_number_char(int radix, char c){
  switch(radix){
  case 16:
    return isxdigit(c);

  case 10:
    return isdigit(c);

  case 8:
    switch(c){
    case '0': case '1':
    case '2': case '3': case '4':
    case '5': case '6': case '7':
      return true;
    default:
      return false;
    }

  case 2:
    switch(c){
    case '0': case '1':
      return true;
    default:
      return false;
    }

  default:
    UNEXP_DEFAULT();
  }
}

int eat_sharp(FILE* f, string& o){
  decltype(fgetc(f)) c;
  int sharps = 0;

  while((c = fgetc(f)) == '#'){
    o.push_back('0');
    ++sharps;
  }
  ungetc(c, f);

  return sharps;
}

struct ParserRet {
  const Number number;
  const Exactness ex;

  constexpr ParserRet() // error value
    : number(), ex(Exactness::unspecified){}

  constexpr ParserRet(const Number& n, Exactness e)
    : number(n), ex(e){}

  explicit operator bool() const {
    return static_cast<bool>(number);
  }
};

ParserRet parse_unsigned(int radix, FILE* f, string& s){
  decltype(fgetc(f)) c;

  while(is_number_char(radix, c = fgetc(f)))
    s.push_back(c);
  ungetc(c, f);

  if(s.empty()){
    return {};
  }

  Exactness e;

  if(eat_sharp(f, s) > 0){
    e = Exactness::inexact;
  }else{
    e = Exactness::exact;
  }

  errno = 0;
  long l = strtol(s.c_str(), nullptr, radix);
  if(errno) return {};

  return {Number{l}, e};
}

inline
bool check_decimal_suffix(char c){
  switch(c){
  case 'e': case 's': case 'f': case 'd': case 'l':
    return true;
  default:
    return false;
  }
}

ParserRet parse_decimal(FILE* f, string& s){
  decltype(fgetc(f)) c;
  bool dot_start = false;
  int sharps_before_dot = 0;

  if(s.empty()){
    if((c = fgetc(f)) == '.'){
      ungetc(c, f);
      dot_start = true;
    }else{
      return {};
    }
  }else{
    sharps_before_dot = eat_sharp(f, s);
  }

  if((c = fgetc(f)) != '.'){
    goto end; // 1. no frac part
  }
  s.push_back('.');

  if(sharps_before_dot > 0){
    eat_sharp(f, s);
    goto end; // 4. only sharps after dot
  }

  {
    bool digits_after_dot = false;

    while(isdigit(c = fgetc(f))){
      digits_after_dot = true;
      s.push_back(c);
    }
    ungetc(c, f);

    if(dot_start && !digits_after_dot)
      return {}; // 2. dot start should have digits

    eat_sharp(f, s);
  }

 end:
  if(check_decimal_suffix(c = fgetc(f))){
    s.push_back('e');

    switch(c = fgetc(f)){
    case '+': case '-':
      s.push_back(c); break;
    default:
      ungetc(c, f); break;
    }

    {
      bool exp_digits = false;

      while(isdigit(c = fgetc(f))){
        exp_digits = true;
        s.push_back(c);
      }
      ungetc(c, f);

      if(!exp_digits)
        return {}; // no number on exp. part
    }
  }else{
    ungetc(c, f);
  }

  return {Number{strtod(s.c_str(), nullptr)},
      Exactness::inexact};
}

ParserRet parse_real_number(int radix, FILE* f){
  decltype(fgetc(f)) c;
  int sign = 1;

  switch(c = fgetc(f)){
  case '+':
    sign = 1;
    break;
  case '-':
    sign = -1;
    break;
  default:
    sign = 1;
    ungetc(c, f);
    break;
  }

  string s;

  auto u1 = parse_unsigned(radix, f, s);
  c = fgetc(f);

  if((c == '.') || (u1 && check_decimal_suffix(c))){
    // decimal float
    if(radix == 10){
      ungetc(c, f);
      auto n = parse_decimal(f, s);

      if(n.number.type() == Number::Type::real){
        return {Number{n.number.coerce<double>() * sign},
            Exactness::inexact};
      }
    }
    return {};
  }else if(!u1){
    return {};
  }else if(c == '/'){
    // rational
    string s2;
    auto u2 = parse_unsigned(radix, f, s2);
    if(!u2) return {};

    return {Number(sign * u1.number.coerce<double>() / u2.number.coerce<double>()),
        Exactness::inexact};
  }else{
    // integer?
    ungetc(c, f);
    // FIXME: inexact or super-big integer can be fall into float.
    return {Number(sign * u1.number.coerce<long>()), u1.ex};
  }
}

ParserRet parse_complex(int radix, FILE* f){
  const auto first_char = fgetc(f);
  ungetc(first_char, f);

  // has real part
  auto real = parse_real_number(radix, f);
  if(!real) return {};

  switch(auto c = fgetc(f)){
  case '@': {// polar literal
    auto deg = parse_real_number(radix, f);
    if(!deg) return {};

    return {Number{polar(real.number.coerce<double>(), deg.number.coerce<double>())},
        Exactness::inexact};
  }
  case '+': case '-': {
    const int sign = (c == '+') ? 1 : -1;

    if((c = fgetc(f)) == 'i'){
      return {Number{real.number.coerce<double>(), static_cast<double>(sign)},
          Exactness::inexact};
    }
    ungetc(c, f);

    auto imag = parse_real_number(radix, f);
    if(!imag || fgetc(f) != 'i')
      return {};

    return {Number{real.number.coerce<double>(), imag.number.coerce<double>() * sign},
        Exactness::inexact};
  }
  case 'i':
    if(first_char == '+' || first_char == '-'){
      return {Number{0, real.number.coerce<double>()},
          Exactness::inexact};
    }else{
      return {};
    }
  default:
    ungetc(c, f);
    return real;
  }
}

} // namespace

Number parse_number(FILE* f){
  const auto prefix_info = parse_number_prefix(f);
  if(!prefix_info) return {};

  const auto r = parse_complex(prefix_info.radix, f);
  if(!r) return {};

  if(prefix_info.ex == Exactness::unspecified
     || prefix_info.ex == r.ex){
    return r.number;
  }else if(prefix_info.ex == Exactness::exact){
    return to_exact(r.number);
  }else{
    return to_inexact(r.number);
  }
}

bool eql(const Number& n, const Number& m){
  if(n.type() != m.type()) return false;

  switch(n.type()){
  case Number::Type::uninitialized:
    return false;
  case Number::Type::complex:
    return n.get<Number::complex_type>() == m.get<Number::complex_type>();
  case Number::Type::real:
    return n.get<Number::real_type>() == m.get<Number::real_type>();
  case Number::Type::integer:
    return n.get<Number::integer_type>() == m.get<Number::integer_type>();
  default:
    UNEXP_DEFAULT();
  }
}

void print(FILE* f, const Number& n){
  switch(n.type()){
  case Number::Type::uninitialized:
    fprintf(f, "(uninitialied number)");
    break;
  case Number::Type::complex: {
    auto&& z = n.get<Number::complex_type>();
    fprintf(f, "%g+%gi", z.real(), z.imag());
  }
    break;
  case Number::Type::real:
    fprintf(f, "%g", n.get<Number::real_type>());
    break;
  case Number::Type::integer:
    fprintf(f, "%ld", n.get<Number::integer_type>());
    break;
  default:
    UNEXP_DEFAULT();
  }
}

Number to_exact(const Number& n){
  switch(n.type()){
  case Number::Type::complex:
    return {}; // not supported
  case Number::Type::real:
    return {}; // not supported
  case Number::Type::integer:
    return n;
  case Number::Type::uninitialized:
  default:
    return {};
  }
}

Number to_inexact(const Number& n){
  switch(n.type()){
  case Number::Type::complex:
    return n;
  case Number::Type::real:
    return n;
  case Number::Type::integer:
    return Number{static_cast<Number::real_type>
        (n.get<Number::integer_type>())};
  case Number::Type::uninitialized:
  default:
    return {};
  }
}

const char* stringify(Number::Type t){
  switch(t){
  case Number::Type::uninitialized:
    return "uninitialized";
  case Number::Type::complex:
    return "complex";
  case Number::Type::real:
    return "real";
  case Number::Type::integer:
    return "integer";
  default:
    return "(unknown number type)";
  }
}

void describe(FILE* f, Number::Type t){
  fputs(stringify(t), f);
}

void describe(FILE* f, const Number& n){
  const auto t = n.type();

  fprintf(f, "Number: %s(", stringify(t));
  print(f, n);
  fputc(')', f);
}

<|endoftext|>


<commit_before>/*
 * IceWM
 *
 * Copyright (C) 1999-2002 Marko Macek
 */
#include "config.h"
#include "objmenu.h"
#include "objbar.h"
#include "objbutton.h"
#include "ybutton.h"
#include "prefs.h"
#include "wmtaskbar.h"
#include "wmapp.h"
#include "wpixmaps.h"
#include "yrect.h"
#include "yicon.h"

ref<YFont> ObjectButton::font;
YColor * ObjectButton::bgColor(NULL);
YColor * ObjectButton::fgColor(NULL);

ObjectBar::ObjectBar(YWindow *parent): YWindow(parent) {
    setSize(1, 1);
}

ObjectBar::~ObjectBar() {
}

void ObjectBar::addButton(const ustring &name, ref<YIcon> icon, YButton *button) {
    button->setToolTip(name);
    if (icon != null) {
        button->setIcon(icon, YIcon::smallSize());
        button->setSize(button->width() + 4, button->width() + 4);
    } else
        button->setText(name);

    button->setPosition(width(), 0);
    int h = button->height();
    if (h < height())
        h = height();

    if (h < height())
        h = height();

    button->setSize(button->width(), h);
    setSize(width() + button->width(), h);
    button->show();

    objects.append(button);
}

void ObjectBar::paint(Graphics &g, const YRect &/*r*/) {
    ref<YImage> gradient(parent()->getGradient());

    if (gradient != null)
        g.drawImage(gradient, this->x(), this->y(), width(), height(), 0, 0);
    else
    if (taskbackPixmap != null)
        g.fillPixmap(taskbackPixmap, 0, 0, width(), height());
    else {
        g.setColor(getTaskBarBg());
        g.fillRect(0, 0, width(), height());
    }
}

void ObjectBar::addObject(DObject *object) {
    YButton *button = new ObjectButton(this, object);
    addButton(object->getName(), object->getIcon(), button);
}

void ObjectBar::addSeparator() {
    setSize(width() + 4, height());
    objects.append(0);
}

void ObjectBar::addContainer(const ustring &name, ref<YIcon> icon, ObjectContainer *container) {
    if (container) {
        YButton *button = new ObjectButton(this, (YMenu*) container);
        addButton(name, icon, button);
    }
}

void ObjectBar::configure(const YRect &r) {
    YWindow::configure(r);

    int left = 0;
    for (int i = 0; i < objects.getCount(); i++) {
        YButton *obj = objects[i];
        if (obj) {
            obj->setGeometry(YRect(left, 0, obj->width(), height()));
            left += obj->width();
        } else
            left += 4;
    }
}

ref<YFont> ObjectButton::getFont() {
    return font != null ? font : font =
        (*toolButtonFontName ? YFont::getFont(XFA(toolButtonFontName))
         : YButton::getFont());
}

YColor * ObjectButton::getColor() {
    return *clrToolButtonText
        ? fgColor ? fgColor : fgColor = new YColor(clrToolButtonText)
        : YButton::getColor();
}

YSurface ObjectButton::getSurface() {
    if (bgColor == 0)
        bgColor = new YColor(*clrToolButton ? clrToolButton : clrNormalButton);

    return YSurface(bgColor, toolbuttonPixmap, toolbuttonPixbuf);
}

void ObjectButton::actionPerformed(YAction action, unsigned modifiers) {
    wmapp->signalGuiEvent(geLaunchApp);
    if (fObject) fObject->open();
    else YButton::actionPerformed(action, modifiers);
}

ObjectMenu *rootMenu(NULL);

// vim: set sw=4 ts=4 et:
<commit_msg>Use dynamic_cast for downcast from container to menu and check the result for issue #195.<commit_after>/*
 * IceWM
 *
 * Copyright (C) 1999-2002 Marko Macek
 */
#include "config.h"
#include "objmenu.h"
#include "objbar.h"
#include "objbutton.h"
#include "ybutton.h"
#include "prefs.h"
#include "wmtaskbar.h"
#include "wmapp.h"
#include "wpixmaps.h"
#include "yrect.h"
#include "yicon.h"

ref<YFont> ObjectButton::font;
YColor * ObjectButton::bgColor(NULL);
YColor * ObjectButton::fgColor(NULL);

ObjectBar::ObjectBar(YWindow *parent): YWindow(parent) {
    setSize(1, 1);
}

ObjectBar::~ObjectBar() {
}

void ObjectBar::addButton(const ustring &name, ref<YIcon> icon, YButton *button) {
    button->setToolTip(name);
    if (icon != null) {
        button->setIcon(icon, YIcon::smallSize());
        button->setSize(button->width() + 4, button->width() + 4);
    } else
        button->setText(name);

    button->setPosition(width(), 0);
    int h = button->height();
    if (h < height())
        h = height();

    if (h < height())
        h = height();

    button->setSize(button->width(), h);
    setSize(width() + button->width(), h);
    button->show();

    objects.append(button);
}

void ObjectBar::paint(Graphics &g, const YRect &/*r*/) {
    ref<YImage> gradient(parent()->getGradient());

    if (gradient != null)
        g.drawImage(gradient, this->x(), this->y(), width(), height(), 0, 0);
    else
    if (taskbackPixmap != null)
        g.fillPixmap(taskbackPixmap, 0, 0, width(), height());
    else {
        g.setColor(getTaskBarBg());
        g.fillRect(0, 0, width(), height());
    }
}

void ObjectBar::addObject(DObject *object) {
    YButton *button = new ObjectButton(this, object);
    addButton(object->getName(), object->getIcon(), button);
}

void ObjectBar::addSeparator() {
    setSize(width() + 4, height());
    objects.append(0);
}

void ObjectBar::addContainer(const ustring &name, ref<YIcon> icon, ObjectContainer *container) {
    if (container) {
        ObjectMenu* menu = dynamic_cast<ObjectMenu *>(container);
        PRECONDITION(menu);
        if (!menu) return CARP(Bad menu);
        YButton *button = new ObjectButton(this, menu);
        addButton(name, icon, button);
    }
}

void ObjectBar::configure(const YRect &r) {
    YWindow::configure(r);

    int left = 0;
    for (int i = 0; i < objects.getCount(); i++) {
        YButton *obj = objects[i];
        if (obj) {
            obj->setGeometry(YRect(left, 0, obj->width(), height()));
            left += obj->width();
        } else
            left += 4;
    }
}

ref<YFont> ObjectButton::getFont() {
    return font != null ? font : font =
        (*toolButtonFontName ? YFont::getFont(XFA(toolButtonFontName))
         : YButton::getFont());
}

YColor * ObjectButton::getColor() {
    return *clrToolButtonText
        ? fgColor ? fgColor : fgColor = new YColor(clrToolButtonText)
        : YButton::getColor();
}

YSurface ObjectButton::getSurface() {
    if (bgColor == 0)
        bgColor = new YColor(*clrToolButton ? clrToolButton : clrNormalButton);

    return YSurface(bgColor, toolbuttonPixmap, toolbuttonPixbuf);
}

void ObjectButton::actionPerformed(YAction action, unsigned modifiers) {
    wmapp->signalGuiEvent(geLaunchApp);
    if (fObject) fObject->open();
    else YButton::actionPerformed(action, modifiers);
}

ObjectMenu *rootMenu(NULL);

// vim: set sw=4 ts=4 et:
<|endoftext|>


<commit_before>// Copyright 2015 Chris Sattinger
#include "ofApp.h"
#include "ofMain.h"
#include <stdio.h>
#include "style.h"

//--------------------------------------------------------------
void ofApp::setup() {
    ofSetVerticalSync(true);
    ofSetFrameRate(60);

    ofAddListener(dataSource.didLoadEvent, this, &ofApp::dataSourceDidLoad);

    windowResized(ofGetWidth(), ofGetHeight());

    setupGui();
}

void ofApp::setupGui() {
    gui = new ofxDatGui(ofxDatGuiAnchor::TOP_RIGHT);
    controls.loadButton = gui->addButton("Click to load dataset");
    controls.selectSound = gui->addDropdown("Sound", superCollider.defNames());
    controls.selectSound->select(0);  // what is actual index of current sound ?
    controls.pointRadius = gui->addSlider("Point radius", 1, 6, scatterPlots.pointRadius);
    controls.brushWidth = gui->addSlider("Brush Width", 1, 15, scatterPlots.brush.brushWidth);
    controls.brushHeight = gui->addSlider("Brush Height", 1, 15, scatterPlots.brush.brushHeight);
    controls.amp = gui->addSlider("Amp", 0.0, 1.0, sonifier.amp);
    controls.sustain = gui->addSlider("Sustain", 0.005, 1.0, sonifier.sustain);
    controls.freqBase = gui->addSlider("Freq", 220, 3520, sonifier.freqBase);

    // gui->addColorPicker("Brush Color", engagedPointColor);
    gui->addFRM(1.0f);

    gui->onButtonEvent(this, &ofApp::onOfxDatGuiButtonEvent);
    gui->onSliderEvent(this, &ofApp::onOfxDatGuiSliderEvent);
    gui->onDropdownEvent(this, &ofApp::onOfxDatGuiDropdownEvent);
}

//--------------------------------------------------------------
void ofApp::update() {
}

//--------------------------------------------------------------
void ofApp::draw() {
    ofBackground(settingsBackground);
    scatterPlots.draw();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key) {
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key) {
}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y) {
    scatterPlots.brush.mouseMoved(x, ofGetHeight() - y);
}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button) {
    scatterPlots.brush.mouseDragged(x, ofGetHeight() - y, button);
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button) {
    scatterPlots.brush.mousePressed(x, ofGetHeight() - y, button);
}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button) {
    scatterPlots.brush.mouseReleased(x, ofGetHeight() - y, button);
}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y) {
}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y) {
}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h) {
    const double panelWidth = 310;
    auto rect = ofRectangle(0, 0, w - panelWidth - gutter - gutter, h);
    scatterPlots.setFrame(rect);
}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg) {
}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo) {
    auto path = dragInfo.files.at(dragInfo.files.size() - 1);
    dataSource.load(path);
}

void ofApp::dataSourceDidLoad() {
    scatterPlots.setData(dataSource);
    controls.loadButton->setLabel(dataSource.title);
}

void ofApp::onOfxDatGuiButtonEvent(ofxDatGuiButtonEvent e) {
    if (e.target == controls.loadButton) {
        // initial load file dialog
    }
}

void ofApp::onOfxDatGuiDropdownEvent(ofxDatGuiDropdownEvent e) {
    if (e.target == controls.selectSound) {
        sonifier.selectSynthDef(e.child);
    }
}

void ofApp::onOfxDatGuiSliderEvent(ofxDatGuiSliderEvent e) {
    if (e.target == controls.brushHeight) {
        scatterPlots.brush.brushHeight = e.value;
    } else if (e.target == controls.brushWidth) {
        scatterPlots.brush.brushWidth = e.value;
    } else if (e.target == controls.pointRadius) {
        scatterPlots.pointRadius = e.value;
        scatterPlots.redrawPlotter();
    } else if (e.target == controls.amp) {
        sonifier.amp = e.value;
    } else if (e.target == controls.sustain) {
        sonifier.sustain = e.value;
    } else if (e.target == controls.freqBase) {
        sonifier.freqBase = e.value;
    }
}
<commit_msg>prevent auto-selecting the first sound if there are none loaded<commit_after>// Copyright 2015 Chris Sattinger
#include "ofApp.h"
#include "ofMain.h"
#include <stdio.h>
#include "style.h"

//--------------------------------------------------------------
void ofApp::setup() {
    ofSetVerticalSync(true);
    ofSetFrameRate(60);

    ofAddListener(dataSource.didLoadEvent, this, &ofApp::dataSourceDidLoad);

    windowResized(ofGetWidth(), ofGetHeight());

    if (sonifier.sound() == "") {
        if (superCollider.synthDefs.size() > 0) {
            sonifier.selectSynthDef(0);
        }
    }

    setupGui();
}

void ofApp::setupGui() {
    gui = new ofxDatGui(ofxDatGuiAnchor::TOP_RIGHT);
    controls.loadButton = gui->addButton("Click to load dataset");
    controls.selectSound = gui->addDropdown("Sound", superCollider.defNames());
    controls.selectSound->select(0);  // what is actual index of current sound ?
    controls.pointRadius = gui->addSlider("Point radius", 1, 6, scatterPlots.pointRadius);
    controls.brushWidth = gui->addSlider("Brush Width", 1, 15, scatterPlots.brush.brushWidth);
    controls.brushHeight = gui->addSlider("Brush Height", 1, 15, scatterPlots.brush.brushHeight);
    controls.amp = gui->addSlider("Amp", 0.0, 1.0, sonifier.amp);
    controls.sustain = gui->addSlider("Sustain", 0.005, 1.0, sonifier.sustain);
    controls.freqBase = gui->addSlider("Freq", 220, 3520, sonifier.freqBase);

    // gui->addColorPicker("Brush Color", engagedPointColor);
    gui->addFRM(1.0f);

    gui->onButtonEvent(this, &ofApp::onOfxDatGuiButtonEvent);
    gui->onSliderEvent(this, &ofApp::onOfxDatGuiSliderEvent);
    gui->onDropdownEvent(this, &ofApp::onOfxDatGuiDropdownEvent);
}

//--------------------------------------------------------------
void ofApp::update() {
}

//--------------------------------------------------------------
void ofApp::draw() {
    ofBackground(settingsBackground);
    scatterPlots.draw();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key) {
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key) {
}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y) {
    scatterPlots.brush.mouseMoved(x, ofGetHeight() - y);
}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button) {
    scatterPlots.brush.mouseDragged(x, ofGetHeight() - y, button);
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button) {
    scatterPlots.brush.mousePressed(x, ofGetHeight() - y, button);
}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button) {
    scatterPlots.brush.mouseReleased(x, ofGetHeight() - y, button);
}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y) {
}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y) {
}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h) {
    const double panelWidth = 310;
    auto rect = ofRectangle(0, 0, w - panelWidth - gutter - gutter, h);
    scatterPlots.setFrame(rect);
}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg) {
}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo) {
    auto path = dragInfo.files.at(dragInfo.files.size() - 1);
    dataSource.load(path);
}

void ofApp::dataSourceDidLoad() {
    scatterPlots.setData(dataSource);
    controls.loadButton->setLabel(dataSource.title);
}

void ofApp::onOfxDatGuiButtonEvent(ofxDatGuiButtonEvent e) {
    if (e.target == controls.loadButton) {
        // initial load file dialog
    }
}

void ofApp::onOfxDatGuiDropdownEvent(ofxDatGuiDropdownEvent e) {
    if (e.target == controls.selectSound) {
        sonifier.selectSynthDef(e.child);
    }
}

void ofApp::onOfxDatGuiSliderEvent(ofxDatGuiSliderEvent e) {
    if (e.target == controls.brushHeight) {
        scatterPlots.brush.brushHeight = e.value;
    } else if (e.target == controls.brushWidth) {
        scatterPlots.brush.brushWidth = e.value;
    } else if (e.target == controls.pointRadius) {
        scatterPlots.pointRadius = e.value;
        scatterPlots.redrawPlotter();
    } else if (e.target == controls.amp) {
        sonifier.amp = e.value;
    } else if (e.target == controls.sustain) {
        sonifier.sustain = e.value;
    } else if (e.target == controls.freqBase) {
        sonifier.freqBase = e.value;
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include "btree.h"

using namespace std;

int main(int argc, char** argv)
{
    {
        btree index;
        for (int i = 0; i < 8; i++)
        {
            index.insert(8 - i, i + 1);
            index.print();
            cout << "====================" << endl;
        }

        index.remove(5);

        cout << "After remove" << endl;
        index.print();

    }

    return 0;
}<commit_msg>Randomized testing found interesting access violation<commit_after>#include <iostream>
#include <map>
#include <cstdlib>
#include <cassert>
#include "btree.h"

using namespace std;

int main(int argc, char** argv)
{
    map<int, int> reference;
    btree tree;
    srand(0);
    int min_key = -30;
    int max_key = 30;
    for (int i = 0; i < 1000; i++)
    {
        int operation = rand() % 3;
        switch (operation)
        {
        case 0:
        {
            int key_to_insert = rand() % (max_key - min_key) + min_key;
            int val_to_insert = rand() % (max_key - min_key) + min_key;
            bool insertion_result = tree.insert(key_to_insert, val_to_insert);
            if (reference.find(key_to_insert) == reference.end())
            {
                reference.insert(make_pair(key_to_insert, val_to_insert));
                assert(insertion_result);
            }
            else
            {
                assert(!insertion_result);
            }
        }
        break;
        case 1:
        {
            int key_to_remove = rand() % (max_key - min_key) + min_key;
            bool remove_result = tree.remove(key_to_remove);
            if (reference.find(key_to_remove) != reference.end())
            {
                reference.erase(key_to_remove);
                assert(remove_result);
            }
            else
            {
                assert(!remove_result);
            }
        }
        break;
        case 2:
        {
            int select_answer;
            int key_to_select = rand() % (max_key - min_key) + min_key;
            bool select_result = tree.select(key_to_select, &select_answer);
            if (reference.find(key_to_select) != reference.end())
            {
                assert(select_result);
                assert(reference[key_to_select] == select_answer);
            }
            else
            {
                assert(!select_result);
            }

            break;
        }
        }

    }

    return 0;
}<|endoftext|>


<commit_before>// statTemplates.cpp : Defines the entry point for the DLL application.
//

#include "statTemplates.h"
#include "bzfsAPI.h"
#include "plugin_utils.h"

double start;
std::string getFileHeader ( void )
{
  start = bz_getCurrentTime();
  std::string page ="\n
\n";

  std::string publicAddr = bz_getPublicAddr().c_str();
  page = "Stats for";
  page += publicAddr + "
\n";

  return page;
}

std::string getFileFooter ( void )
{
  return format("

Page generated by webstats in %f seconds\n",bz_getCurrentTime()-start);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Add blank before servername<commit_after>// statTemplates.cpp : Defines the entry point for the DLL application.
//

#include "statTemplates.h"
#include "bzfsAPI.h"
#include "plugin_utils.h"

double start;
std::string getFileHeader ( void )
{
  start = bz_getCurrentTime();
  std::string page ="\n
\n";

  std::string publicAddr = bz_getPublicAddr().c_str();
  page = "Stats for ";
  page += publicAddr + "
\n";

  return page;
}

std::string getFileFooter ( void )
{
  return format("

Page generated by webstats in %f seconds\n",bz_getCurrentTime()-start);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>