<commit_before>// Filename: p3dMainObject.cxx
// Created by:  drose (10Jul09)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "p3dMainObject.h"
#include "p3dInstance.h"
#include "p3dSession.h"
#include "p3dUndefinedObject.h"
#include "p3dStringObject.h"
#include "p3dInstanceManager.h"

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::Constructor
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
P3DMainObject::
P3DMainObject() :
  _pyobj(NULL)
{
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::Destructor
//       Access: Public, Virtual
//  Description:
////////////////////////////////////////////////////////////////////
P3DMainObject::
~P3DMainObject() {
  set_pyobj(NULL);

  // Clear the local properties.
  Properties::const_iterator pi;
  for (pi = _properties.begin(); pi != _properties.end(); ++pi) {
    P3D_object *value = (*pi).second;
    P3D_OBJECT_DECREF(value);
  }
  _properties.clear();
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_type
//       Access: Public, Virtual
//  Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DMainObject::
get_type() {
  return P3D_OT_object;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_bool
//       Access: Public, Virtual
//  Description: Returns the object value coerced to a boolean, if
//               possible.
////////////////////////////////////////////////////////////////////
bool P3DMainObject::
get_bool() {
  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_int
//       Access: Public, Virtual
//  Description: Returns the object value coerced to an integer, if
//               possible.
////////////////////////////////////////////////////////////////////
int P3DMainObject::
get_int() {
  return 0;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_float
//       Access: Public, Virtual
//  Description: Returns the object value coerced to a floating-point
//               value, if possible.
////////////////////////////////////////////////////////////////////
double P3DMainObject::
get_float() {
  return 0.0;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::make_string
//       Access: Public, Virtual
//  Description: Fills the indicated C++ string object with the value
//               of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DMainObject::
make_string(string &value) {
  if (_pyobj == NULL) {
    value = "P3DMainObject";
  } else {
    int size = P3D_OBJECT_GET_STRING(_pyobj, NULL, 0);
    char *buffer = new char[size];
    P3D_OBJECT_GET_STRING(_pyobj, buffer, size);
    value = string(buffer, size);
    delete[] buffer;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_property
//       Access: Public, Virtual
//  Description: Returns the named property element in the object.  The
//               return value is a new-reference P3D_object, or NULL
//               on error.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
get_property(const string &property) {
  if (_pyobj == NULL) {
    // Without a pyobj, we just report whatever's been stored locally.
    Properties::const_iterator pi;
    pi = _properties.find(property);
    if (pi != _properties.end()) {
      P3D_object *result = (*pi).second;
      P3D_OBJECT_INCREF(result);
      return result;
    }
    return NULL;
  }

  // With a pyobj, we pass the query down to it.
  return P3D_OBJECT_GET_PROPERTY(_pyobj, property.c_str());
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::set_property
//       Access: Public, Virtual
//  Description: Modifies (or deletes, if value is NULL) the named
//               property element in the object.  Returns true on
//               success, false on failure.
////////////////////////////////////////////////////////////////////
bool P3DMainObject::
set_property(const string &property, P3D_object *value) {
  // First, we set the property locally.
  if (value != NULL) {
    Properties::iterator pi;
    pi = _properties.insert(Properties::value_type(property, NULL)).first;
    assert(pi != _properties.end());
    P3D_object *orig_value = (*pi).second;
    if (orig_value != value) {
      P3D_OBJECT_XDECREF(orig_value);
      (*pi).second = value;
      P3D_OBJECT_INCREF(value);
    }
  } else {
    // (Or delete the property locally.)
    Properties::iterator pi;
    pi = _properties.find(property);
    if (pi != _properties.end()) {
      P3D_object *orig_value = (*pi).second;
      P3D_OBJECT_DECREF(orig_value);
      _properties.erase(pi);
    }
  }

  if (_pyobj == NULL) {
    // Without a pyobj, that's all we do.
    return true;
  }

  // With a pyobj, we also pass this request down.
  return P3D_OBJECT_SET_PROPERTY(_pyobj, property.c_str(), value);
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::has_method
//       Access: Public, Virtual
//  Description: Returns true if the named method exists on this
//               object, false otherwise.
////////////////////////////////////////////////////////////////////
bool P3DMainObject::
has_method(const string &method_name) {
  // Some special-case methods implemented in-place.
  if (method_name == "read_game_log") {
    return true;
  } else if (method_name == "read_system_log") {
    return true;
  }

  if (_pyobj == NULL) {
    // No methods until we get our pyobj.
    return false;
  }

  return P3D_OBJECT_HAS_METHOD(_pyobj, method_name.c_str());
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::call
//       Access: Public, Virtual
//  Description: Invokes the named method on the object, passing the
//               indicated parameters.  If the method name is empty,
//               invokes the object itself.
//
//               If needs_response is true, the return value is a
//               new-reference P3D_object on success, or NULL on
//               failure.  If needs_response is false, the return
//               value is always NULL, and there is no way to
//               determine success or failure.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
call(const string &method_name, bool needs_response,
     P3D_object *params[], int num_params) {
  if (method_name == "read_game_log") {
    return call_read_game_log();
  } else if (method_name == "read_system_log") {
    return call_read_system_log();
  }

  if (_pyobj == NULL) {
    // No methods until we get our pyobj.
    return NULL;
  }

  return P3D_OBJECT_CALL(_pyobj, method_name.c_str(), needs_response,
                         params, num_params);
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::output
//       Access: Public, Virtual
//  Description: Writes a formatted representation of the value to the
//               indicated string.  This is intended for developer
//               assistance.
////////////////////////////////////////////////////////////////////
void P3DMainObject::
output(ostream &out) {
  out << "P3DMainObject";
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::set_pyobj
//       Access: Public
//  Description: Changes the internal pyobj pointer.  This is the
//               P3D_object that references the actual PyObject held
//               within the child process, corresponding to the true
//               main object there.  The new object's reference
//               count is incremented, and the previous object's is
//               decremented.
////////////////////////////////////////////////////////////////////
void P3DMainObject::
set_pyobj(P3D_object *pyobj) {
  if (_pyobj != pyobj) {
    P3D_OBJECT_XDECREF(_pyobj);
    _pyobj = pyobj;
    if (_pyobj != NULL) {
      P3D_OBJECT_INCREF(_pyobj);

      // Now that we have a pyobj, we have to transfer down all of the
      // properties we'd set locally.
      Properties::const_iterator pi;
      for (pi = _properties.begin(); pi != _properties.end(); ++pi) {
        const string &property_name = (*pi).first;
        P3D_object *value = (*pi).second;
        P3D_OBJECT_SET_PROPERTY(_pyobj, property_name.c_str(), value);
      }
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_pyobj
//       Access: Public
//  Description: Returns the internal pyobj pointer, or NULL if it has
//               not yet been set.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
get_pyobj() const {
  return _pyobj;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::set_instance
//       Access: Public
//  Description: Sets a callback pointer to the instance that owns
//               this object.  When this instance destructs, it clears
//               this pointer to NULL.
////////////////////////////////////////////////////////////////////
void P3DMainObject::
set_instance(P3DInstance *inst) {
  _inst = inst;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::call_read_game_log
//       Access: Private
//  Description: Reads the entire logfile as a string, and returns it
//               to the calling JavaScript process.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
call_read_game_log() {
  nout << "call_read_game_log: " << _inst << "\n";
  if (_inst == NULL) {
    return new P3DUndefinedObject();
  }

  P3DSession *session = _inst->get_session();
  nout << "session = " << session << "\n";

  string log_pathname = session->get_log_pathname();
  nout << "log_pathname = " << log_pathname << "\n";

  ifstream log(log_pathname.c_str(), ios::in);

  // Get the size of the file.
  log.seekg(0, ios::end);
  size_t size = (size_t)log.tellg();
  log.seekg(0, ios::beg);

  // Read the entire file into memory all at once.
  char *buffer = new char[size];
  if (buffer == NULL) {
    return NULL;
  }

  log.read(buffer, size);
  P3D_object *result = new P3DStringObject(buffer, size);
  delete[] buffer;

  return result;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::call_read_system_log
//       Access: Private
//  Description: As above, but reads the system log, the logfile for
//               the installation process.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
call_read_system_log() {
  nout << "call_read_system_log: " << _inst << "\n";

  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
  string log_pathname = inst_mgr->get_log_pathname();
  nout << "log_pathname = " << log_pathname << "\n";

  ifstream log(log_pathname.c_str(), ios::in);

  // Get the size of the file.
  log.seekg(0, ios::end);
  size_t size = (size_t)log.tellg();
  log.seekg(0, ios::beg);

  // Read the entire file into memory all at once.
  char *buffer = new char[size];
  if (buffer == NULL) {
    return NULL;
  }

  log.read(buffer, size);
  P3D_object *result = new P3DStringObject(buffer, size);
  delete[] buffer;

  return result;
}
<commit_msg>minor fix<commit_after>// Filename: p3dMainObject.cxx
// Created by:  drose (10Jul09)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "p3dMainObject.h"
#include "p3dInstance.h"
#include "p3dSession.h"
#include "p3dUndefinedObject.h"
#include "p3dStringObject.h"
#include "p3dInstanceManager.h"

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::Constructor
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
P3DMainObject::
P3DMainObject() :
  _pyobj(NULL)
{
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::Destructor
//       Access: Public, Virtual
//  Description:
////////////////////////////////////////////////////////////////////
P3DMainObject::
~P3DMainObject() {
  set_pyobj(NULL);

  // Clear the local properties.
  Properties::const_iterator pi;
  for (pi = _properties.begin(); pi != _properties.end(); ++pi) {
    P3D_object *value = (*pi).second;
    P3D_OBJECT_DECREF(value);
  }
  _properties.clear();
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_type
//       Access: Public, Virtual
//  Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DMainObject::
get_type() {
  return P3D_OT_object;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_bool
//       Access: Public, Virtual
//  Description: Returns the object value coerced to a boolean, if
//               possible.
////////////////////////////////////////////////////////////////////
bool P3DMainObject::
get_bool() {
  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_int
//       Access: Public, Virtual
//  Description: Returns the object value coerced to an integer, if
//               possible.
////////////////////////////////////////////////////////////////////
int P3DMainObject::
get_int() {
  return 0;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_float
//       Access: Public, Virtual
//  Description: Returns the object value coerced to a floating-point
//               value, if possible.
////////////////////////////////////////////////////////////////////
double P3DMainObject::
get_float() {
  return 0.0;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::make_string
//       Access: Public, Virtual
//  Description: Fills the indicated C++ string object with the value
//               of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DMainObject::
make_string(string &value) {
  if (_pyobj == NULL) {
    value = "P3DMainObject";
  } else {
    int size = P3D_OBJECT_GET_STRING(_pyobj, NULL, 0);
    char *buffer = new char[size];
    P3D_OBJECT_GET_STRING(_pyobj, buffer, size);
    value = string(buffer, size);
    delete[] buffer;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_property
//       Access: Public, Virtual
//  Description: Returns the named property element in the object.  The
//               return value is a new-reference P3D_object, or NULL
//               on error.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
get_property(const string &property) {
  if (_pyobj == NULL) {
    // Without a pyobj, we just report whatever's been stored locally.
    Properties::const_iterator pi;
    pi = _properties.find(property);
    if (pi != _properties.end()) {
      P3D_object *result = (*pi).second;
      P3D_OBJECT_INCREF(result);
      return result;
    }
    return NULL;
  }

  // With a pyobj, we pass the query down to it.
  return P3D_OBJECT_GET_PROPERTY(_pyobj, property.c_str());
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::set_property
//       Access: Public, Virtual
//  Description: Modifies (or deletes, if value is NULL) the named
//               property element in the object.  Returns true on
//               success, false on failure.
////////////////////////////////////////////////////////////////////
bool P3DMainObject::
set_property(const string &property, P3D_object *value) {
  // First, we set the property locally.
  if (value != NULL) {
    Properties::iterator pi;
    pi = _properties.insert(Properties::value_type(property, NULL)).first;
    assert(pi != _properties.end());
    P3D_object *orig_value = (*pi).second;
    if (orig_value != value) {
      P3D_OBJECT_XDECREF(orig_value);
      (*pi).second = value;
      P3D_OBJECT_INCREF(value);
    }
  } else {
    // (Or delete the property locally.)
    Properties::iterator pi;
    pi = _properties.find(property);
    if (pi != _properties.end()) {
      P3D_object *orig_value = (*pi).second;
      P3D_OBJECT_DECREF(orig_value);
      _properties.erase(pi);
    }
  }

  if (_pyobj == NULL) {
    // Without a pyobj, that's all we do.
    return true;
  }

  // With a pyobj, we also pass this request down.
  return P3D_OBJECT_SET_PROPERTY(_pyobj, property.c_str(), value);
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::has_method
//       Access: Public, Virtual
//  Description: Returns true if the named method exists on this
//               object, false otherwise.
////////////////////////////////////////////////////////////////////
bool P3DMainObject::
has_method(const string &method_name) {
  // Some special-case methods implemented in-place.
  if (method_name == "read_game_log") {
    return true;
  } else if (method_name == "read_system_log") {
    return true;
  }

  if (_pyobj == NULL) {
    // No methods until we get our pyobj.
    return false;
  }

  return P3D_OBJECT_HAS_METHOD(_pyobj, method_name.c_str());
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::call
//       Access: Public, Virtual
//  Description: Invokes the named method on the object, passing the
//               indicated parameters.  If the method name is empty,
//               invokes the object itself.
//
//               If needs_response is true, the return value is a
//               new-reference P3D_object on success, or NULL on
//               failure.  If needs_response is false, the return
//               value is always NULL, and there is no way to
//               determine success or failure.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
call(const string &method_name, bool needs_response,
     P3D_object *params[], int num_params) {
  if (method_name == "read_game_log") {
    return call_read_game_log();
  } else if (method_name == "read_system_log") {
    return call_read_system_log();
  }

  if (_pyobj == NULL) {
    // No methods until we get our pyobj.
    return NULL;
  }

  return P3D_OBJECT_CALL(_pyobj, method_name.c_str(), needs_response,
                         params, num_params);
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::output
//       Access: Public, Virtual
//  Description: Writes a formatted representation of the value to the
//               indicated string.  This is intended for developer
//               assistance.
////////////////////////////////////////////////////////////////////
void P3DMainObject::
output(ostream &out) {
  out << "P3DMainObject";
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::set_pyobj
//       Access: Public
//  Description: Changes the internal pyobj pointer.  This is the
//               P3D_object that references the actual PyObject held
//               within the child process, corresponding to the true
//               main object there.  The new object's reference
//               count is incremented, and the previous object's is
//               decremented.
////////////////////////////////////////////////////////////////////
void P3DMainObject::
set_pyobj(P3D_object *pyobj) {
  if (_pyobj != pyobj) {
    P3D_OBJECT_XDECREF(_pyobj);
    _pyobj = pyobj;
    if (_pyobj != NULL) {
      P3D_OBJECT_INCREF(_pyobj);

      // Now that we have a pyobj, we have to transfer down all of the
      // properties we'd set locally.
      Properties::const_iterator pi;
      for (pi = _properties.begin(); pi != _properties.end(); ++pi) {
        const string &property_name = (*pi).first;
        P3D_object *value = (*pi).second;
        P3D_OBJECT_SET_PROPERTY(_pyobj, property_name.c_str(), value);
      }
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::get_pyobj
//       Access: Public
//  Description: Returns the internal pyobj pointer, or NULL if it has
//               not yet been set.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
get_pyobj() const {
  return _pyobj;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::set_instance
//       Access: Public
//  Description: Sets a callback pointer to the instance that owns
//               this object.  When this instance destructs, it clears
//               this pointer to NULL.
////////////////////////////////////////////////////////////////////
void P3DMainObject::
set_instance(P3DInstance *inst) {
  _inst = inst;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::call_read_game_log
//       Access: Private
//  Description: Reads the entire logfile as a string, and returns it
//               to the calling JavaScript process.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
call_read_game_log() {
  if (_inst == NULL) {
    return new P3DUndefinedObject();
  }

  P3DSession *session = _inst->get_session();
  if (session == NULL) {
    return new P3DUndefinedObject();
  }

  string log_pathname = session->get_log_pathname();
  ifstream log(log_pathname.c_str(), ios::in);

  // Get the size of the file.
  log.seekg(0, ios::end);
  size_t size = (size_t)log.tellg();
  log.seekg(0, ios::beg);

  // Read the entire file into memory all at once.
  char *buffer = new char[size];
  if (buffer == NULL) {
    return NULL;
  }

  log.read(buffer, size);
  P3D_object *result = new P3DStringObject(buffer, size);
  delete[] buffer;

  return result;
}

////////////////////////////////////////////////////////////////////
//     Function: P3DMainObject::call_read_system_log
//       Access: Private
//  Description: As above, but reads the system log, the logfile for
//               the installation process.
////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject::
call_read_system_log() {
  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();

  string log_pathname = inst_mgr->get_log_pathname();
  ifstream log(log_pathname.c_str(), ios::in);

  // Get the size of the file.
  log.seekg(0, ios::end);
  size_t size = (size_t)log.tellg();
  log.seekg(0, ios::beg);

  // Read the entire file into memory all at once.
  char *buffer = new char[size];
  if (buffer == NULL) {
    return NULL;
  }

  log.read(buffer, size);
  P3D_object *result = new P3DStringObject(buffer, size);
  delete[] buffer;

  return result;
}
<|endoftext|>


<commit_before>#include "MALLOC.H"

#include "GAMEFLOW.H"
#include "SPECIFIC.H"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define GAME_MALLOC_BUFFER_SIZE (1024*1024) + (1024*36)

char* malloc_ptr = NULL;
int malloc_used = 0;
int malloc_free = GAME_MALLOC_BUFFER_SIZE;
int script_malloc_size = 0;
char malloc_buffer[GAME_MALLOC_BUFFER_SIZE];

/*
 * [FUNCTIONALITY] - init_game_malloc.
 * Resets malloc_buffer and all allocation stats back to their default values.
 * Note: The entire malloc_buffer is zero initialised.
 * Note: Once the gameflow script is loaded it's always in malloc_buffer regardless.
 */

void init_game_malloc()//5E79C(<), 5F4F8(<) (F) (*)
{
	malloc_used = gfScriptLen;
	malloc_free = GAME_MALLOC_BUFFER_SIZE - gfScriptLen;
	malloc_ptr = &malloc_buffer[gfScriptLen];
	memset(&malloc_ptr[0], 0, GAME_MALLOC_BUFFER_SIZE - gfScriptLen);
}

/*
 * [FUNCTIONALITY] - game_malloc.
 * "Allocates" memory from our malloc_buffer declared on the stack.
 * Note: Memory that is "allocated" is not zero initialised.
 * Note: If you run out of memory the application will exit.
 * Note: Usage should be seen as stack functionality, always free the last block of memory you allocated (LIFO).
 * [USAGE]
 * @PARAM - [size] The amount of memory you wish to "allocate".
 * @RETURN - [ptr] Pointer to the memory block you just "allocated".
 */

char* game_malloc(int size)//5E7E8(<), 5F544(<) (F) (*) (?)
{
#if DEBUG_VERSION
	char buf[80];
#endif

	char* ptr;

	size = (size + 3) & -4;

	if (size <= malloc_free)
	{
		ptr = malloc_ptr;

		malloc_free -= size;
		malloc_ptr += size;
		malloc_used += size;

	}
#if DEBUG_VERSION
	else
	{
		sprintf(buf, "game_malloc() out of space (needs %d only got %d)\n", size, malloc_free);
		S_ExitSystem(buf);
		return NULL;
	}
#endif
	return ptr;
}

/*
 * [FUNCTIONALITY] - game_free.
 * "Frees" memory from malloc_buffer.
 * Note: Memory that is freed is not zero initialised.
 * Note: There is no error checking so ensure you do not free more memory than the buffer can hold.
 * Note: Usage should be seen as stack functionality, always free the last block of memory you allocated (LIFO).
 * [USAGE]
 * @PARAM - [size] The amount of memory you wish to "free".
 */

void game_free(int size)//5E85C(<), 5F590(<) (F) (*)
{
	size = (size + 3) & -4;

	malloc_ptr -= size;
	malloc_free += size;
	malloc_used -= size;
}

/*
 * [FUNCTIONALITY] - show_game_malloc_totals.
 * Prints the amount of free/used malloc_buffer memory to stdio in Kilobytes.
 */

void show_game_malloc_totals()//5E894(<), * (F) (*)
{
	printf("---->Total Memory Used %dK of %dK<----\n", ((malloc_used + 1023) / 1024) - 10, ((malloc_used + malloc_free) / 1024) - 10);
}

/*
 * [FUNCTIONALITY] - dump_game_malloc.
 * Dumps the entire malloc_buffer to a file named "DUMP.BIN"
 * This is typically used to inspect malloc_buffer memory and compare to PS1.
 */

void dump_game_malloc()//*, *
{
	FILE* fileHandle = NULL;

	fileHandle = fopen("DUMP.BIN", "wb");
	if (fileHandle != NULL)
	{
		fwrite(&malloc_buffer[0], sizeof(char), GAME_MALLOC_BUFFER_SIZE, fileHandle);
		fclose(fileHandle);
	}
	else
	{
		printf("Failed to dump memory!\n");
	}
}<commit_msg>PSXPC Macro alteration.<commit_after>#include "MALLOC.H"

#include "GAMEFLOW.H"
#include "SPECIFIC.H"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define GAME_MALLOC_BUFFER_SIZE (1024*1060)

char* malloc_ptr = NULL;
int malloc_used = 0;
int malloc_free = GAME_MALLOC_BUFFER_SIZE;
int script_malloc_size = 0;
char malloc_buffer[GAME_MALLOC_BUFFER_SIZE];

/*
 * [FUNCTIONALITY] - init_game_malloc.
 * Resets malloc_buffer and all allocation stats back to their default values.
 * Note: The entire malloc_buffer is zero initialised.
 * Note: Once the gameflow script is loaded it's always in malloc_buffer regardless.
 */

void init_game_malloc()//5E79C(<), 5F4F8(<) (F) (*)
{
	malloc_used = gfScriptLen;
	malloc_free = GAME_MALLOC_BUFFER_SIZE - gfScriptLen;
	malloc_ptr = &malloc_buffer[gfScriptLen];
	memset(&malloc_ptr[0], 0, GAME_MALLOC_BUFFER_SIZE - gfScriptLen);
}

/*
 * [FUNCTIONALITY] - game_malloc.
 * "Allocates" memory from our malloc_buffer declared on the stack.
 * Note: Memory that is "allocated" is not zero initialised.
 * Note: If you run out of memory the application will exit.
 * Note: Usage should be seen as stack functionality, always free the last block of memory you allocated (LIFO).
 * [USAGE]
 * @PARAM - [size] The amount of memory you wish to "allocate".
 * @RETURN - [ptr] Pointer to the memory block you just "allocated".
 */

char* game_malloc(int size)//5E7E8(<), 5F544(<) (F) (*) (?)
{
#if DEBUG_VERSION
	char buf[80];
#endif

	char* ptr;

	size = (size + 3) & -4;

	if (size <= malloc_free)
	{
		ptr = malloc_ptr;

		malloc_free -= size;
		malloc_ptr += size;
		malloc_used += size;

	}
#if DEBUG_VERSION
	else
	{
		sprintf(buf, "game_malloc() out of space (needs %d only got %d)\n", size, malloc_free);
		S_ExitSystem(buf);
		return NULL;
	}
#endif
	return ptr;
}

/*
 * [FUNCTIONALITY] - game_free.
 * "Frees" memory from malloc_buffer.
 * Note: Memory that is freed is not zero initialised.
 * Note: There is no error checking so ensure you do not free more memory than the buffer can hold.
 * Note: Usage should be seen as stack functionality, always free the last block of memory you allocated (LIFO).
 * [USAGE]
 * @PARAM - [size] The amount of memory you wish to "free".
 */

void game_free(int size)//5E85C(<), 5F590(<) (F) (*)
{
	size = (size + 3) & -4;

	malloc_ptr -= size;
	malloc_free += size;
	malloc_used -= size;
}

/*
 * [FUNCTIONALITY] - show_game_malloc_totals.
 * Prints the amount of free/used malloc_buffer memory to stdio in Kilobytes.
 */

void show_game_malloc_totals()//5E894(<), * (F) (*)
{
	printf("---->Total Memory Used %dK of %dK<----\n", ((malloc_used + 1023) / 1024) - 10, ((malloc_used + malloc_free) / 1024) - 10);
}

/*
 * [FUNCTIONALITY] - dump_game_malloc.
 * Dumps the entire malloc_buffer to a file named "DUMP.BIN"
 * This is typically used to inspect malloc_buffer memory and compare to PS1.
 */

void dump_game_malloc()//*, *
{
	FILE* fileHandle = NULL;

	fileHandle = fopen("DUMP.BIN", "wb");
	if (fileHandle != NULL)
	{
		fwrite(&malloc_buffer[0], sizeof(char), GAME_MALLOC_BUFFER_SIZE, fileHandle);
		fclose(fileHandle);
	}
	else
	{
		printf("Failed to dump memory!\n");
	}
}<|endoftext|>


<commit_before>#include "ovkCLogManager.h"

#include <iostream>

using namespace OpenViBE;
using namespace OpenViBE::Kernel;
using namespace std;

CLogManager::CLogManager(const IKernelContext& rKernelContext)
	:TKernelObject<ILogManager>(rKernelContext)
	,m_eCurrentLogLevel(LogLevel_Info)
{
}

boolean CLogManager::isActive(ELogLevel eLogLevel)
{
	map<ELogLevel, boolean>::iterator itLogLevel=m_vActiveLevel.find(eLogLevel);
	if(itLogLevel==m_vActiveLevel.end())
	{
		return true;
	}
	return itLogLevel->second;
}

boolean CLogManager::activate(ELogLevel eLogLevel, boolean bActive)
{
	m_vActiveLevel[eLogLevel]=bActive;
	return true;
}

boolean CLogManager::activate(ELogLevel eStartLogLevel, ELogLevel eEndLogLevel, boolean bActive)
{
	for(int i=eStartLogLevel; i<=eEndLogLevel; i++)
	{
		m_vActiveLevel[ELogLevel(i)]=bActive;
	}
	return true;
}

boolean CLogManager::activate(boolean bActive)
{
	return activate(LogLevel_First, LogLevel_Last, bActive);
}

void CLogManager::log(const time64 time64Value)
{
	logForEach<const time64>(time64Value);
}

void CLogManager::log(const uint64 ui64Value)
{
	logForEach<const uint64>(ui64Value);
}

void CLogManager::log(const uint32 ui32Value)
{
	logForEach<const uint32>(ui32Value);
}

void CLogManager::log(const uint16 ui16Value)
{
	logForEach<const uint16>(ui16Value);
}

void CLogManager::log(const uint8 ui8Value)
{
	logForEach<const uint8>(ui8Value);
}

void CLogManager::log(const int64 i64Value)
{
	logForEach<const int64>(i64Value);
}

void CLogManager::log(const int32 i32Value)
{
	logForEach<const int32>(i32Value);
}

void CLogManager::log(const int16 i16Value)
{
	logForEach<const int16>(i16Value);
}

void CLogManager::log(const int8 i8Value)
{
	logForEach<const int8>(i8Value);
}

void CLogManager::log(const float64 f64Value)
{
	logForEach<const float64>(f64Value);
}

void CLogManager::log(const float32 f32Value)
{
	logForEach<const float32>(f32Value);
}

void CLogManager::log(const boolean bValue)
{
	logForEach<const boolean>(bValue);
}

void CLogManager::log(const CIdentifier& rValue)
{
	logForEach<const CIdentifier&>(rValue);
}

void CLogManager::log(const CString& rValue)
{
	logForEach<const CString&>(rValue);
}

void CLogManager::log(const char* rValue)
{
	logForEach<const char*>(rValue);
}

void CLogManager::log(const ELogLevel eLogLevel)
{
	m_eCurrentLogLevel=eLogLevel;
	logForEach<ELogLevel>(eLogLevel);
}

void CLogManager::log(const ELogColor eLogColor)
{
	logForEach<ELogColor>(eLogColor);
}

boolean CLogManager::addListener(ILogListener* pListener)
{
	if(pListener==NULL)
	{
		return false;
	}

	vector<ILogListener*>::iterator itLogListener=m_vListener.begin();
	while(itLogListener!=m_vListener.end())
	{
		if((*itLogListener)==pListener)
		{
			return false;
		}
		itLogListener++;
	}

	m_vListener.push_back(pListener);
	return true;
}

boolean CLogManager::removeListener(ILogListener* pListener)
{
	boolean l_bResult=false;
	vector<ILogListener*>::iterator itLogListener=m_vListener.begin();
	while(itLogListener!=m_vListener.end())
	{
		if((*itLogListener)==pListener)
		{
			itLogListener=m_vListener.erase(itLogListener);
			l_bResult=true;
		}
		itLogListener++;
	}
	return l_bResult;
}
<commit_msg>openvibe-kernel: * [ovkCLogManager.cpp] fixed the removeListener() function crash<commit_after>#include "ovkCLogManager.h"

#include <iostream>

using namespace OpenViBE;
using namespace OpenViBE::Kernel;
using namespace std;

CLogManager::CLogManager(const IKernelContext& rKernelContext)
	:TKernelObject<ILogManager>(rKernelContext)
	,m_eCurrentLogLevel(LogLevel_Info)
{
}

boolean CLogManager::isActive(ELogLevel eLogLevel)
{
	map<ELogLevel, boolean>::iterator itLogLevel=m_vActiveLevel.find(eLogLevel);
	if(itLogLevel==m_vActiveLevel.end())
	{
		return true;
	}
	return itLogLevel->second;
}

boolean CLogManager::activate(ELogLevel eLogLevel, boolean bActive)
{
	m_vActiveLevel[eLogLevel]=bActive;
	return true;
}

boolean CLogManager::activate(ELogLevel eStartLogLevel, ELogLevel eEndLogLevel, boolean bActive)
{
	for(int i=eStartLogLevel; i<=eEndLogLevel; i++)
	{
		m_vActiveLevel[ELogLevel(i)]=bActive;
	}
	return true;
}

boolean CLogManager::activate(boolean bActive)
{
	return activate(LogLevel_First, LogLevel_Last, bActive);
}

void CLogManager::log(const time64 time64Value)
{
	logForEach<const time64>(time64Value);
}

void CLogManager::log(const uint64 ui64Value)
{
	logForEach<const uint64>(ui64Value);
}

void CLogManager::log(const uint32 ui32Value)
{
	logForEach<const uint32>(ui32Value);
}

void CLogManager::log(const uint16 ui16Value)
{
	logForEach<const uint16>(ui16Value);
}

void CLogManager::log(const uint8 ui8Value)
{
	logForEach<const uint8>(ui8Value);
}

void CLogManager::log(const int64 i64Value)
{
	logForEach<const int64>(i64Value);
}

void CLogManager::log(const int32 i32Value)
{
	logForEach<const int32>(i32Value);
}

void CLogManager::log(const int16 i16Value)
{
	logForEach<const int16>(i16Value);
}

void CLogManager::log(const int8 i8Value)
{
	logForEach<const int8>(i8Value);
}

void CLogManager::log(const float64 f64Value)
{
	logForEach<const float64>(f64Value);
}

void CLogManager::log(const float32 f32Value)
{
	logForEach<const float32>(f32Value);
}

void CLogManager::log(const boolean bValue)
{
	logForEach<const boolean>(bValue);
}

void CLogManager::log(const CIdentifier& rValue)
{
	logForEach<const CIdentifier&>(rValue);
}

void CLogManager::log(const CString& rValue)
{
	logForEach<const CString&>(rValue);
}

void CLogManager::log(const char* rValue)
{
	logForEach<const char*>(rValue);
}

void CLogManager::log(const ELogLevel eLogLevel)
{
	m_eCurrentLogLevel=eLogLevel;
	logForEach<ELogLevel>(eLogLevel);
}

void CLogManager::log(const ELogColor eLogColor)
{
	logForEach<ELogColor>(eLogColor);
}

boolean CLogManager::addListener(ILogListener* pListener)
{
	if(pListener==NULL)
	{
		return false;
	}

	vector<ILogListener*>::iterator itLogListener=m_vListener.begin();
	while(itLogListener!=m_vListener.end())
	{
		if((*itLogListener)==pListener)
		{
			return false;
		}
		itLogListener++;
	}

	m_vListener.push_back(pListener);
	return true;
}

boolean CLogManager::removeListener(ILogListener* pListener)
{
	boolean l_bResult=false;
	vector<ILogListener*>::iterator itLogListener=m_vListener.begin();
	while(itLogListener!=m_vListener.end())
	{
		if((*itLogListener)==pListener)
		{
			itLogListener=m_vListener.erase(itLogListener);
			l_bResult=true;
		} else {
			itLogListener++;
		}
	}
	return l_bResult;
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 Egor Pugin <egor.pugin@gmail.com>
//
// 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/.

#include <primitives/filesystem.h>

#include <primitives/file_iterator.h>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

#include <iostream>
#include <regex>

#ifdef _WIN32
#include <Windows.h>
#endif

#ifndef _WIN32
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#endif

#ifndef _WIN32
#define _GNU_SOURCE // for dladdr
#include <dlfcn.h>
#endif

path get_home_directory()
{
#ifdef _WIN32
    auto home = _wgetenv(L"USERPROFILE");
    if (!home)
        std::cerr << "Cannot get user's home directory (%USERPROFILE%)\n";
#else
    auto home = getenv("HOME");
    if (!home)
    {
        auto p = getpwuid(getuid());
        if (p)
            return p->pw_dir;
        std::cerr << "Cannot get user's home directory ($HOME)\n";
    }
#endif
    if (home == nullptr)
        return "";
    return home;
}

path current_thread_path(const path &p)
{
    thread_local path thread_working_dir = p.empty() ? fs::current_path() : fs::canonical(fs::absolute(p));
    if (p.empty())
        return thread_working_dir;
    return thread_working_dir = fs::canonical(fs::absolute(p));
}

void remove_file(const path &p)
{
    error_code ec;
    fs::remove(p, ec);
    if (ec)
        std::cerr << "Cannot remove file: " << p.u8string() << "\n";
}

void remove_all_from_dir(const path &dir)
{
    for (auto &f : fs::directory_iterator(dir))
        fs::remove_all(f);
}

String normalize_path(const path &p)
{
    if (p.empty())
        return "";
    auto s = p.u8string();
    normalize_string(s);
    return s;
}

String normalize_path_windows(const path &p)
{
    if (p.empty())
        return "";
    auto s = p.u8string();
    normalize_string_windows(s);
    return s;
}

std::wstring wnormalize_path(const path &p)
{
    if (p.empty())
        return L"";
    auto s = p.wstring();
    normalize_string(s);
    return s;
}

std::wstring wnormalize_path_windows(const path &p)
{
    if (p.empty())
        return L"";
    auto s = p.wstring();
    normalize_string_windows(s);
    return s;
}

String read_file_bytes_unchecked(const path &p, uintmax_t offset, uintmax_t count)
{
    ScopedFile ifile(p, "rb");

    String f;
    f.resize(count);
    ifile.seek(offset);
    ifile.read(&f[0], count);
    return f;
}

String read_file_bytes(const path &p, uintmax_t offset, uintmax_t count)
{
    error_code ec;
    if (!fs::exists(p, ec))
        throw std::runtime_error("File '" + p.u8string() + "' does not exist");
    return read_file_bytes_unchecked(p, offset, count);
}

String read_file_from_offset(const path &p, uintmax_t offset, uintmax_t max_size)
{
    error_code ec;
    if (!fs::exists(p, ec))
        throw std::runtime_error("File '" + p.u8string() + "' does not exist");

    auto sz = fs::file_size(p) - offset;
    if (sz > max_size)
        throw std::runtime_error("File " + p.u8string() + " is bigger than allowed limit (" + std::to_string(max_size) + " bytes)");

    return read_file_bytes_unchecked(p, offset, sz);
}

String read_file(const path &p, uintmax_t max_size)
{
    return read_file_from_offset(p, 0, max_size);
}

String read_file_without_bom(const path &p, uintmax_t max_size)
{
    static const std::vector<std::vector<uint8_t>> boms
    {
        // UTF-8
        { 0xEF, 0xBB, 0xBF, },

        // UTF-16 BE, LE
        { 0xFE, 0xFF, },
        { 0xFF, 0xFE, },

        // UTF-32 BE, LE
        { 0x00, 0x00, 0xFE, 0xFF, },
        { 0xFF, 0xFE, 0x00, 0x00, },

        // UTF-7
        { 0x2B, 0x2F, 0x76, 0x38 },
        { 0x2B, 0x2F, 0x76, 0x39 },
        { 0x2B, 0x2F, 0x76, 0x2B },
        { 0x2B, 0x2F, 0x76, 0x2F },
        { 0x2B, 0x2F, 0x76, 0x38, 0x2D },

        // UTF-1
        { 0xF7, 0x64, 0x4C, },

        // UTF-EBCDIC
        { 0xDD, 0x73, 0x66, 0x73 },

        // SCSU
        { 0x0E, 0xFE, 0xFF, },

        // BOCU-1
        { 0xFB, 0xEE, 0x28, },

        // GB-18030
        { 0x84, 0x31, 0x95, 0x33 },
    };

    static const auto max_len = std::max_element(boms.begin(), boms.end(),
        [](const auto &e1, const auto &e2) { return e1.size() < e2.size(); })->size();

    // read max bom length
    auto s = read_file_bytes(p, 0, max_len);

    for (auto &b : boms)
    {
        if (s.size() >= b.size() && memcmp(s.data(), b.data(), b.size()) == 0)
            return read_file_from_offset(p, b.size(), max_size);
    }

    return read_file(p, max_size);
}

Strings read_lines(const path &p)
{
    auto s = read_file(p);
    return split_lines(s);
}

static void write_file1(const path &p, const String &s, const char *mode)
{
    auto pp = p.parent_path();
    if (!pp.empty())
        fs::create_directories(pp);

    ScopedFile f(p, mode);
    fwrite(s.c_str(), s.size(), 1, f.getHandle());
}

void write_file(const path &p, const String &s)
{
    write_file1(p, s, "wb");
}

void write_file_if_different(const path &p, const String &s)
{
    error_code ec;
    if (fs::exists(p, ec))
    {
        auto s2 = read_file(p);
        if (s == s2)
            return;
    }
    write_file(p, s);
}

void prepend_file(const path &p, const String &s)
{
    auto s2 = read_file(p);
    write_file(p, s + s2);
}

void append_file(const path &p, const String &s)
{
    write_file1(p, s, "ab");
}

void copy_dir(const path &src, const path &dst)
{
    error_code ec;
    fs::create_directories(dst, ec);
    for (auto &f : fs::directory_iterator(src))
    {
        if (fs::is_directory(f))
            copy_dir(f, dst / f.path().filename());
        else
            copy_file(f, dst / f.path().filename(), fs::copy_options::overwrite_existing);
    }
}

void remove_files(const Files &files)
{
    for (auto &f : files)
        fs::remove(f);
}

void remove_files_like(const Files &files, const String &regex)
{
    remove_files(filter_files_like(files, regex));
}

void remove_files_like(const path &dir, const String &regex, bool recursive)
{
    remove_files_like(enumerate_files(dir, recursive), regex);
}

Files enumerate_files(const path &dir, bool recursive)
{
    Files files;
    error_code ec;
    if (!fs::exists(dir, ec))
        return files;
    if (recursive)
    {
        for (auto &f : fs::recursive_directory_iterator(dir))
        {
            if (!fs::is_regular_file(f))
                continue;
            files.insert(f);
        }
    }
    else
    {
        for (auto &f : fs::directory_iterator(dir))
        {
            if (!fs::is_regular_file(f))
                continue;
            files.insert(f);
        }
    }
    return files;
}

Files enumerate_files_like(const path &dir, const String &regex, bool recursive)
{
    return filter_files_like(enumerate_files(dir, recursive), regex);
}

Files enumerate_files_like(const Files &files, const String &regex)
{
    return filter_files_like(files, regex);
}

Files filter_files_like(const Files &files, const String &regex)
{
    Files fls;
    std::regex r(regex);
    for (auto &f : files)
    {
        if (!std::regex_match(f.filename().u8string(), r))
            continue;
        fls.insert(f);
    }
    return fls;
}

bool is_under_root(path p, const path &root_dir)
{
    if (p.empty())
        return false;
    error_code ec;
    if (fs::exists(p, ec))
        // Converts p, which must exist, to an absolute path
        // that has no symbolic link, dot, or dot-dot elements.
        p = fs::canonical(p);
    while (!p.empty() && p != p.root_path())
    {
        if (fs::equivalent(p, root_dir, ec))
            return true;
        p = p.parent_path();
    }
    return false;
}

bool compare_files(const path &fn1, const path &fn2)
{
    FileIterator fi({ fn1, fn2 });
    return fi.iterate([](const auto &bufs, auto sz)
    {
        if (memcmp(bufs[0].get().data(), bufs[1].get().data(), (size_t)sz) != 0)
            return false;
        return true;
    });
}

bool compare_dirs(const path &dir1, const path &dir2)
{
    auto traverse_dir = [](const auto &dir)
    {
        std::vector<path> files;
        error_code ec;
        if (fs::exists(dir, ec))
        {
            for (auto &f : fs::recursive_directory_iterator(dir))
            {
                if (!fs::is_regular_file(f))
                    continue;
                files.push_back(f);
            }
        }
        return files;
    };

    auto files1 = traverse_dir(dir1);
    auto files2 = traverse_dir(dir2);

    if (files1.empty())
        return false; // throw std::runtime_error("left side has no files");
    if (files2.empty())
        return false; // throw std::runtime_error("right side has no files");
    if (files1.size() != files2.size())
        return false; // throw std::runtime_error("different number of files");

    auto sz = files1.size();
    for (size_t i = 0; i < sz; i++)
    {
        if (!compare_files(files1[i], files2[i]))
            return false;
    }

    return true;
}

FileIterator::FileIterator(const FilesOrdered &fns)
{
    if (fns.empty())
        throw std::runtime_error("Provide at least one file");

    for (auto &f : fns)
    {
        File d;
        d.size = fs::file_size(f);
        d.ifile = std::make_unique<ScopedFile>(f, "rb");
        files.emplace_back(std::move(d));
    }
}

bool FileIterator::is_same_size() const
{
    auto sz = files.front().size;
    return std::all_of(files.begin(), files.end(),
        [sz](const auto &f) { return f.size == sz; });
}

bool FileIterator::is_same_read_size() const
{
    auto sz = files.front().read;
    return std::all_of(files.begin(), files.end(),
        [sz](const auto &f) { return f.read == sz; });
}

bool FileIterator::iterate(std::function<bool(const BuffersRef &, uint64_t)> f)
{
    if (!is_same_size())
        return false;

    BuffersRef buffers;
    for (auto &f : files)
    {
        f.buf.resize(buffer_size);
        buffers.emplace_back(f.buf);
    }

    while (std::none_of(files.begin(), files.end(),
        [](const auto &f) { return feof(f.ifile->getHandle()); }))
    {
        std::for_each(files.begin(), files.end(), [this](auto &f)
        {
            f.read = f.ifile->read((char *)&f.buf[0], buffer_size);
        });
        if (!is_same_read_size())
            return false;

        if (!f(buffers, files.front().read))
            return false;
    }
    return true;
}

path unique_path(const path &p)
{
    return boost::filesystem::unique_path(p.u8string()).wstring();
}

namespace primitives::filesystem
{

FILE *fopen(const path &p, const char *mode)
{
#ifdef _WIN32
    auto s = p.wstring();
    if (s.size() >= 255)
    {
        s = L"\\\\?\\" + s;
        boost::replace_all(s, L"/", L"\\");
    }
    return _wfopen(s.c_str(), path(mode).wstring().c_str());
#else
    return ::fopen(p.u8string().c_str(), mode);
#endif
}

FILE *fopen_checked(const path &p, const char *mode)
{
    auto f = fopen(p, mode);
    if (!f)
        throw std::runtime_error("Cannot open file: " + p.u8string() + ", mode = " + mode + ", errno = " + std::to_string(errno));
    return f;
}

void create(const path &p)
{
    // probably this is fixed in MS STL
    /*auto s = p.parent_path().u8string();
#ifdef _WIN32
    if (s.size() >= 255)
    {
        s = "\\\\?\\" + s;
        boost::replace_all(s, "/", "\\");
    }
#endif
    fs::create_directories(s);*/
    fs::create_directories(p.parent_path());
    fclose(fopen(p, "wb"));
}

}

ScopedFile::ScopedFile(const path &p, const char *mode)
{
    f = primitives::filesystem::fopen_checked(p, mode);
}

ScopedFile::~ScopedFile()
{
    if (f)
        fclose(f);
}

size_t ScopedFile::read(void *buf, size_t sz)
{
    return fread(buf, 1, sz, f);
}

void ScopedFile::seek(uintmax_t offset)
{
    fseek(f, offset, SEEK_SET);
}
<commit_msg>Prefer getpwuid to env var while detecting home dir.<commit_after>// Copyright (C) 2018 Egor Pugin <egor.pugin@gmail.com>
//
// 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/.

#include <primitives/filesystem.h>

#include <primitives/file_iterator.h>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

#include <iostream>
#include <regex>

#ifdef _WIN32
#include <Windows.h>
#endif

#ifndef _WIN32
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#endif

#ifndef _WIN32
#define _GNU_SOURCE // for dladdr
#include <dlfcn.h>
#endif

path get_home_directory()
{
#ifdef _WIN32
    auto home = _wgetenv(L"USERPROFILE");
    if (!home)
        std::cerr << "Cannot get user's home directory (%USERPROFILE%)\n";
#else
    // prefer this way
    auto p = getpwuid(getuid());
    if (p)
        return p->pw_dir;
    auto home = getenv("HOME");
    if (!home)
        std::cerr << "Cannot get user's home directory ($HOME)\n";
#endif
    if (home == nullptr)
        return "";
    return home;
}

path current_thread_path(const path &p)
{
    thread_local path thread_working_dir = p.empty() ? fs::current_path() : fs::canonical(fs::absolute(p));
    if (p.empty())
        return thread_working_dir;
    return thread_working_dir = fs::canonical(fs::absolute(p));
}

void remove_file(const path &p)
{
    error_code ec;
    fs::remove(p, ec);
    if (ec)
        std::cerr << "Cannot remove file: " << p.u8string() << "\n";
}

void remove_all_from_dir(const path &dir)
{
    for (auto &f : fs::directory_iterator(dir))
        fs::remove_all(f);
}

String normalize_path(const path &p)
{
    if (p.empty())
        return "";
    auto s = p.u8string();
    normalize_string(s);
    return s;
}

String normalize_path_windows(const path &p)
{
    if (p.empty())
        return "";
    auto s = p.u8string();
    normalize_string_windows(s);
    return s;
}

std::wstring wnormalize_path(const path &p)
{
    if (p.empty())
        return L"";
    auto s = p.wstring();
    normalize_string(s);
    return s;
}

std::wstring wnormalize_path_windows(const path &p)
{
    if (p.empty())
        return L"";
    auto s = p.wstring();
    normalize_string_windows(s);
    return s;
}

String read_file_bytes_unchecked(const path &p, uintmax_t offset, uintmax_t count)
{
    ScopedFile ifile(p, "rb");

    String f;
    f.resize(count);
    ifile.seek(offset);
    ifile.read(&f[0], count);
    return f;
}

String read_file_bytes(const path &p, uintmax_t offset, uintmax_t count)
{
    error_code ec;
    if (!fs::exists(p, ec))
        throw std::runtime_error("File '" + p.u8string() + "' does not exist");
    return read_file_bytes_unchecked(p, offset, count);
}

String read_file_from_offset(const path &p, uintmax_t offset, uintmax_t max_size)
{
    error_code ec;
    if (!fs::exists(p, ec))
        throw std::runtime_error("File '" + p.u8string() + "' does not exist");

    auto sz = fs::file_size(p) - offset;
    if (sz > max_size)
        throw std::runtime_error("File " + p.u8string() + " is bigger than allowed limit (" + std::to_string(max_size) + " bytes)");

    return read_file_bytes_unchecked(p, offset, sz);
}

String read_file(const path &p, uintmax_t max_size)
{
    return read_file_from_offset(p, 0, max_size);
}

String read_file_without_bom(const path &p, uintmax_t max_size)
{
    static const std::vector<std::vector<uint8_t>> boms
    {
        // UTF-8
        { 0xEF, 0xBB, 0xBF, },

        // UTF-16 BE, LE
        { 0xFE, 0xFF, },
        { 0xFF, 0xFE, },

        // UTF-32 BE, LE
        { 0x00, 0x00, 0xFE, 0xFF, },
        { 0xFF, 0xFE, 0x00, 0x00, },

        // UTF-7
        { 0x2B, 0x2F, 0x76, 0x38 },
        { 0x2B, 0x2F, 0x76, 0x39 },
        { 0x2B, 0x2F, 0x76, 0x2B },
        { 0x2B, 0x2F, 0x76, 0x2F },
        { 0x2B, 0x2F, 0x76, 0x38, 0x2D },

        // UTF-1
        { 0xF7, 0x64, 0x4C, },

        // UTF-EBCDIC
        { 0xDD, 0x73, 0x66, 0x73 },

        // SCSU
        { 0x0E, 0xFE, 0xFF, },

        // BOCU-1
        { 0xFB, 0xEE, 0x28, },

        // GB-18030
        { 0x84, 0x31, 0x95, 0x33 },
    };

    static const auto max_len = std::max_element(boms.begin(), boms.end(),
        [](const auto &e1, const auto &e2) { return e1.size() < e2.size(); })->size();

    // read max bom length
    auto s = read_file_bytes(p, 0, max_len);

    for (auto &b : boms)
    {
        if (s.size() >= b.size() && memcmp(s.data(), b.data(), b.size()) == 0)
            return read_file_from_offset(p, b.size(), max_size);
    }

    return read_file(p, max_size);
}

Strings read_lines(const path &p)
{
    auto s = read_file(p);
    return split_lines(s);
}

static void write_file1(const path &p, const String &s, const char *mode)
{
    auto pp = p.parent_path();
    if (!pp.empty())
        fs::create_directories(pp);

    ScopedFile f(p, mode);
    fwrite(s.c_str(), s.size(), 1, f.getHandle());
}

void write_file(const path &p, const String &s)
{
    write_file1(p, s, "wb");
}

void write_file_if_different(const path &p, const String &s)
{
    error_code ec;
    if (fs::exists(p, ec))
    {
        auto s2 = read_file(p);
        if (s == s2)
            return;
    }
    write_file(p, s);
}

void prepend_file(const path &p, const String &s)
{
    auto s2 = read_file(p);
    write_file(p, s + s2);
}

void append_file(const path &p, const String &s)
{
    write_file1(p, s, "ab");
}

void copy_dir(const path &src, const path &dst)
{
    error_code ec;
    fs::create_directories(dst, ec);
    for (auto &f : fs::directory_iterator(src))
    {
        if (fs::is_directory(f))
            copy_dir(f, dst / f.path().filename());
        else
            copy_file(f, dst / f.path().filename(), fs::copy_options::overwrite_existing);
    }
}

void remove_files(const Files &files)
{
    for (auto &f : files)
        fs::remove(f);
}

void remove_files_like(const Files &files, const String &regex)
{
    remove_files(filter_files_like(files, regex));
}

void remove_files_like(const path &dir, const String &regex, bool recursive)
{
    remove_files_like(enumerate_files(dir, recursive), regex);
}

Files enumerate_files(const path &dir, bool recursive)
{
    Files files;
    error_code ec;
    if (!fs::exists(dir, ec))
        return files;
    if (recursive)
    {
        for (auto &f : fs::recursive_directory_iterator(dir))
        {
            if (!fs::is_regular_file(f))
                continue;
            files.insert(f);
        }
    }
    else
    {
        for (auto &f : fs::directory_iterator(dir))
        {
            if (!fs::is_regular_file(f))
                continue;
            files.insert(f);
        }
    }
    return files;
}

Files enumerate_files_like(const path &dir, const String &regex, bool recursive)
{
    return filter_files_like(enumerate_files(dir, recursive), regex);
}

Files enumerate_files_like(const Files &files, const String &regex)
{
    return filter_files_like(files, regex);
}

Files filter_files_like(const Files &files, const String &regex)
{
    Files fls;
    std::regex r(regex);
    for (auto &f : files)
    {
        if (!std::regex_match(f.filename().u8string(), r))
            continue;
        fls.insert(f);
    }
    return fls;
}

bool is_under_root(path p, const path &root_dir)
{
    if (p.empty())
        return false;
    error_code ec;
    if (fs::exists(p, ec))
        // Converts p, which must exist, to an absolute path
        // that has no symbolic link, dot, or dot-dot elements.
        p = fs::canonical(p);
    while (!p.empty() && p != p.root_path())
    {
        if (fs::equivalent(p, root_dir, ec))
            return true;
        p = p.parent_path();
    }
    return false;
}

bool compare_files(const path &fn1, const path &fn2)
{
    FileIterator fi({ fn1, fn2 });
    return fi.iterate([](const auto &bufs, auto sz)
    {
        if (memcmp(bufs[0].get().data(), bufs[1].get().data(), (size_t)sz) != 0)
            return false;
        return true;
    });
}

bool compare_dirs(const path &dir1, const path &dir2)
{
    auto traverse_dir = [](const auto &dir)
    {
        std::vector<path> files;
        error_code ec;
        if (fs::exists(dir, ec))
        {
            for (auto &f : fs::recursive_directory_iterator(dir))
            {
                if (!fs::is_regular_file(f))
                    continue;
                files.push_back(f);
            }
        }
        return files;
    };

    auto files1 = traverse_dir(dir1);
    auto files2 = traverse_dir(dir2);

    if (files1.empty())
        return false; // throw std::runtime_error("left side has no files");
    if (files2.empty())
        return false; // throw std::runtime_error("right side has no files");
    if (files1.size() != files2.size())
        return false; // throw std::runtime_error("different number of files");

    auto sz = files1.size();
    for (size_t i = 0; i < sz; i++)
    {
        if (!compare_files(files1[i], files2[i]))
            return false;
    }

    return true;
}

FileIterator::FileIterator(const FilesOrdered &fns)
{
    if (fns.empty())
        throw std::runtime_error("Provide at least one file");

    for (auto &f : fns)
    {
        File d;
        d.size = fs::file_size(f);
        d.ifile = std::make_unique<ScopedFile>(f, "rb");
        files.emplace_back(std::move(d));
    }
}

bool FileIterator::is_same_size() const
{
    auto sz = files.front().size;
    return std::all_of(files.begin(), files.end(),
        [sz](const auto &f) { return f.size == sz; });
}

bool FileIterator::is_same_read_size() const
{
    auto sz = files.front().read;
    return std::all_of(files.begin(), files.end(),
        [sz](const auto &f) { return f.read == sz; });
}

bool FileIterator::iterate(std::function<bool(const BuffersRef &, uint64_t)> f)
{
    if (!is_same_size())
        return false;

    BuffersRef buffers;
    for (auto &f : files)
    {
        f.buf.resize(buffer_size);
        buffers.emplace_back(f.buf);
    }

    while (std::none_of(files.begin(), files.end(),
        [](const auto &f) { return feof(f.ifile->getHandle()); }))
    {
        std::for_each(files.begin(), files.end(), [this](auto &f)
        {
            f.read = f.ifile->read((char *)&f.buf[0], buffer_size);
        });
        if (!is_same_read_size())
            return false;

        if (!f(buffers, files.front().read))
            return false;
    }
    return true;
}

path unique_path(const path &p)
{
    return boost::filesystem::unique_path(p.u8string()).wstring();
}

namespace primitives::filesystem
{

FILE *fopen(const path &p, const char *mode)
{
#ifdef _WIN32
    auto s = p.wstring();
    if (s.size() >= 255)
    {
        s = L"\\\\?\\" + s;
        boost::replace_all(s, L"/", L"\\");
    }
    return _wfopen(s.c_str(), path(mode).wstring().c_str());
#else
    return ::fopen(p.u8string().c_str(), mode);
#endif
}

FILE *fopen_checked(const path &p, const char *mode)
{
    auto f = fopen(p, mode);
    if (!f)
        throw std::runtime_error("Cannot open file: " + p.u8string() + ", mode = " + mode + ", errno = " + std::to_string(errno));
    return f;
}

void create(const path &p)
{
    // probably this is fixed in MS STL
    /*auto s = p.parent_path().u8string();
#ifdef _WIN32
    if (s.size() >= 255)
    {
        s = "\\\\?\\" + s;
        boost::replace_all(s, "/", "\\");
    }
#endif
    fs::create_directories(s);*/
    fs::create_directories(p.parent_path());
    fclose(fopen(p, "wb"));
}

}

ScopedFile::ScopedFile(const path &p, const char *mode)
{
    f = primitives::filesystem::fopen_checked(p, mode);
}

ScopedFile::~ScopedFile()
{
    if (f)
        fclose(f);
}

size_t ScopedFile::read(void *buf, size_t sz)
{
    return fread(buf, 1, sz, f);
}

void ScopedFile::seek(uintmax_t offset)
{
    fseek(f, offset, SEEK_SET);
}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2010, The Mineserver Project
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
 * Neither the name of the The Mineserver Project nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <string>
#include <map>

#include "constants.h"

std::map<std::string, std::string> defaultConf;
std::map<uint8, Drop> BLOCKDROPS;

void initConstants()
{
  // Init configuration
  defaultConf.insert(std::pair<std::string, std::string>("port", "25565"));
  defaultConf.insert(std::pair<std::string, std::string>("servername", "Minecraft server"));
  defaultConf.insert(std::pair<std::string, std::string>("mapdir", "testmap"));
  defaultConf.insert(std::pair<std::string, std::string>("userlimit", "20"));
  defaultConf.insert(std::pair<std::string, std::string>("map_release_time", "10"));
  defaultConf.insert(std::pair<std::string, std::string>("liquid_physics", "1"));
  defaultConf.insert(std::pair<std::string, std::string>("map_flatland", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("oreDensity", "24"));
  defaultConf.insert(std::pair<std::string, std::string>("seaLevel", "63"));
  defaultConf.insert(std::pair<std::string, std::string>("server_full_message",
                                                         "Server is currently full"));
  defaultConf.insert(std::pair<std::string, std::string>("default_kick_message",
                                                         "You have been kicked"));
  defaultConf.insert(std::pair<std::string, std::string>("wrong_protocol_message",
                                                         "Wrong client protocol"));

  // Block drops (10000 = 100%)

  // Blocks that always drop one item
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_STONE, Drop(BLOCK_COBBLESTONE, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_GRASS, Drop(BLOCK_DIRT, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_DIRT, Drop(BLOCK_DIRT, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_COBBLESTONE, Drop(BLOCK_COBBLESTONE, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_WOOD, Drop(BLOCK_WOOD, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_SAPLING, Drop(BLOCK_SAPLING, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_SAND, Drop(BLOCK_SAND, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_COAL_ORE, Drop(ITEM_COAL, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_IRON_ORE, Drop(ITEM_IRON_INGOT, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_GOLD_ORE, Drop(ITEM_GOLD_INGOT, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_DIAMOND_ORE, Drop(ITEM_DIAMOND, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_LOG, Drop(BLOCK_LOG, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_WOODEN_STAIRS, Drop(BLOCK_WOOD, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_RED_ROSE, Drop(BLOCK_RED_ROSE, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_YELLOW_FLOWER, Drop(BLOCK_RED_ROSE, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_BROWN_MUSHROOM, Drop(BLOCK_BROWN_MUSHROOM, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_RED_MUSHROOM, Drop(BLOCK_RED_MUSHROOM, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_LADDER, Drop(BLOCK_LADDER, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_CACTUS, Drop(BLOCK_CACTUS, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_REED, Drop(BLOCK_REED, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_PUMPKIN, Drop(BLOCK_PUMPKIN, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_TORCH, Drop(BLOCK_TORCH, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_REDSTONE_TORCH_OFF, Drop(BLOCK_REDSTONE_TORCH_OFF, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_REDSTONE_TORCH_ON, Drop(BLOCK_REDSTONE_TORCH_ON, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_LIGHTSTONE, Drop(ITEM_LIGHTSTONE_DUST, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_BRICK, Drop(ITEM_CLAY_BRICK, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_JUKEBOX, Drop(BLOCK_JUKEBOX, 10000, 1, true)));

  // Always drop but give more then one item
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_REDSTONE_ORE, Drop(ITEM_REDSTONE, 10000, 4, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_CLAY, Drop(ITEM_CLAY_BALLS, 10000, 4, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_FURNACE, Drop(BLOCK_COBBLESTONE, 10000, 3, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_BURNING_FURNACE, Drop(BLOCK_COBBLESTONE, 10000, 3, true)));

  // Blocks that drop items by chance
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_GRAVEL, Drop(ITEM_FLINT, 850, 1, false)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_LEAVES, Drop(BLOCK_SAPLING, 1200, 1, true)));

  /* BLOCK_SPONGE, BLOCK_GLASS, BLOCK_RED_CLOTH,
  BLOCK_ORANGE_CLOTH, BLOCK_YELLOW_CLOTH, BLOCK_LIME_CLOTH, BLOCK_GREEN_CLOTH,
  BLOCK_AQUA_GREEN_CLOTH, BLOCK_CYAN_CLOTH, BLOCK_BLUE_CLOTH, BLOCK_PURPLE_CLOTH,
  BLOCK_INDIGO_CLOTH, BLOCK_VIOLET_CLOTH, BLOCK_MAGENTA_CLOTH, BLOCK_PINK_CLOTH,
  BLOCK_BLACK_CLOTH, BLOCK_GRAY_CLOTH, BLOCK_WHITE_CLOTH, BLOCK_GOLD_BLOCK,
  BLOCK_IRON_BLOCK, BLOCK_DOUBLE_STEP, BLOCK_STEP, , BLOCK_TNT,
  BLOCK_BOOKSHELF, BLOCK_MOSSY_COBBLESTONE, BLOCK_OBSIDIAN,, BLOCK_FIRE,
  BLOCK_MOB_SPAWNER, BLOCK_CHEST, BLOCK_REDSTONE_WIRE,
  BLOCK_DIAMOND_ORE, BLOCK_DIAMOND_BLOCK, BLOCK_WORKBENCH, BLOCK_CROPS, BLOCK_SOIL,
  BLOCK_SIGN_POST, BLOCK_WOODEN_DOOR,
  , BLOCK_MINECART_TRACKS, BLOCK_COBBLESTONE_STAIRS, BLOCK_WALL_SIGN,
  BLOCK_LEVER, BLOCK_STONE_PRESSURE_PLATE, BLOCK_IRON_DOOR, BLOCK_WOODEN_PRESSURE_PLATE,

  , BLOCK_STONE_BUTTON, BLOCK_SNOW, BLOCK_ICE, BLOCK_SNOW_BLOCK,
  , BLOCK_FENCE,
  BLOCK_NETHERSTONE, BLOCK_SLOW_SAND, BLOCK_PORTAL, BLOCK_JACK_O_LANTERN
*/
  // Blocks that drop nothing
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_TNT, Drop(BLOCK_TNT, 10000, 0, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_GLASS, Drop(BLOCK_GLASS, 10000, 0, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_MOB_SPAWNER, Drop(BLOCK_MOB_SPAWNER, 10000, 0, true)));

}
<commit_msg>Added more blocks<commit_after>/*
   Copyright (c) 2010, The Mineserver Project
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
 * Neither the name of the The Mineserver Project nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <string>
#include <map>

#include "constants.h"

std::map<std::string, std::string> defaultConf;
std::map<uint8, Drop> BLOCKDROPS;

void initConstants()
{
  // Init configuration
  defaultConf.insert(std::pair<std::string, std::string>("port", "25565"));
  defaultConf.insert(std::pair<std::string, std::string>("servername", "Minecraft server"));
  defaultConf.insert(std::pair<std::string, std::string>("mapdir", "testmap"));
  defaultConf.insert(std::pair<std::string, std::string>("userlimit", "20"));
  defaultConf.insert(std::pair<std::string, std::string>("map_release_time", "10"));
  defaultConf.insert(std::pair<std::string, std::string>("liquid_physics", "1"));
  defaultConf.insert(std::pair<std::string, std::string>("map_flatland", "false"));
  defaultConf.insert(std::pair<std::string, std::string>("oreDensity", "24"));
  defaultConf.insert(std::pair<std::string, std::string>("seaLevel", "63"));
  defaultConf.insert(std::pair<std::string, std::string>("server_full_message",
                                                         "Server is currently full"));
  defaultConf.insert(std::pair<std::string, std::string>("default_kick_message",
                                                         "You have been kicked"));
  defaultConf.insert(std::pair<std::string, std::string>("wrong_protocol_message",
                                                         "Wrong client protocol"));

  // Block drops (10000 = 100%)

  // Blocks that always drop one item
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_STONE, Drop(BLOCK_COBBLESTONE, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_GRASS, Drop(BLOCK_DIRT, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_DIRT, Drop(BLOCK_DIRT, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_COBBLESTONE, Drop(BLOCK_COBBLESTONE, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_WOOD, Drop(BLOCK_WOOD, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_SAPLING, Drop(BLOCK_SAPLING, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_SAND, Drop(BLOCK_SAND, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_COAL_ORE, Drop(ITEM_COAL, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_IRON_ORE, Drop(ITEM_IRON_INGOT, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_GOLD_ORE, Drop(ITEM_GOLD_INGOT, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_DIAMOND_ORE, Drop(ITEM_DIAMOND, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_LOG, Drop(BLOCK_LOG, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_WOODEN_STAIRS, Drop(BLOCK_WOOD, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_RED_ROSE, Drop(BLOCK_RED_ROSE, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_YELLOW_FLOWER, Drop(BLOCK_RED_ROSE, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_BROWN_MUSHROOM, Drop(BLOCK_BROWN_MUSHROOM, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_RED_MUSHROOM, Drop(BLOCK_RED_MUSHROOM, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_LADDER, Drop(BLOCK_LADDER, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_CACTUS, Drop(BLOCK_CACTUS, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_REED, Drop(BLOCK_REED, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_PUMPKIN, Drop(BLOCK_PUMPKIN, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_TORCH, Drop(BLOCK_TORCH, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_REDSTONE_TORCH_OFF, Drop(BLOCK_REDSTONE_TORCH_OFF, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_REDSTONE_TORCH_ON, Drop(BLOCK_REDSTONE_TORCH_ON, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_LIGHTSTONE, Drop(ITEM_LIGHTSTONE_DUST, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_BRICK, Drop(ITEM_CLAY_BRICK, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_JUKEBOX, Drop(BLOCK_JUKEBOX, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_NETHERSTONE, Drop(BLOCK_NETHERSTONE, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_SLOW_SAND, Drop(BLOCK_SLOW_SAND, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_JACK_O_LANTERN, Drop(BLOCK_JACK_O_LANTERN, 10000, 1, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_MINECART_TRACKS, Drop(BLOCK_MINECART_TRACKS, 10000, 1, true)));

  // Always drop but give more then one item
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_REDSTONE_ORE, Drop(ITEM_REDSTONE, 10000, 4, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_CLAY, Drop(ITEM_CLAY_BALLS, 10000, 4, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_FURNACE, Drop(BLOCK_COBBLESTONE, 10000, 3, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_BURNING_FURNACE, Drop(BLOCK_COBBLESTONE, 10000, 3, true)));

  // Blocks that drop items by chance
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_GRAVEL, Drop(ITEM_FLINT, 850, 1, false)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_LEAVES, Drop(BLOCK_SAPLING, 1200, 1, true)));

  /* BLOCK_SPONGE, BLOCK_GLASS, BLOCK_RED_CLOTH,
  BLOCK_ORANGE_CLOTH, BLOCK_YELLOW_CLOTH, BLOCK_LIME_CLOTH, BLOCK_GREEN_CLOTH,
  BLOCK_AQUA_GREEN_CLOTH, BLOCK_CYAN_CLOTH, BLOCK_BLUE_CLOTH, BLOCK_PURPLE_CLOTH,
  BLOCK_INDIGO_CLOTH, BLOCK_VIOLET_CLOTH, BLOCK_MAGENTA_CLOTH, BLOCK_PINK_CLOTH,
  BLOCK_BLACK_CLOTH, BLOCK_GRAY_CLOTH, BLOCK_WHITE_CLOTH, BLOCK_GOLD_BLOCK,
  BLOCK_IRON_BLOCK, BLOCK_DOUBLE_STEP, BLOCK_STEP, , BLOCK_TNT,
  BLOCK_BOOKSHELF, BLOCK_MOSSY_COBBLESTONE, BLOCK_OBSIDIAN,, BLOCK_FIRE,
  BLOCK_MOB_SPAWNER, BLOCK_CHEST, BLOCK_REDSTONE_WIRE,
  BLOCK_DIAMOND_ORE, BLOCK_DIAMOND_BLOCK, BLOCK_WORKBENCH, BLOCK_CROPS, BLOCK_SOIL,
  BLOCK_SIGN_POST, BLOCK_WOODEN_DOOR,
  , , BLOCK_COBBLESTONE_STAIRS, BLOCK_WALL_SIGN,
  BLOCK_LEVER, BLOCK_STONE_PRESSURE_PLATE, BLOCK_IRON_DOOR, BLOCK_WOODEN_PRESSURE_PLATE,
  , BLOCK_STONE_BUTTON, BLOCK_SNOW, BLOCK_ICE, BLOCK_SNOW_BLOCK,
  , BLOCK_FENCE,
  , , BLOCK_PORTAL,
*/
  // Blocks that drop nothing
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_TNT, Drop(BLOCK_TNT, 10000, 0, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_GLASS, Drop(BLOCK_GLASS, 10000, 0, true)));
  BLOCKDROPS.insert(std::pair<uint8, Drop>(BLOCK_MOB_SPAWNER, Drop(BLOCK_MOB_SPAWNER, 10000, 0, true)));

}
<|endoftext|>