<commit_before>/*
   Copyright 2015 The Trustees of Princeton University

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "driver.h"
#include "impl.h"
#include "read.h"
#include "write.h"
#include "client.h"
#include "core.h"
#include "consistency.h"

// connect to the CDN
// return 0 on success
// return -ENOMEM on OOM
static int UG_impl_connect_cache( struct SG_gateway* gateway, CURL* curl, char const* url, void* cls ) {

   int rc = 0;
   char* out_url = NULL;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );

   rc = UG_driver_cdn_url( ug, url, &out_url );
   if( rc != 0 ) {
      return rc;
   }

   // set up the curl handle
   curl_easy_setopt( curl, CURLOPT_URL, out_url );
   SG_safe_free( out_url );
   return 0;
}

// update a file's manifest, in response to a remote call
// return 0 on success
// return -ENOENT if not found
// return -ESTALE if not local
// return -errno on error
// NOTE: the permissions will already have been checked by the server
static int UG_impl_manifest_patch( struct SG_gateway* gateway, struct SG_request_data* reqdat, struct SG_manifest* write_delta, void* cls ) {

   int rc = 0;
   int ref_rc = 0;
   struct fskit_entry* fent = NULL;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );

   struct fskit_core* fs = UG_state_fs( ug );
   struct UG_inode* inode = NULL;

   struct ms_client* ms = SG_gateway_ms( gateway );
   uint64_t volume_id = ms_client_get_volume_id( ms );

   rc = UG_consistency_path_ensure_fresh( gateway, reqdat->fs_path );
   if( rc != 0 ) {
      SG_error("UG_consistency_path_ensure_fresh('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }

   rc = UG_consistency_manifest_ensure_fresh( gateway, reqdat->fs_path );
   if( rc != 0 ) {
      SG_error("UG_consistency_manifest_ensure_fresh('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }

   // look up
   fent = fskit_entry_resolve_path( fs, reqdat->fs_path, reqdat->user_id, volume_id, true, &rc );
   if( fent == NULL ) {

      return rc;
   }

   inode = (struct UG_inode*)fskit_entry_get_user_data( fent );

   // must be coordinated by us
   if( UG_inode_coordinator_id( inode ) != SG_gateway_id( gateway ) ) {

      fskit_entry_unlock( fent );
      return -ESTALE;
   }

   // update the manifest
   fskit_entry_ref_entry( fent );
   rc = UG_write_patch_manifest( gateway, reqdat, inode, write_delta );

   fskit_entry_unlock( fent );

   ref_rc = fskit_entry_unref( fs, reqdat->fs_path, fent );
   if( ref_rc != 0 ) {
      SG_warn("fskit_entry_unref('%s') rc = %d\n", reqdat->fs_path, rc );
   }

   return rc;
}

// stat a file--build a manifest request, and set its mode
// return 0 on success
// return -ESTALE if the inode is not local
// return -ENOENT if we don't have it
// return -ENOMEM on OOM
// return -errno on error
static int UG_impl_stat( struct SG_gateway* gateway, struct SG_request_data* reqdat, struct SG_request_data* entity_info, mode_t* mode, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );
   struct md_entry ent_info;

   rc = UG_stat_raw( ug, reqdat->fs_path, &ent_info );
   if( rc != 0 ) {

      SG_error("UG_stat_raw('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }

   if( ent_info.coordinator != SG_gateway_id( gateway ) ) {

      // not ours
      SG_error("Not the coordinator of '%s' (it is now %" PRIu64 ")\n", reqdat->fs_path, ent_info.coordinator );
      md_entry_free( &ent_info );
      return -ESTALE;
   }

   if( mode != NULL ) {
      *mode = ent_info.mode;
   }

   if( entity_info != NULL ) {

      rc = SG_request_data_init_manifest( gateway, reqdat->fs_path, ent_info.file_id, ent_info.version, ent_info.manifest_mtime_sec, ent_info.manifest_mtime_nsec, entity_info );
      if( rc != 0 ) {

         // OOM
         md_entry_free( &ent_info );
         return -ENOMEM;
      }

      if( ent_info.type != MD_ENTRY_FILE ) {

         // not a file
         md_entry_free( &ent_info );
         return -ENOENT;
      }
   }
   md_entry_free( &ent_info );

   return 0;
}

// stat a file's block--build a manifest request, and set its mode
// return 0 on success
// return -ESTALE if the inode is not local
// return -ENOENT if we don't have it
// return -ENOMEM on OOM
// return -errno on error
static int UG_impl_stat_block( struct SG_gateway* gateway, struct SG_request_data* reqdat, struct SG_request_data* entity_info, mode_t* mode, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );
   int64_t block_version = 0;
   UG_handle_t* fi = NULL;
   struct fskit_entry* fent = NULL;
   struct UG_inode* inode = NULL;
   uint64_t file_id = 0;
   int64_t file_version = 0;
   int close_rc = 0;

   fi = UG_open( ug, reqdat->fs_path, O_RDONLY, &rc );
   if( fi == NULL ) {

      SG_error("UG_open('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }

   fskit_file_handle_rlock( fi->fh );

   fent = fskit_file_handle_get_entry( fi->fh );
   if( fent == NULL ) {
      SG_error("BUG: no entry for handle %p\n", fi->fh );
      exit(1);
   }

   fskit_entry_rlock( fent );
   inode = (struct UG_inode*)fskit_entry_get_user_data( fent );
   if( inode == NULL ) {
      SG_error("BUG: no inode for entry %p\n", fent );
      exit(1);
   }

   if( UG_inode_coordinator_id( inode ) != SG_gateway_id( gateway ) ) {

      // not ours
      SG_error("Not the coordinator of '%s' (it is now %" PRIu64 ")\n", reqdat->fs_path, UG_inode_coordinator_id( inode ) );
      fskit_entry_unlock( fent );
      fskit_file_handle_unlock( fi->fh );

      rc = UG_close( ug, fi );
      if( rc != 0 ) {

         SG_error("UG_close('%s') rc = %d\n", reqdat->fs_path, rc );
      }
      return rc;
   }

   file_id = UG_inode_file_id( inode );
   file_version = UG_inode_file_version( inode );

   if( mode != NULL ) {
      *mode = fskit_entry_get_mode( fent );
   }
   if( entity_info != NULL ) {
      rc = UG_getblockinfo( ug, reqdat->block_id, &block_version, NULL, fi );
   }

   fskit_entry_unlock( fent );
   fskit_file_handle_unlock( fi->fh );
   inode = NULL;

   if( rc != 0 ) {

      SG_error("UG_getblockinfo(%s[%" PRIu64 "]) rc = %d\n", reqdat->fs_path, reqdat->block_id, rc);
      goto UG_impl_stat_block_out;
   }

   rc = SG_request_data_init_block( gateway, reqdat->fs_path, file_id, file_version, reqdat->block_id, block_version, entity_info );
   if( rc != 0 ) {

      SG_error("SG_request_data_init_block rc = %d\n", rc );
      goto UG_impl_stat_block_out;
   }

UG_impl_stat_block_out:

   close_rc = UG_close( ug, fi );
   if( close_rc != 0 ) {

      SG_error("UG_close('%s') rc = %d\n", reqdat->fs_path, close_rc );
   }

   return rc;
}

// remote request to rename a file.
// there can be at most one ongoing rename at a given moment.
// return 0 on success
// return -ENOMEM on OOM
// return -EBUSY if the given path is being renamed already
// return -ESTALE if the node is not local
// return -errno on error
static int UG_impl_rename( struct SG_gateway* gateway, struct SG_request_data* reqdat, char const* new_path, void* cls ) {

   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );

   return UG_rename( ug, reqdat->fs_path, new_path );
}

// truncate a file
// return 0 on success
// return -errno on error
static int UG_impl_truncate( struct SG_gateway* gateway, struct SG_request_data* reqdat, uint64_t new_size, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );
   struct fskit_core* fs = UG_state_fs( ug );

   struct ms_client* ms = (struct ms_client*)SG_gateway_ms( gateway );
   uint64_t volume_id = ms_client_get_volume_id( ms );

   // truncate locally.  The MS will be informed as part of the user route.
   rc = fskit_trunc( fs, reqdat->fs_path, reqdat->user_id, volume_id, new_size );
   if( rc != 0 ) {

      SG_error("fskit_trunc( '%s', %" PRIu64 ") rc = %d\n", reqdat->fs_path, new_size, rc);
   }

   return rc;
}

// detach a file
// return 0 on success
// return -errno on error
static int UG_impl_detach( struct SG_gateway* gateway, struct SG_request_data* reqdat, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );
   struct fskit_core* fs = UG_state_fs( ug );

   struct ms_client* ms = (struct ms_client*)SG_gateway_ms( gateway );
   uint64_t volume_id = ms_client_get_volume_id( ms );

   struct stat sb;
   char const* method = NULL;

   // file or directory?
   rc = fskit_stat( fs, reqdat->fs_path, 0, 0, &sb );
   if( rc != 0 ) {

      return rc;
   }

   if( S_ISREG( sb.st_mode ) ) {

      // unlink locally.  The MS will be informed as part of the user route.
      method = "fskit_unlink";
      rc = fskit_unlink( fs, reqdat->fs_path, reqdat->user_id, volume_id );
   }
   else {

      // rmdir locally.  The MS will be informed as part of the user route
      method = "fskit_rmdir";
      rc = fskit_rmdir( fs, reqdat->fs_path, reqdat->user_id, volume_id );
   }

   if( rc != 0 ) {

      SG_error("%s( '%s' ) rc = %d\n", method, reqdat->fs_path, rc);
   }

   return 0;
}

// on config reload, re-calculate the set of replica gateway IDs
// return 0 on success
// return negative on error
static int UG_impl_config_change( struct SG_gateway* gateway, int driver_reload_rc, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)cls;

   rc = UG_state_reload_replica_gateway_ids( ug );
   if( rc != 0 ) {

      SG_error("UG_state_reload_replica_gateway_ids rc = %d\n", rc );
   }

   return rc;
}

// set up the gateway's method implementation
// always succeeds
int UG_impl_install_methods( struct SG_gateway* gateway ) {

   SG_impl_connect_cache( gateway, UG_impl_connect_cache );
   SG_impl_stat( gateway, UG_impl_stat );
   SG_impl_stat_block( gateway, UG_impl_stat_block );
   SG_impl_truncate( gateway, UG_impl_truncate );
   SG_impl_rename( gateway, UG_impl_rename );
   SG_impl_detach( gateway, UG_impl_detach );

   SG_impl_patch_manifest( gateway, UG_impl_manifest_patch );
   SG_impl_config_change( gateway, UG_impl_config_change );
   SG_impl_serialize( gateway, UG_driver_chunk_serialize );
   SG_impl_deserialize( gateway, UG_driver_chunk_deserialize );

   return 0;
}

<commit_msg>write_delta carries new file size on write<commit_after>/*
   Copyright 2015 The Trustees of Princeton University

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "driver.h"
#include "impl.h"
#include "read.h"
#include "write.h"
#include "client.h"
#include "core.h"
#include "consistency.h"

// connect to the CDN
// return 0 on success
// return -ENOMEM on OOM
static int UG_impl_connect_cache( struct SG_gateway* gateway, CURL* curl, char const* url, void* cls ) {

   int rc = 0;
   char* out_url = NULL;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );

   rc = UG_driver_cdn_url( ug, url, &out_url );
   if( rc != 0 ) {
      return rc;
   }

   // set up the curl handle
   curl_easy_setopt( curl, CURLOPT_URL, out_url );
   SG_safe_free( out_url );
   return 0;
}

// update a file's manifest, in response to a remote call
// write_delta must contain the new file size
// return 0 on success
// return -ENOENT if not found
// return -ESTALE if not local
// return -errno on error
// NOTE: the permissions will already have been checked by the server
static int UG_impl_manifest_patch( struct SG_gateway* gateway, struct SG_request_data* reqdat, struct SG_manifest* write_delta, void* cls ) {

   int rc = 0;
   int ref_rc = 0;
   struct fskit_entry* fent = NULL;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );

   struct fskit_core* fs = UG_state_fs( ug );
   struct UG_inode* inode = NULL;

   struct ms_client* ms = SG_gateway_ms( gateway );
   uint64_t volume_id = ms_client_get_volume_id( ms );

   rc = UG_consistency_path_ensure_fresh( gateway, reqdat->fs_path );
   if( rc != 0 ) {
      SG_error("UG_consistency_path_ensure_fresh('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }

   rc = UG_consistency_manifest_ensure_fresh( gateway, reqdat->fs_path );
   if( rc != 0 ) {
      SG_error("UG_consistency_manifest_ensure_fresh('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }

   // look up
   fent = fskit_entry_resolve_path( fs, reqdat->fs_path, reqdat->user_id, volume_id, true, &rc );
   if( fent == NULL ) {

      return rc;
   }

   inode = (struct UG_inode*)fskit_entry_get_user_data( fent );

   // must be coordinated by us
   if( UG_inode_coordinator_id( inode ) != SG_gateway_id( gateway ) ) {

      fskit_entry_unlock( fent );
      return -ESTALE;
   }

   // update the manifest
   fskit_entry_ref_entry( fent );
   rc = UG_write_patch_manifest( gateway, reqdat, inode, write_delta );

   fskit_entry_unlock( fent );

   ref_rc = fskit_entry_unref( fs, reqdat->fs_path, fent );
   if( ref_rc != 0 ) {
      SG_warn("fskit_entry_unref('%s') rc = %d\n", reqdat->fs_path, rc );
   }

   return rc;
}

// stat a file--build a manifest request, and set its mode
// return 0 on success
// return -ESTALE if the inode is not local
// return -ENOENT if we don't have it
// return -ENOMEM on OOM
// return -errno on error
static int UG_impl_stat( struct SG_gateway* gateway, struct SG_request_data* reqdat, struct SG_request_data* entity_info, mode_t* mode, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );
   struct md_entry ent_info;

   rc = UG_stat_raw( ug, reqdat->fs_path, &ent_info );
   if( rc != 0 ) {

      SG_error("UG_stat_raw('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }

   if( ent_info.coordinator != SG_gateway_id( gateway ) ) {

      // not ours
      SG_error("Not the coordinator of '%s' (it is now %" PRIu64 ")\n", reqdat->fs_path, ent_info.coordinator );
      md_entry_free( &ent_info );
      return -ESTALE;
   }

   if( mode != NULL ) {
      *mode = ent_info.mode;
   }

   if( entity_info != NULL ) {

      rc = SG_request_data_init_manifest( gateway, reqdat->fs_path, ent_info.file_id, ent_info.version, ent_info.manifest_mtime_sec, ent_info.manifest_mtime_nsec, entity_info );
      if( rc != 0 ) {

         // OOM
         md_entry_free( &ent_info );
         return -ENOMEM;
      }

      if( ent_info.type != MD_ENTRY_FILE ) {

         // not a file
         md_entry_free( &ent_info );
         return -ENOENT;
      }
   }
   md_entry_free( &ent_info );

   return 0;
}

// stat a file's block--build a manifest request, and set its mode
// return 0 on success
// return -ESTALE if the inode is not local
// return -ENOENT if we don't have it
// return -ENOMEM on OOM
// return -errno on error
static int UG_impl_stat_block( struct SG_gateway* gateway, struct SG_request_data* reqdat, struct SG_request_data* entity_info, mode_t* mode, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );
   int64_t block_version = 0;
   UG_handle_t* fi = NULL;
   struct fskit_entry* fent = NULL;
   struct UG_inode* inode = NULL;
   uint64_t file_id = 0;
   int64_t file_version = 0;
   int close_rc = 0;

   fi = UG_open( ug, reqdat->fs_path, O_RDONLY, &rc );
   if( fi == NULL ) {

      SG_error("UG_open('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }

   fskit_file_handle_rlock( fi->fh );

   fent = fskit_file_handle_get_entry( fi->fh );
   if( fent == NULL ) {
      SG_error("BUG: no entry for handle %p\n", fi->fh );
      exit(1);
   }

   fskit_entry_rlock( fent );
   inode = (struct UG_inode*)fskit_entry_get_user_data( fent );
   if( inode == NULL ) {
      SG_error("BUG: no inode for entry %p\n", fent );
      exit(1);
   }

   if( UG_inode_coordinator_id( inode ) != SG_gateway_id( gateway ) ) {

      // not ours
      SG_error("Not the coordinator of '%s' (it is now %" PRIu64 ")\n", reqdat->fs_path, UG_inode_coordinator_id( inode ) );
      fskit_entry_unlock( fent );
      fskit_file_handle_unlock( fi->fh );

      rc = UG_close( ug, fi );
      if( rc != 0 ) {

         SG_error("UG_close('%s') rc = %d\n", reqdat->fs_path, rc );
      }
      return rc;
   }

   file_id = UG_inode_file_id( inode );
   file_version = UG_inode_file_version( inode );

   if( mode != NULL ) {
      *mode = fskit_entry_get_mode( fent );
   }
   if( entity_info != NULL ) {
      rc = UG_getblockinfo( ug, reqdat->block_id, &block_version, NULL, fi );
   }

   fskit_entry_unlock( fent );
   fskit_file_handle_unlock( fi->fh );
   inode = NULL;

   if( rc != 0 ) {

      SG_error("UG_getblockinfo(%s[%" PRIu64 "]) rc = %d\n", reqdat->fs_path, reqdat->block_id, rc);
      goto UG_impl_stat_block_out;
   }

   rc = SG_request_data_init_block( gateway, reqdat->fs_path, file_id, file_version, reqdat->block_id, block_version, entity_info );
   if( rc != 0 ) {

      SG_error("SG_request_data_init_block rc = %d\n", rc );
      goto UG_impl_stat_block_out;
   }

UG_impl_stat_block_out:

   close_rc = UG_close( ug, fi );
   if( close_rc != 0 ) {

      SG_error("UG_close('%s') rc = %d\n", reqdat->fs_path, close_rc );
   }

   return rc;
}

// remote request to rename a file.
// there can be at most one ongoing rename at a given moment.
// return 0 on success
// return -ENOMEM on OOM
// return -EBUSY if the given path is being renamed already
// return -ESTALE if the node is not local
// return -errno on error
static int UG_impl_rename( struct SG_gateway* gateway, struct SG_request_data* reqdat, char const* new_path, void* cls ) {

   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );

   return UG_rename( ug, reqdat->fs_path, new_path );
}

// truncate a file
// return 0 on success
// return -errno on error
static int UG_impl_truncate( struct SG_gateway* gateway, struct SG_request_data* reqdat, uint64_t new_size, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );
   struct fskit_core* fs = UG_state_fs( ug );

   struct ms_client* ms = (struct ms_client*)SG_gateway_ms( gateway );
   uint64_t volume_id = ms_client_get_volume_id( ms );

   // truncate locally.  The MS will be informed as part of the user route.
   rc = fskit_trunc( fs, reqdat->fs_path, reqdat->user_id, volume_id, new_size );
   if( rc != 0 ) {

      SG_error("fskit_trunc( '%s', %" PRIu64 ") rc = %d\n", reqdat->fs_path, new_size, rc);
   }

   return rc;
}

// detach a file
// return 0 on success
// return -errno on error
static int UG_impl_detach( struct SG_gateway* gateway, struct SG_request_data* reqdat, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );
   struct fskit_core* fs = UG_state_fs( ug );

   struct ms_client* ms = (struct ms_client*)SG_gateway_ms( gateway );
   uint64_t volume_id = ms_client_get_volume_id( ms );

   struct stat sb;
   char const* method = NULL;

   // file or directory?
   rc = fskit_stat( fs, reqdat->fs_path, 0, 0, &sb );
   if( rc != 0 ) {

      return rc;
   }

   if( S_ISREG( sb.st_mode ) ) {

      // unlink locally.  The MS will be informed as part of the user route.
      method = "fskit_unlink";
      rc = fskit_unlink( fs, reqdat->fs_path, reqdat->user_id, volume_id );
   }
   else {

      // rmdir locally.  The MS will be informed as part of the user route
      method = "fskit_rmdir";
      rc = fskit_rmdir( fs, reqdat->fs_path, reqdat->user_id, volume_id );
   }

   if( rc != 0 ) {

      SG_error("%s( '%s' ) rc = %d\n", method, reqdat->fs_path, rc);
   }

   return 0;
}

// on config reload, re-calculate the set of replica gateway IDs
// return 0 on success
// return negative on error
static int UG_impl_config_change( struct SG_gateway* gateway, int driver_reload_rc, void* cls ) {

   int rc = 0;
   struct UG_state* ug = (struct UG_state*)cls;

   rc = UG_state_reload_replica_gateway_ids( ug );
   if( rc != 0 ) {

      SG_error("UG_state_reload_replica_gateway_ids rc = %d\n", rc );
   }

   return rc;
}

// set up the gateway's method implementation
// always succeeds
int UG_impl_install_methods( struct SG_gateway* gateway ) {

   SG_impl_connect_cache( gateway, UG_impl_connect_cache );
   SG_impl_stat( gateway, UG_impl_stat );
   SG_impl_stat_block( gateway, UG_impl_stat_block );
   SG_impl_truncate( gateway, UG_impl_truncate );
   SG_impl_rename( gateway, UG_impl_rename );
   SG_impl_detach( gateway, UG_impl_detach );

   SG_impl_patch_manifest( gateway, UG_impl_manifest_patch );
   SG_impl_config_change( gateway, UG_impl_config_change );
   SG_impl_serialize( gateway, UG_driver_chunk_serialize );
   SG_impl_deserialize( gateway, UG_driver_chunk_deserialize );

   return 0;
}

<|endoftext|>


<commit_before>/**
 * @file   UvUtils.hpp
 * @brief  UvUtils class prototype.
 * @author zer0
 * @date   2016-11-03
 */

#ifndef __INCLUDE_LIBTBAG__LIBTBAG_UTIL_UVUTILS_HPP__
#define __INCLUDE_LIBTBAG__LIBTBAG_UTIL_UVUTILS_HPP__

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#include <libtbag/config.h>
#include <libtbag/predef.hpp>
#include <libtbag/Noncopyable.hpp>
#include <libtbag/debug/ErrorCode.hpp>

#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
# include <cstdint>
typedef intptr_t ssize_t;
# define _SSIZE_T_
# define _SSIZE_T_DEFINED
#endif

#include <string>

// -------------------
NAMESPACE_LIBTBAG_OPEN
// -------------------

namespace util {

#ifndef TBAG_UTIL_UV_HANDLE_MAP
#define TBAG_UTIL_UV_HANDLE_MAP(_TBAG_HANDLE_XX, _TBAG_REQ_XX, _TBAG_ETC_XX) \
    /* Handle types. */                      \
    _TBAG_HANDLE_XX(LOOP    , uv_loop_t)     \
    _TBAG_HANDLE_XX(HANDLE  , uv_handle_t)   \
    _TBAG_HANDLE_XX(STREAM  , uv_stream_t)   \
    _TBAG_HANDLE_XX(TCP     , uv_tcp_t)      \
    _TBAG_HANDLE_XX(UDP     , uv_udp_t)      \
    _TBAG_HANDLE_XX(PIPE    , uv_pipe_t)     \
    _TBAG_HANDLE_XX(TTY     , uv_tty_t)      \
    _TBAG_HANDLE_XX(POLL    , uv_poll_t)     \
    _TBAG_HANDLE_XX(TIMER   , uv_timer_t)    \
    _TBAG_HANDLE_XX(PREPARE , uv_prepare_t)  \
    _TBAG_HANDLE_XX(CHECK   , uv_check_t)    \
    _TBAG_HANDLE_XX(IDLE    , uv_idle_t)     \
    _TBAG_HANDLE_XX(ASYNC   , uv_async_t)    \
    _TBAG_HANDLE_XX(PROCESS , uv_process_t)  \
    _TBAG_HANDLE_XX(FS_EVENT, uv_fs_event_t) \
    _TBAG_HANDLE_XX(FS_POLL , uv_fs_poll_t)  \
    _TBAG_HANDLE_XX(SIGNAL  , uv_signal_t)   \
    /* Request types. */                        \
    _TBAG_REQ_XX(REQ        , uv_req_t)         \
    _TBAG_REQ_XX(GETADDRINFO, uv_getaddrinfo_t) \
    _TBAG_REQ_XX(GETNAMEINFO, uv_getnameinfo_t) \
    _TBAG_REQ_XX(SHUTDOWN   , uv_shutdown_t)    \
    _TBAG_REQ_XX(WRITE      , uv_write_t)       \
    _TBAG_REQ_XX(CONNECT    , uv_connect_t)     \
    _TBAG_REQ_XX(UDP_SEND   , uv_udp_send_t)    \
    _TBAG_REQ_XX(FS         , uv_fs_t)          \
    _TBAG_REQ_XX(WORK       , uv_work_t)        \
    /* None of the above. */                                \
    _TBAG_ETC_XX(CPU_INFO         , uv_cpu_info_t)          \
    _TBAG_ETC_XX(INTERFACE_ADDRESS, uv_interface_address_t) \
    _TBAG_ETC_XX(DIRENT           , uv_dirent_t)            \
    _TBAG_ETC_XX(PASSWD           , uv_passwd_t)            \
    /* -- END -- */
#endif

#ifndef TBAG_UTIL_UV_HANDLE_MAP_ALL
#define TBAG_UTIL_UV_HANDLE_MAP_ALL(_TBAG_XX) \
    TBAG_UTIL_UV_HANDLE_MAP(_TBAG_XX, _TBAG_XX, _TBAG_XX)
#endif

/**
 * Table of libuv types.
 *
 * @author zer0
 * @date   2016-12-07
 */
enum class UvType : int
{
    UNKNOWN = 0,
#define _TBAG_XX(name, type) name,
    TBAG_UTIL_UV_HANDLE_MAP_ALL(_TBAG_XX)
#undef _TBAG_XX
    SIZE
};

/**
 * Table of libuv handle types.
 *
 * @author zer0
 * @date   2016-12-17
 */
enum class UvHandleType : int
{
    UNKNOWN = 0,
#define _TBAG_XX(name, type) name = static_cast<int>(UvType::name),
#define _TBAG_NX(name, type)
    TBAG_UTIL_UV_HANDLE_MAP(_TBAG_XX, _TBAG_NX, _TBAG_NX)
#undef _TBAG_XX
#undef _TBAG_NX
    SIZE
};

TBAG_API void initUv();
TBAG_API char const * getUvHandleName(void * handle);

/**
 * @remarks
 *  Same this code:
 *  @code
 *    const char* uv_strerror(int err);
 *  @endcode
 */
TBAG_API std::string getUvErrorString(int uv_error_code);

/**
 * @remarks
 *  Same this code:
 *  @code
 *    const char* uv_err_name(int err);
 *  @endcode
 */
TBAG_API std::string getUvErrorName(int uv_error_code);

TBAG_API bool isUvHandle(UvType type);
TBAG_API bool isUvRequest(UvType type);

/**
 * libuv native type utility class.
 *
 * @author zer0
 * @date   2016-12-07
 */
class TBAG_API UvNative : public Noncopyable
{
public:
    using Type = UvType;

private:
    Type const TYPE;
    void * _native;

public:
    UvNative(Type type);
    ~UvNative();

public:
    inline operator bool() const TBAG_NOEXCEPT
    { return _native != nullptr; }

public:
    inline Type getType() const TBAG_NOEXCEPT
    { return TYPE; }
    inline bool isHandle() const TBAG_NOEXCEPT
    { return isUvHandle(TYPE); }
    inline bool isRequest() const TBAG_NOEXCEPT
    { return isUvRequest(TYPE); }

public:
    inline void * getNative() TBAG_NOEXCEPT
    { return _native; }
    inline void const * getNative() const TBAG_NOEXCEPT
    { return _native; }

public:
    template <typename T>
    inline T * castNative() const TBAG_NOEXCEPT
    { return static_cast<T*>(_native); }
};

/**
 * libuv handle type utility class.
 *
 * @author zer0
 * @date   2016-12-17
 */
class TBAG_API UvHandle : public UvNative
{
public:
    struct OnCloseCallback
    {
        virtual void onClose() = 0;
    };

private:
    OnCloseCallback * _on_close_cb;

public:
    UvHandle(UvHandleType type);
    ~UvHandle();

public:
    inline void setOnCloseCallback(OnCloseCallback * callback) TBAG_NOEXCEPT
    { _on_close_cb = callback; }

public:
    bool isClosing() const TBAG_NOEXCEPT;
    ErrorCode close();

public:
    void onClose(void * handle);
};

} // namespace util

// --------------------
NAMESPACE_LIBTBAG_CLOSE
// --------------------

#endif // __INCLUDE_LIBTBAG__LIBTBAG_UTIL_UVUTILS_HPP__

<commit_msg>Refactoring enum types in UvUtils package.<commit_after>/**
 * @file   UvUtils.hpp
 * @brief  UvUtils class prototype.
 * @author zer0
 * @date   2016-11-03
 */

#ifndef __INCLUDE_LIBTBAG__LIBTBAG_UTIL_UVUTILS_HPP__
#define __INCLUDE_LIBTBAG__LIBTBAG_UTIL_UVUTILS_HPP__

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#include <libtbag/config.h>
#include <libtbag/predef.hpp>
#include <libtbag/Noncopyable.hpp>
#include <libtbag/debug/ErrorCode.hpp>

#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
# include <cstdint>
typedef intptr_t ssize_t;
# define _SSIZE_T_
# define _SSIZE_T_DEFINED
#endif

#include <string>

// -------------------
NAMESPACE_LIBTBAG_OPEN
// -------------------

namespace util {

#ifndef TBAG_UTIL_UV_HANDLE_MAP
#define TBAG_UTIL_UV_HANDLE_MAP(_TBAG_HANDLE_XX, _TBAG_REQ_XX, _TBAG_ETC_XX) \
    /* Handle types. */                      \
    _TBAG_HANDLE_XX(LOOP    , uv_loop_t)     \
    _TBAG_HANDLE_XX(HANDLE  , uv_handle_t)   \
    _TBAG_HANDLE_XX(STREAM  , uv_stream_t)   \
    _TBAG_HANDLE_XX(TCP     , uv_tcp_t)      \
    _TBAG_HANDLE_XX(UDP     , uv_udp_t)      \
    _TBAG_HANDLE_XX(PIPE    , uv_pipe_t)     \
    _TBAG_HANDLE_XX(TTY     , uv_tty_t)      \
    _TBAG_HANDLE_XX(POLL    , uv_poll_t)     \
    _TBAG_HANDLE_XX(TIMER   , uv_timer_t)    \
    _TBAG_HANDLE_XX(PREPARE , uv_prepare_t)  \
    _TBAG_HANDLE_XX(CHECK   , uv_check_t)    \
    _TBAG_HANDLE_XX(IDLE    , uv_idle_t)     \
    _TBAG_HANDLE_XX(ASYNC   , uv_async_t)    \
    _TBAG_HANDLE_XX(PROCESS , uv_process_t)  \
    _TBAG_HANDLE_XX(FS_EVENT, uv_fs_event_t) \
    _TBAG_HANDLE_XX(FS_POLL , uv_fs_poll_t)  \
    _TBAG_HANDLE_XX(SIGNAL  , uv_signal_t)   \
    /* Request types. */                        \
    _TBAG_REQ_XX(REQ        , uv_req_t)         \
    _TBAG_REQ_XX(GETADDRINFO, uv_getaddrinfo_t) \
    _TBAG_REQ_XX(GETNAMEINFO, uv_getnameinfo_t) \
    _TBAG_REQ_XX(SHUTDOWN   , uv_shutdown_t)    \
    _TBAG_REQ_XX(WRITE      , uv_write_t)       \
    _TBAG_REQ_XX(CONNECT    , uv_connect_t)     \
    _TBAG_REQ_XX(UDP_SEND   , uv_udp_send_t)    \
    _TBAG_REQ_XX(FS         , uv_fs_t)          \
    _TBAG_REQ_XX(WORK       , uv_work_t)        \
    /* None of the above. */                                \
    _TBAG_ETC_XX(CPU_INFO         , uv_cpu_info_t)          \
    _TBAG_ETC_XX(INTERFACE_ADDRESS, uv_interface_address_t) \
    _TBAG_ETC_XX(DIRENT           , uv_dirent_t)            \
    _TBAG_ETC_XX(PASSWD           , uv_passwd_t)            \
    /* -- END -- */
#endif

#ifndef TBAG_UTIL_UV_HANDLE_MAP_ALL
#define TBAG_UTIL_UV_HANDLE_MAP_ALL(_TBAG_XX) \
    TBAG_UTIL_UV_HANDLE_MAP(_TBAG_XX, _TBAG_XX, _TBAG_XX)
#endif

typedef int UvPodType;

/**
 * Table of libuv types.
 *
 * @author zer0
 * @date   2016-12-07
 */
enum class UvType : UvPodType
{
    UNKNOWN = 0,
#define _TBAG_XX(name, type) name,
    TBAG_UTIL_UV_HANDLE_MAP_ALL(_TBAG_XX)
#undef _TBAG_XX
    _SIZE_
};

// @formatter:off
#define _TBAG_XX(name, type) name = static_cast<UvPodType>(UvType::name),
#define _TBAG_NOT(name, type)
enum class UvHandleType  : UvPodType { _START_NUMBER_ = -1, TBAG_UTIL_UV_HANDLE_MAP(_TBAG_XX, _TBAG_NOT, _TBAG_NOT) _SIZE_ };
enum class UvRequsetType : UvPodType { _START_NUMBER_ = -1, TBAG_UTIL_UV_HANDLE_MAP(_TBAG_NOT, _TBAG_XX, _TBAG_NOT) _SIZE_ };
enum class UvEtcType     : UvPodType { _START_NUMBER_ = -1, TBAG_UTIL_UV_HANDLE_MAP(_TBAG_NOT, _TBAG_NOT, _TBAG_XX) _SIZE_ };
#undef _TBAG_XX
#undef _TBAG_NOT
// @formatter:on

TBAG_API void initUv();
TBAG_API char const * getUvHandleName(void * handle);

/**
 * @remarks
 *  Same this code:
 *  @code
 *    const char* uv_strerror(int err);
 *  @endcode
 */
TBAG_API std::string getUvErrorString(int uv_error_code);

/**
 * @remarks
 *  Same this code:
 *  @code
 *    const char* uv_err_name(int err);
 *  @endcode
 */
TBAG_API std::string getUvErrorName(int uv_error_code);

TBAG_API bool isUvHandle(UvType type);
TBAG_API bool isUvRequest(UvType type);

/**
 * libuv native type utility class.
 *
 * @author zer0
 * @date   2016-12-07
 */
class TBAG_API UvNative : public Noncopyable
{
public:
    using Type = UvType;

private:
    Type const TYPE;
    void * _native;

public:
    UvNative(Type type);
    ~UvNative();

public:
    inline operator bool() const TBAG_NOEXCEPT
    { return _native != nullptr; }

public:
    inline Type getType() const TBAG_NOEXCEPT
    { return TYPE; }
    inline bool isHandle() const TBAG_NOEXCEPT
    { return isUvHandle(TYPE); }
    inline bool isRequest() const TBAG_NOEXCEPT
    { return isUvRequest(TYPE); }

public:
    inline void * getNative() TBAG_NOEXCEPT
    { return _native; }
    inline void const * getNative() const TBAG_NOEXCEPT
    { return _native; }

public:
    template <typename T>
    inline T * castNative() const TBAG_NOEXCEPT
    { return static_cast<T*>(_native); }
};

/**
 * libuv handle type utility class.
 *
 * @author zer0
 * @date   2016-12-17
 */
class TBAG_API UvHandle : public UvNative
{
public:
    struct OnCloseCallback
    {
        virtual void onClose() = 0;
    };

private:
    OnCloseCallback * _on_close_cb;

public:
    UvHandle(UvHandleType type);
    ~UvHandle();

public:
    inline void setOnCloseCallback(OnCloseCallback * callback) TBAG_NOEXCEPT
    { _on_close_cb = callback; }

public:
    bool isClosing() const TBAG_NOEXCEPT;
    ErrorCode close();

public:
    void onClose(void * handle);
};

} // namespace util

// --------------------
NAMESPACE_LIBTBAG_CLOSE
// --------------------

#endif // __INCLUDE_LIBTBAG__LIBTBAG_UTIL_UVUTILS_HPP__

<|endoftext|>


<commit_before>//
// ********************************************************************
// * License and Disclaimer                                           *
// *                                                                  *
// * The  Geant4 software  is  copyright of the Copyright Holders  of *
// * the Geant4 Collaboration.  It is provided  under  the terms  and *
// * conditions of the Geant4 Software License,  included in the file *
// * LICENSE and available at  http://cern.ch/geant4/license .  These *
// * include a list of copyright holders.                             *
// *                                                                  *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work  make  any representation or  warranty, express or implied, *
// * regarding  this  software system or assume any liability for its *
// * use.  Please see the license in the file  LICENSE  and URL above *
// * for the full disclaimer and the limitation of liability.         *
// *                                                                  *
// * This  code  implementation is the result of  the  scientific and *
// * technical work of the GEANT4 collaboration.                      *
// * By using,  copying,  modifying or  distributing the software (or *
// * any work based  on the software)  you  agree  to acknowledge its *
// * use  in  resulting  scientific  publications,  and indicate your *
// * acceptance of all terms of the Geant4 Software license.          *
// ********************************************************************
//
// $Id: exampleB4a.cc 75215 2013-10-29 16:07:06Z gcosmo $
//
/// \file exampleB4a.cc
/// \brief Main program of the B4a example

#include "DetectorConstruction.hh"
#include "ActionInitialization.hh"

#ifdef G4MULTITHREADED
#include "G4MTRunManager.hh"
#else
#include "G4RunManager.hh"
#endif

#include "G4UImanager.hh"
#include "G4UIcommand.hh"
#include "FTFP_BERT.hh"
#include "QGSP_BERT.hh"
#include "QGSP_BERT_HP.hh"

#include "G4PhysListFactory.hh"
#include "G4RadioactiveDecayPhysics.hh"

#include "Randomize.hh"

#ifdef G4VIS_USE
#include "G4VisExecutive.hh"
#endif

#ifdef G4UI_USE
#include "G4UIExecutive.hh"
#endif

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

namespace {
    void PrintUsage() {
        G4cerr << " Usage: " << G4endl;
        G4cerr << " exampleB4a [-m macro ] [-u UIsession] [-t nThreads]" << G4endl;
        G4cerr << "   note: -t option is available only for multi-threaded mode."
        << G4endl;
    }
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

int main(int argc,char** argv)
{
    // Evaluate arguments
    //
    if ( argc > 7 ) {
        PrintUsage();
        return 1;
    }

    G4String macro;
    G4String session;
#ifdef G4MULTITHREADED
    G4int nThreads = 0;
#endif
    for ( G4int i=1; i<argc; i=i+2 ) {
        if      ( G4String(argv[i]) == "-m" ) macro = argv[i+1];
        else if ( G4String(argv[i]) == "-u" ) session = argv[i+1];
#ifdef G4MULTITHREADED
        else if ( G4String(argv[i]) == "-t" ) {
            nThreads = G4UIcommand::ConvertToInt(argv[i+1]);
        }
#endif
        else {
            PrintUsage();
            return 1;
        }
    }

    // Choose the Random engine
    //
    //G4Random::setTheEngine(new CLHEP::RanecuEngine);

    CLHEP::RanluxEngine defaultEngine( 1234567, 4 );
    G4Random::setTheEngine( &defaultEngine );
    G4int seed = time( NULL );
    G4Random::setTheSeed( seed );

    // Construct the default run manager
    //
#ifdef G4MULTITHREADED
    G4MTRunManager * runManager = new G4MTRunManager;
    runManager->SetNumberOfThreads(1);

    /*
     if ( nThreads > 0 ) {
     runManager->SetNumberOfThreads(4);
     }
     */
#else
    G4RunManager * runManager = new G4RunManager;
#endif

    // Set mandatory initialization classes
    //
    DetectorConstruction* detConstruction = new DetectorConstruction();
    runManager->SetUserInitialization(detConstruction);

    /*
    G4VModularPhysicsList* physicsList = new QGSP_BERT;
    runManager->SetUserInitialization(physicsList);
    */

    ////////////////////////////////////////////////////////////////////
    //      Initialising the Physics List with Radioactive Decay
    ////////////////////////////////////////////////////////////////////

    G4PhysListFactory factory;
    G4VModularPhysicsList* phys = 0;
    G4String physName = "QGSP_BERT";
    // reference PhysicsList via its name
    phys = factory.GetReferencePhysList(physName);
    phys->RegisterPhysics(new G4RadioactiveDecayPhysics());
    runManager->SetUserInitialization(phys);

    ActionInitialization* actionInitialization
    = new ActionInitialization(detConstruction);
    runManager->SetUserInitialization(actionInitialization);

    // Initialize G4 kernel
    //
    runManager->Initialize();

#ifdef G4VIS_USE
    // Initialize visualization
    G4VisManager* visManager = new G4VisExecutive;
    // G4VisExecutive can take a verbosity argument - see /vis/verbose guidance.
    // G4VisManager* visManager = new G4VisExecutive("Quiet");
    visManager->Initialize();
#endif

    // Get the pointer to the User Interface manager
    G4UImanager* UImanager = G4UImanager::GetUIpointer();

    if ( macro.size() ) {
        // batch mode
        G4String command = "/control/execute ";
        UImanager->ApplyCommand(command+macro);
    }
    else  {
        // interactive mode : define UI session
#ifdef G4UI_USE
        G4UIExecutive* ui = new G4UIExecutive(argc, argv, session);
#ifdef G4VIS_USE
        UImanager->ApplyCommand("/control/execute init_vis.mac");
#else
        UImanager->ApplyCommand("/control/execute init.mac");
#endif
        if (ui->IsGUI())
            UImanager->ApplyCommand("/control/execute gui.mac");
        ui->SessionStart();
        delete ui;
#endif
    }

    // Job termination
    // Free the store: user actions, physics_list and detector_description are
    // owned and deleted by the run manager, so they should not be deleted
    // in the main() program !

#ifdef G4VIS_USE
    delete visManager;
#endif
    delete runManager;

    return 0;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
<commit_msg>remove<commit_after><|endoftext|>


<commit_before>/**********************************************************\

  Auto-generated Chimera.cpp

  This file contains the auto-generated main plugin object
  implementation for the Chimera project

\**********************************************************/

#include "ChimeraAPI.h"

#include "Chimera.h"
#include "parrot/api.h"

///////////////////////////////////////////////////////////////////////////////
/// @fn Chimera::StaticInitialize()
///
/// @brief  Called from PluginFactory::globalPluginInitialize()
///
/// @see FB::FactoryBase::globalPluginInitialize
///////////////////////////////////////////////////////////////////////////////
void Chimera::StaticInitialize()
{
    // Place one-time initialization stuff here; As of FireBreath 1.4 this should only
    // be called once per process
}

///////////////////////////////////////////////////////////////////////////////
/// @fn Chimera::StaticInitialize()
///
/// @brief  Called from PluginFactory::globalPluginDeinitialize()
///
/// @see FB::FactoryBase::globalPluginDeinitialize
///////////////////////////////////////////////////////////////////////////////
void Chimera::StaticDeinitialize()
{
    // Place one-time deinitialization stuff here. As of FireBreath 1.4 this should
    // always be called just before the plugin library is unloaded
}

///////////////////////////////////////////////////////////////////////////////
/// @brief  Chimera constructor.  Note that your API is not available
///         at this point, nor the window.  For best results wait to use
///         the JSAPI object until the onPluginReady method is called
///////////////////////////////////////////////////////////////////////////////
Chimera::Chimera()
{
}

///////////////////////////////////////////////////////////////////////////////
/// @brief  Chimera destructor.
///////////////////////////////////////////////////////////////////////////////
Chimera::~Chimera()
{
    // This is optional, but if you reset m_api (the shared_ptr to your JSAPI
    // root object) and tell the host to free the retained JSAPI objects then
    // unless you are holding another shared_ptr reference to your JSAPI object
    // they will be released here.
    releaseRootJSAPI();
    m_host->freeRetainedObjects();
}

void Chimera::onPluginReady()
{
    // When this is called, the BrowserHost is attached, the JSAPI object is
    // created, and we are ready to interact with the page and such.  The
    // PluginWindow may or may not have already fire the AttachedEvent at
    // this point.
}

void Chimera::shutdown()
{
    // This will be called when it is time for the plugin to shut down;
    // any threads or anything else that may hold a shared_ptr to this
    // object should be released here so that this object can be safely
    // destroyed. This is the last point that shared_from_this and weak_ptr
    // references to this object will be valid
}

///////////////////////////////////////////////////////////////////////////////
/// @brief  Creates an instance of the JSAPI object that provides your main
///         Javascript interface.
///
/// Note that m_host is your BrowserHost and shared_ptr returns a
/// FB::PluginCorePtr, which can be used to provide a
/// boost::weak_ptr<Chimera> for your JSAPI class.
///
/// Be very careful where you hold a shared_ptr to your plugin class from,
/// as it could prevent your plugin class from getting destroyed properly.
///////////////////////////////////////////////////////////////////////////////
FB::JSAPIPtr Chimera::createJSAPI()
{
    // m_host is the BrowserHost
    return boost::make_shared<ChimeraAPI>(FB::ptr_cast<Chimera>(shared_from_this()), m_host);
}

bool Chimera::onMouseDown(FB::MouseDownEvent *evt, FB::PluginWindow *)
{
    //printf("Mouse down at: %d, %d\n", evt->m_x, evt->m_y);
    return false;
}

bool Chimera::onMouseUp(FB::MouseUpEvent *evt, FB::PluginWindow *)
{
    //printf("Mouse up at: %d, %d\n", evt->m_x, evt->m_y);
    return false;
}

bool Chimera::onMouseMove(FB::MouseMoveEvent *evt, FB::PluginWindow *)
{
    //printf("Mouse move at: %d, %d\n", evt->m_x, evt->m_y);
    return false;
}
bool Chimera::onWindowAttached(FB::AttachedEvent *evt, FB::PluginWindow *)
{
    // The window is attached; act appropriately
    return false;
}

bool Chimera::onWindowDetached(FB::DetachedEvent *evt, FB::PluginWindow *)
{
    // The window is about to be detached; act appropriately
    return false;
}

<commit_msg>Add the code to actually create a Parrot interpreter. Doesn't compile yet because we haven't told cmake to compile against libparrot yet<commit_after>/**********************************************************\

  Auto-generated Chimera.cpp

  This file contains the auto-generated main plugin object
  implementation for the Chimera project

\**********************************************************/

#include "ChimeraAPI.h"

#include "Chimera.h"
#include "parrot/api.h"
#include "stdio.h"

///////////////////////////////////////////////////////////////////////////////
/// @fn Chimera::StaticInitialize()
///
/// @brief  Called from PluginFactory::globalPluginInitialize()
///
/// @see FB::FactoryBase::globalPluginInitialize
///////////////////////////////////////////////////////////////////////////////
void Chimera::StaticInitialize()
{
    // Place one-time initialization stuff here; As of FireBreath 1.4 this should only
    // be called once per process
    Parrot_PMC interp = NULL;

    if (!Parrot_api_make_interpreter(NULL, NULL, 0, &interp)) {
        fprintf(stderr, "Cannot create Parrot interpreter!\n");
    } else {
        printf("Parrot interp created!\n");
    }
}

///////////////////////////////////////////////////////////////////////////////
/// @fn Chimera::StaticInitialize()
///
/// @brief  Called from PluginFactory::globalPluginDeinitialize()
///
/// @see FB::FactoryBase::globalPluginDeinitialize
///////////////////////////////////////////////////////////////////////////////
void Chimera::StaticDeinitialize()
{
    // Place one-time deinitialization stuff here. As of FireBreath 1.4 this should
    // always be called just before the plugin library is unloaded
}

///////////////////////////////////////////////////////////////////////////////
/// @brief  Chimera constructor.  Note that your API is not available
///         at this point, nor the window.  For best results wait to use
///         the JSAPI object until the onPluginReady method is called
///////////////////////////////////////////////////////////////////////////////
Chimera::Chimera()
{
}

///////////////////////////////////////////////////////////////////////////////
/// @brief  Chimera destructor.
///////////////////////////////////////////////////////////////////////////////
Chimera::~Chimera()
{
    // This is optional, but if you reset m_api (the shared_ptr to your JSAPI
    // root object) and tell the host to free the retained JSAPI objects then
    // unless you are holding another shared_ptr reference to your JSAPI object
    // they will be released here.
    releaseRootJSAPI();
    m_host->freeRetainedObjects();
}

void Chimera::onPluginReady()
{
    // When this is called, the BrowserHost is attached, the JSAPI object is
    // created, and we are ready to interact with the page and such.  The
    // PluginWindow may or may not have already fire the AttachedEvent at
    // this point.
}

void Chimera::shutdown()
{
    // This will be called when it is time for the plugin to shut down;
    // any threads or anything else that may hold a shared_ptr to this
    // object should be released here so that this object can be safely
    // destroyed. This is the last point that shared_from_this and weak_ptr
    // references to this object will be valid
}

///////////////////////////////////////////////////////////////////////////////
/// @brief  Creates an instance of the JSAPI object that provides your main
///         Javascript interface.
///
/// Note that m_host is your BrowserHost and shared_ptr returns a
/// FB::PluginCorePtr, which can be used to provide a
/// boost::weak_ptr<Chimera> for your JSAPI class.
///
/// Be very careful where you hold a shared_ptr to your plugin class from,
/// as it could prevent your plugin class from getting destroyed properly.
///////////////////////////////////////////////////////////////////////////////
FB::JSAPIPtr Chimera::createJSAPI()
{
    // m_host is the BrowserHost
    return boost::make_shared<ChimeraAPI>(FB::ptr_cast<Chimera>(shared_from_this()), m_host);
}

bool Chimera::onMouseDown(FB::MouseDownEvent *evt, FB::PluginWindow *)
{
    //printf("Mouse down at: %d, %d\n", evt->m_x, evt->m_y);
    return false;
}

bool Chimera::onMouseUp(FB::MouseUpEvent *evt, FB::PluginWindow *)
{
    //printf("Mouse up at: %d, %d\n", evt->m_x, evt->m_y);
    return false;
}

bool Chimera::onMouseMove(FB::MouseMoveEvent *evt, FB::PluginWindow *)
{
    //printf("Mouse move at: %d, %d\n", evt->m_x, evt->m_y);
    return false;
}
bool Chimera::onWindowAttached(FB::AttachedEvent *evt, FB::PluginWindow *)
{
    // The window is attached; act appropriately
    return false;
}

bool Chimera::onWindowDetached(FB::DetachedEvent *evt, FB::PluginWindow *)
{
    // The window is about to be detached; act appropriately
    return false;
}

<|endoftext|>


<commit_before>/***********************************************************************
    created:    Sun Jul 19 2009
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2009 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#include "CEGUI/Font_xmlHandler.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/Logger.h"
#include "CEGUI/XMLAttributes.h"
#include "CEGUI/System.h"
#include "CEGUI/XMLParser.h"
#include "CEGUI/PixmapFont.h"
#include "CEGUI/SharedStringStream.h"

#ifdef CEGUI_HAS_FREETYPE
#   include "CEGUI/FreeTypeFont.h"
#endif

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
const String Font_xmlHandler::FontSchemaName("Font.xsd");
const String Font_xmlHandler::FontElement("Font");
const String Font_xmlHandler::FontsElement("Fonts");
const String Font_xmlHandler::MappingElement("Mapping");
const String Font_xmlHandler::FontTypeAttribute("type");
const String Font_xmlHandler::FontNameAttribute("name");
const String Font_xmlHandler::FontFilenameAttribute("filename");
const String Font_xmlHandler::FontResourceGroupAttribute("resourceGroup");
const String Font_xmlHandler::FontAutoScaledAttribute("autoScaled");
const String Font_xmlHandler::FontNativeHorzResAttribute("nativeHorzRes");
const String Font_xmlHandler::FontNativeVertResAttribute("nativeVertRes");
const String Font_xmlHandler::FontLineSpacingAttribute("lineSpacing");
const String Font_xmlHandler::FontSizeAttribute("size");
const String Font_xmlHandler::FontAntiAliasedAttribute("antiAlias");
const String Font_xmlHandler::MappingCodepointAttribute("codepoint");
const String Font_xmlHandler::MappingImageAttribute("image");
const String Font_xmlHandler::MappingHorzAdvanceAttribute("horzAdvance");
const String Font_xmlHandler::FontVersionAttribute( "version" );
const String Font_xmlHandler::FontTypeFreeType("FreeType");
const String Font_xmlHandler::FontTypePixmap("Pixmap");

//----------------------------------------------------------------------------//
// note: The assets' versions aren't usually the same as CEGUI version, they
// are versioned from version 1 onwards!
//
// previous versions (though not specified in files until 3)
// 1 - CEGUI up to and including 0.4.x
// 2 - CEGUI versions 0.5.x through 0.7.x (Static/Dynamic types renamed to Pixmap/TrueType
//                                         Removed facility to pre-declare glyphs and glyph ranges)
// 3 - CEGUI version 1.x.x (changed case of attr names, added version support)
const String NativeVersion( "4" );

//----------------------------------------------------------------------------//
Font_xmlHandler::Font_xmlHandler():
    d_font(0),
    d_isFontLoadingDone(false)
{}

//----------------------------------------------------------------------------//
Font_xmlHandler::~Font_xmlHandler()
{
    if (!d_isFontLoadingDone && d_font != 0)
    {
        Logger::getSingleton().logEvent("Font_xmlHandler::~Font_xmlHandler: "
            "Font XML Handler is being destroyed, but loading of Font with name \"" + d_font->getName() + "\" has not been completed.",
            Warnings);

        delete d_font;
    }
}

//----------------------------------------------------------------------------//
std::vector<Font*>& Font_xmlHandler::getObjects()
{
    if (d_loadedFonts.empty())
        throw InvalidRequestException("Attempting to return the loaded Fonts but the container of loaded Fonts is empty.");

    if (d_loadedFonts.empty())
        throw InvalidRequestException("Attempting to return the loaded Fonts but loading of font \"" + d_font->getName() + "\" has not been finished.");

    d_isFontLoadingDone = true;
    return d_loadedFonts;
}

//----------------------------------------------------------------------------//
const String& Font_xmlHandler::getSchemaName() const
{
    return FontSchemaName;
}

//----------------------------------------------------------------------------//
const String& Font_xmlHandler::getDefaultResourceGroup() const
{
    return Font::getDefaultResourceGroup();
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::elementStart(const String& element,
                                   const XMLAttributes& attributes)
{
    // handle root Font element
    if (element == FontsElement)
        elementFontsStart(attributes);
    // handle root Font element
    else if (element == FontElement)
        elementFontStart(attributes);
    // handle a Mapping element
    else if (element == MappingElement)
        elementMappingStart(attributes);
    // anything else is a non-fatal error.
    else
        Logger::getSingleton().logEvent("Font_xmlHandler::elementStart: "
            "Unknown element encountered: <" + element + ">", Errors);
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::elementEnd(const String& element)
{
    if (element == FontsElement)
        elementFontsEnd();
    else if (element == FontElement)
        elementFontEnd();
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::elementFontsStart(const XMLAttributes& attributes)
{
    validateFontFileVersion(attributes);
}

void Font_xmlHandler::elementFontStart(const XMLAttributes& attributes)
{
    if (d_font != 0)
    {
        throw InvalidRequestException(
            "Attempting to load a new font but the loading of the "
            "previous font \"" + d_font->getName() + "\" has not been completed.");
    }

    // get type of font being created
    const String font_type(attributes.getValueAsString(FontTypeAttribute));

    // log the start of font creation.
    CEGUI_LOGINSANE(
        "Started creation of Font from XML specification:");

    if (font_type == FontTypeFreeType)
        createFreeTypeFont(attributes);
    else if (font_type == FontTypePixmap)
        createPixmapFont(attributes);
    else
        throw InvalidRequestException(
        "Encountered unknown font type of '" + font_type + "'");
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::validateFontFileVersion(const XMLAttributes& attrs)
{
    const String version(attrs.getValueAsString(FontVersionAttribute,
                                                "unknown"));

    if (version == NativeVersion)
        return;

    throw InvalidRequestException(
        "You are attempting to load a font of version '" + version + "' but "
        "this CEGUI version is only meant to load fonts of version '" +
        NativeVersion + "'. Consider using the migrate.py script bundled with "
        "CEGUI Unified Editor to migrate your data.");
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::elementFontEnd()
{
    String addressStr = SharedStringstream::GetPointerAddressAsString(d_font);
    Logger::getSingleton().logEvent("Finished creation of Font '" +
        d_font->getName() + "' via XML file. " + addressStr, Informative);

    d_loadedFonts.push_back(d_font);
    d_font = 0;
}

void Font_xmlHandler::elementFontsEnd()
{
    if (d_font != 0)
        throw InvalidRequestException(
        "The Fonts node was closed but the loading for the last font has not been completed.");

    Logger::getSingleton().logEvent("Finished Fonts loading. Number of loaded fonts: " + d_loadedFonts.size(), Informative);
}

void Font_xmlHandler::elementMappingStart(const XMLAttributes& attributes)
{
    if (!d_font)
        throw InvalidRequestException(
            "Attempt to access null object.");

    // double-check font type just in case - report issues as 'soft' errors
    if (d_font->getTypeName() != FontTypePixmap)
        Logger::getSingleton().logEvent(
            "Imageset_xmlHandler::elementMappingStart: <Mapping> element is "
            "only valid for Pixmap type fonts.", Errors);
    else
        static_cast<PixmapFont*>(d_font)->defineMapping(
            attributes.getValueAsInteger(MappingCodepointAttribute),
            attributes.getValueAsString(MappingImageAttribute),
            attributes.getValueAsFloat(MappingHorzAdvanceAttribute, -1.0f));
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::createFreeTypeFont(const XMLAttributes& attributes)
{
    const String name(attributes.getValueAsString(FontNameAttribute));
    const String filename(attributes.getValueAsString(FontFilenameAttribute));
    const String resource_group(attributes.getValueAsString(FontResourceGroupAttribute));

#ifdef CEGUI_HAS_FREETYPE
    if (d_font != 0)
    {
        throw InvalidRequestException(
            "Attempting to create a FreeTypeFont but loading of a "
            " previous font has not been finished.");
    }

    CEGUI_LOGINSANE("---- CEGUI font name: " + name);
    CEGUI_LOGINSANE("----       Font type: FreeType");
    CEGUI_LOGINSANE("----     Source file: " + filename +
                    " in resource group: " + (resource_group.empty() ?
                                              "(Default)" : resource_group));
    CEGUI_LOGINSANE("---- Real point size: " +
            attributes.getValueAsString(FontSizeAttribute, "12"));

    d_font = new FreeTypeFont(name,
        attributes.getValueAsFloat(FontSizeAttribute, 12.0f),
        attributes.getValueAsBool(FontAntiAliasedAttribute, true),
        filename, resource_group,
        PropertyHelper<AutoScaledMode>::fromString(
                attributes.getValueAsString(FontAutoScaledAttribute)),
        Sizef(attributes.getValueAsFloat(FontNativeHorzResAttribute, 640.0f),
              attributes.getValueAsFloat(FontNativeVertResAttribute, 480.0f)),
        attributes.getValueAsFloat(FontLineSpacingAttribute, 0.0f));
#else
    throw InvalidRequestException(
        "CEGUI was compiled without freetype support.");
#endif
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::createPixmapFont(const XMLAttributes& attributes)
{
    const String name(attributes.getValueAsString(FontNameAttribute));
    const String filename(attributes.getValueAsString(FontFilenameAttribute));
    const String resource_group(attributes.getValueAsString(FontResourceGroupAttribute));

    if (d_font != 0)
    {
        throw InvalidRequestException(
            "Attempting to create a PixmapFont but loading of a "
            " previous font has not been finished.");
    }

    CEGUI_LOGINSANE("---- CEGUI font name: " + name);
    CEGUI_LOGINSANE("----       Font type: Pixmap");
    CEGUI_LOGINSANE("----     Source file: " + filename +
                    " in resource group: " + (resource_group.empty() ? "(Default)" : resource_group));

    d_font = new PixmapFont(name, filename, resource_group,
        PropertyHelper<AutoScaledMode>::fromString(
                        attributes.getValueAsString(FontAutoScaledAttribute)),
        Sizef(attributes.getValueAsFloat(FontNativeHorzResAttribute, 640.0f),
              attributes.getValueAsFloat(FontNativeVertResAttribute, 480.0f)));
}

}
<commit_msg>MOD: use std::ostringstream to append numbers to log output<commit_after>/***********************************************************************
    created:    Sun Jul 19 2009
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2009 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#include "CEGUI/Font_xmlHandler.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/Logger.h"
#include "CEGUI/XMLAttributes.h"
#include "CEGUI/System.h"
#include "CEGUI/XMLParser.h"
#include "CEGUI/PixmapFont.h"
#include "CEGUI/SharedStringStream.h"

#ifdef CEGUI_HAS_FREETYPE
#   include "CEGUI/FreeTypeFont.h"
#endif

#include <sstream>

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
const String Font_xmlHandler::FontSchemaName("Font.xsd");
const String Font_xmlHandler::FontElement("Font");
const String Font_xmlHandler::FontsElement("Fonts");
const String Font_xmlHandler::MappingElement("Mapping");
const String Font_xmlHandler::FontTypeAttribute("type");
const String Font_xmlHandler::FontNameAttribute("name");
const String Font_xmlHandler::FontFilenameAttribute("filename");
const String Font_xmlHandler::FontResourceGroupAttribute("resourceGroup");
const String Font_xmlHandler::FontAutoScaledAttribute("autoScaled");
const String Font_xmlHandler::FontNativeHorzResAttribute("nativeHorzRes");
const String Font_xmlHandler::FontNativeVertResAttribute("nativeVertRes");
const String Font_xmlHandler::FontLineSpacingAttribute("lineSpacing");
const String Font_xmlHandler::FontSizeAttribute("size");
const String Font_xmlHandler::FontAntiAliasedAttribute("antiAlias");
const String Font_xmlHandler::MappingCodepointAttribute("codepoint");
const String Font_xmlHandler::MappingImageAttribute("image");
const String Font_xmlHandler::MappingHorzAdvanceAttribute("horzAdvance");
const String Font_xmlHandler::FontVersionAttribute( "version" );
const String Font_xmlHandler::FontTypeFreeType("FreeType");
const String Font_xmlHandler::FontTypePixmap("Pixmap");

//----------------------------------------------------------------------------//
// note: The assets' versions aren't usually the same as CEGUI version, they
// are versioned from version 1 onwards!
//
// previous versions (though not specified in files until 3)
// 1 - CEGUI up to and including 0.4.x
// 2 - CEGUI versions 0.5.x through 0.7.x (Static/Dynamic types renamed to Pixmap/TrueType
//                                         Removed facility to pre-declare glyphs and glyph ranges)
// 3 - CEGUI version 1.x.x (changed case of attr names, added version support)
const String NativeVersion( "4" );

//----------------------------------------------------------------------------//
Font_xmlHandler::Font_xmlHandler():
    d_font(0),
    d_isFontLoadingDone(false)
{}

//----------------------------------------------------------------------------//
Font_xmlHandler::~Font_xmlHandler()
{
    if (!d_isFontLoadingDone && d_font != 0)
    {
        Logger::getSingleton().logEvent("Font_xmlHandler::~Font_xmlHandler: "
            "Font XML Handler is being destroyed, but loading of Font with name \"" + d_font->getName() + "\" has not been completed.",
            Warnings);

        delete d_font;
    }
}

//----------------------------------------------------------------------------//
std::vector<Font*>& Font_xmlHandler::getObjects()
{
    if (d_loadedFonts.empty())
        throw InvalidRequestException("Attempting to return the loaded Fonts but the container of loaded Fonts is empty.");

    if (d_loadedFonts.empty())
        throw InvalidRequestException("Attempting to return the loaded Fonts but loading of font \"" + d_font->getName() + "\" has not been finished.");

    d_isFontLoadingDone = true;
    return d_loadedFonts;
}

//----------------------------------------------------------------------------//
const String& Font_xmlHandler::getSchemaName() const
{
    return FontSchemaName;
}

//----------------------------------------------------------------------------//
const String& Font_xmlHandler::getDefaultResourceGroup() const
{
    return Font::getDefaultResourceGroup();
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::elementStart(const String& element,
                                   const XMLAttributes& attributes)
{
    // handle root Font element
    if (element == FontsElement)
        elementFontsStart(attributes);
    // handle root Font element
    else if (element == FontElement)
        elementFontStart(attributes);
    // handle a Mapping element
    else if (element == MappingElement)
        elementMappingStart(attributes);
    // anything else is a non-fatal error.
    else
        Logger::getSingleton().logEvent("Font_xmlHandler::elementStart: "
            "Unknown element encountered: <" + element + ">", Errors);
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::elementEnd(const String& element)
{
    if (element == FontsElement)
        elementFontsEnd();
    else if (element == FontElement)
        elementFontEnd();
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::elementFontsStart(const XMLAttributes& attributes)
{
    validateFontFileVersion(attributes);
}

void Font_xmlHandler::elementFontStart(const XMLAttributes& attributes)
{
    if (d_font != 0)
    {
        throw InvalidRequestException(
            "Attempting to load a new font but the loading of the "
            "previous font \"" + d_font->getName() + "\" has not been completed.");
    }

    // get type of font being created
    const String font_type(attributes.getValueAsString(FontTypeAttribute));

    // log the start of font creation.
    CEGUI_LOGINSANE(
        "Started creation of Font from XML specification:");

    if (font_type == FontTypeFreeType)
        createFreeTypeFont(attributes);
    else if (font_type == FontTypePixmap)
        createPixmapFont(attributes);
    else
        throw InvalidRequestException(
        "Encountered unknown font type of '" + font_type + "'");
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::validateFontFileVersion(const XMLAttributes& attrs)
{
    const String version(attrs.getValueAsString(FontVersionAttribute,
                                                "unknown"));

    if (version == NativeVersion)
        return;

    throw InvalidRequestException(
        "You are attempting to load a font of version '" + version + "' but "
        "this CEGUI version is only meant to load fonts of version '" +
        NativeVersion + "'. Consider using the migrate.py script bundled with "
        "CEGUI Unified Editor to migrate your data.");
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::elementFontEnd()
{
    String addressStr = SharedStringstream::GetPointerAddressAsString(d_font);
    Logger::getSingleton().logEvent("Finished creation of Font '" +
        d_font->getName() + "' via XML file. " + addressStr, Informative);

    d_loadedFonts.push_back(d_font);
    d_font = 0;
}

void Font_xmlHandler::elementFontsEnd()
{
    if (d_font != 0)
        throw InvalidRequestException(
        "The Fonts node was closed but the loading for the last font has not been completed.");

    std::ostringstream stream;
    stream << "Finished Fonts loading. Number of loaded fonts: " << d_loadedFonts.size();

    Logger::getSingleton().logEvent(stream.str(), Informative);
}

void Font_xmlHandler::elementMappingStart(const XMLAttributes& attributes)
{
    if (!d_font)
        throw InvalidRequestException(
            "Attempt to access null object.");

    // double-check font type just in case - report issues as 'soft' errors
    if (d_font->getTypeName() != FontTypePixmap)
        Logger::getSingleton().logEvent(
            "Imageset_xmlHandler::elementMappingStart: <Mapping> element is "
            "only valid for Pixmap type fonts.", Errors);
    else
        static_cast<PixmapFont*>(d_font)->defineMapping(
            attributes.getValueAsInteger(MappingCodepointAttribute),
            attributes.getValueAsString(MappingImageAttribute),
            attributes.getValueAsFloat(MappingHorzAdvanceAttribute, -1.0f));
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::createFreeTypeFont(const XMLAttributes& attributes)
{
    const String name(attributes.getValueAsString(FontNameAttribute));
    const String filename(attributes.getValueAsString(FontFilenameAttribute));
    const String resource_group(attributes.getValueAsString(FontResourceGroupAttribute));

#ifdef CEGUI_HAS_FREETYPE
    if (d_font != 0)
    {
        throw InvalidRequestException(
            "Attempting to create a FreeTypeFont but loading of a "
            " previous font has not been finished.");
    }

    CEGUI_LOGINSANE("---- CEGUI font name: " + name);
    CEGUI_LOGINSANE("----       Font type: FreeType");
    CEGUI_LOGINSANE("----     Source file: " + filename +
                    " in resource group: " + (resource_group.empty() ?
                                              "(Default)" : resource_group));
    CEGUI_LOGINSANE("---- Real point size: " +
            attributes.getValueAsString(FontSizeAttribute, "12"));

    d_font = new FreeTypeFont(name,
        attributes.getValueAsFloat(FontSizeAttribute, 12.0f),
        attributes.getValueAsBool(FontAntiAliasedAttribute, true),
        filename, resource_group,
        PropertyHelper<AutoScaledMode>::fromString(
                attributes.getValueAsString(FontAutoScaledAttribute)),
        Sizef(attributes.getValueAsFloat(FontNativeHorzResAttribute, 640.0f),
              attributes.getValueAsFloat(FontNativeVertResAttribute, 480.0f)),
        attributes.getValueAsFloat(FontLineSpacingAttribute, 0.0f));
#else
    throw InvalidRequestException(
        "CEGUI was compiled without freetype support.");
#endif
}

//----------------------------------------------------------------------------//
void Font_xmlHandler::createPixmapFont(const XMLAttributes& attributes)
{
    const String name(attributes.getValueAsString(FontNameAttribute));
    const String filename(attributes.getValueAsString(FontFilenameAttribute));
    const String resource_group(attributes.getValueAsString(FontResourceGroupAttribute));

    if (d_font != 0)
    {
        throw InvalidRequestException(
            "Attempting to create a PixmapFont but loading of a "
            " previous font has not been finished.");
    }

    CEGUI_LOGINSANE("---- CEGUI font name: " + name);
    CEGUI_LOGINSANE("----       Font type: Pixmap");
    CEGUI_LOGINSANE("----     Source file: " + filename +
                    " in resource group: " + (resource_group.empty() ? "(Default)" : resource_group));

    d_font = new PixmapFont(name, filename, resource_group,
        PropertyHelper<AutoScaledMode>::fromString(
                        attributes.getValueAsString(FontAutoScaledAttribute)),
        Sizef(attributes.getValueAsFloat(FontNativeHorzResAttribute, 640.0f),
              attributes.getValueAsFloat(FontNativeVertResAttribute, 480.0f)));
}

}
<|endoftext|>


<commit_before>// Day23.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

enum class OpCode { Inc, Dec, Copy, Jump, Toggle, Noop };

struct Registers;
struct Instruction;
typedef std::vector<Instruction> InstructionVector;
typedef std::function<signed&(Registers &)> FetchFunction;
typedef std::function<signed(Registers &)> FetchValueFunction;

struct Registers
{
	signed A = 0;
	signed B = 0;
	signed C = 0;
	signed D = 0;
	size_t IP = 0;

	Registers() = default;
	Registers(signed A, signed B, signed C, signed D, size_t IP)
		:A(A), B(B), C(C), D(D), IP(IP)
	{}

	void Print() const
	{
		std::cout.width(8);
		std::cout << IP << " | ";
		std::cout.width(8);
		std::cout << A;
		std::cout.width(8);
		std::cout << B;
		std::cout.width(8);
		std::cout << C;
		std::cout.width(8);
		std::cout << D;
	}
};

struct Instruction
{
	OpCode Code;
	FetchFunction RefFetch;
	FetchValueFunction Arg1;
	FetchValueFunction Arg2;

	Instruction()
		:Code(OpCode::Noop), RefFetch(nullptr), Arg1(nullptr), Arg2(nullptr)
	{}

	Instruction(OpCode Code, FetchFunction RefFetch)
		:Code(Code), RefFetch(RefFetch), Arg1(nullptr), Arg2(nullptr)
	{}

	Instruction(OpCode Code, FetchValueFunction Arg1)
		:Code(Code), RefFetch(nullptr), Arg1(Arg1), Arg2(nullptr)
	{}

	Instruction(OpCode Code, FetchFunction RefFetch, FetchValueFunction Arg1)
		:Code(Code), RefFetch(RefFetch), Arg1(Arg1), Arg2(nullptr)
	{}

	Instruction(OpCode Code, FetchValueFunction Arg1, FetchValueFunction Arg2)
		:Code(Code), RefFetch(nullptr), Arg1(Arg1), Arg2(Arg2)
	{}

	void operator() (Registers & State, InstructionVector & Instructions)
	{
		switch (Code)
		{
		case OpCode::Inc:
			if(RefFetch)
				RefFetch(State)++;
			break;
		case OpCode::Dec:
			if (RefFetch)
				RefFetch(State)--;
			break;
		case OpCode::Copy:
			if (RefFetch)
				RefFetch(State) = Arg1(State);
			break;
		case OpCode::Jump:
			if (Arg1(State) != 0)
			{
				signed JumpDistance = RefFetch ? RefFetch(State) : Arg2(State);
				State.IP += JumpDistance;
				return;
			}
			break;
		case OpCode::Toggle:
			{
				size_t Instruction = State.IP + (RefFetch ? RefFetch(State) : Arg1(State));
				if (Instruction < Instructions.size())
				{
					Instructions[Instruction].Toggle();
				}
			}
			break;
		default:
			std::cout << "Unknown Op Code" << std::endl;
		case OpCode::Noop:
			break;
		};

		State.IP++;
	};

	void Toggle()
	{
		switch(Code)
		{
		case OpCode::Inc:
			Code = OpCode::Dec;
			break;
		case OpCode::Dec:
		case OpCode::Toggle:
			Code = OpCode::Inc;
			break;
		case OpCode::Copy:
			Code = OpCode::Jump;
			break;
		case OpCode::Jump:
			Code = OpCode::Copy;
			break;
		}
	}

	void Print() const
	{
		std::cout << " | ";

		switch (Code)
		{
		case OpCode::Inc:
			std::cout << "Inc";
			break;
		case OpCode::Dec:
			std::cout << "Dec";
			break;
		case OpCode::Copy:
			std::cout << "Copy";
			break;
		case OpCode::Jump:
			std::cout << "Jump";
			break;
		case OpCode::Toggle:
			std::cout << "Toogle";
		break;
		case OpCode::Noop:
			std::cout << "Noop";
			break;
		default:
			std::cout << "Unknown Op Code";
			break;
		};
	}
};

Instruction ParseInc(const StringVector & Line);
Instruction ParseDec(const StringVector & Line);
Instruction ParseCpy(const StringVector & Line);
Instruction ParseJnz(const StringVector & Line);
Instruction ParseTgl(const StringVector & Line);

static const std::map<std::string, std::function<Instruction(const StringVector &)>> AssemblyParserMap = {
	{ "inc", &ParseInc },
	{ "dec", &ParseDec },
	{ "cpy", &ParseCpy },
	{ "jnz", &ParseJnz },
	{ "tgl", &ParseTgl }
};

static const std::map<std::string, FetchFunction> RegisterFetchMap = {
	{ "a", [](Registers & State)->signed& { return State.A; } },
	{ "b", [](Registers & State)->signed& { return State.B; } },
	{ "c", [](Registers & State)->signed& { return State.C; } },
	{ "d", [](Registers & State)->signed& { return State.D; } },
};

InstructionVector ParseAssembly(const StringVectorVector & Lines);
Registers Run(InstructionVector & Instructions, Registers InitialState = Registers());

int main()
{
	StringVectorVector Lines = GetFileLineParts("Input.txt");
	InstructionVector Instructions = ParseAssembly(Lines);

	Registers PartOne = Run(Instructions, { 7, 0, 0, 0, 0 });

	std::cout << "A: " << PartOne.A << std::endl;

	system("pause");

	return 0;
}

InstructionVector ParseAssembly(const StringVectorVector & Lines)
{
	InstructionVector Instructions;
	Instructions.reserve(Lines.size());

	for(const StringVector & Line : Lines)
	{
		auto Parser = AssemblyParserMap.find(Line[0]);
		if (Parser == AssemblyParserMap.end())
		{
			std::cout << "Unknwon Assembly: " << Line[0] << std::endl;
			__debugbreak();
			Instructions.emplace_back();
		}
		else
		{
			Instructions.push_back(Parser->second(Line));
		}
	}

	return Instructions;
}

void PrintDebug(const Registers & State, const Instruction & Instruction)
{
	State.Print();
	Instruction.Print();
	std::cout << std::endl;
	getchar();
}

Registers Run(InstructionVector & Instructions, Registers InitialState)
{
	Registers & State = InitialState;

	while (State.IP < Instructions.size())
	{
		//PrintDebug(State, Instructions[State.IP]);

		Instructions[State.IP](State, Instructions);
	}

	return State;
}

FetchFunction GetFetchFunction(const std::string & Identifier)
{
	auto RegisterFetch = RegisterFetchMap.find(Identifier);
	if (RegisterFetch == RegisterFetchMap.end())
	{
		return nullptr;
	}
	else
	{
		return RegisterFetch->second;
	}
}

FetchValueFunction GetFetchValueFunction(const std::string & Identifier)
{
	auto RegisterFetchFunction = GetFetchFunction(Identifier);
	if (RegisterFetchFunction == nullptr)
	{
		signed Value = std::stoi(Identifier);
		return [Value](Registers & State) { return Value; };
	}
	else
	{
		return [RegisterFetchFunction](Registers & State) { return static_cast<signed>(RegisterFetchFunction(State)); };
	}
}

Instruction ParseInc(const StringVector & Line)
{
	return Instruction(OpCode::Inc, GetFetchFunction(Line[1]));
}

Instruction ParseDec(const StringVector & Line)
{
	return Instruction(OpCode::Dec, GetFetchFunction(Line[1]));
}

Instruction ParseCpy(const StringVector & Line)
{
	// Get First Argument as Value
	FetchValueFunction FetchValue = GetFetchValueFunction(Line[1]);
	FetchFunction RegisterFetch = GetFetchFunction(Line[2]);

	return Instruction(OpCode::Copy, RegisterFetch, FetchValue);
}

Instruction ParseJnz(const StringVector & Line)
{
	// Get Second Argument as Value
	FetchValueFunction FetchTestValue = GetFetchValueFunction(Line[1]);
	FetchFunction FetchJumpValue = GetFetchFunction(Line[2]);

	if (FetchJumpValue)
	{
		return Instruction(OpCode::Jump, FetchJumpValue, FetchTestValue);
	}
	else
	{
		return Instruction(OpCode::Jump, FetchTestValue, GetFetchValueFunction(Line[2]));
	}
}

Instruction ParseTgl(const StringVector & Line)
{
	FetchFunction FetchValue = GetFetchFunction(Line[1]);

	if (FetchValue)
	{
		return Instruction(OpCode::Toggle, FetchValue);
	}
	else
	{
		return Instruction(OpCode::Toggle, GetFetchValueFunction(Line[1]));
	}
}<commit_msg>Day 23 part two<commit_after>// Day23.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

enum class OpCode { Inc, Dec, Copy, Jump, Toggle, Noop };

struct Registers;
struct Instruction;
typedef std::vector<Instruction> InstructionVector;
typedef std::function<signed&(Registers &)> FetchFunction;
typedef std::function<signed(Registers &)> FetchValueFunction;

struct Registers
{
	signed A = 0;
	signed B = 0;
	signed C = 0;
	signed D = 0;
	size_t IP = 0;

	Registers() = default;
	Registers(signed A, signed B, signed C, signed D, size_t IP)
		:A(A), B(B), C(C), D(D), IP(IP)
	{}

	void Print() const
	{
		std::cout.width(8);
		std::cout << IP << " | ";
		std::cout.width(8);
		std::cout << A;
		std::cout.width(8);
		std::cout << B;
		std::cout.width(8);
		std::cout << C;
		std::cout.width(8);
		std::cout << D;
	}
};

struct Instruction
{
	OpCode Code;
	FetchFunction RefFetch;
	FetchValueFunction Arg1;
	FetchValueFunction Arg2;

	Instruction()
		:Code(OpCode::Noop), RefFetch(nullptr), Arg1(nullptr), Arg2(nullptr)
	{}

	Instruction(OpCode Code, FetchFunction RefFetch)
		:Code(Code), RefFetch(RefFetch), Arg1(nullptr), Arg2(nullptr)
	{}

	Instruction(OpCode Code, FetchValueFunction Arg1)
		:Code(Code), RefFetch(nullptr), Arg1(Arg1), Arg2(nullptr)
	{}

	Instruction(OpCode Code, FetchFunction RefFetch, FetchValueFunction Arg1)
		:Code(Code), RefFetch(RefFetch), Arg1(Arg1), Arg2(nullptr)
	{}

	Instruction(OpCode Code, FetchValueFunction Arg1, FetchValueFunction Arg2)
		:Code(Code), RefFetch(nullptr), Arg1(Arg1), Arg2(Arg2)
	{}

	void operator() (Registers & State, InstructionVector & Instructions)
	{
		switch (Code)
		{
		case OpCode::Inc:
			if(RefFetch)
				RefFetch(State)++;
			break;
		case OpCode::Dec:
			if (RefFetch)
				RefFetch(State)--;
			break;
		case OpCode::Copy:
			if (RefFetch)
				RefFetch(State) = Arg1(State);
			break;
		case OpCode::Jump:
			if (Arg1(State) != 0)
			{
				signed JumpDistance = RefFetch ? RefFetch(State) : Arg2(State);
				State.IP += JumpDistance;
				return;
			}
			break;
		case OpCode::Toggle:
			{
				State.Print();
				std::cout << std::endl;
				size_t Instruction = State.IP + (RefFetch ? RefFetch(State) : Arg1(State));
				if (Instruction < Instructions.size())
				{
					Instructions[Instruction].Toggle();
				}
			}
			break;
		default:
			std::cout << "Unknown Op Code" << std::endl;
		case OpCode::Noop:
			break;
		};

		State.IP++;
	};

	void Toggle()
	{
		switch(Code)
		{
		case OpCode::Inc:
			Code = OpCode::Dec;
			break;
		case OpCode::Dec:
		case OpCode::Toggle:
			Code = OpCode::Inc;
			break;
		case OpCode::Copy:
			Code = OpCode::Jump;
			break;
		case OpCode::Jump:
			Code = OpCode::Copy;
			break;
		}
	}

	void Print() const
	{
		std::cout << " | ";

		switch (Code)
		{
		case OpCode::Inc:
			std::cout << "Inc";
			break;
		case OpCode::Dec:
			std::cout << "Dec";
			break;
		case OpCode::Copy:
			std::cout << "Copy";
			break;
		case OpCode::Jump:
			std::cout << "Jump";
			break;
		case OpCode::Toggle:
			std::cout << "Toogle";
		break;
		case OpCode::Noop:
			std::cout << "Noop";
			break;
		default:
			std::cout << "Unknown Op Code";
			break;
		};
	}
};

Instruction ParseInc(const StringVector & Line);
Instruction ParseDec(const StringVector & Line);
Instruction ParseCpy(const StringVector & Line);
Instruction ParseJnz(const StringVector & Line);
Instruction ParseTgl(const StringVector & Line);

static const std::map<std::string, std::function<Instruction(const StringVector &)>> AssemblyParserMap = {
	{ "inc", &ParseInc },
	{ "dec", &ParseDec },
	{ "cpy", &ParseCpy },
	{ "jnz", &ParseJnz },
	{ "tgl", &ParseTgl }
};

static const std::map<std::string, FetchFunction> RegisterFetchMap = {
	{ "a", [](Registers & State)->signed& { return State.A; } },
	{ "b", [](Registers & State)->signed& { return State.B; } },
	{ "c", [](Registers & State)->signed& { return State.C; } },
	{ "d", [](Registers & State)->signed& { return State.D; } },
};

InstructionVector ParseAssembly(const StringVectorVector & Lines);
Registers Run(InstructionVector Instructions, Registers InitialState = Registers());

int main()
{
	StringVectorVector Lines = GetFileLineParts("Input.txt");
	InstructionVector Instructions = ParseAssembly(Lines);

	// A = 7! + 81 * 73
	Registers PartOne = Run(Instructions, { 7, 0, 0, 0, 0 });
	std::cout << "Part One: " << PartOne.A << std::endl;

	// A = 12! + 81 * 73
	Registers PartTwo = Run(Instructions, { 12, 0, 0, 0, 0 });
	std::cout << "Part Two: " << PartTwo.A << std::endl;

	system("pause");

	return 0;
}

InstructionVector ParseAssembly(const StringVectorVector & Lines)
{
	InstructionVector Instructions;
	Instructions.reserve(Lines.size());

	for(const StringVector & Line : Lines)
	{
		auto Parser = AssemblyParserMap.find(Line[0]);
		if (Parser == AssemblyParserMap.end())
		{
			std::cout << "Unknwon Assembly: " << Line[0] << std::endl;
			__debugbreak();
			Instructions.emplace_back();
		}
		else
		{
			Instructions.push_back(Parser->second(Line));
		}
	}

	return Instructions;
}

void PrintDebug(const Registers & State, const Instruction & Instruction)
{
	State.Print();
	Instruction.Print();
	std::cout << std::endl;
	getchar();
}

Registers Run(InstructionVector Instructions, Registers InitialState)
{
	Registers & State = InitialState;

	while (State.IP < Instructions.size())
	{
		//PrintDebug(State, Instructions[State.IP]);

		Instructions[State.IP](State, Instructions);
	}

	return State;
}

FetchFunction GetFetchFunction(const std::string & Identifier)
{
	auto RegisterFetch = RegisterFetchMap.find(Identifier);
	if (RegisterFetch == RegisterFetchMap.end())
	{
		return nullptr;
	}
	else
	{
		return RegisterFetch->second;
	}
}

FetchValueFunction GetFetchValueFunction(const std::string & Identifier)
{
	auto RegisterFetchFunction = GetFetchFunction(Identifier);
	if (RegisterFetchFunction == nullptr)
	{
		signed Value = std::stoi(Identifier);
		return [Value](Registers & State) { return Value; };
	}
	else
	{
		return [RegisterFetchFunction](Registers & State) { return static_cast<signed>(RegisterFetchFunction(State)); };
	}
}

Instruction ParseInc(const StringVector & Line)
{
	return Instruction(OpCode::Inc, GetFetchFunction(Line[1]));
}

Instruction ParseDec(const StringVector & Line)
{
	return Instruction(OpCode::Dec, GetFetchFunction(Line[1]));
}

Instruction ParseCpy(const StringVector & Line)
{
	// Get First Argument as Value
	FetchValueFunction FetchValue = GetFetchValueFunction(Line[1]);
	FetchFunction RegisterFetch = GetFetchFunction(Line[2]);

	return Instruction(OpCode::Copy, RegisterFetch, FetchValue);
}

Instruction ParseJnz(const StringVector & Line)
{
	// Get Second Argument as Value
	FetchValueFunction FetchTestValue = GetFetchValueFunction(Line[1]);
	FetchFunction FetchJumpValue = GetFetchFunction(Line[2]);

	if (FetchJumpValue)
	{
		return Instruction(OpCode::Jump, FetchJumpValue, FetchTestValue);
	}
	else
	{
		return Instruction(OpCode::Jump, FetchTestValue, GetFetchValueFunction(Line[2]));
	}
}

Instruction ParseTgl(const StringVector & Line)
{
	FetchFunction FetchValue = GetFetchFunction(Line[1]);

	if (FetchValue)
	{
		return Instruction(OpCode::Toggle, FetchValue);
	}
	else
	{
		return Instruction(OpCode::Toggle, GetFetchValueFunction(Line[1]));
	}
}

/*

cpy a b
dec b
cpy a d
cpy 0 a
cpy b c
inc a
dec c
jnz c -2
dec d
jnz d -5
dec b
cpy b c
cpy c d
dec d
inc c
jnz d -2
tgl c
cpy -16 c
jnz 1 c
cpy 81 c
jnz 73 d
inc a
inc d
jnz d -2
inc c
jnz c -5

*/<|endoftext|>


<commit_before>#include "SkinV2.h"

#include "../Logger.h"
#include "../MeterWnd/Meters/MeterTypes.h"
#include "../StringUtils.h"
#include "MeterComponent.h"
#include "OSDComponent.h"
#include "SkinUtils.h"

SkinV2::SkinV2(std::wstring skinXML) :
SkinInfo(skinXML) {

}

SkinV2::~SkinV2() {

}

OSDComponent *SkinV2::VolumeOSD() {
    OSDComponent *volume = new OSDComponent;

    /* Images */
    volume->background = LoadImg(_skinDir + L"\\OSD\\back.png");
    volume->mask = LoadImg(_skinDir + L"\\OSD\\glassMask.png");

    /* Sound */
    std::wstring soundName = _skinDir + L"\\sound.wav";
    SoundPlayer *player = new SoundPlayer(soundName);
    if (player->Ready() == false) {
        delete player;
        player = NULL;
    }
    volume->sound = player;

    /* Determine the number of units */
    int units = 10;
    tinyxml2::XMLElement *meterMax = SubElement("osd", "meterMax");
    if (meterMax) {
        meterMax->QueryIntText(&units);
    }
    volume->defaultUnits = units;

    /* Load the meter(s) */
    const char *meterType = nullptr;
    tinyxml2::XMLElement *meterOrientation
        = SubElement("osd", "meterOrientation");
    if (meterOrientation) {
        meterType = meterOrientation->GetText();
    }
    int x = 0;
    int y = 0;
    tinyxml2::XMLElement *pos = SubElement("osd", "meterPosition");
    if (pos) {
        tinyxml2::XMLElement *xelem = pos->FirstChildElement("X");
        tinyxml2::XMLElement *yelem = pos->FirstChildElement("Y");
        if (xelem) {
            xelem->QueryIntText(&x);
        }
        if (yelem) {
            yelem->QueryIntText(&y);
        }
    }

    std::wstring meterImg = _skinDir + L"\\OSD\\meter.png";
    if (meterType == "vertical") {
        volume->meters.push_back(
            new VerticalBar(meterImg, x, y, units));
    } else if (meterType == "bitstrip") {
        volume->meters.push_back(
            new Bitstrip(meterImg, x, y, units));
    } else {
        /* Horizontal meter is the default */
        volume->meters.push_back(
            new HorizontalBar(meterImg, x, y, units));
    }

    return volume;
}

OSDComponent *SkinV2::MuteOSD() {
    OSDComponent *mute = new OSDComponent;
    mute->background = LoadImg(_skinDir + L"\\OSD\\mute.png");
    mute->mask = LoadImg(_skinDir + L"\\OSD\\glassMask.png");
    return mute;
}

OSDComponent *SkinV2::EjectOSD() {
    return nullptr;
}

std::vector<HICON> SkinV2::VolumeIconset() {
    std::wstring iconDir = _skinDir + L"\\Notification Icons\\";
    return SkinUtils::ReadIconDirectory(iconDir);
}

SliderComponent *SkinV2::VolumeSlider() {
    return nullptr;
}<commit_msg>Implement v2 eject OSD<commit_after>#include "SkinV2.h"

#include "../Logger.h"
#include "../MeterWnd/Meters/MeterTypes.h"
#include "../StringUtils.h"
#include "MeterComponent.h"
#include "OSDComponent.h"
#include "SkinUtils.h"

SkinV2::SkinV2(std::wstring skinXML) :
SkinInfo(skinXML) {

}

SkinV2::~SkinV2() {

}

OSDComponent *SkinV2::VolumeOSD() {
    OSDComponent *volume = new OSDComponent;

    /* Images */
    volume->background = LoadImg(_skinDir + L"\\OSD\\back.png");
    volume->mask = LoadImg(_skinDir + L"\\OSD\\glassMask.png");

    /* Sound */
    std::wstring soundName = _skinDir + L"\\sound.wav";
    SoundPlayer *player = new SoundPlayer(soundName);
    if (player->Ready() == false) {
        delete player;
        player = NULL;
    }
    volume->sound = player;

    /* Determine the number of units */
    int units = 10;
    tinyxml2::XMLElement *meterMax = SubElement("osd", "meterMax");
    if (meterMax) {
        meterMax->QueryIntText(&units);
    }
    volume->defaultUnits = units;

    /* Load the meter(s) */
    const char *meterType = nullptr;
    tinyxml2::XMLElement *meterOrientation
        = SubElement("osd", "meterOrientation");
    if (meterOrientation) {
        meterType = meterOrientation->GetText();
    }
    int x = 0;
    int y = 0;
    tinyxml2::XMLElement *pos = SubElement("osd", "meterPosition");
    if (pos) {
        tinyxml2::XMLElement *xelem = pos->FirstChildElement("X");
        tinyxml2::XMLElement *yelem = pos->FirstChildElement("Y");
        if (xelem) {
            xelem->QueryIntText(&x);
        }
        if (yelem) {
            yelem->QueryIntText(&y);
        }
    }

    std::wstring meterImg = _skinDir + L"\\OSD\\meter.png";
    if (meterType == "vertical") {
        volume->meters.push_back(
            new VerticalBar(meterImg, x, y, units));
    } else if (meterType == "bitstrip") {
        volume->meters.push_back(
            new Bitstrip(meterImg, x, y, units));
    } else {
        /* Horizontal meter is the default */
        volume->meters.push_back(
            new HorizontalBar(meterImg, x, y, units));
    }

    return volume;
}

OSDComponent *SkinV2::MuteOSD() {
    OSDComponent *mute = new OSDComponent;
    mute->background = LoadImg(_skinDir + L"\\OSD\\mute.png");
    mute->mask = LoadImg(_skinDir + L"\\OSD\\glassMask.png");
    return mute;
}

OSDComponent *SkinV2::EjectOSD() {
    OSDComponent *eject = new OSDComponent;
    eject->background = LoadImg(_skinDir + L"\\OSD\\eject.png");
    eject->mask = LoadImg(_skinDir + L"\\OSD\\glassMask.png");
    return eject;
}

std::vector<HICON> SkinV2::VolumeIconset() {
    std::wstring iconDir = _skinDir + L"\\Notification Icons\\";
    return SkinUtils::ReadIconDirectory(iconDir);
}

SliderComponent *SkinV2::VolumeSlider() {
    return nullptr;
}<|endoftext|>