<commit_before>//===--- SwiftRemoteMirror.cpp - C wrapper for Reflection API -------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "swift/SwiftRemoteMirror/Platform.h"

#define SWIFT_CLASS_IS_SWIFT_MASK swift_reflection_classIsSwiftMask
extern "C" {
SWIFT_REMOTE_MIRROR_LINKAGE __attribute__((__weak_import__))
unsigned long long swift_reflection_classIsSwiftMask = 2;
}

#include "swift/Reflection/ReflectionContext.h"
#include "swift/Reflection/TypeLowering.h"
#include "swift/Remote/CMemoryReader.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/SwiftRemoteMirror/SwiftRemoteMirror.h"

using namespace swift;
using namespace swift::reflection;
using namespace swift::remote;

using NativeReflectionContext = swift::reflection::ReflectionContext<
    External<RuntimeTarget<sizeof(uintptr_t)>>>;

struct SwiftReflectionContext {
  NativeReflectionContext *nativeContext;
  std::vector<std::function<void()>> freeFuncs;
  std::vector<std::tuple<swift_addr_t, swift_addr_t>> dataSegments;

  SwiftReflectionContext(MemoryReaderImpl impl) {
    auto Reader = std::make_shared<CMemoryReader>(impl);
    nativeContext = new NativeReflectionContext(Reader);
  }

  ~SwiftReflectionContext() {
    delete nativeContext;
    for (auto f : freeFuncs)
      f();
  }
};

uint16_t
swift_reflection_getSupportedMetadataVersion() {
  return SWIFT_REFLECTION_METADATA_VERSION;
}

template <uint8_t WordSize>
static int minimalDataLayoutQueryFunction(void *ReaderContext,
                                          DataLayoutQueryType type,
                                          void *inBuffer, void *outBuffer) {
  if (type == DLQ_GetPointerSize || type == DLQ_GetSizeSize) {
    auto result = static_cast<uint8_t *>(outBuffer);
    *result = WordSize;
    return 1;
  }
  return 0;
}

SwiftReflectionContextRef
swift_reflection_createReflectionContext(void *ReaderContext,
                                         uint8_t PointerSize,
                                         FreeBytesFunction Free,
                                         ReadBytesFunction ReadBytes,
                                         GetStringLengthFunction GetStringLength,
                                         GetSymbolAddressFunction GetSymbolAddress) {
  assert((PointerSize == 4 || PointerSize == 8) && "We only support 32-bit and 64-bit.");
  assert(PointerSize == sizeof(uintptr_t) &&
         "We currently only support the pointer size this file was compiled with.");

  auto *DataLayout = PointerSize == 4 ? minimalDataLayoutQueryFunction<4>
                                      : minimalDataLayoutQueryFunction<8>;
  MemoryReaderImpl ReaderImpl {
    ReaderContext,
    DataLayout,
    Free,
    ReadBytes,
    GetStringLength,
    GetSymbolAddress
  };

  return new SwiftReflectionContext(ReaderImpl);
}

SwiftReflectionContextRef
swift_reflection_createReflectionContextWithDataLayout(void *ReaderContext,
                                    QueryDataLayoutFunction DataLayout,
                                    FreeBytesFunction Free,
                                    ReadBytesFunction ReadBytes,
                                    GetStringLengthFunction GetStringLength,
                                    GetSymbolAddressFunction GetSymbolAddress) {
  MemoryReaderImpl ReaderImpl {
    ReaderContext,
    DataLayout,
    Free,
    ReadBytes,
    GetStringLength,
    GetSymbolAddress
  };

  return new SwiftReflectionContext(ReaderImpl);
}

void swift_reflection_destroyReflectionContext(SwiftReflectionContextRef ContextRef) {
  delete ContextRef;
}

void
swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
                                   swift_reflection_info_t Info) {
  auto Context = ContextRef->nativeContext;

  Context->addReflectionInfo(*reinterpret_cast<ReflectionInfo *>(&Info));
}

int
swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
                          swift_addr_t imageStart) {
  auto Context = ContextRef->nativeContext;
  return Context->addImage(RemoteAddress(imageStart));
}

int
swift_reflection_readIsaMask(SwiftReflectionContextRef ContextRef,
                             uintptr_t *outIsaMask) {
  auto Context = ContextRef->nativeContext;
  auto isaMask = Context->readIsaMask();
  if (isaMask) {
    *outIsaMask = *isaMask;
    return true;
  }
  *outIsaMask = 0;
  return false;
}

swift_typeref_t
swift_reflection_typeRefForMetadata(SwiftReflectionContextRef ContextRef,
                                    uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto TR = Context->readTypeFromMetadata(Metadata);
  return reinterpret_cast<swift_typeref_t>(TR);
}

int
swift_reflection_ownsObject(SwiftReflectionContextRef ContextRef, uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  return Context->ownsObject(RemoteAddress(Object));
}

int
swift_reflection_ownsAddress(SwiftReflectionContextRef ContextRef, uintptr_t Address) {
  auto Context = ContextRef->nativeContext;
  return Context->ownsAddress(RemoteAddress(Address));
}

uintptr_t
swift_reflection_metadataForObject(SwiftReflectionContextRef ContextRef,
                                   uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto MetadataAddress = Context->readMetadataFromInstance(Object);
  if (!MetadataAddress)
    return 0;
  return *MetadataAddress;
}

swift_typeref_t
swift_reflection_typeRefForInstance(SwiftReflectionContextRef ContextRef,
                                    uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto MetadataAddress = Context->readMetadataFromInstance(Object);
  if (!MetadataAddress)
    return 0;
  auto TR = Context->readTypeFromMetadata(*MetadataAddress);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef,
                                           const char *MangledTypeName,
                                           uint64_t Length) {
  auto Context = ContextRef->nativeContext;
  auto TR = Context->readTypeFromMangledName(MangledTypeName, Length);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_genericArgumentOfTypeRef(swift_typeref_t OpaqueTypeRef,
                                          unsigned Index) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);

  if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
    auto &Params = BG->getGenericParams();
    assert(Index < Params.size());
    return reinterpret_cast<swift_typeref_t>(Params[Index]);
  }
  return 0;
}

unsigned
swift_reflection_genericArgumentCountOfTypeRef(swift_typeref_t OpaqueTypeRef) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);

  if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
    auto &Params = BG->getGenericParams();
    return Params.size();
  }
  return 0;
}

swift_layout_kind_t getTypeInfoKind(const TypeInfo &TI) {
  switch (TI.getKind()) {
  case TypeInfoKind::Builtin: {
    auto &BuiltinTI = cast<BuiltinTypeInfo>(TI);
    if (BuiltinTI.getMangledTypeName() == "Bp")
      return SWIFT_RAW_POINTER;
    return SWIFT_BUILTIN;
  }
  case TypeInfoKind::Record: {
    auto &RecordTI = cast<RecordTypeInfo>(TI);
    switch (RecordTI.getRecordKind()) {
    case RecordKind::Invalid:
      return SWIFT_UNKNOWN;
    case RecordKind::Tuple:
      return SWIFT_TUPLE;
    case RecordKind::Struct:
      return SWIFT_STRUCT;
    case RecordKind::NoPayloadEnum:
      return SWIFT_NO_PAYLOAD_ENUM;
    case RecordKind::SinglePayloadEnum:
      return SWIFT_SINGLE_PAYLOAD_ENUM;
    case RecordKind::MultiPayloadEnum:
      return SWIFT_MULTI_PAYLOAD_ENUM;
    case RecordKind::ThickFunction:
      return SWIFT_THICK_FUNCTION;
    case RecordKind::OpaqueExistential:
      return SWIFT_OPAQUE_EXISTENTIAL;
    case RecordKind::ClassExistential:
      return SWIFT_CLASS_EXISTENTIAL;
    case RecordKind::ErrorExistential:
      return SWIFT_ERROR_EXISTENTIAL;
    case RecordKind::ExistentialMetatype:
      return SWIFT_EXISTENTIAL_METATYPE;
    case RecordKind::ClassInstance:
      return SWIFT_CLASS_INSTANCE;
    case RecordKind::ClosureContext:
      return SWIFT_CLOSURE_CONTEXT;
    }
  }
  case TypeInfoKind::Reference: {
    auto &ReferenceTI = cast<ReferenceTypeInfo>(TI);
    switch (ReferenceTI.getReferenceKind()) {
    case ReferenceKind::Strong: return SWIFT_STRONG_REFERENCE;
#define REF_STORAGE(Name, name, NAME) \
    case ReferenceKind::Name: return SWIFT_##NAME##_REFERENCE;
#include "swift/AST/ReferenceStorage.def"
    }
  }
  }

  swift_runtime_unreachable("Unhandled TypeInfoKind in switch");
}

static swift_typeinfo_t convertTypeInfo(const TypeInfo *TI) {
  if (TI == nullptr) {
    return {
      SWIFT_UNKNOWN,
      0,
      0,
      0,
      0
    };
  }

  unsigned NumFields = 0;
  if (auto *RecordTI = dyn_cast<RecordTypeInfo>(TI))
    NumFields = RecordTI->getNumFields();

  return {
    getTypeInfoKind(*TI),
    TI->getSize(),
    TI->getAlignment(),
    TI->getStride(),
    NumFields
  };
}

static swift_childinfo_t convertChild(const TypeInfo *TI, unsigned Index) {
  auto *RecordTI = cast<RecordTypeInfo>(TI);
  auto &FieldInfo = RecordTI->getFields()[Index];

  return {
    FieldInfo.Name.c_str(),
    FieldInfo.Offset,
    getTypeInfoKind(FieldInfo.TI),
    reinterpret_cast<swift_typeref_t>(FieldInfo.TR),
  };
}

swift_typeinfo_t
swift_reflection_infoForTypeRef(SwiftReflectionContextRef ContextRef,
                                swift_typeref_t OpaqueTypeRef) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto TI = Context->getTypeInfo(TR);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfTypeRef(SwiftReflectionContextRef ContextRef,
                                swift_typeref_t OpaqueTypeRef,
                                unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto *TI = Context->getTypeInfo(TR);
  return convertChild(TI, Index);
}

swift_typeinfo_t
swift_reflection_infoForMetadata(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getMetadataTypeInfo(Metadata);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfMetadata(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Metadata,
                                 unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getMetadataTypeInfo(Metadata);
  return convertChild(TI, Index);
}

swift_typeinfo_t
swift_reflection_infoForInstance(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getInstanceTypeInfo(Object);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfInstance(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Object,
                                 unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getInstanceTypeInfo(Object);
  return convertChild(TI, Index);
}

int swift_reflection_projectExistential(SwiftReflectionContextRef ContextRef,
                                        swift_addr_t ExistentialAddress,
                                        swift_typeref_t ExistentialTypeRef,
                                        swift_typeref_t *InstanceTypeRef,
                                        swift_addr_t *StartOfInstanceData) {
  auto Context = ContextRef->nativeContext;
  auto ExistentialTR = reinterpret_cast<const TypeRef *>(ExistentialTypeRef);
  auto RemoteExistentialAddress = RemoteAddress(ExistentialAddress);
  const TypeRef *InstanceTR = nullptr;
  RemoteAddress RemoteStartOfInstanceData(nullptr);
  auto Success = Context->projectExistential(RemoteExistentialAddress,
                                             ExistentialTR,
                                             &InstanceTR,
                                             &RemoteStartOfInstanceData);

  if (Success) {
    *InstanceTypeRef = reinterpret_cast<swift_typeref_t>(InstanceTR);
    *StartOfInstanceData = RemoteStartOfInstanceData.getAddressData();
  }

  return Success;
}

void swift_reflection_dumpTypeRef(swift_typeref_t OpaqueTypeRef) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  if (TR == nullptr) {
    std::cout << "<null type reference>\n";
  } else {
    TR->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
                                         swift_typeref_t OpaqueTypeRef) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto TI = Context->getTypeInfo(TR);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
                                          uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto TI = Context->getMetadataTypeInfo(Metadata);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForInstance(SwiftReflectionContextRef ContextRef,
                                          uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto TI = Context->getInstanceTypeInfo(Object);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

size_t swift_reflection_demangle(const char *MangledName, size_t Length,
                                 char *OutDemangledName, size_t MaxLength) {
  if (MangledName == nullptr || Length == 0)
    return 0;

  std::string Mangled(MangledName, Length);
  auto Demangled = Demangle::demangleTypeAsString(Mangled);
  strncpy(OutDemangledName, Demangled.c_str(), MaxLength);
  return Demangled.size();
}
<commit_msg>[RemoteMirror] Rearrange #includes to fix warnings generated from the addition of __weak_import__ to classIsSwiftMask.<commit_after>//===--- SwiftRemoteMirror.cpp - C wrapper for Reflection API -------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "swift/SwiftRemoteMirror/Platform.h"
#include "swift/SwiftRemoteMirror/SwiftRemoteMirror.h"

#define SWIFT_CLASS_IS_SWIFT_MASK swift_reflection_classIsSwiftMask
extern "C" {
SWIFT_REMOTE_MIRROR_LINKAGE
unsigned long long swift_reflection_classIsSwiftMask = 2;
}

#include "swift/Reflection/ReflectionContext.h"
#include "swift/Reflection/TypeLowering.h"
#include "swift/Remote/CMemoryReader.h"
#include "swift/Runtime/Unreachable.h"

using namespace swift;
using namespace swift::reflection;
using namespace swift::remote;

using NativeReflectionContext = swift::reflection::ReflectionContext<
    External<RuntimeTarget<sizeof(uintptr_t)>>>;

struct SwiftReflectionContext {
  NativeReflectionContext *nativeContext;
  std::vector<std::function<void()>> freeFuncs;
  std::vector<std::tuple<swift_addr_t, swift_addr_t>> dataSegments;

  SwiftReflectionContext(MemoryReaderImpl impl) {
    auto Reader = std::make_shared<CMemoryReader>(impl);
    nativeContext = new NativeReflectionContext(Reader);
  }

  ~SwiftReflectionContext() {
    delete nativeContext;
    for (auto f : freeFuncs)
      f();
  }
};

uint16_t
swift_reflection_getSupportedMetadataVersion() {
  return SWIFT_REFLECTION_METADATA_VERSION;
}

template <uint8_t WordSize>
static int minimalDataLayoutQueryFunction(void *ReaderContext,
                                          DataLayoutQueryType type,
                                          void *inBuffer, void *outBuffer) {
  if (type == DLQ_GetPointerSize || type == DLQ_GetSizeSize) {
    auto result = static_cast<uint8_t *>(outBuffer);
    *result = WordSize;
    return 1;
  }
  return 0;
}

SwiftReflectionContextRef
swift_reflection_createReflectionContext(void *ReaderContext,
                                         uint8_t PointerSize,
                                         FreeBytesFunction Free,
                                         ReadBytesFunction ReadBytes,
                                         GetStringLengthFunction GetStringLength,
                                         GetSymbolAddressFunction GetSymbolAddress) {
  assert((PointerSize == 4 || PointerSize == 8) && "We only support 32-bit and 64-bit.");
  assert(PointerSize == sizeof(uintptr_t) &&
         "We currently only support the pointer size this file was compiled with.");

  auto *DataLayout = PointerSize == 4 ? minimalDataLayoutQueryFunction<4>
                                      : minimalDataLayoutQueryFunction<8>;
  MemoryReaderImpl ReaderImpl {
    ReaderContext,
    DataLayout,
    Free,
    ReadBytes,
    GetStringLength,
    GetSymbolAddress
  };

  return new SwiftReflectionContext(ReaderImpl);
}

SwiftReflectionContextRef
swift_reflection_createReflectionContextWithDataLayout(void *ReaderContext,
                                    QueryDataLayoutFunction DataLayout,
                                    FreeBytesFunction Free,
                                    ReadBytesFunction ReadBytes,
                                    GetStringLengthFunction GetStringLength,
                                    GetSymbolAddressFunction GetSymbolAddress) {
  MemoryReaderImpl ReaderImpl {
    ReaderContext,
    DataLayout,
    Free,
    ReadBytes,
    GetStringLength,
    GetSymbolAddress
  };

  return new SwiftReflectionContext(ReaderImpl);
}

void swift_reflection_destroyReflectionContext(SwiftReflectionContextRef ContextRef) {
  delete ContextRef;
}

void
swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
                                   swift_reflection_info_t Info) {
  auto Context = ContextRef->nativeContext;

  Context->addReflectionInfo(*reinterpret_cast<ReflectionInfo *>(&Info));
}

int
swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
                          swift_addr_t imageStart) {
  auto Context = ContextRef->nativeContext;
  return Context->addImage(RemoteAddress(imageStart));
}

int
swift_reflection_readIsaMask(SwiftReflectionContextRef ContextRef,
                             uintptr_t *outIsaMask) {
  auto Context = ContextRef->nativeContext;
  auto isaMask = Context->readIsaMask();
  if (isaMask) {
    *outIsaMask = *isaMask;
    return true;
  }
  *outIsaMask = 0;
  return false;
}

swift_typeref_t
swift_reflection_typeRefForMetadata(SwiftReflectionContextRef ContextRef,
                                    uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto TR = Context->readTypeFromMetadata(Metadata);
  return reinterpret_cast<swift_typeref_t>(TR);
}

int
swift_reflection_ownsObject(SwiftReflectionContextRef ContextRef, uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  return Context->ownsObject(RemoteAddress(Object));
}

int
swift_reflection_ownsAddress(SwiftReflectionContextRef ContextRef, uintptr_t Address) {
  auto Context = ContextRef->nativeContext;
  return Context->ownsAddress(RemoteAddress(Address));
}

uintptr_t
swift_reflection_metadataForObject(SwiftReflectionContextRef ContextRef,
                                   uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto MetadataAddress = Context->readMetadataFromInstance(Object);
  if (!MetadataAddress)
    return 0;
  return *MetadataAddress;
}

swift_typeref_t
swift_reflection_typeRefForInstance(SwiftReflectionContextRef ContextRef,
                                    uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto MetadataAddress = Context->readMetadataFromInstance(Object);
  if (!MetadataAddress)
    return 0;
  auto TR = Context->readTypeFromMetadata(*MetadataAddress);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef,
                                           const char *MangledTypeName,
                                           uint64_t Length) {
  auto Context = ContextRef->nativeContext;
  auto TR = Context->readTypeFromMangledName(MangledTypeName, Length);
  return reinterpret_cast<swift_typeref_t>(TR);
}

swift_typeref_t
swift_reflection_genericArgumentOfTypeRef(swift_typeref_t OpaqueTypeRef,
                                          unsigned Index) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);

  if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
    auto &Params = BG->getGenericParams();
    assert(Index < Params.size());
    return reinterpret_cast<swift_typeref_t>(Params[Index]);
  }
  return 0;
}

unsigned
swift_reflection_genericArgumentCountOfTypeRef(swift_typeref_t OpaqueTypeRef) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);

  if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
    auto &Params = BG->getGenericParams();
    return Params.size();
  }
  return 0;
}

swift_layout_kind_t getTypeInfoKind(const TypeInfo &TI) {
  switch (TI.getKind()) {
  case TypeInfoKind::Builtin: {
    auto &BuiltinTI = cast<BuiltinTypeInfo>(TI);
    if (BuiltinTI.getMangledTypeName() == "Bp")
      return SWIFT_RAW_POINTER;
    return SWIFT_BUILTIN;
  }
  case TypeInfoKind::Record: {
    auto &RecordTI = cast<RecordTypeInfo>(TI);
    switch (RecordTI.getRecordKind()) {
    case RecordKind::Invalid:
      return SWIFT_UNKNOWN;
    case RecordKind::Tuple:
      return SWIFT_TUPLE;
    case RecordKind::Struct:
      return SWIFT_STRUCT;
    case RecordKind::NoPayloadEnum:
      return SWIFT_NO_PAYLOAD_ENUM;
    case RecordKind::SinglePayloadEnum:
      return SWIFT_SINGLE_PAYLOAD_ENUM;
    case RecordKind::MultiPayloadEnum:
      return SWIFT_MULTI_PAYLOAD_ENUM;
    case RecordKind::ThickFunction:
      return SWIFT_THICK_FUNCTION;
    case RecordKind::OpaqueExistential:
      return SWIFT_OPAQUE_EXISTENTIAL;
    case RecordKind::ClassExistential:
      return SWIFT_CLASS_EXISTENTIAL;
    case RecordKind::ErrorExistential:
      return SWIFT_ERROR_EXISTENTIAL;
    case RecordKind::ExistentialMetatype:
      return SWIFT_EXISTENTIAL_METATYPE;
    case RecordKind::ClassInstance:
      return SWIFT_CLASS_INSTANCE;
    case RecordKind::ClosureContext:
      return SWIFT_CLOSURE_CONTEXT;
    }
  }
  case TypeInfoKind::Reference: {
    auto &ReferenceTI = cast<ReferenceTypeInfo>(TI);
    switch (ReferenceTI.getReferenceKind()) {
    case ReferenceKind::Strong: return SWIFT_STRONG_REFERENCE;
#define REF_STORAGE(Name, name, NAME) \
    case ReferenceKind::Name: return SWIFT_##NAME##_REFERENCE;
#include "swift/AST/ReferenceStorage.def"
    }
  }
  }

  swift_runtime_unreachable("Unhandled TypeInfoKind in switch");
}

static swift_typeinfo_t convertTypeInfo(const TypeInfo *TI) {
  if (TI == nullptr) {
    return {
      SWIFT_UNKNOWN,
      0,
      0,
      0,
      0
    };
  }

  unsigned NumFields = 0;
  if (auto *RecordTI = dyn_cast<RecordTypeInfo>(TI))
    NumFields = RecordTI->getNumFields();

  return {
    getTypeInfoKind(*TI),
    TI->getSize(),
    TI->getAlignment(),
    TI->getStride(),
    NumFields
  };
}

static swift_childinfo_t convertChild(const TypeInfo *TI, unsigned Index) {
  auto *RecordTI = cast<RecordTypeInfo>(TI);
  auto &FieldInfo = RecordTI->getFields()[Index];

  return {
    FieldInfo.Name.c_str(),
    FieldInfo.Offset,
    getTypeInfoKind(FieldInfo.TI),
    reinterpret_cast<swift_typeref_t>(FieldInfo.TR),
  };
}

swift_typeinfo_t
swift_reflection_infoForTypeRef(SwiftReflectionContextRef ContextRef,
                                swift_typeref_t OpaqueTypeRef) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto TI = Context->getTypeInfo(TR);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfTypeRef(SwiftReflectionContextRef ContextRef,
                                swift_typeref_t OpaqueTypeRef,
                                unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto *TI = Context->getTypeInfo(TR);
  return convertChild(TI, Index);
}

swift_typeinfo_t
swift_reflection_infoForMetadata(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getMetadataTypeInfo(Metadata);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfMetadata(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Metadata,
                                 unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getMetadataTypeInfo(Metadata);
  return convertChild(TI, Index);
}

swift_typeinfo_t
swift_reflection_infoForInstance(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getInstanceTypeInfo(Object);
  return convertTypeInfo(TI);
}

swift_childinfo_t
swift_reflection_childOfInstance(SwiftReflectionContextRef ContextRef,
                                 uintptr_t Object,
                                 unsigned Index) {
  auto Context = ContextRef->nativeContext;
  auto *TI = Context->getInstanceTypeInfo(Object);
  return convertChild(TI, Index);
}

int swift_reflection_projectExistential(SwiftReflectionContextRef ContextRef,
                                        swift_addr_t ExistentialAddress,
                                        swift_typeref_t ExistentialTypeRef,
                                        swift_typeref_t *InstanceTypeRef,
                                        swift_addr_t *StartOfInstanceData) {
  auto Context = ContextRef->nativeContext;
  auto ExistentialTR = reinterpret_cast<const TypeRef *>(ExistentialTypeRef);
  auto RemoteExistentialAddress = RemoteAddress(ExistentialAddress);
  const TypeRef *InstanceTR = nullptr;
  RemoteAddress RemoteStartOfInstanceData(nullptr);
  auto Success = Context->projectExistential(RemoteExistentialAddress,
                                             ExistentialTR,
                                             &InstanceTR,
                                             &RemoteStartOfInstanceData);

  if (Success) {
    *InstanceTypeRef = reinterpret_cast<swift_typeref_t>(InstanceTR);
    *StartOfInstanceData = RemoteStartOfInstanceData.getAddressData();
  }

  return Success;
}

void swift_reflection_dumpTypeRef(swift_typeref_t OpaqueTypeRef) {
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  if (TR == nullptr) {
    std::cout << "<null type reference>\n";
  } else {
    TR->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
                                         swift_typeref_t OpaqueTypeRef) {
  auto Context = ContextRef->nativeContext;
  auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
  auto TI = Context->getTypeInfo(TR);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
                                          uintptr_t Metadata) {
  auto Context = ContextRef->nativeContext;
  auto TI = Context->getMetadataTypeInfo(Metadata);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

void swift_reflection_dumpInfoForInstance(SwiftReflectionContextRef ContextRef,
                                          uintptr_t Object) {
  auto Context = ContextRef->nativeContext;
  auto TI = Context->getInstanceTypeInfo(Object);
  if (TI == nullptr) {
    std::cout << "<null type info>\n";
  } else {
    TI->dump(std::cout);
  }
}

size_t swift_reflection_demangle(const char *MangledName, size_t Length,
                                 char *OutDemangledName, size_t MaxLength) {
  if (MangledName == nullptr || Length == 0)
    return 0;

  std::string Mangled(MangledName, Length);
  auto Demangled = Demangle::demangleTypeAsString(Mangled);
  strncpy(OutDemangledName, Demangled.c_str(), MaxLength);
  return Demangled.size();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: networkdomain.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-01-16 13:17:55 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef __FRAMEWORK_HELPER_NETWORKDOMAIN_HXX_
#include <helper/networkdomain.hxx>
#endif

namespace framework
{

#ifdef WNT
//_________________________________________________________________________________________________________________
//  Windows
//_________________________________________________________________________________________________________________

#define UNICODE
#include <windows.h>

//_________________________________________________________________________________________________________________
//  Win NT, Win 2000, Win XP
//_________________________________________________________________________________________________________________

static DWORD WINAPI GetUserDomainW_NT( LPWSTR lpBuffer, DWORD nSize )
{
    return GetEnvironmentVariable( TEXT("USERDOMAIN"), lpBuffer, nSize );
}

//_________________________________________________________________________________________________________________
//  Win 9x,Win ME
//_________________________________________________________________________________________________________________

static DWORD WINAPI GetUserDomainW_WINDOWS( LPWSTR lpBuffer, DWORD nSize )
{
    HKEY    hkeyLogon;
    HKEY    hkeyWorkgroup;
    DWORD   dwResult = 0;

    if ( ERROR_SUCCESS  == RegOpenKeyEx(
        HKEY_LOCAL_MACHINE,
        TEXT("Network\\Logon"),
        0, KEY_READ, &hkeyLogon ) )
    {
        DWORD   dwLogon = 0;
        DWORD   dwLogonSize = sizeof(dwLogon);
        LONG    lResult = RegQueryValueEx( hkeyLogon, TEXT("LMLogon"), 0, NULL, (LPBYTE)&dwLogon, &dwLogonSize );
        RegCloseKey( hkeyLogon );

        if ( dwLogon )
        {
            HKEY    hkeyNetworkProvider;

            if ( ERROR_SUCCESS  == RegOpenKeyEx(
                HKEY_LOCAL_MACHINE,
                TEXT("SYSTEM\\CurrentControlSet\\Services\\MSNP32\\NetworkProvider"),
                0, KEY_READ, &hkeyNetworkProvider ) )
            {
                DWORD   dwBufferSize = nSize;
                LONG    lResult = RegQueryValueEx( hkeyNetworkProvider, TEXT("AuthenticatingAgent"), 0, NULL, (LPBYTE)lpBuffer, &dwBufferSize );

                if ( ERROR_SUCCESS == lResult || ERROR_MORE_DATA == lResult )
                    dwResult = dwBufferSize / sizeof(TCHAR);

                RegCloseKey( hkeyNetworkProvider );
            }
        }
    }
    else if ( ERROR_SUCCESS == RegOpenKeyEx(
        HKEY_LOCAL_MACHINE,
        TEXT("SYSTEM\\CurrentControlSet\\Services\\VxD\\VNETSUP"),
        0, KEY_READ, &hkeyWorkgroup ) )
    {
        DWORD   dwBufferSize = nSize;
        LONG    lResult = RegQueryValueEx( hkeyWorkgroup, TEXT("Workgroup"), 0, NULL, (LPBYTE)lpBuffer, &dwBufferSize );

        if ( ERROR_SUCCESS == lResult || ERROR_MORE_DATA == lResult )
            dwResult = dwBufferSize / sizeof(TCHAR);

        RegCloseKey( hkeyWorkgroup );
    }

    return dwResult;
}

static rtl::OUString GetUserDomain()
{
    sal_Unicode aBuffer[256];

    long    nVersion = GetVersion();
    DWORD   nResult;

    if ( nVersion < 0 )
        nResult = GetUserDomainW_WINDOWS( aBuffer, sizeof( aBuffer ) );
    else
        nResult = GetUserDomainW_NT( aBuffer, sizeof( aBuffer ) );

    if ( nResult > 0 )
        return rtl::OUString( aBuffer );
    else
        return rtl::OUString();
}

//_________________________________________________________________________________________________________________
//  Windows
//_________________________________________________________________________________________________________________

rtl::OUString NetworkDomain::GetYPDomainName()
{
    return ::rtl::OUString();
}

rtl::OUString NetworkDomain::GetNTDomainName()
{
    return GetUserDomain();
}

#elif defined( UNIX )

#include <rtl/ustring.h>
#include <stdlib.h>
#include <errno.h>
#include <osl/thread.h>

//_________________________________________________________________________________________________________________
//  Unix
//_________________________________________________________________________________________________________________

#if defined( SOLARIS )

//_________________________________________________________________________________________________________________
//  Solaris
//_________________________________________________________________________________________________________________

#include <sys/systeminfo.h>
#include <sal/alloca.h>

static rtl_uString *getDomainName()
{
    /* Initialize and assume failure */
    rtl_uString *ustrDomainName = NULL;

    char    szBuffer[256];

    long    nCopied = sizeof(szBuffer);
    char    *pBuffer = szBuffer;
    long    nBufSize;

    do
    {
        nBufSize = nCopied;
        nCopied = sysinfo( SI_SRPC_DOMAIN, pBuffer, nBufSize );

        /*  If nCopied is greater than buffersize we need to allocate
            a buffer with suitable size */

        if ( nCopied > nBufSize )
            pBuffer = (char *)alloca( nCopied );

    } while ( nCopied > nBufSize );

    if ( -1 != nCopied  )
    {
        rtl_string2UString(
            &ustrDomainName,
            pBuffer,
            nCopied - 1,
            osl_getThreadTextEncoding(),
            OSTRING_TO_OUSTRING_CVTFLAGS );
    }

    return ustrDomainName;
}

#elif defined( LINUX ) /* endif SOLARIS */

//_________________________________________________________________________________________________________________
//  Linux
//_________________________________________________________________________________________________________________

#include <unistd.h>
#include <string.h>

static rtl_uString *getDomainName()
{
    /* Initialize and assume failure */
    rtl_uString *ustrDomainName = NULL;

    char    *pBuffer;
    int     result;
    size_t  nBufSize = 0;

    do
    {
        nBufSize += 256; /* Increase buffer size by steps of 256 bytes */
        pBuffer = (char *)alloca( nBufSize );
        result = getdomainname( pBuffer, nBufSize );
        /* If buffersize in not large enough -1 is returned and errno
        is set to EINVAL. This only applies to libc. With glibc the name
        is truncated. */
    } while ( -1 == result && EINVAL == errno );

    if ( 0 == result )
    {
        rtl_string2UString(
            &ustrDomainName,
            pBuffer,
            strlen( pBuffer ),
            osl_getThreadTextEncoding(),
            OSTRING_TO_OUSTRING_CVTFLAGS );
    }

    return ustrDomainName;
}

#else /* LINUX */

//_________________________________________________________________________________________________________________
//  Other Unix
//_________________________________________________________________________________________________________________

static rtl_uString *getDomainName()
{
    return NULL;
}

#endif

//_________________________________________________________________________________________________________________
//  Unix
//_________________________________________________________________________________________________________________

rtl::OUString NetworkDomain::GetYPDomainName()
{
    rtl_uString* pResult = getDomainName();
    if ( pResult )
        return rtl::OUString( pResult );
    else
        return rtl::OUString();
}

rtl::OUString NetworkDomain::GetNTDomainName()
{
    return ::rtl::OUString();
}

#else /* UNIX */

//_________________________________________________________________________________________________________________
//  Other operating systems (non-Windows and non-Unix)
//_________________________________________________________________________________________________________________

rtl::OUString NetworkDomain::GetYPDomainName()
{
    return rtl::OUString();
}

rtl::OUString NetworkDomain::GetNTDomainName()
{
    return rtl::OUString();
}

#endif

} // namespace framework
<commit_msg>INTEGRATION: CWS pchfix02 (1.5.148); FILE MERGED 2006/09/01 17:29:09 kaib 1.5.148.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: networkdomain.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 13:57:53 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"

#ifndef __FRAMEWORK_HELPER_NETWORKDOMAIN_HXX_
#include <helper/networkdomain.hxx>
#endif

namespace framework
{

#ifdef WNT
//_________________________________________________________________________________________________________________
//  Windows
//_________________________________________________________________________________________________________________

#define UNICODE
#include <windows.h>

//_________________________________________________________________________________________________________________
//  Win NT, Win 2000, Win XP
//_________________________________________________________________________________________________________________

static DWORD WINAPI GetUserDomainW_NT( LPWSTR lpBuffer, DWORD nSize )
{
    return GetEnvironmentVariable( TEXT("USERDOMAIN"), lpBuffer, nSize );
}

//_________________________________________________________________________________________________________________
//  Win 9x,Win ME
//_________________________________________________________________________________________________________________

static DWORD WINAPI GetUserDomainW_WINDOWS( LPWSTR lpBuffer, DWORD nSize )
{
    HKEY    hkeyLogon;
    HKEY    hkeyWorkgroup;
    DWORD   dwResult = 0;

    if ( ERROR_SUCCESS  == RegOpenKeyEx(
        HKEY_LOCAL_MACHINE,
        TEXT("Network\\Logon"),
        0, KEY_READ, &hkeyLogon ) )
    {
        DWORD   dwLogon = 0;
        DWORD   dwLogonSize = sizeof(dwLogon);
        LONG    lResult = RegQueryValueEx( hkeyLogon, TEXT("LMLogon"), 0, NULL, (LPBYTE)&dwLogon, &dwLogonSize );
        RegCloseKey( hkeyLogon );

        if ( dwLogon )
        {
            HKEY    hkeyNetworkProvider;

            if ( ERROR_SUCCESS  == RegOpenKeyEx(
                HKEY_LOCAL_MACHINE,
                TEXT("SYSTEM\\CurrentControlSet\\Services\\MSNP32\\NetworkProvider"),
                0, KEY_READ, &hkeyNetworkProvider ) )
            {
                DWORD   dwBufferSize = nSize;
                LONG    lResult = RegQueryValueEx( hkeyNetworkProvider, TEXT("AuthenticatingAgent"), 0, NULL, (LPBYTE)lpBuffer, &dwBufferSize );

                if ( ERROR_SUCCESS == lResult || ERROR_MORE_DATA == lResult )
                    dwResult = dwBufferSize / sizeof(TCHAR);

                RegCloseKey( hkeyNetworkProvider );
            }
        }
    }
    else if ( ERROR_SUCCESS == RegOpenKeyEx(
        HKEY_LOCAL_MACHINE,
        TEXT("SYSTEM\\CurrentControlSet\\Services\\VxD\\VNETSUP"),
        0, KEY_READ, &hkeyWorkgroup ) )
    {
        DWORD   dwBufferSize = nSize;
        LONG    lResult = RegQueryValueEx( hkeyWorkgroup, TEXT("Workgroup"), 0, NULL, (LPBYTE)lpBuffer, &dwBufferSize );

        if ( ERROR_SUCCESS == lResult || ERROR_MORE_DATA == lResult )
            dwResult = dwBufferSize / sizeof(TCHAR);

        RegCloseKey( hkeyWorkgroup );
    }

    return dwResult;
}

static rtl::OUString GetUserDomain()
{
    sal_Unicode aBuffer[256];

    long    nVersion = GetVersion();
    DWORD   nResult;

    if ( nVersion < 0 )
        nResult = GetUserDomainW_WINDOWS( aBuffer, sizeof( aBuffer ) );
    else
        nResult = GetUserDomainW_NT( aBuffer, sizeof( aBuffer ) );

    if ( nResult > 0 )
        return rtl::OUString( aBuffer );
    else
        return rtl::OUString();
}

//_________________________________________________________________________________________________________________
//  Windows
//_________________________________________________________________________________________________________________

rtl::OUString NetworkDomain::GetYPDomainName()
{
    return ::rtl::OUString();
}

rtl::OUString NetworkDomain::GetNTDomainName()
{
    return GetUserDomain();
}

#elif defined( UNIX )

#include <rtl/ustring.h>
#include <stdlib.h>
#include <errno.h>
#include <osl/thread.h>

//_________________________________________________________________________________________________________________
//  Unix
//_________________________________________________________________________________________________________________

#if defined( SOLARIS )

//_________________________________________________________________________________________________________________
//  Solaris
//_________________________________________________________________________________________________________________

#include <sys/systeminfo.h>
#include <sal/alloca.h>

static rtl_uString *getDomainName()
{
    /* Initialize and assume failure */
    rtl_uString *ustrDomainName = NULL;

    char    szBuffer[256];

    long    nCopied = sizeof(szBuffer);
    char    *pBuffer = szBuffer;
    long    nBufSize;

    do
    {
        nBufSize = nCopied;
        nCopied = sysinfo( SI_SRPC_DOMAIN, pBuffer, nBufSize );

        /*  If nCopied is greater than buffersize we need to allocate
            a buffer with suitable size */

        if ( nCopied > nBufSize )
            pBuffer = (char *)alloca( nCopied );

    } while ( nCopied > nBufSize );

    if ( -1 != nCopied  )
    {
        rtl_string2UString(
            &ustrDomainName,
            pBuffer,
            nCopied - 1,
            osl_getThreadTextEncoding(),
            OSTRING_TO_OUSTRING_CVTFLAGS );
    }

    return ustrDomainName;
}

#elif defined( LINUX ) /* endif SOLARIS */

//_________________________________________________________________________________________________________________
//  Linux
//_________________________________________________________________________________________________________________

#include <unistd.h>
#include <string.h>

static rtl_uString *getDomainName()
{
    /* Initialize and assume failure */
    rtl_uString *ustrDomainName = NULL;

    char    *pBuffer;
    int     result;
    size_t  nBufSize = 0;

    do
    {
        nBufSize += 256; /* Increase buffer size by steps of 256 bytes */
        pBuffer = (char *)alloca( nBufSize );
        result = getdomainname( pBuffer, nBufSize );
        /* If buffersize in not large enough -1 is returned and errno
        is set to EINVAL. This only applies to libc. With glibc the name
        is truncated. */
    } while ( -1 == result && EINVAL == errno );

    if ( 0 == result )
    {
        rtl_string2UString(
            &ustrDomainName,
            pBuffer,
            strlen( pBuffer ),
            osl_getThreadTextEncoding(),
            OSTRING_TO_OUSTRING_CVTFLAGS );
    }

    return ustrDomainName;
}

#else /* LINUX */

//_________________________________________________________________________________________________________________
//  Other Unix
//_________________________________________________________________________________________________________________

static rtl_uString *getDomainName()
{
    return NULL;
}

#endif

//_________________________________________________________________________________________________________________
//  Unix
//_________________________________________________________________________________________________________________

rtl::OUString NetworkDomain::GetYPDomainName()
{
    rtl_uString* pResult = getDomainName();
    if ( pResult )
        return rtl::OUString( pResult );
    else
        return rtl::OUString();
}

rtl::OUString NetworkDomain::GetNTDomainName()
{
    return ::rtl::OUString();
}

#else /* UNIX */

//_________________________________________________________________________________________________________________
//  Other operating systems (non-Windows and non-Unix)
//_________________________________________________________________________________________________________________

rtl::OUString NetworkDomain::GetYPDomainName()
{
    return rtl::OUString();
}

rtl::OUString NetworkDomain::GetNTDomainName()
{
    return rtl::OUString();
}

#endif

} // namespace framework
<|endoftext|>


<commit_before>/*
 * Copyright 2014-2015 Daniel Collin. All rights reserved.
 * License: http://www.opensource.org/licenses/BSD-2-Clause
 */

#include <bgfx.h>
#include <bx/allocator.h>
#include <bx/fpumath.h>
#include <ocornut-imgui/imgui.h>
#include "imgui.h"
#include "ocornut_imgui.h"
#include <stb/stb_image.c>

#if defined(SCI_NAMESPACE)
#	include "../entry/input.h"
#endif // defined(SCI_NAMESPACE)

#include "vs_ocornut_imgui.bin.h"
#include "fs_ocornut_imgui.bin.h"

struct OcornutImguiContext
{
	static void* memAlloc(size_t _size);
	static void memFree(void* _ptr);
	static void renderDrawLists(ImDrawData* draw_data);

	void render(ImDrawData* draw_data)
	{
		const float width  = ImGui::GetIO().DisplaySize.x;
		const float height = ImGui::GetIO().DisplaySize.y;

		float ortho[16];
		bx::mtxOrtho(ortho, 0.0f, width, height, 0.0f, -1.0f, 1.0f);

		bgfx::setViewTransform(m_viewId, NULL, ortho);

		// Render command lists
		for (int32_t ii = 0; ii < draw_data->CmdListsCount; ++ii)
		{
			bgfx::TransientVertexBuffer tvb;
			bgfx::TransientIndexBuffer tib;

			const ImDrawList* cmd_list   = draw_data->CmdLists[ii];
			uint32_t vtx_size = (uint32_t)cmd_list->VtxBuffer.size();
			uint32_t idx_size = (uint32_t)cmd_list->IdxBuffer.size();

			if (!bgfx::checkAvailTransientVertexBuffer(vtx_size, m_decl) || !bgfx::checkAvailTransientIndexBuffer(idx_size) )
			{
				// not enough space in transient buffer just quit drawing the rest...
				break;
			}

			bgfx::allocTransientVertexBuffer(&tvb, vtx_size, m_decl);
			bgfx::allocTransientIndexBuffer(&tib, idx_size);

			ImDrawVert* verts = (ImDrawVert*)tvb.data;
			memcpy(verts, cmd_list->VtxBuffer.begin(), vtx_size * sizeof(ImDrawVert) );

			ImDrawIdx* indices = (ImDrawIdx*)tib.data;
			memcpy(indices, cmd_list->IdxBuffer.begin(), idx_size * sizeof(ImDrawIdx) );

			uint32_t elem_offset = 0;
			const ImDrawCmd* pcmd_begin = cmd_list->CmdBuffer.begin();
			const ImDrawCmd* pcmd_end   = cmd_list->CmdBuffer.end();
			for (const ImDrawCmd* pcmd = pcmd_begin; pcmd != pcmd_end; pcmd++)
			{
				if (pcmd->UserCallback)
				{
					pcmd->UserCallback(cmd_list, pcmd);
					elem_offset += pcmd->ElemCount;
					continue;
				}
				if (0 == pcmd->ElemCount)
				{
					continue;
				}

				bgfx::setState(0
					| BGFX_STATE_RGB_WRITE
					| BGFX_STATE_ALPHA_WRITE
					| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
					| BGFX_STATE_MSAA
					);
				bgfx::setScissor(uint16_t(bx::fmax(pcmd->ClipRect.x, 0.0f) )
					, uint16_t(bx::fmax(pcmd->ClipRect.y, 0.0f) )
					, uint16_t(bx::fmin(pcmd->ClipRect.z, 65535.0f)-bx::fmax(pcmd->ClipRect.x, 0.0f) )
					, uint16_t(bx::fmin(pcmd->ClipRect.w, 65535.0f)-bx::fmax(pcmd->ClipRect.y, 0.0f) )
					);
				union { void* ptr; bgfx::TextureHandle handle; } texture = { pcmd->TextureId };

				bgfx::setTexture(0, s_tex, 0 != texture.handle.idx
					? texture.handle
					: m_texture
					);

				bgfx::setVertexBuffer(&tvb, 0, vtx_size);
				bgfx::setIndexBuffer(&tib, elem_offset, pcmd->ElemCount);
				bgfx::setProgram(m_program);
				bgfx::submit(m_viewId);

				elem_offset += pcmd->ElemCount;
			}
		}
	}

	void create(const void* _data, uint32_t _size, float _fontSize, bx::AllocatorI* _allocator)
	{
		m_viewId = 255;
		m_allocator = _allocator;
		m_lastScroll = 0;

		ImGuiIO& io = ImGui::GetIO();
		io.RenderDrawListsFn = renderDrawLists;
		if (NULL != m_allocator)
		{
			io.MemAllocFn = memAlloc;
			io.MemFreeFn  = memFree;
		}
		io.DisplaySize = ImVec2(1280.0f, 720.0f);
		io.DeltaTime   = 1.0f / 60.0f;
		io.IniFilename = NULL;

#if defined(SCI_NAMESPACE)
		io.KeyMap[ImGuiKey_Tab]        = (int)entry::Key::Tab;
		io.KeyMap[ImGuiKey_LeftArrow]  = (int)entry::Key::Left;
		io.KeyMap[ImGuiKey_RightArrow] = (int)entry::Key::Right;
		io.KeyMap[ImGuiKey_UpArrow]    = (int)entry::Key::Up;
		io.KeyMap[ImGuiKey_DownArrow]  = (int)entry::Key::Down;
		io.KeyMap[ImGuiKey_Home]       = (int)entry::Key::Home;
		io.KeyMap[ImGuiKey_End]        = (int)entry::Key::End;
		io.KeyMap[ImGuiKey_Delete]     = (int)entry::Key::Delete;
		io.KeyMap[ImGuiKey_Backspace]  = (int)entry::Key::Backspace;
		io.KeyMap[ImGuiKey_Enter]      = (int)entry::Key::Return;
		io.KeyMap[ImGuiKey_Escape]     = (int)entry::Key::Esc;
		io.KeyMap[ImGuiKey_A]          = (int)entry::Key::KeyA;
		io.KeyMap[ImGuiKey_C]          = (int)entry::Key::KeyC;
		io.KeyMap[ImGuiKey_V]          = (int)entry::Key::KeyV;
		io.KeyMap[ImGuiKey_X]          = (int)entry::Key::KeyX;
		io.KeyMap[ImGuiKey_Y]          = (int)entry::Key::KeyY;
		io.KeyMap[ImGuiKey_Z]          = (int)entry::Key::KeyZ;
#endif // defined(SCI_NAMESPACE)

		const bgfx::Memory* vsmem;
		const bgfx::Memory* fsmem;

		switch (bgfx::getRendererType() )
		{
		case bgfx::RendererType::Direct3D9:
			vsmem = bgfx::makeRef(vs_ocornut_imgui_dx9, sizeof(vs_ocornut_imgui_dx9) );
			fsmem = bgfx::makeRef(fs_ocornut_imgui_dx9, sizeof(fs_ocornut_imgui_dx9) );
			break;

		case bgfx::RendererType::Direct3D11:
		case bgfx::RendererType::Direct3D12:
			vsmem = bgfx::makeRef(vs_ocornut_imgui_dx11, sizeof(vs_ocornut_imgui_dx11) );
			fsmem = bgfx::makeRef(fs_ocornut_imgui_dx11, sizeof(fs_ocornut_imgui_dx11) );
			break;

		default:
			vsmem = bgfx::makeRef(vs_ocornut_imgui_glsl, sizeof(vs_ocornut_imgui_glsl) );
			fsmem = bgfx::makeRef(fs_ocornut_imgui_glsl, sizeof(fs_ocornut_imgui_glsl) );
			break;
		}

		bgfx::ShaderHandle vsh = bgfx::createShader(vsmem);
		bgfx::ShaderHandle fsh = bgfx::createShader(fsmem);
		m_program = bgfx::createProgram(vsh, fsh, true);

		m_decl
			.begin()
			.add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
			.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
			.end();

		s_tex = bgfx::createUniform("s_tex", bgfx::UniformType::Int1);

		uint8_t* data;
		int32_t width;
		int32_t height;
		void* font = ImGui::MemAlloc(_size);
		memcpy(font, _data, _size);
		io.Fonts->AddFontFromMemoryTTF(font, _size, _fontSize);

		io.Fonts->GetTexDataAsRGBA32(&data, &width, &height);

		m_texture = bgfx::createTexture2D( (uint16_t)width
			, (uint16_t)height
			, 1
			, bgfx::TextureFormat::BGRA8
			, 0
			, bgfx::copy(data, width*height*4)
			);

		ImGuiStyle& style = ImGui::GetStyle();
		style.FrameRounding = 4.0f;
	}

	void destroy()
	{
		ImGui::Shutdown();

		bgfx::destroyUniform(s_tex);
		bgfx::destroyTexture(m_texture);
		bgfx::destroyProgram(m_program);

		m_allocator = NULL;
	}

	void beginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, int _width, int _height, char _inputChar, uint8_t _viewId)
	{
		m_viewId = _viewId;
		ImGuiIO& io = ImGui::GetIO();
		if (_inputChar < 0x7f)
		{
			io.AddInputCharacter(_inputChar); // ASCII or GTFO! :(
		}

		io.DisplaySize = ImVec2( (float)_width, (float)_height);
		io.DeltaTime = 1.0f / 60.0f;
		io.MousePos = ImVec2( (float)_mx, (float)_my);
		io.MouseDown[0] = 0 != (_button & IMGUI_MBUT_LEFT);
		io.MouseDown[1] = 0 != (_button & IMGUI_MBUT_RIGHT);
		io.MouseWheel = (float)(_scroll - m_lastScroll);
		m_lastScroll = _scroll;

#if defined(SCI_NAMESPACE)
		uint8_t modifiers = inputGetModifiersState();
		io.KeyShift = 0 != (modifiers & (entry::Modifier::LeftShift | entry::Modifier::RightShift) );
		io.KeyCtrl  = 0 != (modifiers & (entry::Modifier::LeftCtrl  | entry::Modifier::RightCtrl ) );
		io.KeyAlt   = 0 != (modifiers & (entry::Modifier::LeftAlt   | entry::Modifier::RightAlt  ) );
		for (int32_t ii = 0; ii < (int32_t)entry::Key::Count; ++ii)
		{
			io.KeysDown[ii] = inputGetKeyState(entry::Key::Enum(ii) );
		}
#endif // defined(SCI_NAMESPACE)

		ImGui::NewFrame();

		//ImGui::ShowTestWindow(); //Debug only.
	}

	void endFrame()
	{
		ImGui::Render();
	}

	bx::AllocatorI*     m_allocator;
	bgfx::VertexDecl    m_decl;
	bgfx::ProgramHandle m_program;
	bgfx::TextureHandle m_texture;
	bgfx::UniformHandle s_tex;
	uint8_t m_viewId;
	int32_t m_lastScroll;
};

static OcornutImguiContext s_ctx;

void* OcornutImguiContext::memAlloc(size_t _size)
{
	return BX_ALLOC(s_ctx.m_allocator, _size);
}

void OcornutImguiContext::memFree(void* _ptr)
{
	BX_FREE(s_ctx.m_allocator, _ptr);
}

void OcornutImguiContext::renderDrawLists(ImDrawData* draw_data)
{
	s_ctx.render(draw_data);
}

void IMGUI_create(const void* _data, uint32_t _size, float _fontSize, bx::AllocatorI* _allocator)
{
	s_ctx.create(_data, _size, _fontSize, _allocator);
}

void IMGUI_destroy()
{
	s_ctx.destroy();
}

void IMGUI_beginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, int _width, int _height, char _inputChar, uint8_t _viewId)
{
	s_ctx.beginFrame(_mx, _my, _button, _scroll, _width, _height, _inputChar, _viewId);
}

void IMGUI_endFrame()
{
	s_ctx.endFrame();
}
<commit_msg>Fixed imgui delta time.<commit_after>/*
 * Copyright 2014-2015 Daniel Collin. All rights reserved.
 * License: http://www.opensource.org/licenses/BSD-2-Clause
 */

#include <bgfx.h>
#include <bx/allocator.h>
#include <bx/fpumath.h>
#include <bx/timer.h>
#include <ocornut-imgui/imgui.h>
#include "imgui.h"
#include "ocornut_imgui.h"
#include <stb/stb_image.c>

#if defined(SCI_NAMESPACE)
#	include "../entry/input.h"
#endif // defined(SCI_NAMESPACE)

#include "vs_ocornut_imgui.bin.h"
#include "fs_ocornut_imgui.bin.h"

struct OcornutImguiContext
{
	static void* memAlloc(size_t _size);
	static void memFree(void* _ptr);
	static void renderDrawLists(ImDrawData* draw_data);

	void render(ImDrawData* draw_data)
	{
		const float width  = ImGui::GetIO().DisplaySize.x;
		const float height = ImGui::GetIO().DisplaySize.y;

		float ortho[16];
		bx::mtxOrtho(ortho, 0.0f, width, height, 0.0f, -1.0f, 1.0f);

		bgfx::setViewTransform(m_viewId, NULL, ortho);

		// Render command lists
		for (int32_t ii = 0; ii < draw_data->CmdListsCount; ++ii)
		{
			bgfx::TransientVertexBuffer tvb;
			bgfx::TransientIndexBuffer tib;

			const ImDrawList* cmd_list   = draw_data->CmdLists[ii];
			uint32_t vtx_size = (uint32_t)cmd_list->VtxBuffer.size();
			uint32_t idx_size = (uint32_t)cmd_list->IdxBuffer.size();

			if (!bgfx::checkAvailTransientVertexBuffer(vtx_size, m_decl) || !bgfx::checkAvailTransientIndexBuffer(idx_size) )
			{
				// not enough space in transient buffer just quit drawing the rest...
				break;
			}

			bgfx::allocTransientVertexBuffer(&tvb, vtx_size, m_decl);
			bgfx::allocTransientIndexBuffer(&tib, idx_size);

			ImDrawVert* verts = (ImDrawVert*)tvb.data;
			memcpy(verts, cmd_list->VtxBuffer.begin(), vtx_size * sizeof(ImDrawVert) );

			ImDrawIdx* indices = (ImDrawIdx*)tib.data;
			memcpy(indices, cmd_list->IdxBuffer.begin(), idx_size * sizeof(ImDrawIdx) );

			uint32_t elem_offset = 0;
			const ImDrawCmd* pcmd_begin = cmd_list->CmdBuffer.begin();
			const ImDrawCmd* pcmd_end   = cmd_list->CmdBuffer.end();
			for (const ImDrawCmd* pcmd = pcmd_begin; pcmd != pcmd_end; pcmd++)
			{
				if (pcmd->UserCallback)
				{
					pcmd->UserCallback(cmd_list, pcmd);
					elem_offset += pcmd->ElemCount;
					continue;
				}
				if (0 == pcmd->ElemCount)
				{
					continue;
				}

				bgfx::setState(0
					| BGFX_STATE_RGB_WRITE
					| BGFX_STATE_ALPHA_WRITE
					| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
					| BGFX_STATE_MSAA
					);
				bgfx::setScissor(uint16_t(bx::fmax(pcmd->ClipRect.x, 0.0f) )
					, uint16_t(bx::fmax(pcmd->ClipRect.y, 0.0f) )
					, uint16_t(bx::fmin(pcmd->ClipRect.z, 65535.0f)-bx::fmax(pcmd->ClipRect.x, 0.0f) )
					, uint16_t(bx::fmin(pcmd->ClipRect.w, 65535.0f)-bx::fmax(pcmd->ClipRect.y, 0.0f) )
					);
				union { void* ptr; bgfx::TextureHandle handle; } texture = { pcmd->TextureId };

				bgfx::setTexture(0, s_tex, 0 != texture.handle.idx
					? texture.handle
					: m_texture
					);

				bgfx::setVertexBuffer(&tvb, 0, vtx_size);
				bgfx::setIndexBuffer(&tib, elem_offset, pcmd->ElemCount);
				bgfx::setProgram(m_program);
				bgfx::submit(m_viewId);

				elem_offset += pcmd->ElemCount;
			}
		}
	}

	void create(const void* _data, uint32_t _size, float _fontSize, bx::AllocatorI* _allocator)
	{
		m_viewId = 255;
		m_allocator = _allocator;
		m_lastScroll = 0;
		m_last = bx::getHPCounter();

		ImGuiIO& io = ImGui::GetIO();
		io.RenderDrawListsFn = renderDrawLists;
		if (NULL != m_allocator)
		{
			io.MemAllocFn = memAlloc;
			io.MemFreeFn  = memFree;
		}

		io.DisplaySize = ImVec2(1280.0f, 720.0f);
		io.DeltaTime   = 1.0f / 60.0f;
		io.IniFilename = NULL;

#if defined(SCI_NAMESPACE)
		io.KeyMap[ImGuiKey_Tab]        = (int)entry::Key::Tab;
		io.KeyMap[ImGuiKey_LeftArrow]  = (int)entry::Key::Left;
		io.KeyMap[ImGuiKey_RightArrow] = (int)entry::Key::Right;
		io.KeyMap[ImGuiKey_UpArrow]    = (int)entry::Key::Up;
		io.KeyMap[ImGuiKey_DownArrow]  = (int)entry::Key::Down;
		io.KeyMap[ImGuiKey_Home]       = (int)entry::Key::Home;
		io.KeyMap[ImGuiKey_End]        = (int)entry::Key::End;
		io.KeyMap[ImGuiKey_Delete]     = (int)entry::Key::Delete;
		io.KeyMap[ImGuiKey_Backspace]  = (int)entry::Key::Backspace;
		io.KeyMap[ImGuiKey_Enter]      = (int)entry::Key::Return;
		io.KeyMap[ImGuiKey_Escape]     = (int)entry::Key::Esc;
		io.KeyMap[ImGuiKey_A]          = (int)entry::Key::KeyA;
		io.KeyMap[ImGuiKey_C]          = (int)entry::Key::KeyC;
		io.KeyMap[ImGuiKey_V]          = (int)entry::Key::KeyV;
		io.KeyMap[ImGuiKey_X]          = (int)entry::Key::KeyX;
		io.KeyMap[ImGuiKey_Y]          = (int)entry::Key::KeyY;
		io.KeyMap[ImGuiKey_Z]          = (int)entry::Key::KeyZ;
#endif // defined(SCI_NAMESPACE)

		const bgfx::Memory* vsmem;
		const bgfx::Memory* fsmem;

		switch (bgfx::getRendererType() )
		{
		case bgfx::RendererType::Direct3D9:
			vsmem = bgfx::makeRef(vs_ocornut_imgui_dx9, sizeof(vs_ocornut_imgui_dx9) );
			fsmem = bgfx::makeRef(fs_ocornut_imgui_dx9, sizeof(fs_ocornut_imgui_dx9) );
			break;

		case bgfx::RendererType::Direct3D11:
		case bgfx::RendererType::Direct3D12:
			vsmem = bgfx::makeRef(vs_ocornut_imgui_dx11, sizeof(vs_ocornut_imgui_dx11) );
			fsmem = bgfx::makeRef(fs_ocornut_imgui_dx11, sizeof(fs_ocornut_imgui_dx11) );
			break;

		default:
			vsmem = bgfx::makeRef(vs_ocornut_imgui_glsl, sizeof(vs_ocornut_imgui_glsl) );
			fsmem = bgfx::makeRef(fs_ocornut_imgui_glsl, sizeof(fs_ocornut_imgui_glsl) );
			break;
		}

		bgfx::ShaderHandle vsh = bgfx::createShader(vsmem);
		bgfx::ShaderHandle fsh = bgfx::createShader(fsmem);
		m_program = bgfx::createProgram(vsh, fsh, true);

		m_decl
			.begin()
			.add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
			.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
			.end();

		s_tex = bgfx::createUniform("s_tex", bgfx::UniformType::Int1);

		uint8_t* data;
		int32_t width;
		int32_t height;
		void* font = ImGui::MemAlloc(_size);
		memcpy(font, _data, _size);
		io.Fonts->AddFontFromMemoryTTF(font, _size, _fontSize);

		io.Fonts->GetTexDataAsRGBA32(&data, &width, &height);

		m_texture = bgfx::createTexture2D( (uint16_t)width
			, (uint16_t)height
			, 1
			, bgfx::TextureFormat::BGRA8
			, 0
			, bgfx::copy(data, width*height*4)
			);

		ImGuiStyle& style = ImGui::GetStyle();
		style.FrameRounding = 4.0f;
	}

	void destroy()
	{
		ImGui::Shutdown();

		bgfx::destroyUniform(s_tex);
		bgfx::destroyTexture(m_texture);
		bgfx::destroyProgram(m_program);

		m_allocator = NULL;
	}

	void beginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, int _width, int _height, char _inputChar, uint8_t _viewId)
	{
		m_viewId = _viewId;
		ImGuiIO& io = ImGui::GetIO();
		if (_inputChar < 0x7f)
		{
			io.AddInputCharacter(_inputChar); // ASCII or GTFO! :(
		}

		io.DisplaySize = ImVec2( (float)_width, (float)_height);

		const int64_t now = bx::getHPCounter();
		const int64_t frameTime = now - m_last;
		m_last = now;
		const double freq = double(bx::getHPFrequency() );
		io.DeltaTime = float(frameTime/freq);

		io.MousePos = ImVec2( (float)_mx, (float)_my);
		io.MouseDown[0] = 0 != (_button & IMGUI_MBUT_LEFT);
		io.MouseDown[1] = 0 != (_button & IMGUI_MBUT_RIGHT);
		io.MouseWheel = (float)(_scroll - m_lastScroll);
		m_lastScroll = _scroll;

#if defined(SCI_NAMESPACE)
		uint8_t modifiers = inputGetModifiersState();
		io.KeyShift = 0 != (modifiers & (entry::Modifier::LeftShift | entry::Modifier::RightShift) );
		io.KeyCtrl  = 0 != (modifiers & (entry::Modifier::LeftCtrl  | entry::Modifier::RightCtrl ) );
		io.KeyAlt   = 0 != (modifiers & (entry::Modifier::LeftAlt   | entry::Modifier::RightAlt  ) );
		for (int32_t ii = 0; ii < (int32_t)entry::Key::Count; ++ii)
		{
			io.KeysDown[ii] = inputGetKeyState(entry::Key::Enum(ii) );
		}
#endif // defined(SCI_NAMESPACE)

		ImGui::NewFrame();

		ImGui::ShowTestWindow(); //Debug only.
	}

	void endFrame()
	{
		ImGui::Render();
	}

	bx::AllocatorI*     m_allocator;
	bgfx::VertexDecl    m_decl;
	bgfx::ProgramHandle m_program;
	bgfx::TextureHandle m_texture;
	bgfx::UniformHandle s_tex;
	int64_t m_last;
	int32_t m_lastScroll;
	uint8_t m_viewId;
};

static OcornutImguiContext s_ctx;

void* OcornutImguiContext::memAlloc(size_t _size)
{
	return BX_ALLOC(s_ctx.m_allocator, _size);
}

void OcornutImguiContext::memFree(void* _ptr)
{
	BX_FREE(s_ctx.m_allocator, _ptr);
}

void OcornutImguiContext::renderDrawLists(ImDrawData* draw_data)
{
	s_ctx.render(draw_data);
}

void IMGUI_create(const void* _data, uint32_t _size, float _fontSize, bx::AllocatorI* _allocator)
{
	s_ctx.create(_data, _size, _fontSize, _allocator);
}

void IMGUI_destroy()
{
	s_ctx.destroy();
}

void IMGUI_beginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, int _width, int _height, char _inputChar, uint8_t _viewId)
{
	s_ctx.beginFrame(_mx, _my, _button, _scroll, _width, _height, _inputChar, _viewId);
}

void IMGUI_endFrame()
{
	s_ctx.endFrame();
}
<|endoftext|>


<commit_before>/// @example store_primes_in_vector.cpp
/// Store primes in a std::vector using primesieve.

#include <primesieve.hpp>
#include <vector>

int main()
{
  std::vector<int> primes;

  // Store the primes <= 1000
  primesieve::generate_primes(1000, &primes);

  primes.clear();

  // Store the first 1000 primes
  primesieve::generate_n_primes(1000, &primes);

  return 0;
}
<commit_msg>Add more examples<commit_after>/// @example store_primes_in_vector.cpp
/// Store primes in a std::vector using primesieve.

#include <primesieve.hpp>
#include <vector>

int main()
{
  std::vector<int> primes;

  // Store primes <= 1000
  primesieve::generate_primes(1000, &primes);

  primes.clear();

  // Store primes inside [1000, 2000]
  primesieve::generate_primes(1000, 2000, &primes);

  primes.clear();

  // Store first 1000 primes
  primesieve::generate_n_primes(1000, &primes);

  primes.clear();

  // Store first 10 primes >= 1000
  primesieve::generate_n_primes(10, 1000, &primes);

  return 0;
}
<|endoftext|>


<commit_before>#include "src/triangle.h"

// simplest case: will plot either a flat bottom or flat top triangles
enum TriangleType
{
    FLAT_BOTTOM,
    FLAT_TOP
};

// internal triangle renderer based on triangle type
void drawTriangleType(const Triangle *t, const Vertex *v0, const Vertex *v1, const Vertex *v2, unsigned char *buffer, enum TriangleType type);

// draw the triangle!
void drawTriangle(const Triangle *t, unsigned char *buffer)
{
    const Vertex *v0, *v1, *v2;

    v0 = &t->vertices[0];
    v1 = &t->vertices[1];
    v2 = &t->vertices[2];

    // sort vertices here so that v0 is topmost, then v1, then v2
    if(v0->position.y > v1->position.y)
    {
        v0 = &t->vertices[1];
        v1 = &t->vertices[0];
    }

    if(v0->position.y > v2->position.y)
    {
        v2 = v0;
        v0 = &t->vertices[2];
    }

    if(v1->position.y == v2->position.y)
        drawTriangleType(t, v0, v1, v2, buffer, FLAT_BOTTOM);
    else if(v0->position.y == v1->position.y)
        drawTriangleType(t, v2, v1, v0, buffer, FLAT_TOP);
    else
    {
        Vertex v3;

        if(v2->position.y > v1->position.y)
        {
            const Vertex *tmp = v2;
            v2 = v1;
            v1 = tmp;
        }

        v3.position.x = v0->position.x + ((float)(v2->position.y - v0->position.y) / (float)(v1->position.y - v0->position.y)) * (v1->position.x - v0->position.x);
        v3.position.y = v2->position.y;
        v3.position.z = v2->position.z;
        v3.uv.u = v1->uv.u * 0.5;
        v3.uv.v = v1->uv.v * 0.5;
        drawTriangleType(t, v0, &v3, v2, buffer, FLAT_BOTTOM);
        drawTriangleType(t, v1, &v3, v2, buffer, FLAT_TOP);
    }
}

/*
* Render counter clockwise (v0->v1->v2) for wanted effect.
* v0         v0----v1
* |\         |     /
* | \        |    /
* |  \       |   /
* |   \      |  /
* |    \     | /
* |     \    |/
* v2-----v1  v2
*/
void drawTriangleType(const Triangle *t, const Vertex *v0, const Vertex *v1, const Vertex *v2, unsigned char *buffer, enum TriangleType type)
{
    float invDy, dxLeft, dxRight, xLeft, xRight;
    int x, y, yDir = 1;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        yDir = -1;
    }
    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    xLeft  = v0->position.x;
    xRight = xLeft;

    if(!t->texture)
    {
        for(y = v0->position.y; ; y += yDir)
        {
            drawLine(xLeft, y, xRight, y, t->color, buffer);
            xLeft += dxLeft;
            xRight += dxRight;

            if(type == FLAT_BOTTOM && y >= v2->position.y)
                break;
            else if(type == FLAT_TOP && y <= v2->position.y)
                break;
        }
    }
    else
    {
        float texW = t->texture->width - 1;
        float texH = t->texture->height - 1;
        float duLeft =  texW * (v2->uv.u - v0->uv.u) * invDy;
        float dvLeft =  texH * (v2->uv.v - v0->uv.v) * invDy;
        float duRight = texW * (v1->uv.u - v0->uv.u) * invDy;
        float dvRight = texH * (v1->uv.v - v0->uv.v) * invDy;

        float uLeft = texW * v0->uv.u;
        float uRight = uLeft;
        float vLeft = texH * v0->uv.v;
        float vRight = vLeft;
        int startY = v0->position.y;
        int endY = v2->position.y;

        setPalette(t->texture->palette);

        if(type == FLAT_BOTTOM)
            y = startY;
        else
        {
            startY = v2->position.y;
            endY   = v0->position.y;
            y = endY;
        }

        for(; ; y += yDir)
        {
            int startX = xLeft;
            int endX  = xRight;
            float u = uLeft;
            float v = vLeft;
            float du, dv;
            float dx = endX - startX;

            if(dx > 0)
            {
                du = (uRight - uLeft) / dx;
                dv = (vRight - vLeft) / dx;
            }
            else
            {
                du = uRight - uLeft;
                dv = vRight - vLeft;
            }

            for(x = startX; x <= endX; ++x)
            {
                byte pixel = t->texture->data[(int)u + ((int)v << 6)];
                drawPixel(x, y, pixel, buffer);
                u += du;
                v += dv;
            }

            xLeft += dxLeft;
            xRight += dxRight;
            uLeft += duLeft;
            uRight += duRight;
            vLeft += dvLeft;
            vRight += dvRight;

           if(type == FLAT_BOTTOM && y >= endY)
                break;
            else if ( type == FLAT_TOP && y <= startY)
                break;
        }
    }
}
<commit_msg>more precision tweaks<commit_after>#include "src/triangle.h"

// simplest case: will plot either a flat bottom or flat top triangles
enum TriangleType
{
    FLAT_BOTTOM,
    FLAT_TOP
};

// internal triangle renderer based on triangle type
void drawTriangleType(const Triangle *t, const Vertex *v0, const Vertex *v1, const Vertex *v2, unsigned char *buffer, enum TriangleType type);

// draw the triangle!
void drawTriangle(const Triangle *t, unsigned char *buffer)
{
    const Vertex *v0, *v1, *v2;

    v0 = &t->vertices[0];
    v1 = &t->vertices[1];
    v2 = &t->vertices[2];

    // sort vertices here so that v0 is topmost, then v1, then v2
    if(v0->position.y > v1->position.y)
    {
        v0 = &t->vertices[1];
        v1 = &t->vertices[0];
    }

    if(v0->position.y > v2->position.y)
    {
        v2 = v0;
        v0 = &t->vertices[2];
    }

    if(v1->position.y == v2->position.y)
        drawTriangleType(t, v0, v1, v2, buffer, FLAT_BOTTOM);
    else if(v0->position.y == v1->position.y)
        drawTriangleType(t, v2, v1, v0, buffer, FLAT_TOP);
    else
    {
        Vertex v3;

        if(v2->position.y > v1->position.y)
        {
            const Vertex *tmp = v2;
            v2 = v1;
            v1 = tmp;
        }

        v3.position.x = v0->position.x + ((float)(v2->position.y - v0->position.y) / (float)(v1->position.y - v0->position.y)) * (v1->position.x - v0->position.x);
        v3.position.y = v2->position.y;
        v3.position.z = v2->position.z;
        v3.uv.u = v1->uv.u * 0.5;
        v3.uv.v = v1->uv.v * 0.5;
        drawTriangleType(t, v0, &v3, v2, buffer, FLAT_BOTTOM);
        drawTriangleType(t, v1, &v3, v2, buffer, FLAT_TOP);
    }
}

/*
* Render counter clockwise (v0->v1->v2) for wanted effect.
* v0         v0----v1
* |\         |     /
* | \        |    /
* |  \       |   /
* |   \      |  /
* |    \     | /
* |     \    |/
* v2-----v1  v2
*/
void drawTriangleType(const Triangle *t, const Vertex *v0, const Vertex *v1, const Vertex *v2, unsigned char *buffer, enum TriangleType type)
{
    double invDy, dxLeft, dxRight, xLeft, xRight;
    double x, y, yDir = 1;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        yDir = -1;
    }
    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    xLeft  = v0->position.x;
    xRight = xLeft;

    if(!t->texture)
    {
        for(y = v0->position.y; ; y += yDir)
        {
            drawLine(xLeft, y, xRight, y, t->color, buffer);
            xLeft += dxLeft;
            xRight += dxRight;

            if(type == FLAT_BOTTOM && y >= v2->position.y)
                break;
            else if(type == FLAT_TOP && y <= v2->position.y)
                break;
        }
    }
    else
    {
        float texW = t->texture->width - 1;
        float texH = t->texture->height - 1;
        float duLeft =  texW * (v2->uv.u - v0->uv.u) * invDy;
        float dvLeft =  texH * (v2->uv.v - v0->uv.v) * invDy;
        float duRight = texW * (v1->uv.u - v0->uv.u) * invDy;
        float dvRight = texH * (v1->uv.v - v0->uv.v) * invDy;

        float uLeft = texW * v0->uv.u;
        float uRight = uLeft;
        float vLeft = texH * v0->uv.v;
        float vRight = vLeft;
        int startY = v0->position.y;
        int endY = v2->position.y;

        setPalette(t->texture->palette);

        if(type == FLAT_BOTTOM)
            y = startY;
        else
        {
            startY = v2->position.y;
            endY   = v0->position.y;
            y = endY;
        }

        for(; ; y += yDir)
        {
            int startX = xLeft;
            int endX  = xRight;
            float u = uLeft;
            float v = vLeft;
            float du, dv;
            float dx = endX - startX;

            if(dx > 0)
            {
                du = (uRight - uLeft) / dx;
                dv = (vRight - vLeft) / dx;
            }
            else
            {
                du = uRight - uLeft;
                dv = vRight - vLeft;
            }

            for(x = startX; x <= endX; ++x)
            {
                byte pixel = t->texture->data[(int)u + ((int)v << 6)];
                drawPixel(x, y, pixel, buffer);
                u += du;
                v += dv;
            }

            xLeft += dxLeft;
            xRight += dxRight;
            uLeft += duLeft;
            uRight += duRight;
            vLeft += dvLeft;
            vRight += dvRight;

           if(type == FLAT_BOTTOM && y >= endY)
                break;
            else if ( type == FLAT_TOP && y <= startY)
                break;
        }
    }
}
<|endoftext|>


<commit_before>#include <Eigen/Sparse>

#include <functional>
#include <iostream>
#include <random>

#include <spii/auto_diff_term.h>
#include <spii/function.h>
#include <spii/solver.h>
using namespace spii;

#include "hastighet.h"

// One term in the negative log-likelihood function for
// a one-dimensional Gaussian distribution.
struct NegLogLikelihood
{
	double sample;
	NegLogLikelihood(double sample)
	{
		this->sample = sample;
	}

	template<typename R>
	R operator()(const R* const mu, const R* const sigma) const
	{
		R diff = (*mu - sample) / *sigma;
		return 0.5 * diff*diff + log(*sigma);
	}
};

class LikelihoodBenchmark :
	public hastighet::Test
{
public:
	Function f;
	double mu;
	double sigma;
	Eigen::VectorXd x, g;
	Eigen::MatrixXd H;
	double out;
	Solver solver;
	SolverResults results;

	LikelihoodBenchmark() :
		x(2),
		g(2)
	{
		std::mt19937 prng(unsigned(1));
		std::normal_distribution<double> normal;
		auto randn = std::bind(normal, prng);

		mu    = 5.0;
		sigma = 3.0;

		f.add_variable(&mu, 1);
		f.add_variable(&sigma, 1);

		for (int i = 0; i < 10000; ++i) {
			double sample = sigma*randn() + mu;
			auto* llh = new NegLogLikelihood(sample);
			f.add_term(new AutoDiffTerm<NegLogLikelihood, 1, 1>(llh), &mu, &sigma);
		}

		f.copy_user_to_global(&x);
		f.set_number_of_threads(1);

		solver.log_function = [](const std::string&) { };
		solver.maximum_iterations = 1;
	}
};

BENCHMARK_F(LikelihoodBenchmark, evaluate)
{
	f.evaluate();
}

BENCHMARK_F(LikelihoodBenchmark, evaluate_x)
{
	f.evaluate(x);
}

BENCHMARK_F(LikelihoodBenchmark, evaluate_x_g)
{
	f.evaluate(x, &g);
}

BENCHMARK_F(LikelihoodBenchmark, evaluate_x_g_H)
{
	f.evaluate(x, &g, &H);
}

struct LennardJonesTerm
{
	template<typename R>
	R operator()(const R* const p1, const R* const p2) const
	{
		R dx = p1[0] - p2[0];
		R dy = p1[1] - p2[1];
		R dz = p1[2] - p2[2];
		R r2 = dx*dx + dy*dy + dz*dz;
		R r6  = r2*r2*r2;
		R r12 = r6*r6;
		return 1.0 / r12 - 2.0 / r6;
	}
};

class LennardJonesBenchmark :
	public hastighet::Test
{
public:
	Function potential;
	std::vector<Eigen::Vector3d> points;
	std::vector<Eigen::Vector3d> org_points;
	Eigen::VectorXd x, g;
	Eigen::MatrixXd H;
	Solver solver;
	SolverResults results;

	LennardJonesBenchmark() :
		points(100)
	{
		std::mt19937 prng(1);
		std::normal_distribution<double> normal;
		auto randn = std::bind(normal, prng);

		int N = points.size();
		int n = int(std::ceil(std::pow(double(N), 1.0/3.0)));

		// Initial position is a cubic grid with random pertubations.
		for (int i = 0; i < N; ++i) {
			int x =  i % n;
			int y = (i / n) % n;
			int z = (i / n) / n;

			potential.add_variable(&points[i][0], 3);
			points[i][0] = x + 0.05 * randn();
			points[i][1] = y + 0.05 * randn();
			points[i][2] = z + 0.05 * randn();
		}

		for (int i = 0; i < N; ++i) {
			for (int j = i + 1; j < N; ++j) {
				potential.add_term(
					new AutoDiffTerm<LennardJonesTerm, 3, 3>(
						new LennardJonesTerm),
						&points[i][0],
						&points[j][0]);
			}
		}

		x.resize(potential.get_number_of_scalars());
		potential.copy_user_to_global(&x);
		g.resize(potential.get_number_of_scalars());
		org_points = points;

		potential.set_number_of_threads(1);

		solver.log_function = [](const std::string&) { };
		solver.maximum_iterations = 1;
	}
};

BENCHMARK_F(LennardJonesBenchmark, solver_1_newton_iter)
{
	points = org_points;
	solver.solve_newton(potential, &results);
}

BENCHMARK_F(LennardJonesBenchmark, solver_1_lbfgs_iter)
{
	points = org_points;
	solver.solve_lbfgs(potential, &results);
}

int main(int argc, char** argv)
{
	hastighet::Benchmarker::RunAllTests(argc, argv);
}
<commit_msg>No solver in function benchmark.<commit_after>#include <Eigen/Sparse>

#include <functional>
#include <iostream>
#include <random>

#include <spii/auto_diff_term.h>
#include <spii/function.h>
#include <spii/solver.h>
using namespace spii;

#include "hastighet.h"

// One term in the negative log-likelihood function for
// a one-dimensional Gaussian distribution.
struct NegLogLikelihood
{
	double sample;
	NegLogLikelihood(double sample)
	{
		this->sample = sample;
	}

	template<typename R>
	R operator()(const R* const mu, const R* const sigma) const
	{
		R diff = (*mu - sample) / *sigma;
		return 0.5 * diff*diff + log(*sigma);
	}
};

class LikelihoodBenchmark :
	public hastighet::Test
{
public:
	Function f;
	double mu;
	double sigma;
	Eigen::VectorXd x, g;
	Eigen::MatrixXd H;
	double out;

	LikelihoodBenchmark() :
		x(2),
		g(2)
	{
		std::mt19937 prng(unsigned(1));
		std::normal_distribution<double> normal;
		auto randn = std::bind(normal, prng);

		mu    = 5.0;
		sigma = 3.0;

		f.add_variable(&mu, 1);
		f.add_variable(&sigma, 1);

		for (int i = 0; i < 10000; ++i) {
			double sample = sigma*randn() + mu;
			auto* llh = new NegLogLikelihood(sample);
			f.add_term(new AutoDiffTerm<NegLogLikelihood, 1, 1>(llh), &mu, &sigma);
		}

		f.copy_user_to_global(&x);
		f.set_number_of_threads(1);
	}
};

BENCHMARK_F(LikelihoodBenchmark, evaluate)
{
	f.evaluate();
}

BENCHMARK_F(LikelihoodBenchmark, evaluate_x)
{
	f.evaluate(x);
}

BENCHMARK_F(LikelihoodBenchmark, evaluate_x_g)
{
	f.evaluate(x, &g);
}

BENCHMARK_F(LikelihoodBenchmark, evaluate_x_g_H)
{
	f.evaluate(x, &g, &H);
}

struct LennardJonesTerm
{
	template<typename R>
	R operator()(const R* const p1, const R* const p2) const
	{
		R dx = p1[0] - p2[0];
		R dy = p1[1] - p2[1];
		R dz = p1[2] - p2[2];
		R r2 = dx*dx + dy*dy + dz*dz;
		R r6  = r2*r2*r2;
		R r12 = r6*r6;
		return 1.0 / r12 - 2.0 / r6;
	}
};

class LennardJonesBenchmark :
	public hastighet::Test
{
public:
	Function potential;
	std::vector<Eigen::Vector3d> points;
	std::vector<Eigen::Vector3d> org_points;
	Eigen::VectorXd x, g;
	Eigen::MatrixXd H;

	LennardJonesBenchmark() :
		points(100)
	{
		std::mt19937 prng(1);
		std::normal_distribution<double> normal;
		auto randn = std::bind(normal, prng);

		int N = points.size();
		int n = int(std::ceil(std::pow(double(N), 1.0/3.0)));

		// Initial position is a cubic grid with random pertubations.
		for (int i = 0; i < N; ++i) {
			int x =  i % n;
			int y = (i / n) % n;
			int z = (i / n) / n;

			potential.add_variable(&points[i][0], 3);
			points[i][0] = x + 0.05 * randn();
			points[i][1] = y + 0.05 * randn();
			points[i][2] = z + 0.05 * randn();
		}

		for (int i = 0; i < N; ++i) {
			for (int j = i + 1; j < N; ++j) {
				potential.add_term(
					new AutoDiffTerm<LennardJonesTerm, 3, 3>(
						new LennardJonesTerm),
						&points[i][0],
						&points[j][0]);
			}
		}

		x.resize(potential.get_number_of_scalars());
		potential.copy_user_to_global(&x);
		g.resize(potential.get_number_of_scalars());
		org_points = points;

		potential.set_number_of_threads(1);
	}
};

BENCHMARK_F(LennardJonesBenchmark, evaluate)
{
	potential.evaluate();
}

BENCHMARK_F(LennardJonesBenchmark, evaluate_x)
{
	potential.evaluate(x);
}

BENCHMARK_F(LennardJonesBenchmark, evaluate_x_g)
{
	potential.evaluate(x, &g);
}

BENCHMARK_F(LennardJonesBenchmark, evaluate_x_g_H)
{
	potential.evaluate(x, &g, &H);
}

int main(int argc, char** argv)
{
	hastighet::Benchmarker::RunAllTests(argc, argv);
}
<|endoftext|>