<commit_before>//===-- cc1as_main.cpp - Clang Assembler  ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the entry point to the clang -cc1as functionality, which implements
// the direct interface to the LLVM MC based assembler.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/CC1AsOptions.h"
#include "clang/Driver/OptTable.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetAsmBackend.h"
#include "llvm/Target/TargetAsmParser.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetSelect.h"
using namespace clang;
using namespace clang::driver;
using namespace llvm;

namespace {

/// \brief Helper class for representing a single invocation of the assembler.
struct AssemblerInvocation {
  /// @name Target Options
  /// @{

  std::string Triple;

  /// @}
  /// @name Language Options
  /// @{

  std::vector<std::string> IncludePaths;
  unsigned NoInitialTextSection : 1;

  /// @}
  /// @name Frontend Options
  /// @{

  std::string InputFile;
  std::vector<std::string> LLVMArgs;
  std::string OutputPath;
  enum FileType {
    FT_Asm,  ///< Assembly (.s) output, transliterate mode.
    FT_Null, ///< No output, for timing purposes.
    FT_Obj   ///< Object file output.
  };
  FileType OutputType;
  unsigned ShowHelp : 1;
  unsigned ShowVersion : 1;

  /// @}
  /// @name Transliterate Options
  /// @{

  unsigned OutputAsmVariant;
  unsigned ShowEncoding : 1;
  unsigned ShowInst : 1;

  /// @}
  /// @name Assembler Options
  /// @{

  unsigned RelaxAll : 1;

  /// @}

public:
  AssemblerInvocation() {
    Triple = "";
    NoInitialTextSection = 0;
    InputFile = "-";
    OutputPath = "-";
    OutputType = FT_Asm;
    OutputAsmVariant = 0;
    ShowInst = 0;
    ShowEncoding = 0;
    RelaxAll = 0;
  }

  static void CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin,
                             const char **ArgEnd, Diagnostic &Diags);
};

}

void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
                                         const char **ArgBegin,
                                         const char **ArgEnd,
                                         Diagnostic &Diags) {
  using namespace clang::driver::cc1asoptions;
  // Parse the arguments.
  OwningPtr<OptTable> OptTbl(createCC1AsOptTable());
  unsigned MissingArgIndex, MissingArgCount;
  OwningPtr<InputArgList> Args(
    OptTbl->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));

  // Check for missing argument error.
  if (MissingArgCount)
    Diags.Report(diag::err_drv_missing_argument)
      << Args->getArgString(MissingArgIndex) << MissingArgCount;

  // Issue errors on unknown arguments.
  for (arg_iterator it = Args->filtered_begin(cc1asoptions::OPT_UNKNOWN),
         ie = Args->filtered_end(); it != ie; ++it)
    Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args);

  // Construct the invocation.

  // Target Options
  Opts.Triple = Args->getLastArgValue(OPT_triple);
  if (Opts.Triple.empty()) // Use the host triple if unspecified.
    Opts.Triple = sys::getHostTriple();

  // Language Options
  Opts.IncludePaths = Args->getAllArgValues(OPT_I);
  Opts.NoInitialTextSection = Args->hasArg(OPT_n);

  // Frontend Options
  if (Args->hasArg(OPT_INPUT)) {
    bool First = true;
    for (arg_iterator it = Args->filtered_begin(OPT_INPUT),
           ie = Args->filtered_end(); it != ie; ++it, First=false) {
      const Arg *A = it;
      if (First)
        Opts.InputFile = A->getValue(*Args);
      else
        Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args);
    }
  }
  Opts.LLVMArgs = Args->getAllArgValues(OPT_mllvm);
  Opts.OutputPath = Args->getLastArgValue(OPT_o);
  if (Arg *A = Args->getLastArg(OPT_filetype)) {
    StringRef Name = A->getValue(*Args);
    unsigned OutputType = StringSwitch<unsigned>(Name)
      .Case("asm", FT_Asm)
      .Case("null", FT_Null)
      .Case("obj", FT_Obj)
      .Default(~0U);
    if (OutputType == ~0U)
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(*Args) << Name;
    else
      Opts.OutputType = FileType(OutputType);
  }
  Opts.ShowHelp = Args->hasArg(OPT_help);
  Opts.ShowVersion = Args->hasArg(OPT_version);

  // Transliterate Options
  Opts.OutputAsmVariant = Args->getLastArgIntValue(OPT_output_asm_variant,
                                                   0, Diags);
  Opts.ShowEncoding = Args->hasArg(OPT_show_encoding);
  Opts.ShowInst = Args->hasArg(OPT_show_inst);

  // Assemble Options
  Opts.RelaxAll = Args->hasArg(OPT_relax_all);
}

static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts,
                                              Diagnostic &Diags,
                                              bool Binary) {
  if (Opts.OutputPath.empty())
    Opts.OutputPath = "-";

  // Make sure that the Out file gets unlinked from the disk if we get a
  // SIGINT.
  if (Opts.OutputPath != "-")
    sys::RemoveFileOnSignal(sys::Path(Opts.OutputPath));

  std::string Error;
  raw_fd_ostream *Out =
    new raw_fd_ostream(Opts.OutputPath.c_str(), Error,
                       (Binary ? raw_fd_ostream::F_Binary : 0));
  if (!Error.empty()) {
    Diags.Report(diag::err_fe_unable_to_open_output)
      << Opts.OutputPath << Error;
    return 0;
  }

  return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM);
}

static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) {
  // Get the target specific parser.
  std::string Error;
  const Target *TheTarget(TargetRegistry::lookupTarget(Opts.Triple, Error));
  if (!TheTarget) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(Opts.InputFile, &Error);
  if (Buffer == 0) {
    Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
    return false;
  }

  SourceMgr SrcMgr;

  // Tell SrcMgr about this buffer, which is what the parser will pick up.
  SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());

  // Record the location of the include directories so that the lexer can find
  // it later.
  SrcMgr.setIncludeDirs(Opts.IncludePaths);

  OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(Opts.Triple));
  assert(MAI && "Unable to create target asm info!");

  MCContext Ctx(*MAI);
  bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
  formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary);
  if (!Out)
    return false;

  // FIXME: We shouldn't need to do this (and link in codegen).
  OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(Opts.Triple, ""));
  if (!TM) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  OwningPtr<MCCodeEmitter> CE;
  OwningPtr<MCStreamer> Str;
  OwningPtr<TargetAsmBackend> TAB;

  if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
    MCInstPrinter *IP =
      TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI);
    if (Opts.ShowEncoding)
      CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
    Str.reset(createAsmStreamer(Ctx, *Out,TM->getTargetData()->isLittleEndian(),
                                /*asmverbose*/true, IP, CE.get(),
                                Opts.ShowInst));
  } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
    Str.reset(createNullStreamer(Ctx));
  } else {
    assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
           "Invalid file type!");
    CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
    TAB.reset(TheTarget->createAsmBackend(Opts.Triple));
    Str.reset(createMachOStreamer(Ctx, *TAB, *Out, CE.get(), Opts.RelaxAll));
  }

  OwningPtr<MCAsmParser> Parser(createMCAsmParser(*TheTarget, SrcMgr, Ctx,
                                                  *Str.get(), *MAI));
  OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(*Parser));
  if (!TAP) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  Parser->setTargetParser(*TAP.get());

  bool Success = !Parser->Run(Opts.NoInitialTextSection);

  // Close the output.
  delete Out;

  // Delete output on errors.
  if (!Success && Opts.OutputPath != "-")
    sys::Path(Opts.OutputPath).eraseFromDisk();

  return Success;
}

static void LLVMErrorHandler(void *UserData, const std::string &Message) {
  Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);

  Diags.Report(diag::err_fe_error_backend) << Message;

  // We cannot recover from llvm errors.
  exit(1);
}

int cc1as_main(const char **ArgBegin, const char **ArgEnd,
               const char *Argv0, void *MainAddr) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(ArgEnd - ArgBegin, ArgBegin);
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  // Initialize targets and assembly printers/parsers.
  InitializeAllTargetInfos();
  // FIXME: We shouldn't need to initialize the Target(Machine)s.
  InitializeAllTargets();
  InitializeAllAsmPrinters();
  InitializeAllAsmParsers();

  // Construct our diagnostic client.
  TextDiagnosticPrinter DiagClient(errs(), DiagnosticOptions());
  DiagClient.setPrefix("clang -cc1as");
  Diagnostic Diags(&DiagClient);

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  install_fatal_error_handler(LLVMErrorHandler,
                                    static_cast<void*>(&Diags));

  // Parse the arguments.
  AssemblerInvocation Asm;
  AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags);

  // Honor -help.
  if (Asm.ShowHelp) {
    llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1AsOptTable());
    Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler");
    return 0;
  }

  // Honor -version.
  //
  // FIXME: Use a better -version message?
  if (Asm.ShowVersion) {
    llvm::cl::PrintVersionMessage();
    return 0;
  }

  // Honor -mllvm.
  //
  // FIXME: Remove this, one day.
  if (!Asm.LLVMArgs.empty()) {
    unsigned NumArgs = Asm.LLVMArgs.size();
    const char **Args = new const char*[NumArgs + 2];
    Args[0] = "clang (LLVM option parsing)";
    for (unsigned i = 0; i != NumArgs; ++i)
      Args[i + 1] = Asm.LLVMArgs[i].c_str();
    Args[NumArgs + 1] = 0;
    llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast<char **>(Args));
  }

  // Execute the invocation, unless there were parsing errors.
  bool Success = false;
  if (!Diags.getNumErrors())
    Success = ExecuteAssembler(Asm, Diags);

  // If any timers were active but haven't been destroyed yet, print their
  // results now.
  TimerGroup::printAll(errs());

  return !Success;
}
<commit_msg>Update for LLVM API change.<commit_after>//===-- cc1as_main.cpp - Clang Assembler  ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the entry point to the clang -cc1as functionality, which implements
// the direct interface to the LLVM MC based assembler.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/CC1AsOptions.h"
#include "clang/Driver/OptTable.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetAsmBackend.h"
#include "llvm/Target/TargetAsmParser.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetSelect.h"
using namespace clang;
using namespace clang::driver;
using namespace llvm;

namespace {

/// \brief Helper class for representing a single invocation of the assembler.
struct AssemblerInvocation {
  /// @name Target Options
  /// @{

  std::string Triple;

  /// @}
  /// @name Language Options
  /// @{

  std::vector<std::string> IncludePaths;
  unsigned NoInitialTextSection : 1;

  /// @}
  /// @name Frontend Options
  /// @{

  std::string InputFile;
  std::vector<std::string> LLVMArgs;
  std::string OutputPath;
  enum FileType {
    FT_Asm,  ///< Assembly (.s) output, transliterate mode.
    FT_Null, ///< No output, for timing purposes.
    FT_Obj   ///< Object file output.
  };
  FileType OutputType;
  unsigned ShowHelp : 1;
  unsigned ShowVersion : 1;

  /// @}
  /// @name Transliterate Options
  /// @{

  unsigned OutputAsmVariant;
  unsigned ShowEncoding : 1;
  unsigned ShowInst : 1;

  /// @}
  /// @name Assembler Options
  /// @{

  unsigned RelaxAll : 1;

  /// @}

public:
  AssemblerInvocation() {
    Triple = "";
    NoInitialTextSection = 0;
    InputFile = "-";
    OutputPath = "-";
    OutputType = FT_Asm;
    OutputAsmVariant = 0;
    ShowInst = 0;
    ShowEncoding = 0;
    RelaxAll = 0;
  }

  static void CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin,
                             const char **ArgEnd, Diagnostic &Diags);
};

}

void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
                                         const char **ArgBegin,
                                         const char **ArgEnd,
                                         Diagnostic &Diags) {
  using namespace clang::driver::cc1asoptions;
  // Parse the arguments.
  OwningPtr<OptTable> OptTbl(createCC1AsOptTable());
  unsigned MissingArgIndex, MissingArgCount;
  OwningPtr<InputArgList> Args(
    OptTbl->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));

  // Check for missing argument error.
  if (MissingArgCount)
    Diags.Report(diag::err_drv_missing_argument)
      << Args->getArgString(MissingArgIndex) << MissingArgCount;

  // Issue errors on unknown arguments.
  for (arg_iterator it = Args->filtered_begin(cc1asoptions::OPT_UNKNOWN),
         ie = Args->filtered_end(); it != ie; ++it)
    Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args);

  // Construct the invocation.

  // Target Options
  Opts.Triple = Args->getLastArgValue(OPT_triple);
  if (Opts.Triple.empty()) // Use the host triple if unspecified.
    Opts.Triple = sys::getHostTriple();

  // Language Options
  Opts.IncludePaths = Args->getAllArgValues(OPT_I);
  Opts.NoInitialTextSection = Args->hasArg(OPT_n);

  // Frontend Options
  if (Args->hasArg(OPT_INPUT)) {
    bool First = true;
    for (arg_iterator it = Args->filtered_begin(OPT_INPUT),
           ie = Args->filtered_end(); it != ie; ++it, First=false) {
      const Arg *A = it;
      if (First)
        Opts.InputFile = A->getValue(*Args);
      else
        Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args);
    }
  }
  Opts.LLVMArgs = Args->getAllArgValues(OPT_mllvm);
  Opts.OutputPath = Args->getLastArgValue(OPT_o);
  if (Arg *A = Args->getLastArg(OPT_filetype)) {
    StringRef Name = A->getValue(*Args);
    unsigned OutputType = StringSwitch<unsigned>(Name)
      .Case("asm", FT_Asm)
      .Case("null", FT_Null)
      .Case("obj", FT_Obj)
      .Default(~0U);
    if (OutputType == ~0U)
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(*Args) << Name;
    else
      Opts.OutputType = FileType(OutputType);
  }
  Opts.ShowHelp = Args->hasArg(OPT_help);
  Opts.ShowVersion = Args->hasArg(OPT_version);

  // Transliterate Options
  Opts.OutputAsmVariant = Args->getLastArgIntValue(OPT_output_asm_variant,
                                                   0, Diags);
  Opts.ShowEncoding = Args->hasArg(OPT_show_encoding);
  Opts.ShowInst = Args->hasArg(OPT_show_inst);

  // Assemble Options
  Opts.RelaxAll = Args->hasArg(OPT_relax_all);
}

static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts,
                                              Diagnostic &Diags,
                                              bool Binary) {
  if (Opts.OutputPath.empty())
    Opts.OutputPath = "-";

  // Make sure that the Out file gets unlinked from the disk if we get a
  // SIGINT.
  if (Opts.OutputPath != "-")
    sys::RemoveFileOnSignal(sys::Path(Opts.OutputPath));

  std::string Error;
  raw_fd_ostream *Out =
    new raw_fd_ostream(Opts.OutputPath.c_str(), Error,
                       (Binary ? raw_fd_ostream::F_Binary : 0));
  if (!Error.empty()) {
    Diags.Report(diag::err_fe_unable_to_open_output)
      << Opts.OutputPath << Error;
    return 0;
  }

  return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM);
}

static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) {
  // Get the target specific parser.
  std::string Error;
  const Target *TheTarget(TargetRegistry::lookupTarget(Opts.Triple, Error));
  if (!TheTarget) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(Opts.InputFile, &Error);
  if (Buffer == 0) {
    Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
    return false;
  }

  SourceMgr SrcMgr;

  // Tell SrcMgr about this buffer, which is what the parser will pick up.
  SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());

  // Record the location of the include directories so that the lexer can find
  // it later.
  SrcMgr.setIncludeDirs(Opts.IncludePaths);

  OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(Opts.Triple));
  assert(MAI && "Unable to create target asm info!");

  MCContext Ctx(*MAI);
  bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
  formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary);
  if (!Out)
    return false;

  // FIXME: We shouldn't need to do this (and link in codegen).
  OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(Opts.Triple, ""));
  if (!TM) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  OwningPtr<MCCodeEmitter> CE;
  OwningPtr<MCStreamer> Str;
  OwningPtr<TargetAsmBackend> TAB;

  if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
    MCInstPrinter *IP =
      TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI);
    if (Opts.ShowEncoding)
      CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
    Str.reset(createAsmStreamer(Ctx, *Out,TM->getTargetData()->isLittleEndian(),
                                /*asmverbose*/true, IP, CE.get(),
                                Opts.ShowInst));
  } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
    Str.reset(createNullStreamer(Ctx));
  } else {
    assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
           "Invalid file type!");
    CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
    TAB.reset(TheTarget->createAsmBackend(Opts.Triple));
    Str.reset(createMachOStreamer(Ctx, *TAB, *Out, CE.get(), Opts.RelaxAll));
  }

  OwningPtr<MCAsmParser> Parser(createMCAsmParser(*TheTarget, SrcMgr, Ctx,
                                                  *Str.get(), *MAI));
  OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(*Parser, *TM));
  if (!TAP) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  Parser->setTargetParser(*TAP.get());

  bool Success = !Parser->Run(Opts.NoInitialTextSection);

  // Close the output.
  delete Out;

  // Delete output on errors.
  if (!Success && Opts.OutputPath != "-")
    sys::Path(Opts.OutputPath).eraseFromDisk();

  return Success;
}

static void LLVMErrorHandler(void *UserData, const std::string &Message) {
  Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);

  Diags.Report(diag::err_fe_error_backend) << Message;

  // We cannot recover from llvm errors.
  exit(1);
}

int cc1as_main(const char **ArgBegin, const char **ArgEnd,
               const char *Argv0, void *MainAddr) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(ArgEnd - ArgBegin, ArgBegin);
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  // Initialize targets and assembly printers/parsers.
  InitializeAllTargetInfos();
  // FIXME: We shouldn't need to initialize the Target(Machine)s.
  InitializeAllTargets();
  InitializeAllAsmPrinters();
  InitializeAllAsmParsers();

  // Construct our diagnostic client.
  TextDiagnosticPrinter DiagClient(errs(), DiagnosticOptions());
  DiagClient.setPrefix("clang -cc1as");
  Diagnostic Diags(&DiagClient);

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  install_fatal_error_handler(LLVMErrorHandler,
                                    static_cast<void*>(&Diags));

  // Parse the arguments.
  AssemblerInvocation Asm;
  AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags);

  // Honor -help.
  if (Asm.ShowHelp) {
    llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1AsOptTable());
    Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler");
    return 0;
  }

  // Honor -version.
  //
  // FIXME: Use a better -version message?
  if (Asm.ShowVersion) {
    llvm::cl::PrintVersionMessage();
    return 0;
  }

  // Honor -mllvm.
  //
  // FIXME: Remove this, one day.
  if (!Asm.LLVMArgs.empty()) {
    unsigned NumArgs = Asm.LLVMArgs.size();
    const char **Args = new const char*[NumArgs + 2];
    Args[0] = "clang (LLVM option parsing)";
    for (unsigned i = 0; i != NumArgs; ++i)
      Args[i + 1] = Asm.LLVMArgs[i].c_str();
    Args[NumArgs + 1] = 0;
    llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast<char **>(Args));
  }

  // Execute the invocation, unless there were parsing errors.
  bool Success = false;
  if (!Diags.getNumErrors())
    Success = ExecuteAssembler(Asm, Diags);

  // If any timers were active but haven't been destroyed yet, print their
  // results now.
  TimerGroup::printAll(errs());

  return !Success;
}
<|endoftext|>


<commit_before>#include <hir/hir.hpp>
#include <hir/item_path.hpp>
#include <hir/main_bindings.hpp>
#include <macro_rules/macro_rules.hpp>
#include <mir/mir.hpp>
#include <mir/operations.hpp>   // MIR_Dump_Fcn

int g_debug_indent_level = 0;

struct Args
{
    Args(int argc, const char* const argv[]);

    ::std::string   infile;
};

struct Dumper
{
    struct Filters {
        struct Types {
            bool    macros = true;
            bool    functions = true;
            bool    statics = true;
            bool    types = true;
            bool    traits = true;
        } types;
        bool public_only = false;
        bool no_body = false;
    } filters;

    void dump_crate(const char* name, const ::HIR::Crate& crate) const;
    void dump_module(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Module& mod) const;
    void dump_function(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Function& fcn, int indent=0) const;
    void dump_trait(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Trait& trait, int indent=0) const;
};

int main(int argc, const char* argv[])
{
    Args    args(argc, argv);
    Dumper  dumper;

    dumper.filters.types.functions = true;

    auto hir = HIR_Deserialise(args.infile);
    dumper.dump_crate("", *hir);
}
namespace {
    template<typename T, typename Fcn>
    void dump_impl_group(const ::HIR::Crate::ImplGroup<T>& ig, Fcn cb)
    {
        for(const auto& named_il : ig.named)
        {
            for(const auto& impl : named_il.second)
            {
                cb(*impl);
            }
        }
        for(const auto& impl : ig.non_named)
        {
            cb(*impl);
        }
        for(const auto& impl : ig.generic)
        {
            cb(*impl);
        }
    }
}
void Dumper::dump_crate(const char* name, const ::HIR::Crate& crate) const
{
    // Dump macros
    for(const auto& mac : crate.m_exported_macros)
    {
        ::std::cout << "macro_rules! " << mac.first << "{" << std::endl;
        for(const auto& arm : mac.second->m_rules)
        {
            ::std::cout << "    (";
            for(const auto& pat : arm.m_pattern)
            {
                TU_MATCH_HDRA( (pat), {)
                TU_ARMA(End, e)
                    ::std::cout << " EOS";
                TU_ARMA(LoopStart, e)
                    ::std::cout << " (";
                TU_ARMA(LoopNext, e)
                    ::std::cout << " ^";
                TU_ARMA(LoopEnd, e)
                    ::std::cout << " )";
                TU_ARMA(Jump, e)
                    ::std::cout << " <" << e.jump_target;
                TU_ARMA(ExpectTok, e)
                    ::std::cout << " =" << e;
                TU_ARMA(ExpectPat, e)
                    ::std::cout << " " << e.idx << "=" << e.type;
                TU_ARMA(If, e) {
                    ::std::cout << " ?" << (e.is_equal ? "" : "!") << "{";
                    for(const auto& ent : e.ents) {
                        if(ent.ty == MacroPatEnt::PAT_TOKEN)
                            ::std::cout << " =" << ent.tok;
                        else
                            ::std::cout << " " << ent.ty;
                    }
                    ::std::cout << "}->" << e.jump_target;
                    }
                }
            }
            ::std::cout << " ) => {\n";
            // TODO: Macro expansion
            ::std::cout << "    }\n";
        }
        ::std::cout << "}\n";
        ::std::cout << ::std::endl;
    }

    this->dump_module(::HIR::ItemPath(name), ::HIR::Publicity::new_global(), crate.m_root_module);

    for(const auto& i : crate.m_trait_impls)
    {
        dump_impl_group(i.second, [&](const ::HIR::TraitImpl& ti) {
            auto root_ip = ::HIR::ItemPath(ti.m_type, i.first, ti.m_trait_args);
            ::std::cout << "impl" << ti.m_params.fmt_args() << " " << i.first << ti.m_trait_args << " for " << ti.m_type << "\n";
            ::std::cout << "  where" << ti.m_params.fmt_bounds() << "\n";
            ::std::cout << "{" << ::std::endl;
            if( this->filters.types.functions )
            {
                for(const auto& m : ti.m_methods)
                {
                    this->dump_function(root_ip + m.first, ::HIR::Publicity::new_global(), m.second.data, 1);
                }
            }
            ::std::cout << "}" << ::std::endl;
        });
    }

    dump_impl_group(crate.m_type_impls, [&](const auto& i) {
        auto root_ip = ::HIR::ItemPath(i.m_type);
        ::std::cout << "impl" << i.m_params.fmt_args() << " " << i.m_type << "\n";
        ::std::cout << "  where" << i.m_params.fmt_bounds() << "\n";
        ::std::cout << "{" << ::std::endl;
        if( this->filters.types.functions )
        {
            for(const auto& m : i.m_methods)
            {
                this->dump_function(root_ip + m.first, ::HIR::Publicity::new_global(), m.second.data, 1);
            }
        }
        ::std::cout << "}" << ::std::endl;
    });
}
void Dumper::dump_module(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Module& mod) const
{
    if( !filters.public_only && !pub.is_global() )
    {
        return ;
    }
    ::std::cout << "// mod " << ip << ::std::endl;
    for(const auto& i : mod.m_mod_items)
    {
        auto sub_ip = ip + i.first;
        //::std::cout << "// " << i.second->ent.tagstr() << " " << sub_ip << "\n";
        TU_MATCH_HDRA( (i.second->ent), {)
        TU_ARMA(Module, e) {
            this->dump_module(sub_ip, i.second->publicity, e);
            }
        TU_ARMA(Import, e) {
            //this->dump_mod_import(sub_ip, e);
            }
        TU_ARMA(TypeAlias, e) {
            //this->dump_type_alias(sub_ip, e);
            }
        TU_ARMA(ExternType, e) {
            //this->dump_ext_type(sub_ip, e);
            }
        TU_ARMA(Enum, e) {
            //this->dump_enum(sub_ip, e);
            }
        TU_ARMA(Struct, e) {
            //this->dump_enum(sub_ip, e);
            }
        TU_ARMA(Union, e) {
            //this->dump_trait(sub_ip, e);
            }
        TU_ARMA(Trait, e) {
            this->dump_trait(sub_ip, i.second->publicity, e);
            }
        }
    }
    for(const auto& i : mod.m_value_items)
    {
        auto sub_ip = ip + i.first;
        //::std::cout << "// " << i.second->ent.tagstr() << " " << sub_ip << "\n";
        TU_MATCH_HDRA( (i.second->ent), {)
        TU_ARMA(Import, e) {
            //this->dump_val_import(sub_ip, e);
            }
        TU_ARMA(Constant, e) {
            //this->dump_constant(sub_ip, e);
            }
        TU_ARMA(Static, e) {
            //this->dump_constant(sub_ip, e);
            }
        TU_ARMA(StructConstant, e) {
            //this->dump_constant(sub_ip, e);
            }
        TU_ARMA(StructConstructor, e) {
            //this->dump_constant(sub_ip, e);
            }
        TU_ARMA(Function, e) {
            this->dump_function(sub_ip, i.second->publicity, e);
            }
        }
    }
}
void Dumper::dump_function(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Function& fcn, int nindent/*=0*/) const
{
    auto indent = RepeatLitStr { "   ", nindent };
    if( !this->filters.types.functions ) {
        return ;
    }
    if( !filters.public_only && !pub.is_global() ) {
        return ;
    }
    ::std::cout << indent << "fn " << ip << fcn.m_params.fmt_args() << "(";
    ::std::cout << " )";
    if( fcn.m_code.m_mir )
    {
        ::std::cout << "\n";
        ::std::cout << indent << "{\n";
        if( filters.no_body ) {
            ::std::cout << indent << "...\n";
        }
        else {
            MIR_Dump_Fcn(::std::cout, *fcn.m_code.m_mir, nindent+1);
        }
        ::std::cout << indent << "}\n";
        ::std::cout << ::std::endl;
    }
    else
    {
        ::std::cout << ";" << ::std::endl;
    }
}
void Dumper::dump_trait(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Trait& trait, int nindent/*=0*/) const
{
    auto indent = RepeatLitStr { "   ", nindent };
    if( !this->filters.types.functions ) {
        return ;
    }
    if( !filters.public_only && !pub.is_global() ) {
        return ;
    }
    ::std::cout << indent << "trait " << ip << trait.m_params.fmt_args() << "\n";
    ::std::cout << indent << "{\n";
    auto indent2 = RepeatLitStr { "   ", nindent+1 };
    // ...
    ::std::cout << indent << "}\n";
    ::std::cout << ::std::endl;
}

bool debug_enabled()
{
    return false;
}
::std::ostream& debug_output(int indent, const char* function)
{
    return ::std::cout << "- " << RepeatLitStr { " ", indent } << function << ": ";
}

Args::Args(int argc, const char* const argv[])
{
    this->infile = argv[1];
}

// TODO: This is copy-pasted from src/main.cpp, should live somewhere better
::std::ostream& operator<<(::std::ostream& os, const FmtEscaped& x)
{
    os << ::std::hex;
    for(auto s = x.s; *s != '\0'; s ++)
    {
        switch(*s)
        {
        case '\0':  os << "\\0";    break;
        case '\n':  os << "\\n";    break;
        case '\\':  os << "\\\\";   break;
        case '"':   os << "\\\"";   break;
        default:
            uint8_t v = *s;
            if( v < 0x80 )
            {
                if( v < ' ' || v > 0x7F )
                    os << "\\u{" << ::std::hex << (unsigned int)v << "}";
                else
                    os << v;
            }
            else if( v < 0xC0 )
                ;
            else if( v < 0xE0 )
            {
                uint32_t    val = (uint32_t)(v & 0x1F) << 6;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 6;
                os << "\\u{" << ::std::hex << val << "}";
            }
            else if( v < 0xF0 )
            {
                uint32_t    val = (uint32_t)(v & 0x0F) << 12;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 12;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 6;
                os << "\\u{" << ::std::hex << val << "}";
            }
            else if( v < 0xF8 )
            {
                uint32_t    val = (uint32_t)(v & 0x07) << 18;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 18;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 12;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 6;
                os << "\\u{" << ::std::hex << val << "}";
            }
            break;
        }
    }
    os << ::std::dec;
    return os;
}

MIR::EnumCachePtr::~EnumCachePtr()
{
    assert(!this->p);
}
<commit_msg>dump_hirfile - Fix publicity handling<commit_after>#include <hir/hir.hpp>
#include <hir/item_path.hpp>
#include <hir/main_bindings.hpp>
#include <macro_rules/macro_rules.hpp>
#include <mir/mir.hpp>
#include <mir/operations.hpp>   // MIR_Dump_Fcn

int g_debug_indent_level = 0;

struct Args
{
    Args(int argc, const char* const argv[]);

    ::std::string   infile;
};

struct Dumper
{
    struct Filters {
        struct Types {
            bool    macros = true;
            bool    functions = true;
            bool    statics = true;
            bool    types = true;
            bool    traits = true;
        } types;
        bool public_only = false;
        bool no_body = false;
    } filters;

    void dump_crate(const char* name, const ::HIR::Crate& crate) const;
    void dump_module(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Module& mod) const;
    void dump_function(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Function& fcn, int indent=0) const;
    void dump_trait(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Trait& trait, int indent=0) const;
};

int main(int argc, const char* argv[])
{
    Args    args(argc, argv);
    Dumper  dumper;

    dumper.filters.types.functions = true;

    auto hir = HIR_Deserialise(args.infile);
    dumper.dump_crate("", *hir);
}
namespace {
    template<typename T, typename Fcn>
    void dump_impl_group(const ::HIR::Crate::ImplGroup<T>& ig, Fcn cb)
    {
        for(const auto& named_il : ig.named)
        {
            for(const auto& impl : named_il.second)
            {
                cb(*impl);
            }
        }
        for(const auto& impl : ig.non_named)
        {
            cb(*impl);
        }
        for(const auto& impl : ig.generic)
        {
            cb(*impl);
        }
    }
}
void Dumper::dump_crate(const char* name, const ::HIR::Crate& crate) const
{
    // Dump macros
    for(const auto& mac : crate.m_exported_macros)
    {
        ::std::cout << "macro_rules! " << mac.first << "{" << std::endl;
        for(const auto& arm : mac.second->m_rules)
        {
            ::std::cout << "    (";
            for(const auto& pat : arm.m_pattern)
            {
                TU_MATCH_HDRA( (pat), {)
                TU_ARMA(End, e)
                    ::std::cout << " EOS";
                TU_ARMA(LoopStart, e)
                    ::std::cout << " (";
                TU_ARMA(LoopNext, e)
                    ::std::cout << " ^";
                TU_ARMA(LoopEnd, e)
                    ::std::cout << " )";
                TU_ARMA(Jump, e)
                    ::std::cout << " <" << e.jump_target;
                TU_ARMA(ExpectTok, e)
                    ::std::cout << " =" << e;
                TU_ARMA(ExpectPat, e)
                    ::std::cout << " " << e.idx << "=" << e.type;
                TU_ARMA(If, e) {
                    ::std::cout << " ?" << (e.is_equal ? "" : "!") << "{";
                    for(const auto& ent : e.ents) {
                        if(ent.ty == MacroPatEnt::PAT_TOKEN)
                            ::std::cout << " =" << ent.tok;
                        else
                            ::std::cout << " " << ent.ty;
                    }
                    ::std::cout << "}->" << e.jump_target;
                    }
                }
            }
            ::std::cout << " ) => {\n";
            // TODO: Macro expansion
            ::std::cout << "    }\n";
        }
        ::std::cout << "}\n";
        ::std::cout << ::std::endl;
    }

    this->dump_module(::HIR::ItemPath(name), ::HIR::Publicity::new_global(), crate.m_root_module);

    for(const auto& i : crate.m_trait_impls)
    {
        dump_impl_group(i.second, [&](const ::HIR::TraitImpl& ti) {
            auto root_ip = ::HIR::ItemPath(ti.m_type, i.first, ti.m_trait_args);
            ::std::cout << "impl" << ti.m_params.fmt_args() << " " << i.first << ti.m_trait_args << " for " << ti.m_type << "\n";
            ::std::cout << "  where" << ti.m_params.fmt_bounds() << "\n";
            ::std::cout << "{" << ::std::endl;
            if( this->filters.types.functions )
            {
                for(const auto& m : ti.m_methods)
                {
                    this->dump_function(root_ip + m.first, ::HIR::Publicity::new_global(), m.second.data, 1);
                }
            }
            ::std::cout << "}" << ::std::endl;
        });
    }

    dump_impl_group(crate.m_type_impls, [&](const auto& i) {
        auto root_ip = ::HIR::ItemPath(i.m_type);
        ::std::cout << "impl" << i.m_params.fmt_args() << " " << i.m_type << "\n";
        ::std::cout << "  where" << i.m_params.fmt_bounds() << "\n";
        ::std::cout << "{" << ::std::endl;
        if( this->filters.types.functions )
        {
            for(const auto& m : i.m_methods)
            {
                this->dump_function(root_ip + m.first, ::HIR::Publicity::new_global(), m.second.data, 1);
            }
        }
        ::std::cout << "}" << ::std::endl;
    });
}
void Dumper::dump_module(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Module& mod) const
{
    if( filters.public_only && !pub.is_global() )
    {
        return ;
    }
    ::std::cout << "// mod " << ip << ::std::endl;
    for(const auto& i : mod.m_mod_items)
    {
        auto sub_ip = ip + i.first;
        //::std::cout << "// " << i.second->ent.tagstr() << " " << sub_ip << "\n";
        TU_MATCH_HDRA( (i.second->ent), {)
        TU_ARMA(Module, e) {
            this->dump_module(sub_ip, i.second->publicity, e);
            }
        TU_ARMA(Import, e) {
            //this->dump_mod_import(sub_ip, e);
            }
        TU_ARMA(TypeAlias, e) {
            //this->dump_type_alias(sub_ip, e);
            }
        TU_ARMA(ExternType, e) {
            //this->dump_ext_type(sub_ip, e);
            }
        TU_ARMA(Enum, e) {
            //this->dump_enum(sub_ip, e);
            }
        TU_ARMA(Struct, e) {
            //this->dump_enum(sub_ip, e);
            }
        TU_ARMA(Union, e) {
            //this->dump_trait(sub_ip, e);
            }
        TU_ARMA(Trait, e) {
            this->dump_trait(sub_ip, i.second->publicity, e);
            }
        }
    }
    for(const auto& i : mod.m_value_items)
    {
        auto sub_ip = ip + i.first;
        //::std::cout << "// " << i.second->ent.tagstr() << " " << sub_ip << "\n";
        TU_MATCH_HDRA( (i.second->ent), {)
        TU_ARMA(Import, e) {
            //this->dump_val_import(sub_ip, e);
            }
        TU_ARMA(Constant, e) {
            //this->dump_constant(sub_ip, e);
            }
        TU_ARMA(Static, e) {
            //this->dump_constant(sub_ip, e);
            }
        TU_ARMA(StructConstant, e) {
            //this->dump_constant(sub_ip, e);
            }
        TU_ARMA(StructConstructor, e) {
            //this->dump_constant(sub_ip, e);
            }
        TU_ARMA(Function, e) {
            this->dump_function(sub_ip, i.second->publicity, e);
            }
        }
    }
}
void Dumper::dump_function(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Function& fcn, int nindent/*=0*/) const
{
    auto indent = RepeatLitStr { "   ", nindent };
    if( !this->filters.types.functions ) {
        return ;
    }
    if( filters.public_only && !pub.is_global() ) {
        return ;
    }
    ::std::cout << indent << "fn " << ip << fcn.m_params.fmt_args() << "(";
    ::std::cout << " )";
    if( fcn.m_code.m_mir )
    {
        ::std::cout << "\n";
        ::std::cout << indent << "{\n";
        if( filters.no_body ) {
            ::std::cout << indent << "...\n";
        }
        else {
            MIR_Dump_Fcn(::std::cout, *fcn.m_code.m_mir, nindent+1);
        }
        ::std::cout << indent << "}\n";
        ::std::cout << ::std::endl;
    }
    else
    {
        ::std::cout << ";" << ::std::endl;
    }
}
void Dumper::dump_trait(::HIR::ItemPath ip, const ::HIR::Publicity& pub, const ::HIR::Trait& trait, int nindent/*=0*/) const
{
    auto indent = RepeatLitStr { "   ", nindent };
    if( !this->filters.types.functions ) {
        return ;
    }
    if( !filters.public_only && !pub.is_global() ) {
        return ;
    }
    ::std::cout << indent << "trait " << ip << trait.m_params.fmt_args() << "\n";
    ::std::cout << indent << "{\n";
    auto indent2 = RepeatLitStr { "   ", nindent+1 };
    // ...
    ::std::cout << indent << "}\n";
    ::std::cout << ::std::endl;
}

bool debug_enabled()
{
    return false;
}
::std::ostream& debug_output(int indent, const char* function)
{
    return ::std::cout << "- " << RepeatLitStr { " ", indent } << function << ": ";
}

Args::Args(int argc, const char* const argv[])
{
    this->infile = argv[1];
}

// TODO: This is copy-pasted from src/main.cpp, should live somewhere better
::std::ostream& operator<<(::std::ostream& os, const FmtEscaped& x)
{
    os << ::std::hex;
    for(auto s = x.s; *s != '\0'; s ++)
    {
        switch(*s)
        {
        case '\0':  os << "\\0";    break;
        case '\n':  os << "\\n";    break;
        case '\\':  os << "\\\\";   break;
        case '"':   os << "\\\"";   break;
        default:
            uint8_t v = *s;
            if( v < 0x80 )
            {
                if( v < ' ' || v > 0x7F )
                    os << "\\u{" << ::std::hex << (unsigned int)v << "}";
                else
                    os << v;
            }
            else if( v < 0xC0 )
                ;
            else if( v < 0xE0 )
            {
                uint32_t    val = (uint32_t)(v & 0x1F) << 6;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 6;
                os << "\\u{" << ::std::hex << val << "}";
            }
            else if( v < 0xF0 )
            {
                uint32_t    val = (uint32_t)(v & 0x0F) << 12;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 12;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 6;
                os << "\\u{" << ::std::hex << val << "}";
            }
            else if( v < 0xF8 )
            {
                uint32_t    val = (uint32_t)(v & 0x07) << 18;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 18;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 12;
                v = (uint8_t)*++s; if( (v & 0xC0) != 0x80 ) { s--; continue ; } val |= (uint32_t)v << 6;
                os << "\\u{" << ::std::hex << val << "}";
            }
            break;
        }
    }
    os << ::std::dec;
    return os;
}

MIR::EnumCachePtr::~EnumCachePtr()
{
    assert(!this->p);
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2011  Lasath Fernando <kde@lasath.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "conversations-model.h"
#include "conversation.h"
#include "conversation-target.h"
#include "messages-model.h"
#include "channel-delegator.h"

#include <KDebug>

#include <TelepathyQt/ChannelClassSpec>
#include <TelepathyQt/TextChannel>
#include <TelepathyQt/ClientRegistrar>

static inline Tp::ChannelClassSpecList channelClassList()
{
    return Tp::ChannelClassSpecList() << Tp::ChannelClassSpec::textChat();
}

class ConversationsModel::ConversationsModelPrivate
{
  public:
    QList<Conversation*> conversations;
};

ConversationsModel::ConversationsModel(QObject *parent) :
        QAbstractListModel(parent),
        Tp::AbstractClientHandler(channelClassList()),
        d(new ConversationsModelPrivate)
{
    QHash<int, QByteArray> roles;
    roles[ConversationRole] = "conversation";
    setRoleNames(roles);
    connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(totalUnreadCountChanged()));
    connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(totalUnreadCountChanged()));
}

ConversationsModel::~ConversationsModel()
{
    delete d;
}

QVariant ConversationsModel::data(const QModelIndex &index, int role) const
{
    QVariant result;
    if (index.isValid()) {
        if (role == ConversationRole) {
            result = QVariant::fromValue<Conversation*>(d->conversations[index.row()]);
            kDebug() << "returning value " << result;
        }
    }
    return result;
}

int ConversationsModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return d->conversations.count();
}

void ConversationsModel::handleChannels(const Tp::MethodInvocationContextPtr<> &context,
                                        const Tp::AccountPtr &account,
                                        const Tp::ConnectionPtr &connection,
                                        const QList<Tp::ChannelPtr> &channels,
                                        const QList<Tp::ChannelRequestPtr> &channelRequests,
                                        const QDateTime &userActionTime,
                                        const HandlerInfo &handlerInfo)
{
    Q_UNUSED(connection);
    Q_UNUSED(handlerInfo);

    bool handled = false;
    bool shouldDelegate = false;

    //check that the channel is of type text
    Tp::TextChannelPtr textChannel;
    Q_FOREACH(const Tp::ChannelPtr &channel, channels) {
        textChannel = Tp::TextChannelPtr::dynamicCast(channel);
        if (textChannel) {
            break;
        }
    }

    Q_ASSERT(textChannel);

    //find the relevant channelRequest
    Q_FOREACH(const Tp::ChannelRequestPtr channelRequest, channelRequests) {
        kDebug() << channelRequest->hints().allHints();
        shouldDelegate = channelRequest->hints().hint(QLatin1String("org.freedesktop.Telepathy.ChannelRequest"), QLatin1String("DelegateToPreferredHandler")).toBool();
    }

    //loop through all conversations checking for matches

    //if we are handling and we're not told to delegate it, update the text channel
    //if we are handling but should delegate, call delegate channel
    Q_FOREACH(Conversation *convo, d->conversations) {
        if (convo->target()->id() == textChannel->targetId() &&
                convo->messages()->textChannel()->targetHandleType() == textChannel->targetHandleType())
        {
            if (!shouldDelegate) {
                convo->messages()->setTextChannel(textChannel);
            } else {
                if (convo->messages()->textChannel() == textChannel) {
                    ChannelDelegator::delegateChannel(account, textChannel, userActionTime);
                }
            }
            handled = true;
            break;
        }
    }

    //if we are not handling channel already and should not delegate, add the conversation
    //if we not handling the channel but should delegate it, do nothing.

    if (!handled && !shouldDelegate) {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        Conversation *newConvo = new Conversation(textChannel, account, this);
        d->conversations.append(newConvo);
        connect(newConvo, SIGNAL(validityChanged(bool)), SLOT(handleValidityChange(bool)));
        connect(newConvo, SIGNAL(conversationDelegated()), SLOT(conversationDelegated()));
        connect(newConvo->messages(), SIGNAL(unreadCountChanged(int)), SIGNAL(unreadCountChanged()));
        endInsertRows();
        context->setFinished();
    }

}

bool ConversationsModel::bypassApproval() const
{
    return true;
}

void ConversationsModel::startChat(const Tp::AccountPtr &account, const KTp::ContactPtr &contact)
{
    Q_ASSERT(account);
    account->ensureTextChat(contact, QDateTime::currentDateTime(),
                            QLatin1String("org.freedesktop.Telepathy.Client.KDE.TextUi.ConversationWatcher"));
}

void ConversationsModel::handleValidityChange(bool valid)
{
    if (!valid) {
        removeConversation(qobject_cast<Conversation*>(QObject::sender()));
    }
}

void ConversationsModel::conversationDelegated()
{
    removeConversation(qobject_cast<Conversation*>(QObject::sender()));
}

void ConversationsModel::removeConversation(Conversation* conv)
{
    int index = d->conversations.indexOf(conv);
    if (index != -1) {
        beginRemoveRows(QModelIndex(), index, index);
        d->conversations.removeAt(index);
        conv->deleteLater();
        endRemoveRows();
    } else {
        kError() << "attempting to delete non-existent conversation";
    }
}

int ConversationsModel::nextActiveConversation(int fromRow)
{
    if(d->conversations.isEmpty()) {
        return -1;
    }
    Q_ASSERT(qBound(0, fromRow, d->conversations.count()-1) == fromRow);

    bool first = true; //let first be checked on the first loop
    for(int i = fromRow; i != fromRow || first; i = (i + 1) % d->conversations.count()) {
        if(d->conversations[i]->messages()->unreadCount() > 0) {
            return i;
        }
        first = false;
    }
    return -1;
}

int ConversationsModel::totalUnreadCount() const
{
    int ret = 0;
    Q_FOREACH(Conversation *c, d->conversations) {
        ret += c->messages()->unreadCount();
    }
    return ret;
}
<commit_msg>fix signal name<commit_after>/*
    Copyright (C) 2011  Lasath Fernando <kde@lasath.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "conversations-model.h"
#include "conversation.h"
#include "conversation-target.h"
#include "messages-model.h"
#include "channel-delegator.h"

#include <KDebug>

#include <TelepathyQt/ChannelClassSpec>
#include <TelepathyQt/TextChannel>
#include <TelepathyQt/ClientRegistrar>

static inline Tp::ChannelClassSpecList channelClassList()
{
    return Tp::ChannelClassSpecList() << Tp::ChannelClassSpec::textChat();
}

class ConversationsModel::ConversationsModelPrivate
{
  public:
    QList<Conversation*> conversations;
};

ConversationsModel::ConversationsModel(QObject *parent) :
        QAbstractListModel(parent),
        Tp::AbstractClientHandler(channelClassList()),
        d(new ConversationsModelPrivate)
{
    QHash<int, QByteArray> roles;
    roles[ConversationRole] = "conversation";
    setRoleNames(roles);
    connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(totalUnreadCountChanged()));
    connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(totalUnreadCountChanged()));
}

ConversationsModel::~ConversationsModel()
{
    delete d;
}

QVariant ConversationsModel::data(const QModelIndex &index, int role) const
{
    QVariant result;
    if (index.isValid()) {
        if (role == ConversationRole) {
            result = QVariant::fromValue<Conversation*>(d->conversations[index.row()]);
            kDebug() << "returning value " << result;
        }
    }
    return result;
}

int ConversationsModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return d->conversations.count();
}

void ConversationsModel::handleChannels(const Tp::MethodInvocationContextPtr<> &context,
                                        const Tp::AccountPtr &account,
                                        const Tp::ConnectionPtr &connection,
                                        const QList<Tp::ChannelPtr> &channels,
                                        const QList<Tp::ChannelRequestPtr> &channelRequests,
                                        const QDateTime &userActionTime,
                                        const HandlerInfo &handlerInfo)
{
    Q_UNUSED(connection);
    Q_UNUSED(handlerInfo);

    bool handled = false;
    bool shouldDelegate = false;

    //check that the channel is of type text
    Tp::TextChannelPtr textChannel;
    Q_FOREACH(const Tp::ChannelPtr &channel, channels) {
        textChannel = Tp::TextChannelPtr::dynamicCast(channel);
        if (textChannel) {
            break;
        }
    }

    Q_ASSERT(textChannel);

    //find the relevant channelRequest
    Q_FOREACH(const Tp::ChannelRequestPtr channelRequest, channelRequests) {
        kDebug() << channelRequest->hints().allHints();
        shouldDelegate = channelRequest->hints().hint(QLatin1String("org.freedesktop.Telepathy.ChannelRequest"), QLatin1String("DelegateToPreferredHandler")).toBool();
    }

    //loop through all conversations checking for matches

    //if we are handling and we're not told to delegate it, update the text channel
    //if we are handling but should delegate, call delegate channel
    Q_FOREACH(Conversation *convo, d->conversations) {
        if (convo->target()->id() == textChannel->targetId() &&
                convo->messages()->textChannel()->targetHandleType() == textChannel->targetHandleType())
        {
            if (!shouldDelegate) {
                convo->messages()->setTextChannel(textChannel);
            } else {
                if (convo->messages()->textChannel() == textChannel) {
                    ChannelDelegator::delegateChannel(account, textChannel, userActionTime);
                }
            }
            handled = true;
            break;
        }
    }

    //if we are not handling channel already and should not delegate, add the conversation
    //if we not handling the channel but should delegate it, do nothing.

    if (!handled && !shouldDelegate) {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        Conversation *newConvo = new Conversation(textChannel, account, this);
        d->conversations.append(newConvo);
        connect(newConvo, SIGNAL(validityChanged(bool)), SLOT(handleValidityChange(bool)));
        connect(newConvo, SIGNAL(conversationDelegated()), SLOT(conversationDelegated()));
        connect(newConvo->messages(), SIGNAL(unreadCountChanged(int)), SIGNAL(totalUnreadCountChanged()));
        endInsertRows();
        context->setFinished();
    }

}

bool ConversationsModel::bypassApproval() const
{
    return true;
}

void ConversationsModel::startChat(const Tp::AccountPtr &account, const KTp::ContactPtr &contact)
{
    Q_ASSERT(account);
    account->ensureTextChat(contact, QDateTime::currentDateTime(),
                            QLatin1String("org.freedesktop.Telepathy.Client.KDE.TextUi.ConversationWatcher"));
}

void ConversationsModel::handleValidityChange(bool valid)
{
    if (!valid) {
        removeConversation(qobject_cast<Conversation*>(QObject::sender()));
    }
}

void ConversationsModel::conversationDelegated()
{
    removeConversation(qobject_cast<Conversation*>(QObject::sender()));
}

void ConversationsModel::removeConversation(Conversation* conv)
{
    int index = d->conversations.indexOf(conv);
    if (index != -1) {
        beginRemoveRows(QModelIndex(), index, index);
        d->conversations.removeAt(index);
        conv->deleteLater();
        endRemoveRows();
    } else {
        kError() << "attempting to delete non-existent conversation";
    }
}

int ConversationsModel::nextActiveConversation(int fromRow)
{
    if(d->conversations.isEmpty()) {
        return -1;
    }
    Q_ASSERT(qBound(0, fromRow, d->conversations.count()-1) == fromRow);

    bool first = true; //let first be checked on the first loop
    for(int i = fromRow; i != fromRow || first; i = (i + 1) % d->conversations.count()) {
        if(d->conversations[i]->messages()->unreadCount() > 0) {
            return i;
        }
        first = false;
    }
    return -1;
}

int ConversationsModel::totalUnreadCount() const
{
    int ret = 0;
    Q_FOREACH(Conversation *c, d->conversations) {
        ret += c->messages()->unreadCount();
    }
    return ret;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <seqan/index.h>

using namespace std;
using namespace seqan;

	struct TMySpec;

	template <typename TString, typename TSpec>
	bool nodePredicate(Iter<Index<TString, Index_Wotd<TMySpec> >, TSpec> const &it) {
		return (countOccurrences(it) >= 2) && (repLength(it) >= 4);
	}

int main ()
{
///We begin with a @Class.String@ to store our sequence.
	String<char> myString = "How many wood would a woodchuck chuck.";

///Then we create an @Class.Index@ of this @Class.StringSet@
	typedef Index< String<char>, Index_Wotd<TMySpec> > TMyIndex;
	TMyIndex myIndex(myString);

///To find maximal repeats, we use SeqAn's @Spec.MaxRepeats Iterator@
///and set the minimum repeat length to 3.
	typedef Iterator< TMyIndex, TopDown<ParentLinks<> > >::Type TMaxRepeatIterator;
	TMaxRepeatIterator myRepeatIterator(myIndex);

	goBegin(myRepeatIterator);
	while (!atEnd(myRepeatIterator))
	{

///@Function.countOccurrences@ returns the number of hits of the representative.
		cout << countOccurrences(myRepeatIterator) << "x  ";

///The repeat string itself can be determined with @Function.representative@
		cout << "\t\"" << representative(myRepeatIterator) << '\"' << endl;

		goNext(myRepeatIterator);
	}

	return 0;
}
<commit_msg><commit_after>#include <iostream>
#include <seqan/index.h>

using namespace std;
using namespace seqan;

/// constraint parameters
struct TMyConstraints {
	double p_min;
	int replen_max;
};

/// SeqAn extensions
namespace seqan
{
	// custom TSpec for our customized wotd-Index
	struct TMyIndex;

	template <typename TText>
	struct Cargo<Index<TText, Index_Wotd<TMyIndex> > > {
		typedef TMyConstraints Type;
	};

	// node predicate
	template <typename TText, typename TSpec>
	bool nodePredicate(Iter<Index<TText, Index_Wotd<TMyIndex> >, TSpec> const &it)
	{
		TMyConstraints const &cons = cargo(container(it));
		unsigned replen = repLength(it);
		unsigned textLen = length(container(it));

		if (textLen == replen) return false;
		return ((double)countOccurrences(it) /
				(double)(textLen - replen)) > cons.p_min;
	}

	// monotonic hull
	template <typename TText, typename TSpec>
	bool nodeHullPredicate(Iter<Index<TText, Index_Wotd<TMyIndex> >, TSpec> const &it)
	{
		Index<TText, Index_Wotd<TMyIndex> > const &index = container(it);
		TMyConstraints const &cons = cargo(index);

		if (repLength(it) > cons.replen_max) return false;
		return ((double)countOccurrences(it) /
				(double)(length(index) - cons.replen_max)) > cons.p_min;
	}
}

int main ()
{
///We begin with a @Class.String@ to store our sequence.
	String<char> myString = "How many wood would a woodchuck chuck.";

///Then we create our customized index which is a specialization
///of the deferred @Class.Index.wotd-Index@
	typedef Index< String<char>, Index_Wotd<TMyIndex> > TMyIndex;
	TMyIndex myIndex(myString);

	cargo(myIndex).replen_max = 10;
	cargo(myIndex).p_min = 0.05;

///To find all strings that fulfill our constraints,
///we simply do a dfs-traversal via @Function.goBegin@ and @Function.goNext@
	typedef Iterator< TMyIndex, TopDown<ParentLinks<> > >::Type TConstrainedIterator;
	TConstrainedIterator myConstrainedIterator(myIndex);

	goBegin(myConstrainedIterator);
	while (!atEnd(myConstrainedIterator))
	{

///@Function.countOccurrences@ returns the number of hits of the representative.
		cout << countOccurrences(myConstrainedIterator) << "x  ";

///The representative string can be determined with @Function.representative@
		cout << "\t\"" << representative(myConstrainedIterator) << '\"' << endl;

		goNext(myConstrainedIterator);
	}

	return 0;
}
<|endoftext|>


<commit_before>#include <osg/ApplicationUsage>
#include <osg/Math>

using namespace osg;

ApplicationUsage::ApplicationUsage(const std::string& commandLineUsage):
    _commandLineUsage(commandLineUsage)
{
}

ApplicationUsage* ApplicationUsage::instance()
{
    static ApplicationUsage s_applicationUsage;
    return &s_applicationUsage;
}

void ApplicationUsage::addUsageExplanation(Type type,const std::string& option,const std::string& explanation)
{
    switch(type)
    {
        case(COMMAND_LINE_OPTION):
            addCommandLineOption(option,explanation);
            break;
        case(ENVIRONMENTAL_VARIABLE):
            addEnvironmentalVariable(option,explanation);
            break;
        case(KEYBOARD_MOUSE_BINDING):
            addKeyboardMouseBinding(option,explanation);
            break;
    }
}

void ApplicationUsage::addCommandLineOption(const std::string& option,const std::string& explanation,const std::string& defaultValue)
{
    _commandLineOptions[option]=explanation;
    _commandLineOptionsDefaults[option]=defaultValue;
}

void ApplicationUsage::addEnvironmentalVariable(const std::string& option,const std::string& explanation, const std::string& defaultValue)
{
    _environmentalVariables[option]=explanation;
    _environmentalVariablesDefaults[option]=defaultValue;
}

void ApplicationUsage::addKeyboardMouseBinding(const std::string& option,const std::string& explanation)
{
    _keyboardMouse[option]=explanation;
}

void ApplicationUsage::getFormattedString(std::string& str, const UsageMap& um,unsigned int widthOfOutput,bool showDefaults,const UsageMap& ud)
{

    unsigned int maxNumCharsInOptions = 0;
    ApplicationUsage::UsageMap::const_iterator citr;
    for(citr=um.begin();
        citr!=um.end();
        ++citr)
    {
        maxNumCharsInOptions = maximum(maxNumCharsInOptions,(unsigned int)citr->first.length());
    }

    unsigned int fullWidth = widthOfOutput;
    unsigned int optionPos = 2;
    unsigned int explanationPos = optionPos+maxNumCharsInOptions+2;
    unsigned int defaultPos = 0;
    if (showDefaults)
    {
        defaultPos = explanationPos;
        explanationPos = optionPos+8;
    }
    unsigned int explanationWidth = fullWidth-explanationPos;

    std::string line;

    for(citr=um.begin();
        citr!=um.end();
        ++citr)
    {
        line.assign(fullWidth,' ');
        line.replace(optionPos,citr->first.length(),citr->first);

        if (showDefaults)
        {
            UsageMap::const_iterator ditr = ud.find(citr->first);
            if (ditr != ud.end())
            {
                line.replace(defaultPos, std::string::npos, "");
                if (ditr->second != "")
                {
                    line += "[";
                    line += ditr->second;
                    line += "]";
                }
                str += line;
                str += "\n";
                line.assign(fullWidth,' ');
            }
        }

        const std::string& explanation = citr->second;
        std::string::size_type pos = 0;
        std::string::size_type offset = 0;
        bool firstInLine = true;
        while (pos<explanation.length())
        {
            if (firstInLine) offset = 0;

            // skip any leading white space.
            while (pos<explanation.length() && explanation[pos]==' ')
            {
                if (firstInLine) ++offset;
                ++pos;
            }

            firstInLine = false;

            std::string::size_type width = minimum((std::string::size_type)(explanation.length()-pos),(std::string::size_type)(explanationWidth-offset));
            std::string::size_type slashn_pos = explanation.find('\n',pos);

            unsigned int extraSkip = 0;
            bool concatinated = false;
            if (slashn_pos!=std::string::npos)
            {
                if (slashn_pos<pos+width)
                {
                    width = slashn_pos-pos;
                    ++extraSkip;
                    firstInLine = true;
                }
                else if (slashn_pos==pos+width)
                {
                    ++extraSkip;
                    firstInLine = true;
                }
            }

            if (pos+width<explanation.length())
            {
                // now reduce width until we get a space or a return
                // so that we ensure that whole words are printed.
                while (width>0 &&
                       explanation[pos+width]!=' ' &&
                       explanation[pos+width]!='\n') --width;

                if (width==0)
                {
                    // word must be longer than a whole line so will need
                    // to concatinate it.
                    width = explanationWidth-1;
                    concatinated = true;
                }
            }

            line.replace(explanationPos+offset,explanationWidth, explanation, pos, width);

            if (concatinated) { str += line; str += "-\n"; }
            else { str += line; str += "\n"; }

            // move to the next line of output.
            line.assign(fullWidth,' ');

            pos += width+extraSkip;

        }

    }
}

void ApplicationUsage::write(std::ostream& output, const ApplicationUsage::UsageMap& um,unsigned int widthOfOutput,bool showDefaults,const ApplicationUsage::UsageMap& ud)
{
    std::string str;
    getFormattedString(str, um, widthOfOutput, showDefaults, ud);
    output << str << std::endl;
}

void ApplicationUsage::write(std::ostream& output, unsigned int type, unsigned int widthOfOutput, bool showDefaults)
{

    output << "Usage: "<<getCommandLineUsage()<<std::endl;
    bool needspace = false;
    if ((type&COMMAND_LINE_OPTION) && !getCommandLineOptions().empty())
    {
        if (needspace) output << std::endl;
        output << "Options";
        if (showDefaults) output << " [and default value]";
        output << ":"<<std::endl;
        write(output,getCommandLineOptions(),widthOfOutput,showDefaults,getCommandLineOptionsDefaults());
        needspace = true;
    }

    if ((type&ENVIRONMENTAL_VARIABLE) && !getEnvironmentalVariables().empty())
    {
        if (needspace) output << std::endl;
        output << "Environmental Variables";
        if (showDefaults) output << " [and default value]";
        output << ":"<<std::endl;
        write(output,getEnvironmentalVariables(),widthOfOutput,showDefaults,getEnvironmentalVariablesDefaults());
        needspace = true;
    }

    if ((type&KEYBOARD_MOUSE_BINDING) && !getKeyboardMouseBindings().empty())
    {
        if (needspace) output << std::endl;
        output << "Keyboard and Mouse Bindings:"<<std::endl;
        write(output,getKeyboardMouseBindings(),widthOfOutput);
        needspace = true;
    }

}

void ApplicationUsage::writeEnvironmentSettings(std::ostream& output)
{
    output << "Current Environment Settings:"<<std::endl;

    unsigned int maxNumCharsInOptions = 0;
    ApplicationUsage::UsageMap::const_iterator citr;
    for(citr=getEnvironmentalVariables().begin();
        citr!=getEnvironmentalVariables().end();
        ++citr)
    {
        std::string::size_type len = citr->first.find_first_of("\n\r\t ");
        if (len == std::string::npos) len = citr->first.size();
        maxNumCharsInOptions = maximum(maxNumCharsInOptions,(unsigned int) len);
    }

    unsigned int optionPos = 2;
    std::string line;

    for(citr=getEnvironmentalVariables().begin();
        citr!=getEnvironmentalVariables().end();
        ++citr)
    {
        line.assign(optionPos+maxNumCharsInOptions+2,' ');
        std::string::size_type len = citr->first.find_first_of("\n\r\t ");
        if (len == std::string::npos) len = citr->first.size();
        line.replace(optionPos,len,citr->first.substr(0,len));
        char *cp = getenv(citr->first.substr(0, len).c_str());
        if (!cp) cp = "[not set]";
        else if (!*cp) cp = "[set]";
        line += std::string(cp) + "\n";

        output << line;
    }
    output << std::endl;
}
<commit_msg>From Bob Kuehne, proper c++ cast instead of c-cast for ApplicationUsage<commit_after>#include <osg/ApplicationUsage>
#include <osg/Math>

using namespace osg;

ApplicationUsage::ApplicationUsage(const std::string& commandLineUsage):
    _commandLineUsage(commandLineUsage)
{
}

ApplicationUsage* ApplicationUsage::instance()
{
    static ApplicationUsage s_applicationUsage;
    return &s_applicationUsage;
}

void ApplicationUsage::addUsageExplanation(Type type,const std::string& option,const std::string& explanation)
{
    switch(type)
    {
        case(COMMAND_LINE_OPTION):
            addCommandLineOption(option,explanation);
            break;
        case(ENVIRONMENTAL_VARIABLE):
            addEnvironmentalVariable(option,explanation);
            break;
        case(KEYBOARD_MOUSE_BINDING):
            addKeyboardMouseBinding(option,explanation);
            break;
    }
}

void ApplicationUsage::addCommandLineOption(const std::string& option,const std::string& explanation,const std::string& defaultValue)
{
    _commandLineOptions[option]=explanation;
    _commandLineOptionsDefaults[option]=defaultValue;
}

void ApplicationUsage::addEnvironmentalVariable(const std::string& option,const std::string& explanation, const std::string& defaultValue)
{
    _environmentalVariables[option]=explanation;
    _environmentalVariablesDefaults[option]=defaultValue;
}

void ApplicationUsage::addKeyboardMouseBinding(const std::string& option,const std::string& explanation)
{
    _keyboardMouse[option]=explanation;
}

void ApplicationUsage::getFormattedString(std::string& str, const UsageMap& um,unsigned int widthOfOutput,bool showDefaults,const UsageMap& ud)
{

    unsigned int maxNumCharsInOptions = 0;
    ApplicationUsage::UsageMap::const_iterator citr;
    for(citr=um.begin();
        citr!=um.end();
        ++citr)
    {
        maxNumCharsInOptions = maximum(maxNumCharsInOptions,(unsigned int)citr->first.length());
    }

    unsigned int fullWidth = widthOfOutput;
    unsigned int optionPos = 2;
    unsigned int explanationPos = optionPos+maxNumCharsInOptions+2;
    unsigned int defaultPos = 0;
    if (showDefaults)
    {
        defaultPos = explanationPos;
        explanationPos = optionPos+8;
    }
    unsigned int explanationWidth = fullWidth-explanationPos;

    std::string line;

    for(citr=um.begin();
        citr!=um.end();
        ++citr)
    {
        line.assign(fullWidth,' ');
        line.replace(optionPos,citr->first.length(),citr->first);

        if (showDefaults)
        {
            UsageMap::const_iterator ditr = ud.find(citr->first);
            if (ditr != ud.end())
            {
                line.replace(defaultPos, std::string::npos, "");
                if (ditr->second != "")
                {
                    line += "[";
                    line += ditr->second;
                    line += "]";
                }
                str += line;
                str += "\n";
                line.assign(fullWidth,' ');
            }
        }

        const std::string& explanation = citr->second;
        std::string::size_type pos = 0;
        std::string::size_type offset = 0;
        bool firstInLine = true;
        while (pos<explanation.length())
        {
            if (firstInLine) offset = 0;

            // skip any leading white space.
            while (pos<explanation.length() && explanation[pos]==' ')
            {
                if (firstInLine) ++offset;
                ++pos;
            }

            firstInLine = false;

            std::string::size_type width = minimum((std::string::size_type)(explanation.length()-pos),(std::string::size_type)(explanationWidth-offset));
            std::string::size_type slashn_pos = explanation.find('\n',pos);

            unsigned int extraSkip = 0;
            bool concatinated = false;
            if (slashn_pos!=std::string::npos)
            {
                if (slashn_pos<pos+width)
                {
                    width = slashn_pos-pos;
                    ++extraSkip;
                    firstInLine = true;
                }
                else if (slashn_pos==pos+width)
                {
                    ++extraSkip;
                    firstInLine = true;
                }
            }

            if (pos+width<explanation.length())
            {
                // now reduce width until we get a space or a return
                // so that we ensure that whole words are printed.
                while (width>0 &&
                       explanation[pos+width]!=' ' &&
                       explanation[pos+width]!='\n') --width;

                if (width==0)
                {
                    // word must be longer than a whole line so will need
                    // to concatinate it.
                    width = explanationWidth-1;
                    concatinated = true;
                }
            }

            line.replace(explanationPos+offset,explanationWidth, explanation, pos, width);

            if (concatinated) { str += line; str += "-\n"; }
            else { str += line; str += "\n"; }

            // move to the next line of output.
            line.assign(fullWidth,' ');

            pos += width+extraSkip;

        }

    }
}

void ApplicationUsage::write(std::ostream& output, const ApplicationUsage::UsageMap& um,unsigned int widthOfOutput,bool showDefaults,const ApplicationUsage::UsageMap& ud)
{
    std::string str;
    getFormattedString(str, um, widthOfOutput, showDefaults, ud);
    output << str << std::endl;
}

void ApplicationUsage::write(std::ostream& output, unsigned int type, unsigned int widthOfOutput, bool showDefaults)
{

    output << "Usage: "<<getCommandLineUsage()<<std::endl;
    bool needspace = false;
    if ((type&COMMAND_LINE_OPTION) && !getCommandLineOptions().empty())
    {
        if (needspace) output << std::endl;
        output << "Options";
        if (showDefaults) output << " [and default value]";
        output << ":"<<std::endl;
        write(output,getCommandLineOptions(),widthOfOutput,showDefaults,getCommandLineOptionsDefaults());
        needspace = true;
    }

    if ((type&ENVIRONMENTAL_VARIABLE) && !getEnvironmentalVariables().empty())
    {
        if (needspace) output << std::endl;
        output << "Environmental Variables";
        if (showDefaults) output << " [and default value]";
        output << ":"<<std::endl;
        write(output,getEnvironmentalVariables(),widthOfOutput,showDefaults,getEnvironmentalVariablesDefaults());
        needspace = true;
    }

    if ((type&KEYBOARD_MOUSE_BINDING) && !getKeyboardMouseBindings().empty())
    {
        if (needspace) output << std::endl;
        output << "Keyboard and Mouse Bindings:"<<std::endl;
        write(output,getKeyboardMouseBindings(),widthOfOutput);
        needspace = true;
    }

}

void ApplicationUsage::writeEnvironmentSettings(std::ostream& output)
{
    output << "Current Environment Settings:"<<std::endl;

    unsigned int maxNumCharsInOptions = 0;
    ApplicationUsage::UsageMap::const_iterator citr;
    for(citr=getEnvironmentalVariables().begin();
        citr!=getEnvironmentalVariables().end();
        ++citr)
    {
        std::string::size_type len = citr->first.find_first_of("\n\r\t ");
        if (len == std::string::npos) len = citr->first.size();
        maxNumCharsInOptions = maximum( maxNumCharsInOptions,static_cast<unsigned int>(len));
    }

    unsigned int optionPos = 2;
    std::string line;

    for(citr=getEnvironmentalVariables().begin();
        citr!=getEnvironmentalVariables().end();
        ++citr)
    {
        line.assign(optionPos+maxNumCharsInOptions+2,' ');
        std::string::size_type len = citr->first.find_first_of("\n\r\t ");
        if (len == std::string::npos) len = citr->first.size();
        line.replace(optionPos,len,citr->first.substr(0,len));
        char *cp = getenv(citr->first.substr(0, len).c_str());
        if (!cp) cp = "[not set]";
        else if (!*cp) cp = "[set]";
        line += std::string(cp) + "\n";

        output << line;
    }
    output << std::endl;
}
<|endoftext|>


<commit_before>// UjoImro, 2013

#ifndef __OPENCL_HPP__
#define __OPENCL_HPP__

#include <string>
#include <vector>
#include <CL/cl.h>
#include <fstream>
#include <stdexcept>
#include <boost/foreach.hpp>
#include <boost/smart_ptr.hpp>

#include "errors.hpp"

namespace carp {
    namespace opencl {

        std::string
        readfile( const std::string & filename )
        {
            std::ifstream input( filename, std::ifstream::binary );

            if (!input) throw std::runtime_error("error: Couldn't open file `" + filename + "'" );

            input.seekg(0, input.end);
            int length = input.tellg();
            input.seekg(0, input.beg);

            boost::scoped_array<char> result_c_str(new char[length+1]);
            input.read(result_c_str.get(), length);
            if (!input) throw std::runtime_error("error: Could not read file `" + filename + "'");

            std::string result(result_c_str.get());

            return result;
        } // readfile

        class kernel {
        private:
            cl_kernel cqKernel;

        public:
            kernel() : cqKernel(NULL) { };

            kernel & operator= ( cl_kernel cqKernel ) {
                this->cqKernel = cqKernel;
                return *this;
            } // operator=

            void release() {
                if (cqKernel) clReleaseKernel(cqKernel);
                cqKernel=NULL;
            } // release

        }; // class kernel

        class device {
        private:
            typedef std::map<std::string, opencl::kernel> kernels_t;

            cl_context cxGPUContext;        // OpenCL context
            cl_command_queue cqCommandQueue;// OpenCL command queue
            cl_platform_id cpPlatform;      // OpenCL platform
            cl_device_id cdDevice;          // OpenCL device
            cl_program cpProgram;           // OpenCL program
            kernels_t kernels; // OpenCL kernel
            cl_uint num_platforms;          // The number of OpenCL platforms
            cl_uint num_devices;            // The number of OpenCL devices

        public:

            device() {
                cl_int err; // for the error messages

                device::check(clGetPlatformIDs(1, &cpPlatform, &num_platforms), __FILE__, __LINE__ );
                assert(num_platforms==1);  // there is only one supported platform at the time

                device::check(clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &cdDevice, &num_devices), __FILE__, __LINE__ );
                assert(num_devices==1);

                cxGPUContext = clCreateContext( NULL, 1, &cdDevice, NULL, NULL, &err );
                device::check( err, __FILE__, __LINE__ );

                cqCommandQueue = clCreateCommandQueue( cxGPUContext, cdDevice, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &err );
                device::check( err, __FILE__, __LINE__ );

            }

            static void check(
                const cl_int & error,
                const std::string & filename = __FILE__,
                const int & line = __LINE__
                ) throw (std::exception&) {
                if ( error != CL_SUCCESS )
                    throw std::runtime_error( std::string("error: OpenCL: ") +
                                              carp::opencl::errors[error] +
                                              "; line: " + std::to_string(__LINE__) + " in file " + __FILE__ );
            }

            ~device() {
                if(cpProgram) clReleaseProgram(cpProgram);
                if(cqCommandQueue) clReleaseCommandQueue(cqCommandQueue);
                if(cxGPUContext) clReleaseContext(cxGPUContext);
                std::for_each( kernels.begin(), kernels.end(), [] ( kernels_t::allocator_type::value_type & kernel ) {// kernel->second.release();
                    } );
            } // ~device

            void compile( const std::vector<std::string> & filenames,
                          const std::vector<std::string> & kernelnames ) {
                cl_int err;

                // loading the sources
                std::vector<std::string> sources;
                std::vector<const char*> c_strs;
                std::vector<size_t> lengths;

                BOOST_FOREACH( std::string filename, filenames ) {
                    sources.push_back(readfile(filename));
                    c_strs.push_back(sources.back().c_str());
                    lengths.push_back(sources.back().size());
                }

                cpProgram = clCreateProgramWithSource( cxGPUContext, sources.size(), &(c_strs[0]), &(lengths[0]), &err );
                device::check(err);

                // building the OpenCL source code
                err = clBuildProgram( cpProgram, 0, NULL, NULL, NULL, NULL );
                if ( err!=CL_SUCCESS )
                {
                    size_t len;
                    std::string buffer(1048576, 0);

                    device::check( clGetProgramBuildInfo( cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, buffer.size(), reinterpret_cast<void*>(&buffer[0]), &len ) );

                    std::cerr << buffer << std::endl;
                    throw std::runtime_error("error: OpenCL: The compilation has failed.");
                }

                // extracting the kernel entrances
                BOOST_FOREACH( std::string kernel_name, kernelnames )
                {
                    cl_int err;
                    kernels[kernel_name] = clCreateKernel( cpProgram, kernel_name.c_str(), &err);
                    device::check(err);
                }

                return;
            } // compile

            kernel & operator [] ( const std::string & filename ) {
                return kernels[filename];
            } // operator[]
        }; // class device

    } // namespace opencl
} // namespace carp

#endif /* __OPENCL_HPP__ */
// LuM end of file
<commit_msg>created the opencl array<commit_after>// UjoImro, 2013

#ifndef __OPENCL_HPP__
#define __OPENCL_HPP__

#include <string>
#include <vector>
#include <CL/cl.h>
#include <fstream>
#include <stdexcept>
#include <boost/foreach.hpp>
#include <boost/smart_ptr.hpp>

#include "errors.hpp"

namespace carp {
    namespace opencl {

        std::string
        readfile( const std::string & filename )
        {
            std::ifstream input( filename, std::ifstream::binary );

            if (!input) throw std::runtime_error("error: Couldn't open file `" + filename + "'" );

            input.seekg(0, input.end);
            int length = input.tellg();
            input.seekg(0, input.beg);

            boost::scoped_array<char> result_c_str(new char[length+1]);
            input.read(result_c_str.get(), length);
            if (!input) throw std::runtime_error("error: Could not read file `" + filename + "'");

            std::string result(result_c_str.get());

            return result;
        } // readfile

        void checkerror(
            const cl_int & error,
            const std::string & filename = __FILE__,
            const int & line = __LINE__
            ) throw (std::exception&) {
            if ( error != CL_SUCCESS )
                throw std::runtime_error( std::string("error: OpenCL: ") +
                                          carp::opencl::errors[error] +
                                          "; line: " + std::to_string(__LINE__) + " in file " + __FILE__ );
        }

        class kernel {
        private:
            cl_kernel cqKernel;

            template <class MT0, class Pos>
            bool
            setparameter( Pos & pos, MT0 & mt0 ) {
                checkerror( clSetKernelArg(cqKernel, pos, sizeof(mt0), static_cast<void*>(&mt0) ), __FILE__, __LINE__ );
                pos++; // move the position of the parameter applied
                return true;
            } // setparameter

        public:
            kernel() : cqKernel(NULL) { };

            kernel & operator= ( cl_kernel cqKernel ) {
                this->cqKernel = cqKernel;
                return *this;
            } // operator=

            void release() {
                if (cqKernel) clReleaseKernel(cqKernel);
                cqKernel=NULL;
            } // release

            template <class ...MT>
            void operator() ( MT ... mt ) {
                int pos=0; // the position of the parameters
                std::vector<bool> err { setparameter(pos, mt)... };
            } // operator ()

        }; // class kernel

        class device {
        private:
            typedef std::map<std::string, opencl::kernel> kernels_t;

            cl_context cxGPUContext;        // OpenCL context
            cl_command_queue cqCommandQueue;// OpenCL command queue
            cl_platform_id cpPlatform;      // OpenCL platform
            cl_device_id cdDevice;          // OpenCL device
            cl_program cpProgram;           // OpenCL program
            kernels_t kernels; // OpenCL kernel
            cl_uint num_platforms;          // The number of OpenCL platforms
            cl_uint num_devices;            // The number of OpenCL devices

        public:

            device() {
                cl_int err; // for the error messages

                checkerror(clGetPlatformIDs(1, &cpPlatform, &num_platforms), __FILE__, __LINE__ );
                assert(num_platforms==1);  // there is only one supported platform at the time

                checkerror(clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &cdDevice, &num_devices), __FILE__, __LINE__ );
                assert(num_devices==1);

                cxGPUContext = clCreateContext( NULL, 1, &cdDevice, NULL, NULL, &err );
                checkerror( err, __FILE__, __LINE__ );

                cqCommandQueue = clCreateCommandQueue( cxGPUContext, cdDevice, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &err );
                checkerror( err, __FILE__, __LINE__ );

            }

            ~device() {
                if(cpProgram) clReleaseProgram(cpProgram);
                if(cqCommandQueue) clReleaseCommandQueue(cqCommandQueue);
                if(cxGPUContext) clReleaseContext(cxGPUContext);
                std::for_each( kernels.begin(), kernels.end(), [] ( kernels_t::allocator_type::value_type & kernel ) {// kernel->second.release();
                    } );
            } // ~device

            void compile( const std::vector<std::string> & filenames,
                          const std::vector<std::string> & kernelnames ) {
                cl_int err;

                // loading the sources
                std::vector<std::string> sources;
                std::vector<const char*> c_strs;
                std::vector<size_t> lengths;

                BOOST_FOREACH( std::string filename, filenames ) {
                    sources.push_back(readfile(filename));
                    c_strs.push_back(sources.back().c_str());
                    lengths.push_back(sources.back().size());
                }

                cpProgram = clCreateProgramWithSource( cxGPUContext, sources.size(), &(c_strs[0]), &(lengths[0]), &err );
                checkerror(err, __FILE__, __LINE__ );

                // building the OpenCL source code
                err = clBuildProgram( cpProgram, 0, NULL, NULL, NULL, NULL );
                if ( err!=CL_SUCCESS )
                {
                    size_t len;
                    std::string buffer(1048576, 0);

                    checkerror( clGetProgramBuildInfo( cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, buffer.size(), reinterpret_cast<void*>(&buffer[0]), &len ), __FILE__, __LINE__ );

                    std::cerr << buffer << std::endl;
                    throw std::runtime_error("error: OpenCL: The compilation has failed.");
                }

                // extracting the kernel entrances
                BOOST_FOREACH( std::string kernel_name, kernelnames )
                {
                    cl_int err;
                    kernels[kernel_name] = clCreateKernel( cpProgram, kernel_name.c_str(), &err);
                    checkerror(err, __FILE__, __LINE__ );
                }

                return;
            } // compile

            kernel & operator [] ( const std::string & filename ) {
                return kernels[filename];
            } // operator[]
        }; // class device

        template <class T0>
        class array {
        private:
            cl_mem cl_ptr;
            size_t size;
            cl_context context;
            cl_command_queue command_queue;

            array( const array<T0> & ) { } // copy constructor forbidden

        public:
            array( const cl_context & context,
                   const cl_command_queue & command_queue,
                   const size_t & size,
                   cl_mem_flags flags = CL_MEM_READ_WRITE
                ) : size(size), context(context), command_queue(command_queue) {
                assert( (flags & CL_MEM_USE_HOST_PTR) == 0 );
                cl_int err;
                cl_ptr = clCreateBuffer( context, flags, size * sizeof(T0), NULL, &err );
                checkerror( err, __FILE__, __LINE__ );
            } // array

            array( const cl_context & context,
                   const cl_command_queue & command_queue,
                   std::vector<T0> & input,
                   cl_mem_flags flags = CL_MEM_READ_WRITE
                ) : size(input.size()) {
                cl_int err;
                cl_ptr = clCreateBuffer( context, flags | CL_MEM_COPY_HOST_PTR, size * sizeof(T0), reinterpret_cast<void*>(intput[0]), &err );
                checkerror( err, __FILE__, __LINE__ );
            } // array

            cl_mem get() {
                return cl_ptr;
            } // get

            ~array() {
                clReleaseMemObject(cl_ptr);
            } // ~array

            size_t size() {
                return size;
            } // size

            std::vector<T0> extract( ) {
                std::vector<T0> result(size);
                checkerror( clEnqueueReadBuffer( command_queue, cl_ptr, CL_TRUE, 0, sizeof(T0) * size, &(result[0]), 0, NULL, NULL), __FILE__, __LINE__ );

                return result;
            } // extract

        }; // class array

    } // namespace opencl
} // namespace carp

#endif /* __OPENCL_HPP__ */
// LuM end of file
<|endoftext|>


<commit_before>#include "pegr/gensys/PodChunk.hpp"

#include <cassert>
#include <algorithm>

namespace pegr {
namespace Gensys {
namespace Pod {

Chunk_Ptr::Chunk_Ptr(void* chunk, std::size_t size)
: m_voidptr(chunk)
, m_size(size) {
    assert(m_size % 8 == 0);
}

Chunk_Ptr::Chunk_Ptr()
: m_voidptr(nullptr)
, m_size(0) {}

bool Chunk_Ptr::is_nullptr() const {
    return m_voidptr == nullptr;
}
void Chunk_Ptr::make_nullptr() {
    m_voidptr = nullptr;
    m_size = 0;
}

void* Chunk_Ptr::get_raw() const {
    return m_voidptr;
}
std::size_t Chunk_Ptr::get_size() const {
    return m_size;
}

bool Chunk_Ptr::operator ==(const Chunk_Ptr& rhs) const {
    return m_voidptr == rhs.m_voidptr;
}
bool Chunk_Ptr::operator !=(const Chunk_Ptr& rhs) const {
    return m_voidptr != rhs.m_voidptr;
}
Chunk_Ptr::operator bool() const {
    return m_voidptr == nullptr;
}

bool operator ==(std::nullptr_t, const Chunk_Ptr& rhs) {
    return rhs.m_voidptr == nullptr;
}
bool operator ==(const Chunk_Ptr& lhs, std::nullptr_t) {
    return lhs.m_voidptr == nullptr;
}
bool operator !=(std::nullptr_t, const Chunk_Ptr& rhs) {
    return rhs.m_voidptr != nullptr;
}
bool operator !=(const Chunk_Ptr& lhs, std::nullptr_t) {
    return lhs.m_voidptr != nullptr;
}

void Chunk_Ptr_Deleter::operator ()(pointer ptr) const {
    delete_pod_chunk(ptr);
}

Chunk_Ptr new_pod_chunk(std::size_t req_size) {
    if (req_size == 0) {
        int64_t* chunk = new int64_t[1];
        return Chunk_Ptr(chunk, 0);
    }

    // Fewest number of int64's that can hold the requested number of bytes
    std::size_t size = (req_size / 8) + (req_size % 8 == 0 ? 0 : 1);
    int64_t* chunk = new int64_t[size];
    return Chunk_Ptr(chunk, size);
}

void delete_pod_chunk(Chunk_Ptr ptr) {
    if (!ptr.get_raw()) return;

    delete[] static_cast<int64_t*>(ptr.get_raw());
}

void copy_pod_chunk(
        Chunk_Ptr src, std::size_t src_start,
        Chunk_Ptr dest, std::size_t dest_start, std::size_t num_bytes) {

    assert(src_start % 8 == 0);
    assert(dest_start % 8 == 0);
    assert(num_bytes % 8 == 0);
    assert(src_start >= 0);
    assert(dest_start >= 0);
    assert(num_bytes >= 0);
    assert(!dest.is_nullptr());
    assert(num_bytes <= src.get_size() - src_start);
    assert(num_bytes <= dest.get_size() - dest_start);

    if (src.is_nullptr()) {
        assert(num_bytes == 0);
        return;
    }

    int64_t* src_array = static_cast<int64_t*>(src.get_raw());
    int64_t* dest_array = static_cast<int64_t*>(dest.get_raw());

    std::copy(
        src_array + (src_start / 8),
        src_array + ((src_start + num_bytes) / 8),
        dest_array + (dest_start / 8));
}

} // namespace Pod
} // namespace Gensys
} // namespace pegr
<commit_msg>Use proper null check<commit_after>#include "pegr/gensys/PodChunk.hpp"

#include <cassert>
#include <algorithm>

namespace pegr {
namespace Gensys {
namespace Pod {

Chunk_Ptr::Chunk_Ptr(void* chunk, std::size_t size)
: m_voidptr(chunk)
, m_size(size) {
    assert(m_size % 8 == 0);
}

Chunk_Ptr::Chunk_Ptr()
: m_voidptr(nullptr)
, m_size(0) {}

bool Chunk_Ptr::is_nullptr() const {
    return m_voidptr == nullptr;
}
void Chunk_Ptr::make_nullptr() {
    m_voidptr = nullptr;
    m_size = 0;
}

void* Chunk_Ptr::get_raw() const {
    return m_voidptr;
}
std::size_t Chunk_Ptr::get_size() const {
    return m_size;
}

bool Chunk_Ptr::operator ==(const Chunk_Ptr& rhs) const {
    return m_voidptr == rhs.m_voidptr;
}
bool Chunk_Ptr::operator !=(const Chunk_Ptr& rhs) const {
    return m_voidptr != rhs.m_voidptr;
}
Chunk_Ptr::operator bool() const {
    return m_voidptr == nullptr;
}

bool operator ==(std::nullptr_t, const Chunk_Ptr& rhs) {
    return rhs.m_voidptr == nullptr;
}
bool operator ==(const Chunk_Ptr& lhs, std::nullptr_t) {
    return lhs.m_voidptr == nullptr;
}
bool operator !=(std::nullptr_t, const Chunk_Ptr& rhs) {
    return rhs.m_voidptr != nullptr;
}
bool operator !=(const Chunk_Ptr& lhs, std::nullptr_t) {
    return lhs.m_voidptr != nullptr;
}

void Chunk_Ptr_Deleter::operator ()(pointer ptr) const {
    delete_pod_chunk(ptr);
}

Chunk_Ptr new_pod_chunk(std::size_t req_size) {
    /* Special case if there is no size: Create a "zero-length" array
     * NOT nullptr! This ensures that no two independent return values for this
     * function are equal!
     */
    if (req_size == 0) {
        int64_t* chunk = new int64_t[1];
        return Chunk_Ptr(chunk, 0);
    }

    // Fewest number of int64's that can hold the requested number of bytes
    std::size_t size = (req_size / 8) + (req_size % 8 == 0 ? 0 : 1);
    int64_t* chunk = new int64_t[size];
    return Chunk_Ptr(chunk, size);
}

void delete_pod_chunk(Chunk_Ptr ptr) {
    if (ptr.is_nullptr()) return;
    delete[] static_cast<int64_t*>(ptr.get_raw());
}

void copy_pod_chunk(
        Chunk_Ptr src, std::size_t src_start,
        Chunk_Ptr dest, std::size_t dest_start, std::size_t num_bytes) {

    assert(src_start % 8 == 0);
    assert(dest_start % 8 == 0);
    assert(num_bytes % 8 == 0);
    assert(src_start >= 0);
    assert(dest_start >= 0);
    assert(num_bytes >= 0);
    assert(!dest.is_nullptr());
    assert(num_bytes <= src.get_size() - src_start);
    assert(num_bytes <= dest.get_size() - dest_start);

    if (src.is_nullptr()) {
        assert(num_bytes == 0);
        return;
    }

    int64_t* src_array = static_cast<int64_t*>(src.get_raw());
    int64_t* dest_array = static_cast<int64_t*>(dest.get_raw());

    std::copy(
        src_array + (src_start / 8),
        src_array + ((src_start + num_bytes) / 8),
        dest_array + (dest_start / 8));
}

} // namespace Pod
} // namespace Gensys
} // namespace pegr
<|endoftext|>