<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include <xenia/kernel/xboxkrnl_io.h>

#include <xenia/kernel/async_request.h>
#include <xenia/kernel/kernel_state.h>
#include <xenia/kernel/xboxkrnl_private.h>
#include <xenia/kernel/objects/xevent.h>
#include <xenia/kernel/objects/xfile.h>
#include <xenia/kernel/util/shim_utils.h>

using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::fs;

namespace xe {
namespace kernel {

SHIM_CALL NtCreateFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t handle_ptr = SHIM_GET_ARG_32(0);
  uint32_t desired_access = SHIM_GET_ARG_32(1);
  uint32_t object_attributes_ptr = SHIM_GET_ARG_32(2);
  uint32_t io_status_block_ptr = SHIM_GET_ARG_32(3);
  uint32_t allocation_size_ptr = SHIM_GET_ARG_32(4);
  uint32_t file_attributes = SHIM_GET_ARG_32(5);
  uint32_t share_access = SHIM_GET_ARG_32(6);
  uint32_t creation_disposition = SHIM_GET_ARG_32(7);

  X_OBJECT_ATTRIBUTES attrs(SHIM_MEM_BASE, object_attributes_ptr);

  XELOGD(
      "NtCreateFile(%.8X, %.8X, %.8X(%s), %.8X, %.8X, %.8X, %d, %d)",
      handle_ptr,
      desired_access,
      object_attributes_ptr,
      attrs.object_name.buffer,
      io_status_block_ptr,
      allocation_size_ptr,
      file_attributes,
      share_access,
      creation_disposition);

  uint64_t allocation_size = 0; // is this correct???
  if (allocation_size_ptr != 0) {
    allocation_size = SHIM_MEM_64(allocation_size_ptr);
  }

  X_STATUS result = X_STATUS_NO_SUCH_FILE;
  uint32_t info = X_FILE_DOES_NOT_EXIST;
  uint32_t handle;

  // Resolve the file using the virtual file system.
  FileSystem* fs = state->file_system();
  Entry* entry = fs->ResolvePath(attrs.object_name.buffer);
  XFile* file = NULL;
  if (entry && entry->type() == Entry::kTypeFile) {
    // Open the file.
    result = entry->Open(
        state,
        desired_access,
        false, // TODO(benvanik): pick async mode, if needed.
        &file);
  } else {
    result = X_STATUS_NO_SUCH_FILE;
    info = X_FILE_DOES_NOT_EXIST;
  }

  if (XSUCCEEDED(result)) {
    // Handle ref is incremented, so return that.
    handle = file->handle();
    file->Release();
    result  = X_STATUS_SUCCESS;
    info    = X_FILE_OPENED;
  }

  if (io_status_block_ptr) {
    SHIM_SET_MEM_32(io_status_block_ptr, result);   // Status
    SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
  }
  if (XSUCCEEDED(result)) {
    if (handle_ptr) {
      SHIM_SET_MEM_32(handle_ptr, handle);
    }
  }
  SHIM_SET_RETURN(result);
}

SHIM_CALL NtOpenFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE);
}

class xeNtReadFileState {
public:
  uint32_t x;
};
void xeNtReadFileCompleted(XAsyncRequest* request, xeNtReadFileState* state) {
  // TODO(benvanik): set io_status_block_ptr
  delete request;
  delete state;
}

SHIM_CALL NtReadFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t file_handle = SHIM_GET_ARG_32(0);
  uint32_t event_handle = SHIM_GET_ARG_32(1);
  uint32_t apc_routine_ptr = SHIM_GET_ARG_32(2);
  uint32_t apc_context = SHIM_GET_ARG_32(3);
  uint32_t io_status_block_ptr = SHIM_GET_ARG_32(4);
  uint32_t buffer = SHIM_GET_ARG_32(5);
  uint32_t buffer_length = SHIM_GET_ARG_32(6);
  uint32_t byte_offset_ptr = SHIM_GET_ARG_32(7);
  size_t byte_offset = byte_offset_ptr ? SHIM_MEM_64(byte_offset_ptr) : 0;

  XELOGD(
      "NtReadFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %d)",
      file_handle,
      event_handle,
      apc_routine_ptr,
      apc_context,
      io_status_block_ptr,
      buffer,
      buffer_length,
      byte_offset_ptr);

  // Async not supported yet.
  XEASSERTNULL(apc_routine_ptr);

  X_STATUS result = X_STATUS_SUCCESS;
  uint32_t info = 0;

  // Grab event to signal.
  XEvent* ev = NULL;
  bool signal_event = false;
  if (event_handle) {
    result = state->object_table()->GetObject(
        event_handle, (XObject**)&ev);
  }

  // Grab file.
  XFile* file = NULL;
  if (XSUCCEEDED(result)) {
    result = state->object_table()->GetObject(
        file_handle, (XObject**)&file);
  }

  // Execute read.
  if (XSUCCEEDED(result)) {
    // Reset event before we begin.
    if (ev) {
      ev->Reset();
    }

    // TODO(benvanik): async path.
    if (true) {
      // Synchronous request.
      if (!byte_offset_ptr ||
          byte_offset == 0xFFFFFFFFfffffffe) {
        // FILE_USE_FILE_POINTER_POSITION
        byte_offset = -1;
      }

      // Read now.
      size_t bytes_read = 0;
      result = file->Read(
          SHIM_MEM_ADDR(buffer), buffer_length, byte_offset,
          &bytes_read);
      if (XSUCCEEDED(result)) {
        info = (int32_t)bytes_read;
      }

      // Mark that we should signal the event now. We do this after
      // we have written the info out.
      signal_event = true;
    } else {
      // X_STATUS_PENDING if not returning immediately.
      // XFile is waitable and signalled after each async req completes.
      // reset the input event (->Reset())
      /*xeNtReadFileState* call_state = new xeNtReadFileState();
      XAsyncRequest* request = new XAsyncRequest(
          state, file,
          (XAsyncRequest::CompletionCallback)xeNtReadFileCompleted,
          call_state);*/
      //result = file->Read(buffer, buffer_length, byte_offset, request);
      result = X_STATUS_PENDING;
      info = 0;
    }
  }

  if (io_status_block_ptr) {
    SHIM_SET_MEM_32(io_status_block_ptr, result);   // Status
    SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
  }

  if (file) {
    file->Release();
  }
  if (ev) {
    if (signal_event) {
      ev->Set(0, false);
    }
    ev->Release();
  }

  SHIM_SET_RETURN(result);
}

SHIM_CALL NtSetInformationFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t file_handle = SHIM_GET_ARG_32(0);
  uint32_t io_status_block_ptr = SHIM_GET_ARG_32(1);
  uint32_t file_info_ptr = SHIM_GET_ARG_32(2);
  uint32_t length = SHIM_GET_ARG_32(3);
  uint32_t file_info_class = SHIM_GET_ARG_32(4);

  XELOGD(
      "NtSetInformationFile(%.8X, %.8X, %.8X, %.8X, %.8X)",
      file_handle,
      io_status_block_ptr,
      file_info_ptr,
      length,
      file_info_class);

  X_STATUS result = X_STATUS_SUCCESS;
  uint32_t info = 0;

  // Grab file.
  XFile* file = NULL;
  result = state->object_table()->GetObject(
      file_handle, (XObject**)&file);

  if (XSUCCEEDED(result)) {
    result = X_STATUS_SUCCESS;
    switch (file_info_class) {
    case XFilePositionInformation:
      // struct FILE_POSITION_INFORMATION {
      //   LARGE_INTEGER CurrentByteOffset;
      // };
      XEASSERT(length == 8);
      info = 8;
      file->set_position(SHIM_MEM_64(file_info_ptr));
      break;
    default:
      // Unsupported, for now.
      XEASSERTALWAYS();
      info = 0;
      break;
    }
  }

  if (XFAILED(result)) {
    info = 0;
  }
  if (io_status_block_ptr) {
    SHIM_SET_MEM_32(io_status_block_ptr, result);   // Status
    SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
  }

  if (file) {
    file->Release();
  }

  SHIM_SET_RETURN(result);
}

SHIM_CALL NtQueryInformationFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t file_handle = SHIM_GET_ARG_32(0);
  uint32_t io_status_block_ptr = SHIM_GET_ARG_32(1);
  uint32_t file_info_ptr = SHIM_GET_ARG_32(2);
  uint32_t length = SHIM_GET_ARG_32(3);
  uint32_t file_info_class = SHIM_GET_ARG_32(4);

  XELOGD(
      "NtQueryInformationFile(%.8X, %.8X, %.8X, %.8X, %.8X)",
      file_handle,
      io_status_block_ptr,
      file_info_ptr,
      length,
      file_info_class);

  X_STATUS result = X_STATUS_SUCCESS;
  uint32_t info = 0;

  // Grab file.
  XFile* file = NULL;
  result = state->object_table()->GetObject(
      file_handle, (XObject**)&file);

  if (XSUCCEEDED(result)) {
    result = X_STATUS_SUCCESS;
    switch (file_info_class) {
    case XFilePositionInformation:
      // struct FILE_POSITION_INFORMATION {
      //   LARGE_INTEGER CurrentByteOffset;
      // };
      XEASSERT(length == 8);
      info = 8;
      SHIM_SET_MEM_64(file_info_ptr, file->position());
      break;
    case XFileNetworkOpenInformation:
      // struct FILE_NETWORK_OPEN_INFORMATION {
      //   LARGE_INTEGER CreationTime;
      //   LARGE_INTEGER LastAccessTime;
      //   LARGE_INTEGER LastWriteTime;
      //   LARGE_INTEGER ChangeTime;
      //   LARGE_INTEGER AllocationSize;
      //   LARGE_INTEGER EndOfFile;
      //   ULONG         FileAttributes;
      //   ULONG         Unknown;
      // };
      XEASSERT(length == 56);
      XFileInfo file_info;
      result = file->QueryInfo(&file_info);
      if (XSUCCEEDED(result)) {
        info = 56;
        file_info.Write(SHIM_MEM_BASE, file_info_ptr);
      }
      break;
    case XFileMailslotSetInformation:
      // Read timeout.
      if (length == 4) {
        info = 4; // ? it's not a read.
        uint32_t read_timeout = SHIM_MEM_32(file_info_ptr);
        // May be INFINITE.
        // Do something with this?
      } else {
        result = X_STATUS_INFO_LENGTH_MISMATCH;
      }
      break;
    default:
      // Unsupported, for now.
      XEASSERTALWAYS();
      info = 0;
      break;
    }
  }

  if (XFAILED(result)) {
    info = 0;
  }
  if (io_status_block_ptr) {
    SHIM_SET_MEM_32(io_status_block_ptr, result);   // Status
    SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
  }

  if (file) {
    file->Release();
  }

  SHIM_SET_RETURN(result);
}

SHIM_CALL NtQueryFullAttributesFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t object_attributes_ptr = SHIM_GET_ARG_32(0);
  uint32_t file_info_ptr = SHIM_GET_ARG_32(1);

  X_OBJECT_ATTRIBUTES attrs(SHIM_MEM_BASE, object_attributes_ptr);

  XELOGD(
      "NtQueryFullAttributesFile(%.8X(%s), %.8X)",
      object_attributes_ptr,
      attrs.object_name.buffer,
      file_info_ptr);

  X_STATUS result = X_STATUS_NO_SUCH_FILE;

  // Resolve the file using the virtual file system.
  FileSystem* fs = state->file_system();
  Entry* entry = fs->ResolvePath(attrs.object_name.buffer);
  if (entry && entry->type() == Entry::kTypeFile) {
    // Found.
    XFileInfo file_info;
    result = entry->QueryInfo(&file_info);
    if (XSUCCEEDED(result)) {
      file_info.Write(SHIM_MEM_BASE, file_info_ptr);
    }
  }

  SHIM_SET_RETURN(result);
}

SHIM_CALL NtQueryVolumeInformationFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE);
}

}  // namespace kernel
}  // namespace xe

void xe::kernel::xboxkrnl::RegisterIoExports(
    ExportResolver* export_resolver, KernelState* state) {
  SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtOpenFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtReadFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryInformationFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtSetInformationFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryFullAttributesFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryVolumeInformationFile, state);
}
<commit_msg>FscSetCacheElementCount stub.<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include <xenia/kernel/xboxkrnl_io.h>

#include <xenia/kernel/async_request.h>
#include <xenia/kernel/kernel_state.h>
#include <xenia/kernel/xboxkrnl_private.h>
#include <xenia/kernel/objects/xevent.h>
#include <xenia/kernel/objects/xfile.h>
#include <xenia/kernel/util/shim_utils.h>

using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::fs;

namespace xe {
namespace kernel {

SHIM_CALL NtCreateFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t handle_ptr = SHIM_GET_ARG_32(0);
  uint32_t desired_access = SHIM_GET_ARG_32(1);
  uint32_t object_attributes_ptr = SHIM_GET_ARG_32(2);
  uint32_t io_status_block_ptr = SHIM_GET_ARG_32(3);
  uint32_t allocation_size_ptr = SHIM_GET_ARG_32(4);
  uint32_t file_attributes = SHIM_GET_ARG_32(5);
  uint32_t share_access = SHIM_GET_ARG_32(6);
  uint32_t creation_disposition = SHIM_GET_ARG_32(7);

  X_OBJECT_ATTRIBUTES attrs(SHIM_MEM_BASE, object_attributes_ptr);

  XELOGD(
      "NtCreateFile(%.8X, %.8X, %.8X(%s), %.8X, %.8X, %.8X, %d, %d)",
      handle_ptr,
      desired_access,
      object_attributes_ptr,
      attrs.object_name.buffer,
      io_status_block_ptr,
      allocation_size_ptr,
      file_attributes,
      share_access,
      creation_disposition);

  uint64_t allocation_size = 0; // is this correct???
  if (allocation_size_ptr != 0) {
    allocation_size = SHIM_MEM_64(allocation_size_ptr);
  }

  X_STATUS result = X_STATUS_NO_SUCH_FILE;
  uint32_t info = X_FILE_DOES_NOT_EXIST;
  uint32_t handle;

  // Resolve the file using the virtual file system.
  FileSystem* fs = state->file_system();
  Entry* entry = fs->ResolvePath(attrs.object_name.buffer);
  XFile* file = NULL;
  if (entry && entry->type() == Entry::kTypeFile) {
    // Open the file.
    result = entry->Open(
        state,
        desired_access,
        false, // TODO(benvanik): pick async mode, if needed.
        &file);
  } else {
    result = X_STATUS_NO_SUCH_FILE;
    info = X_FILE_DOES_NOT_EXIST;
  }

  if (XSUCCEEDED(result)) {
    // Handle ref is incremented, so return that.
    handle = file->handle();
    file->Release();
    result  = X_STATUS_SUCCESS;
    info    = X_FILE_OPENED;
  }

  if (io_status_block_ptr) {
    SHIM_SET_MEM_32(io_status_block_ptr, result);   // Status
    SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
  }
  if (XSUCCEEDED(result)) {
    if (handle_ptr) {
      SHIM_SET_MEM_32(handle_ptr, handle);
    }
  }
  SHIM_SET_RETURN(result);
}

SHIM_CALL NtOpenFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE);
}

class xeNtReadFileState {
public:
  uint32_t x;
};
void xeNtReadFileCompleted(XAsyncRequest* request, xeNtReadFileState* state) {
  // TODO(benvanik): set io_status_block_ptr
  delete request;
  delete state;
}

SHIM_CALL NtReadFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t file_handle = SHIM_GET_ARG_32(0);
  uint32_t event_handle = SHIM_GET_ARG_32(1);
  uint32_t apc_routine_ptr = SHIM_GET_ARG_32(2);
  uint32_t apc_context = SHIM_GET_ARG_32(3);
  uint32_t io_status_block_ptr = SHIM_GET_ARG_32(4);
  uint32_t buffer = SHIM_GET_ARG_32(5);
  uint32_t buffer_length = SHIM_GET_ARG_32(6);
  uint32_t byte_offset_ptr = SHIM_GET_ARG_32(7);
  size_t byte_offset = byte_offset_ptr ? SHIM_MEM_64(byte_offset_ptr) : 0;

  XELOGD(
      "NtReadFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %d)",
      file_handle,
      event_handle,
      apc_routine_ptr,
      apc_context,
      io_status_block_ptr,
      buffer,
      buffer_length,
      byte_offset_ptr);

  // Async not supported yet.
  XEASSERTNULL(apc_routine_ptr);

  X_STATUS result = X_STATUS_SUCCESS;
  uint32_t info = 0;

  // Grab event to signal.
  XEvent* ev = NULL;
  bool signal_event = false;
  if (event_handle) {
    result = state->object_table()->GetObject(
        event_handle, (XObject**)&ev);
  }

  // Grab file.
  XFile* file = NULL;
  if (XSUCCEEDED(result)) {
    result = state->object_table()->GetObject(
        file_handle, (XObject**)&file);
  }

  // Execute read.
  if (XSUCCEEDED(result)) {
    // Reset event before we begin.
    if (ev) {
      ev->Reset();
    }

    // TODO(benvanik): async path.
    if (true) {
      // Synchronous request.
      if (!byte_offset_ptr ||
          byte_offset == 0xFFFFFFFFfffffffe) {
        // FILE_USE_FILE_POINTER_POSITION
        byte_offset = -1;
      }

      // Read now.
      size_t bytes_read = 0;
      result = file->Read(
          SHIM_MEM_ADDR(buffer), buffer_length, byte_offset,
          &bytes_read);
      if (XSUCCEEDED(result)) {
        info = (int32_t)bytes_read;
      }

      // Mark that we should signal the event now. We do this after
      // we have written the info out.
      signal_event = true;
    } else {
      // X_STATUS_PENDING if not returning immediately.
      // XFile is waitable and signalled after each async req completes.
      // reset the input event (->Reset())
      /*xeNtReadFileState* call_state = new xeNtReadFileState();
      XAsyncRequest* request = new XAsyncRequest(
          state, file,
          (XAsyncRequest::CompletionCallback)xeNtReadFileCompleted,
          call_state);*/
      //result = file->Read(buffer, buffer_length, byte_offset, request);
      result = X_STATUS_PENDING;
      info = 0;
    }
  }

  if (io_status_block_ptr) {
    SHIM_SET_MEM_32(io_status_block_ptr, result);   // Status
    SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
  }

  if (file) {
    file->Release();
  }
  if (ev) {
    if (signal_event) {
      ev->Set(0, false);
    }
    ev->Release();
  }

  SHIM_SET_RETURN(result);
}

SHIM_CALL NtSetInformationFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t file_handle = SHIM_GET_ARG_32(0);
  uint32_t io_status_block_ptr = SHIM_GET_ARG_32(1);
  uint32_t file_info_ptr = SHIM_GET_ARG_32(2);
  uint32_t length = SHIM_GET_ARG_32(3);
  uint32_t file_info_class = SHIM_GET_ARG_32(4);

  XELOGD(
      "NtSetInformationFile(%.8X, %.8X, %.8X, %.8X, %.8X)",
      file_handle,
      io_status_block_ptr,
      file_info_ptr,
      length,
      file_info_class);

  X_STATUS result = X_STATUS_SUCCESS;
  uint32_t info = 0;

  // Grab file.
  XFile* file = NULL;
  result = state->object_table()->GetObject(
      file_handle, (XObject**)&file);

  if (XSUCCEEDED(result)) {
    result = X_STATUS_SUCCESS;
    switch (file_info_class) {
    case XFilePositionInformation:
      // struct FILE_POSITION_INFORMATION {
      //   LARGE_INTEGER CurrentByteOffset;
      // };
      XEASSERT(length == 8);
      info = 8;
      file->set_position(SHIM_MEM_64(file_info_ptr));
      break;
    default:
      // Unsupported, for now.
      XEASSERTALWAYS();
      info = 0;
      break;
    }
  }

  if (XFAILED(result)) {
    info = 0;
  }
  if (io_status_block_ptr) {
    SHIM_SET_MEM_32(io_status_block_ptr, result);   // Status
    SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
  }

  if (file) {
    file->Release();
  }

  SHIM_SET_RETURN(result);
}

SHIM_CALL NtQueryInformationFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t file_handle = SHIM_GET_ARG_32(0);
  uint32_t io_status_block_ptr = SHIM_GET_ARG_32(1);
  uint32_t file_info_ptr = SHIM_GET_ARG_32(2);
  uint32_t length = SHIM_GET_ARG_32(3);
  uint32_t file_info_class = SHIM_GET_ARG_32(4);

  XELOGD(
      "NtQueryInformationFile(%.8X, %.8X, %.8X, %.8X, %.8X)",
      file_handle,
      io_status_block_ptr,
      file_info_ptr,
      length,
      file_info_class);

  X_STATUS result = X_STATUS_SUCCESS;
  uint32_t info = 0;

  // Grab file.
  XFile* file = NULL;
  result = state->object_table()->GetObject(
      file_handle, (XObject**)&file);

  if (XSUCCEEDED(result)) {
    result = X_STATUS_SUCCESS;
    switch (file_info_class) {
    case XFilePositionInformation:
      // struct FILE_POSITION_INFORMATION {
      //   LARGE_INTEGER CurrentByteOffset;
      // };
      XEASSERT(length == 8);
      info = 8;
      SHIM_SET_MEM_64(file_info_ptr, file->position());
      break;
    case XFileNetworkOpenInformation:
      // struct FILE_NETWORK_OPEN_INFORMATION {
      //   LARGE_INTEGER CreationTime;
      //   LARGE_INTEGER LastAccessTime;
      //   LARGE_INTEGER LastWriteTime;
      //   LARGE_INTEGER ChangeTime;
      //   LARGE_INTEGER AllocationSize;
      //   LARGE_INTEGER EndOfFile;
      //   ULONG         FileAttributes;
      //   ULONG         Unknown;
      // };
      XEASSERT(length == 56);
      XFileInfo file_info;
      result = file->QueryInfo(&file_info);
      if (XSUCCEEDED(result)) {
        info = 56;
        file_info.Write(SHIM_MEM_BASE, file_info_ptr);
      }
      break;
    case XFileMailslotSetInformation:
      // Read timeout.
      if (length == 4) {
        info = 4; // ? it's not a read.
        uint32_t read_timeout = SHIM_MEM_32(file_info_ptr);
        // May be INFINITE.
        // Do something with this?
      } else {
        result = X_STATUS_INFO_LENGTH_MISMATCH;
      }
      break;
    default:
      // Unsupported, for now.
      XEASSERTALWAYS();
      info = 0;
      break;
    }
  }

  if (XFAILED(result)) {
    info = 0;
  }
  if (io_status_block_ptr) {
    SHIM_SET_MEM_32(io_status_block_ptr, result);   // Status
    SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
  }

  if (file) {
    file->Release();
  }

  SHIM_SET_RETURN(result);
}

SHIM_CALL NtQueryFullAttributesFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t object_attributes_ptr = SHIM_GET_ARG_32(0);
  uint32_t file_info_ptr = SHIM_GET_ARG_32(1);

  X_OBJECT_ATTRIBUTES attrs(SHIM_MEM_BASE, object_attributes_ptr);

  XELOGD(
      "NtQueryFullAttributesFile(%.8X(%s), %.8X)",
      object_attributes_ptr,
      attrs.object_name.buffer,
      file_info_ptr);

  X_STATUS result = X_STATUS_NO_SUCH_FILE;

  // Resolve the file using the virtual file system.
  FileSystem* fs = state->file_system();
  Entry* entry = fs->ResolvePath(attrs.object_name.buffer);
  if (entry && entry->type() == Entry::kTypeFile) {
    // Found.
    XFileInfo file_info;
    result = entry->QueryInfo(&file_info);
    if (XSUCCEEDED(result)) {
      file_info.Write(SHIM_MEM_BASE, file_info_ptr);
    }
  }

  SHIM_SET_RETURN(result);
}

SHIM_CALL NtQueryVolumeInformationFile_shim(
    PPCContext* ppc_state, KernelState* state) {
  SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE);
}

SHIM_CALL FscSetCacheElementCount_shim(
    PPCContext* ppc_state, KernelState* state) {
  uint32_t unk_0 = SHIM_GET_ARG_32(0);
  uint32_t unk_1 = SHIM_GET_ARG_32(1);
  // unk_0 = 0
  // unk_1 looks like a count? in what units? 256 is a common value

  XELOGD(
      "FscSetCacheElementCount(%.8X, %.8X)",
      unk_0, unk_1);

  SHIM_SET_RETURN(X_STATUS_SUCCESS);
}

}  // namespace kernel
}  // namespace xe

void xe::kernel::xboxkrnl::RegisterIoExports(
    ExportResolver* export_resolver, KernelState* state) {
  SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtOpenFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtReadFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryInformationFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtSetInformationFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryFullAttributesFile, state);
  SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryVolumeInformationFile, state);

  SHIM_SET_MAPPING("xboxkrnl.exe", FscSetCacheElementCount, state);
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

/*
 * CBrowseModelVersionDialog.cpp
 *
 *  Created on: 21 Feb 2016
 *      Author: Peyman Zarrineh
 */

#include <QMessageBox>
#include <QInputDialog>
#include <QDir>
#include "CBrowseModelVersionDialog.h"
#include "ui_CBrowseModelVersionDialog.h"

#ifdef COPASI_Provenance
#include "copasi/Provenance/CProvenanceXMLWriter.h"
#endif

CBrowseModelVersionDialog::CBrowseModelVersionDialog(QWidget *parent, CModelVersion  * ModelVersion, DataModelGUI * ModelGUI,   QUndoStack  *     UndoStack
#ifdef COPASI_Provenance
    , QString PathProvenance,   QString ProvenanceParentOfCurrentModel
#endif
                                                    ) :
  QDialog(parent),
  ui(new Ui::CBrowseModelVersionDialog)
{
  ui->setupUi(this);
  //mLastSavedParentOfCurrentModel = LastSavedParentOfCurrentModel;
  // set "the dialog table pointer" points to main table in the table of this dialog

  int NumberOfVersions = ModelVersion->getNumberOfVersions();
  mpModelVersion = ModelVersion;
  mpDataModelGUI = ModelGUI;
  int i;
  ui->tableView->setModel(mpModelVersion->getModelVersionHierarchy());
  ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
  ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);

  for (i = NumberOfVersions; i < mpModelVersion->getModelVersionHierarchy()->rowCount(); i++)
    {
      ui->tableView->setRowHidden(i, true);
    }

  ui->tableView->setColumnHidden(4, true);
  ui->tableView->setColumnHidden(5, true);
  ui->DeleteButton->setEnabled(false);
  ui->RestoreButton->setEnabled(false);
  ui->CloseButton->setEnabled(true);
  ui->tableView->setEnabled(true);
  mpUndoStack = UndoStack;
#ifdef COPASI_Provenance
  mPathProvenance = PathProvenance;
  mProvenanceParentOfCurrentModel =  ProvenanceParentOfCurrentModel;
#endif
}

CBrowseModelVersionDialog::~CBrowseModelVersionDialog()
{
  delete ui;
}

void CBrowseModelVersionDialog::on_RestoreButton_clicked()
{

  QModelIndex selectedIndex = ui->tableView->currentIndex();
  QString Version = mpModelVersion->getModelVersionHierarchy()->item(selectedIndex.row(), 0)->text();
  QMessageBox msgBox;
  msgBox.setWindowTitle("Version Restoring Warning");
  msgBox.setText("The current model will be replaced, losing edits. To keep the current model create a version. Do you still want to restore this version?");
  msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
  int ret = msgBox.exec();

  switch (ret)
    {
      case QMessageBox::Ok:
      {
        int i = mpModelVersion->restoreVersion(Version);

        if (i == 1)
          {
            QMessageBox::about(this, tr("Error"), tr("Version name is empty"));
          }

        if (i == 2)
          {
            QMessageBox::about(this, tr("Error"), tr("Version name does not exist in version hierarchy"));
          }

        // Load the selected version in combined archive as the current model
        if (i == 0)
          {
            QString dataFile;

            if (mpModelVersion->getPathFile() == "")
              {
                dataFile = Version +  "/" + Version;
              }
            else
              {
                dataFile = mpModelVersion->getPathFile() +  "/" + Version +  "/" + Version;
              }

            QFile Fout(dataFile);

            if (!Fout.exists())
              {
                QMessageBox::about(this, tr("Error"), tr("Version file does not exist in the folder"));
              }
            else
              {
                mpDataModelGUI->loadModel(dataFile.toStdString());
                mpUndoStack->clear();
              }
          }

        ui->DeleteButton->setEnabled(false);
        ui->RestoreButton->setEnabled(false);
        ui->CloseButton->setEnabled(true);
        ui->tableView->setEnabled(true);
      }

      case QMessageBox::Cancel:
      {
        ui->DeleteButton->setEnabled(false);
        ui->RestoreButton->setEnabled(false);
        ui->CloseButton->setEnabled(true);
        ui->tableView->setEnabled(true);
      }
    }
}

void CBrowseModelVersionDialog::on_DeleteButton_clicked()
{
  QModelIndex selectedIndex = ui->tableView->currentIndex();
  QString Version = mpModelVersion->getModelVersionHierarchy()->item(selectedIndex.row(), 0)->text();
  QMessageBox::NoIcon;
  QMessageBox msgBox;
  QString ParentOfCurrentModel = mpModelVersion->getParentOfCurrentModel();
  msgBox.setWindowTitle("Version Deletion Warning");
  msgBox.setText("Are you sure you want delete this version?");
  msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
  int ret = msgBox.exec();
  QString ParentVersion;

  switch (ret)
    {
      case QMessageBox::Ok:
      {
        int i;
        //bool isParrentOfLastSavedVersion = false;
        //if(mLastSavedParentOfCurrentModel==Version)
        //{
        //    isParrentOfLastSavedVersion = true;
        //    ParentVersion = mpModelVersion->getParentVersion(Version);
        //}
#ifdef COPASI_Provenance
        bool isParrentOfCurrentVersion = false;

        if (ParentOfCurrentModel == Version)
          {
            isParrentOfCurrentVersion = true;
          }

        QList<QString> ChildrenVersions = mpModelVersion->getChildrenOfVersionForProvenanceXML(Version);
#endif

        i = mpModelVersion->deleteVersion(Version);

        if (i == 1)
          {
            QMessageBox::about(this, tr("Error"), tr("Version name is empty"));
          }

        if (i == 2)
          {
            QMessageBox::about(this, tr("Error"), tr("Version name does not exist in version hierarchy"));
          }

        if (i == 3)
          {
            QMessageBox::about(this, tr("Error"), tr("Root version cannot be deleted in the presence of any other version"));
          }

        // Delete the selected version from
        if (i == 0)
          {
            //if(isParrentOfLastSavedVersion)
            //{
            //        mLastSavedParentOfCurrentModel = ParentVersion;
            //}

            QDir destination;
            QString dataFile;

            if (mpModelVersion->getPathFile() == "")
              {
                dataFile = Version +  "/" + Version;
              }
            else
              {
                dataFile = mpModelVersion->getPathFile() + "/" + Version +  "/" + Version;
              }

            destination.remove(dataFile);
#ifdef COPASI_Provenance
            CProvenanceXMLWriter* ProvenanceXMLWriter = new CProvenanceXMLWriter(this, mpUndoStack, mPathProvenance, QString(""), QString(""), mProvenanceParentOfCurrentModel, ParentOfCurrentModel);

            if (isParrentOfCurrentVersion)
              {
                ProvenanceXMLWriter->deleteParentofCurrentVersionProvenance(Version);
                mProvenanceParentOfCurrentModel =  mpModelVersion->getParentOfCurrentModel();
              }

            if (!ChildrenVersions.isEmpty())
              {
                int j;

                for (j = 0; j < ChildrenVersions.size(); ++j)
                  {
                    ProvenanceXMLWriter->combineVersionProvenance(Version, ChildrenVersions.at(j));
                  }
              }

            ProvenanceXMLWriter->deleteVersionProvenance(Version);
#endif
// now remove the directory
            QString path = mpModelVersion->getPathFile() + "/" + Version;
            QDir dir(path);

            if (dir.exists())
              {
                dir.rmdir(path);
              }
          }

        int NumberOfVersions = mpModelVersion->getNumberOfVersions();
        ui->tableView->setModel(mpModelVersion->getModelVersionHierarchy());
        ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);

        for (i = NumberOfVersions; i < mpModelVersion->getModelVersionHierarchy()->rowCount(); i++)
          {
            ui->tableView->setRowHidden(i, true);
          }

        ui->tableView->setColumnHidden(4, true);
        ui->tableView->setColumnHidden(5, true);

        ui->DeleteButton->setEnabled(false);
        ui->RestoreButton->setEnabled(false);
        ui->CloseButton->setEnabled(true);
        ui->tableView->setEnabled(true);
      }

      case QMessageBox::Cancel:
      {
        ui->DeleteButton->setEnabled(false);
        ui->RestoreButton->setEnabled(false);
        ui->CloseButton->setEnabled(true);
        ui->tableView->setEnabled(true);
      }
    }
}

void CBrowseModelVersionDialog::on_tableView_clicked()
{
  ui->DeleteButton->setEnabled(true);
  ui->RestoreButton->setEnabled(true);
  ui->CloseButton->setEnabled(true);
  ui->tableView->setEnabled(true);
}

void CBrowseModelVersionDialog::on_tableView_doubleClicked(const QModelIndex &index)
{
  if (index.column() == mpModelVersion->getModelVersionHierarchy()->columnCount() - 1)
    {
      QString text = QInputDialog::getText(this, tr("Update Comments"), tr("Update selected Comments:"), QLineEdit::Normal);

      if (text.isEmpty() == false)
        {
          mpModelVersion->updateSelectedCell(index, text);
        }
    }
}

#ifdef COPASI_Provenance
QString CBrowseModelVersionDialog::getProvenanceParentOfCurrentModel()
{
  return(mProvenanceParentOfCurrentModel);
}

#endif

//QString CBrowseModelVersionDialog::getLastSavedParentOfCurrentModel()
//{
//    return(mLastSavedParentOfCurrentModel);
//}
<commit_msg>copasi/UI/CBrowseModelVersionDialog.cpp<commit_after>// Copyright (C) 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

/*
 * CBrowseModelVersionDialog.cpp
 *
 *  Created on: 21 Feb 2016
 *      Author: Peyman Zarrineh
 */

#include <QMessageBox>
#include <QInputDialog>
#include <QDir>
#include "CBrowseModelVersionDialog.h"
#include "ui_CBrowseModelVersionDialog.h"

#ifdef COPASI_Provenance
#include "copasi/Provenance/CProvenanceXMLWriter.h"
#endif

CBrowseModelVersionDialog::CBrowseModelVersionDialog(QWidget *parent, CModelVersion  * ModelVersion, DataModelGUI * ModelGUI,   QUndoStack  *     UndoStack
#ifdef COPASI_Provenance
//                                                     , QString PathProvenance,   QString ProvenanceParentOfCurrentModel
    , QString PathProvenance
#endif
                                                    ) :
  QDialog(parent),
  ui(new Ui::CBrowseModelVersionDialog)
{
  ui->setupUi(this);
  //mLastSavedParentOfCurrentModel = LastSavedParentOfCurrentModel;
  // set "the dialog table pointer" points to main table in the table of this dialog

  int NumberOfVersions = ModelVersion->getNumberOfVersions();
  mpModelVersion = ModelVersion;
  mpDataModelGUI = ModelGUI;
  int i;
  ui->tableView->setModel(mpModelVersion->getModelVersionHierarchy());
  ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
  ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);

  for (i = NumberOfVersions; i < mpModelVersion->getModelVersionHierarchy()->rowCount(); i++)
    {
      ui->tableView->setRowHidden(i, true);
    }

  ui->tableView->setColumnHidden(4, true);
  ui->tableView->setColumnHidden(5, true);
  ui->DeleteButton->setEnabled(false);
  ui->RestoreButton->setEnabled(false);
  ui->CloseButton->setEnabled(true);
  ui->tableView->setEnabled(true);
  mpUndoStack = UndoStack;
#ifdef COPASI_Provenance
  mPathProvenance = PathProvenance;
  //mProvenanceParentOfCurrentModel =  ProvenanceParentOfCurrentModel;
#endif
}

CBrowseModelVersionDialog::~CBrowseModelVersionDialog()
{
  delete ui;
}

void CBrowseModelVersionDialog::on_RestoreButton_clicked()
{

  QModelIndex selectedIndex = ui->tableView->currentIndex();
  QString Version = mpModelVersion->getModelVersionHierarchy()->item(selectedIndex.row(), 0)->text();
  QMessageBox msgBox;
  msgBox.setWindowTitle("Version Restoring Warning");
  msgBox.setText("The current model will be replaced, losing edits. To keep the current model create a version. Do you still want to restore this version?");
  msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
  int ret = msgBox.exec();

  switch (ret)
    {
      case QMessageBox::Ok:
      {
        int i = mpModelVersion->restoreVersion(Version);

        if (i == 1)
          {
            QMessageBox::about(this, tr("Error"), tr("Version name is empty"));
          }

        if (i == 2)
          {
            QMessageBox::about(this, tr("Error"), tr("Version name does not exist in version hierarchy"));
          }

        // Load the selected version in combined archive as the current model
        if (i == 0)
          {
            QString dataFile;

            if (mpModelVersion->getPathFile() == "")
              {
                dataFile = Version +  "/" + Version;
              }
            else
              {
                dataFile = mpModelVersion->getPathFile() +  "/" + Version +  "/" + Version;
              }

            QFile Fout(dataFile);

            if (!Fout.exists())
              {
                QMessageBox::about(this, tr("Error"), tr("Version file does not exist in the folder"));
              }
            else
              {
                mpDataModelGUI->loadModel(dataFile.toStdString());
                mpUndoStack->clear();
              }

#ifdef COPASI_Provenance
            // After restore remove mainbody provenance
            QDir destination;
            dataFile = mpModelVersion->getPathFile() + "/ProvenanceMainBody.xml";
            destination.remove(dataFile);
#endif
          }

        ui->DeleteButton->setEnabled(false);
        ui->RestoreButton->setEnabled(false);
        ui->CloseButton->setEnabled(true);
        ui->tableView->setEnabled(true);
      }

      case QMessageBox::Cancel:
      {
        ui->DeleteButton->setEnabled(false);
        ui->RestoreButton->setEnabled(false);
        ui->CloseButton->setEnabled(true);
        ui->tableView->setEnabled(true);
      }
    }
}

void CBrowseModelVersionDialog::on_DeleteButton_clicked()
{
  QModelIndex selectedIndex = ui->tableView->currentIndex();
  QString Version = mpModelVersion->getModelVersionHierarchy()->item(selectedIndex.row(), 0)->text();
  QMessageBox::NoIcon;
  QMessageBox msgBox;
  msgBox.setWindowTitle("Version Deletion Warning");
  msgBox.setText("Are you sure you want delete this version?");
  msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
  int ret = msgBox.exec();
  //QString ParentVersion;

  switch (ret)
    {
      case QMessageBox::Ok:
      {
        int i;
        //bool isParrentOfLastSavedVersion = false;
        //if(mLastSavedParentOfCurrentModel==Version)
        //{
        //    isParrentOfLastSavedVersion = true;
        //    ParentVersion = mpModelVersion->getParentVersion(Version);
        //}
#ifdef COPASI_Provenance
        bool isParrentOfCurrentVersion = false;
        QString ParentOfCurrentModel = mpModelVersion->getParentOfCurrentModel();

        if (ParentOfCurrentModel == Version)
          {
            isParrentOfCurrentVersion = true;
          }

        QList<QString> ChildrenVersions = mpModelVersion->getChildrenOfVersionForProvenanceXML(Version);
#endif

        i = mpModelVersion->deleteVersion(Version);

        if (i == 1)
          {
            QMessageBox::about(this, tr("Error"), tr("Version name is empty"));
          }

        if (i == 2)
          {
            QMessageBox::about(this, tr("Error"), tr("Version name does not exist in version hierarchy"));
          }

        if (i == 3)
          {
            QMessageBox::about(this, tr("Error"), tr("Root version cannot be deleted in the presence of any other version"));
          }

        // Delete the selected version from
        if (i == 0)
          {
            //if(isParrentOfLastSavedVersion)
            //{
            //        mLastSavedParentOfCurrentModel = ParentVersion;
            //}

            QDir destination;
            QString dataFile;

            if (mpModelVersion->getPathFile() == "")
              {
                dataFile = Version +  "/" + Version;
              }
            else
              {
                dataFile = mpModelVersion->getPathFile() + "/" + Version +  "/" + Version;
              }

            destination.remove(dataFile);
#ifdef COPASI_Provenance
            //CProvenanceXMLWriter* ProvenanceXMLWriter = new CProvenanceXMLWriter(this, mpUndoStack, mPathProvenance, QString(""), QString(""), mProvenanceParentOfCurrentModel, ParentOfCurrentModel);
            CProvenanceXMLWriter* ProvenanceXMLWriter = new CProvenanceXMLWriter(this, mpUndoStack, mPathProvenance);

            if (isParrentOfCurrentVersion)
              {
                ProvenanceXMLWriter->deleteParentofCurrentVersionProvenance(Version);
                //mProvenanceParentOfCurrentModel =  mpModelVersion->getParentOfCurrentModel();
              }

            if (!ChildrenVersions.isEmpty())
              {
                int j;

                for (j = 0; j < ChildrenVersions.size(); ++j)
                  {
                    ProvenanceXMLWriter->combineVersionProvenance(Version, ChildrenVersions.at(j));
                  }
              }

            ProvenanceXMLWriter->deleteVersionProvenance(Version);
#endif
// now remove the directory
            QString path = mpModelVersion->getPathFile() + "/" + Version;
            QDir dir(path);

            if (dir.exists())
              {
                dir.rmdir(path);
              }
          }

        int NumberOfVersions = mpModelVersion->getNumberOfVersions();
        ui->tableView->setModel(mpModelVersion->getModelVersionHierarchy());
        ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);

        for (i = NumberOfVersions; i < mpModelVersion->getModelVersionHierarchy()->rowCount(); i++)
          {
            ui->tableView->setRowHidden(i, true);
          }

        ui->tableView->setColumnHidden(4, true);
        ui->tableView->setColumnHidden(5, true);

        ui->DeleteButton->setEnabled(false);
        ui->RestoreButton->setEnabled(false);
        ui->CloseButton->setEnabled(true);
        ui->tableView->setEnabled(true);
      }

      case QMessageBox::Cancel:
      {
        ui->DeleteButton->setEnabled(false);
        ui->RestoreButton->setEnabled(false);
        ui->CloseButton->setEnabled(true);
        ui->tableView->setEnabled(true);
      }
    }
}

void CBrowseModelVersionDialog::on_tableView_clicked()
{
  ui->DeleteButton->setEnabled(true);
  ui->RestoreButton->setEnabled(true);
  ui->CloseButton->setEnabled(true);
  ui->tableView->setEnabled(true);
}

void CBrowseModelVersionDialog::on_tableView_doubleClicked(const QModelIndex &index)
{
  if (index.column() == mpModelVersion->getModelVersionHierarchy()->columnCount() - 1)
    {
      QString text = QInputDialog::getText(this, tr("Update Comments"), tr("Update selected Comments:"), QLineEdit::Normal);

      if (text.isEmpty() == false)
        {
          mpModelVersion->updateSelectedCell(index, text);
        }
    }
}

//#ifdef COPASI_Provenance
//QString CBrowseModelVersionDialog::getProvenanceParentOfCurrentModel()
//{
//  return(mProvenanceParentOfCurrentModel);
//}

//#endif

//QString CBrowseModelVersionDialog::getLastSavedParentOfCurrentModel()
//{
//    return(mLastSavedParentOfCurrentModel);
//}
<|endoftext|>


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

#include "qmessageservice.h"
#include "qmessageservice_symbian_p.h"
#include "qmtmengine_symbian_p.h"

QTM_BEGIN_NAMESPACE

QMessageServicePrivate::QMessageServicePrivate(QMessageService* parent)
 : q_ptr(parent),
   _state(QMessageService::InactiveState),
   _active(false)
{
}

QMessageServicePrivate::~QMessageServicePrivate()
{
}

bool QMessageServicePrivate::sendSMS(QMessage &message)
{
	return CMTMEngine::instance()->sendSMS(message);
}

bool QMessageServicePrivate::sendMMS(QMessage &message)
{
	CMTMEngine* mtmEngine = CMTMEngine::instance();
	bool retVal = mtmEngine->storeMMS(message, KMsvGlobalOutBoxIndexEntryId);
	if (retVal){
		mtmEngine->sendMMS();
	}
	return retVal;
}

bool QMessageServicePrivate::sendEmail(QMessage &message)
{
	CMTMEngine* mtmEngine = CMTMEngine::instance();
	bool retVal = mtmEngine->storeEmail(message, KMsvGlobalOutBoxIndexEntryId);
	if (retVal){
		mtmEngine->sendEmail(message);
	}
	return retVal;
}

bool QMessageServicePrivate::show(const QMessageId& id)
{
	return CMTMEngine::instance()->showMessage(id);
}

bool QMessageServicePrivate::compose(const QMessage &message)
{
	return CMTMEngine::instance()->composeMessage(message);
}

bool QMessageServicePrivate::queryMessages(const QMessageFilter &filter, const QMessageSortOrder &sortOrder, uint limit, uint offset) const
{
    return CMTMEngine::instance()->queryMessages((QMessageServicePrivate&)*this, filter, sortOrder, limit, offset);
}

bool QMessageServicePrivate::queryMessages(const QMessageFilter &filter, const QString &body, QMessageDataComparator::MatchFlags matchFlags, const QMessageSortOrder &sortOrder, uint limit, uint offset) const
{
    return CMTMEngine::instance()->queryMessages((QMessageServicePrivate&)*this, filter, body, matchFlags, sortOrder, limit, offset);
}

bool QMessageServicePrivate::countMessages(const QMessageFilter &filter)
{
    return CMTMEngine::instance()->countMessages((QMessageServicePrivate&)*this, filter);
}

bool QMessageServicePrivate::retrieve(const QMessageId &messageId, const QMessageContentContainerId &id)
{
	return CMTMEngine::instance()->retrieve(messageId, id);
}

bool QMessageServicePrivate::retrieveBody(const QMessageId& id)
{
	return CMTMEngine::instance()->retrieveBody(id);
}

bool QMessageServicePrivate::retrieveHeader(const QMessageId& id)
{
	return CMTMEngine::instance()->retrieveHeader(id);
}

void QMessageServicePrivate::setFinished(bool successful, void (QMessageService::*signal)(QMessageService::State))
{
    if (!successful && (_error == QMessageManager::NoError)) {
        // We must report an error of some sort
        _error = QMessageManager::RequestIncomplete;
    }

    _state = QMessageService::FinishedState;
    emit q_ptr->(*signal)(_state);
    _active = false;
}

QMessageService::QMessageService(QObject *parent)
    : QObject(parent),
    d_ptr(new QMessageServicePrivate(this))
{
	connect(d_ptr, SIGNAL(stateChanged(QMessageService::State)), this, SIGNAL(stateChanged(QMessageService::State)));
	connect(d_ptr, SIGNAL(messagesFound(const QMessageIdList&)), this, SIGNAL(messagesFound(const QMessageIdList&)));
    connect(d_ptr, SIGNAL(messagesCounted(int)), this, SIGNAL(messagesCounted(int)));
	connect(d_ptr, SIGNAL(progressChanged(uint, uint)), this, SIGNAL(progressChanged(uint, uint)));
}

QMessageService::~QMessageService()
{
}

bool QMessageService::queryMessages(const QMessageFilter &filter, const QMessageSortOrder &sortOrder, uint limit, uint offset)
{
    if (d_ptr->_active) {
        return false;
    }

    d_ptr->_active = true;
    d_ptr->_error = QMessageManager::NoError;

    if (d_ptr->queryMessages(filter, sortOrder, limit, offset)) {
        d_ptr->_state = QMessageService::ActiveState;
        emit stateChanged(d_ptr->_state);
    } else {
        d_ptr->setFinished(false, &QMessageService::stateChanged);
    }

    return d_ptr->_active;
}

bool QMessageService::queryMessages(const QMessageFilter &filter, const QString &body, QMessageDataComparator::MatchFlags matchFlags, const QMessageSortOrder &sortOrder, uint limit, uint offset)
{
    if (d_ptr->_active) {
        return false;
    }

    d_ptr->_active = true;
    d_ptr->_error = QMessageManager::NoError;

    if (d_ptr->queryMessages(filter, body, matchFlags, sortOrder, limit, offset)) {
        d_ptr->_state = QMessageService::ActiveState;
        emit stateChanged(d_ptr->_state);
    } else {
        d_ptr->setFinished(false, &QMessageService::stateChanged);
    }

    return d_ptr->_active;
}

bool QMessageService::countMessages(const QMessageFilter &filter)
{
    if (d_ptr->_active) {
        return false;
    }

    d_ptr->_active = true;
    d_ptr->_error = QMessageManager::NoError;

    if (d_ptr->countMessages(filter)) {
        d_ptr->_state = QMessageService::ActiveState;
        emit stateChanged(d_ptr->_state);
    } else {
        d_ptr->setFinished(false, &QMessageService::stateChanged);
    }

    return d_ptr->_active;
}

bool QMessageService::send(QMessage &message)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

    bool retVal = true;

    d_ptr->_state = QMessageService::ActiveState;
    emit stateChanged(d_ptr->_state);

    // Check message type
    if(message.type() == QMessage::AnyType || message.type() == QMessage::NoType) {
        d_ptr->_error = QMessageManager::ConstraintFailure;
        retVal = false;
    }

    QMessageAccountId accountId = message.parentAccountId();
    if (retVal) {
        // Check account
        if (!accountId.isValid()) {
            accountId = QMessageAccount::defaultAccount(message.type());
            if (!accountId.isValid()) {
                d_ptr->_error = QMessageManager::InvalidId;
                retVal = false;
            }
        }
    }

    if (retVal) {
        // Check account/message type compatibility
        QMessageAccount account(accountId);
        if (!(account.messageTypes() & message.type())) {
            d_ptr->_error = QMessageManager::ConstraintFailure;
            retVal = false;
        }
    }

    if (retVal) {
        // Check recipients
        QMessageAddressList recipients = message.to() + message.bcc() + message.cc();
        if (recipients.isEmpty()) {
            d_ptr->_error = QMessageManager::ConstraintFailure;
            return false;
        }
    }

    QMessage outgoing(message);

    // Set default account if unset
    if (!outgoing.parentAccountId().isValid()) {
        outgoing.setParentAccountId(accountId);
    }

    if (retVal) {
        if (message.type() == QMessage::Sms) {
            retVal = d_ptr->sendSMS(outgoing);
        } else if (message.type() == QMessage::Mms) {
            retVal = d_ptr->sendMMS(outgoing);
        } else if (message.type() == QMessage::Email) {
            retVal = d_ptr->sendEmail(outgoing);
        }
    }

    d_ptr->setFinished(retVal, &QMessageService::stateChanged);
    return retVal;
}

bool QMessageService::compose(const QMessage &message)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

	retVal = d_ptr->compose(message);

    d_ptr->setFinished(retVal, &QMessageService::stateChanged);
    return retVal;
}

bool QMessageService::retrieveHeader(const QMessageId& id)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

	retVal = d_ptr->retrieveHeader(id);

    d_ptr->setFinished(retVal, &QMessageService::stateChanged);
    return retVal;
}

bool QMessageService::retrieveBody(const QMessageId& id)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

	retVal = d_ptr->retrieveBody(id);

    d_ptr->setFinished(retVal, &QMessageService::stateChanged);
    return retVal;
}

bool QMessageService::retrieve(const QMessageId &messageId, const QMessageContentContainerId& id)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

	retVal = d_ptr->retrieve(messageId, id);

    d_ptr->setFinished(retVal, &QMessageService::stateChanged);
    return retVal;
}

bool QMessageService::show(const QMessageId& id)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

    retVal = d_ptr->show(id);

    d_ptr->setFinished(retVal, &QMessageService::stateChanged);
    return retVal;
}

bool QMessageService::exportUpdates(const QMessageAccountId &/*id*/)
{
	//Not supported
	return true;
}

QMessageService::State QMessageService::state() const
{
	return d_ptr->_state;
}

void QMessageService::cancel()
{
}

QMessageManager::Error QMessageService::error() const
{
    return d_ptr->_error;
}

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

#include "qmessageservice.h"
#include "qmessageservice_symbian_p.h"
#include "qmtmengine_symbian_p.h"

QTM_BEGIN_NAMESPACE

QMessageServicePrivate::QMessageServicePrivate(QMessageService* parent)
 : q_ptr(parent),
   _state(QMessageService::InactiveState),
   _active(false)
{
}

QMessageServicePrivate::~QMessageServicePrivate()
{
}

bool QMessageServicePrivate::sendSMS(QMessage &message)
{
	return CMTMEngine::instance()->sendSMS(message);
}

bool QMessageServicePrivate::sendMMS(QMessage &message)
{
	CMTMEngine* mtmEngine = CMTMEngine::instance();
	bool retVal = mtmEngine->storeMMS(message, KMsvGlobalOutBoxIndexEntryId);
	if (retVal){
		mtmEngine->sendMMS();
	}
	return retVal;
}

bool QMessageServicePrivate::sendEmail(QMessage &message)
{
	CMTMEngine* mtmEngine = CMTMEngine::instance();
	bool retVal = mtmEngine->storeEmail(message, KMsvGlobalOutBoxIndexEntryId);
	if (retVal){
		mtmEngine->sendEmail(message);
	}
	return retVal;
}

bool QMessageServicePrivate::show(const QMessageId& id)
{
	return CMTMEngine::instance()->showMessage(id);
}

bool QMessageServicePrivate::compose(const QMessage &message)
{
	return CMTMEngine::instance()->composeMessage(message);
}

bool QMessageServicePrivate::queryMessages(const QMessageFilter &filter, const QMessageSortOrder &sortOrder, uint limit, uint offset) const
{
    return CMTMEngine::instance()->queryMessages((QMessageServicePrivate&)*this, filter, sortOrder, limit, offset);
}

bool QMessageServicePrivate::queryMessages(const QMessageFilter &filter, const QString &body, QMessageDataComparator::MatchFlags matchFlags, const QMessageSortOrder &sortOrder, uint limit, uint offset) const
{
    return CMTMEngine::instance()->queryMessages((QMessageServicePrivate&)*this, filter, body, matchFlags, sortOrder, limit, offset);
}

bool QMessageServicePrivate::countMessages(const QMessageFilter &filter)
{
    return CMTMEngine::instance()->countMessages((QMessageServicePrivate&)*this, filter);
}

bool QMessageServicePrivate::retrieve(const QMessageId &messageId, const QMessageContentContainerId &id)
{
	return CMTMEngine::instance()->retrieve(messageId, id);
}

bool QMessageServicePrivate::retrieveBody(const QMessageId& id)
{
	return CMTMEngine::instance()->retrieveBody(id);
}

bool QMessageServicePrivate::retrieveHeader(const QMessageId& id)
{
	return CMTMEngine::instance()->retrieveHeader(id);
}

void QMessageServicePrivate::setFinished(bool successful)
{
    if (!successful && (_error == QMessageManager::NoError)) {
        // We must report an error of some sort
        _error = QMessageManager::RequestIncomplete;
    }

    _state = QMessageService::FinishedState;
    emit q_ptr->stateChanged(_state);
    _active = false;
}

QMessageService::QMessageService(QObject *parent)
    : QObject(parent),
    d_ptr(new QMessageServicePrivate(this))
{
	connect(d_ptr, SIGNAL(stateChanged(QMessageService::State)), this, SIGNAL(stateChanged(QMessageService::State)));
	connect(d_ptr, SIGNAL(messagesFound(const QMessageIdList&)), this, SIGNAL(messagesFound(const QMessageIdList&)));
    connect(d_ptr, SIGNAL(messagesCounted(int)), this, SIGNAL(messagesCounted(int)));
	connect(d_ptr, SIGNAL(progressChanged(uint, uint)), this, SIGNAL(progressChanged(uint, uint)));
}

QMessageService::~QMessageService()
{
}

bool QMessageService::queryMessages(const QMessageFilter &filter, const QMessageSortOrder &sortOrder, uint limit, uint offset)
{
    if (d_ptr->_active) {
        return false;
    }

    d_ptr->_active = true;
    d_ptr->_error = QMessageManager::NoError;

    if (d_ptr->queryMessages(filter, sortOrder, limit, offset)) {
        d_ptr->_state = QMessageService::ActiveState;
        emit stateChanged(d_ptr->_state);
    } else {
        d_ptr->setFinished(false);
    }

    return d_ptr->_active;
}

bool QMessageService::queryMessages(const QMessageFilter &filter, const QString &body, QMessageDataComparator::MatchFlags matchFlags, const QMessageSortOrder &sortOrder, uint limit, uint offset)
{
    if (d_ptr->_active) {
        return false;
    }

    d_ptr->_active = true;
    d_ptr->_error = QMessageManager::NoError;

    if (d_ptr->queryMessages(filter, body, matchFlags, sortOrder, limit, offset)) {
        d_ptr->_state = QMessageService::ActiveState;
        emit stateChanged(d_ptr->_state);
    } else {
        d_ptr->setFinished(false);
    }

    return d_ptr->_active;
}

bool QMessageService::countMessages(const QMessageFilter &filter)
{
    if (d_ptr->_active) {
        return false;
    }

    d_ptr->_active = true;
    d_ptr->_error = QMessageManager::NoError;

    if (d_ptr->countMessages(filter)) {
        d_ptr->_state = QMessageService::ActiveState;
        emit stateChanged(d_ptr->_state);
    } else {
        d_ptr->setFinished(false);
    }

    return d_ptr->_active;
}

bool QMessageService::send(QMessage &message)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

    bool retVal = true;

    d_ptr->_state = QMessageService::ActiveState;
    emit stateChanged(d_ptr->_state);

    // Check message type
    if(message.type() == QMessage::AnyType || message.type() == QMessage::NoType) {
        d_ptr->_error = QMessageManager::ConstraintFailure;
        retVal = false;
    }

    QMessageAccountId accountId = message.parentAccountId();
    if (retVal) {
        // Check account
        if (!accountId.isValid()) {
            accountId = QMessageAccount::defaultAccount(message.type());
            if (!accountId.isValid()) {
                d_ptr->_error = QMessageManager::InvalidId;
                retVal = false;
            }
        }
    }

    if (retVal) {
        // Check account/message type compatibility
        QMessageAccount account(accountId);
        if (!(account.messageTypes() & message.type())) {
            d_ptr->_error = QMessageManager::ConstraintFailure;
            retVal = false;
        }
    }

    if (retVal) {
        // Check recipients
        QMessageAddressList recipients = message.to() + message.bcc() + message.cc();
        if (recipients.isEmpty()) {
            d_ptr->_error = QMessageManager::ConstraintFailure;
            return false;
        }
    }

    QMessage outgoing(message);

    // Set default account if unset
    if (!outgoing.parentAccountId().isValid()) {
        outgoing.setParentAccountId(accountId);
    }

    if (retVal) {
        if (message.type() == QMessage::Sms) {
            retVal = d_ptr->sendSMS(outgoing);
        } else if (message.type() == QMessage::Mms) {
            retVal = d_ptr->sendMMS(outgoing);
        } else if (message.type() == QMessage::Email) {
            retVal = d_ptr->sendEmail(outgoing);
        }
    }

    d_ptr->setFinished(retVal);
    return retVal;
}

bool QMessageService::compose(const QMessage &message)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

	retVal = d_ptr->compose(message);

    d_ptr->setFinished(retVal);
    return retVal;
}

bool QMessageService::retrieveHeader(const QMessageId& id)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

	retVal = d_ptr->retrieveHeader(id);

    d_ptr->setFinished(retVal);
    return retVal;
}

bool QMessageService::retrieveBody(const QMessageId& id)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

	retVal = d_ptr->retrieveBody(id);

    d_ptr->setFinished(retVal);
    return retVal;
}

bool QMessageService::retrieve(const QMessageId &messageId, const QMessageContentContainerId& id)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

	retVal = d_ptr->retrieve(messageId, id);

    d_ptr->setFinished(retVal);
    return retVal;
}

bool QMessageService::show(const QMessageId& id)
{
	if (d_ptr->_active) {
		return false;
	}

	d_ptr->_active = true;
	d_ptr->_error = QMessageManager::NoError;

	bool retVal = true;
	d_ptr->_state = QMessageService::ActiveState;
	emit stateChanged(d_ptr->_state);

    retVal = d_ptr->show(id);

    d_ptr->setFinished(retVal);
    return retVal;
}

bool QMessageService::exportUpdates(const QMessageAccountId &/*id*/)
{
	//Not supported
	return true;
}

QMessageService::State QMessageService::state() const
{
	return d_ptr->_state;
}

void QMessageService::cancel()
{
}

QMessageManager::Error QMessageService::error() const
{
    return d_ptr->_error;
}

#include "moc_qmessageservice_symbian_p.cpp"
QTM_END_NAMESPACE
<|endoftext|>


<commit_before><commit_msg>Using macro for forward declarations<commit_after><|endoftext|>


<commit_before>/// @file
/// @author  Kresimir Spes
/// @author  Boris Mikic
/// @author  Ivan Vucica
/// @version 3.3
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#ifdef _OPENKODE
#include <KD/kd.h>
#endif

#include <stdio.h>
#ifdef __APPLE__
#include <TargetConditionals.h>
#endif

#include <hltypes/harray.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hlog.h>
#include <hltypes/hplatform.h>
#include <hltypes/hresource.h>
#include <hltypes/hstring.h>

#include "april.h"
#include "RenderSystem.h"
#ifdef _DIRECTX9
#include "DirectX9_RenderSystem.h"
#endif
#ifdef _DIRECTX11
#include "DirectX11_RenderSystem.h"
#endif
#ifdef _OPENGL1
#include "OpenGL1_RenderSystem.h"
#endif
#ifdef _OPENGLES1
#include "OpenGLES1_RenderSystem.h"
#endif
#ifdef _OPENGLES2
#include "OpenGLES2_RenderSystem.h"
#endif
#ifdef _OPENKODE_WINDOW
#include "OpenKODE_Window.h"
#endif
#include "Window.h"
#ifdef _ANDROID
#include "AndroidJNI_Window.h"
#endif
#ifdef _IOS
#include "iOS_Window.h"
#endif
#ifdef _SDL_WINDOW
#include "SDL_Window.h"
#endif
#ifdef _COCOA_WINDOW
#include "Mac_Window.h"
#endif
#ifdef _WIN32_WINDOW
#include "Win32_Window.h"
#endif
#ifdef _WINRT_WINDOW
#include "WinRT_Window.h"
#endif
#ifdef _EGL
#include "egl.h"
#endif

#ifdef _WIN32
	#ifdef _DIRECTX9
		#define RS_INTERNAL_DEFAULT RS_DIRECTX9
	#elif defined(_DIRECTX11)
		#define RS_INTERNAL_DEFAULT RS_DIRECTX11
	#elif defined(_OPENGL1)
		#define RS_INTERNAL_DEFAULT RS_OPENGL1
	#elif defined(_OPENGLES1)
		#define RS_INTERNAL_DEFAULT RS_OPENGLES1
	#elif defined(_OPENGLES2)
		#define RS_INTERNAL_DEFAULT RS_OPENGLES2
	#endif
	#ifdef _OPENKODE_WINDOW
		#define WS_INTERNAL_DEFAULT WS_OPENKODE
	#elif !defined(_WINRT)
		#define WS_INTERNAL_DEFAULT WS_WIN32
	#else
		#define WS_INTERNAL_DEFAULT WS_WINRT
	#endif
#elif defined(__APPLE__)
	#if TARGET_OS_IPHONE
		#ifdef _OPENGLES2
			#define RS_INTERNAL_DEFAULT RS_OPENGLES2
		#elif defined(_OPENGLES1)
			#define RS_INTERNAL_DEFAULT RS_OPENGLES1
		#endif
		#ifdef _OPENKODE_WINDOW
			#define WS_INTERNAL_DEFAULT WS_OPENKODE
		#else
			#define WS_INTERNAL_DEFAULT WS_IOS
		#endif
	#else
		#define RS_INTERNAL_DEFAULT RS_OPENGL1
		#ifdef _OPENKODE_WINDOW
			#define WS_INTERNAL_DEFAULT WS_OPENKODE
		#elif defined(_SDL_WINDOW)
			#define WS_INTERNAL_DEFAULT WS_SDL
		#else
			#define WS_INTERNAL_DEFAULT WS_MAC
		#endif
	#endif
#elif defined(_UNIX)
	#define RS_INTERNAL_DEFAULT RS_OPENGL1
	#ifdef _OPENKODE_WINDOW
		#define WS_INTERNAL_DEFAULT WS_OPENKODE
	#else
		#define WS_INTERNAL_DEFAULT WS_SDL
	#endif
#elif defined(_ANDROID)
	#ifdef _OPENGLES1
		#define RS_INTERNAL_DEFAULT RS_OPENGLES1
	#elif defined(_OPENGLES2)
		#define RS_INTERNAL_DEFAULT RS_OPENGLES2
	#endif
	#ifdef _OPENKODE_WINDOW
		#define WS_INTERNAL_DEFAULT WS_OPENKODE
	#elif defined(_ANDROIDJNI_WINDOW)
		#define WS_INTERNAL_DEFAULT WS_ANDROIDJNI
	#endif
#endif

#ifndef RS_INTERNAL_DEFAULT
	#define RS_INTERNAL_DEFAULT RS_DEFAULT
#endif
#ifndef WS_INTERNAL_DEFAULT
	#define WS_INTERNAL_DEFAULT WS_DEFAULT
#endif

#ifdef _WIN32
	#ifndef _WINRT
		#define APRIL_PLATFORM_NAME "Win32"
	#elif !defined(_WINP8)
		#define APRIL_PLATFORM_NAME "WinRT"
	#else
		#define APRIL_PLATFORM_NAME "WinP8"
	#endif
#elif defined(_ANDROID)
	#define APRIL_PLATFORM_NAME "Android"
#elif defined(__APPLE__)
	#if TARGET_OS_IPHONE
		#define APRIL_PLATFORM_NAME "iOS"
	#else
		#define APRIL_PLATFORM_NAME "Mac OS X"
	#endif
#elif defined(_UNIX)
	#define APRIL_PLATFORM_NAME "Unix"
#endif
#ifndef APRIL_PLATFORM_NAME
#define APRIL_PLATFORM_NAME "Unknown"
#endif

#ifdef _ARM
	#define APRIL_PLATFORM_ARCHITECTURE "ARM"
#elif defined(_X64)
	#define APRIL_PLATFORM_ARCHITECTURE "x64"
#endif
#ifndef APRIL_PLATFORM_ARCHITECTURE
	#define APRIL_PLATFORM_ARCHITECTURE "x86"
#endif

namespace april
{
	hstr logTag = "april";

	static harray<hstr> extensions;

	void _startInit()
	{
		hlog::writef(april::logTag, "Initializing APRIL. (Platform: %s %s)", APRIL_PLATFORM_NAME, APRIL_PLATFORM_ARCHITECTURE);
		extensions += ".jpt";
		extensions += ".png";
		extensions += ".jpg";
#if TARGET_OS_IPHONE
		extensions += ".pvr";
#endif
#ifdef _EGL
		april::egl = new EglData();
#endif
	}

	void _finishInit()
	{
		hlog::writef(april::logTag, "Using: %s, %s", april::rendersys->getName().c_str(), april::window->getName().c_str());
	}

	void _createRenderSystem(RenderSystemType renderSystemType)
	{
		// creating the rendersystem
		RenderSystemType renderSystem = renderSystemType;
		if (renderSystem == RS_DEFAULT)
		{
			renderSystem = RS_INTERNAL_DEFAULT;
		}
#ifdef _DIRECTX9
		if (april::rendersys == NULL && renderSystem == RS_DIRECTX9)
		{
			april::rendersys = new DirectX9_RenderSystem();
		}
#endif
#ifdef _DIRECTX11
		if (april::rendersys == NULL && renderSystem == RS_DIRECTX11)
		{
			april::rendersys = new DirectX11_RenderSystem();
		}
#endif
#ifdef _OPENGL1
		if (april::rendersys == NULL && renderSystem == RS_OPENGL1)
		{
			april::rendersys = new OpenGL1_RenderSystem();
		}
#endif
#ifdef _OPENGLES1
		if (april::rendersys == NULL && renderSystem == RS_OPENGLES1)
		{
			april::rendersys = new OpenGLES1_RenderSystem();
		}
#endif
#ifdef _OPENGLES2
		if (april::rendersys == NULL && renderSystem == RS_OPENGLES2)
		{
			april::rendersys = new OpenGLES2_RenderSystem();
		}
#endif
		if (april::rendersys == NULL)
		{
			throw hl_exception("Could not create given rendersystem!");
		}
	}

	void _createWindowSystem(WindowType windowType)
	{
		// creating the windowsystem
		WindowType window = windowType;
		if (window == WS_DEFAULT)
		{
			window = WS_INTERNAL_DEFAULT;
		}
#ifdef _WIN32_WINDOW
		if (april::window == NULL && window == WS_WIN32)
		{
			april::window = new Win32_Window();
		}
#endif
#ifdef _WINRT_WINDOW
		if (april::window == NULL && window == WS_WINRT)
		{
			april::window = new WinRT_Window();
		}
#endif
#ifdef _SDL_WINDOW
		if (april::window == NULL && window == WS_SDL)
		{
			april::window = new SDL_Window();
		}
#endif
#ifdef _COCOA_WINDOW
		if (april::window == NULL && window == WS_MAC)
		{
			april::window = new Mac_Window();
		}
#endif
#ifdef _IOS
		if (april::window == NULL && window == WS_IOS)
		{
			april::window = new iOS_Window();
		}
#endif
#ifdef _ANDROIDJNI_WINDOW
		if (april::window == NULL && window == WS_ANDROIDJNI)
		{
			april::window = new AndroidJNI_Window();
		}
#endif
#ifdef _OPENKODE_WINDOW
		if (april::window == NULL && window == WS_OPENKODE)
		{
			april::window = new OpenKODE_Window();
		}
#endif
		if (april::window == NULL)
		{
			throw hl_exception("Could not create given windowsystem!");
		}
	}

	void init(RenderSystemType renderSystemType, WindowType windowType)
	{
		_startInit();
		_createRenderSystem(renderSystemType);
		_createWindowSystem(windowType);
		_finishInit();
	}

	void init(RenderSystem* customRenderSystem, WindowType windowType)
	{
		_startInit();
		april::rendersys = customRenderSystem;
		_createWindowSystem(windowType);
		_finishInit();
	}

	void init(RenderSystemType renderSystemType, Window* customWindow)
	{
		_startInit();
		_createRenderSystem(renderSystemType);
		april::window = customWindow;
		_finishInit();
	}

	void init(RenderSystem* customRenderSystem, Window* customWindow)
	{
		_startInit();
		april::rendersys = customRenderSystem;
		april::window = customWindow;
		_finishInit();
	}

	void init(RenderSystemType renderSystemType, WindowType windowType, RenderSystem::Options renderSystemOptions,
		int w, int h, bool fullscreen, chstr title, Window::Options windowOptions)
	{
		init(renderSystemType, windowType);
		createRenderSystem(renderSystemOptions);
		createWindow(w, h, fullscreen, title, windowOptions);
	}

	void init(RenderSystem* customRenderSystem, WindowType windowType, RenderSystem::Options renderSystemOptions,
		int w, int h, bool fullscreen, chstr title, Window::Options windowOptions)
	{
		init(customRenderSystem, windowType);
		createRenderSystem(renderSystemOptions);
		createWindow(w, h, fullscreen, title, windowOptions);
	}

	void init(RenderSystemType renderSystemType, Window* customWindow, RenderSystem::Options renderSystemOptions,
		int w, int h, bool fullscreen, chstr title, Window::Options windowOptions)
	{
		init(renderSystemType, customWindow);
		createRenderSystem(renderSystemOptions);
		createWindow(w, h, fullscreen, title, windowOptions);
	}

	void init(RenderSystem* customRenderSystem, Window* customWindow, RenderSystem::Options renderSystemOptions,
		int w, int h, bool fullscreen, chstr title, Window::Options windowOptions)
	{
		init(customRenderSystem, customWindow);
		createRenderSystem(renderSystemOptions);
		createWindow(w, h, fullscreen, title, windowOptions);
	}

	void createRenderSystem(RenderSystem::Options options)
	{
		april::rendersys->create(options);
	}

	void createWindow(int w, int h, bool fullscreen, chstr title, Window::Options options)
	{
		april::window->create(w, h, fullscreen, title, options);
		april::rendersys->assignWindow(april::window);
	}

	void destroy()
	{
		if (april::rendersys != NULL || april::window != NULL)
		{
			hlog::write(april::logTag, "Destroying APRIL.");
		}
		if (april::window != NULL)
		{
			april::window->unassign();
		}
		if (april::window != NULL && april::rendersys != NULL)
		{
			april::rendersys->destroy();
			april::window->destroy();
		}
		if (april::window != NULL)
		{
			delete april::window;
			april::window = NULL;
		}
		if (april::rendersys != NULL)
		{
			delete april::rendersys;
			april::rendersys = NULL;
		}
#ifdef _EGL
		if (april::egl != NULL)
		{
			delete april::egl;
			april::egl = NULL;
		}
#endif
	}

	void addTextureExtension(chstr extension)
	{
		extensions += extension;
	}

	harray<hstr> getTextureExtensions()
	{
		return extensions;
	}

	void setTextureExtensions(const harray<hstr>& exts)
	{
		extensions = exts;
	}

}
<commit_msg><commit_after>/// @file
/// @author  Kresimir Spes
/// @author  Boris Mikic
/// @author  Ivan Vucica
/// @version 3.3
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#pragma message("WARNING! This version of the library is deprecated! Please use the one from: http://libapril.googlecode.com")

#ifdef _OPENKODE
#include <KD/kd.h>
#endif

#include <stdio.h>
#ifdef __APPLE__
#include <TargetConditionals.h>
#endif

#include <hltypes/harray.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hlog.h>
#include <hltypes/hplatform.h>
#include <hltypes/hresource.h>
#include <hltypes/hstring.h>

#include "april.h"
#include "RenderSystem.h"
#ifdef _DIRECTX9
#include "DirectX9_RenderSystem.h"
#endif
#ifdef _DIRECTX11
#include "DirectX11_RenderSystem.h"
#endif
#ifdef _OPENGL1
#include "OpenGL1_RenderSystem.h"
#endif
#ifdef _OPENGLES1
#include "OpenGLES1_RenderSystem.h"
#endif
#ifdef _OPENGLES2
#include "OpenGLES2_RenderSystem.h"
#endif
#ifdef _OPENKODE_WINDOW
#include "OpenKODE_Window.h"
#endif
#include "Window.h"
#ifdef _ANDROID
#include "AndroidJNI_Window.h"
#endif
#ifdef _IOS
#include "iOS_Window.h"
#endif
#ifdef _SDL_WINDOW
#include "SDL_Window.h"
#endif
#ifdef _COCOA_WINDOW
#include "Mac_Window.h"
#endif
#ifdef _WIN32_WINDOW
#include "Win32_Window.h"
#endif
#ifdef _WINRT_WINDOW
#include "WinRT_Window.h"
#endif
#ifdef _EGL
#include "egl.h"
#endif

#ifdef _WIN32
	#ifdef _DIRECTX9
		#define RS_INTERNAL_DEFAULT RS_DIRECTX9
	#elif defined(_DIRECTX11)
		#define RS_INTERNAL_DEFAULT RS_DIRECTX11
	#elif defined(_OPENGL1)
		#define RS_INTERNAL_DEFAULT RS_OPENGL1
	#elif defined(_OPENGLES1)
		#define RS_INTERNAL_DEFAULT RS_OPENGLES1
	#elif defined(_OPENGLES2)
		#define RS_INTERNAL_DEFAULT RS_OPENGLES2
	#endif
	#ifdef _OPENKODE_WINDOW
		#define WS_INTERNAL_DEFAULT WS_OPENKODE
	#elif !defined(_WINRT)
		#define WS_INTERNAL_DEFAULT WS_WIN32
	#else
		#define WS_INTERNAL_DEFAULT WS_WINRT
	#endif
#elif defined(__APPLE__)
	#if TARGET_OS_IPHONE
		#ifdef _OPENGLES2
			#define RS_INTERNAL_DEFAULT RS_OPENGLES2
		#elif defined(_OPENGLES1)
			#define RS_INTERNAL_DEFAULT RS_OPENGLES1
		#endif
		#ifdef _OPENKODE_WINDOW
			#define WS_INTERNAL_DEFAULT WS_OPENKODE
		#else
			#define WS_INTERNAL_DEFAULT WS_IOS
		#endif
	#else
		#define RS_INTERNAL_DEFAULT RS_OPENGL1
		#ifdef _OPENKODE_WINDOW
			#define WS_INTERNAL_DEFAULT WS_OPENKODE
		#elif defined(_SDL_WINDOW)
			#define WS_INTERNAL_DEFAULT WS_SDL
		#else
			#define WS_INTERNAL_DEFAULT WS_MAC
		#endif
	#endif
#elif defined(_UNIX)
	#define RS_INTERNAL_DEFAULT RS_OPENGL1
	#ifdef _OPENKODE_WINDOW
		#define WS_INTERNAL_DEFAULT WS_OPENKODE
	#else
		#define WS_INTERNAL_DEFAULT WS_SDL
	#endif
#elif defined(_ANDROID)
	#ifdef _OPENGLES1
		#define RS_INTERNAL_DEFAULT RS_OPENGLES1
	#elif defined(_OPENGLES2)
		#define RS_INTERNAL_DEFAULT RS_OPENGLES2
	#endif
	#ifdef _OPENKODE_WINDOW
		#define WS_INTERNAL_DEFAULT WS_OPENKODE
	#elif defined(_ANDROIDJNI_WINDOW)
		#define WS_INTERNAL_DEFAULT WS_ANDROIDJNI
	#endif
#endif

#ifndef RS_INTERNAL_DEFAULT
	#define RS_INTERNAL_DEFAULT RS_DEFAULT
#endif
#ifndef WS_INTERNAL_DEFAULT
	#define WS_INTERNAL_DEFAULT WS_DEFAULT
#endif

#ifdef _WIN32
	#ifndef _WINRT
		#define APRIL_PLATFORM_NAME "Win32"
	#elif !defined(_WINP8)
		#define APRIL_PLATFORM_NAME "WinRT"
	#else
		#define APRIL_PLATFORM_NAME "WinP8"
	#endif
#elif defined(_ANDROID)
	#define APRIL_PLATFORM_NAME "Android"
#elif defined(__APPLE__)
	#if TARGET_OS_IPHONE
		#define APRIL_PLATFORM_NAME "iOS"
	#else
		#define APRIL_PLATFORM_NAME "Mac OS X"
	#endif
#elif defined(_UNIX)
	#define APRIL_PLATFORM_NAME "Unix"
#endif
#ifndef APRIL_PLATFORM_NAME
#define APRIL_PLATFORM_NAME "Unknown"
#endif

#ifdef _ARM
	#define APRIL_PLATFORM_ARCHITECTURE "ARM"
#elif defined(_X64)
	#define APRIL_PLATFORM_ARCHITECTURE "x64"
#endif
#ifndef APRIL_PLATFORM_ARCHITECTURE
	#define APRIL_PLATFORM_ARCHITECTURE "x86"
#endif

namespace april
{
	hstr logTag = "april";

	static harray<hstr> extensions;

	void _startInit()
	{
		hlog::writef(april::logTag, "Initializing APRIL. (Platform: %s %s)", APRIL_PLATFORM_NAME, APRIL_PLATFORM_ARCHITECTURE);
		extensions += ".jpt";
		extensions += ".png";
		extensions += ".jpg";
#if TARGET_OS_IPHONE
		extensions += ".pvr";
#endif
#ifdef _EGL
		april::egl = new EglData();
#endif
	}

	void _finishInit()
	{
		hlog::writef(april::logTag, "Using: %s, %s", april::rendersys->getName().c_str(), april::window->getName().c_str());
	}

	void _createRenderSystem(RenderSystemType renderSystemType)
	{
		// creating the rendersystem
		RenderSystemType renderSystem = renderSystemType;
		if (renderSystem == RS_DEFAULT)
		{
			renderSystem = RS_INTERNAL_DEFAULT;
		}
#ifdef _DIRECTX9
		if (april::rendersys == NULL && renderSystem == RS_DIRECTX9)
		{
			april::rendersys = new DirectX9_RenderSystem();
		}
#endif
#ifdef _DIRECTX11
		if (april::rendersys == NULL && renderSystem == RS_DIRECTX11)
		{
			april::rendersys = new DirectX11_RenderSystem();
		}
#endif
#ifdef _OPENGL1
		if (april::rendersys == NULL && renderSystem == RS_OPENGL1)
		{
			april::rendersys = new OpenGL1_RenderSystem();
		}
#endif
#ifdef _OPENGLES1
		if (april::rendersys == NULL && renderSystem == RS_OPENGLES1)
		{
			april::rendersys = new OpenGLES1_RenderSystem();
		}
#endif
#ifdef _OPENGLES2
		if (april::rendersys == NULL && renderSystem == RS_OPENGLES2)
		{
			april::rendersys = new OpenGLES2_RenderSystem();
		}
#endif
		if (april::rendersys == NULL)
		{
			throw hl_exception("Could not create given rendersystem!");
		}
	}

	void _createWindowSystem(WindowType windowType)
	{
		// creating the windowsystem
		WindowType window = windowType;
		if (window == WS_DEFAULT)
		{
			window = WS_INTERNAL_DEFAULT;
		}
#ifdef _WIN32_WINDOW
		if (april::window == NULL && window == WS_WIN32)
		{
			april::window = new Win32_Window();
		}
#endif
#ifdef _WINRT_WINDOW
		if (april::window == NULL && window == WS_WINRT)
		{
			april::window = new WinRT_Window();
		}
#endif
#ifdef _SDL_WINDOW
		if (april::window == NULL && window == WS_SDL)
		{
			april::window = new SDL_Window();
		}
#endif
#ifdef _COCOA_WINDOW
		if (april::window == NULL && window == WS_MAC)
		{
			april::window = new Mac_Window();
		}
#endif
#ifdef _IOS
		if (april::window == NULL && window == WS_IOS)
		{
			april::window = new iOS_Window();
		}
#endif
#ifdef _ANDROIDJNI_WINDOW
		if (april::window == NULL && window == WS_ANDROIDJNI)
		{
			april::window = new AndroidJNI_Window();
		}
#endif
#ifdef _OPENKODE_WINDOW
		if (april::window == NULL && window == WS_OPENKODE)
		{
			april::window = new OpenKODE_Window();
		}
#endif
		if (april::window == NULL)
		{
			throw hl_exception("Could not create given windowsystem!");
		}
	}

	void init(RenderSystemType renderSystemType, WindowType windowType)
	{
		_startInit();
		_createRenderSystem(renderSystemType);
		_createWindowSystem(windowType);
		_finishInit();
	}

	void init(RenderSystem* customRenderSystem, WindowType windowType)
	{
		_startInit();
		april::rendersys = customRenderSystem;
		_createWindowSystem(windowType);
		_finishInit();
	}

	void init(RenderSystemType renderSystemType, Window* customWindow)
	{
		_startInit();
		_createRenderSystem(renderSystemType);
		april::window = customWindow;
		_finishInit();
	}

	void init(RenderSystem* customRenderSystem, Window* customWindow)
	{
		_startInit();
		april::rendersys = customRenderSystem;
		april::window = customWindow;
		_finishInit();
	}

	void init(RenderSystemType renderSystemType, WindowType windowType, RenderSystem::Options renderSystemOptions,
		int w, int h, bool fullscreen, chstr title, Window::Options windowOptions)
	{
		init(renderSystemType, windowType);
		createRenderSystem(renderSystemOptions);
		createWindow(w, h, fullscreen, title, windowOptions);
	}

	void init(RenderSystem* customRenderSystem, WindowType windowType, RenderSystem::Options renderSystemOptions,
		int w, int h, bool fullscreen, chstr title, Window::Options windowOptions)
	{
		init(customRenderSystem, windowType);
		createRenderSystem(renderSystemOptions);
		createWindow(w, h, fullscreen, title, windowOptions);
	}

	void init(RenderSystemType renderSystemType, Window* customWindow, RenderSystem::Options renderSystemOptions,
		int w, int h, bool fullscreen, chstr title, Window::Options windowOptions)
	{
		init(renderSystemType, customWindow);
		createRenderSystem(renderSystemOptions);
		createWindow(w, h, fullscreen, title, windowOptions);
	}

	void init(RenderSystem* customRenderSystem, Window* customWindow, RenderSystem::Options renderSystemOptions,
		int w, int h, bool fullscreen, chstr title, Window::Options windowOptions)
	{
		init(customRenderSystem, customWindow);
		createRenderSystem(renderSystemOptions);
		createWindow(w, h, fullscreen, title, windowOptions);
	}

	void createRenderSystem(RenderSystem::Options options)
	{
		april::rendersys->create(options);
	}

	void createWindow(int w, int h, bool fullscreen, chstr title, Window::Options options)
	{
		april::window->create(w, h, fullscreen, title, options);
		april::rendersys->assignWindow(april::window);
	}

	void destroy()
	{
		if (april::rendersys != NULL || april::window != NULL)
		{
			hlog::write(april::logTag, "Destroying APRIL.");
		}
		if (april::window != NULL)
		{
			april::window->unassign();
		}
		if (april::window != NULL && april::rendersys != NULL)
		{
			april::rendersys->destroy();
			april::window->destroy();
		}
		if (april::window != NULL)
		{
			delete april::window;
			april::window = NULL;
		}
		if (april::rendersys != NULL)
		{
			delete april::rendersys;
			april::rendersys = NULL;
		}
#ifdef _EGL
		if (april::egl != NULL)
		{
			delete april::egl;
			april::egl = NULL;
		}
#endif
	}

	void addTextureExtension(chstr extension)
	{
		extensions += extension;
	}

	harray<hstr> getTextureExtensions()
	{
		return extensions;
	}

	void setTextureExtensions(const harray<hstr>& exts)
	{
		extensions = exts;
	}

}
<|endoftext|>


<commit_before>/*
*  Copyright 2016 Ivan Ryabov
*
*  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.
*/
/*******************************************************************************
 * libSolace
 *	@file		array.cpp
 *	@author		$LastChangedBy: soultaker $
 *	@date		$LastChangedDate$
 *	@brief		Helper functions for fixed size arrays
 *	ID:			$Id$
 ******************************************************************************/
#include "solace/array.hpp"

#include "solace/exception.hpp"

using namespace Solace;

const HeapArrayDisposer HeapArrayDisposer::instance = HeapArrayDisposer();

// Utility class that assists in constructing or destroying elements of an array, where the
// constructor or destructor could throw exceptions.  In case of an exception,
// ExceptionSafeArrayUtil's destructor will call destructors on all elements that have been
// constructed but not destroyed.  Remember that destructors that throw exceptions are required
// to use UnwindDetector to detect unwind and avoid exceptions in this case.  Therefore, no more
// than one exception will be thrown (and the program will not terminate).
class ExceptionSafeArrayUtil {
public:

    inline ~ExceptionSafeArrayUtil() noexcept(false) {
        if (_constructedElementCount > 0) destroyAll();
    }

    inline ExceptionSafeArrayUtil(void* ptr, size_t elementSize, size_t constructedElementCount,
                                void (*destoyer)(void*)) noexcept
        : _pos(reinterpret_cast<byte*>(ptr) + elementSize * constructedElementCount)
        , _elementSize(elementSize)
        , _constructedElementCount(constructedElementCount)
        , _destroyElement(destoyer)
    {}

    ExceptionSafeArrayUtil(ExceptionSafeArrayUtil const&) = delete;
    ExceptionSafeArrayUtil& operator= (ExceptionSafeArrayUtil const& ) = delete;

    // Construct the given number of elements.
    void construct(size_t count, void (*constructElement)(void*)) {
        while (count > 0) {
            constructElement(_pos);
            _pos += _elementSize;
            ++_constructedElementCount;
            --count;
        }
    }

    // Destroy all elements.  Call this immediately before ExceptionSafeArrayUtil goes out-of-scope
    // to ensure that one element throwing an exception does not prevent the others from being
    // destroyed.
    void destroyAll() {
        while (_constructedElementCount > 0) {
            _pos -= _elementSize;
            --_constructedElementCount;
            _destroyElement(_pos);
        }
    }

    // Prevent ExceptionSafeArrayUtil's destructor from destroying the constructed elements.
    // Call this after you've successfully finished constructing.
    constexpr void release() noexcept { _constructedElementCount = 0; }

private:

    byte*       _pos;
    size_t      _elementSize;
    size_t      _constructedElementCount;
    void        (*_destroyElement)(void*);
};

struct AutoDeleter {
    void* ptr;

    inline ~AutoDeleter() { operator delete(ptr); }
    constexpr AutoDeleter(void* pos) noexcept: ptr(pos) {}
    constexpr void* release() noexcept { void* result = ptr; ptr = nullptr; return result; }
};

void*
HeapArrayDisposer::allocateImpl(size_t elementSize, size_type elementCount, size_type capacity,
                                      void (*constructElement)(void*),
                                      void (*destroyElement)(void*)) {

    // NOTE: Allocate memory for the array storage
    AutoDeleter result(operator new(elementSize * capacity));

    if (constructElement == nullptr) {
        // Nothing to do.
    } else if (destroyElement == nullptr) {
        byte* pos = reinterpret_cast<byte*>(result.ptr);
        while (elementCount > 0) {
            constructElement(pos);
            pos += elementSize;
            --elementCount;
        }
    } else {
        ExceptionSafeArrayUtil guard(result.ptr, elementSize, 0, destroyElement);
        guard.construct(elementCount, constructElement);
        guard.release();
    }

    return result.release();
}

void
HeapArrayDisposer::disposeImpl(void* firstElement, size_t elementSize, size_type elementCount,
    void (*destroyElement)(void*)) const {
    // Note that capacity is ignored since operator delete() doesn't care about it.
    AutoDeleter deleter(firstElement);

    if (destroyElement != nullptr) {
        ExceptionSafeArrayUtil guard(firstElement, elementSize, elementCount, destroyElement);
        guard.destroyAll();
    }
}
<commit_msg>Fixed gcc6 compilation error: handling of constexpr<commit_after>/*
*  Copyright 2016 Ivan Ryabov
*
*  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.
*/
/*******************************************************************************
 * libSolace
 *	@file		array.cpp
 *	@author		$LastChangedBy: soultaker $
 *	@date		$LastChangedDate$
 *	@brief		Helper functions for fixed size arrays
 *	ID:			$Id$
 ******************************************************************************/
#include "solace/array.hpp"

#include "solace/exception.hpp"

using namespace Solace;

const HeapArrayDisposer HeapArrayDisposer::instance = HeapArrayDisposer();

// Utility class that assists in constructing or destroying elements of an array, where the
// constructor or destructor could throw exceptions.  In case of an exception,
// ExceptionSafeArrayUtil's destructor will call destructors on all elements that have been
// constructed but not destroyed.  Remember that destructors that throw exceptions are required
// to use UnwindDetector to detect unwind and avoid exceptions in this case.  Therefore, no more
// than one exception will be thrown (and the program will not terminate).
class ExceptionSafeArrayUtil {
public:

    inline ~ExceptionSafeArrayUtil() noexcept(false) {
        if (_constructedElementCount > 0) destroyAll();
    }

    inline ExceptionSafeArrayUtil(void* ptr, size_t elementSize, size_t constructedElementCount,
                                void (*destoyer)(void*)) noexcept
        : _pos(reinterpret_cast<byte*>(ptr) + elementSize * constructedElementCount)
        , _elementSize(elementSize)
        , _constructedElementCount(constructedElementCount)
        , _destroyElement(destoyer)
    {}

    ExceptionSafeArrayUtil(ExceptionSafeArrayUtil const&) = delete;
    ExceptionSafeArrayUtil& operator= (ExceptionSafeArrayUtil const& ) = delete;

    // Construct the given number of elements.
    void construct(size_t count, void (*constructElement)(void*)) {
        while (count > 0) {
            constructElement(_pos);
            _pos += _elementSize;
            ++_constructedElementCount;
            --count;
        }
    }

    // Destroy all elements.  Call this immediately before ExceptionSafeArrayUtil goes out-of-scope
    // to ensure that one element throwing an exception does not prevent the others from being
    // destroyed.
    void destroyAll() {
        while (_constructedElementCount > 0) {
            _pos -= _elementSize;
            --_constructedElementCount;
            _destroyElement(_pos);
        }
    }

    // Prevent ExceptionSafeArrayUtil's destructor from destroying the constructed elements.
    // Call this after you've successfully finished constructing.
    void release() noexcept { _constructedElementCount = 0; }

private:

    byte*       _pos;
    size_t      _elementSize;
    size_t      _constructedElementCount;
    void        (*_destroyElement)(void*);
};

struct AutoDeleter {
    void* ptr;

    inline ~AutoDeleter() { operator delete(ptr); }
    constexpr AutoDeleter(void* pos) noexcept: ptr(pos) {}
    void* release() noexcept { void* result = ptr; ptr = nullptr; return result; }
};

void*
HeapArrayDisposer::allocateImpl(size_t elementSize, size_type elementCount, size_type capacity,
                                      void (*constructElement)(void*),
                                      void (*destroyElement)(void*)) {

    // NOTE: Allocate memory for the array storage
    AutoDeleter result(operator new(elementSize * capacity));

    if (constructElement == nullptr) {
        // Nothing to do.
    } else if (destroyElement == nullptr) {
        byte* pos = reinterpret_cast<byte*>(result.ptr);
        while (elementCount > 0) {
            constructElement(pos);
            pos += elementSize;
            --elementCount;
        }
    } else {
        ExceptionSafeArrayUtil guard(result.ptr, elementSize, 0, destroyElement);
        guard.construct(elementCount, constructElement);
        guard.release();
    }

    return result.release();
}

void
HeapArrayDisposer::disposeImpl(void* firstElement, size_t elementSize, size_type elementCount,
    void (*destroyElement)(void*)) const {
    // Note that capacity is ignored since operator delete() doesn't care about it.
    AutoDeleter deleter(firstElement);

    if (destroyElement != nullptr) {
        ExceptionSafeArrayUtil guard(firstElement, elementSize, elementCount, destroyElement);
        guard.destroyAll();
    }
}
<|endoftext|>