<commit_before>//===- FunctionImport.cpp - ThinLTO Summary-based Function Import ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Function import based on summaries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/FunctionImport.h"

#include "llvm/ADT/StringSet.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SourceMgr.h"
using namespace llvm;

#define DEBUG_TYPE "function-import"

/// Limit on instruction count of imported functions.
static cl::opt<unsigned> ImportInstrLimit(
    "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"),
    cl::desc("Only import functions with less than N instructions"));

// Load lazily a module from \p FileName in \p Context.
static std::unique_ptr<Module> loadFile(const std::string &FileName,
                                        LLVMContext &Context) {
  SMDiagnostic Err;
  DEBUG(dbgs() << "Loading '" << FileName << "'\n");
  std::unique_ptr<Module> Result = getLazyIRFileModule(FileName, Err, Context);
  if (!Result) {
    Err.print("function-import", errs());
    return nullptr;
  }

  Result->materializeMetadata();
  UpgradeDebugInfo(*Result);

  return Result;
}

// Get a Module for \p FileName from the cache, or load it lazily.
Module &ModuleLazyLoaderCache::operator()(StringRef FileName) {
  auto &Module = ModuleMap[FileName];
  if (!Module)
    Module = loadFile(FileName, Context);
  return *Module;
}

/// Walk through the instructions in \p F looking for external
/// calls not already in the \p CalledFunctions set. If any are
/// found they are added to the \p Worklist for importing.
static void findExternalCalls(const Function &F, StringSet<> &CalledFunctions,
                              SmallVector<StringRef, 64> &Worklist) {
  for (auto &BB : F) {
    for (auto &I : BB) {
      if (isa<CallInst>(I)) {
        DEBUG(dbgs() << "Found a call: '" << I << "'\n");
        auto CalledFunction = cast<CallInst>(I).getCalledFunction();
        // Insert any new external calls that have not already been
        // added to set/worklist.
        if (CalledFunction && CalledFunction->hasName() &&
            CalledFunction->isDeclaration() &&
            !CalledFunctions.count(CalledFunction->getName())) {
          CalledFunctions.insert(CalledFunction->getName());
          Worklist.push_back(CalledFunction->getName());
        }
      }
    }
  }
}

// Automatically import functions in Module \p M based on the summaries index.
//
// The current implementation imports every called functions that exists in the
// summaries index.
bool FunctionImporter::importFunctions(Module &M) {

  bool Changed = false;

  /// First step is collecting the called external functions.
  StringSet<> CalledFunctions;
  SmallVector<StringRef, 64> Worklist;
  for (auto &F : M) {
    if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone))
      continue;
    findExternalCalls(F, CalledFunctions, Worklist);
  }

  /// Second step: for every call to an external function, try to import it.

  // Linker that will be used for importing function
  Linker L(M, DiagnosticHandler);

  while (!Worklist.empty()) {
    auto CalledFunctionName = Worklist.pop_back_val();
    DEBUG(dbgs() << "Process import for " << CalledFunctionName << "\n");

    // Try to get a summary for this function call.
    auto InfoList = Index.findFunctionInfoList(CalledFunctionName);
    if (InfoList == Index.end()) {
      DEBUG(dbgs() << "No summary for " << CalledFunctionName
                   << " Ignoring.\n");
      continue;
    }
    assert(!InfoList->second.empty() && "No summary, error at import?");

    // Comdat can have multiple entries, FIXME: what do we do with them?
    auto &Info = InfoList->second[0];
    assert(Info && "Nullptr in list, error importing summaries?\n");

    auto *Summary = Info->functionSummary();
    if (!Summary) {
      // FIXME: in case we are lazyloading summaries, we can do it now.
      DEBUG(dbgs() << "Missing summary for  " << CalledFunctionName
                   << ", error at import?\n");
      llvm_unreachable("Missing summary");
    }

    if (Summary->instCount() > ImportInstrLimit) {
      DEBUG(dbgs() << "Skip import of " << CalledFunctionName << " with "
                   << Summary->instCount() << " instructions (limit "
                   << ImportInstrLimit << ")\n");
      continue;
    }

    // Get the module path from the summary.
    auto FileName = Summary->modulePath();
    DEBUG(dbgs() << "Importing " << CalledFunctionName << " from " << FileName
                 << "\n");

    // Get the module for the import (potentially from the cache).
    auto &Module = getLazyModule(FileName);
    assert(&Module.getContext() == &M.getContext());

    // The function that we will import!
    GlobalValue *SGV = Module.getNamedValue(CalledFunctionName);
    StringRef ImportFunctionName = CalledFunctionName;
    if (!SGV) {
      // Might be local in source Module, promoted/renamed in dest Module M.
      std::pair<StringRef, StringRef> Split =
          CalledFunctionName.split(".llvm.");
      SGV = Module.getNamedValue(Split.first);
#ifndef NDEBUG
      // Assert that Split.second is module id
      uint64_t ModuleId;
      assert(!Split.second.getAsInteger(10, ModuleId));
      assert(ModuleId == Index.getModuleId(FileName));
#endif
    }
    Function *F = dyn_cast<Function>(SGV);
    if (!F && isa<GlobalAlias>(SGV)) {
      auto *SGA = dyn_cast<GlobalAlias>(SGV);
      F = dyn_cast<Function>(SGA->getBaseObject());
      ImportFunctionName = F->getName();
    }
    if (!F) {
      errs() << "Can't load function '" << CalledFunctionName << "' in Module '"
             << FileName << "', error in the summary?\n";
      llvm_unreachable("Can't load function in Module");
    }

    // We cannot import weak_any functions/aliases without possibly affecting
    // the order they are seen and selected by the linker, changing program
    // semantics.
    if (SGV->hasWeakAnyLinkage()) {
      DEBUG(dbgs() << "Ignoring import request for weak-any "
                   << (isa<Function>(SGV) ? "function " : "alias ")
                   << CalledFunctionName << " from " << FileName << "\n");
      continue;
    }

    // Link in the specified function.
    DenseSet<const GlobalValue *> FunctionsToImport;
    FunctionsToImport.insert(F);
    if (L.linkInModule(Module, Linker::Flags::None, &Index,
                       &FunctionsToImport))
      report_fatal_error("Function Import: link error");

    // Process the newly imported function and add callees to the worklist.
    GlobalValue *NewGV = M.getNamedValue(ImportFunctionName);
    assert(NewGV);
    Function *NewF = dyn_cast<Function>(NewGV);
    assert(NewF);
    findExternalCalls(*NewF, CalledFunctions, Worklist);

    Changed = true;
  }

  return Changed;
}

/// Summary file to use for function importing when using -function-import from
/// the command line.
static cl::opt<std::string>
    SummaryFile("summary-file",
                cl::desc("The summary file to use for function importing."));

static void diagnosticHandler(const DiagnosticInfo &DI) {
  raw_ostream &OS = errs();
  DiagnosticPrinterRawOStream DP(OS);
  DI.print(DP);
  OS << '\n';
}

/// Parse the function index out of an IR file and return the function
/// index object if found, or nullptr if not.
static std::unique_ptr<FunctionInfoIndex>
getFunctionIndexForFile(StringRef Path, std::string &Error,
                        DiagnosticHandlerFunction DiagnosticHandler) {
  std::unique_ptr<MemoryBuffer> Buffer;
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFile(Path);
  if (std::error_code EC = BufferOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  Buffer = std::move(BufferOrErr.get());
  ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
      object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(),
                                              DiagnosticHandler);
  if (std::error_code EC = ObjOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  return (*ObjOrErr)->takeIndex();
}

/// Pass that performs cross-module function import provided a summary file.
class FunctionImportPass : public ModulePass {

public:
  /// Pass identification, replacement for typeid
  static char ID;

  explicit FunctionImportPass() : ModulePass(ID) {}

  bool runOnModule(Module &M) override {
    if (SummaryFile.empty()) {
      report_fatal_error("error: -function-import requires -summary-file\n");
    }
    std::string Error;
    std::unique_ptr<FunctionInfoIndex> Index =
        getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler);
    if (!Index) {
      errs() << "Error loading file '" << SummaryFile << "': " << Error << "\n";
      return false;
    }

    // Perform the import now.
    ModuleLazyLoaderCache Loader(M.getContext());
    FunctionImporter Importer(*Index, diagnosticHandler,
                              [&](StringRef Name)
                                  -> Module &{ return Loader(Name); });
    return Importer.importFunctions(M);

    return false;
  }
};

char FunctionImportPass::ID = 0;
INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import",
                      "Summary Based Function Import", false, false)
INITIALIZE_PASS_END(FunctionImportPass, "function-import",
                    "Summary Based Function Import", false, false)

namespace llvm {
Pass *createFunctionImportPass() { return new FunctionImportPass(); }
}
<commit_msg>Refactor FunctionImporter::importFunctions with a helper function to process the Worklist (NFC)<commit_after>//===- FunctionImport.cpp - ThinLTO Summary-based Function Import ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Function import based on summaries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/FunctionImport.h"

#include "llvm/ADT/StringSet.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SourceMgr.h"
using namespace llvm;

#define DEBUG_TYPE "function-import"

/// Limit on instruction count of imported functions.
static cl::opt<unsigned> ImportInstrLimit(
    "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"),
    cl::desc("Only import functions with less than N instructions"));

// Load lazily a module from \p FileName in \p Context.
static std::unique_ptr<Module> loadFile(const std::string &FileName,
                                        LLVMContext &Context) {
  SMDiagnostic Err;
  DEBUG(dbgs() << "Loading '" << FileName << "'\n");
  std::unique_ptr<Module> Result = getLazyIRFileModule(FileName, Err, Context);
  if (!Result) {
    Err.print("function-import", errs());
    return nullptr;
  }

  Result->materializeMetadata();
  UpgradeDebugInfo(*Result);

  return Result;
}

// Get a Module for \p FileName from the cache, or load it lazily.
Module &ModuleLazyLoaderCache::operator()(StringRef FileName) {
  auto &Module = ModuleMap[FileName];
  if (!Module)
    Module = loadFile(FileName, Context);
  return *Module;
}

/// Walk through the instructions in \p F looking for external
/// calls not already in the \p CalledFunctions set. If any are
/// found they are added to the \p Worklist for importing.
static void findExternalCalls(const Function &F, StringSet<> &CalledFunctions,
                              SmallVector<StringRef, 64> &Worklist) {
  for (auto &BB : F) {
    for (auto &I : BB) {
      if (isa<CallInst>(I)) {
        auto CalledFunction = cast<CallInst>(I).getCalledFunction();
        // Insert any new external calls that have not already been
        // added to set/worklist.
        if (CalledFunction && CalledFunction->hasName() &&
            CalledFunction->isDeclaration() &&
            !CalledFunctions.count(CalledFunction->getName())) {
          CalledFunctions.insert(CalledFunction->getName());
          Worklist.push_back(CalledFunction->getName());
        }
      }
    }
  }
}

// Helper function: given a worklist and an index, will process all the worklist
// and import them based on the summary information
static unsigned ProcessImportWorklist(Module &DestModule, SmallVector<StringRef, 64> &Worklist,
                                      StringSet<> &CalledFunctions,
                            Linker &TheLinker, const FunctionInfoIndex &Index,
                            std::function<Module &(StringRef FileName)> &LazyModuleLoader) {
  unsigned ImportCount = 0;
  while (!Worklist.empty()) {
    auto CalledFunctionName = Worklist.pop_back_val();
    DEBUG(dbgs() << "Process import for " << CalledFunctionName << "\n");

    // Try to get a summary for this function call.
    auto InfoList = Index.findFunctionInfoList(CalledFunctionName);
    if (InfoList == Index.end()) {
      DEBUG(dbgs() << "No summary for " << CalledFunctionName
                   << " Ignoring.\n");
      continue;
    }
    assert(!InfoList->second.empty() && "No summary, error at import?");

    // Comdat can have multiple entries, FIXME: what do we do with them?
    auto &Info = InfoList->second[0];
    assert(Info && "Nullptr in list, error importing summaries?\n");

    auto *Summary = Info->functionSummary();
    if (!Summary) {
      // FIXME: in case we are lazyloading summaries, we can do it now.
      DEBUG(dbgs() << "Missing summary for  " << CalledFunctionName
                   << ", error at import?\n");
      llvm_unreachable("Missing summary");
    }

    if (Summary->instCount() > ImportInstrLimit) {
      DEBUG(dbgs() << "Skip import of " << CalledFunctionName << " with "
                   << Summary->instCount() << " instructions (limit "
                   << ImportInstrLimit << ")\n");
      continue;
    }

    // Get the module path from the summary.
    auto FileName = Summary->modulePath();
    DEBUG(dbgs() << "Importing " << CalledFunctionName << " from " << FileName
                 << "\n");

    // Get the module for the import (potentially from the cache).
    auto &Module = LazyModuleLoader(FileName);
    assert(&Module.getContext() == &DestModule.getContext());

    // The function that we will import!
    GlobalValue *SGV = Module.getNamedValue(CalledFunctionName);
    StringRef ImportFunctionName = CalledFunctionName;
    if (!SGV) {
      // Might be local in source Module, promoted/renamed in DestModule.
      std::pair<StringRef, StringRef> Split =
          CalledFunctionName.split(".llvm.");
      SGV = Module.getNamedValue(Split.first);
#ifndef NDEBUG
      // Assert that Split.second is module id
      uint64_t ModuleId;
      assert(!Split.second.getAsInteger(10, ModuleId));
      assert(ModuleId == Index.getModuleId(FileName));
#endif
    }
    Function *F = dyn_cast<Function>(SGV);
    if (!F && isa<GlobalAlias>(SGV)) {
      auto *SGA = dyn_cast<GlobalAlias>(SGV);
      F = dyn_cast<Function>(SGA->getBaseObject());
      ImportFunctionName = F->getName();
    }
    if (!F) {
      errs() << "Can't load function '" << CalledFunctionName << "' in Module '"
             << FileName << "', error in the summary?\n";
      llvm_unreachable("Can't load function in Module");
    }

    // We cannot import weak_any functions/aliases without possibly affecting
    // the order they are seen and selected by the linker, changing program
    // semantics.
    if (SGV->hasWeakAnyLinkage()) {
      DEBUG(dbgs() << "Ignoring import request for weak-any "
                   << (isa<Function>(SGV) ? "function " : "alias ")
                   << CalledFunctionName << " from " << FileName << "\n");
      continue;
    }

    // Link in the specified function.
    DenseSet<const GlobalValue *> FunctionsToImport;
    FunctionsToImport.insert(F);
    if (TheLinker.linkInModule(Module, Linker::Flags::None, &Index,
                       &FunctionsToImport))
      report_fatal_error("Function Import: link error");

    // Process the newly imported function and add callees to the worklist.
    GlobalValue *NewGV = DestModule.getNamedValue(ImportFunctionName);
    assert(NewGV);
    Function *NewF = dyn_cast<Function>(NewGV);
    assert(NewF);
    findExternalCalls(*NewF, CalledFunctions, Worklist);
    ++ImportCount;
  }
  return ImportCount;
}

// Automatically import functions in Module \p DestModule based on the summaries
// index.
//
// The current implementation imports every called functions that exists in the
// summaries index.
bool FunctionImporter::importFunctions(Module &DestModule) {
  DEBUG(errs() << "Starting import for Module " << DestModule.getModuleIdentifier()
               << "\n");
  unsigned ImportedCount = 0;

  /// First step is collecting the called external functions.
  StringSet<> CalledFunctions;
  SmallVector<StringRef, 64> Worklist;
  for (auto &F : DestModule) {
    if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone))
      continue;
    findExternalCalls(F, CalledFunctions, Worklist);
  }
  if (Worklist.empty())
    return false;

  /// Second step: for every call to an external function, try to import it.

  // Linker that will be used for importing function
  Linker TheLinker(DestModule, DiagnosticHandler);

  ImportedCount += ProcessImportWorklist(DestModule, Worklist, CalledFunctions, TheLinker, Index, getLazyModule );

  DEBUG(errs() << "Imported " << ImportedCount << " functions for Module "
               << DestModule.getModuleIdentifier() << "\n");
  return ImportedCount;
}

/// Summary file to use for function importing when using -function-import from
/// the command line.
static cl::opt<std::string>
    SummaryFile("summary-file",
                cl::desc("The summary file to use for function importing."));

static void diagnosticHandler(const DiagnosticInfo &DI) {
  raw_ostream &OS = errs();
  DiagnosticPrinterRawOStream DP(OS);
  DI.print(DP);
  OS << '\n';
}

/// Parse the function index out of an IR file and return the function
/// index object if found, or nullptr if not.
static std::unique_ptr<FunctionInfoIndex>
getFunctionIndexForFile(StringRef Path, std::string &Error,
                        DiagnosticHandlerFunction DiagnosticHandler) {
  std::unique_ptr<MemoryBuffer> Buffer;
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFile(Path);
  if (std::error_code EC = BufferOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  Buffer = std::move(BufferOrErr.get());
  ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
      object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(),
                                              DiagnosticHandler);
  if (std::error_code EC = ObjOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  return (*ObjOrErr)->takeIndex();
}

/// Pass that performs cross-module function import provided a summary file.
class FunctionImportPass : public ModulePass {

public:
  /// Pass identification, replacement for typeid
  static char ID;

  explicit FunctionImportPass() : ModulePass(ID) {}

  bool runOnModule(Module &M) override {
    if (SummaryFile.empty()) {
      report_fatal_error("error: -function-import requires -summary-file\n");
    }
    std::string Error;
    std::unique_ptr<FunctionInfoIndex> Index =
        getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler);
    if (!Index) {
      errs() << "Error loading file '" << SummaryFile << "': " << Error << "\n";
      return false;
    }

    // Perform the import now.
    ModuleLazyLoaderCache Loader(M.getContext());
    FunctionImporter Importer(*Index, diagnosticHandler,
                              [&](StringRef Name)
                                  -> Module &{ return Loader(Name); });
    return Importer.importFunctions(M);

    return false;
  }
};

char FunctionImportPass::ID = 0;
INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import",
                      "Summary Based Function Import", false, false)
INITIALIZE_PASS_END(FunctionImportPass, "function-import",
                    "Summary Based Function Import", false, false)

namespace llvm {
Pass *createFunctionImportPass() { return new FunctionImportPass(); }
}
<|endoftext|>


<commit_before>#include <Quiver.h>

Quiver::Quiver(QString sourcePath, QObject *parent) : QObject(parent)
{
  _engine = new QQmlApplicationEngine;
  addProperty("quiver", this);

  _watcher = new QFileSystemWatcher;
  connect(_watcher,     SIGNAL(fileChanged(const QString&)),
    this,    SLOT(fileChanged(const QString&)));
  connect(_watcher,     SIGNAL(directoryChanged(const QString&)),
    this,    SLOT(fileChanged(const QString&)));

  if (!sourcePath.isEmpty()) {
    setSource(sourcePath);
  }
}

Quiver::~Quiver()
{
  delete _engine;
  delete _watcher;
}

void Quiver::detectPlatform() {
        QString platform_name("unknown");

#ifdef Q_OS_IOS
        platform_name = "ios";
#endif

#ifdef Q_OS_MACX
        platform_name = "osx";
#endif

#ifdef Q_OS_WIN
        platform_name = "win";
#endif

        QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
        if (env.contains("Quiver_platformName") && !env.value("Quiver_platformName").isEmpty()) {
                platform_name = env.value("Quiver_platformName");
        }

        setPlatform(platform_name);
}

void Quiver::setPlatform(const QString & platformName) {
  _platformName = platformName;
}

void Quiver::setSource(const QString & path)
{
  _sourcePath = path;

  if (_platformName.isEmpty()) {
          detectPlatform();
  }

  QDir platformDir(_sourcePath + "/" + _platformName);
  _engine->addImportPath(_sourcePath);
  _engine->load(QUrl::fromLocalFile(platformDir.absolutePath() + "/main.qml"));
  addWatchPath(platformDir.absolutePath());
}

void Quiver::fileChanged(const QString & path)
{
  _engine->clearComponentCache();
  emit pendingConnectionRequestChanged();

  _watcher->addPath(path);
}

void Quiver::addWatchPath(const QString & path)
{
  _watcher->addPath(path);
}

void Quiver::addWatchPaths(const QStringList & paths)
{
  _watcher->addPaths(paths);
}

void Quiver::addProperty(const QString & name, QObject * obj)
{
  _engine->rootContext()->setContextProperty(name, obj);
}
<commit_msg>announce when we have loaded main.qml (for the Quiver launcher app)<commit_after>#include <Quiver.h>

Quiver::Quiver(QString sourcePath, QObject *parent) : QObject(parent)
{
  _engine = new QQmlApplicationEngine;
  addProperty("quiver", this);

  _watcher = new QFileSystemWatcher;
  connect(_watcher,     SIGNAL(fileChanged(const QString&)),
    this,    SLOT(fileChanged(const QString&)));
  connect(_watcher,     SIGNAL(directoryChanged(const QString&)),
    this,    SLOT(fileChanged(const QString&)));

  if (!sourcePath.isEmpty()) {
    setSource(sourcePath);
  }
}

Quiver::~Quiver()
{
  delete _engine;
  delete _watcher;
}

void Quiver::detectPlatform() {
        QString platform_name("unknown");

#ifdef Q_OS_IOS
        platform_name = "ios";
#endif

#ifdef Q_OS_MACX
        platform_name = "osx";
#endif

#ifdef Q_OS_WIN
        platform_name = "win";
#endif

        QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
        if (env.contains("Quiver_platformName") && !env.value("Quiver_platformName").isEmpty()) {
                platform_name = env.value("Quiver_platformName");
        }

        setPlatform(platform_name);
}

void Quiver::setPlatform(const QString & platformName) {
  _platformName = platformName;
}

void Quiver::setSource(const QString & path)
{
  _sourcePath = path;

  if (_platformName.isEmpty()) {
          detectPlatform();
  }

  QDir platformDir(_sourcePath + "/" + _platformName);
  _engine->addImportPath(_sourcePath);
  _engine->load(QUrl::fromLocalFile(platformDir.absolutePath() + "/main.qml"));
  addWatchPath(platformDir.absolutePath());
  printf("Quiver: main.qml loaded\n"); //this must be printf() and not qDebug() << for some reason ... (20141125)
  fflush(stdout);
}

void Quiver::fileChanged(const QString & path)
{
  _engine->clearComponentCache();
  emit pendingConnectionRequestChanged();

  _watcher->addPath(path);
}

void Quiver::addWatchPath(const QString & path)
{
  _watcher->addPath(path);
}

void Quiver::addWatchPaths(const QStringList & paths)
{
  _watcher->addPaths(paths);
}

void Quiver::addProperty(const QString & name, QObject * obj)
{
  _engine->rootContext()->setContextProperty(name, obj);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: rscflag.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-06-17 11:49:51 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _RSCFLAG_HXX
#define _RSCFLAG_HXX

#ifndef _RSCALL_H
#include <rscall.h>
#endif
#ifndef _RSCERROR_H
#include <rscerror.h>
#endif
#ifndef _RSCHASH_HXX
#include <rschash.hxx>
#endif
#ifndef _RSCCONST_HXX
#include <rscconst.hxx>
#endif

/******************* R s c F l a g ***************************************/
class RscFlag : public RscConst {
    struct RscFlagInst{
        USHORT  nFlags;
        USHORT  nDfltFlags;
    };
    BOOL            bUSHORT;
    RSCINST         CreateBasic( RSCINST * pInst );
public:
                    RscFlag( HASHID nId, USHORT nTypId, BOOL bUSHORT = TRUE );
    RSCINST         Create( RSCINST * pInst, const RSCINST & rDflt, BOOL );
    RSCINST         CreateClient( RSCINST * pInst, const RSCINST & rDflt,
                                  BOOL bOwnClass, HASHID nConsId );
    USHORT          Size();

    virtual void    SetToDefault( const RSCINST & rInst );
    BOOL            IsDefault( const RSCINST & rInst );
    BOOL            IsDefault( const RSCINST & rInst, HASHID nConstId );

                    // Ist das Flag gesetzt
    BOOL            IsSet( const RSCINST & rInst, HASHID nConstId );

                    // Als Default setzen
    BOOL            IsValueDefault( const RSCINST & rInst, CLASS_DATA pDef );
    BOOL            IsValueDefault( const RSCINST & rInst, CLASS_DATA pDef,
                                    HASHID nConstId );

    ERRTYPE         SetConst( const RSCINST & rInst, HASHID nValueId,
                              INT32 nValue );
    ERRTYPE         SetNotConst( const RSCINST & rInst, HASHID nConstId );
    void            WriteSrc( const RSCINST & rInst, FILE * fOutput,
                              RscTypCont * pTC, USHORT nTab, const char * );
    ERRTYPE         WriteRc( const RSCINST & rInst, RscWriteRc & aMem,
                             RscTypCont * pTC, USHORT, BOOL bExtra );
};

/******************* R s c C l i e n t ***********************************/
class RscClient : public RscTop
{
    RscFlag *   pRefClass;  //Klasse die als Server benutzt wird
    HASHID      nConstId;   //Id des zu setzenden Wertes
public:
                    RscClient( HASHID nId, USHORT nTypId, RscFlag * pClass,
                               HASHID nConstantId );
    virtual RSCCLASS_TYPE   GetClassType() const;
    RSCINST         Create( RSCINST * pInst, const RSCINST & rDflt, BOOL );
    USHORT          Size(){ return( pRefClass->Size() ); };

                    // Eine Zuweisung an eine Variable
    BOOL            IsDefault( const RSCINST & rInst ){
                        return( pRefClass->IsDefault( rInst, nConstId ) );
                    };
                    // Als Default setzen
    BOOL            IsValueDefault( const RSCINST & rInst, CLASS_DATA pDef ){
                        return pRefClass->IsValueDefault( rInst,
                                                    pDef, nConstId );
                    }
    ERRTYPE         SetBool( const RSCINST & rInst, BOOL bValue ){
                        if( bValue )
                            return( pRefClass->SetConst( rInst, nConstId, bValue ) );
                        else
                            return( pRefClass->
                                    SetNotConst( rInst, nConstId ) );
                    };
    ERRTYPE         GetBool( const RSCINST & rInst, BOOL * pB ){
                        *pB = pRefClass->IsSet( rInst, nConstId );
                        return( ERR_OK );
                    };
    void            WriteSrc( const RSCINST & rInst, FILE * fOutput,
                              RscTypCont * pTC, USHORT nTab, const char * );
};

#endif // _RSCFLAG_HXX
<commit_msg>INTEGRATION: CWS res32bit (1.3.18); FILE MERGED 2004/10/22 13:54:25 pl 1.3.18.1: #i34513# free rsc of 32 bit constraints<commit_after>/*************************************************************************
 *
 *  $RCSfile: rscflag.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2005-01-03 17:21:24 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _RSCFLAG_HXX
#define _RSCFLAG_HXX

#ifndef _RSCALL_H
#include <rscall.h>
#endif
#ifndef _RSCERROR_H
#include <rscerror.h>
#endif
#ifndef _RSCHASH_HXX
#include <rschash.hxx>
#endif
#ifndef _RSCCONST_HXX
#include <rscconst.hxx>
#endif

/******************* R s c F l a g ***************************************/
class RscFlag : public RscConst {
    struct RscFlagInst{
        sal_uInt32  nFlags;
        sal_uInt32  nDfltFlags;
    };
    RSCINST         CreateBasic( RSCINST * pInst );
public:
                    RscFlag( Atom nId, sal_uInt32 nTypId );
    RSCINST         Create( RSCINST * pInst, const RSCINST & rDflt, BOOL );
    RSCINST         CreateClient( RSCINST * pInst, const RSCINST & rDflt,
                                  BOOL bOwnClass, Atom nConsId );
    sal_uInt32          Size();

    virtual void    SetToDefault( const RSCINST & rInst );
    BOOL            IsDefault( const RSCINST & rInst );
    BOOL            IsDefault( const RSCINST & rInst, Atom nConstId );

                    // Ist das Flag gesetzt
    BOOL            IsSet( const RSCINST & rInst, Atom nConstId );

                    // Als Default setzen
    BOOL            IsValueDefault( const RSCINST & rInst, CLASS_DATA pDef );
    BOOL            IsValueDefault( const RSCINST & rInst, CLASS_DATA pDef,
                                    Atom nConstId );

    ERRTYPE         SetConst( const RSCINST & rInst, Atom nValueId,
                              INT32 nValue );
    ERRTYPE         SetNotConst( const RSCINST & rInst, Atom nConstId );
    void            WriteSrc( const RSCINST & rInst, FILE * fOutput,
                              RscTypCont * pTC, sal_uInt32 nTab, const char * );
    ERRTYPE         WriteRc( const RSCINST & rInst, RscWriteRc & aMem,
                             RscTypCont * pTC, sal_uInt32, BOOL bExtra );
};

/******************* R s c C l i e n t ***********************************/
class RscClient : public RscTop
{
    RscFlag *   pRefClass;  //Klasse die als Server benutzt wird
    Atom      nConstId;   //Id des zu setzenden Wertes
public:
                    RscClient( Atom nId, sal_uInt32 nTypId, RscFlag * pClass,
                               Atom nConstantId );
    virtual RSCCLASS_TYPE   GetClassType() const;
    RSCINST         Create( RSCINST * pInst, const RSCINST & rDflt, BOOL );
    sal_uInt32          Size(){ return( pRefClass->Size() ); };

                    // Eine Zuweisung an eine Variable
    BOOL            IsDefault( const RSCINST & rInst ){
                        return( pRefClass->IsDefault( rInst, nConstId ) );
                    };
                    // Als Default setzen
    BOOL            IsValueDefault( const RSCINST & rInst, CLASS_DATA pDef ){
                        return pRefClass->IsValueDefault( rInst,
                                                    pDef, nConstId );
                    }
    ERRTYPE         SetBool( const RSCINST & rInst, BOOL bValue ){
                        if( bValue )
                            return( pRefClass->SetConst( rInst, nConstId, bValue ) );
                        else
                            return( pRefClass->
                                    SetNotConst( rInst, nConstId ) );
                    };
    ERRTYPE         GetBool( const RSCINST & rInst, BOOL * pB ){
                        *pB = pRefClass->IsSet( rInst, nConstId );
                        return( ERR_OK );
                    };
    void            WriteSrc( const RSCINST & rInst, FILE * fOutput,
                              RscTypCont * pTC, sal_uInt32 nTab, const char * );
};

#endif // _RSCFLAG_HXX
<|endoftext|>


<commit_before>// Copyright (c) 2017 Mirants Lu. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "saber/util/mutex.h"

#include <errno.h>
#include <string.h>
#include <sys/time.h>

#include "saber/util/logging.h"
#include "saber/util/timeops.h"

namespace saber {

static void PthreadCall(const char* label, int result) {
  if (result != 0) {
    LOG_FATAL("%s: %s", label, strerror(result));
  }
}

Mutex::Mutex() {
  PthreadCall("pthread_mutex_init", pthread_mutex_init(&mutex_, nullptr));
}

Mutex::~Mutex() {
  PthreadCall("pthread_mutex_destory", pthread_mutex_destroy(&mutex_));
}

void Mutex::Lock() {
  PthreadCall("pthread_mutex_lock", pthread_mutex_lock(&mutex_));
}

void Mutex::UnLock() {
  PthreadCall("pthread_mutex_unlock", pthread_mutex_unlock(&mutex_));
}

Condition::Condition(Mutex* mutex) : mutex_(mutex) {
#ifdef __linux__
  pthread_condattr_t attr;
  pthread_condattr_init(&attr);
  PthreadCall("pthread_condattr_setclock",
              pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
  PthreadCall("pthread_cond_init", pthread_cond_init(&cond_, &attr));
#else
  PthreadCall("pthread_cond_init", pthread_cond_init(&cond_, nullptr));
#endif
}

Condition::~Condition() {
  PthreadCall("pthread_cond_destory", pthread_cond_destroy(&cond_));
}

void Condition::Wait() {
  PthreadCall("pthread_cond_wait", pthread_cond_wait(&cond_, &mutex_->mutex_));
}

bool Condition::Wait(uint64_t micros) {
struct timespec outtime;
#ifdef __linux__
  clock_gettime(CLOCK_MONOTONIC, &outtime);
  outtime.tv_sec += micros / 1000000;
  outtime.tv_nsec += (micros % 1000000) * 1000;
  outtime.tv_sec += outtime.tv_nsec / 1000000000;
  outtime.tv_nsec = outtime.tv_nsec % 1000000000;
#else
  uint64_t now = (NowMicros() + micros) * 1000;
  outtime.tv_sec = now / 1000000000;
  outtime.tv_nsec = now % 1000000000;
#endif
  int res = pthread_cond_timedwait(&cond_, &mutex_->mutex_, &outtime);
  if (res != 0 && res != ETIMEDOUT) {
    PthreadCall("pthread_cond_timedwait", res);
  }
  return res == 0;
}

void Condition::Signal() {
  PthreadCall("pthread_cond_signal", pthread_cond_signal(&cond_));
}

void Condition::SignalAll() {
  PthreadCall("pthread_cond_broadcast", pthread_cond_broadcast(&cond_));
}

void InitOnce(OnceType* once, void (*initializer)()) {
  PthreadCall("pthread_once", pthread_once(once, initializer));
}

}  // namespace saber
<commit_msg>update mutex<commit_after>// Copyright (c) 2017 Mirants Lu. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "saber/util/mutex.h"

#include <errno.h>
#include <string.h>
#include <sys/time.h>

#include "saber/util/logging.h"
#include "saber/util/timeops.h"

namespace saber {

static void PthreadCall(const char* label, int result) {
  if (result != 0) {
    LOG_FATAL("%s: %s", label, strerror(result));
  }
}

Mutex::Mutex() {
  PthreadCall("pthread_mutex_init", pthread_mutex_init(&mutex_, nullptr));
}

Mutex::~Mutex() {
  PthreadCall("pthread_mutex_destory", pthread_mutex_destroy(&mutex_));
}

void Mutex::Lock() {
  PthreadCall("pthread_mutex_lock", pthread_mutex_lock(&mutex_));
}

void Mutex::UnLock() {
  PthreadCall("pthread_mutex_unlock", pthread_mutex_unlock(&mutex_));
}

Condition::Condition(Mutex* mutex) : mutex_(mutex) {
#ifdef __linux__
  pthread_condattr_t attr;
  PthreadCall("pthread_condattr_init", pthread_condattr_init(&attr));
  PthreadCall("pthread_condattr_setclock",
              pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
  PthreadCall("pthread_cond_init", pthread_cond_init(&cond_, &attr));
#else
  PthreadCall("pthread_cond_init", pthread_cond_init(&cond_, nullptr));
#endif
}

Condition::~Condition() {
  PthreadCall("pthread_cond_destory", pthread_cond_destroy(&cond_));
}

void Condition::Wait() {
  PthreadCall("pthread_cond_wait", pthread_cond_wait(&cond_, &mutex_->mutex_));
}

bool Condition::Wait(uint64_t micros) {
  struct timespec outtime;
#ifdef __linux__
  clock_gettime(CLOCK_MONOTONIC, &outtime);
  outtime.tv_sec += micros / 1000000;
  outtime.tv_nsec += (micros % 1000000) * 1000;
  outtime.tv_sec += outtime.tv_nsec / 1000000000;
  outtime.tv_nsec = outtime.tv_nsec % 1000000000;
#else
  uint64_t now = (NowMicros() + micros) * 1000;
  outtime.tv_sec = now / 1000000000;
  outtime.tv_nsec = now % 1000000000;
#endif
  int res = pthread_cond_timedwait(&cond_, &mutex_->mutex_, &outtime);
  if (res != 0 && res != ETIMEDOUT) {
    PthreadCall("pthread_cond_timedwait", res);
  }
  return res == 0;
}

void Condition::Signal() {
  PthreadCall("pthread_cond_signal", pthread_cond_signal(&cond_));
}

void Condition::SignalAll() {
  PthreadCall("pthread_cond_broadcast", pthread_cond_broadcast(&cond_));
}

void InitOnce(OnceType* once, void (*initializer)()) {
  PthreadCall("pthread_once", pthread_once(once, initializer));
}

}  // namespace saber
<|endoftext|>


<commit_before>/*	____________________________________________________________________________

	                 Scanner Component for the Micro A Compiler

	                                mscan.h

	                              Version 2007 - 2016

	                           James L. Richards
	                     Last Update: August 28, 2007
	                      	   Nelson A Castillo
	                     Last Update: January 31, 2016

	The routines in this unit are based on those provided in the book
	"Crafting A Compiler" by Charles N. Fischer and Richard J. LeBlanc, Jr.,
	Benjamin Cummings Publishing Co. (1991).

	See Section 2.2, pp. 25-29.
	____________________________________________________________________________
*/

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;

extern ifstream sourceFile;
extern ofstream outFile, listFile;

#include "mscan.h"

// *******************
// **  Constructor  **
// *******************

Scanner::Scanner()
{
	tokenBuffer = "";
	lineBuffer = "";
	lineNumber = 0;
}

// ********************************
// **  Private Member Functions  **
// ********************************

void Scanner::BufferChar(char c)
{
	if (tokenBuffer.length() < ID_STRING_LEN){
		tokenBuffer += c;
	}
	//cerr << tokenBuffer << endl;
}
void Scanner::BufferString(char c)
{
	stringBuffer += c;
	//cerr << tokenBuffer << endl;
}

Token Scanner::CheckReserved()
{
	/* Convert the string to lower case */
	transform(tokenBuffer.begin(), tokenBuffer.end(), \
				tokenBuffer.begin(), ::tolower);
	/* Check the converted words */
	if ((tokenBuffer) == "bool") return BOOL_SYM;
	if ((tokenBuffer) == "break") return BREAK_SYM;
	if ((tokenBuffer) == "case") return CASE_SYM;
	if ((tokenBuffer) == "cheese") return CHEESE_SYM;
	if ((tokenBuffer) == "decs") return DECS_SYM;
	if ((tokenBuffer) == "do") return DO_SYM;
	if ((tokenBuffer) == "else") return ELSE_SYM;
	if ((tokenBuffer) == "end") return END_SYM;
	if ((tokenBuffer) == "false") return FALSE_SYM;
	if ((tokenBuffer) == "float") return FLOAT_SYM;
	if ((tokenBuffer) == "for") return FOR_SYM;
	if ((tokenBuffer) == "hiphip") return HIPHIP_SYM;
	if ((tokenBuffer) == "if") return IF_SYM;
	if ((tokenBuffer) == "int") return INT_SYM;
	if ((tokenBuffer) == "listen") return LISTEN_SYM;
	if ((tokenBuffer) == "otherwise") return OTHERWISE_SYM;
	if ((tokenBuffer) == "select") return SELECT_SYM;
	if ((tokenBuffer) == "shout") return SHOUT_SYM;
	if ((tokenBuffer) == "then") return THEN_SYM;
	if ((tokenBuffer) == "true") return TRUE_SYM;
	if ((tokenBuffer) == "while") return WHILE_SYM;

	return ID;
}

void Scanner::ClearBuffer()
{
	tokenBuffer = "";
	stringBuffer = "";
}

void Scanner::LexicalError(char& c)
{
	cout << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber + 1 << '.' << endl;
	listFile << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber + 1 << '.' << endl;

	c = NextChar();
}
void Scanner::LexicalError(char& c, const string& errorExp)
{
	cout << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber + 1 << '.' << '\n'
		<< errorExp << endl;
	listFile << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber + 1 << '.' << '\n'
		<< errorExp << endl;

	c = NextChar();
}

char Scanner::NextChar()
{
	char c;

	sourceFile.get(c);
	if (c == '\n')
	{
		listFile.width(6);
		listFile << ++lineNumber << "  " << lineBuffer << endl;
		lineBuffer = "";
	} else{
		lineBuffer += c;
	}
	return c;
}

// *******************************
// **  Public Member Functions  **
// *******************************

Token Scanner::GetNextToken()
{
	char currentChar, c;

	ClearBuffer();
	currentChar = NextChar();
	while (!sourceFile.eof())
	{
		if (isspace(currentChar)) {
			/* do nothing */
			currentChar = NextChar();
		} else if (isalpha(currentChar)) {
			/* identifier */
			BufferChar(currentChar);
			c = sourceFile.peek();
			while (isalnum(c) || c == '_') {
				currentChar = NextChar();
				BufferChar(currentChar);
				c = sourceFile.peek();
			}
			return CheckReserved();
		} else if (isdigit(currentChar)) {
			/* integer or float literals */
			BufferChar(currentChar);
			c = sourceFile.peek();
			while (isdigit(c)) {
				currentChar = NextChar();
				BufferChar(currentChar);
				c = sourceFile.peek();
			}
			/* check if it is a float */
			if (c == '.') {
				currentChar = NextChar();
				c = sourceFile.peek();
				/* check for a digit after the '.' */
				if (!isdigit(c))
					LexicalError(currentChar, to_string(c)+" Boolean needs a digit after the '.'");
				BufferChar(currentChar);
				while (isdigit(c)) {
					currentChar = NextChar();
					BufferChar(currentChar);
					c = sourceFile.peek();
				}
				/* check for power of 10 multipliers */
				if (c == 'e' || c == 'E') {
					currentChar = NextChar();
					c = sourceFile.peek();
					if (c != '+' && c!= '-') {
						LexicalError(currentChar, to_string(c)+" Boolean needs a '+' or a '-' after 'E' ");
					}
					BufferChar(currentChar);
					currentChar = NextChar();
					c = sourceFile.peek();
					if (!isdigit(c))
						LexicalError(currentChar, to_string(c)+"Boolean needs a  digit after '+' or '-'");
					BufferChar(currentChar);
					while (isdigit(c)) {
						currentChar = NextChar();
						BufferChar(currentChar);
						c = sourceFile.peek();
					}
				}
				return FLOAT_LIT;
			}
			return INT_LIT;
		} else if (currentChar == '"') {
			// string literal
			// BufferString(currentChar);
			do {
				currentChar = NextChar();
				// cout << currentChar <<endl;
				if (currentChar == '"' \
						& sourceFile.peek() != '"') {
					// BufferString(currentChar);
					// cout << "________________________" <<endl;
					// cout << stringBuffer <<endl;
					// cout << "________________________" <<endl;
					return CHEESE_LIT;
				} else if (currentChar == '"' \
						& sourceFile.peek() == '"') {
					currentChar = NextChar();
				}
				BufferString(currentChar);
			} while (sourceFile.peek()!='\n');
			return CHEESE_LIT;
		} else if (currentChar == '(') {
			BufferChar(currentChar);
			return LBANANA;
		} else if (currentChar == ')') {
			BufferChar(currentChar);
			return RBANANA;
		} else if (currentChar == '[') {
			BufferChar(currentChar);
			return LSTAPLE;
		} else if (currentChar == ']') {
			BufferChar(currentChar);
			return RSTAPLE;
		} else if (currentChar == '{') {
			BufferChar(currentChar);
			return LMUSTACHE;
		} else if (currentChar == '}') {
			BufferChar(currentChar);
			return RMUSTACHE;
		} else if (currentChar == ';') {
			BufferChar(currentChar);
			return SEMICOLON;
		} else if (currentChar == ':') {
			BufferChar(currentChar);
			return COLON;
		} else if (currentChar == ',') {
			BufferChar(currentChar);
			return COMMA;
		} else if (currentChar == '+') {
			BufferChar(currentChar);
			return PLUS_OP;
		} else if (currentChar == '*') {
			BufferChar(currentChar);
			return MULT_OP;
		} else if (currentChar == '/') {
			/* check if it is a multiline comment */
			if (sourceFile.peek() == ':') {
				do { /* skip comment */
					currentChar = NextChar();
					if (currentChar == ':') {
						currentChar = NextChar();
						if (currentChar == '/') {
							break;
						}
					}
				} while (!sourceFile.eof());
			} else {
				/* if it is a division operator */
				BufferChar(currentChar);
				return DIV_OP;
			}
		} else if (currentChar == '=') {
			if (sourceFile.peek() == '=') {
				currentChar = NextChar();
				return EQ_OP1;
			}
			currentChar = NextChar();
			return ASSIGN_OP;
		} else if (currentChar == '!') {
			if (sourceFile.peek() == '!') {
				currentChar = NextChar();
				return EQ_OP2;
			} else if (sourceFile.peek() == '=') {
				currentChar = NextChar();
				return NE_OP;
			} else {
				LexicalError(currentChar, to_string(c) + \
						" not operator is not" \
						" supported by MnC");
			}
		} else if (currentChar == '<') {
			if (sourceFile.peek() == '=') {
				currentChar = NextChar();
				return LE_OP;
			}
			currentChar = NextChar();
			return LT_OP;
		} else if (currentChar == '>') {
			if (sourceFile.peek() == '=') {
				currentChar = NextChar();
				return GE_OP;
			}
			currentChar = NextChar();
			return GT_OP;
		} else if (currentChar == '-') {
			/* check if it is a comment or a minus symbol */
			if (sourceFile.peek() == '-') { /* comment */
				do { /* skip comment */
					currentChar = NextChar();
				} while (currentChar != '\n');
			} else { /* minus operator */
				BufferChar(currentChar);
				return MINUS_OP;
			}
		} else {
			/* Unrecognized character */
			LexicalError(currentChar, to_string(c)+" Unrecognized character");
		}
	} /* end while */

	return EOF_SYM;
}
<commit_msg>scan: consume the last '/' of multiline comments.<commit_after>/*	____________________________________________________________________________

	                 Scanner Component for the Micro A Compiler

	                                mscan.h

	                              Version 2007 - 2016

	                           James L. Richards
	                     Last Update: August 28, 2007
	                      	   Nelson A Castillo
	                     Last Update: January 31, 2016

	The routines in this unit are based on those provided in the book
	"Crafting A Compiler" by Charles N. Fischer and Richard J. LeBlanc, Jr.,
	Benjamin Cummings Publishing Co. (1991).

	See Section 2.2, pp. 25-29.
	____________________________________________________________________________
*/

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;

extern ifstream sourceFile;
extern ofstream outFile, listFile;

#include "mscan.h"

// *******************
// **  Constructor  **
// *******************

Scanner::Scanner()
{
	tokenBuffer = "";
	lineBuffer = "";
	lineNumber = 0;
}

// ********************************
// **  Private Member Functions  **
// ********************************

void Scanner::BufferChar(char c)
{
	if (tokenBuffer.length() < ID_STRING_LEN){
		tokenBuffer += c;
	}
	//cerr << tokenBuffer << endl;
}
void Scanner::BufferString(char c)
{
	stringBuffer += c;
	//cerr << tokenBuffer << endl;
}

Token Scanner::CheckReserved()
{
	/* Convert the string to lower case */
	transform(tokenBuffer.begin(), tokenBuffer.end(), \
				tokenBuffer.begin(), ::tolower);
	/* Check the converted words */
	if ((tokenBuffer) == "bool") return BOOL_SYM;
	if ((tokenBuffer) == "break") return BREAK_SYM;
	if ((tokenBuffer) == "case") return CASE_SYM;
	if ((tokenBuffer) == "cheese") return CHEESE_SYM;
	if ((tokenBuffer) == "decs") return DECS_SYM;
	if ((tokenBuffer) == "do") return DO_SYM;
	if ((tokenBuffer) == "else") return ELSE_SYM;
	if ((tokenBuffer) == "end") return END_SYM;
	if ((tokenBuffer) == "false") return FALSE_SYM;
	if ((tokenBuffer) == "float") return FLOAT_SYM;
	if ((tokenBuffer) == "for") return FOR_SYM;
	if ((tokenBuffer) == "hiphip") return HIPHIP_SYM;
	if ((tokenBuffer) == "if") return IF_SYM;
	if ((tokenBuffer) == "int") return INT_SYM;
	if ((tokenBuffer) == "listen") return LISTEN_SYM;
	if ((tokenBuffer) == "otherwise") return OTHERWISE_SYM;
	if ((tokenBuffer) == "select") return SELECT_SYM;
	if ((tokenBuffer) == "shout") return SHOUT_SYM;
	if ((tokenBuffer) == "then") return THEN_SYM;
	if ((tokenBuffer) == "true") return TRUE_SYM;
	if ((tokenBuffer) == "while") return WHILE_SYM;

	return ID;
}

void Scanner::ClearBuffer()
{
	tokenBuffer = "";
	stringBuffer = "";
}

void Scanner::LexicalError(char& c)
{
	cout << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber + 1 << '.' << endl;
	listFile << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber + 1 << '.' << endl;

	c = NextChar();
}
void Scanner::LexicalError(char& c, const string& errorExp)
{
	cout << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber + 1 << '.' << '\n'
		<< errorExp << endl;
	listFile << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber + 1 << '.' << '\n'
		<< errorExp << endl;

	c = NextChar();
}

char Scanner::NextChar()
{
	char c;

	sourceFile.get(c);
	if (c == '\n')
	{
		listFile.width(6);
		listFile << ++lineNumber << "  " << lineBuffer << endl;
		lineBuffer = "";
	} else{
		lineBuffer += c;
	}
	return c;
}

// *******************************
// **  Public Member Functions  **
// *******************************

Token Scanner::GetNextToken()
{
	char currentChar, c;

	ClearBuffer();
	currentChar = NextChar();
	while (!sourceFile.eof())
	{
		if (isspace(currentChar)) {
			/* do nothing */
			currentChar = NextChar();
		} else if (isalpha(currentChar)) {
			/* identifier */
			BufferChar(currentChar);
			c = sourceFile.peek();
			while (isalnum(c) || c == '_') {
				currentChar = NextChar();
				BufferChar(currentChar);
				c = sourceFile.peek();
			}
			return CheckReserved();
		} else if (isdigit(currentChar)) {
			/* integer or float literals */
			BufferChar(currentChar);
			c = sourceFile.peek();
			while (isdigit(c)) {
				currentChar = NextChar();
				BufferChar(currentChar);
				c = sourceFile.peek();
			}
			/* check if it is a float */
			if (c == '.') {
				currentChar = NextChar();
				c = sourceFile.peek();
				/* check for a digit after the '.' */
				if (!isdigit(c))
					LexicalError(currentChar, to_string(c)+" Boolean needs a digit after the '.'");
				BufferChar(currentChar);
				while (isdigit(c)) {
					currentChar = NextChar();
					BufferChar(currentChar);
					c = sourceFile.peek();
				}
				/* check for power of 10 multipliers */
				if (c == 'e' || c == 'E') {
					currentChar = NextChar();
					c = sourceFile.peek();
					if (c != '+' && c!= '-') {
						LexicalError(currentChar, to_string(c)+" Boolean needs a '+' or a '-' after 'E' ");
					}
					BufferChar(currentChar);
					currentChar = NextChar();
					c = sourceFile.peek();
					if (!isdigit(c))
						LexicalError(currentChar, to_string(c)+"Boolean needs a  digit after '+' or '-'");
					BufferChar(currentChar);
					while (isdigit(c)) {
						currentChar = NextChar();
						BufferChar(currentChar);
						c = sourceFile.peek();
					}
				}
				return FLOAT_LIT;
			}
			return INT_LIT;
		} else if (currentChar == '"') {
			// string literal
			// BufferString(currentChar);
			do {
				currentChar = NextChar();
				// cout << currentChar <<endl;
				if (currentChar == '"' \
						& sourceFile.peek() != '"') {
					// BufferString(currentChar);
					// cout << "________________________" <<endl;
					// cout << stringBuffer <<endl;
					// cout << "________________________" <<endl;
					return CHEESE_LIT;
				} else if (currentChar == '"' \
						& sourceFile.peek() == '"') {
					currentChar = NextChar();
				}
				BufferString(currentChar);
			} while (sourceFile.peek()!='\n');
			return CHEESE_LIT;
		} else if (currentChar == '(') {
			BufferChar(currentChar);
			return LBANANA;
		} else if (currentChar == ')') {
			BufferChar(currentChar);
			return RBANANA;
		} else if (currentChar == '[') {
			BufferChar(currentChar);
			return LSTAPLE;
		} else if (currentChar == ']') {
			BufferChar(currentChar);
			return RSTAPLE;
		} else if (currentChar == '{') {
			BufferChar(currentChar);
			return LMUSTACHE;
		} else if (currentChar == '}') {
			BufferChar(currentChar);
			return RMUSTACHE;
		} else if (currentChar == ';') {
			BufferChar(currentChar);
			return SEMICOLON;
		} else if (currentChar == ':') {
			BufferChar(currentChar);
			return COLON;
		} else if (currentChar == ',') {
			BufferChar(currentChar);
			return COMMA;
		} else if (currentChar == '+') {
			BufferChar(currentChar);
			return PLUS_OP;
		} else if (currentChar == '*') {
			BufferChar(currentChar);
			return MULT_OP;
		} else if (currentChar == '/') {
			/* check if it is a multiline comment */
			if (sourceFile.peek() == ':') {
				do { /* skip comment */
					currentChar = NextChar();
					if (currentChar == ':') {
						currentChar = NextChar();
						if (currentChar == '/') {
							currentChar = NextChar();
							break;
						}
					}
				} while (!sourceFile.eof());
			} else {
				/* if it is a division operator */
				BufferChar(currentChar);
				return DIV_OP;
			}
		} else if (currentChar == '=') {
			if (sourceFile.peek() == '=') {
				currentChar = NextChar();
				return EQ_OP1;
			}
			currentChar = NextChar();
			return ASSIGN_OP;
		} else if (currentChar == '!') {
			if (sourceFile.peek() == '!') {
				currentChar = NextChar();
				return EQ_OP2;
			} else if (sourceFile.peek() == '=') {
				currentChar = NextChar();
				return NE_OP;
			} else {
				LexicalError(currentChar, to_string(c) + \
						" not operator is not" \
						" supported by MnC");
			}
		} else if (currentChar == '<') {
			if (sourceFile.peek() == '=') {
				currentChar = NextChar();
				return LE_OP;
			}
			currentChar = NextChar();
			return LT_OP;
		} else if (currentChar == '>') {
			if (sourceFile.peek() == '=') {
				currentChar = NextChar();
				return GE_OP;
			}
			currentChar = NextChar();
			return GT_OP;
		} else if (currentChar == '-') {
			/* check if it is a comment or a minus symbol */
			if (sourceFile.peek() == '-') { /* comment */
				do { /* skip comment */
					currentChar = NextChar();
				} while (currentChar != '\n');
			} else { /* minus operator */
				BufferChar(currentChar);
				return MINUS_OP;
			}
		} else {
			/* Unrecognized character */
			LexicalError(currentChar, to_string(c)+" Unrecognized character");
		}
	} /* end while */

	return EOF_SYM;
}
<|endoftext|>


<commit_before>#pragma once

/*  Order Independent Transparency (OIT)
        Original algorithm by Morgan McGuire
        AlloSystem version written by Keehong Youn
        younkeehong@gmail.com

        - Uses OpenGL compatibility profile
        - Provides transparency without sorting of the objects
        - By default uses flat non-lighting shader
            Override "vertCode" & "fragCode" to use custom shader

    use:
        OITFbo oit;
        oit.init(w, h);

        oit.beginOpaque();
        // render opaque things
        oit.endOpaque();

        oit.beginAccum();
        // render transparent things
        oit.endAccum();

        oit.beginReveal();
        // render transparent things
        oit.endReveal();

        oit.composite();

        // now use "oit.result()" to get texture with rendered result

    Reference:
        - http://casual-effects.blogspot.com/2015/03/implemented-weighted-blended-order.html
        - http://casual-effects.blogspot.com/2015/03/colored-blended-order-independent.html
*/

#include "allocore/graphics/al_OpenGL.hpp"
#include "allocore/graphics/al_Graphics.hpp"
#include "allocore/graphics/al_FBO.hpp"
#include "allocore/graphics/al_Shader.hpp"
#include "allocore/graphics/al_Texture.hpp"

#include <string>

namespace al {

class OITFbo {
public:
// private:
    // three render target: opaque, accum, and reveal
    // four shader pass: opaque, accum, reveal, and composite
    static const int opaque = 0;
    static const int accum = 1;
    static const int reveal = 2;
    static const int comp = 3;

    int w, h;

    FBO fbo; // one FBO with
    Texture tex[3]; // three color attachment textures and
    Texture tex_depth; // one common depth texture

    ShaderProgram shader[4];
    Graphics g;

public:
    OITFbo() {};
    ~OITFbo() {};

    void init(int _w, int _h) {
        w = _w;
        h = _h;

        tex_depth = Texture(w, h, Graphics::DEPTH_COMPONENT, Graphics::FLOAT);
        tex_depth.submit(); // this actually makes texture registered at gpu
        fbo.attachTexture2D(tex_depth.id(), FBO::DEPTH_ATTACHMENT);

        for (int i = 0; i < 3; i++) {
          tex[i] = Texture(w, h, Graphics::RGBA, Graphics::FLOAT);
          tex[i].submit();
        }

        // would be nice if could FBO::COLOR_ATTACHMENT0 + i, but can't
        fbo.attachTexture2D(tex[opaque].id(), FBO::COLOR_ATTACHMENT0);
        fbo.attachTexture2D(tex[accum].id(), FBO::COLOR_ATTACHMENT1);
        fbo.attachTexture2D(tex[reveal].id(), FBO::COLOR_ATTACHMENT2);

        shader[opaque].compile(vertRenderCode().c_str(), fragOpaqueCode().c_str());
        shader[accum].compile(vertRenderCode().c_str(), fragAccumCode().c_str());
        shader[reveal].compile(vertRenderCode().c_str(), fragRevealCode().c_str());
        shader[comp].compile(vertCompositeCode().c_str(), fragCompsiteCode().c_str());

        ShaderProgram& c = shader[comp];
        c.begin();
        c.uniform("tex_accum", 0);
        c.uniform("tex_reveal", 1);
        c.end();
    }

    void beginOpaque() {
        glEnable(GL_DEPTH_TEST);
        glDepthMask(GL_TRUE);
        glDisable(GL_BLEND);
        bindFBO();
        renderToOpaque();
        clearDepth();
        shader[opaque].begin();
    }
    void endOpaque() {
        shader[opaque].end();
        unbindFBO();
    }

    void beginAccum() {
        glDepthMask(GL_FALSE); // depth test enabled but not masking
        glEnable(GL_BLEND);
        glBlendEquation(GL_FUNC_ADD);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // src, dst
        bindFBO();
        renderToAccum();
        clearColor(); // but don't clear depth from opaque rendering
        shader[accum].begin();
    }
    void endAccum() {
        shader[accum].end();
        unbindFBO();
    }

    void beginReveal() {
        glDepthMask(GL_FALSE);
        glEnable(GL_BLEND);
        glBlendEquation(GL_FUNC_ADD);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        bindFBO();
        renderToReveal();
        clearColor();
        shader[reveal].begin();
    }
    void endReveal() {
        shader[reveal].end();
        unbindFBO();
    }

    void composite() {
        glDisable(GL_DEPTH_TEST);
        glDepthMask(GL_FALSE);
        glEnable(GL_BLEND);
        glBlendEquation(GL_FUNC_ADD);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        bindFBO();
        renderToOpaque();
        shader[comp].begin();
        tex[accum].bind(0);
        tex[reveal].bind(1);
        quadViewport(); // push pixels for entire screen
        tex[accum].unbind(0); // it is important to unbind
        tex[reveal].unbind(1);
        shader[comp].end();
        unbindFBO();
    }

    Texture& result() {
        return tex[opaque];
    }

    virtual std::string vertRenderCode();
    virtual std::string fragOpaqueCode();
    virtual std::string fragAccumCode();
    virtual std::string fragRevealCode();

    virtual std::string vertCompositeCode();
    virtual std::string fragCompsiteCode();

private:
    void bindFBO() { fbo.begin(); }
    void unbindFBO() { fbo.end(); }
    void renderToOpaque() { glDrawBuffer(GL_COLOR_ATTACHMENT0); }
    void renderToAccum() { glDrawBuffer(GL_COLOR_ATTACHMENT1); }
    void renderToReveal() { glDrawBuffer(GL_COLOR_ATTACHMENT2); }

    void quadViewport();
    void clearColor(float r=0, float g=0, float b=0, float a=0);
    void clearDepth(float d=1);
};

inline std::string OITFbo::vertRenderCode() {
    return R"(
varying vec4 color;
void main(){
    color = gl_Color;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
)";
}

inline std::string OITFbo::fragOpaqueCode() {
    return R"(
varying vec4 color;
void main(){
    gl_FragColor = color;
}
)";
}

inline std::string OITFbo::fragAccumCode() {
    return R"(
varying vec4 color;
void main() {
    vec4 premult = vec4(color.rgb * color.a, color.a);
    vec3 transmit = color.rgb * (1.0 - color.a);
    premult.a *= 1.0 - clamp((transmit.r + transmit.g + transmit.b) / 3.0, 0.0, 1.0);
    float tmp = (min(premult.a, 1.0) * 8.0 + 0.01) * (1.0 - gl_FragCoord.z * 0.95);
    float w = clamp(tmp * tmp * tmp * 1e3, 1e-2, 3e2);
    gl_FragColor = premult * w / 100.0; // divide by 100 so we write a val less than 1.0
}
)";
}

inline std::string OITFbo::fragRevealCode() {
    return R"(
varying vec4 color;
void main() {
    vec4 premult = vec4(color.rgb * color.a, color.a);
    vec3 transmit = color.rgb * (1.0 - color.a);
    premult.a *= 1.0 - clamp((transmit.r + transmit.g + transmit.b) / 3.0, 0.0, 1.0);
    // all ouput we want is one value but we gotta write to 4 channels
    gl_FragColor = vec4(premult.a);
}
)";
}

inline std::string OITFbo::vertCompositeCode() {
    return R"(
void main(){
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
)";
}

inline std::string OITFbo::fragCompsiteCode() {
    return R"(
uniform sampler2D tex_accum;
uniform sampler2D tex_reveal;
void main(){
    vec4 accum = texture2D(tex_accum, gl_TexCoord[0].st) * 100.0;
    float revealage = texture2D(tex_reveal, gl_TexCoord[0].st).a;
    gl_FragColor = vec4(accum.rgb / max(accum.a, 0.00001), revealage);
}
)";
}

inline void OITFbo::quadViewport() {
    g.pushMatrix(g.PROJECTION);
    g.loadIdentity();
    g.pushMatrix(g.MODELVIEW);
    g.loadIdentity();
    g.depthMask(0); // write only to color buffer
    al::Mesh& m = g.mesh();
    m.reset();
    m.primitive(g.TRIANGLE_STRIP);
    m.vertex(-1, -1, 0);
    m.texCoord(0, 0);
    m.vertex(1, -1, 0);
    m.texCoord(1, 0);
    m.vertex(-1, 1, 0);
    m.texCoord(0, 1);
    m.vertex(1, 1, 0);
    m.texCoord(1, 1);
    g.draw(m);
    g.depthMask(1);
    g.popMatrix(g.PROJECTION);
    g.popMatrix(g.MODELVIEW);
}

inline void OITFbo::clearColor(float r, float g, float b, float a) {
    glClearColor(r, g, b, a);
    glClear(GL_COLOR_BUFFER_BIT);
}

inline void OITFbo::clearDepth(float d) {
    glClearDepth(d);
    glClear(GL_DEPTH_BUFFER_BIT);
}

}<commit_msg>OITFbo: add getters for shaders<commit_after>#pragma once

/*  Order Independent Transparency (OIT)
        Original algorithm by Morgan McGuire
        AlloSystem version written by Keehong Youn
        younkeehong@gmail.com

        - Uses OpenGL compatibility profile
        - Provides transparency without sorting of the objects
        - By default uses flat non-lighting shader
            Override "vertCode" & "fragCode" to use custom shader

    use:
        OITFbo oit;
        oit.init(w, h);

        oit.beginOpaque();
        // render opaque things
        oit.endOpaque();

        oit.beginAccum();
        // render transparent things
        oit.endAccum();

        oit.beginReveal();
        // render transparent things
        oit.endReveal();

        oit.composite();

        // now use "oit.result()" to get texture with rendered result

    Reference:
        - http://casual-effects.blogspot.com/2015/03/implemented-weighted-blended-order.html
        - http://casual-effects.blogspot.com/2015/03/colored-blended-order-independent.html
*/

#include "allocore/graphics/al_OpenGL.hpp"
#include "allocore/graphics/al_Graphics.hpp"
#include "allocore/graphics/al_FBO.hpp"
#include "allocore/graphics/al_Shader.hpp"
#include "allocore/graphics/al_Texture.hpp"

#include <string>

namespace al {

class OITFbo {
public:
// private:
    // three render target: opaque, accum, and reveal
    // four shader pass: opaque, accum, reveal, and composite
    static const int opaque = 0;
    static const int accum = 1;
    static const int reveal = 2;
    static const int comp = 3;

    int w, h;

    FBO fbo; // one FBO with
    Texture tex[3]; // three color attachment textures and
    Texture tex_depth; // one common depth texture

    ShaderProgram shader[4];
    Graphics g;

public:
    OITFbo() {};
    ~OITFbo() {};

    void init(int _w, int _h) {
        w = _w;
        h = _h;

        tex_depth = Texture(w, h, Graphics::DEPTH_COMPONENT, Graphics::FLOAT);
        tex_depth.submit(); // this actually makes texture registered at gpu
        fbo.attachTexture2D(tex_depth.id(), FBO::DEPTH_ATTACHMENT);

        for (int i = 0; i < 3; i++) {
          tex[i] = Texture(w, h, Graphics::RGBA, Graphics::FLOAT);
          tex[i].submit();
        }

        // would be nice if could FBO::COLOR_ATTACHMENT0 + i, but can't
        fbo.attachTexture2D(tex[opaque].id(), FBO::COLOR_ATTACHMENT0);
        fbo.attachTexture2D(tex[accum].id(), FBO::COLOR_ATTACHMENT1);
        fbo.attachTexture2D(tex[reveal].id(), FBO::COLOR_ATTACHMENT2);

        shader[opaque].compile(vertRenderCode().c_str(), fragOpaqueCode().c_str());
        shader[accum].compile(vertRenderCode().c_str(), fragAccumCode().c_str());
        shader[reveal].compile(vertRenderCode().c_str(), fragRevealCode().c_str());
        shader[comp].compile(vertCompositeCode().c_str(), fragCompsiteCode().c_str());

        ShaderProgram& c = shader[comp];
        c.begin();
        c.uniform("tex_accum", 0);
        c.uniform("tex_reveal", 1);
        c.end();
    }

    void beginOpaque() {
        glEnable(GL_DEPTH_TEST);
        glDepthMask(GL_TRUE);
        glDisable(GL_BLEND);
        bindFBO();
        renderToOpaque();
        clearDepth();
        shader[opaque].begin();
    }

    void endOpaque() {
        shader[opaque].end();
        unbindFBO();
    }

    void beginAccum() {
        glDepthMask(GL_FALSE); // depth test enabled but not masking
        glEnable(GL_BLEND);
        glBlendEquation(GL_FUNC_ADD);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // src, dst
        bindFBO();
        renderToAccum();
        clearColor(); // but don't clear depth from opaque rendering
        shader[accum].begin();
    }

    void endAccum() {
        shader[accum].end();
        unbindFBO();
    }

    void beginReveal() {
        glDepthMask(GL_FALSE);
        glEnable(GL_BLEND);
        glBlendEquation(GL_FUNC_ADD);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        bindFBO();
        renderToReveal();
        clearColor();
        shader[reveal].begin();
    }

    void endReveal() {
        shader[reveal].end();
        unbindFBO();
    }

    void composite() {
        glDisable(GL_DEPTH_TEST);
        glDepthMask(GL_FALSE);
        glEnable(GL_BLEND);
        glBlendEquation(GL_FUNC_ADD);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        bindFBO();
        renderToOpaque();
        shader[comp].begin();
        tex[accum].bind(0);
        tex[reveal].bind(1);
        quadViewport(); // push pixels for entire screen
        tex[accum].unbind(0); // it is important to unbind
        tex[reveal].unbind(1);
        shader[comp].end();
        unbindFBO();
    }

    ShaderProgram& opaqueShader() {
        return shader[opaque];
    }

    ShaderProgram& accumShader() {
        return shader[accum];
    }

    ShaderProgram& revealShader() {
        return shader[reveal];
    }

    ShaderProgram& compShader() {
        return shader[comp];
    }

    Texture& result() {
        return tex[opaque];
    }

    virtual std::string vertRenderCode();
    virtual std::string fragOpaqueCode();
    virtual std::string fragAccumCode();
    virtual std::string fragRevealCode();

    virtual std::string vertCompositeCode();
    virtual std::string fragCompsiteCode();

private:
    void bindFBO() { fbo.begin(); }
    void unbindFBO() { fbo.end(); }
    void renderToOpaque() { glDrawBuffer(GL_COLOR_ATTACHMENT0); }
    void renderToAccum() { glDrawBuffer(GL_COLOR_ATTACHMENT1); }
    void renderToReveal() { glDrawBuffer(GL_COLOR_ATTACHMENT2); }

    void quadViewport();
    void clearColor(float r=0, float g=0, float b=0, float a=0);
    void clearDepth(float d=1);
};

inline std::string OITFbo::vertRenderCode() {
    return R"(
varying vec4 color;
void main(){
    color = gl_Color;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
)";
}

inline std::string OITFbo::fragOpaqueCode() {
    return R"(
varying vec4 color;
void main(){
    gl_FragColor = color;
}
)";
}

inline std::string OITFbo::fragAccumCode() {
    return R"(
varying vec4 color;
void main() {
    vec4 premult = vec4(color.rgb * color.a, color.a);
    vec3 transmit = color.rgb * (1.0 - color.a);
    premult.a *= 1.0 - clamp((transmit.r + transmit.g + transmit.b) / 3.0, 0.0, 1.0);
    float tmp = (min(premult.a, 1.0) * 8.0 + 0.01) * (1.0 - gl_FragCoord.z * 0.95);
    float w = clamp(tmp * tmp * tmp * 1e3, 1e-2, 3e2);
    gl_FragColor = premult * w / 100.0; // divide by 100 so we write a val less than 1.0
}
)";
}

inline std::string OITFbo::fragRevealCode() {
    return R"(
varying vec4 color;
void main() {
    vec4 premult = vec4(color.rgb * color.a, color.a);
    vec3 transmit = color.rgb * (1.0 - color.a);
    premult.a *= 1.0 - clamp((transmit.r + transmit.g + transmit.b) / 3.0, 0.0, 1.0);
    // all ouput we want is one value but we gotta write to 4 channels
    gl_FragColor = vec4(premult.a);
}
)";
}

inline std::string OITFbo::vertCompositeCode() {
    return R"(
void main(){
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
)";
}

inline std::string OITFbo::fragCompsiteCode() {
    return R"(
uniform sampler2D tex_accum;
uniform sampler2D tex_reveal;
void main(){
    vec4 accum = texture2D(tex_accum, gl_TexCoord[0].st) * 100.0;
    float revealage = texture2D(tex_reveal, gl_TexCoord[0].st).a;
    gl_FragColor = vec4(accum.rgb / max(accum.a, 0.00001), revealage);
}
)";
}

inline void OITFbo::quadViewport() {
    g.pushMatrix(g.PROJECTION);
    g.loadIdentity();
    g.pushMatrix(g.MODELVIEW);
    g.loadIdentity();
    g.depthMask(0); // write only to color buffer
    al::Mesh& m = g.mesh();
    m.reset();
    m.primitive(g.TRIANGLE_STRIP);
    m.vertex(-1, -1, 0);
    m.texCoord(0, 0);
    m.vertex(1, -1, 0);
    m.texCoord(1, 0);
    m.vertex(-1, 1, 0);
    m.texCoord(0, 1);
    m.vertex(1, 1, 0);
    m.texCoord(1, 1);
    g.draw(m);
    g.depthMask(1);
    g.popMatrix(g.PROJECTION);
    g.popMatrix(g.MODELVIEW);
}

inline void OITFbo::clearColor(float r, float g, float b, float a) {
    glClearColor(r, g, b, a);
    glClear(GL_COLOR_BUFFER_BIT);
}

inline void OITFbo::clearDepth(float d) {
    glClearDepth(d);
    glClear(GL_DEPTH_BUFFER_BIT);
}

}<|endoftext|>


<commit_before>
// Copyright(c) Microsoft.All rights reserved.
// Licensed under the MIT license.See LICENSE file in the project root for full license information.

#define _CRT_SECURE_NO_WARNINGS

#include <boost/python.hpp>
#include <string>
#include <vector>
#include <list>

#include "azure_c_shared_utility/platform.h"
#include "iothub_client.h"
#include "iothub_client_version.h"
#include "iothub_message.h"
#include "iothubtransporthttp.h"
#include "iothubtransportamqp.h"
#include "iothubtransportmqtt.h"

#define IMPORT_NAME iothub_client_mock

// "platform.h"

int platform_init(void)
{
    return 0;
}

void platform_deinit(void)
{
}

// "map.h"

MAP_HANDLE mockMapHandle = (MAP_HANDLE)0x12345678;

#define MOCKMAPSIZE 128
#define MOCKARRAYSIZE 8
MAP_FILTER_CALLBACK mockFilterFunc = NULL;
char mockKey[MOCKMAPSIZE] = { 0 };
char *mockKeyArray[MOCKARRAYSIZE] = { mockKey };
char mockValue[MOCKMAPSIZE] = { 0 };
char *mockValueArray[MOCKARRAYSIZE] = { mockValue };

MAP_HANDLE Map_Create(MAP_FILTER_CALLBACK mapFilterFunc)
{
    // reset mock buffers
    memset(mockKey, 0, sizeof(mockKey));
    memset(mockValue, 0, sizeof(mockValue));
    mockFilterFunc = mapFilterFunc;
    return mockMapHandle;
}

void Map_Destroy(MAP_HANDLE handle)
{
    // mockFilterFunc = NULL;
}

MAP_HANDLE Map_Clone(MAP_HANDLE handle)
{
    return mockMapHandle;
}

MAP_RESULT Map_Add(MAP_HANDLE handle, const char* key, const char* value)
{
    MAP_RESULT result = MAP_OK;

    if (mockFilterFunc != NULL)
    {
        result = mockFilterFunc(key, value) ? MAP_FILTER_REJECT : MAP_OK;
    }

    if (result == MAP_OK)
    {
        if (strcmp(mockKey, key) == 0)
        {
            result = MAP_KEYEXISTS;
        }
        else
        {
            strcpy(mockKey, key);
            strcpy(mockValue, value);
        }
    }
    return result;
}

MAP_RESULT Map_AddOrUpdate(MAP_HANDLE handle, const char* key, const char* value)
{
    MAP_RESULT result = MAP_OK;

    if (mockFilterFunc != NULL)
    {
        result = mockFilterFunc(key, value) ? MAP_FILTER_REJECT : MAP_OK;
    }

    if (result == MAP_OK)
    {
        strcpy(mockKey, key);
        strcpy(mockValue, value);
    }

    return result;
}

MAP_RESULT Map_Delete(MAP_HANDLE handle, const char* key)
{
    MAP_RESULT result = MAP_KEYNOTFOUND;

    if (strcmp(mockKey, key) == 0)
    {
        memset(mockKey, 0, sizeof(mockKey));
        memset(mockValue, 0, sizeof(mockValue));
        result = MAP_OK;
    }

    return result;
}

MAP_RESULT Map_ContainsKey(MAP_HANDLE handle, const char* key, bool* keyExists)
{
    *keyExists = strcmp(mockKey, key) == 0;
    return MAP_OK;
}

MAP_RESULT Map_ContainsValue(MAP_HANDLE handle, const char* value, bool* valueExists)
{
    *valueExists = strcmp(mockValue, value) == 0;
    return MAP_OK;
}

const char* Map_GetValueFromKey(MAP_HANDLE handle, const char* key)
{
    if (strcmp(mockKey, key) == 0)
    {
        return mockValue;
    }
    return NULL;
}

MAP_RESULT Map_GetInternals(MAP_HANDLE handle, const char*const** keys, const char*const** values, size_t* count)
{
    *count = 0;
    *keys = mockKeyArray;
    *values = mockValueArray;

    if (*mockKey != '\0')
    {
        *count = 1;
    }

    return MAP_OK;
}

// "iothub_client.h"

IOTHUB_CLIENT_HANDLE mockClientHandle = (IOTHUB_CLIENT_HANDLE)0x12345678;

IOTHUB_CLIENT_HANDLE IoTHubClient_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
{
    return mockClientHandle;
}

IOTHUB_CLIENT_HANDLE IoTHubClient_Create(const IOTHUB_CLIENT_CONFIG* config)
{
    return mockClientHandle;
}

void IoTHubClient_Destroy(IOTHUB_CLIENT_HANDLE iotHubClientHandle)
{
}

IOTHUB_CLIENT_RESULT IoTHubClient_SendEventAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
{
    return IOTHUB_CLIENT_OK;
}

IOTHUB_CLIENT_RESULT IoTHubClient_GetSendStatus(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
{
    return IOTHUB_CLIENT_OK;
}

IOTHUB_CLIENT_RESULT IoTHubClient_SetMessageCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback)
{
    return IOTHUB_CLIENT_OK;
}

IOTHUB_CLIENT_RESULT IoTHubClient_GetLastMessageReceiveTime(IOTHUB_CLIENT_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime)
{
    return IOTHUB_CLIENT_INDEFINITE_TIME;
}

IOTHUB_CLIENT_RESULT IoTHubClient_SetOption(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* optionName, const void* value)
{
    return IOTHUB_CLIENT_OK;
}

// "iothub_client_version.h"

const char* IoTHubClient_GetVersionString(void)
{
    return IOTHUB_SDK_VERSION;
}

// "iothub_message.h"

IOTHUB_MESSAGE_HANDLE mockMessageHandle = (IOTHUB_MESSAGE_HANDLE)0x12345678;
#define MOCKMESSAGESIZE 128
char mockBuffer[MOCKMESSAGESIZE] = { 0 };
char mockMessageId[MOCKMESSAGESIZE] = { 0 };
char mockCorrelationId[MOCKMESSAGESIZE] = { 0 };
size_t mockSize = 0;
bool mockString = false;

IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromByteArray(const unsigned char* byteArray, size_t size)
{
    mockSize = size > MOCKMESSAGESIZE ? MOCKMESSAGESIZE : size;
    memcpy(mockBuffer, byteArray, mockSize);
    mockString = false;
    return mockMessageHandle;
}

IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromString(const char* source)
{
    mockString = true;
    strncpy(mockBuffer, source, MOCKMESSAGESIZE);
    return mockMessageHandle;
}

IOTHUB_MESSAGE_HANDLE IoTHubMessage_Clone(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    return mockMessageHandle;
}

IOTHUB_MESSAGE_RESULT IoTHubMessage_GetByteArray(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const unsigned char** buffer, size_t* size)
{
    if (mockString)
    {
        return IOTHUB_MESSAGE_INVALID_TYPE;
    }
    *buffer = (unsigned char*)mockBuffer;
    *size = mockSize;
    return IOTHUB_MESSAGE_OK;
}

const char* IoTHubMessage_GetString(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    if (!mockString)
    {
        return NULL;
    }
    return mockBuffer;
}

IOTHUBMESSAGE_CONTENT_TYPE IoTHubMessage_GetContentType(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    return mockString ? IOTHUBMESSAGE_STRING : IOTHUBMESSAGE_BYTEARRAY;
}

MAP_HANDLE IoTHubMessage_Properties(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    return mockMapHandle;
}

const char* IoTHubMessage_GetMessageId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    if (*mockMessageId == '\0')
    {
        return NULL;
    }
    return mockMessageId;
}

IOTHUB_MESSAGE_RESULT IoTHubMessage_SetMessageId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* messageId)
{
    strncpy(mockMessageId, messageId, MOCKMESSAGESIZE);
    return IOTHUB_MESSAGE_OK;
}

const char* IoTHubMessage_GetCorrelationId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    if (*mockCorrelationId == '\0')
    {
        return NULL;
    }
    return mockCorrelationId;
}

IOTHUB_MESSAGE_RESULT IoTHubMessage_SetCorrelationId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* correlationId)
{
    strncpy(mockCorrelationId, correlationId, MOCKMESSAGESIZE);
    return IOTHUB_MESSAGE_OK;
}

void IoTHubMessage_Destroy(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
}

// "iothubtransporthttp.h"
void *mockProtocol = (void *)0x12345678;
const void* HTTP_Protocol(void)
{
    return mockProtocol;
}

// "iothubtransportamqp.h"

const void* AMQP_Protocol(void)
{
    return mockProtocol;
}

// "iothubtransportmqtt.h"

const void* MQTT_Protocol(void)
{
    return mockProtocol;
}

<commit_msg>fix python<commit_after>
// Copyright(c) Microsoft.All rights reserved.
// Licensed under the MIT license.See LICENSE file in the project root for full license information.

#define _CRT_SECURE_NO_WARNINGS

#include <boost/python.hpp>
#include <string>
#include <vector>
#include <list>

#include "azure_c_shared_utility/platform.h"
#include "iothub_client.h"
#include "iothub_client_version.h"
#include "iothub_message.h"
#include "iothubtransporthttp.h"
#include "iothubtransportamqp.h"
#include "iothubtransportmqtt.h"

#define IMPORT_NAME iothub_client_mock

// "platform.h"

int platform_init(void)
{
    return 0;
}

void platform_deinit(void)
{
}

// "map.h"

MAP_HANDLE mockMapHandle = (MAP_HANDLE)0x12345678;

#define MOCKMAPSIZE 128
#define MOCKARRAYSIZE 8
MAP_FILTER_CALLBACK mockFilterFunc = NULL;
char mockKey[MOCKMAPSIZE] = { 0 };
char *mockKeyArray[MOCKARRAYSIZE] = { mockKey };
char mockValue[MOCKMAPSIZE] = { 0 };
char *mockValueArray[MOCKARRAYSIZE] = { mockValue };

MAP_HANDLE Map_Create(MAP_FILTER_CALLBACK mapFilterFunc)
{
    // reset mock buffers
    memset(mockKey, 0, sizeof(mockKey));
    memset(mockValue, 0, sizeof(mockValue));
    mockFilterFunc = mapFilterFunc;
    return mockMapHandle;
}

void Map_Destroy(MAP_HANDLE handle)
{
    // mockFilterFunc = NULL;
}

MAP_HANDLE Map_Clone(MAP_HANDLE handle)
{
    return mockMapHandle;
}

MAP_RESULT Map_Add(MAP_HANDLE handle, const char* key, const char* value)
{
    MAP_RESULT result = MAP_OK;

    if (mockFilterFunc != NULL)
    {
        result = mockFilterFunc(key, value) ? MAP_FILTER_REJECT : MAP_OK;
    }

    if (result == MAP_OK)
    {
        if (strcmp(mockKey, key) == 0)
        {
            result = MAP_KEYEXISTS;
        }
        else
        {
            strcpy(mockKey, key);
            strcpy(mockValue, value);
        }
    }
    return result;
}

MAP_RESULT Map_AddOrUpdate(MAP_HANDLE handle, const char* key, const char* value)
{
    MAP_RESULT result = MAP_OK;

    if (mockFilterFunc != NULL)
    {
        result = mockFilterFunc(key, value) ? MAP_FILTER_REJECT : MAP_OK;
    }

    if (result == MAP_OK)
    {
        strcpy(mockKey, key);
        strcpy(mockValue, value);
    }

    return result;
}

MAP_RESULT Map_Delete(MAP_HANDLE handle, const char* key)
{
    MAP_RESULT result = MAP_KEYNOTFOUND;

    if (strcmp(mockKey, key) == 0)
    {
        memset(mockKey, 0, sizeof(mockKey));
        memset(mockValue, 0, sizeof(mockValue));
        result = MAP_OK;
    }

    return result;
}

MAP_RESULT Map_ContainsKey(MAP_HANDLE handle, const char* key, bool* keyExists)
{
    *keyExists = strcmp(mockKey, key) == 0;
    return MAP_OK;
}

MAP_RESULT Map_ContainsValue(MAP_HANDLE handle, const char* value, bool* valueExists)
{
    *valueExists = strcmp(mockValue, value) == 0;
    return MAP_OK;
}

const char* Map_GetValueFromKey(MAP_HANDLE handle, const char* key)
{
    if (strcmp(mockKey, key) == 0)
    {
        return mockValue;
    }
    return NULL;
}

MAP_RESULT Map_GetInternals(MAP_HANDLE handle, const char*const** keys, const char*const** values, size_t* count)
{
    *count = 0;
    *keys = mockKeyArray;
    *values = mockValueArray;

    if (*mockKey != '\0')
    {
        *count = 1;
    }

    return MAP_OK;
}

// "iothub_client.h"

IOTHUB_CLIENT_HANDLE mockClientHandle = (IOTHUB_CLIENT_HANDLE)0x12345678;

IOTHUB_CLIENT_HANDLE IoTHubClient_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
{
    return mockClientHandle;
}

IOTHUB_CLIENT_HANDLE IoTHubClient_Create(const IOTHUB_CLIENT_CONFIG* config)
{
    return mockClientHandle;
}

void IoTHubClient_Destroy(IOTHUB_CLIENT_HANDLE iotHubClientHandle)
{
}

IOTHUB_CLIENT_RESULT IoTHubClient_SendEventAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
{
    return IOTHUB_CLIENT_OK;
}

IOTHUB_CLIENT_RESULT IoTHubClient_GetSendStatus(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
{
    return IOTHUB_CLIENT_OK;
}

IOTHUB_CLIENT_RESULT IoTHubClient_SetMessageCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback)
{
    return IOTHUB_CLIENT_OK;
}

IOTHUB_CLIENT_RESULT IoTHubClient_GetLastMessageReceiveTime(IOTHUB_CLIENT_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime)
{
    return IOTHUB_CLIENT_INDEFINITE_TIME;
}

IOTHUB_CLIENT_RESULT IoTHubClient_SetOption(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* optionName, const void* value)
{
    return IOTHUB_CLIENT_OK;
}

// "iothub_client_version.h"

const char* IoTHubClient_GetVersionString(void)
{
    return IOTHUB_SDK_VERSION;
}

// "iothub_message.h"

IOTHUB_MESSAGE_HANDLE mockMessageHandle = (IOTHUB_MESSAGE_HANDLE)0x12345678;
#define MOCKMESSAGESIZE 128
char mockBuffer[MOCKMESSAGESIZE] = { 0 };
char mockMessageId[MOCKMESSAGESIZE] = { 0 };
char mockCorrelationId[MOCKMESSAGESIZE] = { 0 };
size_t mockSize = 0;
bool mockString = false;

IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromByteArray(const unsigned char* byteArray, size_t size)
{
    mockSize = size > MOCKMESSAGESIZE ? MOCKMESSAGESIZE : size;
    memcpy(mockBuffer, byteArray, mockSize);
    mockString = false;
    return mockMessageHandle;
}

IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromString(const char* source)
{
    mockString = true;
    strncpy(mockBuffer, source, MOCKMESSAGESIZE);
    return mockMessageHandle;
}

IOTHUB_MESSAGE_HANDLE IoTHubMessage_Clone(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    return mockMessageHandle;
}

IOTHUB_MESSAGE_RESULT IoTHubMessage_GetByteArray(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const unsigned char** buffer, size_t* size)
{
    if (mockString)
    {
        return IOTHUB_MESSAGE_INVALID_TYPE;
    }
    *buffer = (unsigned char*)mockBuffer;
    *size = mockSize;
    return IOTHUB_MESSAGE_OK;
}

const char* IoTHubMessage_GetString(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    if (!mockString)
    {
        return NULL;
    }
    return mockBuffer;
}

IOTHUBMESSAGE_CONTENT_TYPE IoTHubMessage_GetContentType(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    return mockString ? IOTHUBMESSAGE_STRING : IOTHUBMESSAGE_BYTEARRAY;
}

MAP_HANDLE IoTHubMessage_Properties(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    return mockMapHandle;
}

const char* IoTHubMessage_GetMessageId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    if (*mockMessageId == '\0')
    {
        return NULL;
    }
    return mockMessageId;
}

IOTHUB_MESSAGE_RESULT IoTHubMessage_SetMessageId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* messageId)
{
    strncpy(mockMessageId, messageId, MOCKMESSAGESIZE);
    return IOTHUB_MESSAGE_OK;
}

const char* IoTHubMessage_GetCorrelationId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    if (*mockCorrelationId == '\0')
    {
        return NULL;
    }
    return mockCorrelationId;
}

IOTHUB_MESSAGE_RESULT IoTHubMessage_SetCorrelationId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* correlationId)
{
    strncpy(mockCorrelationId, correlationId, MOCKMESSAGESIZE);
    return IOTHUB_MESSAGE_OK;
}

void IoTHubMessage_Destroy(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
}

// "iothubtransporthttp.h"
TRANSPORT_PROVIDER *mockProtocol = (TRANSPORT_PROVIDER *)0x12345678;
const TRANSPORT_PROVIDER* HTTP_Protocol(void)
{
    return mockProtocol;
}

// "iothubtransportamqp.h"

const TRANSPORT_PROVIDER* AMQP_Protocol(void)
{
    return mockProtocol;
}

// "iothubtransportmqtt.h"

const TRANSPORT_PROVIDER* MQTT_Protocol(void)
{
    return mockProtocol;
}

<|endoftext|>