<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief V8 line editor
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "V8LineEditor.h"
#include "Basics/logging.h"
#include "Basics/StringUtils.h"
#include "Basics/tri-strings.h"
#include "Utilities/ShellImplementation.h"
#include "Utilities/ShellImplFactory.h"
#include "V8/v8-utils.h"

using namespace std;
using namespace triagens;
using namespace arangodb;

// -----------------------------------------------------------------------------
// --SECTION--                                                  helper functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief signal handler for CTRL-C
////////////////////////////////////////////////////////////////////////////////

#ifndef _WIN32

static void SignalHandler (int signal) {
  // get the instance of the console
  auto instance = V8LineEditor::instance();

  if (instance != nullptr) {
    if (instance->isExecutingCommand()) {
      v8::Isolate* isolate = instance->isolate();

      if (! v8::V8::IsExecutionTerminating(isolate)) {
        v8::V8::TerminateExecution(isolate);
      }
    }

    instance->signal();
  }
}

#endif

// -----------------------------------------------------------------------------
// --SECTION--                                                 class V8Completer
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                                 Completer methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////

bool V8Completer::isComplete (std::string const& source, size_t lineno) {
  int openParen    = 0;
  int openBrackets = 0;
  int openBraces   = 0;
  int openStrings  = 0;  // only used for template strings, which can be multi-line
  int openComments = 0;

  enum line_parse_state_e {
    NORMAL,             // start
    NORMAL_1,           // from NORMAL: seen a single /
    DOUBLE_QUOTE,       // from NORMAL: seen a single "
    DOUBLE_QUOTE_ESC,   // from DOUBLE_QUOTE: seen a backslash
    SINGLE_QUOTE,       // from NORMAL: seen a single '
    SINGLE_QUOTE_ESC,   // from SINGLE_QUOTE: seen a backslash
    BACKTICK,           // from NORMAL: seen a single `
    BACKTICK_ESC,       // from BACKTICK: seen a backslash
    MULTI_COMMENT,      // from NORMAL_1: seen a *
    MULTI_COMMENT_1,    // from MULTI_COMMENT, seen a *
    SINGLE_COMMENT      // from NORMAL_1; seen a /
  };

  char const* ptr = source.c_str();
  char const* end = ptr + source.length();
  line_parse_state_e state = NORMAL;

  while (ptr < end) {
    if (state == DOUBLE_QUOTE) {
      if (*ptr == '\\') {
        state = DOUBLE_QUOTE_ESC;
      }
      else if (*ptr == '"') {
        state = NORMAL;
      }

      ++ptr;
    }
    else if (state == DOUBLE_QUOTE_ESC) {
      state = DOUBLE_QUOTE;
      ptr++;
    }
    else if (state == SINGLE_QUOTE) {
      if (*ptr == '\\') {
        state = SINGLE_QUOTE_ESC;
      }
      else if (*ptr == '\'') {
        state = NORMAL;
      }

      ++ptr;
    }
    else if (state == SINGLE_QUOTE_ESC) {
      state = SINGLE_QUOTE;
      ptr++;
    }
    else if (state == BACKTICK) {
      if (*ptr == '\\') {
        state = BACKTICK_ESC;
      }
      else if (*ptr == '`') {
        state = NORMAL;
        --openStrings;
      }

      ++ptr;
    }
    else if (state == BACKTICK_ESC) {
      state = BACKTICK;
      ptr++;
    }
    else if (state == MULTI_COMMENT) {
      if (*ptr == '*') {
        state = MULTI_COMMENT_1;
      }

      ++ptr;
    }
    else if (state == MULTI_COMMENT_1) {
      if (*ptr == '/') {
        state = NORMAL;
        --openComments;
      }

      ++ptr;
    }
    else if (state == SINGLE_COMMENT) {
      ++ptr;

      if (ptr == end) {
        state = NORMAL;
        --openComments;
      }
    }
    else if (state == NORMAL_1) {
      switch (*ptr) {
        case '/':
          state = SINGLE_COMMENT;
          ++openComments;
          ++ptr;
          break;

        case '*':
          state = MULTI_COMMENT;
          ++openComments;
          ++ptr;
          break;

        default:
          state = NORMAL; // try again, do not change ptr
          break;
      }
    }
    else {
      switch (*ptr) {
        case '"':
          state = DOUBLE_QUOTE;
          break;

        case '\'':
          state = SINGLE_QUOTE;
          break;

        case '`':
          state = BACKTICK;
          ++openStrings;
          break;

        case '/':
          state = NORMAL_1;
          break;

        case '(':
          ++openParen;
          break;

        case ')':
          --openParen;
          break;

        case '[':
          ++openBrackets;
          break;

        case ']':
          --openBrackets;
          break;

        case '{':
          ++openBraces;
          break;

        case '}':
          --openBraces;
          break;

        case '\\':
          ++ptr;
          break;
      }

      ++ptr;
    }
  }

  return (openParen <= 0 && openBrackets <= 0 && openBraces <= 0 && openStrings <= 0 && openComments <= 0);
}

////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////

vector<string> V8Completer::alternatives (char const * text) {
  vector<string> result;

  // locate global object or sub-object
  v8::Isolate* isolate = v8::Isolate::GetCurrent();

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Handle<v8::Object> current = context->Global();
  string path;
  char* prefix;

  if (*text != '\0') {
    TRI_vector_string_t splitted = TRI_SplitString(text, '.');

    if (1 < splitted._length) {
      for (size_t i = 0;  i < splitted._length - 1;  ++i) {
        v8::Handle<v8::String> name = TRI_V8_STRING(splitted._buffer[i]);

        if (! current->Has(name)) {
          TRI_DestroyVectorString(&splitted);
          return result;
        }

        v8::Handle<v8::Value> val = current->Get(name);

        if (! val->IsObject()) {
          TRI_DestroyVectorString(&splitted);
          return result;
        }

        current = val->ToObject();
        path = path + splitted._buffer[i] + ".";
      }

      prefix = TRI_DuplicateString(splitted._buffer[splitted._length - 1]);
    }
    else {
      prefix = TRI_DuplicateString(text);
    }

    TRI_DestroyVectorString(&splitted);
  }
  else {
    prefix = TRI_DuplicateString(text);
  }

  v8::HandleScope scope(isolate);

  // compute all possible completions
  v8::Handle<v8::Array> properties;
  v8::Handle<v8::String> cpl = TRI_V8_ASCII_STRING("_COMPLETIONS");

  if (current->HasOwnProperty(cpl)) {
    v8::Handle<v8::Value> funcVal = current->Get(cpl);

    if (funcVal->IsFunction()) {
      v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(funcVal);
      v8::Handle<v8::Value> args;

      try {
        v8::Handle<v8::Value> cpls = func->Call(current, 0, &args);

        if (cpls->IsArray()) {
          properties = v8::Handle<v8::Array>::Cast(cpls);
        }
      }
      catch (...) {
        // silently ignore errors here
      }
    }
  }
  else {
    properties = current->GetPropertyNames();
  }

  // locate
  try {
    if (! properties.IsEmpty()) {
      uint32_t const n = properties->Length();
      result.reserve(static_cast<size_t>(n));

      for (uint32_t i = 0;  i < n;  ++i) {
        v8::Handle<v8::Value> v = properties->Get(i);

        TRI_Utf8ValueNFC str(TRI_UNKNOWN_MEM_ZONE, v);
        char const* s = *str;

        if (s != nullptr && *s) {
          string suffix = (current->Get(v)->IsFunction()) ? "()" : "";
          string name = path + s + suffix;

          if (*prefix == '\0' || TRI_IsPrefixString(s, prefix)) {
            result.emplace_back(name);
          }
        }
      }
    }
  }
  catch (...) {
    // ignore errors in case of OOM
  }

  TRI_FreeString(TRI_CORE_MEM_ZONE, prefix);
  return result;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                class V8LineEditor
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                          static private variables
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief the active instance of the editor
////////////////////////////////////////////////////////////////////////////////

std::atomic<V8LineEditor*> V8LineEditor::_instance(nullptr);

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new editor
////////////////////////////////////////////////////////////////////////////////

V8LineEditor::V8LineEditor (v8::Isolate* isolate,
                            v8::Handle<v8::Context> context,
                            std::string const& history)
  : LineEditor(history),
    _isolate(isolate),
    _context(context),
    _completer(V8Completer()),
    _executingCommand(false) {

  // register global instance
  TRI_ASSERT(_instance.load() == nullptr);
  _instance.store(this);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys the editor
////////////////////////////////////////////////////////////////////////////////

V8LineEditor::~V8LineEditor () {
  // unregister global instance
  TRI_ASSERT(_instance.load() != nullptr);
  _instance.store(nullptr);
}

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

////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the shell implementation supports colors
////////////////////////////////////////////////////////////////////////////////

bool V8LineEditor::supportsColors () const {
  if (_shellImpl == nullptr) {
    return false;
  }

  return _shellImpl->supportsColors();
}

// -----------------------------------------------------------------------------
// --SECTION--                                                 protected methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup a signal handler for CTRL-C
////////////////////////////////////////////////////////////////////////////////

void V8LineEditor::setupCtrlCHandler () {
#ifndef _WIN32
  if (_shellImpl != nullptr &&
      _shellImpl->supportsCtrlCHandler()) {
    struct sigaction sa;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = &SignalHandler;

    int res = sigaction(SIGINT, &sa, 0);

    if (res != 0) {
      LOG_ERROR("unable to install signal handler");
    }
  }
#endif
}

// -----------------------------------------------------------------------------
// --SECTION--                                                 protected methods
// -----------------------------------------------------------------------------

void V8LineEditor::initializeShell () {
  _shellImpl = ShellImplFactory::buildShell(_history, &_completer);

  setupCtrlCHandler();
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------
<commit_msg>do not halt on single-line comments<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief V8 line editor
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "V8LineEditor.h"
#include "Basics/logging.h"
#include "Basics/StringUtils.h"
#include "Basics/tri-strings.h"
#include "Utilities/ShellImplementation.h"
#include "Utilities/ShellImplFactory.h"
#include "V8/v8-utils.h"

using namespace std;
using namespace triagens;
using namespace arangodb;

// -----------------------------------------------------------------------------
// --SECTION--                                                  helper functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief signal handler for CTRL-C
////////////////////////////////////////////////////////////////////////////////

#ifndef _WIN32

static void SignalHandler (int signal) {
  // get the instance of the console
  auto instance = V8LineEditor::instance();

  if (instance != nullptr) {
    if (instance->isExecutingCommand()) {
      v8::Isolate* isolate = instance->isolate();

      if (! v8::V8::IsExecutionTerminating(isolate)) {
        v8::V8::TerminateExecution(isolate);
      }
    }

    instance->signal();
  }
}

#endif

// -----------------------------------------------------------------------------
// --SECTION--                                                 class V8Completer
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                                 Completer methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////

bool V8Completer::isComplete (std::string const& source, size_t lineno) {
  int openParen    = 0;
  int openBrackets = 0;
  int openBraces   = 0;
  int openStrings  = 0;  // only used for template strings, which can be multi-line
  int openComments = 0;

  enum line_parse_state_e {
    NORMAL,             // start
    NORMAL_1,           // from NORMAL: seen a single /
    DOUBLE_QUOTE,       // from NORMAL: seen a single "
    DOUBLE_QUOTE_ESC,   // from DOUBLE_QUOTE: seen a backslash
    SINGLE_QUOTE,       // from NORMAL: seen a single '
    SINGLE_QUOTE_ESC,   // from SINGLE_QUOTE: seen a backslash
    BACKTICK,           // from NORMAL: seen a single `
    BACKTICK_ESC,       // from BACKTICK: seen a backslash
    MULTI_COMMENT,      // from NORMAL_1: seen a *
    MULTI_COMMENT_1,    // from MULTI_COMMENT, seen a *
    SINGLE_COMMENT      // from NORMAL_1; seen a /
  };

  char const* ptr = source.c_str();
  char const* end = ptr + source.length();
  line_parse_state_e state = NORMAL;

  while (ptr < end) {
    if (state == DOUBLE_QUOTE) {
      if (*ptr == '\\') {
        state = DOUBLE_QUOTE_ESC;
      }
      else if (*ptr == '"') {
        state = NORMAL;
      }

      ++ptr;
    }
    else if (state == DOUBLE_QUOTE_ESC) {
      state = DOUBLE_QUOTE;
      ptr++;
    }
    else if (state == SINGLE_QUOTE) {
      if (*ptr == '\\') {
        state = SINGLE_QUOTE_ESC;
      }
      else if (*ptr == '\'') {
        state = NORMAL;
      }

      ++ptr;
    }
    else if (state == SINGLE_QUOTE_ESC) {
      state = SINGLE_QUOTE;
      ptr++;
    }
    else if (state == BACKTICK) {
      if (*ptr == '\\') {
        state = BACKTICK_ESC;
      }
      else if (*ptr == '`') {
        state = NORMAL;
        --openStrings;
      }

      ++ptr;
    }
    else if (state == BACKTICK_ESC) {
      state = BACKTICK;
      ptr++;
    }
    else if (state == MULTI_COMMENT) {
      if (*ptr == '*') {
        state = MULTI_COMMENT_1;
      }

      ++ptr;
    }
    else if (state == MULTI_COMMENT_1) {
      if (*ptr == '/') {
        state = NORMAL;
        --openComments;
      }

      ++ptr;
    }
    else if (state == SINGLE_COMMENT) {
      ++ptr;

      if (ptr == end || *ptr == '\n') {
        state = NORMAL;
        --openComments;
      }
    }
    else if (state == NORMAL_1) {
      switch (*ptr) {
        case '/':
          state = SINGLE_COMMENT;
          ++openComments;
          ++ptr;
          break;

        case '*':
          state = MULTI_COMMENT;
          ++openComments;
          ++ptr;
          break;

        default:
          state = NORMAL; // try again, do not change ptr
          break;
      }
    }
    else {
      switch (*ptr) {
        case '"':
          state = DOUBLE_QUOTE;
          break;

        case '\'':
          state = SINGLE_QUOTE;
          break;

        case '`':
          state = BACKTICK;
          ++openStrings;
          break;

        case '/':
          state = NORMAL_1;
          break;

        case '(':
          ++openParen;
          break;

        case ')':
          --openParen;
          break;

        case '[':
          ++openBrackets;
          break;

        case ']':
          --openBrackets;
          break;

        case '{':
          ++openBraces;
          break;

        case '}':
          --openBraces;
          break;

        case '\\':
          ++ptr;
          break;
      }

      ++ptr;
    }
  }

  return (openParen <= 0 && openBrackets <= 0 && openBraces <= 0 && openStrings <= 0 && openComments <= 0);
}

////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////

vector<string> V8Completer::alternatives (char const * text) {
  vector<string> result;

  // locate global object or sub-object
  v8::Isolate* isolate = v8::Isolate::GetCurrent();

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Handle<v8::Object> current = context->Global();
  string path;
  char* prefix;

  if (*text != '\0') {
    TRI_vector_string_t splitted = TRI_SplitString(text, '.');

    if (1 < splitted._length) {
      for (size_t i = 0;  i < splitted._length - 1;  ++i) {
        v8::Handle<v8::String> name = TRI_V8_STRING(splitted._buffer[i]);

        if (! current->Has(name)) {
          TRI_DestroyVectorString(&splitted);
          return result;
        }

        v8::Handle<v8::Value> val = current->Get(name);

        if (! val->IsObject()) {
          TRI_DestroyVectorString(&splitted);
          return result;
        }

        current = val->ToObject();
        path = path + splitted._buffer[i] + ".";
      }

      prefix = TRI_DuplicateString(splitted._buffer[splitted._length - 1]);
    }
    else {
      prefix = TRI_DuplicateString(text);
    }

    TRI_DestroyVectorString(&splitted);
  }
  else {
    prefix = TRI_DuplicateString(text);
  }

  v8::HandleScope scope(isolate);

  // compute all possible completions
  v8::Handle<v8::Array> properties;
  v8::Handle<v8::String> cpl = TRI_V8_ASCII_STRING("_COMPLETIONS");

  if (current->HasOwnProperty(cpl)) {
    v8::Handle<v8::Value> funcVal = current->Get(cpl);

    if (funcVal->IsFunction()) {
      v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(funcVal);
      v8::Handle<v8::Value> args;

      try {
        v8::Handle<v8::Value> cpls = func->Call(current, 0, &args);

        if (cpls->IsArray()) {
          properties = v8::Handle<v8::Array>::Cast(cpls);
        }
      }
      catch (...) {
        // silently ignore errors here
      }
    }
  }
  else {
    properties = current->GetPropertyNames();
  }

  // locate
  try {
    if (! properties.IsEmpty()) {
      uint32_t const n = properties->Length();
      result.reserve(static_cast<size_t>(n));

      for (uint32_t i = 0;  i < n;  ++i) {
        v8::Handle<v8::Value> v = properties->Get(i);

        TRI_Utf8ValueNFC str(TRI_UNKNOWN_MEM_ZONE, v);
        char const* s = *str;

        if (s != nullptr && *s) {
          string suffix = (current->Get(v)->IsFunction()) ? "()" : "";
          string name = path + s + suffix;

          if (*prefix == '\0' || TRI_IsPrefixString(s, prefix)) {
            result.emplace_back(name);
          }
        }
      }
    }
  }
  catch (...) {
    // ignore errors in case of OOM
  }

  TRI_FreeString(TRI_CORE_MEM_ZONE, prefix);
  return result;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                class V8LineEditor
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                          static private variables
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief the active instance of the editor
////////////////////////////////////////////////////////////////////////////////

std::atomic<V8LineEditor*> V8LineEditor::_instance(nullptr);

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new editor
////////////////////////////////////////////////////////////////////////////////

V8LineEditor::V8LineEditor (v8::Isolate* isolate,
                            v8::Handle<v8::Context> context,
                            std::string const& history)
  : LineEditor(history),
    _isolate(isolate),
    _context(context),
    _completer(V8Completer()),
    _executingCommand(false) {

  // register global instance
  TRI_ASSERT(_instance.load() == nullptr);
  _instance.store(this);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys the editor
////////////////////////////////////////////////////////////////////////////////

V8LineEditor::~V8LineEditor () {
  // unregister global instance
  TRI_ASSERT(_instance.load() != nullptr);
  _instance.store(nullptr);
}

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

////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the shell implementation supports colors
////////////////////////////////////////////////////////////////////////////////

bool V8LineEditor::supportsColors () const {
  if (_shellImpl == nullptr) {
    return false;
  }

  return _shellImpl->supportsColors();
}

// -----------------------------------------------------------------------------
// --SECTION--                                                 protected methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup a signal handler for CTRL-C
////////////////////////////////////////////////////////////////////////////////

void V8LineEditor::setupCtrlCHandler () {
#ifndef _WIN32
  if (_shellImpl != nullptr &&
      _shellImpl->supportsCtrlCHandler()) {
    struct sigaction sa;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = &SignalHandler;

    int res = sigaction(SIGINT, &sa, 0);

    if (res != 0) {
      LOG_ERROR("unable to install signal handler");
    }
  }
#endif
}

// -----------------------------------------------------------------------------
// --SECTION--                                                 protected methods
// -----------------------------------------------------------------------------

void V8LineEditor::initializeShell () {
  _shellImpl = ShellImplFactory::buildShell(_history, &_completer);

  setupCtrlCHandler();
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------
<|endoftext|>


<commit_before>//===-- Method.cpp - Implement the Method class ------------------*- C++ -*--=//
//
// This file implements the Method & GlobalVariable classes for the VMCore
// library.
//
//===----------------------------------------------------------------------===//

#include "llvm/ValueHolderImpl.h"
#include "llvm/DerivedTypes.h"
#include "llvm/SymbolTable.h"
#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/GlobalVariable.h"
#include "llvm/BasicBlock.h"
#include "llvm/iOther.h"

//===----------------------------------------------------------------------===//
// Method Implementation
//===----------------------------------------------------------------------===//

// Instantiate Templates - This ugliness is the price we have to pay
// for having a ValueHolderImpl.h file seperate from ValueHolder.h!  :(
//
template class ValueHolder<MethodArgument, Method, Method>;
template class ValueHolder<BasicBlock    , Method, Method>;

Method::Method(const MethodType *Ty, const string &name)
  : GlobalValue(PointerType::get(Ty), Value::MethodVal, name),
    SymTabValue(this), BasicBlocks(this), ArgumentList(this, this) {
  assert(::isa<MethodType>(Ty) && "Method signature must be of method type!");
}

Method::~Method() {
  dropAllReferences();    // After this it is safe to delete instructions.

  // TODO: Should remove from the end, not the beginning of vector!
  iterator BI = begin();
  while ((BI = begin()) != end())
    delete BasicBlocks.remove(BI);

  // Delete all of the method arguments and unlink from symbol table...
  ArgumentList.delete_all();
  ArgumentList.setParent(0);
}

// Specialize setName to take care of symbol table majik
void Method::setName(const string &name, SymbolTable *ST) {
  Module *P;
  assert((ST == 0 || (!getParent() || ST == getParent()->getSymbolTable())) &&
	 "Invalid symtab argument!");
  if ((P = getParent()) && hasName()) P->getSymbolTable()->remove(this);
  Value::setName(name);
  if (P && getName() != "") P->getSymbolTableSure()->insert(this);
}

void Method::setParent(Module *parent) {
  Parent = parent;

  // Relink symbol tables together...
  setParentSymTab(Parent ? Parent->getSymbolTableSure() : 0);
}

const MethodType *Method::getMethodType() const {
  return cast<MethodType>(cast<PointerType>(getType())->getValueType());
}

const Type *Method::getReturnType() const {
  return getMethodType()->getReturnType();
}

// dropAllReferences() - This function causes all the subinstructions to "let
// go" of all references that they are maintaining.  This allows one to
// 'delete' a whole class at a time, even though there may be circular
// references... first all references are dropped, and all use counts go to
// zero.  Then everything is delete'd for real.  Note that no operations are
// valid on an object that has "dropped all references", except operator
// delete.
//
void Method::dropAllReferences() {
  for_each(begin(), end(), std::mem_fun(&BasicBlock::dropAllReferences));
}

//===----------------------------------------------------------------------===//
// GlobalVariable Implementation
//===----------------------------------------------------------------------===//

GlobalVariable::GlobalVariable(const Type *Ty, bool isConstant,
			       ConstPoolVal *Initializer = 0,
			       const string &Name = "")
  : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal, Name),
    Constant(isConstant) {
  if (Initializer) Operands.push_back(Use((Value*)Initializer, this));
}

// Specialize setName to take care of symbol table majik
void GlobalVariable::setName(const string &name, SymbolTable *ST) {
  Module *P;
  assert((ST == 0 || (!getParent() || ST == getParent()->getSymbolTable())) &&
	 "Invalid symtab argument!");
  if ((P = getParent()) && hasName()) P->getSymbolTable()->remove(this);
  Value::setName(name);
  if (P && getName() != "") P->getSymbolTableSure()->insert(this);
}
<commit_msg>Added MachineCodeForMethod object in class Method.<commit_after>//===-- Method.cpp - Implement the Method class ------------------*- C++ -*--=//
//
// This file implements the Method & GlobalVariable classes for the VMCore
// library.
//
//===----------------------------------------------------------------------===//

#include "llvm/ValueHolderImpl.h"
#include "llvm/DerivedTypes.h"
#include "llvm/SymbolTable.h"
#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/GlobalVariable.h"
#include "llvm/BasicBlock.h"
#include "llvm/iOther.h"
#include "llvm/CodeGen/MachineInstr.h"

//===----------------------------------------------------------------------===//
// Method Implementation
//===----------------------------------------------------------------------===//

// Instantiate Templates - This ugliness is the price we have to pay
// for having a ValueHolderImpl.h file seperate from ValueHolder.h!  :(
//
template class ValueHolder<MethodArgument, Method, Method>;
template class ValueHolder<BasicBlock    , Method, Method>;

Method::Method(const MethodType *Ty, const string &name)
  : GlobalValue(PointerType::get(Ty), Value::MethodVal, name),
    SymTabValue(this), BasicBlocks(this), ArgumentList(this, this),
    machineCode(new MachineCodeForMethod(this)) {
  assert(::isa<MethodType>(Ty) && "Method signature must be of method type!");
}

Method::~Method() {
  dropAllReferences();    // After this it is safe to delete instructions.

  // TODO: Should remove from the end, not the beginning of vector!
  iterator BI = begin();
  while ((BI = begin()) != end())
    delete BasicBlocks.remove(BI);

  // Delete all of the method arguments and unlink from symbol table...
  ArgumentList.delete_all();
  ArgumentList.setParent(0);
}

// Specialize setName to take care of symbol table majik
void Method::setName(const string &name, SymbolTable *ST) {
  Module *P;
  assert((ST == 0 || (!getParent() || ST == getParent()->getSymbolTable())) &&
	 "Invalid symtab argument!");
  if ((P = getParent()) && hasName()) P->getSymbolTable()->remove(this);
  Value::setName(name);
  if (P && getName() != "") P->getSymbolTableSure()->insert(this);
}

void Method::setParent(Module *parent) {
  Parent = parent;

  // Relink symbol tables together...
  setParentSymTab(Parent ? Parent->getSymbolTableSure() : 0);
}

const MethodType *Method::getMethodType() const {
  return cast<MethodType>(cast<PointerType>(getType())->getValueType());
}

const Type *Method::getReturnType() const {
  return getMethodType()->getReturnType();
}

// dropAllReferences() - This function causes all the subinstructions to "let
// go" of all references that they are maintaining.  This allows one to
// 'delete' a whole class at a time, even though there may be circular
// references... first all references are dropped, and all use counts go to
// zero.  Then everything is delete'd for real.  Note that no operations are
// valid on an object that has "dropped all references", except operator
// delete.
//
void Method::dropAllReferences() {
  for_each(begin(), end(), std::mem_fun(&BasicBlock::dropAllReferences));
}

//===----------------------------------------------------------------------===//
// GlobalVariable Implementation
//===----------------------------------------------------------------------===//

GlobalVariable::GlobalVariable(const Type *Ty, bool isConstant,
			       ConstPoolVal *Initializer = 0,
			       const string &Name = "")
  : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal, Name),
    Constant(isConstant) {
  if (Initializer) Operands.push_back(Use((Value*)Initializer, this));
}

// Specialize setName to take care of symbol table majik
void GlobalVariable::setName(const string &name, SymbolTable *ST) {
  Module *P;
  assert((ST == 0 || (!getParent() || ST == getParent()->getSymbolTable())) &&
	 "Invalid symtab argument!");
  if ((P = getParent()) && hasName()) P->getSymbolTable()->remove(this);
  Value::setName(name);
  if (P && getName() != "") P->getSymbolTableSure()->insert(this);
}
<|endoftext|>


<commit_before>// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.

// Copyright (c) 2011 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
#include "config.h"

static char rcsid[] not_used = { "$Id: ResponseBuilder.cc 23477 2010-09-02 21:02:59Z jimg $" };

#include <iostream>
#include <vector>

//#define DODS_DEBUG

#include "Keywords2.h"
#include "Error.h"
#include "escaping.h"
#include "debug.h"

using namespace std;

namespace libdap {

Keywords::Keywords()
{
    // Load known keywords and their allowed values
    vector<string> v1(7);
    v1[0] = "2"; v1[1] = "2.0"; v1[2] = "3.2"; v1[3] = "3.3"; v1[4] = "3.4";
    v1[5] = "4"; v1[6] = "4.0";
    value_set_t vs = value_set_t(v1.begin(), v1.end());
    d_known_keywords["dap"] = vs;

    vector<string> v2(4);
    v2[0] = "md5"; v2[1] = "MD5"; v2[2] = "sha1"; v2[3] = "SHA1";
    value_set_t vs2 = value_set_t(v2.begin(), v2.end());
    d_known_keywords["checksum"] = vs2;
}

Keywords::~Keywords()
{
}

/** Static function to parse the curly-brace keyword notation.
 * @param kw the keyword clause '<word> ( <value> )'
 * @param word (result) the word
 * @param value (result) the value
 * @return True if the parse was successful (word and value contain useful
 * results) and False otherwise.
 */
static bool f_parse_keyword(const string &kw, string &word, string &value)
{
    word = "";
    value = "";
    string::size_type i = kw.find('(');
    if (i == string::npos)
	return false;
    word = kw.substr(0, i);
    string::size_type j = kw.find(')');
    if (j == string::npos)
	return false;
    ++i; // Move past the opening brace
    value = kw.substr(i, j-i);

    return (!word.empty() && !value.empty());
}

/**
 * Add the keyword to the set of keywords that apply to this request.
 * @note Should call m_is_valid_keyword first.
 * @param word The keyword/function name
 * @param value The keyword/function value
 */
void Keywords::m_add_keyword(const keyword &word, const keyword_value &value)
{
    d_parsed_keywords[word] = value;
}

/** Is the string a valid keyword clause? Assumption: the word and value have
 * already been successfully parsed.
 * @param word The keyword/function name
 * @param value The keyword/function value
 * @return True if the string is valid keyword and the value is one of the
 * allowed values.
 */
bool Keywords::m_is_valid_keyword(const keyword &word, const keyword_value &value) const
{
    map<keyword, value_set_t>::const_iterator ci = d_known_keywords.find(word);
    if (ci == d_known_keywords.end())
	return false;
    else {
	value_set_t vs = ci->second;

	if (vs.find(value) == vs.end())
	    throw Error("Bad value passed to the keyword/function: " + word);
    }

    return true;
}

/**
 * Is the word one of the known keywords for this version of libdap?
 * @param s As a string, including the value
 * @return true if the keyword is known
 */
bool Keywords::is_known_keyword(const string &word) const
{
	return d_known_keywords.count(word) == 1;
}

/**
 * Get a list of the strings that make up the set of current keywords for
 * this request.
 * @return The list of keywords as a list of string objects.
 */
list<Keywords::keyword> Keywords::get_keywords() const
{
    list<keyword> kws;
    map<keyword, keyword_value>::const_iterator i;
    for (i = d_parsed_keywords.begin(); i != d_parsed_keywords.end(); ++i)
    	kws.push_front((*i).first);

    return kws;
}

/**
 * Lookup a keyword_kind and return true if it has been set for this request,
 * otherwise return false.
 * @param kw Keyword
 * @return true if the keyword is set.
 */
bool Keywords::has_keyword(const keyword &kw) const
{
    return d_parsed_keywords.count(kw) == 1;
}

/** Look at the parsed keywords for the value associated with a given keyword.
 *
 * @param k
 * @return The value
 */
Keywords::keyword_value Keywords::get_keyword_value(const keyword &kw) const
{
    if (d_known_keywords.find(kw) == d_known_keywords.end())
    	throw Error("Keyword not known (" + kw + ")");

    return d_parsed_keywords.find(kw)->second;
}

/** Parse the constraint expression, removing all keywords. As a side effect,
 * return the remaining CE.
 * @param ce
 * @return The CE stripped of all recognized keywords.
 */
string Keywords::parse_keywords(const string &ce)
{
    // Get the whole CE
    string projection = www2id(ce, "%", "%20");
    string selection = "";

    // Separate the selection part (which follows/includes the first '&')
    string::size_type amp = projection.find('&');
    if (amp != string::npos) {
	selection = projection.substr(amp);
	projection = projection.substr(0, amp);
    }

    // Extract keywords; add to the Keywords keywords. For this, scan for
    // a known set of keywords and assume that anything else is part of the
    // projection and should be left alone. Keywords must come before variables
    // The 'projection' string will look like: '' or 'dap4.0' or 'dap4.0,u,v'
    while (!projection.empty()) {
	string::size_type i = projection.find(',');
	string next_word = projection.substr(0, i);
	string word, value;
	if (f_parse_keyword(next_word, word, value)
	    && m_is_valid_keyword(word, value)) {
	    m_add_keyword(word, value);
	    if (i != string::npos)
		projection = projection.substr(i + 1);
	    else
		projection = "";
	}
	else {
	    break; // exit on first non-keyword
	}
    }

    // The CE is whatever is left after removing the keywords
    return projection + selection;
}

}
<commit_msg>Updated comments<commit_after>// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.

// Copyright (c) 2011 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
#include "config.h"

static char rcsid[] not_used = { "$Id: ResponseBuilder.cc 23477 2010-09-02 21:02:59Z jimg $" };

#include <iostream>
#include <vector>

//#define DODS_DEBUG

#include "Keywords2.h"
#include "Error.h"
#include "escaping.h"
#include "debug.h"

using namespace std;

namespace libdap {

Keywords::Keywords()
{
    // Load known keywords and their allowed values
    vector<string> v1(7);
    v1[0] = "2"; v1[1] = "2.0"; v1[2] = "3.2"; v1[3] = "3.3"; v1[4] = "3.4";
    v1[5] = "4"; v1[6] = "4.0";
    value_set_t vs = value_set_t(v1.begin(), v1.end());
    d_known_keywords["dap"] = vs;

    vector<string> v2(4);
    v2[0] = "md5"; v2[1] = "MD5"; v2[2] = "sha1"; v2[3] = "SHA1";
    value_set_t vs2 = value_set_t(v2.begin(), v2.end());
    d_known_keywords["checksum"] = vs2;
}

Keywords::~Keywords()
{
}

/** Static function to parse the keyword notation.
 * @param kw the keyword clause '<word> ( <value> )'
 * @param word (result) the word
 * @param value (result) the value
 * @return True if the parse was successful (word and value contain useful
 * results) and False otherwise.
 */
static bool f_parse_keyword(const string &kw, string &word, string &value)
{
    word = "";
    value = "";
    string::size_type i = kw.find('(');
    if (i == string::npos)
	return false;
    word = kw.substr(0, i);
    string::size_type j = kw.find(')');
    if (j == string::npos)
	return false;
    ++i; // Move past the opening paren
    value = kw.substr(i, j-i);

    return (!word.empty() && !value.empty());
}

/**
 * Add the keyword to the set of keywords that apply to this request.
 * @note Should call m_is_valid_keyword first.
 * @param word The keyword/function name
 * @param value The keyword/function value
 */
void Keywords::m_add_keyword(const keyword &word, const keyword_value &value)
{
    d_parsed_keywords[word] = value;
}

/** Is the string a valid keyword clause? Assumption: the word and value have
 * already been successfully parsed.
 * @param word The keyword/function name
 * @param value The keyword/function value
 * @return True if the string is valid keyword and the value is one of the
 * allowed values.
 */
bool Keywords::m_is_valid_keyword(const keyword &word, const keyword_value &value) const
{
    map<keyword, value_set_t>::const_iterator ci = d_known_keywords.find(word);
    if (ci == d_known_keywords.end())
	return false;
    else {
	value_set_t vs = ci->second;

	if (vs.find(value) == vs.end())
	    throw Error("Bad value passed to the keyword/function: " + word);
    }

    return true;
}

/**
 * Is the word one of the known keywords for this version of libdap?
 * @param s As a string, including the value
 * @return true if the keyword is known
 */
bool Keywords::is_known_keyword(const string &word) const
{
	return d_known_keywords.count(word) == 1;
}

/**
 * Get a list of the strings that make up the set of current keywords for
 * this request.
 * @return The list of keywords as a list of string objects.
 */
list<Keywords::keyword> Keywords::get_keywords() const
{
    list<keyword> kws;
    map<keyword, keyword_value>::const_iterator i;
    for (i = d_parsed_keywords.begin(); i != d_parsed_keywords.end(); ++i)
    	kws.push_front((*i).first);

    return kws;
}

/**
 * Lookup a keyword_kind and return true if it has been set for this request,
 * otherwise return false.
 * @param kw Keyword
 * @return true if the keyword is set.
 */
bool Keywords::has_keyword(const keyword &kw) const
{
    return d_parsed_keywords.count(kw) == 1;
}

/** Look at the parsed keywords for the value associated with a given keyword.
 *
 * @param k
 * @return The value
 */
Keywords::keyword_value Keywords::get_keyword_value(const keyword &kw) const
{
    if (d_known_keywords.find(kw) == d_known_keywords.end())
    	throw Error("Keyword not known (" + kw + ")");

    return d_parsed_keywords.find(kw)->second;
}

/** Parse the constraint expression, removing all keywords. As a side effect,
 * return the remaining CE.
 * @param ce
 * @return The CE stripped of all recognized keywords.
 */
string Keywords::parse_keywords(const string &ce)
{
    // Get the whole CE
    string projection = www2id(ce, "%", "%20");
    string selection = "";

    // Separate the selection part (which follows/includes the first '&')
    string::size_type amp = projection.find('&');
    if (amp != string::npos) {
	selection = projection.substr(amp);
	projection = projection.substr(0, amp);
    }

    // Extract keywords; add to the Keywords keywords. For this, scan for
    // a known set of keywords and assume that anything else is part of the
    // projection and should be left alone. Keywords must come before variables
    // The 'projection' string will look like: '' or 'dap4.0' or 'dap4.0,u,v'
    while (!projection.empty()) {
	string::size_type i = projection.find(',');
	string next_word = projection.substr(0, i);
	string word, value;
	if (f_parse_keyword(next_word, word, value)
	    && m_is_valid_keyword(word, value)) {
	    m_add_keyword(word, value);
	    if (i != string::npos)
		projection = projection.substr(i + 1);
	    else
		projection = "";
	}
	else {
	    break; // exit on first non-keyword
	}
    }

    // The CE is whatever is left after removing the keywords
    return projection + selection;
}

}
<|endoftext|>


<commit_before>#include "frame.h"
#include "util.h"
#include "gtest/gtest.h"
#include <string>
#include <iostream>

TEST(UtilTest, NormalTest) {
    std::string data = "hello world";
    uint8_t enc_a_wire[30];
    const uint8_t e_wire[13] = {0x00, 0x0b, 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
    int32_t enc_a_len = UTF8_encode(enc_a_wire, data);
    int32_t enc_e_len = data.size()+2;
    EXPECT_EQ(enc_e_len, enc_a_len);
    EXPECT_TRUE(0 == std::memcmp(enc_a_wire, e_wire, enc_a_len));

    int64_t dec_a_len = 0;
    std::string dec_a_str = UTF8_decode(e_wire, &dec_a_len);
    EXPECT_EQ(enc_e_len, dec_a_len);
    EXPECT_TRUE(0 == std::memcmp(data.c_str(), dec_a_str.c_str(), data.size()));

    int dataNum = 8;
    uint32_t lens[8] = {0, 127, 128, 16383, 16384, 2097151, 2097152, 268435455};
    uint8_t remEnc_a_wire[30];
    uint8_t remEnc_e_wires[8][4] = {{0x00}, {0x7f}, {0x80, 0x01}, {0xff, 0x7f}, {0x80, 0x80, 0x01},
                                 {0xff, 0xff, 0x7f}, {0x80, 0x80, 0x80, 0x01}, {0xff, 0xff, 0xff, 0x7f}};
    for (int i = 0; i < dataNum; i++) {
        int32_t remEnc_e_len = remainEncode(remEnc_a_wire, lens[i]);
        EXPECT_TRUE(0 == std::memcmp(remEnc_e_wires[i], remEnc_a_wire, remEnc_e_len));
    }

    int wire_progress = 0;
    MQTT_ERROR err;
    for (int i = 0; i < dataNum; i++) {
        int32_t a_remLength = remainDecode(remEnc_e_wires[i], &wire_progress, err);
        EXPECT_EQ(lens[i], a_remLength);
    }

    std::vector<std::string> a_parts, e_parts;
    e_parts.push_back("a");
    e_parts.push_back("b");
    e_parts.push_back("c");
    std::string splitted = "a/b/c";
    int done = split(splitted, "/", &a_parts);
    for (int i = 0; i < 3; i++) {
        EXPECT_TRUE(e_parts[i] == a_parts[i]);
    }
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>add fixedheader test<commit_after>#include "frame.h"
#include "util.h"
#include "gtest/gtest.h"
#include <string>
#include <iostream>

TEST(UtilTest, NormalTest) {
    std::string data = "hello world";
    uint8_t enc_a_wire[30];
    const uint8_t e_wire[13] = {0x00, 0x0b, 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
    int32_t enc_a_len = UTF8_encode(enc_a_wire, data);
    int32_t enc_e_len = data.size()+2;
    EXPECT_EQ(enc_e_len, enc_a_len);
    EXPECT_TRUE(0 == std::memcmp(enc_a_wire, e_wire, enc_a_len));

    int64_t dec_a_len = 0;
    std::string dec_a_str = UTF8_decode(e_wire, &dec_a_len);
    EXPECT_EQ(enc_e_len, dec_a_len);
    EXPECT_TRUE(0 == std::memcmp(data.c_str(), dec_a_str.c_str(), data.size()));

    int dataNum = 8;
    uint32_t lens[8] = {0, 127, 128, 16383, 16384, 2097151, 2097152, 268435455};
    uint8_t remEnc_a_wire[30];
    uint8_t remEnc_e_wires[8][4] = {{0x00}, {0x7f}, {0x80, 0x01}, {0xff, 0x7f}, {0x80, 0x80, 0x01},
                                 {0xff, 0xff, 0x7f}, {0x80, 0x80, 0x80, 0x01}, {0xff, 0xff, 0xff, 0x7f}};
    for (int i = 0; i < dataNum; i++) {
        int32_t remEnc_e_len = remainEncode(remEnc_a_wire, lens[i]);
        EXPECT_TRUE(0 == std::memcmp(remEnc_e_wires[i], remEnc_a_wire, remEnc_e_len));
    }

    int wire_progress = 0;
    MQTT_ERROR err;
    for (int i = 0; i < dataNum; i++) {
        int32_t a_remLength = remainDecode(remEnc_e_wires[i], &wire_progress, err);
        EXPECT_EQ(lens[i], a_remLength);
    }

    std::vector<std::string> a_parts, e_parts;
    e_parts.push_back("a");
    e_parts.push_back("b");
    e_parts.push_back("c");
    std::string splitted = "a/b/c";
    int done = split(splitted, "/", &a_parts);
    for (int i = 0; i < 3; i++) {
        EXPECT_TRUE(e_parts[i] == a_parts[i]);
    }
}

TEST(FrameTest, NormalTest) {
    MessageType type = CONNECT_MESSAGE_TYPE;
    bool dup = false;
    uint8_t qos = 0;
    bool retain = false;
    uint32_t len = 0;
    uint16_t id = 0;

    FixedHeader* fh = new FixedHeader(type, dup, qos, retain, len, id);
    EXPECT_EQ(type, fh->Type);
    EXPECT_EQ(dup, fh->Dup);
    EXPECT_EQ(qos, fh->QoS);
    EXPECT_EQ(retain, fh->Retain);
    EXPECT_EQ(len, fh->Length);
    EXPECT_EQ(id, fh->PacketID);

}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifdef _MSC_VER
#pragma warning( 4: 4786 )
#endif

#include "TextureManager.h"
#include "TextUtils.h"

#include "texture.h"
#include "global.h"
#include "MediaFile.h"
#include "ErrorHandler.h"

/*const int NO_VARIANT = (-1); */

// initialize the singleton
template <>
TextureManager* Singleton<TextureManager>::_instance = (TextureManager*)0;

static int noiseProc( ProcTextureInit &init );

ProcTextureInit procLoader[1];

TextureManager::TextureManager()
{
	// fill out the standard proc textures
  procLoader[0].name = "noise";
  procLoader[0].filter = OpenGLTexture::Nearest;
  procLoader[0].proc = noiseProc;

  lastImageID = -1;
  lastBoundID = -1;

  int i, numTextures;
  numTextures = countof(procLoader);
  for (i = 0; i < numTextures; i++)
  {
    procLoader[i].manager = this;
    procLoader[i].proc( procLoader[i] );
  }
}

TextureManager::~TextureManager()
{
  // we are done remove all textures
  for( TextureNameMap::iterator it = textureNames.begin(); it != textureNames.end(); ++it) {
    ImageInfo &tex = it->second;
    if (tex.texture != NULL) {
      delete tex.texture;
    }
  }
  textureNames.clear();
  textureIDs.clear();
}

int TextureManager::getTextureID( const char* name, bool reportFail )
{
  if (!name)
    return -1;

  std::string texName = name;
  // see if we have the texture
  TextureNameMap::iterator it = textureNames.find(texName);
  if (it != textureNames.end())
    return it->second.id;
  else { // we don't have it so try and load it
    FileTextureInit	file;
    file.filter = OpenGLTexture::LinearMipmapLinear;
    file.name = texName;
    ImageInfo info;
    OpenGLTexture *image = loadTexture(file,reportFail);
    if (!image)
      return -1;
    return addTexture(name,image);
  }
  return -1;
}

bool TextureManager::bind ( int id )
{
  TextureIDMap::iterator it = textureIDs.find(id);
  if (it == textureIDs.end())
    return false;

 if (id != lastBoundID)
 {
    it->second->texture->execute();
    lastBoundID = id;
 }
  return true;
}

bool TextureManager::bind ( const char* name )
{
  std::string nameStr = name;

  TextureNameMap::iterator it = textureNames.find(nameStr);
  if (it == textureNames.end())
    return false;

  int id = it->second.id;
  if (id != lastBoundID)
  {
    it->second.texture->execute();
    lastBoundID = id;
  }
  return true;
}

float TextureManager::GetAspectRatio ( int id )
{
  TextureIDMap::iterator it = textureIDs.find(id);
  if (it == textureIDs.end())
    return 0.0;

  return (float)it->second->y/(float)it->second->x;
}

const ImageInfo& TextureManager::getInfo ( int id )
{
 static ImageInfo   crapInfo;
  crapInfo.id = -1;
  TextureIDMap::iterator it = textureIDs.find(id);
  if (it == textureIDs.end())
    return crapInfo;

  return *(it->second);
}
const ImageInfo& TextureManager::getInfo ( const char* name )
{
  static ImageInfo   crapInfo;
  crapInfo.id = -1;
  std::string nameStr = name;

  TextureNameMap::iterator it = textureNames.find(nameStr);
  if (it == textureNames.end())
    return crapInfo;

  return it->second;
}

int TextureManager::addTexture( const char* name, OpenGLTexture *texture )
{
  if (!name || !texture)
    return -1;

   // if the texture allready exists kill it
   // this is why IDs are way better then objects for this stuff
   TextureNameMap::iterator it = textureNames.find(name);
   if (it != textureNames.end())
   {
     textureIDs.erase(textureIDs.find(it->second.id));
     delete it->second.texture;
   }
   ImageInfo info;
   info.name = name;
   info.texture = texture;
   info.id = ++lastImageID;
   info.alpha = texture->hasAlpha();
   info.x = texture->getWidth();
   info.y = texture->getHeight();

   textureNames[name] = info;
   textureIDs[info.id] = &textureNames[name];

   return info.id;
}

OpenGLTexture* TextureManager::loadTexture(FileTextureInit &init, bool reportFail)
{
  int width, height;
  std::string nameToTry = "";

  if (BZDB.isSet( "altImageDir" )) {
    nameToTry = BZDB.get( "altImageDir" );
#ifdef WIN32
   nameToTry += '\\';
#else
   nameToTry += '/';
#endif
   nameToTry += init.name;
  }
  else
    nameToTry = init.name;
  unsigned char* image =NULL;
  if (nameToTry.size() && nameToTry.c_str())
    image = MediaFile::readImage( nameToTry.c_str(), &width, &height);
  if (!image)
    image = MediaFile::readImage( init.name.c_str(), &width, &height);
  if (!image) {
    if (reportFail) {
      std::vector<std::string> args;
      args.push_back(init.name);
      printError("cannot load texture: {1}", &args);
    }
    return NULL;
  }

  OpenGLTexture *texture = new OpenGLTexture(width, height, image, init.filter, true);
  delete[] image;

  return texture;
}

int TextureManager::newTexture ( const char* name, int x, int y, unsigned char* data, OpenGLTexture::Filter filter, bool repeat, int format  )
{
  return addTexture(name,new OpenGLTexture(x,y,data,filter,repeat,format));
}

/* --- Procs --- */

int noiseProc(ProcTextureInit &init)
{
  int noizeSize = 128;
  const int size = 4 * noizeSize * noizeSize;
  unsigned char* noise = new unsigned char[size];
  for (int i = 0; i < size; i += 4 ) {
    unsigned char n = (unsigned char)floor(256.0 * bzfrand());
    noise[i+0] = n;
    noise[i+1] = n;
    noise[i+2] = n;
    noise[i+3] = n;
  }
  int texture = init.manager->newTexture(init.name.c_str(),noizeSize,noizeSize,noise,init.filter);
  delete noise;
  return texture;
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>add some debugage<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifdef _MSC_VER
#pragma warning( 4: 4786 )
#endif

#include "TextureManager.h"
#include "TextUtils.h"

#include "texture.h"
#include "global.h"
#include "MediaFile.h"
#include "ErrorHandler.h"

/*const int NO_VARIANT = (-1); */

// initialize the singleton
template <>
TextureManager* Singleton<TextureManager>::_instance = (TextureManager*)0;

static int noiseProc( ProcTextureInit &init );

ProcTextureInit procLoader[1];

TextureManager::TextureManager()
{
  // fill out the standard proc textures
  procLoader[0].name = "noise";
  procLoader[0].filter = OpenGLTexture::Nearest;
  procLoader[0].proc = noiseProc;

  lastImageID = -1;
  lastBoundID = -1;

  int i, numTextures;
  numTextures = countof(procLoader);
  for (i = 0; i < numTextures; i++)
  {
    procLoader[i].manager = this;
    procLoader[i].proc( procLoader[i] );
  }
}

TextureManager::~TextureManager()
{
  // we are done remove all textures
  for( TextureNameMap::iterator it = textureNames.begin(); it != textureNames.end(); ++it) {
    ImageInfo &tex = it->second;
    if (tex.texture != NULL) {
      delete tex.texture;
    }
  }
  textureNames.clear();
  textureIDs.clear();
}

int TextureManager::getTextureID( const char* name, bool reportFail )
{
  if (!name)
    return -1;

  std::string texName = name;
  // see if we have the texture
  TextureNameMap::iterator it = textureNames.find(texName);
  if (it != textureNames.end())
    return it->second.id;
  else { // we don't have it so try and load it
    FileTextureInit	file;
    file.filter = OpenGLTexture::LinearMipmapLinear;
    file.name = texName;
    ImageInfo info;
    OpenGLTexture *image = loadTexture(file,reportFail);
    if (!image) {
      DEBUG1("Image not found or unloadable: %s\n", name);
      return -1;
    }
    return addTexture(name,image);
  }
  return -1;
}

bool TextureManager::bind ( int id )
{
  TextureIDMap::iterator it = textureIDs.find(id);
  if (it == textureIDs.end()) {
    DEBUG1("Unable to bind texture (by id): %d\n", id);
    return false;
  }

  if (id != lastBoundID) {
    it->second->texture->execute();
    lastBoundID = id;
  }
  return true;
}

bool TextureManager::bind ( const char* name )
{
  std::string nameStr = name;

  TextureNameMap::iterator it = textureNames.find(nameStr);
  if (it == textureNames.end()) {
    DEBUG1("Unable to bind texture (by name): %s\n", name);
    return false;
  }

  int id = it->second.id;
  if (id != lastBoundID) {
    it->second.texture->execute();
    lastBoundID = id;
  }
  return true;
}

float TextureManager::GetAspectRatio ( int id )
{
  TextureIDMap::iterator it = textureIDs.find(id);
  if (it == textureIDs.end())
    return 0.0;

  return (float)it->second->y/(float)it->second->x;
}

const ImageInfo& TextureManager::getInfo ( int id )
{
 static ImageInfo   crapInfo;
  crapInfo.id = -1;
  TextureIDMap::iterator it = textureIDs.find(id);
  if (it == textureIDs.end())
    return crapInfo;

  return *(it->second);
}
const ImageInfo& TextureManager::getInfo ( const char* name )
{
  static ImageInfo   crapInfo;
  crapInfo.id = -1;
  std::string nameStr = name;

  TextureNameMap::iterator it = textureNames.find(nameStr);
  if (it == textureNames.end())
    return crapInfo;

  return it->second;
}

int TextureManager::addTexture( const char* name, OpenGLTexture *texture )
{
  if (!name || !texture)
    return -1;

   // if the texture already exists kill it
   // this is why IDs are way better than objects for this stuff
   TextureNameMap::iterator it = textureNames.find(name);
   if (it != textureNames.end()) {
     DEBUG4("Texture %s already exists, overwriting\n", name);
     textureIDs.erase(textureIDs.find(it->second.id));
     delete it->second.texture;
   }
   ImageInfo info;
   info.name = name;
   info.texture = texture;
   info.id = ++lastImageID;
   info.alpha = texture->hasAlpha();
   info.x = texture->getWidth();
   info.y = texture->getHeight();

   textureNames[name] = info;
   textureIDs[info.id] = &textureNames[name];

   return info.id;
}

OpenGLTexture* TextureManager::loadTexture(FileTextureInit &init, bool reportFail)
{
  int width, height;
  std::string nameToTry = "";

  if (BZDB.isSet( "altImageDir" )) {
    nameToTry = BZDB.get( "altImageDir" );
#ifdef WIN32
   nameToTry += '\\';
#else
   nameToTry += '/';
#endif
   nameToTry += init.name;
  }
  else
    nameToTry = init.name;
  unsigned char* image = NULL;
  if (nameToTry.size() && nameToTry.c_str())
    image = MediaFile::readImage( nameToTry.c_str(), &width, &height);
  if (!image)
    image = MediaFile::readImage( init.name.c_str(), &width, &height);
  if (!image) {
    if (reportFail) {
      std::vector<std::string> args;
      args.push_back(init.name);
      printError("cannot load texture: {1}", &args);
    }
    return NULL;
  }

  OpenGLTexture *texture = new OpenGLTexture(width, height, image, init.filter, true);
  delete[] image;

  return texture;
}

int TextureManager::newTexture ( const char* name, int x, int y, unsigned char* data, OpenGLTexture::Filter filter, bool repeat, int format  )
{
  return addTexture(name,new OpenGLTexture(x,y,data,filter,repeat,format));
}

/* --- Procs --- */

int noiseProc(ProcTextureInit &init)
{
  int noizeSize = 128;
  const int size = 4 * noizeSize * noizeSize;
  unsigned char* noise = new unsigned char[size];
  for (int i = 0; i < size; i += 4 ) {
    unsigned char n = (unsigned char)floor(256.0 * bzfrand());
    noise[i+0] = n;
    noise[i+1] = n;
    noise[i+2] = n;
    noise[i+3] = n;
  }
  int texture = init.manager->newTexture(init.name.c_str(),noizeSize,noizeSize,noise,init.filter);
  delete[] noise;
  return texture;
}

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


<commit_before>// Virvo - Virtual Reality Volume Rendering
// Copyright (C) 1999-2003 University of Stuttgart, 2004-2005 Brown University
// Contact: Jurgen P. Schulze, jschulze@ucsd.edu
//
// This file is part of Virvo.
//
// Virvo 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 (see license.txt); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#ifdef HAVE_CONFIG_H
#include "vvconfig.h"
#endif

#include "vvbonjoureventloop.h"

#include "vvdebugmsg.h"
#include "vvpthread.h"
#include "vvsocketmonitor.h"
#include "vvtcpsocket.h"

#ifdef HAVE_BONJOUR
#include <dns_sd.h>
#endif

namespace
{
#ifdef HAVE_BONJOUR
_DNSServiceRef_t *dnsServiceRef;
#endif
}

struct Thread
{
  pthread_t _pthread;
};

vvBonjourEventLoop::vvBonjourEventLoop(void* service)
{
  _thread = new Thread;
  _thread->_pthread = NULL;
#ifdef HAVE_BONJOUR
  ::dnsServiceRef = reinterpret_cast<_DNSServiceRef_t*>(service);
#else
  (void)service;
#endif
}

vvBonjourEventLoop::~vvBonjourEventLoop()
{
  if(_thread->_pthread)
  {
    pthread_join(_thread->_pthread, NULL);
  }
  delete _thread;
}

void vvBonjourEventLoop::run(bool inThread, double timeout)
{
#ifdef HAVE_BONJOUR
  _timeout = timeout;
  _noMoreFlags = false;
  if(inThread == false)
  {
    loop(this);
    ::dnsServiceRef = NULL;
  }
  else
  {
    pthread_create(&(_thread->_pthread), NULL, loop, this);
  }
#else
  (void)inThread;
  (void)timeout;
#endif
}

void * vvBonjourEventLoop::loop(void * attrib)
{
#ifdef HAVE_BONJOUR
  vvDebugMsg::msg(3, "vvBonjourEventLoop::loop()");
  vvBonjourEventLoop *instance = reinterpret_cast<vvBonjourEventLoop*>(attrib);

  instance->_run = true;
  int dns_sd_fd = DNSServiceRefSockFD(::dnsServiceRef);

  vvTcpSocket sock = vvTcpSocket();
  sock.setSockfd(dns_sd_fd);

  std::vector<vvSocket*> sockets;
  sockets.push_back(&sock);

  vvSocketMonitor socketMonitor;
  socketMonitor.setReadFds(sockets);

  while (instance->_run)
  {
    vvSocket *ready;
    double to = instance->_timeout;
    vvSocketMonitor::ErrorType smErr = socketMonitor.wait(&ready, &to);

    if (smErr == vvSocketMonitor::VV_OK)
    {
      DNSServiceErrorType err = DNSServiceProcessResult(::dnsServiceRef);

      switch(err)
      {
      case kDNSServiceErr_NoError:
        continue;
        break;
      case kDNSServiceErr_NoSuchName:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Given name does not exist");
        break;
      case kDNSServiceErr_NoMemory:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Out of memory");
        break;
      case kDNSServiceErr_BadParam:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Parameter contains invalid data");
        break;
      case kDNSServiceErr_BadReference:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Reference being passed is invalid");
        break;
      case kDNSServiceErr_BadState:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Internal error");
        break;
      case kDNSServiceErr_BadFlags:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Invalid values for flags");
        break;
      case kDNSServiceErr_Unsupported:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Operation not supported");
        break;
      case kDNSServiceErr_NotInitialized:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Reference not initialized");
        break;
      case kDNSServiceErr_AlreadyRegistered:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Attempt to register a service that is registered");
        break;
      case kDNSServiceErr_NameConflict:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Attempt to register a service with an already used name");
        break;
      case kDNSServiceErr_Invalid:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Certain invalid parameter data, such as domain name more than 255 bytes long");
        break;
      case kDNSServiceErr_Incompatible:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Client library incompatible with daemon");
        break;
      case kDNSServiceErr_BadInterfaceIndex:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Specified interface does not exist");
        break;
      case kDNSServiceErr_Unknown:
      default:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() unknown error");
        break;
      }

      // did not "continue", so error occured -> break!
      break;
    }
    else if(smErr == vvSocketMonitor::VV_TIMEOUT)
    {
      vvDebugMsg::msg(0, "vvBonjourEventLoop::loop() timeout reached");
      break;
    }
    else
    {
      vvDebugMsg::msg(0, "vvBonjourEventLoop::loop() socketmonitor returned error");
      break;
    }
  }
#else
  (void)attrib;
#endif
  return NULL;
}

void vvBonjourEventLoop::stop()
{
  vvDebugMsg::msg(3, "vvBonjourEventLoop::stop()");
  _run = false;
}

// vim: sw=2:expandtab:softtabstop=2:ts=2:cino=\:0g0t0
<commit_msg>Don't compare non-pointer type pthread_t to NULL<commit_after>// Virvo - Virtual Reality Volume Rendering
// Copyright (C) 1999-2003 University of Stuttgart, 2004-2005 Brown University
// Contact: Jurgen P. Schulze, jschulze@ucsd.edu
//
// This file is part of Virvo.
//
// Virvo 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 (see license.txt); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#ifdef HAVE_CONFIG_H
#include "vvconfig.h"
#endif

#include "vvbonjoureventloop.h"

#include "vvdebugmsg.h"
#include "vvpthread.h"
#include "vvsocketmonitor.h"
#include "vvtcpsocket.h"

#ifdef HAVE_BONJOUR
#include <dns_sd.h>
#endif

namespace
{
#ifdef HAVE_BONJOUR
_DNSServiceRef_t *dnsServiceRef;
#endif
}

struct Thread
{
  Thread()
    : _pthread(NULL)
  {
  }

  pthread_t* _pthread;
};

vvBonjourEventLoop::vvBonjourEventLoop(void* service)
{
  _thread = new Thread;
  _thread->_pthread = NULL;
#ifdef HAVE_BONJOUR
  ::dnsServiceRef = reinterpret_cast<_DNSServiceRef_t*>(service);
#else
  (void)service;
#endif
}

vvBonjourEventLoop::~vvBonjourEventLoop()
{
  if (_thread != NULL && _thread->_pthread != NULL)
  {
    pthread_join(*_thread->_pthread, NULL);
    delete _thread->_pthread;
  }
  delete _thread;
}

void vvBonjourEventLoop::run(bool inThread, double timeout)
{
#ifdef HAVE_BONJOUR
  _timeout = timeout;
  _noMoreFlags = false;
  if(inThread == false)
  {
    loop(this);
    ::dnsServiceRef = NULL;
  }
  else
  {
    delete _thread->_pthread;
    _thread->_pthread = new pthread_t;
    pthread_create(_thread->_pthread, NULL, loop, this);
  }
#else
  (void)inThread;
  (void)timeout;
#endif
}

void * vvBonjourEventLoop::loop(void * attrib)
{
#ifdef HAVE_BONJOUR
  vvDebugMsg::msg(3, "vvBonjourEventLoop::loop()");
  vvBonjourEventLoop *instance = reinterpret_cast<vvBonjourEventLoop*>(attrib);

  instance->_run = true;
  int dns_sd_fd = DNSServiceRefSockFD(::dnsServiceRef);

  vvTcpSocket sock = vvTcpSocket();
  sock.setSockfd(dns_sd_fd);

  std::vector<vvSocket*> sockets;
  sockets.push_back(&sock);

  vvSocketMonitor socketMonitor;
  socketMonitor.setReadFds(sockets);

  while (instance->_run)
  {
    vvSocket *ready;
    double to = instance->_timeout;
    vvSocketMonitor::ErrorType smErr = socketMonitor.wait(&ready, &to);

    if (smErr == vvSocketMonitor::VV_OK)
    {
      DNSServiceErrorType err = DNSServiceProcessResult(::dnsServiceRef);

      switch(err)
      {
      case kDNSServiceErr_NoError:
        continue;
        break;
      case kDNSServiceErr_NoSuchName:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Given name does not exist");
        break;
      case kDNSServiceErr_NoMemory:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Out of memory");
        break;
      case kDNSServiceErr_BadParam:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Parameter contains invalid data");
        break;
      case kDNSServiceErr_BadReference:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Reference being passed is invalid");
        break;
      case kDNSServiceErr_BadState:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Internal error");
        break;
      case kDNSServiceErr_BadFlags:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Invalid values for flags");
        break;
      case kDNSServiceErr_Unsupported:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Operation not supported");
        break;
      case kDNSServiceErr_NotInitialized:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Reference not initialized");
        break;
      case kDNSServiceErr_AlreadyRegistered:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Attempt to register a service that is registered");
        break;
      case kDNSServiceErr_NameConflict:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Attempt to register a service with an already used name");
        break;
      case kDNSServiceErr_Invalid:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Certain invalid parameter data, such as domain name more than 255 bytes long");
        break;
      case kDNSServiceErr_Incompatible:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Client library incompatible with daemon");
        break;
      case kDNSServiceErr_BadInterfaceIndex:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() Specified interface does not exist");
        break;
      case kDNSServiceErr_Unknown:
      default:
        vvDebugMsg::msg(0, "DNSServiceProcessResult() unknown error");
        break;
      }

      // did not "continue", so error occured -> break!
      break;
    }
    else if(smErr == vvSocketMonitor::VV_TIMEOUT)
    {
      vvDebugMsg::msg(0, "vvBonjourEventLoop::loop() timeout reached");
      break;
    }
    else
    {
      vvDebugMsg::msg(0, "vvBonjourEventLoop::loop() socketmonitor returned error");
      break;
    }
  }
#else
  (void)attrib;
#endif
  return NULL;
}

void vvBonjourEventLoop::stop()
{
  vvDebugMsg::msg(3, "vvBonjourEventLoop::stop()");
  _run = false;
}

// vim: sw=2:expandtab:softtabstop=2:ts=2:cino=\:0g0t0
<|endoftext|>


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

#include "base/message_loop.h"
#include "base/thread.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// We use caps here just to ensure that the method name doesn't interfere with
// the wildcarded suppressions.
class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate {
 public:
  explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {}
  ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() {}
  void ThreadMain() {
    *value_ = true;
  }
 private:
  bool* value_;
};

}

// A memory leak detector should report an error in this test.
TEST(ToolsSanityTest, MemoryLeak) {
  int *leak = new int[256];  // Leak some memory intentionally.
  leak[4] = 1;  // Make sure the allocated memory is used.
}

// A data race detector should report an error in this test.
TEST(ToolsSanityTest, DataRace) {
  bool shared = false;
  PlatformThreadHandle a;
  PlatformThreadHandle b;
  PlatformThread::Delegate *thread1 =
      new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);
  PlatformThread::Delegate *thread2 =
      new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);

  PlatformThread::Create(0, thread1, &a);
  PlatformThread::Create(0, thread2, &b);
  PlatformThread::Join(a);
  PlatformThread::Join(b);
  EXPECT_TRUE(shared);
  delete thread1;
  delete thread2;
}

<commit_msg>Add sleep into data race sanity test since it fails on TSan x64 FYI bot (too fast?) TBR=glider TEST=TSAN x64 FYI bot should become green Review URL: http://codereview.chromium.org/668176<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/message_loop.h"
#include "base/thread.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// We use caps here just to ensure that the method name doesn't interfere with
// the wildcarded suppressions.
class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate {
 public:
  explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {}
  ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() {}
  void ThreadMain() {
    *value_ = true;

    // Sleep for a few milliseconds so the two threads are more likely to live
    // simultaneously. Otherwise we may miss the report due to mutex
    // lock/unlock's inside thread creation code in pure-happens-before mode...
    PlatformThread::Sleep(100);
  }
 private:
  bool* value_;
};

}

// A memory leak detector should report an error in this test.
TEST(ToolsSanityTest, MemoryLeak) {
  int *leak = new int[256];  // Leak some memory intentionally.
  leak[4] = 1;  // Make sure the allocated memory is used.
}

// A data race detector should report an error in this test.
TEST(ToolsSanityTest, DataRace) {
  bool shared = false;
  PlatformThreadHandle a;
  PlatformThreadHandle b;
  PlatformThread::Delegate *thread1 =
      new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);
  PlatformThread::Delegate *thread2 =
      new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);

  PlatformThread::Create(0, thread1, &a);
  PlatformThread::Create(0, thread2, &b);
  PlatformThread::Join(a);
  PlatformThread::Join(b);
  EXPECT_TRUE(shared);
  delete thread1;
  delete thread2;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:    itkThresholdImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#include <iostream>
#include <string>
#include "itkPhysicalImage.h"
#include "itkScalar.h"
#include "itkRandomImageSource.h"
#include "itkThresholdImageFilter.h"
#include "itkCommand.h"
#include "itkOutputWindow.h"

// this class is used to send output to stdout and not the itk window
class TextOutput : public itk::OutputWindow
{
public:
  virtual void DisplayText(const char* s)
    {
      std::cout << s << std::endl;
    }
};

int main()
{
  // Comment the following if you want to use the itk text output window
  itk::OutputWindow::SetInstance(new TextOutput);

  // Uncomment the following if you want to see each message independently
  // itk::OutputWindow::GetInstance()->PromptUserOn();

//  typedef itk::Image<itk::Scalar<float>,2> FloatImage2DType;
  typedef itk::PhysicalImage<float,2> FloatImage2DType;

  itk::RandomImageSource<FloatImage2DType>::Pointer random;
  random = itk::RandomImageSource<FloatImage2DType>::New();
  random->SetMin(0.0);
  random->SetMax(1000.0);

  char buffer[8];
  std::string os;

  // Test #1, filter goes out of scope
  itk::OutputWindow::GetInstance()->DisplayText( "Test #1: Filter goes out of scope -----------------" );
  {
  itk::ThresholdImageFilter<FloatImage2DType>::Pointer threshold;
  threshold = itk::ThresholdImageFilter<FloatImage2DType>::New();
  threshold->SetInput(random->GetOutput());
  threshold->Update();

  os = "Filter: " + std::string(itoa((int)(void *)(threshold), buffer, 10));
  itk::OutputWindow::GetInstance()->DisplayText( os.c_str() );
  os = "Output #0: " + std::string(itoa((int)(void *)(threshold->GetOutput(0)),
                                        buffer, 10));
  itk::OutputWindow::GetInstance()->DisplayText( os.c_str() );
  os = "Output #1: " + std::string(itoa((int)(void *)(threshold->GetOutput(1)),
                                        buffer, 10));
  itk::OutputWindow::GetInstance()->DisplayText( os.c_str() );
  threshold->GetOutput(0)->DebugOn();
  threshold->GetOutput(1)->DebugOn();
  threshold->DebugOn();

  itk::OutputWindow::GetInstance()->DisplayText( "Ending Test #1: filter goes out of scope" );
  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #1 -----------------------------------" );
  }

  // Test #2, user keeps an extra handle to an output
  itk::OutputWindow::GetInstance()->DisplayText( "Test #2: User keeps an extra hold on an output  -----------------" );
  {
  FloatImage2DType::Pointer keep;

  itk::ThresholdImageFilter<FloatImage2DType>::Pointer threshold;
  threshold = itk::ThresholdImageFilter<FloatImage2DType>::New();
  threshold->SetInput(random->GetOutput());
  threshold->Update();

  os = "Filter: " + std::string(itoa((int)(void *)(threshold), buffer, 10));
  itk::OutputWindow::GetInstance()->DisplayText( os.c_str() );
  os = "Output #0: " + std::string(itoa((int)(void *)(threshold->GetOutput(0)),
                                        buffer, 10));
  itk::OutputWindow::GetInstance()->DisplayText( os.c_str() );
  os = "Output #1: " + std::string(itoa((int)(void *)(threshold->GetOutput(1)),
                                        buffer, 10));
  itk::OutputWindow::GetInstance()->DisplayText( os.c_str() );
  threshold->GetOutput(0)->DebugOn();
  threshold->GetOutput(1)->DebugOn();
  threshold->DebugOn();

  keep = threshold->GetOutput(0);

  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #2: last handle on output 0 should go out of scope");
  }
  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #2 -----------------------------------");

  // Test #3, user disconnects a data object from the pipeline
  itk::OutputWindow::GetInstance()->DisplayText( "Test #3: application disconnects a data object from the pipeline  -----------------" );
  {
  FloatImage2DType::Pointer keep;

  itk::ThresholdImageFilter<FloatImage2DType>::Pointer threshold;
  threshold = itk::ThresholdImageFilter<FloatImage2DType>::New();
  threshold->SetInput(random->GetOutput());
  threshold->Update();

  os = "Filter: " + std::string(itoa((int)(void *)(threshold), buffer, 10));
  itk::OutputWindow::GetInstance()->DisplayText( os.c_str() );
  os = "Output #0: " + std::string(itoa((int)(void *)(threshold->GetOutput(0)),
                                        buffer, 10));
  itk::OutputWindow::GetInstance()->DisplayText( os.c_str() );
  os = "Output #1: " + std::string(itoa((int)(void *)(threshold->GetOutput(1)),
                                        buffer, 10));
  itk::OutputWindow::GetInstance()->DisplayText( os.c_str() );
  threshold->GetOutput(0)->DebugOn();
  threshold->GetOutput(1)->DebugOn();
  threshold->DebugOn();

  keep = threshold->GetOutput(0);
  keep->DisconnectPipeline();

  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #3: last handle on output 0 should go out of scope");
  }
  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #3 -----------------------------------");

  return EXIT_SUCCESS;
}

<commit_msg>FIX: removed itoa() calls<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:    itkThresholdImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#include <iostream>
#include <strstream>
#include "itkPhysicalImage.h"
#include "itkScalar.h"
#include "itkRandomImageSource.h"
#include "itkThresholdImageFilter.h"
#include "itkCommand.h"
#include "itkOutputWindow.h"

// this class is used to send output to stdout and not the itk window
class TextOutput : public itk::OutputWindow
{
public:
  virtual void DisplayText(const char* s)
    {
      std::cout << s << std::endl;
    }
};

int main()
{
  // Comment the following if you want to use the itk text output window
  itk::OutputWindow::SetInstance(new TextOutput);

  // Uncomment the following if you want to see each message independently
  // itk::OutputWindow::GetInstance()->PromptUserOn();

//  typedef itk::Image<itk::Scalar<float>,2> FloatImage2DType;
  typedef itk::PhysicalImage<float,2> FloatImage2DType;

  itk::RandomImageSource<FloatImage2DType>::Pointer random;
  random = itk::RandomImageSource<FloatImage2DType>::New();
  random->SetMin(0.0);
  random->SetMax(1000.0);

  std::ostrstream *os;

  // Test #1, filter goes out of scope
  itk::OutputWindow::GetInstance()->DisplayText( "Test #1: Filter goes out of scope -----------------" );
  {
  itk::ThresholdImageFilter<FloatImage2DType>::Pointer threshold;
  threshold = itk::ThresholdImageFilter<FloatImage2DType>::New();
  threshold->SetInput(random->GetOutput());
  threshold->Update();

  os = new std::ostrstream();
  *os << "Filter: " << threshold.GetPointer() << std::ends;
  itk::OutputWindow::GetInstance()->DisplayText( os->str() );
  os->rdbuf()->freeze(0);
  delete os;
  os = new std::ostrstream();
  *os << "Output #0: " << threshold->GetOutput(0).GetPointer() << std::ends;
  itk::OutputWindow::GetInstance()->DisplayText( os->str() );
  os->rdbuf()->freeze(0);
  delete os;
  os = new std::ostrstream();
  *os << "Output #1: " << threshold->GetOutput(1).GetPointer() << std::ends;
  itk::OutputWindow::GetInstance()->DisplayText( os->str() );
  os->rdbuf()->freeze(0);
  delete os;

  threshold->GetOutput(0)->DebugOn();
  threshold->GetOutput(1)->DebugOn();
  threshold->DebugOn();

  itk::OutputWindow::GetInstance()->DisplayText( "Ending Test #1: filter goes out of scope" );
  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #1 -----------------------------------" );
  }

  // Test #2, user keeps an extra handle to an output
  itk::OutputWindow::GetInstance()->DisplayText( "Test #2: User keeps an extra hold on an output  -----------------" );
  {
  FloatImage2DType::Pointer keep;

  itk::ThresholdImageFilter<FloatImage2DType>::Pointer threshold;
  threshold = itk::ThresholdImageFilter<FloatImage2DType>::New();
  threshold->SetInput(random->GetOutput());
  threshold->Update();

  os = new std::ostrstream();
  *os << "Filter: " << threshold.GetPointer() << std::ends;
  itk::OutputWindow::GetInstance()->DisplayText( os->str() );
  os->rdbuf()->freeze(0);
  delete os;
  os = new std::ostrstream();
  *os << "Output #0: " << threshold->GetOutput(0).GetPointer() << std::ends;
  itk::OutputWindow::GetInstance()->DisplayText( os->str() );
  os->rdbuf()->freeze(0);
  delete os;
  os = new std::ostrstream();
  *os << "Output #1: " << threshold->GetOutput(1).GetPointer() << std::ends;
  itk::OutputWindow::GetInstance()->DisplayText( os->str() );
  os->rdbuf()->freeze(0);
  delete os;

  threshold->GetOutput(0)->DebugOn();
  threshold->GetOutput(1)->DebugOn();
  threshold->DebugOn();

  keep = threshold->GetOutput(0);

  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #2: last handle on output 0 should go out of scope");
  }
  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #2 -----------------------------------");

  // Test #3, user disconnects a data object from the pipeline
  itk::OutputWindow::GetInstance()->DisplayText( "Test #3: application disconnects a data object from the pipeline  -----------------" );
  {
  FloatImage2DType::Pointer keep;

  itk::ThresholdImageFilter<FloatImage2DType>::Pointer threshold;
  threshold = itk::ThresholdImageFilter<FloatImage2DType>::New();
  threshold->SetInput(random->GetOutput());
  threshold->Update();

  os = new std::ostrstream();
  *os << "Filter: " << threshold.GetPointer() << std::ends;
  itk::OutputWindow::GetInstance()->DisplayText( os->str() );
  os->rdbuf()->freeze(0);
  delete os;
  os = new std::ostrstream();
  *os << "Output #0: " << threshold->GetOutput(0).GetPointer() << std::ends;
  itk::OutputWindow::GetInstance()->DisplayText( os->str() );
  os->rdbuf()->freeze(0);
  delete os;
  os = new std::ostrstream();
  *os << "Output #1: " << threshold->GetOutput(1).GetPointer() << std::ends;
  itk::OutputWindow::GetInstance()->DisplayText( os->str() );
  os->rdbuf()->freeze(0);
  delete os;

  threshold->GetOutput(0)->DebugOn();
  threshold->GetOutput(1)->DebugOn();
  threshold->DebugOn();

  keep = threshold->GetOutput(0);
  keep->DisconnectPipeline();

  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #3: last handle on output 0 should go out of scope");
  }
  itk::OutputWindow::GetInstance()->DisplayText( "End of Test #3 -----------------------------------");

  return EXIT_SUCCESS;
}

<|endoftext|>