<commit_before>#include "video.hpp"
#include "image_resource.hpp"

#include <allegro5/allegro_opengl.h>

using namespace Ludic;
using namespace std;

//////////////////////////////////////////////////////////////

Video::Video() : backGroundColor( Color ( 0, 0, 0 ) ) {

	// Recebera as dimensoes da resoulucao minima
	int w, h;

	// Recebemos a resoulucao 0 ou minima
	Video::getResolution( Video::sizeResolutions() - 1, w, h );

	// Incializamos o display
	int aux = ALLEGRO_WINDOWED;

#if UNIX
	aux = aux | ALLEGRO_OPENGL;
#endif

	// Setamos as flags do display
	al_set_new_display_flags( aux );

	// Criamos o display
	display = al_create_display( w, h );

	// Setamos o allegro para usar bitmao na memoria de video.
	// Isso permite que a mesma utiliza aceleracao por hardware
	al_set_new_bitmap_flags( ALLEGRO_VIDEO_BITMAP );

	if( display == nullptr )
		throw Ludic::Exception( "* Failed to initialize ALLEGRO_DISPLAY." );

}

//////////////////////////////////////////////////////////////

Video::Video( unsigned int width, unsigned int height, DisplayMode mode ) :
									backGroundColor( Color ( 0, 0, 0 ) ) {

	// Incializamos o display
	int aux = ( int ) mode;

#if LINUX
	aux = aux | ALLEGRO_OPENGL;
	cout << "open" << endl;
#endif

	// Setamos as flags do display
	al_set_new_display_flags( aux );

	// Criamos o display
	display = al_create_display( width, height );

	// Setamos o allegro para usar bitmao na memoria de video.
	// Isso permite que a mesma utiliza aceleracao por hardware
	al_set_new_bitmap_flags( ALLEGRO_VIDEO_BITMAP );

	if( display == nullptr )
		throw Ludic::Exception( "* Failed to initialize ALLEGRO_DISPLAY." );

}

//////////////////////////////////////////////////////////////

Video::~Video() {
	// Destruimos o display da Allegro
	if( display != nullptr )
		al_destroy_display ( display );
}

//////////////////////////////////////////////////////////////

void Video::disableScreenSaver ( bool disable ) {
	al_inhibit_screensaver( disable );
}

//////////////////////////////////////////////////////////////

Video::operator ALLEGRO_DISPLAY * () {
	return display;
}

//////////////////////////////////////////////////////////////

int Video::getHeight() const {
	return al_get_display_height ( display );
}

//////////////////////////////////////////////////////////////

int Video::getWidth() const {
	return al_get_display_width ( display );
}

//////////////////////////////////////////////////////////////

void Video::setBackgroundColor ( const Color& color ) {
	backGroundColor = color;
}

//////////////////////////////////////////////////////////////

void Video::setFitToScreen ( bool fit ) {
	al_set_display_flag ( display, ALLEGRO_FULLSCREEN_WINDOW, fit );
}

//////////////////////////////////////////////////////////////

void Video::setIcon( const String& fileName ) {

	// Criamos o image resource
	ImageResource* img;

	// Carregamos o arquivo de imagem
	img = ImageResource::loadImageResource( fileName.c_str() );

	// Setamos a imagem do display
	if( img )
		al_set_display_icon( display, *img );

}

//////////////////////////////////////////////////////////////

void Video::setPosition ( int pos_x, int pos_y ) {
	al_set_window_position ( display, pos_x, pos_y );
}

//////////////////////////////////////////////////////////////

Vector2D Video::getPosition () {

	// Variaveis auxiliar
	int x, y;

	// Pegamos a posicao do display
	al_get_window_position ( display, &x, &y );

	// Retornamos o vetor com a posicao
	return Vector2D( x, y );
}

//////////////////////////////////////////////////////////////

void Video::setTitle ( const String& title ) {
	al_set_window_title ( display, title.c_str() );
}

//////////////////////////////////////////////////////////////

void Video::refresh() {

	// Atualizamos a tela
	al_flip_display();

	// Limpamos o backbuffer
	al_clear_to_color( backGroundColor );

}

//////////////////////////////////////////////////////////////

void Video::refreshRegion ( const Vector2D& xy, int width, int height ) {

	// Atualiza apenas uma região
	al_update_display_region ( xy.getX(), xy.getY(), width, height );

	// Limpamos o backbuffer
	al_clear_to_color( backGroundColor );

}

//////////////////////////////////////////////////////////////

int Video::sizeResolutions() {
	return al_get_num_display_modes();
}

//////////////////////////////////////////////////////////////

void Video::getResolution( unsigned int index, int& width, int& height ) {

	if( index >= ( unsigned int ) al_get_num_display_modes() ) {

		String str( "Invalid value of index in method getResolution()." );
		std::cout << str << std::endl;

		return;
	}

	ALLEGRO_DISPLAY_MODE disp_data;

	//Capturamos as informacoes da tela de acordo com a resolucao
	// escolhida por index
	al_get_display_mode( index, &disp_data );

	width  = disp_data.width;
	height = disp_data.height;

}

//////////////////////////////////////////////////////////////

void Video::setAsTarger() {
	// Tiramos o display de foco para que possamos deleta-lo
	al_set_target_backbuffer( display );
}

//////////////////////////////////////////////////////////////
<commit_msg>Teste classe Video para usar antialiasing.<commit_after>#include "video.hpp"
#include "image_resource.hpp"

#include <allegro5/allegro_opengl.h>

using namespace Ludic;
using namespace std;

//////////////////////////////////////////////////////////////

Video::Video() : backGroundColor( Color ( 0, 0, 0 ) )
{

	// Recebera as dimensoes da resoulucao minima
	int w, h;

	// Recebemos a resoulucao 0 ou minima
	Video::getResolution( Video::sizeResolutions() - 1, w, h );

	// Incializamos o display
	int aux = ALLEGRO_WINDOWED;

#if UNIX
	aux = aux | ALLEGRO_OPENGL;
#endif

	// Setamos as flags do display
	al_set_new_display_flags( aux );

	al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_REQUIRE);
	// al_set_new_display_option(ALLEGRO_SAMPLES, #, ALLEGRO_SUGGEST);

	// Criamos o display
	display = al_create_display( w, h );

	// Setamos o allegro para usar bitmao na memoria de video.
	// Isso permite que a mesma utiliza aceleracao por hardware
	al_set_new_bitmap_flags( ALLEGRO_VIDEO_BITMAP );

	if( display == nullptr )
		throw Ludic::Exception( "* Failed to initialize ALLEGRO_DISPLAY." );

}

//////////////////////////////////////////////////////////////

Video::Video( unsigned int width, unsigned int height, DisplayMode mode ) :
	backGroundColor( Color ( 0, 0, 0 ) )
{

	// Incializamos o display
	int aux = ( int ) mode;

#if LINUX
	aux = aux | ALLEGRO_OPENGL;
	cout << "open" << endl;
#endif

	// Setamos as flags do display
	al_set_new_display_flags( aux );

	// Criamos o display
	display = al_create_display( width, height );

	// Setamos o allegro para usar bitmao na memoria de video.
	// Isso permite que a mesma utiliza aceleracao por hardware
	al_set_new_bitmap_flags( ALLEGRO_VIDEO_BITMAP );

	if( display == nullptr )
		throw Ludic::Exception( "* Failed to initialize ALLEGRO_DISPLAY." );

}

//////////////////////////////////////////////////////////////

Video::~Video()
{
	// Destruimos o display da Allegro
	if( display != nullptr )
		al_destroy_display ( display );
}

//////////////////////////////////////////////////////////////

void Video::disableScreenSaver ( bool disable )
{
	al_inhibit_screensaver( disable );
}

//////////////////////////////////////////////////////////////

Video::operator ALLEGRO_DISPLAY * ()
{
	return display;
}

//////////////////////////////////////////////////////////////

int Video::getHeight() const
{
	return al_get_display_height ( display );
}

//////////////////////////////////////////////////////////////

int Video::getWidth() const
{
	return al_get_display_width ( display );
}

//////////////////////////////////////////////////////////////

void Video::setBackgroundColor ( const Color& color )
{
	backGroundColor = color;
}

//////////////////////////////////////////////////////////////

void Video::setFitToScreen ( bool fit )
{
	al_set_display_flag ( display, ALLEGRO_FULLSCREEN_WINDOW, fit );
}

//////////////////////////////////////////////////////////////

void Video::setIcon( const String& fileName )
{

	// Criamos o image resource
	ImageResource* img;

	// Carregamos o arquivo de imagem
	img = ImageResource::loadImageResource( fileName.c_str() );

	// Setamos a imagem do display
	if( img )
		al_set_display_icon( display, *img );

}

//////////////////////////////////////////////////////////////

void Video::setPosition ( int pos_x, int pos_y )
{
	al_set_window_position ( display, pos_x, pos_y );
}

//////////////////////////////////////////////////////////////

Vector2D Video::getPosition ()
{

	// Variaveis auxiliar
	int x, y;

	// Pegamos a posicao do display
	al_get_window_position ( display, &x, &y );

	// Retornamos o vetor com a posicao
	return Vector2D( x, y );
}

//////////////////////////////////////////////////////////////

void Video::setTitle ( const String& title )
{
	al_set_window_title ( display, title.c_str() );
}

//////////////////////////////////////////////////////////////

void Video::refresh()
{

	// Atualizamos a tela
	al_flip_display();

	// Limpamos o backbuffer
	al_clear_to_color( backGroundColor );

}

//////////////////////////////////////////////////////////////

void Video::refreshRegion ( const Vector2D& xy, int width, int height )
{

	// Atualiza apenas uma região
	al_update_display_region ( xy.getX(), xy.getY(), width, height );

	// Limpamos o backbuffer
	al_clear_to_color( backGroundColor );

}

//////////////////////////////////////////////////////////////

int Video::sizeResolutions()
{
	return al_get_num_display_modes();
}

//////////////////////////////////////////////////////////////

void Video::getResolution( unsigned int index, int& width, int& height )
{

	if( index >= ( unsigned int ) al_get_num_display_modes() ) {

		String str( "Invalid value of index in method getResolution()." );
		std::cout << str << std::endl;

		return;
	}

	ALLEGRO_DISPLAY_MODE disp_data;

	//Capturamos as informacoes da tela de acordo com a resolucao
	// escolhida por index
	al_get_display_mode( index, &disp_data );

	width  = disp_data.width;
	height = disp_data.height;

}

//////////////////////////////////////////////////////////////

void Video::setAsTarger()
{
	// Tiramos o display de foco para que possamos deleta-lo
	al_set_target_backbuffer( display );
}

//////////////////////////////////////////////////////////////
<|endoftext|>


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

#include <limits>

#include "native_client/src/shared/ppapi_proxy/browser_globals.h"
#include "native_client/src/shared/ppapi_proxy/object_serialize.h"
#include "native_client/src/shared/ppapi_proxy/utility.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/cpp/var.h"
#include "srpcgen/ppb_rpc.h"

using ppapi_proxy::DebugPrintf;
using ppapi_proxy::PPBNetAddressPrivateInterface;
using ppapi_proxy::SerializeTo;
using ppapi_proxy::kMaxReturnVarSize;

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_AreEqual(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr1_bytes, char* addr1,
    nacl_abi_size_t addr2_bytes, char* addr2,
    // output
    int32_t* equals) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr1_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }
  if (addr2_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PP_Bool pp_equals =
      PPBNetAddressPrivateInterface()->AreEqual(
          reinterpret_cast<PP_NetAddress_Private*>(addr1),
          reinterpret_cast<PP_NetAddress_Private*>(addr2));

  DebugPrintf("PPB_NetAddress_Private::AreEqual: pp_equals=%d\n",
              pp_equals);

  *equals = (pp_equals == PP_TRUE);
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_AreHostsEqual(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr1_bytes, char* addr1,
    nacl_abi_size_t addr2_bytes, char* addr2,
    // output
    int32_t* equals) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr1_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }
  if (addr2_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PP_Bool pp_equals =
      PPBNetAddressPrivateInterface()->AreHostsEqual(
          reinterpret_cast<PP_NetAddress_Private*>(addr1),
          reinterpret_cast<PP_NetAddress_Private*>(addr2));

  DebugPrintf("PPB_NetAddress_Private::AreHostsEqual: pp_equals=%d\n",
              pp_equals);

  *equals = (pp_equals == PP_TRUE);
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_Describe(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    int32_t module,
    nacl_abi_size_t addr_bytes, char* addr,
    int32_t include_port,
    // output
    nacl_abi_size_t* description_bytes, char* description) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }
  if (include_port != PP_FALSE && include_port != PP_TRUE)
    return;
  if (*description_bytes != static_cast<nacl_abi_size_t>(kMaxReturnVarSize))
    return;

  PP_Var pp_address = PPBNetAddressPrivateInterface()->Describe(
      module,
      reinterpret_cast<PP_NetAddress_Private*>(addr),
      static_cast<PP_Bool>(include_port));
  pp::Var address(pp::PASS_REF, pp_address);

  if (!SerializeTo(&address.pp_var(), description, description_bytes))
    return;

  DebugPrintf("PPB_NetAddress_Private::Describe: description=%s\n",
              address.AsString().c_str());
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_ReplacePort(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t src_addr_bytes, char* src_addr,
    int32_t port,
    // output
    nacl_abi_size_t* dst_addr_bytes, char* dst_addr,
    int32_t* success) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (src_addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }
  if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    return;
  if (*dst_addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PP_Bool pp_success = PPBNetAddressPrivateInterface()->ReplacePort(
      reinterpret_cast<PP_NetAddress_Private*>(src_addr),
      static_cast<uint16_t>(port),
      reinterpret_cast<PP_NetAddress_Private*>(dst_addr));

  DebugPrintf("PPB_NetAddress_Private::ReplacePort: pp_success=%d\n",
              pp_success);

  *success = (pp_success == PP_TRUE);
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetAnyAddress(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    int32_t is_ipv6,
    // output
    nacl_abi_size_t* addr_bytes, char* addr) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (is_ipv6 != PP_FALSE && is_ipv6 != PP_TRUE)
    return;
  if (*addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PPBNetAddressPrivateInterface()->GetAnyAddress(
      static_cast<PP_Bool>(is_ipv6),
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::GetAnyAddress\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetFamily(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr_bytes, char* addr,
    // output
    int32_t* addr_family) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  *addr_family = static_cast<int32_t>(
      PPBNetAddressPrivateInterface()->GetFamily(
          reinterpret_cast<PP_NetAddress_Private*>(addr)));

  DebugPrintf("PPB_NetAddress_Private::GetFamily\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetPort(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr_bytes, char* addr,
    // output
    int32_t* port) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  *port = PPBNetAddressPrivateInterface()->GetPort(
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::GetPort\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetAddress(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr_bytes, char* addr,
    // output
    nacl_abi_size_t* address_bytes, char* address,
    int32_t* success) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PP_Bool pp_success = PPBNetAddressPrivateInterface()->GetAddress(
      reinterpret_cast<PP_NetAddress_Private*>(addr),
      address, static_cast<uint16_t>(*address_bytes));

  DebugPrintf("PPB_NetAddress_Private::GetAddress: pp_success=%d\n",
              pp_success);

  *success = (pp_success == PP_TRUE);
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetScopeID(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr_bytes, char* addr,
    // output
    int32_t* scope_id) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  *scope_id = PPBNetAddressPrivateInterface()->GetScopeID(
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::GetScopeID\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void
PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_CreateFromIPv4Address(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t ip_bytes, char* ip,
    int32_t port,
    // output
    nacl_abi_size_t* addr_bytes, char* addr) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (ip_bytes != static_cast<nacl_abi_size_t>(4))
    return;
  if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    return;
  if (*addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PPBNetAddressPrivateInterface()->CreateFromIPv4Address(
      reinterpret_cast<uint8_t*>(addr), static_cast<uint16_t>(port),
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::CreateFromIPv4Address\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void
PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_CreateFromIPv6Address(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t ip_bytes, char* ip,
    int32_t scope_id,
    int32_t port,
    // output
    nacl_abi_size_t* addr_bytes, char* addr) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (ip_bytes != static_cast<nacl_abi_size_t>(16))
    return;
  if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    return;
  if (*addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PPBNetAddressPrivateInterface()->CreateFromIPv6Address(
      reinterpret_cast<uint8_t*>(addr), static_cast<uint32_t>(scope_id),
      static_cast<uint16_t>(port),
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::CreateFromIPv6Address\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}
<commit_msg>Fix warning-as-error for NaCl integration BUG=none TEST=trybots Review URL: https://chromiumcodereview.appspot.com/9837094<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SRPC-abstraction wrappers around PPB_NetAddress_Private functions.

#include <limits>

#include "native_client/src/shared/ppapi_proxy/browser_globals.h"
#include "native_client/src/shared/ppapi_proxy/object_serialize.h"
#include "native_client/src/shared/ppapi_proxy/utility.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/cpp/var.h"
#include "srpcgen/ppb_rpc.h"

using ppapi_proxy::DebugPrintf;
using ppapi_proxy::PPBNetAddressPrivateInterface;
using ppapi_proxy::SerializeTo;
using ppapi_proxy::kMaxReturnVarSize;

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_AreEqual(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr1_bytes, char* addr1,
    nacl_abi_size_t addr2_bytes, char* addr2,
    // output
    int32_t* equals) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr1_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }
  if (addr2_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PP_Bool pp_equals =
      PPBNetAddressPrivateInterface()->AreEqual(
          reinterpret_cast<PP_NetAddress_Private*>(addr1),
          reinterpret_cast<PP_NetAddress_Private*>(addr2));

  DebugPrintf("PPB_NetAddress_Private::AreEqual: pp_equals=%d\n",
              pp_equals);

  *equals = (pp_equals == PP_TRUE);
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_AreHostsEqual(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr1_bytes, char* addr1,
    nacl_abi_size_t addr2_bytes, char* addr2,
    // output
    int32_t* equals) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr1_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }
  if (addr2_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PP_Bool pp_equals =
      PPBNetAddressPrivateInterface()->AreHostsEqual(
          reinterpret_cast<PP_NetAddress_Private*>(addr1),
          reinterpret_cast<PP_NetAddress_Private*>(addr2));

  DebugPrintf("PPB_NetAddress_Private::AreHostsEqual: pp_equals=%d\n",
              pp_equals);

  *equals = (pp_equals == PP_TRUE);
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_Describe(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    int32_t module,
    nacl_abi_size_t addr_bytes, char* addr,
    int32_t include_port,
    // output
    nacl_abi_size_t* description_bytes, char* description) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }
  if (include_port != PP_FALSE && include_port != PP_TRUE)
    return;
  if (*description_bytes != static_cast<nacl_abi_size_t>(kMaxReturnVarSize))
    return;

  PP_Var pp_address = PPBNetAddressPrivateInterface()->Describe(
      module,
      reinterpret_cast<PP_NetAddress_Private*>(addr),
      static_cast<PP_Bool>(include_port));
  pp::Var address(pp::PASS_REF, pp_address);

  if (!SerializeTo(&address.pp_var(), description, description_bytes))
    return;

  DebugPrintf("PPB_NetAddress_Private::Describe: description=%s\n",
              address.AsString().c_str());
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_ReplacePort(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t src_addr_bytes, char* src_addr,
    int32_t port,
    // output
    nacl_abi_size_t* dst_addr_bytes, char* dst_addr,
    int32_t* success) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (src_addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }
  if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    return;
  if (*dst_addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PP_Bool pp_success = PPBNetAddressPrivateInterface()->ReplacePort(
      reinterpret_cast<PP_NetAddress_Private*>(src_addr),
      static_cast<uint16_t>(port),
      reinterpret_cast<PP_NetAddress_Private*>(dst_addr));

  DebugPrintf("PPB_NetAddress_Private::ReplacePort: pp_success=%d\n",
              pp_success);

  *success = (pp_success == PP_TRUE);
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetAnyAddress(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    int32_t is_ipv6,
    // output
    nacl_abi_size_t* addr_bytes, char* addr) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (is_ipv6 != PP_FALSE && is_ipv6 != PP_TRUE)
    return;
  if (*addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PPBNetAddressPrivateInterface()->GetAnyAddress(
      static_cast<PP_Bool>(is_ipv6),
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::GetAnyAddress\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetFamily(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr_bytes, char* addr,
    // output
    int32_t* addr_family) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  *addr_family = static_cast<int32_t>(
      PPBNetAddressPrivateInterface()->GetFamily(
          reinterpret_cast<PP_NetAddress_Private*>(addr)));

  DebugPrintf("PPB_NetAddress_Private::GetFamily\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetPort(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr_bytes, char* addr,
    // output
    int32_t* port) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  *port = PPBNetAddressPrivateInterface()->GetPort(
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::GetPort\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetAddress(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr_bytes, char* addr,
    // output
    nacl_abi_size_t* address_bytes, char* address,
    int32_t* success) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PP_Bool pp_success = PPBNetAddressPrivateInterface()->GetAddress(
      reinterpret_cast<PP_NetAddress_Private*>(addr),
      address, static_cast<uint16_t>(*address_bytes));

  DebugPrintf("PPB_NetAddress_Private::GetAddress: pp_success=%d\n",
              pp_success);

  *success = (pp_success == PP_TRUE);
  rpc->result = NACL_SRPC_RESULT_OK;
}

void PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_GetScopeID(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t addr_bytes, char* addr,
    // output
    int32_t* scope_id) {
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  *scope_id = PPBNetAddressPrivateInterface()->GetScopeID(
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::GetScopeID\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void
PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_CreateFromIPv4Address(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t ip_bytes, char* ip,
    int32_t port,
    // output
    nacl_abi_size_t* addr_bytes, char* addr) {
  UNREFERENCED_PARAMETER(ip);
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (ip_bytes != static_cast<nacl_abi_size_t>(4))
    return;
  if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    return;
  if (*addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PPBNetAddressPrivateInterface()->CreateFromIPv4Address(
      reinterpret_cast<uint8_t*>(addr), static_cast<uint16_t>(port),
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::CreateFromIPv4Address\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}

void
PpbNetAddressPrivateRpcServer::PPB_NetAddress_Private_CreateFromIPv6Address(
    NaClSrpcRpc* rpc,
    NaClSrpcClosure* done,
    // input
    nacl_abi_size_t ip_bytes, char* ip,
    int32_t scope_id,
    int32_t port,
    // output
    nacl_abi_size_t* addr_bytes, char* addr) {
  UNREFERENCED_PARAMETER(ip);
  NaClSrpcClosureRunner runner(done);
  rpc->result = NACL_SRPC_RESULT_APP_ERROR;

  if (ip_bytes != static_cast<nacl_abi_size_t>(16))
    return;
  if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    return;
  if (*addr_bytes !=
      static_cast<nacl_abi_size_t>(sizeof(PP_NetAddress_Private))) {
    return;
  }

  PPBNetAddressPrivateInterface()->CreateFromIPv6Address(
      reinterpret_cast<uint8_t*>(addr), static_cast<uint32_t>(scope_id),
      static_cast<uint16_t>(port),
      reinterpret_cast<PP_NetAddress_Private*>(addr));

  DebugPrintf("PPB_NetAddress_Private::CreateFromIPv6Address\n");

  rpc->result = NACL_SRPC_RESULT_OK;
}
<|endoftext|>


<commit_before>/*
 * <one line to give the library's name and an idea of what it does.>
 * Copyright 2013  David Edmundson <d.edmundson@lboro.ac.uk>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License or (at your option) version 3 or any later version
 * accepted by the membership of KDE e.V. (or its successor approved
 * by the membership of KDE e.V.), which shall act as a proxy
 * defined in Section 14 of version 3 of the license.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "metacontact.h"
#include "global.h"
#include <QSharedData>

namespace KPeople {
class MetaContactData : public QSharedData
{
public:
    QString personId;
    KABC::Addressee::Map contacts;
    KABC::Addressee personAddressee;
};
}

using namespace KPeople;

MetaContact::MetaContact():
d(new MetaContactData)
{

}

MetaContact::MetaContact(const QString& personId, const KABC::Addressee::Map& contacts):
d (new MetaContactData)
{
    d->personId = personId;
    d->contacts = contacts;
    reload();
}

MetaContact::MetaContact(const QString &contactId, const KABC::Addressee &contact):
d (new MetaContactData)
{
    d->personId = contactId;
    d->contacts[contactId] = contact;
    reload();
}

MetaContact::MetaContact(const MetaContact &other)
:d (other.d)
{

}

MetaContact& MetaContact::operator=( const MetaContact &other )
{
  if ( this != &other )
    d = other.d;

  return *this;
}

MetaContact::~MetaContact()
{

}

QString MetaContact::id() const
{
    return d->personId;
}

bool MetaContact::isValid() const
{
    return !d->contacts.isEmpty();
}

KABC::Addressee MetaContact::contact(const QString& contactId)
{
    return d->contacts[contactId];
}

KABC::AddresseeList MetaContact::contacts() const
{
    return d->contacts.values();
}

const KABC::Addressee& MetaContact::personAddressee() const
{
    return d->personAddressee;
}

void MetaContact::updateContact(const QString& contactId, const KABC::Addressee& contact)
{
    d->contacts[contactId] = contact;
    reload();
}

void MetaContact::removeContact(const QString& contactId)
{
    d->contacts.remove(contactId);
    reload();
}

void MetaContact::reload()
{
    //always favour the first item

    //TODO - long term goal: resource priority - local vcards for "people" trumps anything else. So we can set a preferred name etc.

    //Optimisation, if only one contact use that for everything
    if (d->contacts.size() == 1) {
        d->personAddressee = d->contacts.values().first();
        return;
    }

    d->personAddressee = KABC::Addressee();

    Q_FOREACH(const KABC::Addressee &contact, d->contacts.values()) {
        //set items with multiple cardinality
        Q_FOREACH(const KABC::Address &address, contact.addresses()) {
            d->personAddressee.insertAddress(address);
        }
        Q_FOREACH(const QString &category, contact.categories()) {
            d->personAddressee.insertCategory(category);
        }
        Q_FOREACH(const QString &email, contact.emails()) {
            d->personAddressee.insertEmail(email);
        }
        Q_FOREACH(const KABC::Key &key, contact.keys()) {
            d->personAddressee.insertKey(key);
        }
        Q_FOREACH(const KABC::PhoneNumber &phoneNumber, contact.phoneNumbers()) {
            d->personAddressee.insertPhoneNumber(phoneNumber);
        }
        //TODO customs

        //set items with single cardinality
        if (d->personAddressee.name().isEmpty() && !contact.name().isEmpty()) {
            d->personAddressee.setName(contact.name());
        }

        if (d->personAddressee.formattedName().isEmpty() && !contact.formattedName().isEmpty()) {
            d->personAddressee.setFormattedName(contact.formattedName());
        }

        //TODO all the remaining items below.

        //Maybe we can use a macro?
        if (d->personAddressee.familyName().isEmpty() && !contact.familyName().isEmpty()) {
            d->personAddressee.setFamilyName(contact.familyName());
        }

        if (d->personAddressee.givenName().isEmpty() && !contact.givenName().isEmpty()) {
            d->personAddressee.setGivenName(contact.givenName());
        }

        if (d->personAddressee.additionalName().isEmpty() && !contact.additionalName().isEmpty()) {
            d->personAddressee.setAdditionalName(contact.additionalName());
        }

        if (d->personAddressee.prefix().isEmpty() && !contact.prefix().isEmpty()) {
            d->personAddressee.setPrefix(contact.prefix());
        }

        if (d->personAddressee.suffix().isEmpty() && !contact.suffix().isEmpty()) {
            d->personAddressee.setSuffix(contact.suffix());
        }

        if (d->personAddressee.nickName().isEmpty() && !contact.nickName().isEmpty()) {
            d->personAddressee.setNickName(contact.nickName());
        }

//TODO merge Mck18's magic code that mixes years and dates
//         void setBirthday( const QDateTime &birthday );

        if (d->personAddressee.birthday().isNull() && !contact.birthday().isNull()) {
            d->personAddressee.setBirthday(contact.birthday());
        }

        if (d->personAddressee.mailer().isEmpty() && !contact.mailer().isEmpty()) {
            d->personAddressee.setMailer(contact.mailer());
        }

        if (!d->personAddressee.timeZone().isValid() && contact.timeZone().isValid()) {
            d->personAddressee.setTimeZone(contact.timeZone());
        }

        if (!d->personAddressee.geo().isValid() && contact.timeZone().isValid()) {
            d->personAddressee.setGeo(contact.geo());
        }

        if (d->personAddressee.title().isEmpty() && !contact.title().isEmpty()) {
            d->personAddressee.setTitle(contact.title());
        }

        if (d->personAddressee.role().isEmpty() && !contact.role().isEmpty()) {
            d->personAddressee.setRole(contact.role());
        }

        if (d->personAddressee.organization().isEmpty() && !contact.organization().isEmpty()) {
            d->personAddressee.setOrganization(contact.organization());
        }

        if (d->personAddressee.department().isEmpty() && !contact.department().isEmpty()) {
            d->personAddressee.setDepartment(contact.department());
        }

//         void setNote( const QString &note );

//         void setProductId( const QString &productId );

//         don't handle revision - it's useless in this context
//         don't handle URL - it's not for websites, it's for a remote ID

        if (!d->personAddressee.secrecy().isValid() && !contact.secrecy().isValid()) {
            d->personAddressee.setSecrecy(contact.secrecy());
        }

        if (d->personAddressee.photo().isEmpty() && !contact.photo().isEmpty()) {
            d->personAddressee.setPhoto(contact.photo());
        }

        // find most online presence
        QString contactPresence = contact.custom("telepathy", "presence");
        QString currentPersonPresence = d->personAddressee.custom("telepathy", "presence");

        if (!contactPresence.isEmpty()) {
            if (KPeople::presenceSortPriority(contactPresence) < KPeople::presenceSortPriority(currentPersonPresence)) {
                d->personAddressee.insertCustom("telepathy", "presence", contactPresence);
            }
        }

//         void setSound( const Sound &sound );

        //TODO something clever here
//         void setCustoms( const QStringList & );
    }
}
<commit_msg>Add missing const &<commit_after>/*
 * <one line to give the library's name and an idea of what it does.>
 * Copyright 2013  David Edmundson <d.edmundson@lboro.ac.uk>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License or (at your option) version 3 or any later version
 * accepted by the membership of KDE e.V. (or its successor approved
 * by the membership of KDE e.V.), which shall act as a proxy
 * defined in Section 14 of version 3 of the license.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "metacontact.h"
#include "global.h"
#include <QSharedData>

namespace KPeople {
class MetaContactData : public QSharedData
{
public:
    QString personId;
    KABC::Addressee::Map contacts;
    KABC::Addressee personAddressee;
};
}

using namespace KPeople;

MetaContact::MetaContact():
d(new MetaContactData)
{

}

MetaContact::MetaContact(const QString& personId, const KABC::Addressee::Map& contacts):
d (new MetaContactData)
{
    d->personId = personId;
    d->contacts = contacts;
    reload();
}

MetaContact::MetaContact(const QString &contactId, const KABC::Addressee &contact):
d (new MetaContactData)
{
    d->personId = contactId;
    d->contacts[contactId] = contact;
    reload();
}

MetaContact::MetaContact(const MetaContact &other)
:d (other.d)
{

}

MetaContact& MetaContact::operator=( const MetaContact &other )
{
  if ( this != &other )
    d = other.d;

  return *this;
}

MetaContact::~MetaContact()
{

}

QString MetaContact::id() const
{
    return d->personId;
}

bool MetaContact::isValid() const
{
    return !d->contacts.isEmpty();
}

KABC::Addressee MetaContact::contact(const QString& contactId)
{
    return d->contacts[contactId];
}

KABC::AddresseeList MetaContact::contacts() const
{
    return d->contacts.values();
}

const KABC::Addressee& MetaContact::personAddressee() const
{
    return d->personAddressee;
}

void MetaContact::updateContact(const QString& contactId, const KABC::Addressee& contact)
{
    d->contacts[contactId] = contact;
    reload();
}

void MetaContact::removeContact(const QString& contactId)
{
    d->contacts.remove(contactId);
    reload();
}

void MetaContact::reload()
{
    //always favour the first item

    //TODO - long term goal: resource priority - local vcards for "people" trumps anything else. So we can set a preferred name etc.

    //Optimisation, if only one contact use that for everything
    if (d->contacts.size() == 1) {
        d->personAddressee = d->contacts.values().first();
        return;
    }

    d->personAddressee = KABC::Addressee();

    Q_FOREACH(const KABC::Addressee &contact, d->contacts.values()) {
        //set items with multiple cardinality
        Q_FOREACH(const KABC::Address &address, contact.addresses()) {
            d->personAddressee.insertAddress(address);
        }
        Q_FOREACH(const QString &category, contact.categories()) {
            d->personAddressee.insertCategory(category);
        }
        Q_FOREACH(const QString &email, contact.emails()) {
            d->personAddressee.insertEmail(email);
        }
        Q_FOREACH(const KABC::Key &key, contact.keys()) {
            d->personAddressee.insertKey(key);
        }
        Q_FOREACH(const KABC::PhoneNumber &phoneNumber, contact.phoneNumbers()) {
            d->personAddressee.insertPhoneNumber(phoneNumber);
        }
        //TODO customs

        //set items with single cardinality
        if (d->personAddressee.name().isEmpty() && !contact.name().isEmpty()) {
            d->personAddressee.setName(contact.name());
        }

        if (d->personAddressee.formattedName().isEmpty() && !contact.formattedName().isEmpty()) {
            d->personAddressee.setFormattedName(contact.formattedName());
        }

        //TODO all the remaining items below.

        //Maybe we can use a macro?
        if (d->personAddressee.familyName().isEmpty() && !contact.familyName().isEmpty()) {
            d->personAddressee.setFamilyName(contact.familyName());
        }

        if (d->personAddressee.givenName().isEmpty() && !contact.givenName().isEmpty()) {
            d->personAddressee.setGivenName(contact.givenName());
        }

        if (d->personAddressee.additionalName().isEmpty() && !contact.additionalName().isEmpty()) {
            d->personAddressee.setAdditionalName(contact.additionalName());
        }

        if (d->personAddressee.prefix().isEmpty() && !contact.prefix().isEmpty()) {
            d->personAddressee.setPrefix(contact.prefix());
        }

        if (d->personAddressee.suffix().isEmpty() && !contact.suffix().isEmpty()) {
            d->personAddressee.setSuffix(contact.suffix());
        }

        if (d->personAddressee.nickName().isEmpty() && !contact.nickName().isEmpty()) {
            d->personAddressee.setNickName(contact.nickName());
        }

//TODO merge Mck18's magic code that mixes years and dates
//         void setBirthday( const QDateTime &birthday );

        if (d->personAddressee.birthday().isNull() && !contact.birthday().isNull()) {
            d->personAddressee.setBirthday(contact.birthday());
        }

        if (d->personAddressee.mailer().isEmpty() && !contact.mailer().isEmpty()) {
            d->personAddressee.setMailer(contact.mailer());
        }

        if (!d->personAddressee.timeZone().isValid() && contact.timeZone().isValid()) {
            d->personAddressee.setTimeZone(contact.timeZone());
        }

        if (!d->personAddressee.geo().isValid() && contact.timeZone().isValid()) {
            d->personAddressee.setGeo(contact.geo());
        }

        if (d->personAddressee.title().isEmpty() && !contact.title().isEmpty()) {
            d->personAddressee.setTitle(contact.title());
        }

        if (d->personAddressee.role().isEmpty() && !contact.role().isEmpty()) {
            d->personAddressee.setRole(contact.role());
        }

        if (d->personAddressee.organization().isEmpty() && !contact.organization().isEmpty()) {
            d->personAddressee.setOrganization(contact.organization());
        }

        if (d->personAddressee.department().isEmpty() && !contact.department().isEmpty()) {
            d->personAddressee.setDepartment(contact.department());
        }

//         void setNote( const QString &note );

//         void setProductId( const QString &productId );

//         don't handle revision - it's useless in this context
//         don't handle URL - it's not for websites, it's for a remote ID

        if (!d->personAddressee.secrecy().isValid() && !contact.secrecy().isValid()) {
            d->personAddressee.setSecrecy(contact.secrecy());
        }

        if (d->personAddressee.photo().isEmpty() && !contact.photo().isEmpty()) {
            d->personAddressee.setPhoto(contact.photo());
        }

        // find most online presence
        const QString &contactPresence = contact.custom("telepathy", "presence");
        const QString &currentPersonPresence = d->personAddressee.custom("telepathy", "presence");

        if (!contactPresence.isEmpty()) {
            if (KPeople::presenceSortPriority(contactPresence) < KPeople::presenceSortPriority(currentPersonPresence)) {
                d->personAddressee.insertCustom("telepathy", "presence", contactPresence);
            }
        }

//         void setSound( const Sound &sound );

        //TODO something clever here
//         void setCustoms( const QStringList & );
    }
}
<|endoftext|>


<commit_before>#ifndef SERVER_PLAYER_LIST_HPP
#define SERVER_PLAYER_LIST_HPP

#include <color32.hpp>
#include <ptr_vector.hpp>
#include <scoped_connection_pool.hpp>
#include <shared_collection.hpp>
#include "server_netcom.hpp"
#include "server_player.hpp"

namespace config {
    class state;
}

namespace request {
namespace client {
    NETCOM_PACKET(player_list_collection_id) {
        struct answer {
            shared_collection_id_t id;
        };
        struct failure {};
    };
    NETCOM_PACKET(leave_players) {
        struct answer {};
        struct failure {};
    };
    NETCOM_PACKET(join_players) {
        std::string name;
        color32 color;
        bool is_ai;

        struct answer {};
        struct failure {
            enum class reason {
                too_many_players = 0
            } rsn;
        };
    };
}
}

namespace packet {
    NETCOM_PACKET(player_list) {
        struct player_t {
            actor_id_t id;
            std::string ip, name;
            color32 color;
            bool is_ai;
        };
        std::vector<player_t> players;
    };
    NETCOM_PACKET(player_connected) {
        actor_id_t id;
        std::string ip, name;
        color32 color;
        bool is_ai;
    };
    NETCOM_PACKET(player_disconnected) {
        actor_id_t id;
        enum class reason {
            connection_lost,
            left,
            auto_kicked
        } rsn;
    };
}

struct player_collection_traits {
    using full_packet   = packet::player_list;
    using add_packet    = packet::player_connected;
    using remove_packet = packet::player_disconnected;
};

namespace server {
    class player_list {
    public :
        player_list(netcom& net, config::state& conf);

        struct auto_kick_policy {
            bool ai_first = false;
            bool older_first = false;
        };

        void set_max_player(std::uint32_t max);
        void set_max_player(std::uint32_t max, auto_kick_policy p);
        std::uint32_t max_player() const;

    private :
        void remove_player_(ctl::ptr_vector<player>::iterator iter,
            packet::player_disconnected::reason rsn);

        netcom& net_;
        config::state& conf_;

        std::uint32_t           max_player_;
        ctl::ptr_vector<player> players_;

        scoped_connection_pool pool_;
        shared_collection<player_collection_traits> collection_;
    };
}

#ifndef NO_AUTOGEN
#include "autogen/packets/server_player_list.hpp"
#endif

#endif
<commit_msg>Added clear message to player list.<commit_after>#ifndef SERVER_PLAYER_LIST_HPP
#define SERVER_PLAYER_LIST_HPP

#include <color32.hpp>
#include <ptr_vector.hpp>
#include <scoped_connection_pool.hpp>
#include <shared_collection.hpp>
#include "server_netcom.hpp"
#include "server_player.hpp"

namespace config {
    class state;
}

namespace request {
namespace client {
    NETCOM_PACKET(player_list_collection_id) {
        struct answer {
            shared_collection_id_t id;
        };
        struct failure {};
    };
    NETCOM_PACKET(leave_players) {
        struct answer {};
        struct failure {};
    };
    NETCOM_PACKET(join_players) {
        std::string name;
        color32 color;
        bool is_ai;

        struct answer {};
        struct failure {
            enum class reason {
                too_many_players = 0
            } rsn;
        };
    };
}
}

namespace packet {
    NETCOM_PACKET(player_list) {
        struct player_t {
            actor_id_t id;
            std::string ip, name;
            color32 color;
            bool is_ai;
        };
        std::vector<player_t> players;
    };
    NETCOM_PACKET(player_connected) {
        actor_id_t id;
        std::string ip, name;
        color32 color;
        bool is_ai;
    };
    NETCOM_PACKET(player_disconnected) {
        actor_id_t id;
        enum class reason {
            connection_lost,
            left,
            auto_kicked
        } rsn;
    };
    NETCOM_PACKET(player_list_cleared) {};
}

struct player_collection_traits {
    using full_packet   = packet::player_list;
    using add_packet    = packet::player_connected;
    using remove_packet = packet::player_disconnected;
    using clear_packet  = packet::player_list_cleared;
};

namespace server {
    class player_list {
    public :
        player_list(netcom& net, config::state& conf);

        struct auto_kick_policy {
            bool ai_first = false;
            bool older_first = false;
        };

        void set_max_player(std::uint32_t max);
        void set_max_player(std::uint32_t max, auto_kick_policy p);
        std::uint32_t max_player() const;

    private :
        void remove_player_(ctl::ptr_vector<player>::iterator iter,
            packet::player_disconnected::reason rsn);

        netcom& net_;
        config::state& conf_;

        std::uint32_t           max_player_;
        ctl::ptr_vector<player> players_;

        scoped_connection_pool pool_;
        shared_collection<player_collection_traits> collection_;
    };
}

#ifndef NO_AUTOGEN
#include "autogen/packets/server_player_list.hpp"
#endif

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2018 ASMlover. 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 ofconditions 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 materialsprovided with the
//    distribution.
//
// 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 OR CONTRIBUTORS 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 "nyx_rpc_channel.h"

namespace nyx { namespace rpc {

rpc_channel::rpc_channel(base_service* service)
  : wbits_(12)
  , memlevel_(5)
  , service_(service) {
}

rpc_channel::~rpc_channel(void) {
}

bool rpc_channel::on_request(unsigned char channel) {
  return false;
}

void rpc_channel::CallMethod(
    const pb::MethodDescriptor* method,
    pb::RpcController* controller,
    const pb::Message* request,
    pb::Message* response,
    pb::Closure* done) {
}

bool rpc_channel::handle_data(
    const char* data, std::size_t size, bool reliable, unsigned char channel) {
  return false;
}

void rpc_channel::set_recv_limit(std::size_t limit) {
}

void rpc_channel::enable_compressor(bool enabled, unsigned char channel) {
}

void rpc_channel::enable_encrypter(
    const std::string& key, unsigned char channel) {
}

void rpc_channel::call_traverse(const rpc_traverse_msg_ptr& msg) {
}

}}
<commit_msg>:construction: chore(channel): updated the rpc channel implementation<commit_after>// Copyright (c) 2018 ASMlover. 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 ofconditions 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 materialsprovided with the
//    distribution.
//
// 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 OR CONTRIBUTORS 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 <sstream>
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
#include "../compressor/nyx_compressor.h"
#include "../crypter/nyx_crypter.h"
#include "../nyx_service.h"
#include "nyx_rpc_converter.h"
#include "nyx_rpc_channel.h"

namespace nyx { namespace rpc {

rpc_channel::rpc_channel(base_service* service)
  : wbits_(12)
  , memlevel_(5)
  , service_(service) {
}

rpc_channel::~rpc_channel(void) {
}

bool rpc_channel::on_request(unsigned char channel) {
  return false;
}

void rpc_channel::CallMethod(
    const pb::MethodDescriptor* method,
    pb::RpcController* controller,
    const pb::Message* request,
    pb::Message* response,
    pb::Closure* done) {
  std::ostringstream oss;
  unsigned int total_len = 0;
  oss.write(reinterpret_cast<const char*>(&total_len), sizeof(total_len));
  method_index_type index = method->index();
  oss.write(reinterpret_cast<const char*>(&index), sizeof(index));
  if (!request->SerializeToOstream(&oss)) {
    service_->disconnect();
    return;
  }

  total_len = oss.tellp();
  auto data_len = total_len - sizeof(total_len);
  oss.seekp(0, std::ios_base::beg);
  oss.write(reinterpret_cast<const char*>(&data_len), sizeof(data_len));
  oss.seekp(total_len);

  auto str_data = std::make_shared<std::string>(oss.str());
  if (traverse_) {
    traverse_->set_msg(str_data);
    traverse_.reset();
  }

  bool reliable{true};
  unsigned char channel = kDefaultChannelId;
  if (controller) {
    auto* ctrl = pb::down_cast<rpc_controller*>(controller);
    reliable |= ctrl->get_reliable();
    channel = ctrl->get_channel();
    if (BOOST_UNLIKELY(channel >= kChannelCount))
      return;
  }

  auto buf = std::make_shared<boost::asio::streambuf>();
  std::ostream os(buf.get());

  auto& converter = converters_[channel];
  if (reliable && converter) {
    std::string encrypted_data;
    converter->handle_ostream_data(*str_data.get(), encrypted_data);
    os.write(encrypted_data.data(), encrypted_data.size());
    // send_count = encrypted_data.size();
  }
  else {
    os.write(str_data->data(), str_data->size());
    // send_count = str_data->size();
  }
  service_->async_write(buf, reliable, channel);
}

bool rpc_channel::handle_data(
    const char* data, std::size_t size, bool reliable, unsigned char channel) {
  return false;
}

void rpc_channel::set_recv_limit(std::size_t limit) {
  for (auto i = 0u; i < kChannelCount; ++i)
    request_parsers_[i].set_recv_limit(limit);
}

void rpc_channel::enable_compressor(bool enabled, unsigned char channel) {
  if (BOOST_UNLIKELY(channel >= kChannelCount))
    return;

  auto& converter = converters_[channel];
  if (!converter)
    converter.reset(new rpc_converter());
  if (enabled) {
    converter->set_compressor(
        std::make_shared<nyx::compressor::zlib_compressor>(wbits_, memlevel_));
  }
  else {
    converter->reset_compressor();
  }
}

void rpc_channel::enable_encrypter(
    const std::string& key, unsigned char channel) {
  if (BOOST_UNLIKELY(channel >= kChannelCount))
    return;

  auto& converter = converters_[channel];
  if (!converter)
    converter.reset(new rpc_converter());
  if (key != "") {
    converter->set_crypter(
        std::make_shared<nyx::crypter::rc4_crypter>(key),
        std::make_shared<nyx::crypter::rc4_crypter>(key));
  }
  else {
    converter->reset_crypter();
  }
}

void rpc_channel::call_traverse(const rpc_traverse_msg_ptr& msg) {
}

}}
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE json test
#include <boost/test/unit_test.hpp>
#include <ten/json.hh>
#ifdef TEN_JSON_CXX11
#include <ten/jserial.hh>
#include <ten/jserial_maybe.hh>
#include <ten/jserial_seq.hh>
#include <ten/jserial_assoc.hh>
#include <ten/jserial_enum.hh>
#endif
#include <array>

#include "ten/logging.hh"
#include "ten/jsonstream.hh"

using namespace std;
using namespace ten;

const char json_text[] =
"{ \"store\": {"
"    \"book\": ["
"      { \"category\": \"reference\","
"        \"author\": \"Nigel Rees\","
"        \"title\": \"Sayings of the Century\","
"        \"price\": 8.95"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"Evelyn Waugh\","
"        \"title\": \"Sword of Honour\","
"        \"price\": 12.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"Herman Melville\","
"        \"title\": \"Moby Dick\","
"        \"isbn\": \"0-553-21311-3\","
"        \"price\": 8.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"J. R. R. Tolkien\","
"        \"title\": \"The Lord of the Rings\","
"        \"isbn\": \"0-395-19395-8\","
"        \"price\": 22.99"
"      }"
"    ],"
"    \"bicycle\": {"
"      \"color\": \"red\","
"      \"price\": 19.95"
"    }"
"  }"
"}";

BOOST_AUTO_TEST_CASE(json_test_path1) {
    json o{json::load(json_text)};
    BOOST_REQUIRE(o.get());

    static const char a1[] = "[\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"]";
    json r1{o.path("/store/book/author")};
    BOOST_CHECK_EQUAL(json::load(a1), r1);

    json r2{o.path("//author")};
    BOOST_CHECK_EQUAL(json::load(a1), r2);

    // jansson hashtable uses size_t for hash
    // we think this is causing the buckets to change on 32bit vs. 64bit
#if (__SIZEOF_SIZE_T__ == 4)
    static const char a3[] = "[{\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, {\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}, {\"color\": \"red\", \"price\": 19.95}]";
#elif (__SIZEOF_SIZE_T__ == 8)
    static const char a3[] = "[{\"color\": \"red\", \"price\": 19.95}, {\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, {\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}]";
#endif
    json r3{o.path("/store/*")};
    json t3{json::load(a3)};
    BOOST_CHECK_EQUAL(t3, r3);

#if (__SIZEOF_SIZE_T__ == 4)
    static const char a4[] = "[8.95, 12.99, 8.99, 22.99, 19.95]";
#elif (__SIZEOF_SIZE_T__ == 8)
    static const char a4[] = "[19.95, 8.95, 12.99, 8.99, 22.99]";
#endif
    json r4{o.path("/store//price")};
    BOOST_CHECK_EQUAL(json::load(a4), r4);

    static const char a5[] = "{\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}";
    json r5{o.path("//book[3]")};
    BOOST_CHECK_EQUAL(json::load(a5), r5);

    static const char a6[] = "\"J. R. R. Tolkien\"";
    json r6{o.path("/store/book[3]/author")};
    BOOST_CHECK_EQUAL(json::load(a6), r6);
    BOOST_CHECK(json::load(a6) == r6);

    static const char a7[] = "[{\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}]";
    json r7{o.path("/store/book[category=\"fiction\"]")};
    BOOST_CHECK_EQUAL(json::load(a7), r7);
}

BOOST_AUTO_TEST_CASE(json_test_path2) {
    json o{json::load("[{\"type\": 0}, {\"type\": 1}]")};
    BOOST_CHECK_EQUAL(json::load("[{\"type\":1}]"), o.path("/[type=1]"));
}

BOOST_AUTO_TEST_CASE(json_test_filter_key_exists) {
    json o{json::load(json_text)};
    BOOST_REQUIRE(o.get());

    static const char a[] = "["
"      { \"category\": \"fiction\","
"        \"author\": \"Herman Melville\","
"        \"title\": \"Moby Dick\","
"        \"isbn\": \"0-553-21311-3\","
"        \"price\": 8.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"J. R. R. Tolkien\","
"        \"title\": \"The Lord of the Rings\","
"        \"isbn\": \"0-395-19395-8\","
"        \"price\": 22.99"
"      }]";
    json r{o.path("//book[isbn]")};
    BOOST_CHECK_EQUAL(json::load(a), r);

    json r1{o.path("//book[doesnotexist]")};
    BOOST_REQUIRE(r1.is_array());
    BOOST_CHECK_EQUAL(0, r1.asize());
}

BOOST_AUTO_TEST_CASE(json_test_truth) {
    json o{{}}; // empty init list
    BOOST_CHECK(o.get("nothing").is_true() == false);
    BOOST_CHECK(o.get("nothing").is_false() == false);
    BOOST_CHECK(o.get("nothing").is_null() == false);
    BOOST_CHECK(!o.get("nothing"));
}

BOOST_AUTO_TEST_CASE(json_test_path3) {
    json o{json::load(json_text)};
    BOOST_REQUIRE(o.get());

    BOOST_CHECK_EQUAL(o, o.path("/"));
    BOOST_CHECK_EQUAL("Sayings of the Century",
        o.path("/store/book[category=\"reference\"]/title"));

    static const char text[] = "["
    "{\"type\":\"a\", \"value\":0},"
    "{\"type\":\"b\", \"value\":1},"
    "{\"type\":\"c\", \"value\":2},"
    "{\"type\":\"c\", \"value\":3}"
    "]";

    BOOST_CHECK_EQUAL(json(1), json::load(text).path("/[type=\"b\"]/value"));
}

BOOST_AUTO_TEST_CASE(json_init_list) {
    json meta{
        { "foo", 17 },
        { "bar", 23 },
        { "baz", true },
        { "corge", json::array({ 1, 3.14159 }) },
        { "grault", json::array({ "hello", string("world") }) },
    };
    BOOST_REQUIRE(meta);
    BOOST_REQUIRE(meta.is_object());
    BOOST_CHECK_EQUAL(meta.osize(), 5);
    BOOST_CHECK_EQUAL(meta["foo"].integer(), 17);
    BOOST_CHECK_EQUAL(meta["corge"][0].integer(), 1);
    BOOST_CHECK_EQUAL(meta["grault"][1].str(), "world");
}

template <class T>
inline void test_conv(T val, json j, json_type t) {
    json j2 = to_json(val);
    BOOST_CHECK_EQUAL(j2.type(), t);
    BOOST_CHECK_EQUAL(j, j2);
    T val2 = json_cast<T>(j2);
    BOOST_CHECK_EQUAL(val, val2);
}

template <class T, json_type TYPE = JSON_INTEGER>
inline void test_conv_num() {
    typedef numeric_limits<T> lim;
    T range[5] = { lim::min(), T(-1), 0, T(1), lim::max() };
    for (unsigned i = 0; i < 5; ++i)
        test_conv<T>(range[i], json(range[i]), TYPE);
}

BOOST_AUTO_TEST_CASE(json_conversions) {
    test_conv<string>(string("hello"), json::str("hello"), JSON_STRING);
    BOOST_CHECK_EQUAL(to_json("world"), json::str("world"));

    test_conv_num<short>();
    test_conv_num<int>();
    test_conv_num<long>();
    test_conv_num<long long>();
    test_conv_num<unsigned short>();
    test_conv_num<unsigned>();
#if ULONG_MAX < LLONG_MAX
    test_conv_num<unsigned long>();
#endif

    test_conv_num<double, JSON_REAL>();
    test_conv_num<float,  JSON_REAL>();

    test_conv<bool>(true,  json::jtrue(),  JSON_TRUE);
    test_conv<bool>(false, json::jfalse(), JSON_FALSE);
}

BOOST_AUTO_TEST_CASE(json_create) {
    json obj1{{}};
    BOOST_CHECK(obj1);
    obj1.set("test", "set");
    BOOST_CHECK(obj1.get("test"));
    json root{
        {"obj1", obj1}
    };
    BOOST_CHECK_EQUAL(root.get("obj1"), obj1);
    obj1.set("this", "that");
    BOOST_CHECK_EQUAL(root.get("obj1").get("this").str(), "that");
    json obj2{ {"answer", 42} };
    obj1.set("obj2", obj2);
    BOOST_CHECK_EQUAL(root.get("obj1").get("obj2"), obj2);
}

#ifdef TEN_JSON_CXX11

struct corge {
    int foo, bar;

    corge() : foo(), bar() {}
    corge(int foo_, int bar_) : foo(foo_), bar(bar_) {}
};
template <class AR>
inline void serialize(AR &ar, corge &c) {
    ar & kv("foo", c.foo) & kv("bar", c.bar);
}
inline bool operator == (const corge &a, const corge &b) {
    return a.foo == b.foo && a.bar == b.bar;
}

enum captain { kirk, picard, janeway, sisko };
const array<string, 4> captain_names = {{ "kirk", "picard", "janeway", "sisko" }};
template <class AR>
inline void serialize(AR &ar, captain &c) {
    serialize_enum(ar, c, captain_names);
}

BOOST_AUTO_TEST_CASE(json_serial) {
    corge c1{42, 17};
    auto j = jsave_all(c1);
    corge c2;
    json_loader(j) >> c2;
    BOOST_CHECK(c1 == c2);

    map<string, int> m;
    json_loader(j) >> m;
    BOOST_CHECK_EQUAL(m.size(), 2);
    BOOST_CHECK(m.find("foo") != m.end());
    BOOST_CHECK(m.find("bar") != m.end());
    BOOST_CHECK_EQUAL(m["foo"], 42);
    BOOST_CHECK_EQUAL(m["bar"], 17);

#if BOOST_VERSION >= 104800
    flat_map<string, int> f;
    json_loader(j) >> f;
    BOOST_CHECK_EQUAL(f.size(), 2);
    BOOST_CHECK(f.find("foo") != f.end());
    BOOST_CHECK(f.find("bar") != f.end());
    BOOST_CHECK_EQUAL(f["foo"], 42);
    BOOST_CHECK_EQUAL(f["bar"], 17);
#endif

    maybe<int> a;
    j = jsave_all(a);
    BOOST_CHECK(!j);
    a = 42;
    j = jsave_all(a);
    BOOST_CHECK_EQUAL(j, 42);

    a.reset();
    BOOST_CHECK(!a.ok());
    j = 17;
    json_loader(j) >> a;
    BOOST_CHECK(a.ok());
    BOOST_CHECK_EQUAL(a.get(), 17);

    captain c = janeway;
    j = jsave_all(c);
    BOOST_CHECK_EQUAL(j, "janeway");
    j = "kirk";
    json_loader(j) >> c;
    BOOST_CHECK_EQUAL(c, kirk);
}

#endif // TEN_JSON_CXX11

BOOST_AUTO_TEST_CASE(json_stream) {
    // TODO: improve these tests or don't. this is a hack anyway
    using namespace jsonstream_manip;
    jsonstream s;
    s << begin_object
        << "key" << 1234
        << "list" << begin_array << "1" << 2.0f << 3.14 << 4 << 5 << end_array
    << end_object;
    LOG(INFO) << s.str();
}

<commit_msg>fix test<commit_after>#define BOOST_TEST_MODULE json test
#include <boost/test/unit_test.hpp>
#include <ten/json.hh>
#ifdef TEN_JSON_CXX11
#include <ten/jserial.hh>
#include <ten/jserial_maybe.hh>
#include <ten/jserial_seq.hh>
#include <ten/jserial_assoc.hh>
#include <ten/jserial_enum.hh>
#endif
#include <array>

#include "ten/logging.hh"
#include "ten/jsonstream.hh"

using namespace std;
using namespace ten;

const char json_text[] =
"{ \"store\": {"
"    \"book\": ["
"      { \"category\": \"reference\","
"        \"author\": \"Nigel Rees\","
"        \"title\": \"Sayings of the Century\","
"        \"price\": 8.95"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"Evelyn Waugh\","
"        \"title\": \"Sword of Honour\","
"        \"price\": 12.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"Herman Melville\","
"        \"title\": \"Moby Dick\","
"        \"isbn\": \"0-553-21311-3\","
"        \"price\": 8.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"J. R. R. Tolkien\","
"        \"title\": \"The Lord of the Rings\","
"        \"isbn\": \"0-395-19395-8\","
"        \"price\": 22.99"
"      }"
"    ],"
"    \"bicycle\": {"
"      \"color\": \"red\","
"      \"price\": 19.95"
"    }"
"  }"
"}";

BOOST_AUTO_TEST_CASE(json_test_path1) {
    json o{json::load(json_text)};
    BOOST_REQUIRE(o.get());

    static const char a1[] = "[\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"]";
    json r1{o.path("/store/book/author")};
    BOOST_CHECK_EQUAL(json::load(a1), r1);

    json r2{o.path("//author")};
    BOOST_CHECK_EQUAL(json::load(a1), r2);

    // jansson hashtable uses size_t for hash
    // we think this is causing the buckets to change on 32bit vs. 64bit
#if (__SIZEOF_SIZE_T__ == 4)
    static const char a3[] = "[{\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, {\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}, {\"color\": \"red\", \"price\": 19.95}]";
#elif (__SIZEOF_SIZE_T__ == 8)
    static const char a3[] = "[{\"color\": \"red\", \"price\": 19.95}, {\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, {\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}]";
#endif
    json r3{o.path("/store/*")};
    json t3{json::load(a3)};
    BOOST_CHECK_EQUAL(t3, r3);

#if (__SIZEOF_SIZE_T__ == 4)
    static const char a4[] = "[8.95, 12.99, 8.99, 22.99, 19.95]";
#elif (__SIZEOF_SIZE_T__ == 8)
    static const char a4[] = "[19.95, 8.95, 12.99, 8.99, 22.99]";
#endif
    json r4{o.path("/store//price")};
    BOOST_CHECK_EQUAL(json::load(a4), r4);

    static const char a5[] = "{\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}";
    json r5{o.path("//book[3]")};
    BOOST_CHECK_EQUAL(json::load(a5), r5);

    static const char a6[] = "\"J. R. R. Tolkien\"";
    json r6{o.path("/store/book[3]/author")};
    BOOST_CHECK_EQUAL(json::load(a6), r6);
    BOOST_CHECK(json::load(a6) == r6);

    static const char a7[] = "[{\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}]";
    json r7{o.path("/store/book[category=\"fiction\"]")};
    BOOST_CHECK_EQUAL(json::load(a7), r7);
}

BOOST_AUTO_TEST_CASE(json_test_path2) {
    json o{json::load("[{\"type\": 0}, {\"type\": 1}]")};
    BOOST_CHECK_EQUAL(json::load("[{\"type\":1}]"), o.path("/[type=1]"));
}

BOOST_AUTO_TEST_CASE(json_test_filter_key_exists) {
    json o{json::load(json_text)};
    BOOST_REQUIRE(o.get());

    static const char a[] = "["
"      { \"category\": \"fiction\","
"        \"author\": \"Herman Melville\","
"        \"title\": \"Moby Dick\","
"        \"isbn\": \"0-553-21311-3\","
"        \"price\": 8.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"J. R. R. Tolkien\","
"        \"title\": \"The Lord of the Rings\","
"        \"isbn\": \"0-395-19395-8\","
"        \"price\": 22.99"
"      }]";
    json r{o.path("//book[isbn]")};
    BOOST_CHECK_EQUAL(json::load(a), r);

    json r1{o.path("//book[doesnotexist]")};
    BOOST_REQUIRE(r1.is_array());
    BOOST_CHECK_EQUAL(0, r1.asize());
}

BOOST_AUTO_TEST_CASE(json_test_truth) {
    json o{{}}; // empty init list
    BOOST_CHECK(o.get("nothing").is_true() == false);
    BOOST_CHECK(o.get("nothing").is_false() == false);
    BOOST_CHECK(o.get("nothing").is_null() == false);
    BOOST_CHECK(!o.get("nothing"));
}

BOOST_AUTO_TEST_CASE(json_test_path3) {
    json o{json::load(json_text)};
    BOOST_REQUIRE(o.get());

    BOOST_CHECK_EQUAL(o, o.path("/"));
    BOOST_CHECK_EQUAL("Sayings of the Century",
        o.path("/store/book[category=\"reference\"]/title"));

    static const char text[] = "["
    "{\"type\":\"a\", \"value\":0},"
    "{\"type\":\"b\", \"value\":1},"
    "{\"type\":\"c\", \"value\":2},"
    "{\"type\":\"c\", \"value\":3}"
    "]";

    BOOST_CHECK_EQUAL(json(1), json::load(text).path("/[type=\"b\"]/value"));
}

BOOST_AUTO_TEST_CASE(json_init_list) {
    json meta{
        { "foo", 17 },
        { "bar", 23 },
        { "baz", true },
        { "corge", json::array({ 1, 3.14159 }) },
        { "grault", json::array({ "hello", string("world") }) },
    };
    BOOST_REQUIRE(meta);
    BOOST_REQUIRE(meta.is_object());
    BOOST_CHECK_EQUAL(meta.osize(), 5);
    BOOST_CHECK_EQUAL(meta["foo"].integer(), 17);
    BOOST_CHECK_EQUAL(meta["corge"][0].integer(), 1);
    BOOST_CHECK_EQUAL(meta["grault"][1].str(), "world");
}

template <class T>
inline void test_conv(T val, json j, json_type t) {
    json j2 = to_json(val);
    BOOST_CHECK_EQUAL(j2.type(), t);
    BOOST_CHECK_EQUAL(j, j2);
    T val2 = json_cast<T>(j2);
    BOOST_CHECK_EQUAL(val, val2);
}

template <class T, json_type TYPE = JSON_INTEGER>
inline void test_conv_num() {
    typedef numeric_limits<T> lim;
    T range[5] = { lim::min(), T(-1), 0, T(1), lim::max() };
    for (unsigned i = 0; i < 5; ++i)
        test_conv<T>(range[i], json(range[i]), TYPE);
}

BOOST_AUTO_TEST_CASE(json_conversions) {
    test_conv<string>(string("hello"), json::str("hello"), JSON_STRING);
    BOOST_CHECK_EQUAL(to_json("world"), json::str("world"));

    test_conv_num<short>();
    test_conv_num<int>();
    test_conv_num<long>();
    test_conv_num<long long>();
    test_conv_num<unsigned short>();
    test_conv_num<unsigned>();
#if ULONG_MAX < LLONG_MAX
    test_conv_num<unsigned long>();
#endif

    test_conv_num<double, JSON_REAL>();
    test_conv_num<float,  JSON_REAL>();

    test_conv<bool>(true,  json::jtrue(),  JSON_TRUE);
    test_conv<bool>(false, json::jfalse(), JSON_FALSE);
}

BOOST_AUTO_TEST_CASE(json_create) {
    json obj1{{}};
    BOOST_CHECK(obj1);
    obj1.set("test", "set");
    BOOST_CHECK(obj1.get("test"));
    json root{
        {"obj1", obj1}
    };
    BOOST_CHECK_EQUAL(root.get("obj1"), obj1);
    obj1.set("this", "that");
    BOOST_CHECK_EQUAL(root.get("obj1").get("this").str(), "that");
    json obj2{ {"answer", 42} };
    obj1.set("obj2", obj2);
    BOOST_CHECK_EQUAL(root.get("obj1").get("obj2"), obj2);
}

#ifdef TEN_JSON_CXX11

struct corge {
    int foo, bar;

    corge() : foo(), bar() {}
    corge(int foo_, int bar_) : foo(foo_), bar(bar_) {}
};
template <class AR>
inline void serialize(AR &ar, corge &c) {
    ar & kv("foo", c.foo) & kv("bar", c.bar);
}
inline bool operator == (const corge &a, const corge &b) {
    return a.foo == b.foo && a.bar == b.bar;
}

enum captain { kirk, picard, janeway, sisko };
const array<string, 4> captain_names = {{ "kirk", "picard", "janeway", "sisko" }};
template <class AR>
inline void serialize(AR &ar, captain &c) {
    serialize_enum(ar, c, captain_names);
}

BOOST_AUTO_TEST_CASE(json_serial) {
    corge c1{42, 17};
    auto j = jsave_all(c1);
    corge c2;
    json_loader(j) >> c2;
    BOOST_CHECK(c1 == c2);

    map<string, int> m;
    json_loader(j) >> m;
    BOOST_CHECK_EQUAL(m.size(), 2);
    BOOST_CHECK(m.find("foo") != m.end());
    BOOST_CHECK(m.find("bar") != m.end());
    BOOST_CHECK_EQUAL(m["foo"], 42);
    BOOST_CHECK_EQUAL(m["bar"], 17);

#if BOOST_VERSION >= 104800
    flat_map<string, int> f;
    json_loader(j) >> f;
    BOOST_CHECK_EQUAL(f.size(), 2);
    BOOST_CHECK(f.find("foo") != f.end());
    BOOST_CHECK(f.find("bar") != f.end());
    BOOST_CHECK_EQUAL(f["foo"], 42);
    BOOST_CHECK_EQUAL(f["bar"], 17);
#endif

    maybe<int> a;
    j = jsave_all(a);
    BOOST_CHECK(!j);
    a = 42;
    j = jsave_all(a);
    BOOST_CHECK_EQUAL(j, 42);

    a.reset();
    BOOST_CHECK(!a.ok());
    j = 17;
    json_loader(j) >> a;
    BOOST_CHECK(a.ok());
    BOOST_CHECK_EQUAL(a.get(), 17);

    captain c = janeway;
    j = jsave_all(c);
    BOOST_CHECK_EQUAL(j, "janeway");
    j = "kirk";
    json_loader(j) >> c;
    BOOST_CHECK_EQUAL(c, kirk);
}

#endif // TEN_JSON_CXX11

BOOST_AUTO_TEST_CASE(json_stream) {
    // TODO: improve these tests or don't. this is a hack anyway
    using namespace jsonstream_manip;
    jsonstream s;
    s << begin_object
        << "key" << 1234
        << "list" << begin_array << "1" << 2.0f << 3.14 << 4 << 5 << end_array
    << end_object;
    BOOST_CHECK(json::load(s.str()));
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file libport/path.cc
 ** \brief Implement libport::path.
 */

#include <cctype>
#include <iostream>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/detect-win32.h>
#include <libport/exception.hh>
#include <libport/fcntl.h>
#include <libport/format.hh>
#include <libport/path.hh>
#include <libport/sys/stat.h>
#include <libport/sys/types.h>
#include <libport/unistd.h>

GD_CATEGORY(Libport.Path);

// Implementation detail: if components() is empty and not absolute
// then the path is '.'.

namespace libport
{
  path::path(const std::string& p)
  {
    init(p);
  }

  path::path(const char* p)
  {
    init(p);
  }

  path::path(const value_type& p)
  {
    init(p.file_string());
  }

  void
  path::init(const std::string& p)
  {
    if (p.empty())
      throw invalid_path("Path can't be empty.");
#ifdef WIN32
    // We want "/" to mean "the root of the current volume" on windows.
    if (p[0] == '/')
      value_ = boost::filesystem::current_path().root_name() + p;
    else
#endif
    value_ = p;
    value_ = clean();
  }

  path&
  path::operator=(const path& rhs)
  {
    value_ = rhs.value_;
    return *this;
  }

  path&
  path::operator/=(const path& rhs)
  {
    if (rhs.absolute_get())
      throw invalid_path(
        "Rhs of concatenation is absolute: " + rhs.to_string());
#ifdef WIN32
    if (!rhs.volume_get().empty())
      throw invalid_path("concatenation of path with volume: " +
			 rhs.to_string());
#endif
    value_ /= rhs.value_;
    value_ = clean();
    return *this;
  }

  path
  path::operator/(const path& rhs) const
  {
    path res = *this;
    return res /= rhs;
  }

  std::string
  path::to_string() const
  {
    if (!value_.is_complete() && components().empty())
      return WIN32_IF(volume_get().empty() ? "." : volume_get(), ".");

    return value_.file_string();
  }

  bool
  path::operator==(const path& rhs) const
  {
    return (volume_get() == rhs.volume_get()
            && absolute_get() == rhs.absolute_get()
            && components() == rhs.components());
  }

  std::ostream&
  path::dump(std::ostream& o) const
  {
    return o << operator std::string();
  }

  std::string
  path::clean() const
  {
    std::string res;
    value_type::iterator i = value_.begin();
    value_type::iterator i_end = value_.end();
    if (i == i_end)
      return ".";

    bool first = true;
    if (absolute_get())
    {
      res = *i;
      ++i;
#ifdef WIN32
      // Add a "\" after the drive letter or network share.
      first = false;
#endif
    }

    for (;i != i_end; ++i)
    {
      // Remove the "." and empty components.
      if (!i->empty() && *i != ".")
      {
        if (!first)
          res += separator_;
        first = false;
        res += *i;
      }
    }
    return res.empty() ? "." : res;
  }

  std::string
  path::volume_get() const
  {
#ifndef WIN32
    return "";
#else
    std::string res = value_.root_name();
    if (res.find("//") == 0)
      res.replace(0, 2, "\\\\");
    return res;
#endif
  }

  path
  path::dirname() const
  {
    // dirname of / is /, dirname of . is .
    if (components().empty())
      return *this;

    std::string res = value_.parent_path().directory_string();
    return path(res.empty() ? "." : res);
  }

  bool path::exists() const
  {
    bool res;
    try
    {
      res = boost::filesystem::exists(value_);
    }
    catch (...)
    {
      res = false;
    }
    GD_FINFO_DUMP("exists: %-5s: %s", res ? "true" : "false", to_string());
    return res;
  }

  path
  path::cwd()
  {
    return path(boost::filesystem::current_path().string());
  }

  bool
  path::is_root() const
  {
    return to_string() == (volume_get() + separator_);
  }

  path
  path::parent() const
  {
    if (is_root())
      return path(volume_get().append(1, separator_));

    const std::string parent_path =
      boost::filesystem::path(to_string()).parent_path().string();

    if (parent_path.empty())
      return cwd();

    return parent_path;
  }

  std::time_t
  path::last_write_time() const
  {
    return boost::filesystem::last_write_time(
      boost::filesystem::path(to_string()));
  }

  bool path::create() const
  {
    int fd = open(to_string().c_str(),
                  O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    if (fd == -1)
      return false;
    close(fd);
    return true;
  }

  path
  path::temporary_file()
  {
#ifndef WIN32
    char tmp_name[] = "/tmp/tmp.XXXXXX";
    int fd = mkstemp(tmp_name);
    close (fd);
#else
    char tmp_dir[MAX_PATH];
    char tmp_name[MAX_PATH];

    if(GetTempPathA(sizeof(tmp_dir), tmp_dir) == 0
       || GetTempFileNameA(tmp_dir, "$$$", 0, tmp_name) == 0)
      throw Exception("cannot generate path for temporary file");
#endif
    return path(tmp_name);
  }

  void
  path::remove() const
  {
    if (!boost::filesystem::remove(value_))
      throw Exception(libport::format("cannot unlink file %s", *this));
  }

  void
  path::rename(const std::string& dst)
  {
    try
    {
      boost::filesystem::rename(value_, dst);
    }
    catch (Exception& e)
    {
      throw Exception(libport::format("cannot rename file %s: %s",
                                      *this, format_boost_fs_error(e.what())));
    }

    *this = dst;
  }

  path::path_type
  path::components() const
  {
    path_type path_;
    value_type::iterator
      i = value_.begin(),
      i_end = value_.end();
    if (i == i_end)
      return path_;

    // Skip volume information.
    if (absolute_get())
    {
      ++i;
#ifdef WIN32 // Skip a / after the volume information.
      ++i;
#endif
    }
    for (;i != i_end; ++i)
      if (!i->empty() && *i != ".")
        path_.push_back(*i);

    return path_;
  }

  std::string
  format_boost_fs_error(const char* what)
  {
    static const std::string ns = "boost::filesystem::";
    // Get rid of function namespace.
    std::string error = std::string(what).substr(ns.size());
    // Get rid of function name and ": ".
    error = error.substr(error.find(":") + 2);
    // Urbi errors begin with a lower case letter.
    error[0] = tolower(error[0]);
    return error;
  }
}
<commit_msg>libport: fix an error message for rename function.<commit_after>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file libport/path.cc
 ** \brief Implement libport::path.
 */

#include <cctype>
#include <iostream>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/detect-win32.h>
#include <libport/exception.hh>
#include <libport/fcntl.h>
#include <libport/format.hh>
#include <libport/path.hh>
#include <libport/sys/stat.h>
#include <libport/sys/types.h>
#include <libport/unistd.h>

GD_CATEGORY(Libport.Path);

// Implementation detail: if components() is empty and not absolute
// then the path is '.'.

namespace libport
{
  path::path(const std::string& p)
  {
    init(p);
  }

  path::path(const char* p)
  {
    init(p);
  }

  path::path(const value_type& p)
  {
    init(p.file_string());
  }

  void
  path::init(const std::string& p)
  {
    if (p.empty())
      throw invalid_path("Path can't be empty.");
#ifdef WIN32
    // We want "/" to mean "the root of the current volume" on windows.
    if (p[0] == '/')
      value_ = boost::filesystem::current_path().root_name() + p;
    else
#endif
    value_ = p;
    value_ = clean();
  }

  path&
  path::operator=(const path& rhs)
  {
    value_ = rhs.value_;
    return *this;
  }

  path&
  path::operator/=(const path& rhs)
  {
    if (rhs.absolute_get())
      throw invalid_path(
        "Rhs of concatenation is absolute: " + rhs.to_string());
#ifdef WIN32
    if (!rhs.volume_get().empty())
      throw invalid_path("concatenation of path with volume: " +
			 rhs.to_string());
#endif
    value_ /= rhs.value_;
    value_ = clean();
    return *this;
  }

  path
  path::operator/(const path& rhs) const
  {
    path res = *this;
    return res /= rhs;
  }

  std::string
  path::to_string() const
  {
    if (!value_.is_complete() && components().empty())
      return WIN32_IF(volume_get().empty() ? "." : volume_get(), ".");

    return value_.file_string();
  }

  bool
  path::operator==(const path& rhs) const
  {
    return (volume_get() == rhs.volume_get()
            && absolute_get() == rhs.absolute_get()
            && components() == rhs.components());
  }

  std::ostream&
  path::dump(std::ostream& o) const
  {
    return o << operator std::string();
  }

  std::string
  path::clean() const
  {
    std::string res;
    value_type::iterator i = value_.begin();
    value_type::iterator i_end = value_.end();
    if (i == i_end)
      return ".";

    bool first = true;
    if (absolute_get())
    {
      res = *i;
      ++i;
#ifdef WIN32
      // Add a "\" after the drive letter or network share.
      first = false;
#endif
    }

    for (;i != i_end; ++i)
    {
      // Remove the "." and empty components.
      if (!i->empty() && *i != ".")
      {
        if (!first)
          res += separator_;
        first = false;
        res += *i;
      }
    }
    return res.empty() ? "." : res;
  }

  std::string
  path::volume_get() const
  {
#ifndef WIN32
    return "";
#else
    std::string res = value_.root_name();
    if (res.find("//") == 0)
      res.replace(0, 2, "\\\\");
    return res;
#endif
  }

  path
  path::dirname() const
  {
    // dirname of / is /, dirname of . is .
    if (components().empty())
      return *this;

    std::string res = value_.parent_path().directory_string();
    return path(res.empty() ? "." : res);
  }

  bool path::exists() const
  {
    bool res;
    try
    {
      res = boost::filesystem::exists(value_);
    }
    catch (...)
    {
      res = false;
    }
    GD_FINFO_DUMP("exists: %-5s: %s", res ? "true" : "false", to_string());
    return res;
  }

  path
  path::cwd()
  {
    return path(boost::filesystem::current_path().string());
  }

  bool
  path::is_root() const
  {
    return to_string() == (volume_get() + separator_);
  }

  path
  path::parent() const
  {
    if (is_root())
      return path(volume_get().append(1, separator_));

    const std::string parent_path =
      boost::filesystem::path(to_string()).parent_path().string();

    if (parent_path.empty())
      return cwd();

    return parent_path;
  }

  std::time_t
  path::last_write_time() const
  {
    return boost::filesystem::last_write_time(
      boost::filesystem::path(to_string()));
  }

  bool path::create() const
  {
    int fd = open(to_string().c_str(),
                  O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    if (fd == -1)
      return false;
    close(fd);
    return true;
  }

  path
  path::temporary_file()
  {
#ifndef WIN32
    char tmp_name[] = "/tmp/tmp.XXXXXX";
    int fd = mkstemp(tmp_name);
    close (fd);
#else
    char tmp_dir[MAX_PATH];
    char tmp_name[MAX_PATH];

    if(GetTempPathA(sizeof(tmp_dir), tmp_dir) == 0
       || GetTempFileNameA(tmp_dir, "$$$", 0, tmp_name) == 0)
      throw Exception("cannot generate path for temporary file");
#endif
    return path(tmp_name);
  }

  void
  path::remove() const
  {
    if (!boost::filesystem::remove(value_))
      throw Exception(libport::format("cannot unlink file %s", *this));
  }

  void
  path::rename(const std::string& dst)
  {
    try
    {
      boost::filesystem::rename(value_, dst);
    }
    catch (Exception& e)
    {
      throw Exception(libport::format("cannot rename directory %s: %s",
                                      *this, format_boost_fs_error(e.what())));
    }

    *this = dst;
  }

  path::path_type
  path::components() const
  {
    path_type path_;
    value_type::iterator
      i = value_.begin(),
      i_end = value_.end();
    if (i == i_end)
      return path_;

    // Skip volume information.
    if (absolute_get())
    {
      ++i;
#ifdef WIN32 // Skip a / after the volume information.
      ++i;
#endif
    }
    for (;i != i_end; ++i)
      if (!i->empty() && *i != ".")
        path_.push_back(*i);

    return path_;
  }

  std::string
  format_boost_fs_error(const char* what)
  {
    static const std::string ns = "boost::filesystem::";
    // Get rid of function namespace.
    std::string error = std::string(what).substr(ns.size());
    // Get rid of function name and ": ".
    error = error.substr(error.find(":") + 2);
    // Urbi errors begin with a lower case letter.
    error[0] = tolower(error[0]);
    return error;
  }
}
<|endoftext|>