<commit_before>/*
 * Copyright 2004-2015 Cray Inc.
 * Other additional copyright holders may be indicated within.
 *
 * The entirety of this work is licensed under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <map>
#include <iostream>
#include <fstream>
#include <iterator>
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>

#include "driver.h"
#include "passes.h"
#include "symbol.h"
#include "expr.h"
#include "stmt.h"
#include "docs.h"
#include "mysystem.h"
#include "stringutil.h"
#include "scopeResolve.h"
#include "AstToText.h"
#include "AstPrintDocs.h"

static int compareNames(const void* v1, const void* v2) {
  Symbol* s1 = *(Symbol* const *)v1;
  Symbol* s2 = *(Symbol* const *)v2;
  return strcmp(s1->name, s2->name);
}

static int compareClasses(const void *v1, const void* v2) {
  Type *t1 = *(Type* const *)v1;
  Type *t2 = *(Type* const *)v2;
  return strcmp(t1->symbol->name, t2->symbol->name);
}

void docs(void) {

  if (fDocs) {
    // To handle inheritance, we need to look up parent classes and records.
    // In order to be successful when looking up these parents, the import
    // expressions should be accurately accounted for.
    addToSymbolTable(gDefExprs);
    processImportExprs();

    // Open the directory to store the docs
    std::string docsDir = (strlen(fDocsFolder) != 0) ? fDocsFolder : "docs";
    std::string docsFolderName = docsDir;

    if (!fDocsTextOnly) {
      docsFolderName = generateSphinxProject(docsDir);
    }

    mkdir(docsFolderName.c_str(), S_IWUSR|S_IRUSR|S_IXUSR);

    forv_Vec(ModuleSymbol, mod, gModuleSymbols) {
      // TODO: Add flag to compiler to turn on doc dev only output
      if (!mod->hasFlag(FLAG_NO_DOC) && !devOnlyModule(mod)) {
        if (isNotSubmodule(mod)) {
          std::ofstream *file = openFileFromMod(mod, docsFolderName);

          AstPrintDocs *docsVisitor = new AstPrintDocs(file);
          mod->accept(docsVisitor);

          // printModule(file, mod, mod->name, 0);

          file->close();
        }
      }
    }

    if (!fDocsTextOnly) {
      generateSphinxOutput(docsDir);
    }
  }
}

bool isNotSubmodule(ModuleSymbol *mod) {
  return (mod->defPoint == NULL ||
          mod->defPoint->parentSymbol == NULL ||
          mod->defPoint->parentSymbol->name == NULL ||
          strcmp("chpl__Program", mod->defPoint->parentSymbol->name) == 0 ||
          strcmp("_root", mod->defPoint->parentSymbol->name) == 0);
}

void printFields(std::ofstream *file, AggregateType *cl, unsigned int tabs) {
  for (int i = 1; i <= cl->fields.length; i++) {
    if (VarSymbol *var = toVarSymbol(((DefExpr *)cl->fields.get(i))->sym)) {
      var->makeField();
      var->printDocs(file, tabs);
    }
  }
}

void inheritance(Vec<AggregateType*> *list, AggregateType *cl) {
  for_alist(expr, cl->inherits) {
    AggregateType* pt = discoverParentAndCheck(expr, cl);

    list->add_exclusive(pt);
    inheritance(list, pt);
  }
}

void printClass(std::ofstream *file, AggregateType *cl, unsigned int tabs) {
  if (!cl->symbol->hasFlag(FLAG_NO_DOC) && ! cl->isUnion()) {
    cl->printDocs(file, tabs);

    printFields(file, cl, tabs + 1);

    // In rst mode, add an additional line break after the attributes and
    // before the next directive.
    if (!fDocsTextOnly) {
      *file << std::endl;
    }

    // If alphabetical option passed, alphabetizes the output
    if (fDocsAlphabetize)
      qsort(cl->methods.v, cl->methods.n, sizeof(cl->methods.v[0]),
        compareNames);

    forv_Vec(FnSymbol, fn, cl->methods){
      // We only want to print methods defined within the class under the
      // class header
      if (fn->isPrimaryMethod())
        fn->printDocs(file, tabs + 1);
    }

    Vec<AggregateType*> superClasses;
    inheritance(&superClasses, cl);

    if (fDocsAlphabetize)
      qsort(superClasses.v, superClasses.n, sizeof(superClasses.v[0]), compareClasses);

    forv_Vec(AggregateType, superClass, superClasses) {
      superClass->printInheritanceDocs(file, tabs + 1);
      printFields(file, superClass, tabs + 2);

      forv_Vec(FnSymbol, fn, superClass->methods) {
        fn->printDocs(file, tabs + 2);
      }
      *file << std::endl;
    }
  }
}

// Returns true if the provided fn is a module initializer, class constructor,
// type constructor, or module copy of a class method.  These functions are
// only printed in developer mode.  Is not applicable to printing class
// functions.
bool devOnlyFunction(FnSymbol *fn) {
  return (fn->hasFlag(FLAG_MODULE_INIT) || fn->hasFlag(FLAG_TYPE_CONSTRUCTOR)
          || fn->hasFlag(FLAG_CONSTRUCTOR) || fn->isPrimaryMethod());
}

// Returns true if the provide module is one of the internal or standard
// modules. It is our opinion that these should only automatically be printed
// out if the user is in developer mode.
bool devOnlyModule(ModuleSymbol *mod) {
  return mod->modTag == MOD_INTERNAL || mod->modTag == MOD_STANDARD;
}

void printModule(std::ofstream *file, ModuleSymbol *mod, unsigned int tabs) {
  if (!mod->hasFlag(FLAG_NO_DOC)) {
    mod->printDocs(file, tabs);

    Vec<VarSymbol*> configs = mod->getTopLevelConfigVars();
    if (fDocsAlphabetize)
      qsort(configs.v, configs.n, sizeof(configs.v[0]), compareNames);
    forv_Vec(VarSymbol, var, configs) {
      var->printDocs(file, tabs + 1);
    }

    Vec<VarSymbol*> variables = mod->getTopLevelVariables();
    if (fDocsAlphabetize)
      qsort(variables.v, variables.n, sizeof(variables.v[0]), compareNames);
    forv_Vec(VarSymbol, var, variables) {
      var->printDocs(file, tabs + 1);
    }
    Vec<FnSymbol*> fns = mod->getTopLevelFunctions(fDocsIncludeExterns);
    // If alphabetical option passed, fDocsAlphabetizes the output
    if (fDocsAlphabetize)
      qsort(fns.v, fns.n, sizeof(fns.v[0]), compareNames);

    forv_Vec(FnSymbol, fn, fns) {
      // TODO: Add flag to compiler to turn on doc dev only output

      // We want methods on classes that are defined at the module level to be
      // printed at the module level
      if (!devOnlyFunction(fn) || fn->isSecondaryMethod()) {
        fn->printDocs(file, tabs + 1);
      }
    }

    Vec<AggregateType*> classes = mod->getTopLevelClasses();
    if (fDocsAlphabetize)
      qsort(classes.v, classes.n, sizeof(classes.v[0]), compareClasses);

    forv_Vec(AggregateType, cl, classes) {
      printClass(file, cl, tabs + 1);
    }

    Vec<ModuleSymbol*> mods = mod->getTopLevelModules();
    if (fDocsAlphabetize)
      qsort(mods.v, mods.n, sizeof(mods.v[0]), compareNames);

    forv_Vec(ModuleSymbol, subMod, mods) {
      // TODO: Add flag to compiler to turn on doc dev only output
      if (!devOnlyModule(subMod)) {
        subMod->addPrefixToName(mod->docsName() + ".");
        printModule(file, subMod, tabs + 1);
      }
    }
  }
}

void createDocsFileFolders(std::string filename) {
  size_t dirCutoff = filename.find("/");
  size_t total = 0;
  while (dirCutoff != std::string::npos) {
    // Creates each subdirectory within the new documentation directory
    dirCutoff += total;
    std::string shorter = filename.substr(dirCutoff+1);
    std::string otherHalf = filename.substr(0, dirCutoff);
    mkdir(otherHalf.c_str(), S_IWUSR|S_IRUSR|S_IXUSR);
    total = dirCutoff + 1;
    dirCutoff = shorter.find("/");
  }
}

/*
 * Create new sphinx project at given location and return path where .rst files
 * should be placed.
 */
std::string generateSphinxProject(std::string dirpath) {
  // FIXME: This ought to be done in a TMPDIR, unless --save-rst is
  //        provided... (thomasvandoren, 2015-01-29)

  // Create the output dir under the docs output dir.
  const char * htmldir = astr(dirpath.c_str(), "/html");

  // Ensure output directory exists.
  const char * mkdirCmd = astr("mkdir -p ", htmldir);
  mysystem(mkdirCmd, "creating docs output dir");

  // Copy the sphinx template into the output dir.
  const char * sphinxTemplate = astr(CHPL_HOME, "/third-party/chpldoc-venv/chpldoc-sphinx-project/*");
  const char * cmd = astr("cp -r ", sphinxTemplate, " ", htmldir, "/");
  mysystem(cmd, "copying chpldoc sphinx template");

  const char * moddir = astr(htmldir, "/source/modules");
  return std::string(moddir);
}

/* Call `make html` from inside sphinx project. */
void generateSphinxOutput(std::string dirpath) {
  const char * htmldir = astr(dirpath.c_str(), "/html");

  // The virtualenv activate script is at:
  //   $CHPL_HOME/third-party/chpldoc-venv/install/$CHPL_TARGET_PLATFORM/chpldoc-virtualenv/bin/activate
  const char * activate = astr(
    CHPL_HOME, "/third-party/chpldoc-venv/install/",
    CHPL_TARGET_PLATFORM, "/chpdoc-virtualenv/bin/activate");

  // Run: `. $activate && cd $htmldir && $CHPL_MAKE html`
  const char * cmd = astr(
    ". ", activate,
    " && cd ", htmldir, " && ",
    CHPL_MAKE, " html");
  mysystem(cmd, "building html output from chpldoc sphinx project");
}

std::string filenameFromMod(ModuleSymbol *mod, std::string docsFolderName) {
  std::string filename = mod->filename;

  if (mod->modTag == MOD_INTERNAL) {
    filename = "internal-modules/";
  } else if (mod ->modTag == MOD_STANDARD) {
    filename = "standard-modules/";
  } else {
    size_t location = filename.rfind("/");
    if (location != std::string::npos) {
      filename = filename.substr(0, location + 1);
    } else {
      filename = "";
    }
  }
  filename = docsFolderName + "/" + filename;
  createDocsFileFolders(filename);

  // Creates files for each top level module.
  if (fDocsTextOnly) {
    filename = filename + mod->name + ".txt";
  } else {
    filename = filename + mod->name + ".rst";
  }

  return filename;
}

std::ofstream* openFileFromMod(ModuleSymbol *mod, std::string docsFolderName) {
  std::string filename = filenameFromMod(mod, docsFolderName);
  return new std::ofstream(filename.c_str(), std::ios::out);
}
<commit_msg>fix printModule() args<commit_after>/*
 * Copyright 2004-2015 Cray Inc.
 * Other additional copyright holders may be indicated within.
 *
 * The entirety of this work is licensed under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <map>
#include <iostream>
#include <fstream>
#include <iterator>
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>

#include "driver.h"
#include "passes.h"
#include "symbol.h"
#include "expr.h"
#include "stmt.h"
#include "docs.h"
#include "mysystem.h"
#include "stringutil.h"
#include "scopeResolve.h"
#include "AstToText.h"
#include "AstPrintDocs.h"

static int compareNames(const void* v1, const void* v2) {
  Symbol* s1 = *(Symbol* const *)v1;
  Symbol* s2 = *(Symbol* const *)v2;
  return strcmp(s1->name, s2->name);
}

static int compareClasses(const void *v1, const void* v2) {
  Type *t1 = *(Type* const *)v1;
  Type *t2 = *(Type* const *)v2;
  return strcmp(t1->symbol->name, t2->symbol->name);
}

void docs(void) {

  if (fDocs) {
    // To handle inheritance, we need to look up parent classes and records.
    // In order to be successful when looking up these parents, the import
    // expressions should be accurately accounted for.
    addToSymbolTable(gDefExprs);
    processImportExprs();

    // Open the directory to store the docs
    std::string docsDir = (strlen(fDocsFolder) != 0) ? fDocsFolder : "docs";
    std::string docsFolderName = docsDir;

    if (!fDocsTextOnly) {
      docsFolderName = generateSphinxProject(docsDir);
    }

    mkdir(docsFolderName.c_str(), S_IWUSR|S_IRUSR|S_IXUSR);

    forv_Vec(ModuleSymbol, mod, gModuleSymbols) {
      // TODO: Add flag to compiler to turn on doc dev only output
      if (!mod->hasFlag(FLAG_NO_DOC) && !devOnlyModule(mod)) {
        if (isNotSubmodule(mod)) {
          std::ofstream *file = openFileFromMod(mod, docsFolderName);

          AstPrintDocs *docsVisitor = new AstPrintDocs(file);
          mod->accept(docsVisitor);

          // printModule(file, mod, 0);

          file->close();
        }
      }
    }

    if (!fDocsTextOnly) {
      generateSphinxOutput(docsDir);
    }
  }
}

bool isNotSubmodule(ModuleSymbol *mod) {
  return (mod->defPoint == NULL ||
          mod->defPoint->parentSymbol == NULL ||
          mod->defPoint->parentSymbol->name == NULL ||
          strcmp("chpl__Program", mod->defPoint->parentSymbol->name) == 0 ||
          strcmp("_root", mod->defPoint->parentSymbol->name) == 0);
}

void printFields(std::ofstream *file, AggregateType *cl, unsigned int tabs) {
  for (int i = 1; i <= cl->fields.length; i++) {
    if (VarSymbol *var = toVarSymbol(((DefExpr *)cl->fields.get(i))->sym)) {
      var->makeField();
      var->printDocs(file, tabs);
    }
  }
}

void inheritance(Vec<AggregateType*> *list, AggregateType *cl) {
  for_alist(expr, cl->inherits) {
    AggregateType* pt = discoverParentAndCheck(expr, cl);

    list->add_exclusive(pt);
    inheritance(list, pt);
  }
}

void printClass(std::ofstream *file, AggregateType *cl, unsigned int tabs) {
  if (!cl->symbol->hasFlag(FLAG_NO_DOC) && ! cl->isUnion()) {
    cl->printDocs(file, tabs);

    printFields(file, cl, tabs + 1);

    // In rst mode, add an additional line break after the attributes and
    // before the next directive.
    if (!fDocsTextOnly) {
      *file << std::endl;
    }

    // If alphabetical option passed, alphabetizes the output
    if (fDocsAlphabetize)
      qsort(cl->methods.v, cl->methods.n, sizeof(cl->methods.v[0]),
        compareNames);

    forv_Vec(FnSymbol, fn, cl->methods){
      // We only want to print methods defined within the class under the
      // class header
      if (fn->isPrimaryMethod())
        fn->printDocs(file, tabs + 1);
    }

    Vec<AggregateType*> superClasses;
    inheritance(&superClasses, cl);

    if (fDocsAlphabetize)
      qsort(superClasses.v, superClasses.n, sizeof(superClasses.v[0]), compareClasses);

    forv_Vec(AggregateType, superClass, superClasses) {
      superClass->printInheritanceDocs(file, tabs + 1);
      printFields(file, superClass, tabs + 2);

      forv_Vec(FnSymbol, fn, superClass->methods) {
        fn->printDocs(file, tabs + 2);
      }
      *file << std::endl;
    }
  }
}

// Returns true if the provided fn is a module initializer, class constructor,
// type constructor, or module copy of a class method.  These functions are
// only printed in developer mode.  Is not applicable to printing class
// functions.
bool devOnlyFunction(FnSymbol *fn) {
  return (fn->hasFlag(FLAG_MODULE_INIT) || fn->hasFlag(FLAG_TYPE_CONSTRUCTOR)
          || fn->hasFlag(FLAG_CONSTRUCTOR) || fn->isPrimaryMethod());
}

// Returns true if the provide module is one of the internal or standard
// modules. It is our opinion that these should only automatically be printed
// out if the user is in developer mode.
bool devOnlyModule(ModuleSymbol *mod) {
  return mod->modTag == MOD_INTERNAL || mod->modTag == MOD_STANDARD;
}

void printModule(std::ofstream *file, ModuleSymbol *mod, unsigned int tabs) {
  if (!mod->hasFlag(FLAG_NO_DOC)) {
    mod->printDocs(file, tabs);

    Vec<VarSymbol*> configs = mod->getTopLevelConfigVars();
    if (fDocsAlphabetize)
      qsort(configs.v, configs.n, sizeof(configs.v[0]), compareNames);
    forv_Vec(VarSymbol, var, configs) {
      var->printDocs(file, tabs + 1);
    }

    Vec<VarSymbol*> variables = mod->getTopLevelVariables();
    if (fDocsAlphabetize)
      qsort(variables.v, variables.n, sizeof(variables.v[0]), compareNames);
    forv_Vec(VarSymbol, var, variables) {
      var->printDocs(file, tabs + 1);
    }
    Vec<FnSymbol*> fns = mod->getTopLevelFunctions(fDocsIncludeExterns);
    // If alphabetical option passed, fDocsAlphabetizes the output
    if (fDocsAlphabetize)
      qsort(fns.v, fns.n, sizeof(fns.v[0]), compareNames);

    forv_Vec(FnSymbol, fn, fns) {
      // TODO: Add flag to compiler to turn on doc dev only output

      // We want methods on classes that are defined at the module level to be
      // printed at the module level
      if (!devOnlyFunction(fn) || fn->isSecondaryMethod()) {
        fn->printDocs(file, tabs + 1);
      }
    }

    Vec<AggregateType*> classes = mod->getTopLevelClasses();
    if (fDocsAlphabetize)
      qsort(classes.v, classes.n, sizeof(classes.v[0]), compareClasses);

    forv_Vec(AggregateType, cl, classes) {
      printClass(file, cl, tabs + 1);
    }

    Vec<ModuleSymbol*> mods = mod->getTopLevelModules();
    if (fDocsAlphabetize)
      qsort(mods.v, mods.n, sizeof(mods.v[0]), compareNames);

    forv_Vec(ModuleSymbol, subMod, mods) {
      // TODO: Add flag to compiler to turn on doc dev only output
      if (!devOnlyModule(subMod)) {
        subMod->addPrefixToName(mod->docsName() + ".");
        printModule(file, subMod, tabs + 1);
      }
    }
  }
}

void createDocsFileFolders(std::string filename) {
  size_t dirCutoff = filename.find("/");
  size_t total = 0;
  while (dirCutoff != std::string::npos) {
    // Creates each subdirectory within the new documentation directory
    dirCutoff += total;
    std::string shorter = filename.substr(dirCutoff+1);
    std::string otherHalf = filename.substr(0, dirCutoff);
    mkdir(otherHalf.c_str(), S_IWUSR|S_IRUSR|S_IXUSR);
    total = dirCutoff + 1;
    dirCutoff = shorter.find("/");
  }
}

/*
 * Create new sphinx project at given location and return path where .rst files
 * should be placed.
 */
std::string generateSphinxProject(std::string dirpath) {
  // FIXME: This ought to be done in a TMPDIR, unless --save-rst is
  //        provided... (thomasvandoren, 2015-01-29)

  // Create the output dir under the docs output dir.
  const char * htmldir = astr(dirpath.c_str(), "/html");

  // Ensure output directory exists.
  const char * mkdirCmd = astr("mkdir -p ", htmldir);
  mysystem(mkdirCmd, "creating docs output dir");

  // Copy the sphinx template into the output dir.
  const char * sphinxTemplate = astr(CHPL_HOME, "/third-party/chpldoc-venv/chpldoc-sphinx-project/*");
  const char * cmd = astr("cp -r ", sphinxTemplate, " ", htmldir, "/");
  mysystem(cmd, "copying chpldoc sphinx template");

  const char * moddir = astr(htmldir, "/source/modules");
  return std::string(moddir);
}

/* Call `make html` from inside sphinx project. */
void generateSphinxOutput(std::string dirpath) {
  const char * htmldir = astr(dirpath.c_str(), "/html");

  // The virtualenv activate script is at:
  //   $CHPL_HOME/third-party/chpldoc-venv/install/$CHPL_TARGET_PLATFORM/chpldoc-virtualenv/bin/activate
  const char * activate = astr(
    CHPL_HOME, "/third-party/chpldoc-venv/install/",
    CHPL_TARGET_PLATFORM, "/chpdoc-virtualenv/bin/activate");

  // Run: `. $activate && cd $htmldir && $CHPL_MAKE html`
  const char * cmd = astr(
    ". ", activate,
    " && cd ", htmldir, " && ",
    CHPL_MAKE, " html");
  mysystem(cmd, "building html output from chpldoc sphinx project");
}

std::string filenameFromMod(ModuleSymbol *mod, std::string docsFolderName) {
  std::string filename = mod->filename;

  if (mod->modTag == MOD_INTERNAL) {
    filename = "internal-modules/";
  } else if (mod ->modTag == MOD_STANDARD) {
    filename = "standard-modules/";
  } else {
    size_t location = filename.rfind("/");
    if (location != std::string::npos) {
      filename = filename.substr(0, location + 1);
    } else {
      filename = "";
    }
  }
  filename = docsFolderName + "/" + filename;
  createDocsFileFolders(filename);

  // Creates files for each top level module.
  if (fDocsTextOnly) {
    filename = filename + mod->name + ".txt";
  } else {
    filename = filename + mod->name + ".rst";
  }

  return filename;
}

std::ofstream* openFileFromMod(ModuleSymbol *mod, std::string docsFolderName) {
  std::string filename = filenameFromMod(mod, docsFolderName);
  return new std::ofstream(filename.c_str(), std::ios::out);
}
<|endoftext|>


<commit_before>#include <cstring>
#include <string>

#include "ccspec/core.h"
#include "ccspec/expectation.h"
#include "ccspec/matchers.h"

namespace spec {
namespace support {

using std::string;
using ccspec::core::describe;
using ccspec::core::it;
using ccspec::expect;
using ccspec::matchers::eq;
using ccspec::support::inspect;

auto inspect_spec = describe(".inspect", [] {
  it("returns the string value for char", [] {
    char c = 'x';
    expect(inspect(c)).to(eq("x"));
  });

  it("returns the string value for unsigned char", [] {
    unsigned char c = 'x';
    expect(inspect(c)).to(eq("x"));
  });

  it("returns the string value for bool", [] {
    bool b = true;
    expect(inspect(b)).to(eq("true"));
  });

  it("returns the value for short", [] {
    short s = 32767;
    expect(inspect(s)).to(eq("32767"));
  });

  it("returns the value for unsigned short", [] {
    unsigned short s = 65535;
    expect(inspect(s)).to(eq("65535"));
  });

  it("returns the value for int", [] {
    int i = 1234567;
    expect(inspect(i)).to(eq("1234567"));
  });

  it("returns the value for unsigned int", [] {
    unsigned int i = 1234567324;
    expect(inspect(i)).to(eq("1234567324"));
  });

  it("returns the value for long", [] {
    long l = 12345678;
    expect(inspect(l)).to(eq("12345678"));
  });

  it("returns the value for unsigned long", [] {
    unsigned long l = 12345673243;
    expect(inspect(l)).to(eq("12345673243"));
  });

  it("returns the value for long long", [] {
    long long l = 1234567890987654321;
    expect(inspect(l)).to(eq("1234567890987654321"));
  });

  it("returns the value for unsigned long long", [] {
    unsigned long long l = 5234567890987654321;
    expect(inspect(l)).to(eq("5234567890987654321"));
  });

  it("returns the value for unsigned long long", [] {
    unsigned long long l = 5234567890987654321;
    expect(inspect(l)).to(eq("5234567890987654321"));
  });

  it("returns the value for float", [] {
    float f = 3.14;
    expect(inspect(f)).to(eq("3.14"));
  });

  it("returns the value for double", [] {
    double f = 3.14159268373523;
    expect(inspect(f)).to(eq("3.14159268373523"));
  });

  it("returns the numerical value for void*", [] {
    void* p = (void*) 0xffffffff;
    expect(inspect(p)).to(eq("0xffffffff"));
  });

  it("returns the string value for const char*", [] {
    const char* s = "Hello, 世界!";
    expect(inspect(s)).to(eq("Hello, 世界!"));
  });

  it("returns the value for string", [] {
    string s = "你好, world!";
    expect(inspect(s)).to(eq("你好, world!"));
  });

  // TODO(zhangsu): add spec for the rest of the overloaded inspect function.
});

}  // namespace support
}  // namespace spec
<commit_msg>Use C++-style cast instead of C style cast<commit_after>#include <cstring>
#include <string>

#include "ccspec/core.h"
#include "ccspec/expectation.h"
#include "ccspec/matchers.h"

namespace spec {
namespace support {

using std::string;
using ccspec::core::describe;
using ccspec::core::it;
using ccspec::expect;
using ccspec::matchers::eq;
using ccspec::support::inspect;

auto inspect_spec = describe(".inspect", [] {
  it("returns the string value for char", [] {
    char c = 'x';
    expect(inspect(c)).to(eq("x"));
  });

  it("returns the string value for unsigned char", [] {
    unsigned char c = 'x';
    expect(inspect(c)).to(eq("x"));
  });

  it("returns the string value for bool", [] {
    bool b = true;
    expect(inspect(b)).to(eq("true"));
  });

  it("returns the value for short", [] {
    short s = 32767;
    expect(inspect(s)).to(eq("32767"));
  });

  it("returns the value for unsigned short", [] {
    unsigned short s = 65535;
    expect(inspect(s)).to(eq("65535"));
  });

  it("returns the value for int", [] {
    int i = 1234567;
    expect(inspect(i)).to(eq("1234567"));
  });

  it("returns the value for unsigned int", [] {
    unsigned int i = 1234567324;
    expect(inspect(i)).to(eq("1234567324"));
  });

  it("returns the value for long", [] {
    long l = 12345678;
    expect(inspect(l)).to(eq("12345678"));
  });

  it("returns the value for unsigned long", [] {
    unsigned long l = 12345673243;
    expect(inspect(l)).to(eq("12345673243"));
  });

  it("returns the value for long long", [] {
    long long l = 1234567890987654321;
    expect(inspect(l)).to(eq("1234567890987654321"));
  });

  it("returns the value for unsigned long long", [] {
    unsigned long long l = 5234567890987654321;
    expect(inspect(l)).to(eq("5234567890987654321"));
  });

  it("returns the value for unsigned long long", [] {
    unsigned long long l = 5234567890987654321;
    expect(inspect(l)).to(eq("5234567890987654321"));
  });

  it("returns the value for float", [] {
    float f = 3.14;
    expect(inspect(f)).to(eq("3.14"));
  });

  it("returns the value for double", [] {
    double f = 3.14159268373523;
    expect(inspect(f)).to(eq("3.14159268373523"));
  });

  it("returns the numerical value for void*", [] {
    void* p = reinterpret_cast<void*>(0xffffffff);
    expect(inspect(p)).to(eq("0xffffffff"));
  });

  it("returns the string value for const char*", [] {
    const char* s = "Hello, 世界!";
    expect(inspect(s)).to(eq("Hello, 世界!"));
  });

  it("returns the value for string", [] {
    string s = "你好, world!";
    expect(inspect(s)).to(eq("你好, world!"));
  });

  // TODO(zhangsu): add spec for the rest of the overloaded inspect function.
});

}  // namespace support
}  // namespace spec
<|endoftext|>


<commit_before>#pragma once

#include "alloc.hpp"
#include "value.hpp"

#include <cstddef>
#include <cstdint>
#include <stdexcept>
#include <string>
#include <unordered_map>

namespace slakken {
  /**
   * Bytecode types and functions.
   */
  namespace bytecode {
    /**
     * An opcode is like a function.
     */
    enum class opcode : uint8_t {
#include "../build/opcode.inc"
    };

    /**
     * An operand is like an argument.
     */
    union operand {
      uint32_t imm;
      std::size_t fun;
      value const* val;
    };

    /**
     * An instruction is like a function call.
     */
    struct instruction {
      opcode what;
      operand op0;
      operand op1;
    };

    /**
     * Constants from a bytecode file.
     */
    struct const_pool : std::vector<value const*>, soil {
      std::size_t root_count() const override;
      value const& root_at(std::size_t) const override;
    };

    /**
     * A mapping from function names to function identifiers.
     */
    using function_map = std::unordered_map<std::size_t, std::size_t>;

    /**
     * An error that occurs during bytecode decoding.
     */
    class decode_error : public std::runtime_error {
    public:
      using std::runtime_error::runtime_error;
    };

    /**
     * An error that occurs because there was too little data when decoding
     * bytecode.
     */
    class decode_eof_error : public decode_error {
    public:
      decode_eof_error();
    };

    /**
     * An error that occurs because a constant pool entry had an invalid type.
     */
    class decode_const_type_error : public decode_error {
    public:
      decode_const_type_error();
    };

    /**
     * An error that occurs because a constant pool lookup was out of range.
     */
    class decode_const_range_error : public decode_error {
    public:
      decode_const_range_error();
    };

    /**
     * An error that occurs because an instruction had an invalid opcode.
     */
    class decode_opcode_error : public decode_error {
    public:
      decode_opcode_error();
    };

    /**
     * Decode bytecode constant pool.
     *
     * \relate const_pool
     *
     * \exception decode_error on invalid input.
     */
    void decode_const_pool(const_pool&, alloc&, char const*, std::size_t);

    /**
     * Decode bytecode instructions.
     *
     * \exception decode_error on invalid input.
     */
    std::vector<instruction> decode_instructions(function_map const&, const_pool const&, char const*, std::size_t);
  }
}
<commit_msg>Use correct key type in function_map<commit_after>#pragma once

#include "alloc.hpp"
#include "value.hpp"

#include <cstddef>
#include <cstdint>
#include <stdexcept>
#include <string>
#include <unordered_map>

namespace slakken {
  /**
   * Bytecode types and functions.
   */
  namespace bytecode {
    /**
     * An opcode is like a function.
     */
    enum class opcode : uint8_t {
#include "../build/opcode.inc"
    };

    /**
     * An operand is like an argument.
     */
    union operand {
      uint32_t imm;
      std::size_t fun;
      value const* val;
    };

    /**
     * An instruction is like a function call.
     */
    struct instruction {
      opcode what;
      operand op0;
      operand op1;
    };

    /**
     * Constants from a bytecode file.
     */
    struct const_pool : std::vector<value const*>, soil {
      std::size_t root_count() const override;
      value const& root_at(std::size_t) const override;
    };

    /**
     * A mapping from function names to function identifiers.
     */
    using function_map = std::unordered_map<std::uint32_t, std::size_t>;

    /**
     * An error that occurs during bytecode decoding.
     */
    class decode_error : public std::runtime_error {
    public:
      using std::runtime_error::runtime_error;
    };

    /**
     * An error that occurs because there was too little data when decoding
     * bytecode.
     */
    class decode_eof_error : public decode_error {
    public:
      decode_eof_error();
    };

    /**
     * An error that occurs because a constant pool entry had an invalid type.
     */
    class decode_const_type_error : public decode_error {
    public:
      decode_const_type_error();
    };

    /**
     * An error that occurs because a constant pool lookup was out of range.
     */
    class decode_const_range_error : public decode_error {
    public:
      decode_const_range_error();
    };

    /**
     * An error that occurs because an instruction had an invalid opcode.
     */
    class decode_opcode_error : public decode_error {
    public:
      decode_opcode_error();
    };

    /**
     * Decode bytecode constant pool.
     *
     * \relate const_pool
     *
     * \exception decode_error on invalid input.
     */
    void decode_const_pool(const_pool&, alloc&, char const*, std::size_t);

    /**
     * Decode bytecode instructions.
     *
     * \exception decode_error on invalid input.
     */
    std::vector<instruction> decode_instructions(function_map const&, const_pool const&, char const*, std::size_t);
  }
}
<|endoftext|>


<commit_before>#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cassert>
#include "phIO.h"
#include "phstream.h" //for makeRStream and makeGRStream
#include "syncio.h"
#include "posixio.h"
#include "streamio.h"

int main(int argc, char* argv[]) {
  MPI_Init(&argc,&argv);
  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  int size;
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  if( argc != 2 ) {
    fprintf(stderr, "Usage: %s <numSyncFiles>\n",argv[0]);
    MPI_Finalize();
    return 1;
  }
  const char* phrase = "number of fishes";
  const char* type = "double";
  const char* iotype = "binary";
  int zero = 0;
  int one = 1;
  int numFish = 0;
  double fishWeight = 1.23;
  int nfiles = atoi(argv[1]);
  int ppf = size/nfiles;
  const char* filename[2] = {"water-dat.", "water.dat."};
  rstream rs = makeRStream();
  grstream grs = makeGRStream();
  phio_fp file[3];
  syncio_setup_write(nfiles, one, ppf, &(file[0]));
  posixio_setup(&(file[1]), 'w');
  streamio_setup_write(&(file[2]), rs);
  for(int i=0; i<2; i++) {
    phio_openfile(filename[i], file[i]);
    phio_writeheader(file[i], phrase, &zero, &one, &zero, type, iotype);
    phio_writedatablock(file[i], phrase, &fishWeight, &zero, type, iotype);
    phio_closefile(file[i]);
  }
  syncio_setup_read(nfiles, &(file[0]));
  posixio_setup(&(file[1]), 'r');
  streamio_read_r(&(file[2]), rs);
  for(int i=0; i<2; i++) {
    phio_openfile(filename[i], file[i]);
    phio_readheader(file[i], phrase, &numFish, &one, type, iotype);
    assert(!numFish);
    phio_readdatablock(file[i], phrase, &fishWeight, &numFish, type, iotype);
    assert(fishWeight == 1.23);
    phio_closefile(file[i]);
  }
  MPI_Finalize();
  return 0;
}
<commit_msg>common: loop iteration limit was off by one<commit_after>#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cassert>
#include "phIO.h"
#include "phstream.h" //for makeRStream and makeGRStream
#include "syncio.h"
#include "posixio.h"
#include "streamio.h"

int main(int argc, char* argv[]) {
  MPI_Init(&argc,&argv);
  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  int size;
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  if( argc != 2 ) {
    fprintf(stderr, "Usage: %s <numSyncFiles>\n",argv[0]);
    MPI_Finalize();
    return 1;
  }
  const char* phrase = "number of fishes";
  const char* type = "double";
  const char* iotype = "binary";
  int zero = 0;
  int one = 1;
  int numFish = 0;
  double fishWeight = 1.23;
  int nfiles = atoi(argv[1]);
  int ppf = size/nfiles;
  const char* filename[2] = {"water-dat.", "water.dat."};
  rstream rs = makeRStream();
  grstream grs = makeGRStream();
  phio_fp file[3];
  syncio_setup_write(nfiles, one, ppf, &(file[0]));
  posixio_setup(&(file[1]), 'w');
  streamio_setup_write(&(file[2]), rs);
  for(int i=0; i<3; i++) {
    phio_openfile(filename[i], file[i]);
    phio_writeheader(file[i], phrase, &zero, &one, &zero, type, iotype);
    phio_writedatablock(file[i], phrase, &fishWeight, &zero, type, iotype);
    phio_closefile(file[i]);
  }
  syncio_setup_read(nfiles, &(file[0]));
  posixio_setup(&(file[1]), 'r');
  streamio_read_r(&(file[2]), rs);
  for(int i=0; i<3; i++) {
    phio_openfile(filename[i], file[i]);
    phio_readheader(file[i], phrase, &numFish, &one, type, iotype);
    assert(!numFish);
    phio_readdatablock(file[i], phrase, &fishWeight, &numFish, type, iotype);
    assert(fishWeight == 1.23);
    phio_closefile(file[i]);
  }
  MPI_Finalize();
  return 0;
}
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "objmeshfilereader.h"

// appleseed.foundation headers.
#include "foundation/core/exceptions/exceptionioerror.h"
#include "foundation/core/exceptions/exceptionnotimplemented.h"
#include "foundation/math/vector.h"
#include "foundation/mesh/imeshbuilder.h"
#include "foundation/mesh/objmeshfilelexer.h"
#include "foundation/utility/memory.h"

// Standard headers.
#include <cassert>
#include <vector>

using namespace std;

namespace foundation
{

//
// OBJMeshFileReader class implementation.
//

namespace
{
    const size_t Undefined = ~0;
}

struct OBJMeshFileReader::Impl
{
    const int               m_options;
    IMeshBuilder&           m_builder;
    OBJMeshFileLexer        m_lexer;
    bool                    m_inside_mesh_def;          // currently inside a mesh definition?
    string                  m_mesh_name;

    // Features defined in the file.
    vector<Vector3d>        m_vertices;
    vector<Vector2d>        m_tex_coords;
    vector<Vector3d>        m_normals;

    // Mappings between internal indices and mesh indices.
    vector<size_t>          m_vertex_index_mapping;
    vector<size_t>          m_tex_coord_index_mapping;
    vector<size_t>          m_normal_index_mapping;

    // Temporary vectors for collecting indices while parsing face statements.
    vector<size_t>          m_face_vertex_indices;
    vector<size_t>          m_face_tex_coord_indices;
    vector<size_t>          m_face_normal_indices;

    // Constructor.
    Impl(
        const int           options,
        IMeshBuilder&       builder)
      : m_options(options)
      , m_builder(builder)
      , m_lexer(
            (options & FavorSpeedOverPrecision)
                ? OBJMeshFileLexer::Fast
                : OBJMeshFileLexer::Precise)
      , m_inside_mesh_def(false)
    {
    }

    // Close the input file and throw an ExceptionParseError exception.
    void parse_error()
    {
        const size_t line_number = m_lexer.get_line_number();

        m_lexer.close();

        throw ExceptionParseError(line_number);
    }

    void parse_file()
    {
        while (true)
        {
            m_lexer.eat_blanks();

            // Handle end of file.
            if (m_lexer.is_eof())
                break;

            // Handle empty lines.
            if (m_lexer.is_eol())
            {
                m_lexer.accept_newline();
                continue;
            }

            const char* keyword;
            size_t keyword_length;

            m_lexer.accept_string(&keyword, &keyword_length);

            if (keyword_length == 1)
            {
                switch (keyword[0])
                {
                  case 'f':
                    parse_f_statement();
                    break;

                  case 'g':
                  case 'o':
                    parse_o_g_statement();
                    break;

                  case 'v':
                    parse_v_statement();
                    break;

                  default:
                    // Ignore unknown or unhandled statements.
                    m_lexer.eat_line();
                    continue;
                }
            }
            else if (keyword_length == 2)
            {
                switch (keyword[0] * 256 + keyword[1])
                {
                  case 'v' * 256 + 'n':
                    parse_vn_statement();
                    break;

                  case 'v' * 256 + 't':
                    parse_vt_statement();
                    break;

                  default:
                    // Ignore unknown or unhandled statements.
                    m_lexer.eat_line();
                    continue;
                }
            }
            else
            {
                // Ignore unknown or unhandled statements.
                m_lexer.eat_line();
                continue;
            }

            m_lexer.eat_blanks();
            m_lexer.accept_newline();
        }

        // End the definition of the last object.
        if (m_inside_mesh_def)
            m_builder.end_mesh();
    }

    // Convert 1-based indices (including negative indices) to 0-based indices.
    size_t fix_index(const long index, const size_t count)
    {
        if (index > 0)
        {
            const size_t i = static_cast<size_t>(index);
            if (i > count)
                parse_error();
            return i - 1;
        }
        else if (index < 0)
        {
            const size_t i = static_cast<size_t>(-index);
            if (i > count)
                parse_error();
            return count - i;
        }
        else
        {
            parse_error();
            return 0;       // keep the compiler happy
        }
    }

    void parse_f_statement()
    {
        clear_keep_memory(m_face_vertex_indices);
        clear_keep_memory(m_face_tex_coord_indices);
        clear_keep_memory(m_face_normal_indices);

        while (true)
        {
            m_lexer.eat_blanks();

            if (m_lexer.is_eol())
                break;

            //
            // Recognized (epsilon)
            // Accept n(/((n(/n)?)|(/n)))?
            //

            {
                const long n = m_lexer.accept_long();
                const size_t v = fix_index(n, m_vertices.size());
                m_face_vertex_indices.push_back(v);
            }

            //
            // Recognized n
            // Accept (/((n(/n)?)|(/n)))?
            //

            {
                const unsigned char c = m_lexer.get_char();
                if (m_lexer.is_space(c))
                    continue;
                else if (c == '/')
                    m_lexer.next_char();
                else parse_error();
            }

            //
            // Recognized n/
            // Accept (n(/n)?)|(/n)
            //

            {
                const unsigned char c = m_lexer.get_char();
                if (c == '/')
                {
                    m_lexer.next_char();
                    goto terminate;
                }
                else
                {
                    const long n = m_lexer.accept_long();
                    const size_t vt = fix_index(n, m_tex_coords.size());
                    m_face_tex_coord_indices.push_back(vt);
                }
            }

            //
            // Recognized n/n
            // Accept (/n)?
            //

            {
                const unsigned char c = m_lexer.get_char();
                if (m_lexer.is_space(c))
                    continue;
                else if (c == '/')
                    m_lexer.next_char();
                else parse_error();
            }

          terminate:

            //
            // Recognized n//
            // Accept n
            //

            {
                const long n = m_lexer.accept_long();
                const size_t vn = fix_index(n, m_normals.size());
                m_face_normal_indices.push_back(vn);
            }
        }

        // Check whether the face is well-formed.
        const size_t vc = m_face_vertex_indices.size();
        const size_t tc = m_face_tex_coord_indices.size();
        const size_t nc = m_face_normal_indices.size();
        const bool well_formed =
                vc >= 3
            && (tc == 0 || tc == vc)
            && (nc == 0 || nc == vc);

        if (well_formed)
        {
            // The face is well-formed, insert it into the mesh.
            insert_face_into_mesh();
        }
        else
        {
            // The face is ill-formed, ignore it or abort parsing.
            if (m_options & StopOnInvalidFaceDef)
                throw ExceptionInvalidFaceDef(m_lexer.get_line_number());
        }
    }

    static void translate_indices(
        vector<size_t>&         indices,
        const vector<size_t>&   mapping)
    {
        for (size_t i = 0; i < indices.size(); ++i)
            indices[i] = mapping[indices[i]];
    }

    void insert_vertices_into_mesh()
    {
        const size_t face_vertex_index_count = m_face_vertex_indices.size();

        for (size_t i = 0; i < face_vertex_index_count; ++i)
        {
            const size_t vertex_index = m_face_vertex_indices[i];
            ensure_minimum_size(m_vertex_index_mapping, vertex_index + 1, Undefined);
            if (m_vertex_index_mapping[vertex_index] == Undefined)
                m_vertex_index_mapping[vertex_index] = m_builder.push_vertex(m_vertices[vertex_index]);
        }
    }

    void insert_vertex_normals_into_mesh()
    {
        const size_t face_normal_index_count = m_face_normal_indices.size();

        for (size_t i = 0; i < face_normal_index_count; ++i)
        {
            const size_t normal_index = m_face_normal_indices[i];
            ensure_minimum_size(m_normal_index_mapping, normal_index + 1, Undefined);
            if (m_normal_index_mapping[normal_index] == Undefined)
                m_normal_index_mapping[normal_index] = m_builder.push_vertex_normal(m_normals[normal_index]);
        }
    }

    void insert_tex_coords_into_mesh()
    {
        const size_t face_tex_coord_index_count = m_face_tex_coord_indices.size();

        for (size_t i = 0; i < face_tex_coord_index_count; ++i)
        {
            const size_t tex_coord_index = m_face_tex_coord_indices[i];
            ensure_minimum_size(m_tex_coord_index_mapping, tex_coord_index + 1, Undefined);
            if (m_tex_coord_index_mapping[tex_coord_index] == Undefined)
                m_tex_coord_index_mapping[tex_coord_index] = m_builder.push_tex_coords(m_tex_coords[tex_coord_index]);
        }
    }

    void insert_face_into_mesh()
    {
        if (!m_inside_mesh_def)
        {
            // Begin the definition of the new mesh.
            m_builder.begin_mesh(m_mesh_name);
            m_inside_mesh_def = true;
        }

        // Insert the features into the mesh, updating index mappings as necessary.
        insert_vertices_into_mesh();
        insert_vertex_normals_into_mesh();
        insert_tex_coords_into_mesh();

        // Translate feature indices from internal space to mesh space.
        translate_indices(m_face_vertex_indices, m_vertex_index_mapping);
        translate_indices(m_face_normal_indices, m_normal_index_mapping);
        translate_indices(m_face_tex_coord_indices, m_tex_coord_index_mapping);

        const size_t n = m_face_vertex_indices.size();

        // Begin defining a new face.
        m_builder.begin_face(n);

        // Set face vertices.
        m_builder.set_face_vertices(&m_face_vertex_indices.front());

        // Set face vertex normals (if any).
        if (m_face_normal_indices.size() == n)
            m_builder.set_face_vertex_normals(&m_face_normal_indices.front());

        // Set face vertex texture coordinates (if any).
        if (m_face_tex_coord_indices.size() == n)
            m_builder.set_face_vertex_tex_coords(&m_face_tex_coord_indices.front());

        // End defining the face.
        m_builder.end_face();
    }

    void parse_o_g_statement()
    {
        m_lexer.eat_blanks();

        // Retrieve the name of the upcoming mesh.
        const string upcoming_mesh_name = parse_mesh_name();

        // Start a new mesh only if the name of the object or group actually changes.
        if (upcoming_mesh_name != m_mesh_name)
        {
            // End the current mesh.
            if (m_inside_mesh_def)
            {
                m_builder.end_mesh();
                m_inside_mesh_def = false;
            }

            clear_keep_memory(m_vertex_index_mapping);
            clear_keep_memory(m_tex_coord_index_mapping);
            clear_keep_memory(m_normal_index_mapping);

            m_mesh_name = upcoming_mesh_name;
        }
    }

    string parse_mesh_name()
    {
        string mesh_name;

        while (!m_lexer.is_eol())
        {
            const char* token;
            size_t token_length;

            m_lexer.accept_string(&token, &token_length);
            m_lexer.eat_blanks();

            if (!mesh_name.empty())
                mesh_name += ' ';

            mesh_name.append(token, token_length);
        }

        return mesh_name;
    }

    void parse_v_statement()
    {
        Vector3d v;

        m_lexer.eat_blanks();
        v.x = m_lexer.accept_double();

        m_lexer.eat_blanks();
        v.y = m_lexer.accept_double();

        m_lexer.eat_blanks();
        v.z = m_lexer.accept_double();

        m_lexer.eat_blanks();

        if (!m_lexer.is_eol())
            m_lexer.accept_double();

        m_vertices.push_back(v);
    }

    void parse_vt_statement()
    {
        Vector2d v;

        m_lexer.eat_blanks();
        v.x = m_lexer.accept_double();

        m_lexer.eat_blanks();
        v.y = m_lexer.accept_double();

        m_lexer.eat_blanks();
        if (!m_lexer.is_eol())
            m_lexer.accept_double();

        m_tex_coords.push_back(v);
    }

    void parse_vn_statement()
    {
        Vector3d n;

        m_lexer.eat_blanks();
        n.x = m_lexer.accept_double();

        m_lexer.eat_blanks();
        n.y = m_lexer.accept_double();

        m_lexer.eat_blanks();
        n.z = m_lexer.accept_double();

        n = normalize(n);

        m_normals.push_back(n);
    }
};

OBJMeshFileReader::OBJMeshFileReader(
    const string&   filename,
    const int       options)
  : m_filename(filename)
  , m_options(options)
{
}

void OBJMeshFileReader::read(IMeshBuilder& builder)
{
    Impl impl(m_options, builder);

    // Open the input file.
    if (!impl.m_lexer.open(m_filename))
        throw ExceptionIOError();

    // Parse the file.
    impl.parse_file();

    // Close the input file.
    impl.m_lexer.close();
}

}   // namespace foundation
<commit_msg>the OBJ mesh file reader now accepts face definitions of the form n// where n is a vertex index.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "objmeshfilereader.h"

// appleseed.foundation headers.
#include "foundation/core/exceptions/exceptionioerror.h"
#include "foundation/core/exceptions/exceptionnotimplemented.h"
#include "foundation/math/vector.h"
#include "foundation/mesh/imeshbuilder.h"
#include "foundation/mesh/objmeshfilelexer.h"
#include "foundation/utility/memory.h"

// Standard headers.
#include <cassert>
#include <vector>

using namespace std;

namespace foundation
{

//
// OBJMeshFileReader class implementation.
//

namespace
{
    const size_t Undefined = ~0;
}

struct OBJMeshFileReader::Impl
{
    const int               m_options;
    IMeshBuilder&           m_builder;
    OBJMeshFileLexer        m_lexer;
    bool                    m_inside_mesh_def;          // currently inside a mesh definition?
    string                  m_mesh_name;

    // Features defined in the file.
    vector<Vector3d>        m_vertices;
    vector<Vector2d>        m_tex_coords;
    vector<Vector3d>        m_normals;

    // Mappings between internal indices and mesh indices.
    vector<size_t>          m_vertex_index_mapping;
    vector<size_t>          m_tex_coord_index_mapping;
    vector<size_t>          m_normal_index_mapping;

    // Temporary vectors for collecting indices while parsing face statements.
    vector<size_t>          m_face_vertex_indices;
    vector<size_t>          m_face_tex_coord_indices;
    vector<size_t>          m_face_normal_indices;

    // Constructor.
    Impl(
        const int           options,
        IMeshBuilder&       builder)
      : m_options(options)
      , m_builder(builder)
      , m_lexer(
            (options & FavorSpeedOverPrecision)
                ? OBJMeshFileLexer::Fast
                : OBJMeshFileLexer::Precise)
      , m_inside_mesh_def(false)
    {
    }

    // Close the input file and throw an ExceptionParseError exception.
    void parse_error()
    {
        const size_t line_number = m_lexer.get_line_number();

        m_lexer.close();

        throw ExceptionParseError(line_number);
    }

    void parse_file()
    {
        while (true)
        {
            m_lexer.eat_blanks();

            // Handle end of file.
            if (m_lexer.is_eof())
                break;

            // Handle empty lines.
            if (m_lexer.is_eol())
            {
                m_lexer.accept_newline();
                continue;
            }

            const char* keyword;
            size_t keyword_length;

            m_lexer.accept_string(&keyword, &keyword_length);

            if (keyword_length == 1)
            {
                switch (keyword[0])
                {
                  case 'f':
                    parse_f_statement();
                    break;

                  case 'g':
                  case 'o':
                    parse_o_g_statement();
                    break;

                  case 'v':
                    parse_v_statement();
                    break;

                  default:
                    // Ignore unknown or unhandled statements.
                    m_lexer.eat_line();
                    continue;
                }
            }
            else if (keyword_length == 2)
            {
                switch (keyword[0] * 256 + keyword[1])
                {
                  case 'v' * 256 + 'n':
                    parse_vn_statement();
                    break;

                  case 'v' * 256 + 't':
                    parse_vt_statement();
                    break;

                  default:
                    // Ignore unknown or unhandled statements.
                    m_lexer.eat_line();
                    continue;
                }
            }
            else
            {
                // Ignore unknown or unhandled statements.
                m_lexer.eat_line();
                continue;
            }

            m_lexer.eat_blanks();
            m_lexer.accept_newline();
        }

        // End the definition of the last object.
        if (m_inside_mesh_def)
            m_builder.end_mesh();
    }

    // Convert 1-based indices (including negative indices) to 0-based indices.
    size_t fix_index(const long index, const size_t count)
    {
        if (index > 0)
        {
            const size_t i = static_cast<size_t>(index);
            if (i > count)
                parse_error();
            return i - 1;
        }
        else if (index < 0)
        {
            const size_t i = static_cast<size_t>(-index);
            if (i > count)
                parse_error();
            return count - i;
        }
        else
        {
            parse_error();
            return 0;       // keep the compiler happy
        }
    }

    void parse_f_statement()
    {
        clear_keep_memory(m_face_vertex_indices);
        clear_keep_memory(m_face_tex_coord_indices);
        clear_keep_memory(m_face_normal_indices);

        while (true)
        {
            m_lexer.eat_blanks();

            if (m_lexer.is_eol())
                break;

            //
            // Recognized (epsilon)
            // Accept n(/((n(/n)?)|(/n)))?
            //

            {
                const long n = m_lexer.accept_long();
                const size_t v = fix_index(n, m_vertices.size());
                m_face_vertex_indices.push_back(v);
            }

            //
            // Recognized n
            // Accept (/((n(/n)?)|(/n)))?
            //

            {
                const unsigned char c = m_lexer.get_char();
                if (m_lexer.is_space(c))
                    continue;
                else if (c == '/')
                    m_lexer.next_char();
                else parse_error();
            }

            //
            // Recognized n/
            // Accept (n(/n)?)|(/n)
            //

            {
                const unsigned char c = m_lexer.get_char();
                if (c == '/')
                {
                    m_lexer.next_char();
                    goto terminate;
                }
                else
                {
                    const long n = m_lexer.accept_long();
                    const size_t vt = fix_index(n, m_tex_coords.size());
                    m_face_tex_coord_indices.push_back(vt);
                }
            }

            //
            // Recognized n/n
            // Accept (/n)?
            //

            {
                const unsigned char c = m_lexer.get_char();
                if (m_lexer.is_space(c))
                    continue;
                else if (c == '/')
                    m_lexer.next_char();
                else parse_error();
            }

          terminate:

            //
            // Recognized n//
            // Accept n
            //

            {
                const unsigned char c = m_lexer.get_char();
                if (m_lexer.is_space(c))
                    continue;
                else
                {
                    const long n = m_lexer.accept_long();
                    const size_t vn = fix_index(n, m_normals.size());
                    m_face_normal_indices.push_back(vn);
                }
            }
        }

        // Check whether the face is well-formed.
        const size_t vc = m_face_vertex_indices.size();
        const size_t tc = m_face_tex_coord_indices.size();
        const size_t nc = m_face_normal_indices.size();
        const bool well_formed =
                vc >= 3
            && (tc == 0 || tc == vc)
            && (nc == 0 || nc == vc);

        if (well_formed)
        {
            // The face is well-formed, insert it into the mesh.
            insert_face_into_mesh();
        }
        else
        {
            // The face is ill-formed, ignore it or abort parsing.
            if (m_options & StopOnInvalidFaceDef)
                throw ExceptionInvalidFaceDef(m_lexer.get_line_number());
        }
    }

    static void translate_indices(
        vector<size_t>&         indices,
        const vector<size_t>&   mapping)
    {
        for (size_t i = 0; i < indices.size(); ++i)
            indices[i] = mapping[indices[i]];
    }

    void insert_vertices_into_mesh()
    {
        const size_t face_vertex_index_count = m_face_vertex_indices.size();

        for (size_t i = 0; i < face_vertex_index_count; ++i)
        {
            const size_t vertex_index = m_face_vertex_indices[i];
            ensure_minimum_size(m_vertex_index_mapping, vertex_index + 1, Undefined);
            if (m_vertex_index_mapping[vertex_index] == Undefined)
                m_vertex_index_mapping[vertex_index] = m_builder.push_vertex(m_vertices[vertex_index]);
        }
    }

    void insert_vertex_normals_into_mesh()
    {
        const size_t face_normal_index_count = m_face_normal_indices.size();

        for (size_t i = 0; i < face_normal_index_count; ++i)
        {
            const size_t normal_index = m_face_normal_indices[i];
            ensure_minimum_size(m_normal_index_mapping, normal_index + 1, Undefined);
            if (m_normal_index_mapping[normal_index] == Undefined)
                m_normal_index_mapping[normal_index] = m_builder.push_vertex_normal(m_normals[normal_index]);
        }
    }

    void insert_tex_coords_into_mesh()
    {
        const size_t face_tex_coord_index_count = m_face_tex_coord_indices.size();

        for (size_t i = 0; i < face_tex_coord_index_count; ++i)
        {
            const size_t tex_coord_index = m_face_tex_coord_indices[i];
            ensure_minimum_size(m_tex_coord_index_mapping, tex_coord_index + 1, Undefined);
            if (m_tex_coord_index_mapping[tex_coord_index] == Undefined)
                m_tex_coord_index_mapping[tex_coord_index] = m_builder.push_tex_coords(m_tex_coords[tex_coord_index]);
        }
    }

    void insert_face_into_mesh()
    {
        if (!m_inside_mesh_def)
        {
            // Begin the definition of the new mesh.
            m_builder.begin_mesh(m_mesh_name);
            m_inside_mesh_def = true;
        }

        // Insert the features into the mesh, updating index mappings as necessary.
        insert_vertices_into_mesh();
        insert_vertex_normals_into_mesh();
        insert_tex_coords_into_mesh();

        // Translate feature indices from internal space to mesh space.
        translate_indices(m_face_vertex_indices, m_vertex_index_mapping);
        translate_indices(m_face_normal_indices, m_normal_index_mapping);
        translate_indices(m_face_tex_coord_indices, m_tex_coord_index_mapping);

        const size_t n = m_face_vertex_indices.size();

        // Begin defining a new face.
        m_builder.begin_face(n);

        // Set face vertices.
        m_builder.set_face_vertices(&m_face_vertex_indices.front());

        // Set face vertex normals (if any).
        if (m_face_normal_indices.size() == n)
            m_builder.set_face_vertex_normals(&m_face_normal_indices.front());

        // Set face vertex texture coordinates (if any).
        if (m_face_tex_coord_indices.size() == n)
            m_builder.set_face_vertex_tex_coords(&m_face_tex_coord_indices.front());

        // End defining the face.
        m_builder.end_face();
    }

    void parse_o_g_statement()
    {
        m_lexer.eat_blanks();

        // Retrieve the name of the upcoming mesh.
        const string upcoming_mesh_name = parse_mesh_name();

        // Start a new mesh only if the name of the object or group actually changes.
        if (upcoming_mesh_name != m_mesh_name)
        {
            // End the current mesh.
            if (m_inside_mesh_def)
            {
                m_builder.end_mesh();
                m_inside_mesh_def = false;
            }

            clear_keep_memory(m_vertex_index_mapping);
            clear_keep_memory(m_tex_coord_index_mapping);
            clear_keep_memory(m_normal_index_mapping);

            m_mesh_name = upcoming_mesh_name;
        }
    }

    string parse_mesh_name()
    {
        string mesh_name;

        while (!m_lexer.is_eol())
        {
            const char* token;
            size_t token_length;

            m_lexer.accept_string(&token, &token_length);
            m_lexer.eat_blanks();

            if (!mesh_name.empty())
                mesh_name += ' ';

            mesh_name.append(token, token_length);
        }

        return mesh_name;
    }

    void parse_v_statement()
    {
        Vector3d v;

        m_lexer.eat_blanks();
        v.x = m_lexer.accept_double();

        m_lexer.eat_blanks();
        v.y = m_lexer.accept_double();

        m_lexer.eat_blanks();
        v.z = m_lexer.accept_double();

        m_lexer.eat_blanks();

        if (!m_lexer.is_eol())
            m_lexer.accept_double();

        m_vertices.push_back(v);
    }

    void parse_vt_statement()
    {
        Vector2d v;

        m_lexer.eat_blanks();
        v.x = m_lexer.accept_double();

        m_lexer.eat_blanks();
        v.y = m_lexer.accept_double();

        m_lexer.eat_blanks();
        if (!m_lexer.is_eol())
            m_lexer.accept_double();

        m_tex_coords.push_back(v);
    }

    void parse_vn_statement()
    {
        Vector3d n;

        m_lexer.eat_blanks();
        n.x = m_lexer.accept_double();

        m_lexer.eat_blanks();
        n.y = m_lexer.accept_double();

        m_lexer.eat_blanks();
        n.z = m_lexer.accept_double();

        n = normalize(n);

        m_normals.push_back(n);
    }
};

OBJMeshFileReader::OBJMeshFileReader(
    const string&   filename,
    const int       options)
  : m_filename(filename)
  , m_options(options)
{
}

void OBJMeshFileReader::read(IMeshBuilder& builder)
{
    Impl impl(m_options, builder);

    // Open the input file.
    if (!impl.m_lexer.open(m_filename))
        throw ExceptionIOError();

    // Parse the file.
    impl.parse_file();

    // Close the input file.
    impl.m_lexer.close();
}

}   // namespace foundation
<|endoftext|>


<commit_before>#ifndef TESTERDRIVER_H
#define TESTERDRIVER_H

#include <iostream>
#include <string.h>
using namespace std;
#include "wrapperregdriver.h"
#include "TesterWrapper.h"

// register driver for the Tester platform, using the Chisel-generated C++ model to
// interface with the accelerator model
// note that TesterWrapper.h must be generated for each new accelerator, it is the
// model header not just for the wrapper, but the entire system (wrapper+accel)

class TesterRegDriver : public WrapperRegDriver {
public:
  TesterRegDriver() {m_freePtr = 0;}

  virtual void attach(const char * name) {
    m_inst = new TesterWrapper_t();
    // get # words in the memory
    m_memWords = m_inst->TesterWrapper__mem.length();
    // initialize and reset the model
    m_inst->init();
    reset();
    m_regCount = m_inst->TesterWrapper__io_regFileIF_regCount.to_ulong();
  }

  virtual void detach() { delete m_inst; }

  virtual void copyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferHostToAccel(hostBuffer, accelBuffer, numBytes);
    else {
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy((void *)&tmp[startDiff], hostBuffer, numBytes);
      // write containing block back to accel memory
      alignedCopyBufferHostToAccel((void *)tmp, (void *)alignedBase, alignedSize);
      delete [] tmp;
    }
  }

  virtual void copyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferAccelToHost(hostBuffer, accelBuffer, numBytes);
    else {
      // implement unaligned accel-to-host
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy(hostBuffer, (void *)&tmp[startDiff],numBytes);
      delete [] tmp;
    }
  }

  virtual void * allocAccelBuffer(unsigned int numBytes) {
    // all this assumes allocation and mem word size of 8 bytes
    // round requested size to nearest multiple of 8
    unsigned int actualAllocSize = numBytes + 7 / 8 * 8;
    void * accelBuf = (void *) m_freePtr;
    // update free pointer and sanity check
    m_freePtr += actualAllocSize;
    if(m_freePtr > m_memWords * 8)
      throw "Not enough memory in allocAccelBuffer";

    return accelBuf;
  }

  // register access methods for the platform wrapper
  virtual void writeReg(unsigned int regInd, AccelReg regValue) {
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_writeData = regValue;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write  = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    step();
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write = 0;
    step(5);  // extra delay on write completion to be realistic
  }

  virtual AccelReg readReg(unsigned int regInd) {
    AccelReg ret;

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 1;
    step(); // don't actually need 1 cycle, regfile reads are combinational

    if(!m_inst->TesterWrapper__io_regFileIF_readData_valid.to_bool())
      throw "Could not read register";

    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 0;

    ret = m_inst->TesterWrapper__io_regFileIF_readData_bits.to_ulong();

    step(5);  // extra delay on read completion to be realistic

    return ret;
  }

  void printAllRegs() {
    for(unsigned int i = 0; i < m_regCount; i++)  {
        AccelReg val = readReg(i);
        cout << "Reg " << i << " = " << val << " (0x" << hex << val << dec << ")" << endl;
      }

  }

protected:
  TesterWrapper_t * m_inst;
  unsigned int m_memWords;
  unsigned int m_regCount;
  uint64_t m_freePtr;

  void reset() {
    m_inst->clock(1);
    m_inst->clock(0);
    // Chisel c++ backend requires this workaround to get out the correct values
    m_inst->clock_lo(0);
  }

  void step(int n = 1) {
    for(int i = 0; i < n; i++) {
      m_inst->clock(0);
      // Chisel c++ backend requires this workaround to get out the correct values
      m_inst->clock_lo(0);
    }
  }

  void memWrite(uint64_t addr, uint64_t value) {
    m_inst->TesterWrapper__io_memAddr = addr;
    m_inst->TesterWrapper__io_memWriteData = value;
    m_inst->TesterWrapper__io_memWriteEn = 1;
    step();
    m_inst->TesterWrapper__io_memWriteEn = 0;
  }

  uint64_t memRead(uint64_t addr) {
    m_inst->TesterWrapper__io_memAddr = addr;
    step();
    uint64_t ret = m_inst->TesterWrapper__io_memReadData[0];
    return ret;
  }

  // "aligned" copy functions, where accel ptr start and size are guaranteed to be 8-aligned
  void alignedCopyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t * host_buf = (uint64_t *) hostBuffer;
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    for(unsigned int i = 0; i < numBytes/8; i++)
        memWrite(accelBufBase + i*8, host_buf[i]);
  }

  void alignedCopyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    uint64_t * readBuf = (uint64_t *) hostBuffer;
    for(unsigned int i = 0; i < numBytes/8; i++)
      readBuf[i] = memRead(accelBufBase + i*8);
  }
};

#endif
<commit_msg>reg read/write debug support in TesterDriver<commit_after>#ifndef TESTERDRIVER_H
#define TESTERDRIVER_H

#include <iostream>
#include <string.h>
using namespace std;
#include "wrapperregdriver.h"
#include "TesterWrapper.h"

// uncomment the second line here to enable verbose reg read/writes
//#define __TESTERDRIVER_DEBUG(x) (cout << x)
#define __TESTERDRIVER_DEBUG(x) (0)

// register driver for the Tester platform, using the Chisel-generated C++ model to
// interface with the accelerator model
// note that TesterWrapper.h must be generated for each new accelerator, it is the
// model header not just for the wrapper, but the entire system (wrapper+accel)

class TesterRegDriver : public WrapperRegDriver {
public:
  TesterRegDriver() {m_freePtr = 0;}

  virtual void attach(const char * name) {
    m_inst = new TesterWrapper_t();
    // get # words in the memory
    m_memWords = m_inst->TesterWrapper__mem.length();
    // initialize and reset the model
    m_inst->init();
    reset();
    m_regCount = m_inst->TesterWrapper__io_regFileIF_regCount.to_ulong();
  }

  virtual void detach() { delete m_inst; }

  virtual void copyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferHostToAccel(hostBuffer, accelBuffer, numBytes);
    else {
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy((void *)&tmp[startDiff], hostBuffer, numBytes);
      // write containing block back to accel memory
      alignedCopyBufferHostToAccel((void *)tmp, (void *)alignedBase, alignedSize);
      delete [] tmp;
    }
  }

  virtual void copyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferAccelToHost(hostBuffer, accelBuffer, numBytes);
    else {
      // implement unaligned accel-to-host
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy(hostBuffer, (void *)&tmp[startDiff],numBytes);
      delete [] tmp;
    }
  }

  virtual void * allocAccelBuffer(unsigned int numBytes) {
    // all this assumes allocation and mem word size of 8 bytes
    // round requested size to nearest multiple of 8
    unsigned int actualAllocSize = numBytes + 7 / 8 * 8;
    void * accelBuf = (void *) m_freePtr;
    // update free pointer and sanity check
    m_freePtr += actualAllocSize;
    if(m_freePtr > m_memWords * 8)
      throw "Not enough memory in allocAccelBuffer";

    return accelBuf;
  }

  // register access methods for the platform wrapper
  virtual void writeReg(unsigned int regInd, AccelReg regValue) {
    __TESTERDRIVER_DEBUG("writeReg(" << regInd << ", " << regValue  << ") "<< endl);

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_writeData = regValue;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write  = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    step();
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write = 0;
    step(5);  // extra delay on write completion to be realistic
  }

  virtual AccelReg readReg(unsigned int regInd) {
    AccelReg ret;

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 1;
    step(); // don't actually need 1 cycle, regfile reads are combinational

    if(!m_inst->TesterWrapper__io_regFileIF_readData_valid.to_bool())
      throw "Could not read register";

    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 0;

    ret = m_inst->TesterWrapper__io_regFileIF_readData_bits.to_ulong();

    __TESTERDRIVER_DEBUG("readReg(" << regInd << ") = " << ret << endl);

    step(5);  // extra delay on read completion to be realistic

    return ret;
  }

  void printAllRegs() {
    for(unsigned int i = 0; i < m_regCount; i++)  {
        AccelReg val = readReg(i);
        cout << "Reg " << i << " = " << val << " (0x" << hex << val << dec << ")" << endl;
      }

  }

protected:
  TesterWrapper_t * m_inst;
  unsigned int m_memWords;
  unsigned int m_regCount;
  uint64_t m_freePtr;

  void reset() {
    m_inst->clock(1);
    m_inst->clock(0);
    // Chisel c++ backend requires this workaround to get out the correct values
    m_inst->clock_lo(0);
  }

  void step(int n = 1) {
    for(int i = 0; i < n; i++) {
      m_inst->clock(0);
      // Chisel c++ backend requires this workaround to get out the correct values
      m_inst->clock_lo(0);
    }
  }

  void memWrite(uint64_t addr, uint64_t value) {
    m_inst->TesterWrapper__io_memAddr = addr;
    m_inst->TesterWrapper__io_memWriteData = value;
    m_inst->TesterWrapper__io_memWriteEn = 1;
    step();
    m_inst->TesterWrapper__io_memWriteEn = 0;
  }

  uint64_t memRead(uint64_t addr) {
    m_inst->TesterWrapper__io_memAddr = addr;
    step();
    uint64_t ret = m_inst->TesterWrapper__io_memReadData[0];
    return ret;
  }

  // "aligned" copy functions, where accel ptr start and size are guaranteed to be 8-aligned
  void alignedCopyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t * host_buf = (uint64_t *) hostBuffer;
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    for(unsigned int i = 0; i < numBytes/8; i++)
        memWrite(accelBufBase + i*8, host_buf[i]);
  }

  void alignedCopyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    uint64_t * readBuf = (uint64_t *) hostBuffer;
    for(unsigned int i = 0; i < numBytes/8; i++)
      readBuf[i] = memRead(accelBufBase + i*8);
  }
};

#endif
<|endoftext|>


<commit_before>
#include "firebasepush.hh"
#include <iostream>
#include <string.h>
#include "log/logmanager.hh"

using namespace std;

FirebasePushNotificationRequest::FirebasePushNotificationRequest(const PushInfo &pinfo)
: PushNotificationRequest(pinfo.mAppId, "firebase") {
	const string &deviceToken = pinfo.mDeviceToken;
	const string &apiKey = pinfo.mApiKey;
	ostringstream httpBody;
	time_t t = time(NULL);
	struct tm *tm = localtime(&t);
	char date[20];
	strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", tm);

	httpBody << "{\"to\":\"" << deviceToken << "\", \"priority\":\"high\"" << ", \"uuid\":" << pinfo.mUid
		<< ", \"send-time\":\"" << date << "\"}";
	mHttpBody = httpBody.str();
	LOGD("Push notification https post body is %s", mHttpBody.c_str());

	ostringstream httpHeader;
	httpHeader << "POST /fcm/send "
	"HTTP/1.1\r\nHost:fcm.googleapis.com\r\nContent-Type:application/json\r\nAuthorization:key="
	<< apiKey << "\r\nContent-Length:" << httpBody.str().size() << "\r\n\r\n";
	mHttpHeader = httpHeader.str();
	SLOGD << "PNR " << this << " https post header is " << mHttpHeader;
}

void FirebasePushNotificationRequest::createPushNotification() {
	int headerLength = mHttpHeader.length();
	int bodyLength = mHttpBody.length();

	mBuffer.clear();
	mBuffer.resize(headerLength + bodyLength);

	char *binaryMessageBuff = &mBuffer[0];
	char *binaryMessagePt = binaryMessageBuff;

	memcpy(binaryMessagePt, &mHttpHeader[0], headerLength);
	binaryMessagePt += headerLength;

	memcpy(binaryMessagePt, &mHttpBody[0], bodyLength);
	binaryMessagePt += bodyLength;
}

const vector<char> &FirebasePushNotificationRequest::getData() {
	createPushNotification();
	return mBuffer;
}

string FirebasePushNotificationRequest::isValidResponse(const string &str) {
	static const char expected[] = "HTTP/1.1 200";
	return strncmp(expected, str.c_str(), sizeof(expected) - 1) == 0 ? "" : "Unexpected HTTP response value (not 200 OK)";
}
<commit_msg>Quote uuid in json body sent to Firebase.<commit_after>
#include "firebasepush.hh"
#include <iostream>
#include <string.h>
#include "log/logmanager.hh"

using namespace std;

FirebasePushNotificationRequest::FirebasePushNotificationRequest(const PushInfo &pinfo)
: PushNotificationRequest(pinfo.mAppId, "firebase") {
	const string &deviceToken = pinfo.mDeviceToken;
	const string &apiKey = pinfo.mApiKey;
	ostringstream httpBody;
	time_t t = time(NULL);
	struct tm *tm = localtime(&t);
	char date[20];
	strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", tm);

	httpBody << "{\"to\":\"" << deviceToken << "\", \"priority\":\"high\"" << ", \"uuid\":\"" << pinfo.mUid
		<< "\", \"send-time\":\"" << date << "\"}";
	mHttpBody = httpBody.str();
	LOGD("Push notification https post body is %s", mHttpBody.c_str());

	ostringstream httpHeader;
	httpHeader << "POST /fcm/send "
	"HTTP/1.1\r\nHost:fcm.googleapis.com\r\nContent-Type:application/json\r\nAuthorization:key="
	<< apiKey << "\r\nContent-Length:" << httpBody.str().size() << "\r\n\r\n";
	mHttpHeader = httpHeader.str();
	SLOGD << "PNR " << this << " https post header is " << mHttpHeader;
}

void FirebasePushNotificationRequest::createPushNotification() {
	int headerLength = mHttpHeader.length();
	int bodyLength = mHttpBody.length();

	mBuffer.clear();
	mBuffer.resize(headerLength + bodyLength);

	char *binaryMessageBuff = &mBuffer[0];
	char *binaryMessagePt = binaryMessageBuff;

	memcpy(binaryMessagePt, &mHttpHeader[0], headerLength);
	binaryMessagePt += headerLength;

	memcpy(binaryMessagePt, &mHttpBody[0], bodyLength);
	binaryMessagePt += bodyLength;
}

const vector<char> &FirebasePushNotificationRequest::getData() {
	createPushNotification();
	return mBuffer;
}

string FirebasePushNotificationRequest::isValidResponse(const string &str) {
	static const char expected[] = "HTTP/1.1 200";
	return strncmp(expected, str.c_str(), sizeof(expected) - 1) == 0 ? "" : "Unexpected HTTP response value (not 200 OK)";
}
<|endoftext|>


<commit_before>/*
 * mainGame.cpp
 *
 *  Created on: Nov 26, 2017
 *      Author: lowji
 */

//created this source file to make the compiler work properly
#include <sstream>
#include <iostream>
#include <string>
#include "Player.h"
#include "ConsoleUI.h"
#include "Card.h"
#include "Deck.h"
#include "Board.h"
//method to determine if a string is an integer
bool isInt(string input){
	//Reference: https://stackoverflow.com/questions/20287186/how-to-check-if-the-input-is-a-valid-integer-without-any-other-chars

	int x; //temporary int variable for checking input validity
	char c; //temporary char variable for checking input validity
	istringstream s(input);

	if (!(s >> x)) {
		return false;
	}

	if (s >> c) {
		return false;
	}

	return true;
}

int main(){

	//set up user interface
  	ConsoleUI* ui = new ConsoleUI();

    ui->welcome();

	string inputTemp;
	inputTemp = ui->input("Input your name: ");
	Player* human = new Player(inputTemp);
	Player* AI = new Player("AI");

	//Preflop
	inputTemp=ui->input("How much do you want the blind to be? ");
	while(!isInt(inputTemp)){
		ui->output("Invalid input. Blind must be an integer.");
		inputTemp=ui->input("How much do you want the blind to be? ");
	}
	const int BLIND=inputTemp;

	ui->output("Your name is "+human->getName());
	ui->output("Your opponent name is "+AI->getName());

<<<<<<< HEAD
	//shuffling(automatic shuffled)
       	Deck* deck = new Deck();
	//draw cards
    human->addOne(deck->draw());
	human->addTwo(deck->draw());

	//print user's hand
	ui->output("Print "+ human->getName()+"'s hand");
       	(human->getHandOne()).printCard();
       	(human->getHandTwo()).printCard();
[
=======
>>>>>>> 02dab9aa4e5f05795ca15ddee9e37bfd52a1e654
	//print table: your stack, small blind, big blind, pot(needs to make)
 Board* board = new Board(human, AI);

	//prompt user decision: raise, bet, check=bet(0), fold

	//Postflop: prompt user, update pot and each player stack size(money), user's decision, draw 3 cards into communitycards, print pot and stacksize, print hands, print communitycards

	//Turn:  prompt user, update pot and each player stack size(money), user's decision, draw 1 cards into communitycards, print pot and stacksize, print hands, print communitycards

	//River: repeat Turn, and go back to preflop...
}

<commit_msg>Solved merge issue<commit_after>/*
 * mainGame.cpp
 *
 *  Created on: Nov 26, 2017
 *      Author: lowji
 */

//created this source file to make the compiler work properly
#include <sstream>
#include <iostream>
#include <string>
#include "Player.h"
#include "ConsoleUI.h"
#include "Card.h"
#include "Deck.h"
#include "Board.h"
//method to determine if a string is an integer
bool isInt(string input){
	//Reference: https://stackoverflow.com/questions/20287186/how-to-check-if-the-input-is-a-valid-integer-without-any-other-chars

	int x; //temporary int variable for checking input validity
	char c; //temporary char variable for checking input validity
	istringstream s(input);

	if (!(s >> x)) {
		return false;
	}

	if (s >> c) {
		return false;
	}

	return true;
}

int main(){

	//set up user interface
  	ConsoleUI* ui = new ConsoleUI();

    ui->welcome();

	string inputTemp;
	inputTemp = ui->input("Input your name: ");
	Player* human = new Player(inputTemp);
	Player* AI = new Player("AI");

	//Preflop
	inputTemp=ui->input("How much do you want the blind to be? ");
	while(!isInt(inputTemp)){
		ui->output("Invalid input. Blind must be an integer.");
		inputTemp=ui->input("How much do you want the blind to be? ");
	}
	const int BLIND=inputTemp;

	ui->output("Your name is "+human->getName());
	ui->output("Your opponent name is "+AI->getName());

	//shuffling(automatic shuffled)
    Deck* deck = new Deck();
	//draw cards
    human->addOne(deck->draw());
	human->addTwo(deck->draw());

	//print user's hand
	ui->output("Print "+ human->getName()+"'s hand");
    (human->getHandOne()).printCard();
    (human->getHandTwo()).printCard();

	//print table: your stack, small blind, big blind, pot(needs to make)
    Board* board = new Board(human, AI);

	//prompt user decision: raise, bet, check=bet(0), fold

	//Postflop: prompt user, update pot and each player stack size(money), user's decision, draw 3 cards into communitycards, print pot and stacksize, print hands, print communitycards

	//Turn:  prompt user, update pot and each player stack size(money), user's decision, draw 1 cards into communitycards, print pot and stacksize, print hands, print communitycards

	//River: repeat Turn, and go back to preflop...
}

<|endoftext|>