<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  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 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
/////////////////////////////////////////////////////////////////////////

#include "bochs.h"

#if !((BX_HAVE_HASH_MAP || BX_HAVE_HASH_MAP_H) && (BX_HAVE_SET || BX_HAVE_SET_H))

static char *BX_HAVE_HASH_MAP_ERR = "context not implemented because BX_HAVE_HASH_MAP=0\n";

char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base)
{
  static bx_bool first = true;
  if (first) {
    dbg_printf ( BX_HAVE_HASH_MAP_ERR);
    first = false;
  }
  return "unk. ctxt";
}

char* bx_dbg_symbolic_address_16bit(Bit32u eip, Bit32u cs)
{
  // just prints an error anyway
  return bx_dbg_symbolic_address (0,0,0);
}

void bx_dbg_symbol_command(char* filename, bx_bool global, Bit32u offset)
{
  dbg_printf ( BX_HAVE_HASH_MAP_ERR);
}

void bx_dbg_info_symbols_command(char *Symbol)
{
  dbg_printf ( BX_HAVE_HASH_MAP_ERR);
}

int bx_dbg_lbreakpoint_symbol_command(char *Symbol)
{
  dbg_printf ( BX_HAVE_HASH_MAP_ERR);
  return -1;
}

Bit32u bx_dbg_get_symbol_value(char *Symbol)
{
  return 0;
}

char* bx_dbg_disasm_symbolic_address(Bit32u eip, Bit32u base)
{
  return 0;
}

#else   /* if BX_HAVE_HASH_MAP == 1 */

/* Haven't figured out how to port this code to OSF1 cxx compiler.
   Until a more portable solution is found, at least make it easy
   to disable the template code:  just set BX_HAVE_HASH_MAP=0
   in config.h */
#if BX_HAVE_HASH_MAP
#include <hash_map>
#elif BX_HAVE_HASH_MAP_H
#include <hash_map.h>
#endif

#if BX_HAVE_SET
#include <set>
#elif BX_HAVE_SET_H
#include <set.h>
#endif

using namespace std;

struct symbol_entry_t
{
  symbol_entry_t (Bit32u _start = 0, char* _name = 0)
  {
    start = _start;
    name = _name;
  }

  char* name;
  Bit32u start;
};

struct lt_symbol_entry_t
{
  bool operator()(const symbol_entry_t* s1, const symbol_entry_t* s2) const
  {
    return s1->start < s2->start;
  }
};

struct lt_rsymbol_entry_t
{
  bool operator()(const symbol_entry_t* s1, const symbol_entry_t* s2) const
  {
    return strcoll(s1->name, s2->name) < 0;
  }
};

struct context_t
{
  context_t (Bit32u);
  ~context_t();
  static context_t* get_context(Bit32u);
  symbol_entry_t* get_symbol_entry(Bit32u);
  symbol_entry_t* get_symbol_entry(const char *Symbol) const;
  void add_symbol(symbol_entry_t*);
  const set<symbol_entry_t*,lt_symbol_entry_t>* get_all_symbols() const {return syms;}
  const set<symbol_entry_t*,lt_rsymbol_entry_t>* get_all_rsymbols() const {return rsyms;}
private:
  static hash_map<int,context_t*>* map;
  // Forvard references (find name by address)
  set<symbol_entry_t*,lt_symbol_entry_t>* syms;
  // Reverse references (find address by name)
  set<symbol_entry_t*,lt_rsymbol_entry_t>* rsyms;
  Bit32u id;
};

hash_map<int,context_t*>* context_t::map = new hash_map<int,context_t*>;

context_t::context_t (Bit32u _id)
{
  id = _id;
  syms = new set<symbol_entry_t*, lt_symbol_entry_t>;
  rsyms = new set<symbol_entry_t*, lt_rsymbol_entry_t>;
  (*map)[id] = this;
}

context_t::~context_t()
{
 set<symbol_entry_t*>::iterator iter;
 if(syms) {
  for(iter=syms->begin();iter!=syms->end();++iter)
   if(*iter)
    delete *iter;
 }

 if(rsyms) {
  for(iter=rsyms->begin();iter!=rsyms->end();++iter)
   if(*iter)
    delete *iter;
 }
}

context_t* context_t::get_context(Bit32u i)
{
  return (*map)[i];
}

symbol_entry_t* context_t::get_symbol_entry(Bit32u ip)
{
  symbol_entry_t probe;
  probe.start = ip;
  // find the first symbol whose address is greater than ip.
  if (syms->empty ()) return 0;
  set<symbol_entry_t*>::iterator iter = syms->upper_bound(&probe);

  if (iter == syms->end()) { // No symbol found
    return 0;
  }

  return *(--iter);
}

symbol_entry_t* context_t::get_symbol_entry(const char *Symbol) const
{
  symbol_entry_t probe;
  probe.name=(char *)Symbol;

  if (rsyms->empty ())
   return 0;

  set<symbol_entry_t*>::const_iterator iter;
  iter=rsyms->find(&probe);
  if(iter==rsyms->end()) // No symbol found
   return 0;
  return *iter;
}

void context_t::add_symbol(symbol_entry_t* sym)
{
  syms->insert(sym);
  rsyms->insert(sym);
}

Bit32u bx_dbg_get_symbol_value(char *Symbol)
{
 context_t* cntx = context_t::get_context(0);
 if(!cntx) // Context not found
  return 0;

 if (Symbol[0]=='\"') Symbol++;
 int len = strlen(Symbol);
 if (Symbol[len - 1] == '\"') Symbol[len - 1] = '\0';

 symbol_entry_t* sym=cntx->get_symbol_entry(Symbol);
 if(!sym) // Symbol not found
  return 0;

 return sym->start;
}

char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base)
{
  static char buf[80];
#if 0
  // bbd: I don't see why we shouldn't allow symbol lookups on
  // segments with a nonzero base.  I need to trace user
  // processes in Linux, which have a base of 0xc0000000.
  if (base != 0) {
    snprintf (buf, 80, "non-zero base");
    return buf;
  }
#endif
  // Look up this context
  context_t* cntx = context_t::get_context(context);
  if (!cntx) {
    // Try global context
    cntx = context_t::get_context(0);
    if (!cntx) {
      snprintf (buf, 80, "unk. ctxt");
      return buf;
    }
  }
  // full linear address not only eip (for nonzero based segments)
  symbol_entry_t* entr = cntx->get_symbol_entry(base+eip);
  if (!entr) {
    snprintf (buf, 80, "no symbol");
    return buf;
  }
  snprintf (buf, 80, "%s+%x", entr->name, (base+eip) - entr->start);
  return buf;
}

char* bx_dbg_disasm_symbolic_address(Bit32u eip, Bit32u base)
{
  static char buf[80];

  // Try global context
  context_t* cntx = context_t::get_context(0);
  if (!cntx) {
    return 0;
  }

  // full linear address not only eip (for nonzero based segments)
  symbol_entry_t* entr = cntx->get_symbol_entry(base+eip);
  if (!entr) {
    return 0;
  }
  snprintf (buf, 80, "%s+%x", entr->name, (base+eip) - entr->start);
  return buf;
}

char* bx_dbg_symbolic_address_16bit(Bit32u eip, Bit32u cs)
{
  // in 16-bit code, the segment selector and offset are combined into a
  // 20-bit linear address = (segment selector<<4) + offset.
  eip &= 0xffff;
  cs &= 0xffff;
  return bx_dbg_symbolic_address (0, eip+(cs<<4), 0);
}

void bx_dbg_symbol_command(char* filename, bx_bool global, Bit32u offset)
{
  if (filename[0] == '"')
    filename++;
  int len = strlen(filename);
  if (filename[len - 1] == '"')
    filename[len - 1] = '\0';

  // Install symbols in correct context (page table)
  // The file format should be
  // address symbol (example '00002afe _StartLoseNT')

  context_t* cntx = (global) ? context_t::get_context(0)
      : context_t::get_context((BX_CPU(dbg_cpu)->cr3) >> 12);

  if (!cntx) {
    cntx = (global) ? new context_t(0)
       : new context_t((BX_CPU(dbg_cpu)->cr3) >> 12);
  }

  FILE* fp = fopen(filename, "rt"); // 't' is need for win32, unixes simply ignore it
  if (!fp) {
    dbg_printf ("Could not open symbol file '%s'\n", filename);
    return;
  }
  char buf[200];
  while (fgets(buf, 200, fp)) {
    // Parse
    char* sym_name = buf;

    for (int i = 0; i < 200 && buf[i]; i++) {
      if (buf[i] == ' ') {
        buf[i] = '\0';
        sym_name = buf + i + 1;
        break;
      }
    }
    if (sym_name == buf) {
      dbg_printf ("Syntax error '%s'\n", buf);
      break;
    }
    Bit32u addr = strtoul(buf, 0, 16);
    if (sym_name[strlen(sym_name)-1] == '\n')
      sym_name[strlen(sym_name)-1] = '\0';
    symbol_entry_t* sym = new symbol_entry_t(addr + offset, strdup(sym_name));
    cntx->add_symbol(sym);
  }
}

// chack if s1 is prefix of s2
static bool bx_dbg_strprefix(const char *s1, const char *s2)
{
  if(!s1 || !s2)
   return false;

  size_t len=strlen(s1);

  if(len>strlen(s2))
   return false;
  return strncmp(s1, s2, len)==0;
}

void bx_dbg_info_symbols_command(char *Symbol)
{
  context_t* cntx = context_t::get_context(0);

  if(!cntx) {
   dbg_printf ("Global context not available\n");
   return;
  }

  if(Symbol) {
   const set<symbol_entry_t*,lt_rsymbol_entry_t>* rsyms;

   rsyms=cntx->get_all_rsymbols();
   if (rsyms->empty ()) {
    dbg_printf ("Symbols not loaded\n");
    return;
   }
   // remove leading and trailing quotas
   if (Symbol[0]=='\"') Symbol++;
   int len = strlen(Symbol);
   if (Symbol[len - 1] == '\"') Symbol[len - 1] = '\0';

   symbol_entry_t probe;
   probe.name=Symbol;
   set<symbol_entry_t*>::const_iterator iter;
   iter=rsyms->lower_bound(&probe);

   if(iter==rsyms->end() || !bx_dbg_strprefix(Symbol, (*iter)->name))
    dbg_printf ("No symbols found\n");
   else
   for(;iter!=rsyms->end() && bx_dbg_strprefix(Symbol, (*iter)->name);++iter) {
    dbg_printf ("%08x: %s\n", (*iter)->start, (*iter)->name);
   }
  }
  else {
   const set<symbol_entry_t*,lt_symbol_entry_t>* syms;

   syms=cntx->get_all_symbols();
   if (syms->empty ()) {
    dbg_printf ("Symbols not loaded\n");
    return;
   }

   set<symbol_entry_t*>::const_iterator iter;
   for(iter = syms->begin();iter!=syms->end();++iter) {
    dbg_printf ("%08x: %s\n", (*iter)->start, (*iter)->name);
   }
  }
}

int bx_dbg_lbreakpoint_symbol_command(char *Symbol)
{
 context_t* cntx = context_t::get_context(0);
 if(!cntx) {
  dbg_printf ("Global context not available\n");
  return -1;
 }
 if (Symbol[0]=='\"') Symbol++;
 int len = strlen(Symbol);
 if (Symbol[len - 1] == '\"') Symbol[len - 1] = '\0';

 const symbol_entry_t* sym=cntx->get_symbol_entry(Symbol);
 if(sym)
  return bx_dbg_lbreakpoint_command(bkRegular, sym->start);
 dbg_printf ("Symbol not found\n");
 return -1;
}
#endif
<commit_msg>dos2unix fix<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  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 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
/////////////////////////////////////////////////////////////////////////

#include "bochs.h"

#if !((BX_HAVE_HASH_MAP || BX_HAVE_HASH_MAP_H) && (BX_HAVE_SET || BX_HAVE_SET_H))

static char *BX_HAVE_HASH_MAP_ERR = "context not implemented because BX_HAVE_HASH_MAP=0\n";

char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base)
{
  static bx_bool first = true;
  if (first) {
    dbg_printf ( BX_HAVE_HASH_MAP_ERR);
    first = false;
  }
  return "unk. ctxt";
}

char* bx_dbg_symbolic_address_16bit(Bit32u eip, Bit32u cs)
{
  // just prints an error anyway
  return bx_dbg_symbolic_address (0,0,0);
}

void bx_dbg_symbol_command(char* filename, bx_bool global, Bit32u offset)
{
  dbg_printf ( BX_HAVE_HASH_MAP_ERR);
}

void bx_dbg_info_symbols_command(char *Symbol)
{
  dbg_printf ( BX_HAVE_HASH_MAP_ERR);
}

int bx_dbg_lbreakpoint_symbol_command(char *Symbol)
{
  dbg_printf ( BX_HAVE_HASH_MAP_ERR);
  return -1;
}

Bit32u bx_dbg_get_symbol_value(char *Symbol)
{
  return 0;
}

char* bx_dbg_disasm_symbolic_address(Bit32u eip, Bit32u base)
{
  return 0;
}

#else   /* if BX_HAVE_HASH_MAP == 1 */

/* Haven't figured out how to port this code to OSF1 cxx compiler.
   Until a more portable solution is found, at least make it easy
   to disable the template code:  just set BX_HAVE_HASH_MAP=0
   in config.h */
#if BX_HAVE_HASH_MAP
#include <hash_map>
#elif BX_HAVE_HASH_MAP_H
#include <hash_map.h>
#endif

#if BX_HAVE_SET
#include <set>
#elif BX_HAVE_SET_H
#include <set.h>
#endif

using namespace std;

struct symbol_entry_t
{
  symbol_entry_t (Bit32u _start = 0, char* _name = 0)
  {
    start = _start;
    name = _name;
  }

  char* name;
  Bit32u start;
};

struct lt_symbol_entry_t
{
  bool operator()(const symbol_entry_t* s1, const symbol_entry_t* s2) const
  {
    return s1->start < s2->start;
  }
};

struct lt_rsymbol_entry_t
{
  bool operator()(const symbol_entry_t* s1, const symbol_entry_t* s2) const
  {
    return strcoll(s1->name, s2->name) < 0;
  }
};

struct context_t
{
  context_t (Bit32u);
  ~context_t();
  static context_t* get_context(Bit32u);
  symbol_entry_t* get_symbol_entry(Bit32u);
  symbol_entry_t* get_symbol_entry(const char *Symbol) const;
  void add_symbol(symbol_entry_t*);
  const set<symbol_entry_t*,lt_symbol_entry_t>* get_all_symbols() const {return syms;}
  const set<symbol_entry_t*,lt_rsymbol_entry_t>* get_all_rsymbols() const {return rsyms;}
private:
  static hash_map<int,context_t*>* map;
  // Forvard references (find name by address)
  set<symbol_entry_t*,lt_symbol_entry_t>* syms;
  // Reverse references (find address by name)
  set<symbol_entry_t*,lt_rsymbol_entry_t>* rsyms;
  Bit32u id;
};

hash_map<int,context_t*>* context_t::map = new hash_map<int,context_t*>;

context_t::context_t (Bit32u _id)
{
  id = _id;
  syms = new set<symbol_entry_t*, lt_symbol_entry_t>;
  rsyms = new set<symbol_entry_t*, lt_rsymbol_entry_t>;
  (*map)[id] = this;
}

context_t::~context_t()
{
 set<symbol_entry_t*>::iterator iter;
 if(syms) {
  for(iter=syms->begin();iter!=syms->end();++iter)
   if(*iter)
    delete *iter;
 }

 if(rsyms) {
  for(iter=rsyms->begin();iter!=rsyms->end();++iter)
   if(*iter)
    delete *iter;
 }
}

context_t* context_t::get_context(Bit32u i)
{
  return (*map)[i];
}

symbol_entry_t* context_t::get_symbol_entry(Bit32u ip)
{
  symbol_entry_t probe;
  probe.start = ip;
  // find the first symbol whose address is greater than ip.
  if (syms->empty ()) return 0;
  set<symbol_entry_t*>::iterator iter = syms->upper_bound(&probe);

  if (iter == syms->end()) { // No symbol found
    return 0;
  }

  return *(--iter);
}

symbol_entry_t* context_t::get_symbol_entry(const char *Symbol) const
{
  symbol_entry_t probe;
  probe.name=(char *)Symbol;

  if (rsyms->empty ())
   return 0;

  set<symbol_entry_t*>::const_iterator iter;
  iter=rsyms->find(&probe);
  if(iter==rsyms->end()) // No symbol found
   return 0;
  return *iter;
}

void context_t::add_symbol(symbol_entry_t* sym)
{
  syms->insert(sym);
  rsyms->insert(sym);
}

Bit32u bx_dbg_get_symbol_value(char *Symbol)
{
 context_t* cntx = context_t::get_context(0);
 if(!cntx) // Context not found
  return 0;

 if (Symbol[0]=='\"') Symbol++;
 int len = strlen(Symbol);
 if (Symbol[len - 1] == '\"') Symbol[len - 1] = '\0';

 symbol_entry_t* sym=cntx->get_symbol_entry(Symbol);
 if(!sym) // Symbol not found
  return 0;

 return sym->start;
}

char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base)
{
  static char buf[80];
#if 0
  // bbd: I don't see why we shouldn't allow symbol lookups on
  // segments with a nonzero base.  I need to trace user
  // processes in Linux, which have a base of 0xc0000000.
  if (base != 0) {
    snprintf (buf, 80, "non-zero base");
    return buf;
  }
#endif
  // Look up this context
  context_t* cntx = context_t::get_context(context);
  if (!cntx) {
    // Try global context
    cntx = context_t::get_context(0);
    if (!cntx) {
      snprintf (buf, 80, "unk. ctxt");
      return buf;
    }
  }
  // full linear address not only eip (for nonzero based segments)
  symbol_entry_t* entr = cntx->get_symbol_entry(base+eip);
  if (!entr) {
    snprintf (buf, 80, "no symbol");
    return buf;
  }
  snprintf (buf, 80, "%s+%x", entr->name, (base+eip) - entr->start);
  return buf;
}

char* bx_dbg_disasm_symbolic_address(Bit32u eip, Bit32u base)
{
  static char buf[80];

  // Try global context
  context_t* cntx = context_t::get_context(0);
  if (!cntx) {
    return 0;
  }

  // full linear address not only eip (for nonzero based segments)
  symbol_entry_t* entr = cntx->get_symbol_entry(base+eip);
  if (!entr) {
    return 0;
  }
  snprintf (buf, 80, "%s+%x", entr->name, (base+eip) - entr->start);
  return buf;
}

char* bx_dbg_symbolic_address_16bit(Bit32u eip, Bit32u cs)
{
  // in 16-bit code, the segment selector and offset are combined into a
  // 20-bit linear address = (segment selector<<4) + offset.
  eip &= 0xffff;
  cs &= 0xffff;
  return bx_dbg_symbolic_address (0, eip+(cs<<4), 0);
}

void bx_dbg_symbol_command(char* filename, bx_bool global, Bit32u offset)
{
  if (filename[0] == '"')
    filename++;
  int len = strlen(filename);
  if (filename[len - 1] == '"')
    filename[len - 1] = '\0';

  // Install symbols in correct context (page table)
  // The file format should be
  // address symbol (example '00002afe _StartLoseNT')

  context_t* cntx = (global) ? context_t::get_context(0)
      : context_t::get_context((BX_CPU(dbg_cpu)->cr3) >> 12);

  if (!cntx) {
    cntx = (global) ? new context_t(0)
       : new context_t((BX_CPU(dbg_cpu)->cr3) >> 12);
  }

  FILE* fp = fopen(filename, "rt"); // 't' is need for win32, unixes simply ignore it
  if (!fp) {
    dbg_printf ("Could not open symbol file '%s'\n", filename);
    return;
  }
  char buf[200];
  while (fgets(buf, 200, fp)) {
    // Parse
    char* sym_name = buf;

    for (int i = 0; i < 200 && buf[i]; i++) {
      if (buf[i] == ' ') {
        buf[i] = '\0';
        sym_name = buf + i + 1;
        break;
      }
    }
    if (sym_name == buf) {
      dbg_printf ("Syntax error '%s'\n", buf);
      break;
    }
    Bit32u addr = strtoul(buf, 0, 16);
    if (sym_name[strlen(sym_name)-1] == '\n')
      sym_name[strlen(sym_name)-1] = '\0';
    symbol_entry_t* sym = new symbol_entry_t(addr + offset, strdup(sym_name));
    cntx->add_symbol(sym);
  }
}

// chack if s1 is prefix of s2
static bool bx_dbg_strprefix(const char *s1, const char *s2)
{
  if(!s1 || !s2)
   return false;

  size_t len=strlen(s1);

  if(len>strlen(s2))
   return false;
  return strncmp(s1, s2, len)==0;
}

void bx_dbg_info_symbols_command(char *Symbol)
{
  context_t* cntx = context_t::get_context(0);

  if(!cntx) {
   dbg_printf ("Global context not available\n");
   return;
  }

  if(Symbol) {
   const set<symbol_entry_t*,lt_rsymbol_entry_t>* rsyms;

   rsyms=cntx->get_all_rsymbols();
   if (rsyms->empty ()) {
    dbg_printf ("Symbols not loaded\n");
    return;
   }
   // remove leading and trailing quotas
   if (Symbol[0]=='\"') Symbol++;
   int len = strlen(Symbol);
   if (Symbol[len - 1] == '\"') Symbol[len - 1] = '\0';

   symbol_entry_t probe;
   probe.name=Symbol;
   set<symbol_entry_t*>::const_iterator iter;
   iter=rsyms->lower_bound(&probe);

   if(iter==rsyms->end() || !bx_dbg_strprefix(Symbol, (*iter)->name))
    dbg_printf ("No symbols found\n");
   else
   for(;iter!=rsyms->end() && bx_dbg_strprefix(Symbol, (*iter)->name);++iter) {
    dbg_printf ("%08x: %s\n", (*iter)->start, (*iter)->name);
   }
  }
  else {
   const set<symbol_entry_t*,lt_symbol_entry_t>* syms;

   syms=cntx->get_all_symbols();
   if (syms->empty ()) {
    dbg_printf ("Symbols not loaded\n");
    return;
   }

   set<symbol_entry_t*>::const_iterator iter;
   for(iter = syms->begin();iter!=syms->end();++iter) {
    dbg_printf ("%08x: %s\n", (*iter)->start, (*iter)->name);
   }
  }
}

int bx_dbg_lbreakpoint_symbol_command(char *Symbol)
{
 context_t* cntx = context_t::get_context(0);
 if(!cntx) {
  dbg_printf ("Global context not available\n");
  return -1;
 }
 if (Symbol[0]=='\"') Symbol++;
 int len = strlen(Symbol);
 if (Symbol[len - 1] == '\"') Symbol[len - 1] = '\0';

 const symbol_entry_t* sym=cntx->get_symbol_entry(Symbol);
 if(sym)
  return bx_dbg_lbreakpoint_command(bkRegular, sym->start);
 dbg_printf ("Symbol not found\n");
 return -1;
}
#endif
<|endoftext|>


<commit_before>#pragma once

// https://infektor.net/posts/2017-03-31-range-based-enumerate.html

#include <iterator>
#include <utility>

// ----------------------------------------------------------------------

namespace _enumerate_internal
{
    template <typename Iterator, typename index_type> struct enumerate_iterator
    {
        using iterator = Iterator;
          //using index_type = typename std::iterator_traits<iterator>::difference_type;
        using reference = typename std::iterator_traits<iterator>::reference;

        enumerate_iterator(index_type aIndex, iterator aIterator) : index(aIndex), iter(aIterator) {}
        enumerate_iterator& operator++() { ++index; ++iter; return *this; }
        bool operator!=(const enumerate_iterator &other) const { return iter != other.iter; }
        std::pair<index_type&, reference> operator*() { return {index, *iter}; }

     private:
        index_type index;
        iterator iter;
    };

      // ----------------------------------------------------------------------

    template <typename Iterator, typename index_type> struct enumerate_range
    {
        // using index_type = typename std::iterator_traits<Iterator>::difference_type;
        using iterator = enumerate_iterator<Iterator, index_type>;

        enumerate_range(Iterator aFirst, Iterator aLast, index_type aInitial) : first(aFirst), last(aLast), initial(aInitial) {}
        iterator begin() const { return iterator(initial, first); }
        iterator end() const { return iterator(0, last); }

     private:
        Iterator first;
        Iterator last;
        index_type initial;
    };

} // namespace _enumerate_internal

// ----------------------------------------------------------------------

namespace acmacs
{
    template <typename Iterator, typename index_type> auto enumerate(Iterator first, Iterator last, index_type initial = 0)
    {
        return _enumerate_internal::enumerate_range<Iterator, index_type>(first, last, initial);
    }

    template <typename Container> auto enumerate(Container& content)
    {
        using iter_type = decltype(std::begin(content));
        return _enumerate_internal::enumerate_range<iter_type, size_t>(std::begin(content), std::end(content), 0U);
    }

    template <typename Container> auto enumerate(const Container& content)
    {
        using iter_type = decltype(std::begin(content));
        return _enumerate_internal::enumerate_range<iter_type, size_t>(std::begin(content), std::end(content), 0U);
    }
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>minor enumerate fixes<commit_after>#pragma once

// https://infektor.net/posts/2017-03-31-range-based-enumerate.html

#include <iterator>
#include <utility>

// ----------------------------------------------------------------------

namespace acmacs
{
    namespace _enumerate_internal
    {
        template <typename Iterator, typename index_type> struct enumerate_iterator
        {
            using iterator = Iterator;
              //using index_type = typename std::iterator_traits<iterator>::difference_type;
            using reference = typename std::iterator_traits<iterator>::reference;

            inline enumerate_iterator(index_type aIndex, iterator aIterator) : index(aIndex), iter(aIterator) {}
            inline enumerate_iterator& operator++() { ++index; ++iter; return *this; }
            inline bool operator!=(const enumerate_iterator &other) const { return iter != other.iter; }
            inline std::pair<index_type&, reference> operator*() { return {index, *iter}; }

         private:
            index_type index;
            iterator iter;
        };

          // ----------------------------------------------------------------------

        template <typename Iterator, typename index_type> struct enumerate_range
        {
              // using index_type = typename std::iterator_traits<Iterator>::difference_type;
            using iterator = enumerate_iterator<Iterator, index_type>;

            inline enumerate_range(Iterator aFirst, Iterator aLast, index_type aInitial) : first(aFirst), last(aLast), initial(aInitial) {}
            inline iterator begin() const { return iterator(initial, first); }
            inline iterator end() const { return iterator(0, last); }

         private:
            Iterator first;
            Iterator last;
            index_type initial;
        };

    } // namespace _enumerate_internal

// ----------------------------------------------------------------------

    template <typename Iterator, typename index_type> inline auto enumerate(Iterator first, Iterator last, index_type initial = 0)
    {
        return _enumerate_internal::enumerate_range<Iterator, index_type>(first, last, initial);
    }

    template <typename Container> inline auto enumerate(Container& content)
    {
        using iter_type = decltype(std::begin(content));
        return _enumerate_internal::enumerate_range<iter_type, size_t>(std::begin(content), std::end(content), 0U);
    }

    template <typename Container> inline auto enumerate(const Container& content)
    {
        using iter_type = decltype(std::begin(content));
        return _enumerate_internal::enumerate_range<iter_type, size_t>(std::begin(content), std::end(content), 0U);
    }

} // namespace acmacs

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qmessageid.h"
#include <qhash.h>
#include <messagingutil_p.h>

QTM_BEGIN_NAMESPACE

class QMessageIdPrivate
{
public:
    QString _id;
};

QMessageId::QMessageId()
 : d_ptr(0)
{
}

QMessageId::QMessageId(const QMessageId& other)
 : d_ptr(0)
{
	this->operator=(other);
}

QMessageId::QMessageId(const QString& id)
{
    d_ptr = new QMessageIdPrivate;
    d_ptr->_id = id;
}

QMessageId::~QMessageId()
{
	delete d_ptr;
}

QMessageId& QMessageId::operator=(const QMessageId& other)
{
    if (!other.d_ptr) {
        delete d_ptr;
        return *this;
    }

    if (!d_ptr)
        d_ptr = new QMessageIdPrivate;

    d_ptr->_id = other.d_ptr->_id;

    return *this;
}

bool QMessageId::operator==(const QMessageId& other) const
{
    if (!other.d_ptr && !d_ptr)
        return true;

    if (!other.d_ptr || !d_ptr)
        return false;

    return (d_ptr->_id == other.d_ptr->_id);
}

bool QMessageId::operator<(const QMessageId& other) const
{
    long left = 0;
    long right = 0;
    if (d_ptr) {
        left = SymbianHelpers::stripIdPrefix(d_ptr->_id).toLong();
        //left = d_ptr->_id.toLong();
    }
    if (other.d_ptr) {
        right = SymbianHelpers::stripIdPrefix(other.d_ptr->_id).toLong();
        //right = other.d_ptr->_id.toLong();
    }

    return (left < right);
}

QString QMessageId::toString() const
{
    return d_ptr ? d_ptr->_id : QString();
}

bool QMessageId::isValid() const
{
    return d_ptr ? true : false;
}

uint qHash(const QMessageId &id)
{
    return qHash(id.toString());
}

QTM_END_NAMESPACE
<commit_msg>Fixed: Assigning an invalid QMessageId causes crash on Symbian<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qmessageid.h"
#include <qhash.h>
#include <messagingutil_p.h>

QTM_BEGIN_NAMESPACE

class QMessageIdPrivate
{
public:
    QString _id;
};

QMessageId::QMessageId()
 : d_ptr(0)
{
}

QMessageId::QMessageId(const QMessageId& other)
 : d_ptr(0)
{
	this->operator=(other);
}

QMessageId::QMessageId(const QString& id)
{
    d_ptr = new QMessageIdPrivate;
    d_ptr->_id = id;
}

QMessageId::~QMessageId()
{
	delete d_ptr;
}

QMessageId& QMessageId::operator=(const QMessageId& other)
{
    if (!other.d_ptr) {
        delete d_ptr;
        d_ptr = 0;
        return *this;
    }

    if (!d_ptr)
        d_ptr = new QMessageIdPrivate;

    d_ptr->_id = other.d_ptr->_id;

    return *this;
}

bool QMessageId::operator==(const QMessageId& other) const
{
    if (!other.d_ptr && !d_ptr)
        return true;

    if (!other.d_ptr || !d_ptr)
        return false;

    return (d_ptr->_id == other.d_ptr->_id);
}

bool QMessageId::operator<(const QMessageId& other) const
{
    long left = 0;
    long right = 0;
    if (d_ptr) {
        left = SymbianHelpers::stripIdPrefix(d_ptr->_id).toLong();
        //left = d_ptr->_id.toLong();
    }
    if (other.d_ptr) {
        right = SymbianHelpers::stripIdPrefix(other.d_ptr->_id).toLong();
        //right = other.d_ptr->_id.toLong();
    }

    return (left < right);
}

QString QMessageId::toString() const
{
    return d_ptr ? d_ptr->_id : QString();
}

bool QMessageId::isValid() const
{
    return d_ptr ? true : false;
}

uint qHash(const QMessageId &id)
{
    return qHash(id.toString());
}

QTM_END_NAMESPACE
<|endoftext|>


<commit_before>/**
 * @file tree_traits.hpp
 * @author Ryan Curtin
 *
 * This file implements the basic, unspecialized TreeTraits class, which
 * provides information about tree types.  If you create a tree class, you
 * should specialize this class with the characteristics of your tree.
 */
#ifndef __MLPACK_CORE_TREE_TREE_TRAITS_HPP
#define __MLPACK_CORE_TREE_TREE_TRAITS_HPP

namespace mlpack {
namespace tree {

/**
 * The TreeTraits class provides compile-time information on the characteristics
 * of a given tree type.  These include traits such as whether or not a node
 * knows the distance to its parent node, or whether or not the subspaces
 * represented by children can overlap.
 *
 * These traits can be used for static compile-time optimization:
 *
 * @code
 * // This if statement will be optimized out at compile time!
 * if (TreeTraits<TreeType>::HasOverlappingChildren == false)
 * {
 *   // Do a simpler computation because no children overlap.
 * }
 * else
 * {
 *   // Do the full, complex calculation.
 * }
 * @endcode
 *
 * The traits can also be used in conjunction with SFINAE to write specialized
 * versions of functions:
 *
 * @code
 * template<typename TreeType>
 * void Compute(TreeType& node,
 *              boost::enable_if<
 *                  TreeTraits<TreeType>::RearrangesDataset>::type*)
 * {
 *   // Computation where special dataset-rearranging tree constructor is
 *   // called.
 * }
 *
 * template<typename TreeType>
 * void Compute(TreeType& node,
 *              boost::enable_if<
 *                  !TreeTraits<TreeType>::RearrangesDataset>::type*)
 * {
 *   // Computation where normal tree constructor is called.
 * }
 * @endcode
 *
 * In those two examples, the boost::enable_if<> class takes a boolean template
 * parameter which allows that function to be called when the boolean is true.
 *
 * Each trait must be a static const value and not a function; only const values
 * can be used as template parameters (with the exception of constexprs, which
 * are a C++11 feature; but MLPACK is not using C++11).  By default (the
 * unspecialized implementation of TreeTraits), each parameter is set to make as
 * few assumptions about the tree as possible; so, even if TreeTraits is not
 * specialized for a particular tree type, tree-based algorithms should still
 * work.
 *
 * When you write your own tree, you must specialize the TreeTraits class to
 * your tree type and set the corresponding values appropriately.  See
 * mlpack/core/tree/binary_space_tree/traits.hpp for an example.
 */
template<typename TreeType>
class TreeTraits
{
 public:
  /**
   * This is true if the subspaces represented by the children of a node can
   * overlap.
   */
  static const bool HasOverlappingChildren = true;

  /**
   * This is true if Point(0) is the centroid of the node.
   */
  static const bool FirstPointIsCentroid = false;

  /**
   * This is true if the points contained in the first child of a node
   * (Child(0)) are also contained in that node.
   */
  static const bool HasSelfChildren = false;

  /**
   * This is true if the tree rearranges points in the dataset when it is built.
   */
  static const bool RearrangesDataset = false;

  /**
   * This is true if the tree always has only two children.
   */
  static const bool BinaryTree = false;
};

}; // namespace tree
}; // namespace mlpack

#endif
<commit_msg>We use C++11 now; update the comment.<commit_after>/**
 * @file tree_traits.hpp
 * @author Ryan Curtin
 *
 * This file implements the basic, unspecialized TreeTraits class, which
 * provides information about tree types.  If you create a tree class, you
 * should specialize this class with the characteristics of your tree.
 */
#ifndef __MLPACK_CORE_TREE_TREE_TRAITS_HPP
#define __MLPACK_CORE_TREE_TREE_TRAITS_HPP

namespace mlpack {
namespace tree {

/**
 * The TreeTraits class provides compile-time information on the characteristics
 * of a given tree type.  These include traits such as whether or not a node
 * knows the distance to its parent node, or whether or not the subspaces
 * represented by children can overlap.
 *
 * These traits can be used for static compile-time optimization:
 *
 * @code
 * // This if statement will be optimized out at compile time!
 * if (TreeTraits<TreeType>::HasOverlappingChildren == false)
 * {
 *   // Do a simpler computation because no children overlap.
 * }
 * else
 * {
 *   // Do the full, complex calculation.
 * }
 * @endcode
 *
 * The traits can also be used in conjunction with SFINAE to write specialized
 * versions of functions:
 *
 * @code
 * template<typename TreeType>
 * void Compute(TreeType& node,
 *              boost::enable_if<
 *                  TreeTraits<TreeType>::RearrangesDataset>::type*)
 * {
 *   // Computation where special dataset-rearranging tree constructor is
 *   // called.
 * }
 *
 * template<typename TreeType>
 * void Compute(TreeType& node,
 *              boost::enable_if<
 *                  !TreeTraits<TreeType>::RearrangesDataset>::type*)
 * {
 *   // Computation where normal tree constructor is called.
 * }
 * @endcode
 *
 * In those two examples, the boost::enable_if<> class takes a boolean template
 * parameter which allows that function to be called when the boolean is true.
 *
 * Each trait must be a static const value and not a function; only const values
 * can be used as template parameters (or constexprs can be used too).  By
 * default (the unspecialized implementation of TreeTraits), each parameter is
 * set to make as few assumptions about the tree as possible; so, even if
 * TreeTraits is not specialized for a particular tree type, tree-based
 * algorithms should still work.
 *
 * When you write your own tree, you must specialize the TreeTraits class to
 * your tree type and set the corresponding values appropriately.  See
 * mlpack/core/tree/binary_space_tree/traits.hpp for an example.
 */
template<typename TreeType>
class TreeTraits
{
 public:
  /**
   * This is true if the subspaces represented by the children of a node can
   * overlap.
   */
  static const bool HasOverlappingChildren = true;

  /**
   * This is true if Point(0) is the centroid of the node.
   */
  static const bool FirstPointIsCentroid = false;

  /**
   * This is true if the points contained in the first child of a node
   * (Child(0)) are also contained in that node.
   */
  static const bool HasSelfChildren = false;

  /**
   * This is true if the tree rearranges points in the dataset when it is built.
   */
  static const bool RearrangesDataset = false;

  /**
   * This is true if the tree always has only two children.
   */
  static const bool BinaryTree = false;
};

}; // namespace tree
}; // namespace mlpack

#endif
<|endoftext|>


<commit_before>//!@Alan
//!
//! Exercise 5.14:
//! Write a program to read strings from standard input looking for duplicated
//! words. The program should find places in the input where one word is followed immediately
//! by itself. Keep track of the largest number of times a single repetition occurs and which
//! word is repeated. Print the maximum number of duplicates, or else print a message saying
//! that no word was repeated. For example, if the input is
//  how now now now brown cow cow
//! the output should indicate that the word now occurred three times.
//!

#include <iostream>
#include <string>

using namespace std;

int main(void)
{
    string curr_str, pre_str, re_str;
    int cnt = 1, max = 1;
    cin >> pre_str;
    while (cin >> curr_str)
    {
        if (curr_str == pre_str)
        {
            ++cnt;
            if (cnt > max)
            {
                max = cnt;
                re_str = curr_str;
            }
        }
        else
        {
            cnt = 1;
        }

        pre_str = curr_str;
    }
    if (!re_str.empty())
    {
        cout << re_str << " occurs " << max << " times" << endl;
    }
    else
    {
        cout << "no such number" << endl;
    }
    return 0;
}<commit_msg>Revert "test"<commit_after>//!@Alan
//!
//! Exercise 5.14:
//! Write a program to read strings from standard input looking for duplicated
//! words. The program should find places in the input where one word is followed immediately
//! by itself. Keep track of the largest number of times a single repetition occurs and which
//! word is repeated. Print the maximum number of duplicates, or else print a message saying
//! that no word was repeated. For example, if the input is
//  how now now now brown cow cow
//! the output should indicate that the word now occurred three times.
//!

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    string current_str, previous_str, max_str, current_repeating_str;
    int current_repeating=0, max_repeating=0;

    cout<<"Please Enter:\n";
    while (cin>>current_str)
    {
        if(current_str.compare(previous_str) == 0)
        {
            current_repeating ++ ;
            current_repeating_str = current_str;
        }
        else
        {
            current_repeating = 0;
            current_repeating_str.clear();
        }

        if(current_repeating > max_repeating)
        {
            max_repeating = current_repeating;
            max_str = current_repeating_str;
        }

        cout<<"The Max repeating string now is "
              <<max_str
                <<"\nThe repeating times="
                  <<max_repeating
                    <<std::endl;

        previous_str = current_str;

    }

    return 0;
}
<|endoftext|>


<commit_before>#include "MPU9150.h"
#include "AConfig.h"
#if(HAS_MPU9150)
#include "Device.h"
#include "Settings.h"
#include <Wire.h>
//#include "I2Cdev.h"
#include "MPU9150Lib.h"
#include "CalLib.h"
//#include "dmpKey.h"
//#include "dmpmap.h"
//#include "inv_mpu.h"
//#include "inv_mpu_dmp_motion_driver.h"
#include <EEPROM.h>
#include "Timer.h"

MPU9150Lib MPU;                                              // the MPU object
int MPUDeviceId = 1;
boolean DidInit = false;
boolean InCallibrationMode = false;
Timer MPU9150ReInit;
CALLIB_DATA calData;
Timer calibration_timer;
int counter = 0;
//  MPU_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the sensor data and DMP output

//  MPU_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the sensor data and DMP output

#define MPU_UPDATE_RATE  (20)

//  MAG_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the magnetometer data
//  MAG_UPDATE_RATE should be less than or equal to the MPU_UPDATE_RATE

#define MAG_UPDATE_RATE  (10)

//  MPU_MAG_MIX defines the influence that the magnetometer has on the yaw output.
//  The magnetometer itself is quite noisy so some mixing with the gyro yaw can help
//  significantly. Some example values are defined below:

#define  MPU_MAG_MIX_GYRO_ONLY          0                   // just use gyro yaw
#define  MPU_MAG_MIX_MAG_ONLY           1                   // just use magnetometer and no gyro yaw
#define  MPU_MAG_MIX_GYRO_AND_MAG       10                  // a good mix value
#define  MPU_MAG_MIX_GYRO_AND_SOME_MAG  50                  // mainly gyros with a bit of mag correction

//  MPU_LPF_RATE is the low pas filter rate and can be between 5 and 188Hz

#define MPU_LPF_RATE   5

void MPU9150::device_setup(){
  //Todo: Read calibration values from EPROM
  Wire.begin();
  MPU.selectDevice(MPUDeviceId);
  //  MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_AND_MAG, MAG_UPDATE_RATE, MPU_LPF_RATE);
  if (!MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_AND_MAG, MAG_UPDATE_RATE, MPU_LPF_RATE)){
	Serial.println(F("log:Trying other MPU9150 address to init;"));
	Serial.print(F("log:IMU Address was :"));
	Serial.print(1);
	MPUDeviceId = !MPUDeviceId;
	Serial.print(F(" but is now:"));
	Serial.print(MPUDeviceId);
	Serial.println(";");
	MPU.selectDevice(MPUDeviceId);
	if (MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_AND_MAG, MAG_UPDATE_RATE, MPU_LPF_RATE)){
		DidInit = true;
		Serial.println(F("log:Init worked the second time;"));
	} else {
		Serial.println(F("log:Failed to init on both addresses;"));
	}
  } else {
	DidInit = true;
	Serial.println(F("log:init on primary addresses;"));
  }                             // start the MPU
  Settings::capability_bitarray |= (1 << COMPASS_CAPABLE);
  Settings::capability_bitarray |= (1 << ORIENTATION_CAPABLE);
  MPU9150ReInit.reset();
}

void MPU9150::device_loop(Command command){
  if (!DidInit){
    if( MPU9150ReInit.elapsed(30000)){
	MPU9150::device_setup();
    }
     return;
  }
  if (command.cmp("ccal")){
   // Compass_Calibrate();
   // The IMU needs both Magnatrometer and Acceleromter to be calibrated. This attempts to do them both at the same time
    calLibRead(MPUDeviceId, &calData);               // pick up existing accel data if there

    calData.accelValid = false;
    calData.accelMinX = 0x7fff;                              // init accel cal data
    calData.accelMaxX = 0x8000;
    calData.accelMinY = 0x7fff;
    calData.accelMaxY = 0x8000;
    calData.accelMinZ = 0x7fff;
    calData.accelMaxZ = 0x8000;

    calData.magValid = false;
    calData.magMinX = 0x7fff;                                // init mag cal data
    calData.magMaxX = 0x8000;
    calData.magMinY = 0x7fff;
    calData.magMaxY = 0x8000;
    calData.magMinZ = 0x7fff;
    calData.magMaxZ = 0x8000;

    MPU.useAccelCal(false);
    //MPU.init(MPU_UPDATE_RATE, 5, 1, MPU_LPF_RATE);

    counter = 359;
    InCallibrationMode = true;
    calibration_timer.reset();
    Serial.println(F("!!!:While the compass counts down from 360 to 0, rotate the ROV slowly in all three axis;"));

  }

  if (InCallibrationMode){
    bool changed = false;

    if(counter>0){
      if (MPU.read()) {                                        // get the latest data
        changed = false;
        if (MPU.m_rawAccel[VEC3_X] < calData.accelMinX) {
          calData.accelMinX = MPU.m_rawAccel[VEC3_X];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_X] > calData.accelMaxX) {
          calData.accelMaxX = MPU.m_rawAccel[VEC3_X];
          changed = true;
        }
        if (MPU.m_rawAccel[VEC3_Y] < calData.accelMinY) {
          calData.accelMinY = MPU.m_rawAccel[VEC3_Y];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_Y] > calData.accelMaxY) {
          calData.accelMaxY = MPU.m_rawAccel[VEC3_Y];
          changed = true;
        }
        if (MPU.m_rawAccel[VEC3_Z] < calData.accelMinZ) {
          calData.accelMinZ = MPU.m_rawAccel[VEC3_Z];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_Z] > calData.accelMaxZ) {
          calData.accelMaxZ = MPU.m_rawAccel[VEC3_Z];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_X] < calData.magMinX) {
          calData.magMinX = MPU.m_rawMag[VEC3_X];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_X] > calData.magMaxX) {
          calData.magMaxX = MPU.m_rawMag[VEC3_X];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_Y] < calData.magMinY) {
          calData.magMinY = MPU.m_rawMag[VEC3_Y];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_Y] > calData.magMaxY) {
          calData.magMaxY = MPU.m_rawMag[VEC3_Y];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_Z] < calData.magMinZ) {
          calData.magMinZ = MPU.m_rawMag[VEC3_Z];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_Z] > calData.magMaxZ) {
          calData.magMaxZ = MPU.m_rawMag[VEC3_Z];
          changed = true;
        }

        if (changed) {
          Serial.print(F("dia:accel.MinX=")); Serial.print(calData.accelMinX); Serial.println(";");
          Serial.print(F("dia:accel.maxX=")); Serial.print(calData.accelMaxX); Serial.println(";");
          Serial.print(F("dia:accel.minY=")); Serial.print(calData.accelMinY); Serial.println(";");
          Serial.print(F("dia:accel.maxY=")); Serial.print(calData.accelMaxY); Serial.println(";");
          Serial.print(F("dia:accel.minZ=")); Serial.print(calData.accelMinZ); Serial.println(";");
          Serial.print(F("dia:accel.maxZ=")); Serial.print(calData.accelMaxZ); Serial.println(";");
          Serial.print(F("dia:mag.minX=")); Serial.print(calData.magMinX); Serial.println(";");
          Serial.print(F("dia:mag.maxX=")); Serial.print(calData.magMaxX); Serial.println(";");
          Serial.print(F("dia:mag.minY=")); Serial.print(calData.magMinY); Serial.println(";");
          Serial.print(F("dia:mag.maxY=")); Serial.print(calData.magMaxY); Serial.println(";");
          Serial.print(F("dia:mag.minZ=")); Serial.print(calData.magMinZ); Serial.println(";");
          Serial.print(F("dia:mag.maxZ=")); Serial.print(calData.magMaxZ); Serial.println(";");
        }
      }
      if (calibration_timer.elapsed (1000)) {
        counter--;
        navdata::HDGD = counter;
        Serial.print(F("hdgd:"));
        Serial.print(navdata::HDGD);
        Serial.print(';');
      }
    }
    if (counter <= 0){
      calData.accelValid = true;
      calData.magValid = true;
      calLibWrite(MPUDeviceId, &calData);
      Serial.println(F("log:Accel cal data saved for device;"));
      InCallibrationMode = false;
    }
    return;  //prevents the normal read and reporting of IMU data
  }
  else if (command.cmp("i2cscan")){
   // scan();
  }
//    MPU.selectDevice(MPUDeviceId);
    MPU.read();
//    {
//        Serial.println(F("log:SwappingIMUAddress;"));
//        MPUDeviceId = !MPUDeviceId;
//        MPU.selectDevice(MPUDeviceId);
//        if(!MPU.read()){
//		Serial.println(F("log:Failed to read IMU on both addresses. Sleeping for 1 minute"));
//		DidInit = false;
//	}
//    }
    navdata::HDGD = MPU.m_fusedEulerPose[VEC3_Z] * RAD_TO_DEGREE;
    //To convert to-180/180 to 0/360
    if (navdata::HDGD < 0) navdata::HDGD+=360;
    navdata::PITC = MPU.m_fusedEulerPose[VEC3_X] * RAD_TO_DEGREE;
    navdata::ROLL = MPU.m_fusedEulerPose[VEC3_Y] * RAD_TO_DEGREE;
    navdata::YAW = MPU.m_fusedEulerPose[VEC3_Z] * RAD_TO_DEGREE;
}
#endif
<commit_msg>Fixed#234; swapped pitch/roll in MPU9150<commit_after>#include "MPU9150.h"
#include "AConfig.h"
#if(HAS_MPU9150)
#include "Device.h"
#include "Settings.h"
#include <Wire.h>
//#include "I2Cdev.h"
#include "MPU9150Lib.h"
#include "CalLib.h"
//#include "dmpKey.h"
//#include "dmpmap.h"
//#include "inv_mpu.h"
//#include "inv_mpu_dmp_motion_driver.h"
#include <EEPROM.h>
#include "Timer.h"

MPU9150Lib MPU;                                              // the MPU object
int MPUDeviceId = 1;
boolean DidInit = false;
boolean InCallibrationMode = false;
Timer MPU9150ReInit;
CALLIB_DATA calData;
Timer calibration_timer;
int counter = 0;
//  MPU_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the sensor data and DMP output

//  MPU_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the sensor data and DMP output

#define MPU_UPDATE_RATE  (20)

//  MAG_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the magnetometer data
//  MAG_UPDATE_RATE should be less than or equal to the MPU_UPDATE_RATE

#define MAG_UPDATE_RATE  (10)

//  MPU_MAG_MIX defines the influence that the magnetometer has on the yaw output.
//  The magnetometer itself is quite noisy so some mixing with the gyro yaw can help
//  significantly. Some example values are defined below:

#define  MPU_MAG_MIX_GYRO_ONLY          0                   // just use gyro yaw
#define  MPU_MAG_MIX_MAG_ONLY           1                   // just use magnetometer and no gyro yaw
#define  MPU_MAG_MIX_GYRO_AND_MAG       10                  // a good mix value
#define  MPU_MAG_MIX_GYRO_AND_SOME_MAG  50                  // mainly gyros with a bit of mag correction

//  MPU_LPF_RATE is the low pas filter rate and can be between 5 and 188Hz

#define MPU_LPF_RATE   5

void MPU9150::device_setup(){
  //Todo: Read calibration values from EPROM
  Wire.begin();
  MPU.selectDevice(MPUDeviceId);
  //  MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_AND_MAG, MAG_UPDATE_RATE, MPU_LPF_RATE);
  if (!MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_AND_MAG, MAG_UPDATE_RATE, MPU_LPF_RATE)){
	Serial.println(F("log:Trying other MPU9150 address to init;"));
	Serial.print(F("log:IMU Address was :"));
	Serial.print(1);
	MPUDeviceId = !MPUDeviceId;
	Serial.print(F(" but is now:"));
	Serial.print(MPUDeviceId);
	Serial.println(";");
	MPU.selectDevice(MPUDeviceId);
	if (MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_AND_MAG, MAG_UPDATE_RATE, MPU_LPF_RATE)){
		DidInit = true;
		Serial.println(F("log:Init worked the second time;"));
	} else {
		Serial.println(F("log:Failed to init on both addresses;"));
	}
  } else {
	DidInit = true;
	Serial.println(F("log:init on primary addresses;"));
  }                             // start the MPU
  Settings::capability_bitarray |= (1 << COMPASS_CAPABLE);
  Settings::capability_bitarray |= (1 << ORIENTATION_CAPABLE);
  MPU9150ReInit.reset();
}

void MPU9150::device_loop(Command command){
  if (!DidInit){
    if( MPU9150ReInit.elapsed(30000)){
	MPU9150::device_setup();
    }
     return;
  }
  if (command.cmp("ccal")){
   // Compass_Calibrate();
   // The IMU needs both Magnatrometer and Acceleromter to be calibrated. This attempts to do them both at the same time
    calLibRead(MPUDeviceId, &calData);               // pick up existing accel data if there

    calData.accelValid = false;
    calData.accelMinX = 0x7fff;                              // init accel cal data
    calData.accelMaxX = 0x8000;
    calData.accelMinY = 0x7fff;
    calData.accelMaxY = 0x8000;
    calData.accelMinZ = 0x7fff;
    calData.accelMaxZ = 0x8000;

    calData.magValid = false;
    calData.magMinX = 0x7fff;                                // init mag cal data
    calData.magMaxX = 0x8000;
    calData.magMinY = 0x7fff;
    calData.magMaxY = 0x8000;
    calData.magMinZ = 0x7fff;
    calData.magMaxZ = 0x8000;

    MPU.useAccelCal(false);
    //MPU.init(MPU_UPDATE_RATE, 5, 1, MPU_LPF_RATE);

    counter = 359;
    InCallibrationMode = true;
    calibration_timer.reset();
    Serial.println(F("!!!:While the compass counts down from 360 to 0, rotate the ROV slowly in all three axis;"));

  }

  if (InCallibrationMode){
    bool changed = false;

    if(counter>0){
      if (MPU.read()) {                                        // get the latest data
        changed = false;
        if (MPU.m_rawAccel[VEC3_X] < calData.accelMinX) {
          calData.accelMinX = MPU.m_rawAccel[VEC3_X];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_X] > calData.accelMaxX) {
          calData.accelMaxX = MPU.m_rawAccel[VEC3_X];
          changed = true;
        }
        if (MPU.m_rawAccel[VEC3_Y] < calData.accelMinY) {
          calData.accelMinY = MPU.m_rawAccel[VEC3_Y];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_Y] > calData.accelMaxY) {
          calData.accelMaxY = MPU.m_rawAccel[VEC3_Y];
          changed = true;
        }
        if (MPU.m_rawAccel[VEC3_Z] < calData.accelMinZ) {
          calData.accelMinZ = MPU.m_rawAccel[VEC3_Z];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_Z] > calData.accelMaxZ) {
          calData.accelMaxZ = MPU.m_rawAccel[VEC3_Z];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_X] < calData.magMinX) {
          calData.magMinX = MPU.m_rawMag[VEC3_X];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_X] > calData.magMaxX) {
          calData.magMaxX = MPU.m_rawMag[VEC3_X];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_Y] < calData.magMinY) {
          calData.magMinY = MPU.m_rawMag[VEC3_Y];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_Y] > calData.magMaxY) {
          calData.magMaxY = MPU.m_rawMag[VEC3_Y];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_Z] < calData.magMinZ) {
          calData.magMinZ = MPU.m_rawMag[VEC3_Z];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_Z] > calData.magMaxZ) {
          calData.magMaxZ = MPU.m_rawMag[VEC3_Z];
          changed = true;
        }

        if (changed) {
          Serial.print(F("dia:accel.MinX=")); Serial.print(calData.accelMinX); Serial.println(";");
          Serial.print(F("dia:accel.maxX=")); Serial.print(calData.accelMaxX); Serial.println(";");
          Serial.print(F("dia:accel.minY=")); Serial.print(calData.accelMinY); Serial.println(";");
          Serial.print(F("dia:accel.maxY=")); Serial.print(calData.accelMaxY); Serial.println(";");
          Serial.print(F("dia:accel.minZ=")); Serial.print(calData.accelMinZ); Serial.println(";");
          Serial.print(F("dia:accel.maxZ=")); Serial.print(calData.accelMaxZ); Serial.println(";");
          Serial.print(F("dia:mag.minX=")); Serial.print(calData.magMinX); Serial.println(";");
          Serial.print(F("dia:mag.maxX=")); Serial.print(calData.magMaxX); Serial.println(";");
          Serial.print(F("dia:mag.minY=")); Serial.print(calData.magMinY); Serial.println(";");
          Serial.print(F("dia:mag.maxY=")); Serial.print(calData.magMaxY); Serial.println(";");
          Serial.print(F("dia:mag.minZ=")); Serial.print(calData.magMinZ); Serial.println(";");
          Serial.print(F("dia:mag.maxZ=")); Serial.print(calData.magMaxZ); Serial.println(";");
        }
      }
      if (calibration_timer.elapsed (1000)) {
        counter--;
        navdata::HDGD = counter;
        Serial.print(F("hdgd:"));
        Serial.print(navdata::HDGD);
        Serial.print(';');
      }
    }
    if (counter <= 0){
      calData.accelValid = true;
      calData.magValid = true;
      calLibWrite(MPUDeviceId, &calData);
      Serial.println(F("log:Accel cal data saved for device;"));
      InCallibrationMode = false;
    }
    return;  //prevents the normal read and reporting of IMU data
  }
  else if (command.cmp("i2cscan")){
   // scan();
  }
//    MPU.selectDevice(MPUDeviceId);
    MPU.read();
//    {
//        Serial.println(F("log:SwappingIMUAddress;"));
//        MPUDeviceId = !MPUDeviceId;
//        MPU.selectDevice(MPUDeviceId);
//        if(!MPU.read()){
//		Serial.println(F("log:Failed to read IMU on both addresses. Sleeping for 1 minute"));
//		DidInit = false;
//	}
//    }
    navdata::HDGD = MPU.m_fusedEulerPose[VEC3_Z] * RAD_TO_DEGREE;
    //To convert to-180/180 to 0/360
    if (navdata::HDGD < 0) navdata::HDGD+=360;
    navdata::PITC = MPU.m_fusedEulerPose[VEC3_Y] * RAD_TO_DEGREE;
    navdata::ROLL = MPU.m_fusedEulerPose[VEC3_X] * RAD_TO_DEGREE;
    navdata::YAW = MPU.m_fusedEulerPose[VEC3_Z] * RAD_TO_DEGREE;
}
#endif
<|endoftext|>


<commit_before>// Copyright (C) 2011, James Webber.
// Distributed under a 3-clause BSD license.  See COPYING.

#ifndef PIPELINE_OUTPUT_STAGE_HPP_zia9vdqt
#define PIPELINE_OUTPUT_STAGE_HPP_zia9vdqt

#include "simple_stages.hpp"

namespace pipeline {

  class outputter {
    virtual void write(packet) = 0;
  };

  class local_outputter  : outputter {
    local_pipe p_;
    void write(packet);
  };

  class thread_outputter : outputter {
    thread_pipe p_;
    void write(packet);
  };

  /*!
   * \ingroup grp_pipeline
   * Specialised outputting stage.
   */
  class output_stage : public observer_stage {
    void output(pkt, outputter) = 0;
    void reconfigure(pkt) = 0;

    // A pipe to the input thread.  This can be local or threaded.
    outputter input_events_;

    void observe(packet *pkt) {
      // fullfills the 'reconfigure' event.  Somebody has to check it.  If we do
      // it here then it avoids type checking of all stages.  Additionally, it
      // means we can later have a reconfgiure event which a configuration chaning
      // stage could deal with.

      // TODO:
      //   Perhaps better in a hypothetical output seqeuence.

      if (pkt.configuration != last_configuration) {
        this->reconfigure(pkt);
      }

      // hmmm...
      this->real_observe(pkt);
    }
  };

}

#endif
<commit_msg>Remove some simple compile errors from the output stage.<commit_after>// Copyright (C) 2011, James Webber.
// Distributed under a 3-clause BSD license.  See COPYING.

#ifndef PIPELINE_OUTPUT_STAGE_HPP_zia9vdqt
#define PIPELINE_OUTPUT_STAGE_HPP_zia9vdqt

#include "simple_stages.hpp"

namespace pipeline {
  class packet;

  //! \ingroup grp_pipeline
  //! Polymoprphic outputtter which is intended to abstract the thread and local
  //! pipes.
  class outputter {
    public:
    virtual void write(packet *) = 0;
    virtual ~outputter() {}
  };

  //! \ingroup grp_pipeline
  class local_outputter : public outputter {
    public:
    void write(packet*);
  };

  //! \ingroup grp_pipeline
  class thread_outputter : public outputter {
    public:
    void write(packet *);
  };

  /*!
   * \ingroup grp_pipeline
   * Specialised outputting stage.
   */
  class output_stage : public observer_stage {
    public:
    virtual void output(packet *, outputter *) = 0;
    virtual void reconfigure(packet *) = 0;

    outputter *input_events_;

    // Fullfills the 'reconfigure' event.  Somebody has to check it.  If we do
    // it here then it avoids type checking of all stages.  Additionally, it
    // means we can later have a reconfgiure event which a configuration chaning
    // stage could deal with.
    void observe(packet *pkt) {
      // TODO:
      //   Perhaps better in a hypothetical output seqeuence.
      // if (pkt.configuration != last_configuration) {
      //   this->reconfigure(pkt);
      // }

      // Prolly this should pass a specialised event interface.
      this->output(pkt, input_events_);
    }
  };

}

#endif
<|endoftext|>


<commit_before>#include "network_world_client.h"
#include "network.h"
#include "level/scene.h"
#include "globals.h"
#include "level/blockobject.h"
#include "util/funcs.h"
#include "object/player.h"
#include "factory/object_factory.h"
#include <pthread.h>
#include <string.h>

#include "object/character.h"
#include "object/cat.h"
#include "object/item.h"

static void * handleMessages( void * arg ){
	NetworkWorldClient * world = (NetworkWorldClient *) arg;
	NLsocket socket = world->getServer();
	// pthread_mutex_t * lock = world->getLock();
	unsigned int received = 0;

	try{
		while ( world->isRunning() ){
			received += 1;
			Global::debug( 1 ) << "Receiving message " << received << endl;
			Network::Message m( socket );
			// pthread_mutex_lock( lock );
			world->addIncomingMessage( m );
			Global::debug( 2 ) << "Received path '" << m.path << "'" << endl;
			// pthread_mutex_unlock( lock );
		}
	} catch ( const Network::NetworkException & n ){
		Global::debug( 0 ) << "Network exception: " << n.getMessage() << endl;
	}

	Global::debug( 0 ) << "Client input stopped" << endl;

	return NULL;
}

NetworkWorldClient::NetworkWorldClient( Network::Socket server, const std::vector< Object * > & players, const string & path, unsigned int id, int screen_size ) throw ( LoadException ):
World( players, path, screen_size ),
server( server ),
world_finished( false ),
id( id ),
running( true ){
	objects.clear();
	pthread_mutex_init( &message_mutex, NULL );
	pthread_mutex_init( &running_mutex, NULL );
	pthread_create( &message_thread, NULL, handleMessages, this );
}

NetworkWorldClient::~NetworkWorldClient(){
	Global::debug( 1 ) << "Destroy client world" << endl;
	stopRunning();
	pthread_join( message_thread, NULL );
}

bool NetworkWorldClient::isRunning(){
	pthread_mutex_lock( &running_mutex );
	bool b = running;
	pthread_mutex_unlock( &running_mutex );
	return b;
}

void NetworkWorldClient::stopRunning(){
	pthread_mutex_lock( &running_mutex );
	running = false;
	pthread_mutex_unlock( &running_mutex );
}

void NetworkWorldClient::addIncomingMessage( const Network::Message & message ){
	pthread_mutex_lock( &message_mutex );
	incoming.push_back( message );
	pthread_mutex_unlock( &message_mutex );
}

vector< Network::Message > NetworkWorldClient::getIncomingMessages(){
	vector< Network::Message > m;
	pthread_mutex_lock( &message_mutex );
	m = incoming;
	incoming.clear();
	pthread_mutex_unlock( &message_mutex );
	return m;
}

bool NetworkWorldClient::uniqueObject( unsigned int id ){
	for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); it++ ){
		Object * o = *it;
		if ( o->getId() == id ){
			return false;
		}
	}
	return true;
}

void NetworkWorldClient::handleCreateCharacter( Network::Message & message ){
	int alliance;
	int id;
	int map;
	string path = Util::getDataPath() + "/" + message.path;
	message >> alliance >> id >> map;
	if ( uniqueObject( id ) ){
		if ( (unsigned int) id == this->id ){
			Player * p = (Player *) players[ 0 ].player;
			p->deathReset();
			addObject( p );
		} else {
			BlockObject block;
			block.setType( ObjectFactory::OBJECT_NETWORK_CHARACTER );
			block.setMap( map );
			block.setPath( path );
			Character * character = (Character *) ObjectFactory::createObject( &block );
			if ( character == NULL ){
				Global::debug( 0 ) << "Could not create character!" << endl;
				return;
			}
			Global::debug( 1 ) << "Create '" << path << "' with id " << id << " alliance " << alliance << endl;
			character->setId( id );
			character->setAlliance( alliance );
			/* TODO: should these values be hard-coded? */
			character->setX( 200 );
			character->setY( 0 );
			character->setZ( 150 );
			addObject( character );
		}
	} else {
		Global::debug( 1 ) << id << " is not unique" << endl;
	}
}

void NetworkWorldClient::handleCreateCat( Network::Message & message ){
	int id;
	message >> id;
	if ( uniqueObject( id ) ){
		string path = Util::getDataPath() + "/" + message.path;
		BlockObject block;
		block.setType( ObjectFactory::OBJECT_CAT );
		block.setPath( path );
		/* TODO: should these values be hard-coded? */
		block.setCoords( 200, 150 );
		Cat * cat = (Cat *) ObjectFactory::createObject( &block );
		if ( cat == NULL ){
			Global::debug( 0 ) << "Could not create cat" << endl;
			return;
		}

		cat->setY( 0 );
		cat->setId( (unsigned int) -1 );
		addObject( cat );
	}
}

const bool NetworkWorldClient::finished() const {
	return world_finished;
}

Object * NetworkWorldClient::removeObject( unsigned int id ){
	for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); ){
		Object * o = *it;
		if ( o->getId() == id ){
			it = objects.erase( it );
			return o;
		} else {
			it++;
		}
	}
	return NULL;
}

void NetworkWorldClient::handleCreateItem( Network::Message & message ){
	int id;
	message >> id;
	if ( uniqueObject( id ) ){
		int x, z;
		int value;
		message >> x >> z >> value;
		string path = Util::getDataPath() + "/" + message.path;
		BlockObject block;
		block.setType( ObjectFactory::OBJECT_ITEM );
		block.setPath( path );
		/* TODO: dont hard-code this */
		block.setStimulationType( "health" );
		block.setStimulationValue( value );
		block.setCoords( x, z );
		Item * item = (Item *) ObjectFactory::createObject( &block );
		if ( item == NULL ){
			Global::debug( 0 ) << "Could not create item" << endl;
			return;
		}

		item->setY( 0 );
		item->setId( id );
		addObject( item );
	}
}

void NetworkWorldClient::handleCreateBang( Network::Message & message ){
	int x, y, z;
	message >> x >> y >> z;
	Object * addx = bang->copy();
	addx->setX( x );
	addx->setY( 0 );
	addx->setZ( y+addx->getHeight()/2 );
	addx->setHealth( 1 );
	addx->setId( (unsigned int) -1 );
	addObject( addx );
}

void NetworkWorldClient::handleMessage( Network::Message & message ){
	if ( message.id == 0 ){
		int type;
		message >> type;
		switch ( type ){
			case CREATE_CHARACTER : {
				handleCreateCharacter( message );
				break;
			}
			case CREATE_CAT : {
				handleCreateCat( message );
				break;
			}
			case CREATE_BANG : {
				handleCreateBang( message );
				break;
			}
			case CREATE_ITEM : {
				handleCreateItem( message );
				break;
			}
			case NEXT_BLOCK : {
				int block;
				message >> block;
				scene->advanceBlocks( block );
				break;
			}
			case DELETE_OBJ : {
				int id;
				message >> id;
				Object * o = removeObject( id );
				if ( o != NULL ){
					delete o;
				}
				break;
			}
			case REMOVE : {
				int id;
				message >> id;
				removeObject( id );
				break;
			}
			case FINISH : {

				Global::debug( 1 ) << "Received finish message" << endl;
				world_finished = true;
				break;
			}
			case NOTHING : {
				Global::debug( 0 ) << "Invalid message. Data dump" << endl;
				for ( int i = 0; i < Network::DATA_SIZE; i++ ){
					Global::debug( 0 ) << (int) message.data[ i ] << " ";
				}
				Global::debug( 0 ) << endl;
				break;
			}
		}
	} else {
		for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); it++ ){
			Object * o = *it;
			if ( o->getId() == message.id ){
				o->interpretMessage( message );
			}
		}
	}
}

void NetworkWorldClient::addMessage( Network::Message m, Network::Socket from ){
	if ( m.id == id ){
		outgoing.push_back( m );
	}
}

void NetworkWorldClient::doScene( int min_x, int max_x ){
	vector< Object * > objs;
	scene->act( min_x, max_x, &objs );
	for ( vector< Object * >::iterator it = objs.begin(); it != objs.end(); it++ ){
		delete *it;
	}
}

void NetworkWorldClient::sendMessage( const Network::Message & message, NLsocket socket ){
	message.send( socket );
}

void NetworkWorldClient::act(){

	if ( quake_time > 0 ){
		quake_time--;
	}

	vector< Object * > added_effects;
	for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); it++ ){
		Object * o = *it;
		o->act( &objects, this, &added_effects );
		if ( o->getZ() < getMinimumZ() ){
			o->setZ( getMinimumZ() );
		}
		if ( o->getZ() > getMaximumZ() ){
			o->setZ( getMaximumZ() );
		}
	}

	double lowest = 9999999;
	for ( vector< PlayerTracker >::iterator it = players.begin(); it != players.end(); it++ ){
		Object * player = it->player;
		double mx = player->getX() - screen_size / 2;
		if ( it->min_x < mx ){
			it->min_x++;
		}

		if ( it->min_x + screen_size >= scene->getLimit() ){
			it->min_x = scene->getLimit() - screen_size;
		}

		if ( it->min_x < lowest ){
			lowest = it->min_x;
		}

		/*
		if ( player->getX() < it->min_x ){
			player->setX( it->min_x );
		}
		*/
		if ( player->getX() < 0 ){
			player->setX( 0 );
		}

		if ( player->getX() > scene->getLimit() ){
			player->setX( scene->getLimit() );
		}
		if ( player->getZ() < getMinimumZ() ){
			player->setZ( getMinimumZ() );
		}
		if ( player->getZ() > getMaximumZ() ){
			player->setZ( getMaximumZ() );
		}
	}

	doScene( 0, 0 );

	vector< Network::Message > messages = getIncomingMessages();
	for ( vector< Network::Message >::iterator it = messages.begin(); it != messages.end(); it++ ){
		handleMessage( *it );
	}

	for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); ){
		if ( (*it)->getHealth() <= 0 ){
			(*it)->died( added_effects );
			if ( ! isPlayer( *it ) ){
				delete *it;
			}
			it = objects.erase( it );
		} else ++it;
	}

	for ( vector< Network::Message >::iterator it = outgoing.begin(); it != outgoing.end(); it++ ){
		Network::Message & m = *it;
		sendMessage( m, getServer() );
	}
	outgoing.clear();

	for ( vector< Object * >::iterator it = added_effects.begin(); it != added_effects.end(); ){
		Object * o = *it;
		o->setId( (unsigned int) -1 );
		it++;
	}
	objects.insert( objects.end(), added_effects.begin(), added_effects.end() );
}
<commit_msg>fixes for windows<commit_after>#include "util/bitmap.h"
#include "network_world_client.h"
#include "network.h"
#include "level/scene.h"
#include "globals.h"
#include "level/blockobject.h"
#include "util/funcs.h"
#include "object/player.h"
#include "factory/object_factory.h"
#include <pthread.h>
#include <string.h>

#include "object/character.h"
#include "object/cat.h"
#include "object/item.h"

static void * handleMessages( void * arg ){
	NetworkWorldClient * world = (NetworkWorldClient *) arg;
	NLsocket socket = world->getServer();
	// pthread_mutex_t * lock = world->getLock();
	unsigned int received = 0;

	try{
		while ( world->isRunning() ){
			received += 1;
			Global::debug( 1 ) << "Receiving message " << received << endl;
			Network::Message m( socket );
			// pthread_mutex_lock( lock );
			world->addIncomingMessage( m );
			Global::debug( 2 ) << "Received path '" << m.path << "'" << endl;
			// pthread_mutex_unlock( lock );
		}
	} catch ( const Network::NetworkException & n ){
		Global::debug( 0 ) << "Network exception: " << n.getMessage() << endl;
	}

	Global::debug( 0 ) << "Client input stopped" << endl;

	return NULL;
}

NetworkWorldClient::NetworkWorldClient( Network::Socket server, const std::vector< Object * > & players, const string & path, unsigned int id, int screen_size ) throw ( LoadException ):
World( players, path, screen_size ),
server( server ),
world_finished( false ),
id( id ),
running( true ){
	objects.clear();
	pthread_mutex_init( &message_mutex, NULL );
	pthread_mutex_init( &running_mutex, NULL );
	pthread_create( &message_thread, NULL, handleMessages, this );
}

NetworkWorldClient::~NetworkWorldClient(){
	Global::debug( 1 ) << "Destroy client world" << endl;
	stopRunning();
	pthread_join( message_thread, NULL );
}

bool NetworkWorldClient::isRunning(){
	pthread_mutex_lock( &running_mutex );
	bool b = running;
	pthread_mutex_unlock( &running_mutex );
	return b;
}

void NetworkWorldClient::stopRunning(){
	pthread_mutex_lock( &running_mutex );
	running = false;
	pthread_mutex_unlock( &running_mutex );
}

void NetworkWorldClient::addIncomingMessage( const Network::Message & message ){
	pthread_mutex_lock( &message_mutex );
	incoming.push_back( message );
	pthread_mutex_unlock( &message_mutex );
}

vector< Network::Message > NetworkWorldClient::getIncomingMessages(){
	vector< Network::Message > m;
	pthread_mutex_lock( &message_mutex );
	m = incoming;
	incoming.clear();
	pthread_mutex_unlock( &message_mutex );
	return m;
}

bool NetworkWorldClient::uniqueObject( unsigned int id ){
	for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); it++ ){
		Object * o = *it;
		if ( o->getId() == id ){
			return false;
		}
	}
	return true;
}

void NetworkWorldClient::handleCreateCharacter( Network::Message & message ){
	int alliance;
	int id;
	int map;
	string path = Util::getDataPath() + "/" + message.path;
	message >> alliance >> id >> map;
	if ( uniqueObject( id ) ){
		if ( (unsigned int) id == this->id ){
			Player * p = (Player *) players[ 0 ].player;
			p->deathReset();
			addObject( p );
		} else {
			BlockObject block;
			block.setType( ObjectFactory::OBJECT_NETWORK_CHARACTER );
			block.setMap( map );
			block.setPath( path );
			Character * character = (Character *) ObjectFactory::createObject( &block );
			if ( character == NULL ){
				Global::debug( 0 ) << "Could not create character!" << endl;
				return;
			}
			Global::debug( 1 ) << "Create '" << path << "' with id " << id << " alliance " << alliance << endl;
			character->setId( id );
			character->setAlliance( alliance );
			/* TODO: should these values be hard-coded? */
			character->setX( 200 );
			character->setY( 0 );
			character->setZ( 150 );
			addObject( character );
		}
	} else {
		Global::debug( 1 ) << id << " is not unique" << endl;
	}
}

void NetworkWorldClient::handleCreateCat( Network::Message & message ){
	int id;
	message >> id;
	if ( uniqueObject( id ) ){
		string path = Util::getDataPath() + "/" + message.path;
		BlockObject block;
		block.setType( ObjectFactory::OBJECT_CAT );
		block.setPath( path );
		/* TODO: should these values be hard-coded? */
		block.setCoords( 200, 150 );
		Cat * cat = (Cat *) ObjectFactory::createObject( &block );
		if ( cat == NULL ){
			Global::debug( 0 ) << "Could not create cat" << endl;
			return;
		}

		cat->setY( 0 );
		cat->setId( (unsigned int) -1 );
		addObject( cat );
	}
}

const bool NetworkWorldClient::finished() const {
	return world_finished;
}

Object * NetworkWorldClient::removeObject( unsigned int id ){
	for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); ){
		Object * o = *it;
		if ( o->getId() == id ){
			it = objects.erase( it );
			return o;
		} else {
			it++;
		}
	}
	return NULL;
}

void NetworkWorldClient::handleCreateItem( Network::Message & message ){
	int id;
	message >> id;
	if ( uniqueObject( id ) ){
		int x, z;
		int value;
		message >> x >> z >> value;
		string path = Util::getDataPath() + "/" + message.path;
		BlockObject block;
		block.setType( ObjectFactory::OBJECT_ITEM );
		block.setPath( path );
		/* TODO: dont hard-code this */
		block.setStimulationType( "health" );
		block.setStimulationValue( value );
		block.setCoords( x, z );
		Item * item = (Item *) ObjectFactory::createObject( &block );
		if ( item == NULL ){
			Global::debug( 0 ) << "Could not create item" << endl;
			return;
		}

		item->setY( 0 );
		item->setId( id );
		addObject( item );
	}
}

void NetworkWorldClient::handleCreateBang( Network::Message & message ){
	int x, y, z;
	message >> x >> y >> z;
	Object * addx = bang->copy();
	addx->setX( x );
	addx->setY( 0 );
	addx->setZ( y+addx->getHeight()/2 );
	addx->setHealth( 1 );
	addx->setId( (unsigned int) -1 );
	addObject( addx );
}

void NetworkWorldClient::handleMessage( Network::Message & message ){
	if ( message.id == 0 ){
		int type;
		message >> type;
		switch ( type ){
			case CREATE_CHARACTER : {
				handleCreateCharacter( message );
				break;
			}
			case CREATE_CAT : {
				handleCreateCat( message );
				break;
			}
			case CREATE_BANG : {
				handleCreateBang( message );
				break;
			}
			case CREATE_ITEM : {
				handleCreateItem( message );
				break;
			}
			case NEXT_BLOCK : {
				int block;
				message >> block;
				scene->advanceBlocks( block );
				break;
			}
			case DELETE_OBJ : {
				int id;
				message >> id;
				Object * o = removeObject( id );
				if ( o != NULL ){
					delete o;
				}
				break;
			}
			case REMOVE : {
				int id;
				message >> id;
				removeObject( id );
				break;
			}
			case FINISH : {

				Global::debug( 1 ) << "Received finish message" << endl;
				world_finished = true;
				break;
			}
			case NOTHING : {
				Global::debug( 0 ) << "Invalid message. Data dump" << endl;
				for ( int i = 0; i < Network::DATA_SIZE; i++ ){
					Global::debug( 0 ) << (int) message.data[ i ] << " ";
				}
				Global::debug( 0 ) << endl;
				break;
			}
		}
	} else {
		for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); it++ ){
			Object * o = *it;
			if ( o->getId() == message.id ){
				o->interpretMessage( message );
			}
		}
	}
}

void NetworkWorldClient::addMessage( Network::Message m, Network::Socket from ){
	if ( m.id == id ){
		outgoing.push_back( m );
	}
}

void NetworkWorldClient::doScene( int min_x, int max_x ){
	vector< Object * > objs;
	scene->act( min_x, max_x, &objs );
	for ( vector< Object * >::iterator it = objs.begin(); it != objs.end(); it++ ){
		delete *it;
	}
}

void NetworkWorldClient::sendMessage( const Network::Message & message, NLsocket socket ){
	message.send( socket );
}

void NetworkWorldClient::act(){

	if ( quake_time > 0 ){
		quake_time--;
	}

	vector< Object * > added_effects;
	for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); it++ ){
		Object * o = *it;
		o->act( &objects, this, &added_effects );
		if ( o->getZ() < getMinimumZ() ){
			o->setZ( getMinimumZ() );
		}
		if ( o->getZ() > getMaximumZ() ){
			o->setZ( getMaximumZ() );
		}
	}

	double lowest = 9999999;
	for ( vector< PlayerTracker >::iterator it = players.begin(); it != players.end(); it++ ){
		Object * player = it->player;
		double mx = player->getX() - screen_size / 2;
		if ( it->min_x < mx ){
			it->min_x++;
		}

		if ( it->min_x + screen_size >= scene->getLimit() ){
			it->min_x = scene->getLimit() - screen_size;
		}

		if ( it->min_x < lowest ){
			lowest = it->min_x;
		}

		/*
		if ( player->getX() < it->min_x ){
			player->setX( it->min_x );
		}
		*/
		if ( player->getX() < 0 ){
			player->setX( 0 );
		}

		if ( player->getX() > scene->getLimit() ){
			player->setX( scene->getLimit() );
		}
		if ( player->getZ() < getMinimumZ() ){
			player->setZ( getMinimumZ() );
		}
		if ( player->getZ() > getMaximumZ() ){
			player->setZ( getMaximumZ() );
		}
	}

	doScene( 0, 0 );

	vector< Network::Message > messages = getIncomingMessages();
	for ( vector< Network::Message >::iterator it = messages.begin(); it != messages.end(); it++ ){
		handleMessage( *it );
	}

	for ( vector< Object * >::iterator it = objects.begin(); it != objects.end(); ){
		if ( (*it)->getHealth() <= 0 ){
			(*it)->died( added_effects );
			if ( ! isPlayer( *it ) ){
				delete *it;
			}
			it = objects.erase( it );
		} else ++it;
	}

	for ( vector< Network::Message >::iterator it = outgoing.begin(); it != outgoing.end(); it++ ){
		Network::Message & m = *it;
		sendMessage( m, getServer() );
	}
	outgoing.clear();

	for ( vector< Object * >::iterator it = added_effects.begin(); it != added_effects.end(); ){
		Object * o = *it;
		o->setId( (unsigned int) -1 );
		it++;
	}
	objects.insert( objects.end(), added_effects.begin(), added_effects.end() );
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 - 2021 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <memory>

#include <QSharedPointer>
#include <qnamespace.h>

#include <ox/claw/claw.hpp>
#include <ox/fs/fs.hpp>
#include <ox/mc/mc.hpp>
#include <ox/model/descwrite.hpp>
#include <ox/std/std.hpp>

#include "nostalgiastudio_export.h"

namespace nostalgia::studio {

enum class ProjectEvent {
	FileAdded,
	// FileRecognized is triggered for all matching files upon a new
	// subscription to a section of the project and upon the addition of a file.
	FileRecognized,
	FileDeleted,
	FileUpdated,
};

[[nodiscard]] QString filePathToName(QString path, QString prefix, QString suffix);

class NOSTALGIASTUDIO_EXPORT Project: public QObject {
	Q_OBJECT

	private:
		QString m_path = "";
		mutable std::unique_ptr<ox::FileSystem> m_fs;

	public:
		explicit Project(QString path);

		~Project() override;

		void create();

		ox::FileSystem *romFs();

		void mkdir(QString path) const;

		/**
		 * Writes a MetalClaw object to the project at the given path.
		 */
		template<typename T>
		void writeObj(QString path, T *obj) const;

		template<typename T>
		std::unique_ptr<T> loadObj(QString path) const;

		ox::FileStat stat(QString path) const;

		bool exists(QString path) const;

		void subscribe(ProjectEvent e, QObject *tgt, const char *slot) const;

		template<typename Functor>
		void subscribe(ProjectEvent e, QObject *tgt, Functor &&slot) const;

	private:
		void writeBuff(QString path, uint8_t *buff, size_t buffLen) const;

		ox::Buffer loadBuff(QString path) const;

		void lsProcDir(QStringList *paths, QString path) const;

		QStringList listFiles(QString path = "") const;

	signals:
		void fileEvent(ProjectEvent, QString path) const;
		void fileAdded(QString) const;
		// FileRecognized is triggered for all matching files upon a new
		// subscription to a section of the project and upon the addition of a
		// file.
		void fileRecognized(QString) const;
		void fileDeleted(QString) const;
		void fileUpdated(QString) const;

};

template<typename T>
void Project::writeObj(QString path, T *obj) const {
	// write MetalClaw
	oxRequireMT(buff, ox::writeClaw(obj, ox::ClawFormat::Metal));
	// write to FS
	writeBuff(path, ox::bit_cast<uint8_t*>(buff.data()), buff.size());

	// write type descriptor
	const auto type = ox::buildTypeDef(obj);
	oxRequireMT(typeOut, ox::writeClaw(type.value, ox::ClawFormat::Organic));
	// replace garbage last character with new line
	typeOut.back().value = '\n';
	// write to FS
	QString descPath = "/.nostalgia/type_descriptors/";
	const auto typePath = descPath + type.value->typeName.c_str();
	mkdir(descPath);
	writeBuff(typePath, ox::bit_cast<uint8_t*>(typeOut.data()), typeOut.size());
	emit fileUpdated(path);
}

template<typename T>
std::unique_ptr<T> Project::loadObj(QString path) const {
	auto obj = std::make_unique<T>();
	auto buff = loadBuff(path);
	oxThrowError(ox::readClaw<T>(buff.data(), buff.size(), obj.get()));
	return std::move(obj);
}

template<typename Functor>
void Project::subscribe(ProjectEvent e, QObject *tgt, Functor &&slot) const {
	switch (e) {
		case ProjectEvent::FileAdded:
			connect(this, &Project::fileAdded, tgt, (slot));
			break;
		case ProjectEvent::FileRecognized:
		{
			for (auto f : listFiles()) {
				slot(f);
			}
			connect(this, &Project::fileRecognized, tgt, (slot));
			break;
		}
		case ProjectEvent::FileDeleted:
			connect(this, &Project::fileDeleted, tgt, (slot));
			break;
		case ProjectEvent::FileUpdated:
			connect(this, &Project::fileUpdated, tgt, (slot));
			break;
	}
}

}
<commit_msg>[nostalgia/studio] Fix copy pessimization<commit_after>/*
 * Copyright 2016 - 2021 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <memory>

#include <QSharedPointer>
#include <qnamespace.h>

#include <ox/claw/claw.hpp>
#include <ox/fs/fs.hpp>
#include <ox/mc/mc.hpp>
#include <ox/model/descwrite.hpp>
#include <ox/std/std.hpp>

#include "nostalgiastudio_export.h"

namespace nostalgia::studio {

enum class ProjectEvent {
	FileAdded,
	// FileRecognized is triggered for all matching files upon a new
	// subscription to a section of the project and upon the addition of a file.
	FileRecognized,
	FileDeleted,
	FileUpdated,
};

[[nodiscard]] QString filePathToName(QString path, QString prefix, QString suffix);

class NOSTALGIASTUDIO_EXPORT Project: public QObject {
	Q_OBJECT

	private:
		QString m_path = "";
		mutable std::unique_ptr<ox::FileSystem> m_fs;

	public:
		explicit Project(QString path);

		~Project() override;

		void create();

		ox::FileSystem *romFs();

		void mkdir(QString path) const;

		/**
		 * Writes a MetalClaw object to the project at the given path.
		 */
		template<typename T>
		void writeObj(QString path, T *obj) const;

		template<typename T>
		std::unique_ptr<T> loadObj(QString path) const;

		ox::FileStat stat(QString path) const;

		bool exists(QString path) const;

		void subscribe(ProjectEvent e, QObject *tgt, const char *slot) const;

		template<typename Functor>
		void subscribe(ProjectEvent e, QObject *tgt, Functor &&slot) const;

	private:
		void writeBuff(QString path, uint8_t *buff, size_t buffLen) const;

		ox::Buffer loadBuff(QString path) const;

		void lsProcDir(QStringList *paths, QString path) const;

		QStringList listFiles(QString path = "") const;

	signals:
		void fileEvent(ProjectEvent, QString path) const;
		void fileAdded(QString) const;
		// FileRecognized is triggered for all matching files upon a new
		// subscription to a section of the project and upon the addition of a
		// file.
		void fileRecognized(QString) const;
		void fileDeleted(QString) const;
		void fileUpdated(QString) const;

};

template<typename T>
void Project::writeObj(QString path, T *obj) const {
	// write MetalClaw
	oxRequireMT(buff, ox::writeClaw(obj, ox::ClawFormat::Metal));
	// write to FS
	writeBuff(path, ox::bit_cast<uint8_t*>(buff.data()), buff.size());

	// write type descriptor
	const auto type = ox::buildTypeDef(obj);
	oxRequireMT(typeOut, ox::writeClaw(type.value, ox::ClawFormat::Organic));
	// replace garbage last character with new line
	typeOut.back().value = '\n';
	// write to FS
	QString descPath = "/.nostalgia/type_descriptors/";
	const auto typePath = descPath + type.value->typeName.c_str();
	mkdir(descPath);
	writeBuff(typePath, ox::bit_cast<uint8_t*>(typeOut.data()), typeOut.size());
	emit fileUpdated(path);
}

template<typename T>
std::unique_ptr<T> Project::loadObj(QString path) const {
	auto obj = std::make_unique<T>();
	auto buff = loadBuff(path);
	oxThrowError(ox::readClaw<T>(buff.data(), buff.size(), obj.get()));
	return obj;
}

template<typename Functor>
void Project::subscribe(ProjectEvent e, QObject *tgt, Functor &&slot) const {
	switch (e) {
		case ProjectEvent::FileAdded:
			connect(this, &Project::fileAdded, tgt, (slot));
			break;
		case ProjectEvent::FileRecognized:
		{
			for (auto f : listFiles()) {
				slot(f);
			}
			connect(this, &Project::fileRecognized, tgt, (slot));
			break;
		}
		case ProjectEvent::FileDeleted:
			connect(this, &Project::fileDeleted, tgt, (slot));
			break;
		case ProjectEvent::FileUpdated:
			connect(this, &Project::fileUpdated, tgt, (slot));
			break;
	}
}

}
<|endoftext|>