<commit_before>/*
 *
 * Copyright 2018 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h"

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include "src/core/lib/slice/slice_internal.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"

/* Main struct for alts_grpc_integrity_only_record_protocol.  */
typedef struct alts_grpc_integrity_only_record_protocol {
  alts_grpc_record_protocol base;
  bool enable_extra_copy;
  grpc_slice_buffer data_sb;
  unsigned char* tag_buf;
} alts_grpc_integrity_only_record_protocol;

/* --- alts_grpc_record_protocol methods implementation. --- */

static tsi_result alts_grpc_integrity_only_protect(
    alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices,
    grpc_slice_buffer* protected_slices) {
  /* Input sanity check.  */
  if (rp == nullptr || unprotected_slices == nullptr ||
      protected_slices == nullptr) {
    gpr_log(GPR_ERROR,
            "Invalid nullptr arguments to alts_grpc_record_protocol protect.");
    return TSI_INVALID_ARGUMENT;
  }
  alts_grpc_integrity_only_record_protocol* integrity_only_record_protocol =
      reinterpret_cast<alts_grpc_integrity_only_record_protocol*>(rp);
  /* Allocates memory for header and tag slices.  */
  grpc_slice header_slice = GRPC_SLICE_MALLOC(rp->header_length);
  grpc_slice tag_slice = GRPC_SLICE_MALLOC(rp->tag_length);
  /* Calls alts_iovec_record_protocol protect.  */
  char* error_details = nullptr;
  iovec_t header_iovec = {GRPC_SLICE_START_PTR(header_slice),
                          GRPC_SLICE_LENGTH(header_slice)};
  iovec_t tag_iovec = {GRPC_SLICE_START_PTR(tag_slice),
                       GRPC_SLICE_LENGTH(tag_slice)};
  alts_grpc_record_protocol_convert_slice_buffer_to_iovec(rp,
                                                          unprotected_slices);
  grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
      rp->iovec_rp, rp->iovec_buf, unprotected_slices->count, header_iovec,
      tag_iovec, &error_details);
  if (status != GRPC_STATUS_OK) {
    gpr_log(GPR_ERROR, "Failed to protect, %s", error_details);
    gpr_free(error_details);
    return TSI_INTERNAL_ERROR;
  }
  /* Appends result to protected_slices.  */
  grpc_slice_buffer_add(protected_slices, header_slice);
  if (integrity_only_record_protocol->enable_extra_copy) {
    /* If extra copy mode is enabled, makes a copy of unprotected_slices.  */
    for (size_t i = 0; i < unprotected_slices->count; i++) {
      grpc_slice_buffer_add(protected_slices,
                            grpc_slice_dup(unprotected_slices->slices[i]));
    }
    grpc_slice_buffer_reset_and_unref_internal(unprotected_slices);
  } else {
    grpc_slice_buffer_move_into(unprotected_slices, protected_slices);
  }
  grpc_slice_buffer_add(protected_slices, tag_slice);
  return TSI_OK;
}

static tsi_result alts_grpc_integrity_only_unprotect(
    alts_grpc_record_protocol* rp, grpc_slice_buffer* protected_slices,
    grpc_slice_buffer* unprotected_slices) {
  /* Input sanity check.  */
  if (rp == nullptr || protected_slices == nullptr ||
      unprotected_slices == nullptr) {
    gpr_log(
        GPR_ERROR,
        "Invalid nullptr arguments to alts_grpc_record_protocol unprotect.");
    return TSI_INVALID_ARGUMENT;
  }
  if (protected_slices->length < rp->header_length + rp->tag_length) {
    gpr_log(GPR_ERROR, "Protected slices do not have sufficient data.");
    return TSI_INVALID_ARGUMENT;
  }
  /* In this method, rp points to alts_grpc_record_protocol struct
   * and integrity_only_record_protocol points to
   * alts_grpc_integrity_only_record_protocol struct.  */
  alts_grpc_integrity_only_record_protocol* integrity_only_record_protocol =
      reinterpret_cast<alts_grpc_integrity_only_record_protocol*>(rp);
  /* Strips frame header from protected slices.  */
  grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
  grpc_slice_buffer_move_first(protected_slices, rp->header_length,
                               &rp->header_sb);
  GPR_ASSERT(rp->header_sb.length == rp->header_length);
  iovec_t header_iovec = alts_grpc_record_protocol_get_header_iovec(rp);
  /* Moves protected slices data to data_sb and leaves the remaining tag.  */
  grpc_slice_buffer_reset_and_unref_internal(
      &integrity_only_record_protocol->data_sb);
  grpc_slice_buffer_move_first(protected_slices,
                               protected_slices->length - rp->tag_length,
                               &integrity_only_record_protocol->data_sb);
  GPR_ASSERT(protected_slices->length == rp->tag_length);
  iovec_t tag_iovec = {nullptr, rp->tag_length};
  if (protected_slices->count == 1) {
    tag_iovec.iov_base = GRPC_SLICE_START_PTR(protected_slices->slices[0]);
  } else {
    /* Frame tag is in multiple slices, copies the tag bytes from slice
     * buffer to a single flat buffer.  */
    alts_grpc_record_protocol_copy_slice_buffer(
        protected_slices, integrity_only_record_protocol->tag_buf);
    tag_iovec.iov_base = integrity_only_record_protocol->tag_buf;
  }
  /* Calls alts_iovec_record_protocol unprotect.  */
  char* error_details = nullptr;
  alts_grpc_record_protocol_convert_slice_buffer_to_iovec(
      rp, &integrity_only_record_protocol->data_sb);
  grpc_status_code status = alts_iovec_record_protocol_integrity_only_unprotect(
      rp->iovec_rp, rp->iovec_buf,
      integrity_only_record_protocol->data_sb.count, header_iovec, tag_iovec,
      &error_details);
  if (status != GRPC_STATUS_OK) {
    gpr_log(GPR_ERROR, "Failed to unprotect, %s", error_details);
    gpr_free(error_details);
    return TSI_INTERNAL_ERROR;
  }
  grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
  grpc_slice_buffer_reset_and_unref_internal(protected_slices);
  grpc_slice_buffer_move_into(&integrity_only_record_protocol->data_sb,
                              unprotected_slices);
  return TSI_OK;
}

static void alts_grpc_integrity_only_destruct(alts_grpc_record_protocol* rp) {
  if (rp == nullptr) {
    return;
  }
  alts_grpc_integrity_only_record_protocol* integrity_only_rp =
      reinterpret_cast<alts_grpc_integrity_only_record_protocol*>(rp);
  grpc_slice_buffer_destroy_internal(&integrity_only_rp->data_sb);
  gpr_free(integrity_only_rp->tag_buf);
}

static const alts_grpc_record_protocol_vtable
    alts_grpc_integrity_only_record_protocol_vtable = {
        alts_grpc_integrity_only_protect, alts_grpc_integrity_only_unprotect,
        alts_grpc_integrity_only_destruct};

tsi_result alts_grpc_integrity_only_record_protocol_create(
    gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
    bool is_protect, bool enable_extra_copy, alts_grpc_record_protocol** rp) {
  if (crypter == nullptr || rp == nullptr) {
    gpr_log(GPR_ERROR,
            "Invalid nullptr arguments to alts_grpc_record_protocol create.");
    return TSI_INVALID_ARGUMENT;
  }
  alts_grpc_integrity_only_record_protocol* impl =
      static_cast<alts_grpc_integrity_only_record_protocol*>(
          gpr_zalloc(sizeof(alts_grpc_integrity_only_record_protocol)));
  /* Calls alts_grpc_record_protocol init.  */
  tsi_result result = alts_grpc_record_protocol_init(
      &impl->base, crypter, overflow_size, is_client,
      /*is_integrity_only=*/true, is_protect);
  if (result != TSI_OK) {
    gpr_free(impl);
    return result;
  }
  impl->enable_extra_copy = enable_extra_copy;
  /* Initializes slice buffer for data_sb.  */
  grpc_slice_buffer_init(&impl->data_sb);
  /* Allocates tag buffer.  */
  impl->tag_buf =
      static_cast<unsigned char*>(gpr_malloc(impl->base.tag_length));
  impl->base.vtable = &alts_grpc_integrity_only_record_protocol_vtable;
  *rp = &impl->base;
  return TSI_OK;
}
<commit_msg>refactor extra-copy integrity-only protector<commit_after>/*
 *
 * Copyright 2018 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h"

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include <string.h>

#include "src/core/lib/slice/slice_internal.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"

/* Main struct for alts_grpc_integrity_only_record_protocol.  */
typedef struct alts_grpc_integrity_only_record_protocol {
  alts_grpc_record_protocol base;
  bool enable_extra_copy;
  grpc_slice_buffer data_sb;
  unsigned char* tag_buf;
} alts_grpc_integrity_only_record_protocol;

/* --- alts_grpc_record_protocol methods implementation. --- */

static tsi_result alts_grpc_integrity_only_extra_copy_protect(
    alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices,
    grpc_slice_buffer* protected_slices) {
  /* Allocates memory for protected frame.  */
  size_t protected_frame_size =
      unprotected_slices->length + rp->header_length + rp->tag_length;
  grpc_slice protected_slice = GRPC_SLICE_MALLOC(protected_frame_size);
  /* Calls alts_iovec_record_protocol protect.  */
  char* error_details = nullptr;
  iovec_t header_iovec = {GRPC_SLICE_START_PTR(protected_slice),
                          rp->header_length};
  iovec_t tag_iovec = {GRPC_SLICE_START_PTR(protected_slice) +
                           rp->header_length + unprotected_slices->length,
                       rp->tag_length};
  alts_grpc_record_protocol_convert_slice_buffer_to_iovec(rp,
                                                          unprotected_slices);
  grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
      rp->iovec_rp, rp->iovec_buf, unprotected_slices->count, header_iovec,
      tag_iovec, &error_details);
  if (status != GRPC_STATUS_OK) {
    gpr_log(GPR_ERROR, "Failed to protect, %s", error_details);
    gpr_free(error_details);
    return TSI_INTERNAL_ERROR;
  }
  /* Copies data from unprotected_slices to protected_slice.  */
  uint8_t* data = GRPC_SLICE_START_PTR(protected_slice) + rp->header_length;
  for (size_t i = 0; i < unprotected_slices->count; i++) {
    memcpy(data, GRPC_SLICE_START_PTR(unprotected_slices->slices[i]),
           GRPC_SLICE_LENGTH(unprotected_slices->slices[i]));
    data += GRPC_SLICE_LENGTH(unprotected_slices->slices[i]);
  }
  grpc_slice_buffer_add(protected_slices, protected_slice);
  grpc_slice_buffer_reset_and_unref_internal(unprotected_slices);
  return TSI_OK;
}

static tsi_result alts_grpc_integrity_only_protect(
    alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices,
    grpc_slice_buffer* protected_slices) {
  /* Input sanity check.  */
  if (rp == nullptr || unprotected_slices == nullptr ||
      protected_slices == nullptr) {
    gpr_log(GPR_ERROR,
            "Invalid nullptr arguments to alts_grpc_record_protocol protect.");
    return TSI_INVALID_ARGUMENT;
  }
  alts_grpc_integrity_only_record_protocol* integrity_only_record_protocol =
      reinterpret_cast<alts_grpc_integrity_only_record_protocol*>(rp);
  if (integrity_only_record_protocol->enable_extra_copy) {
    return alts_grpc_integrity_only_extra_copy_protect(rp, unprotected_slices,
                                                       protected_slices);
  }
  /* Allocates memory for header and tag slices.  */
  grpc_slice header_slice = GRPC_SLICE_MALLOC(rp->header_length);
  grpc_slice tag_slice = GRPC_SLICE_MALLOC(rp->tag_length);
  /* Calls alts_iovec_record_protocol protect.  */
  char* error_details = nullptr;
  iovec_t header_iovec = {GRPC_SLICE_START_PTR(header_slice),
                          GRPC_SLICE_LENGTH(header_slice)};
  iovec_t tag_iovec = {GRPC_SLICE_START_PTR(tag_slice),
                       GRPC_SLICE_LENGTH(tag_slice)};
  alts_grpc_record_protocol_convert_slice_buffer_to_iovec(rp,
                                                          unprotected_slices);
  grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
      rp->iovec_rp, rp->iovec_buf, unprotected_slices->count, header_iovec,
      tag_iovec, &error_details);
  if (status != GRPC_STATUS_OK) {
    gpr_log(GPR_ERROR, "Failed to protect, %s", error_details);
    gpr_free(error_details);
    return TSI_INTERNAL_ERROR;
  }
  /* Appends result to protected_slices.  */
  grpc_slice_buffer_add(protected_slices, header_slice);
  grpc_slice_buffer_move_into(unprotected_slices, protected_slices);
  grpc_slice_buffer_add(protected_slices, tag_slice);
  return TSI_OK;
}

static tsi_result alts_grpc_integrity_only_unprotect(
    alts_grpc_record_protocol* rp, grpc_slice_buffer* protected_slices,
    grpc_slice_buffer* unprotected_slices) {
  /* Input sanity check.  */
  if (rp == nullptr || protected_slices == nullptr ||
      unprotected_slices == nullptr) {
    gpr_log(
        GPR_ERROR,
        "Invalid nullptr arguments to alts_grpc_record_protocol unprotect.");
    return TSI_INVALID_ARGUMENT;
  }
  if (protected_slices->length < rp->header_length + rp->tag_length) {
    gpr_log(GPR_ERROR, "Protected slices do not have sufficient data.");
    return TSI_INVALID_ARGUMENT;
  }
  /* In this method, rp points to alts_grpc_record_protocol struct
   * and integrity_only_record_protocol points to
   * alts_grpc_integrity_only_record_protocol struct.  */
  alts_grpc_integrity_only_record_protocol* integrity_only_record_protocol =
      reinterpret_cast<alts_grpc_integrity_only_record_protocol*>(rp);
  /* Strips frame header from protected slices.  */
  grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
  grpc_slice_buffer_move_first(protected_slices, rp->header_length,
                               &rp->header_sb);
  GPR_ASSERT(rp->header_sb.length == rp->header_length);
  iovec_t header_iovec = alts_grpc_record_protocol_get_header_iovec(rp);
  /* Moves protected slices data to data_sb and leaves the remaining tag.  */
  grpc_slice_buffer_reset_and_unref_internal(
      &integrity_only_record_protocol->data_sb);
  grpc_slice_buffer_move_first(protected_slices,
                               protected_slices->length - rp->tag_length,
                               &integrity_only_record_protocol->data_sb);
  GPR_ASSERT(protected_slices->length == rp->tag_length);
  iovec_t tag_iovec = {nullptr, rp->tag_length};
  if (protected_slices->count == 1) {
    tag_iovec.iov_base = GRPC_SLICE_START_PTR(protected_slices->slices[0]);
  } else {
    /* Frame tag is in multiple slices, copies the tag bytes from slice
     * buffer to a single flat buffer.  */
    alts_grpc_record_protocol_copy_slice_buffer(
        protected_slices, integrity_only_record_protocol->tag_buf);
    tag_iovec.iov_base = integrity_only_record_protocol->tag_buf;
  }
  /* Calls alts_iovec_record_protocol unprotect.  */
  char* error_details = nullptr;
  alts_grpc_record_protocol_convert_slice_buffer_to_iovec(
      rp, &integrity_only_record_protocol->data_sb);
  grpc_status_code status = alts_iovec_record_protocol_integrity_only_unprotect(
      rp->iovec_rp, rp->iovec_buf,
      integrity_only_record_protocol->data_sb.count, header_iovec, tag_iovec,
      &error_details);
  if (status != GRPC_STATUS_OK) {
    gpr_log(GPR_ERROR, "Failed to unprotect, %s", error_details);
    gpr_free(error_details);
    return TSI_INTERNAL_ERROR;
  }
  grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
  grpc_slice_buffer_reset_and_unref_internal(protected_slices);
  grpc_slice_buffer_move_into(&integrity_only_record_protocol->data_sb,
                              unprotected_slices);
  return TSI_OK;
}

static void alts_grpc_integrity_only_destruct(alts_grpc_record_protocol* rp) {
  if (rp == nullptr) {
    return;
  }
  alts_grpc_integrity_only_record_protocol* integrity_only_rp =
      reinterpret_cast<alts_grpc_integrity_only_record_protocol*>(rp);
  grpc_slice_buffer_destroy_internal(&integrity_only_rp->data_sb);
  gpr_free(integrity_only_rp->tag_buf);
}

static const alts_grpc_record_protocol_vtable
    alts_grpc_integrity_only_record_protocol_vtable = {
        alts_grpc_integrity_only_protect, alts_grpc_integrity_only_unprotect,
        alts_grpc_integrity_only_destruct};

tsi_result alts_grpc_integrity_only_record_protocol_create(
    gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
    bool is_protect, bool enable_extra_copy, alts_grpc_record_protocol** rp) {
  if (crypter == nullptr || rp == nullptr) {
    gpr_log(GPR_ERROR,
            "Invalid nullptr arguments to alts_grpc_record_protocol create.");
    return TSI_INVALID_ARGUMENT;
  }
  alts_grpc_integrity_only_record_protocol* impl =
      static_cast<alts_grpc_integrity_only_record_protocol*>(
          gpr_zalloc(sizeof(alts_grpc_integrity_only_record_protocol)));
  /* Calls alts_grpc_record_protocol init.  */
  tsi_result result = alts_grpc_record_protocol_init(
      &impl->base, crypter, overflow_size, is_client,
      /*is_integrity_only=*/true, is_protect);
  if (result != TSI_OK) {
    gpr_free(impl);
    return result;
  }
  impl->enable_extra_copy = enable_extra_copy;
  /* Initializes slice buffer for data_sb.  */
  grpc_slice_buffer_init(&impl->data_sb);
  /* Allocates tag buffer.  */
  impl->tag_buf =
      static_cast<unsigned char*>(gpr_malloc(impl->base.tag_length));
  impl->base.vtable = &alts_grpc_integrity_only_record_protocol_vtable;
  *rp = &impl->base;
  return TSI_OK;
}
<|endoftext|>


<commit_before>#include <gobject-introspection-1.0/girepository.h>
#include <node.h>
#include <nan.h>

#include "boxed.h"
#include "debug.h"
#include "function.h"
#include "gi.h"
#include "gobject.h"
#include "loop.h"
#include "type.h"
#include "util.h"
#include "value.h"

using namespace v8;
using GNodeJS::BaseInfo;

namespace GNodeJS {

    G_DEFINE_QUARK(gnode_js_object,      object);
    G_DEFINE_QUARK(gnode_js_template,    template);
    G_DEFINE_QUARK(gnode_js_constructor, constructor);

    Nan::Persistent<Object> moduleCache(Nan::New<Object>());

    Local<Object> GetModuleCache() {
        return Nan::New<Object>(GNodeJS::moduleCache);
    }
}

static void DefineFunction(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info) {
    const char *function_name = g_base_info_get_name ((GIBaseInfo *) info);
    Local<Function> fn = GNodeJS::MakeFunction (info);

    module_obj->Set(String::NewFromUtf8(isolate, function_name), fn);
}

static void DefineFunction(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info, const char *base_name) {
    Local<Function> fn = GNodeJS::MakeFunction (info);

    char *function_name = g_strdup_printf ("%s_%s", base_name, g_base_info_get_name(info));
    Nan::Set(module_obj, UTF8(function_name), fn);
    g_free (function_name);
}

static void DefineObjectFunctions(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info) {
    const char *object_name = g_base_info_get_name ((GIBaseInfo *) info);

    int n_methods = g_object_info_get_n_methods (info);
    for (int i = 0; i < n_methods; i++) {
        GIFunctionInfo *meth_info = g_object_info_get_method (info, i);
        DefineFunction (isolate, module_obj, meth_info, object_name);
        g_base_info_unref ((GIBaseInfo *) meth_info);
    }
}

static void DefineBoxedFunctions(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info) {
    const char *object_name = g_base_info_get_name ((GIBaseInfo *) info);

    int n_methods = g_struct_info_get_n_methods (info);
    for (int i = 0; i < n_methods; i++) {
        GIFunctionInfo *meth_info = g_struct_info_get_method (info, i);
        DefineFunction (isolate, module_obj, meth_info, object_name);
        g_base_info_unref ((GIBaseInfo *) meth_info);
    }
}

static void DefineBootstrapInfo(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info) {
    GIInfoType type = g_base_info_get_type (info);

    switch (type) {
    case GI_INFO_TYPE_FUNCTION:
        DefineFunction (isolate, module_obj, info);
        break;
    case GI_INFO_TYPE_OBJECT:
        DefineObjectFunctions (isolate, module_obj, info);
        break;
    case GI_INFO_TYPE_BOXED:
    case GI_INFO_TYPE_STRUCT:
        DefineBoxedFunctions (isolate, module_obj, info);
        break;
    default:
        break;
    }
}

NAN_METHOD(Bootstrap) {
    Isolate *isolate = info.GetIsolate();

    GIRepository *repo = g_irepository_get_default ();
    GError *error = NULL;

    const char *ns = "GIRepository";
    g_irepository_require (repo, ns, NULL, (GIRepositoryLoadFlags) 0, &error);

    if (error) {
        Nan::ThrowError( error->message );
        return;
    }

    Local<Object> module_obj = Object::New (isolate);

    int n = g_irepository_get_n_infos (repo, ns);
    for (int i = 0; i < n; i++) {
        BaseInfo baseInfo(g_irepository_get_info(repo, ns, i));
        DefineBootstrapInfo(isolate, module_obj, baseInfo.info());
    }

    info.GetReturnValue().Set(module_obj);
}

NAN_METHOD(GetModuleCache) {
    info.GetReturnValue().Set(Nan::New<Object>(GNodeJS::moduleCache));
}

NAN_METHOD(GetConstantValue) {
    GIBaseInfo *gi_info = (GIBaseInfo *) GNodeJS::BoxedFromWrapper (info[0]);
    GITypeInfo *type = g_constant_info_get_type ((GIConstantInfo *) gi_info);

    if (type == NULL) {
        info.GetReturnValue().SetNull();
        return;
    }

    GIArgument gi_arg;
    g_constant_info_get_value((GIConstantInfo *) gi_info, &gi_arg);
    info.GetReturnValue().Set(GNodeJS::GIArgumentToV8 (type, &gi_arg));
}

NAN_METHOD(MakeFunction) {
    BaseInfo gi_info(info[0]);
    Local<Function> fn = GNodeJS::MakeFunction(*gi_info);
    info.GetReturnValue().Set(fn);
}

NAN_METHOD(MakeVirtualFunction) {
    if (info.Length() < 2 || !info[0]->IsObject() || !info[1]->IsNumber()) {
        Nan::ThrowTypeError("Incorrect arguments. Expecting (GIBaseInfo, GType)");
        return;
    }

    BaseInfo gi_info(info[0]);
    GType implementor = (gulong) info[1]->NumberValue ();

    MaybeLocal<Function> maybeFn = GNodeJS::MakeVirtualFunction(*gi_info, implementor);

    if (maybeFn.IsEmpty())
        return;

    info.GetReturnValue().Set(maybeFn.ToLocalChecked());
}

NAN_METHOD(MakeObjectClass) {
    BaseInfo gi_info(info[0]);
    info.GetReturnValue().Set(GNodeJS::MakeClass(*gi_info));
}

NAN_METHOD(MakeBoxedClass) {
    BaseInfo gi_info(info[0]);
    info.GetReturnValue().Set(GNodeJS::MakeBoxedClass(*gi_info));
}

NAN_METHOD(ObjectPropertyGetter) {
    GObject *gobject = GNodeJS::GObjectFromWrapper (info[0]);

    g_assert(gobject != NULL);

    Nan::Utf8String prop_name_v (info[1]->ToString ());
    const char *prop_name = *prop_name_v;

    GParamSpec *pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (gobject), prop_name);

    if (pspec == NULL) {
        WARN("ObjectPropertyGetter: no property %s", prop_name);
        return;
    }

    GValue value = {};
    g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
    g_object_get_property (gobject, prop_name, &value);

    RETURN(GNodeJS::GValueToV8(&value));
}

NAN_METHOD(ObjectPropertySetter) {
    GObject* gobject = GNodeJS::GObjectFromWrapper(info[0]);
    Nan::Utf8String prop_name_v (info[1]->ToString ());
    const char *prop_name = *prop_name_v;

    if (gobject == NULL) {
        WARN("ObjectPropertySetter: null GObject; cant get %s", prop_name);
        RETURN(Nan::False());
    }

    GParamSpec *pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (gobject), prop_name);

    if (pspec == NULL) {
        WARN("ObjectPropertySetter: no property %s", prop_name);
        Nan::ThrowError("Unexistent property");
        return;
    }

    GValue value = {};
    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (pspec));

    if (GNodeJS::V8ToGValue (&value, info[2])) {
        g_object_set_property (gobject, prop_name, &value);

        RETURN(Nan::True());
    } else {
        Nan::ThrowError("ObjectPropertySetter: could not convert value");

        RETURN(Nan::False());
    }
}

NAN_METHOD(StructFieldSetter) {
    Local<Object> boxedWrapper = info[0].As<Object>();
    Local<Object> fieldInfo    = info[1].As<Object>();
    Local<Value>  value        = info[2];

    void        *boxed = GNodeJS::BoxedFromWrapper(boxedWrapper);
    GIFieldInfo *field = (GIFieldInfo *) GNodeJS::BoxedFromWrapper(fieldInfo);
    GITypeInfo  *field_type = g_field_info_get_type(field);

    g_assert(boxed);
    g_assert(field);
    g_assert(field_type);

    GIArgument arg;

    if (!GNodeJS::V8ToGIArgument(field_type, &arg, value, true)) {
        char *message = g_strdup_printf("Couldn't convert value for field '%s'",
                g_base_info_get_name(field));
        Nan::ThrowTypeError (message);
        g_free(message);

        RETURN (Nan::Undefined());

    } else {

        if (g_field_info_set_field(field, boxed, &arg) == FALSE) {
            Nan::ThrowError("Unable to set field (complex types not allowed)");
            RETURN (Nan::Undefined());
        }

        /*
         * g_field_info_set_field:
         *   This only handles fields of simple C types. It will fail for a field of
         *   a composite type like a nested structure or union even if that is actually
         *   writable. Note also that that it will refuse to write fields where memory
         *   management would by required. A field with a type such as 'char *' must be
         *   set with a setter function.
         * Therefore, no need to free GIArgument.
         */

    }

    g_base_info_unref (field_type);
}

NAN_METHOD(StructFieldGetter) {
    Local<Object> boxedWrapper = info[0].As<Object>();
    Local<Object> fieldInfo    = info[1].As<Object>();

    if (boxedWrapper->InternalFieldCount() == 0) {
        Nan::ThrowError("StructFieldGetter: instance is not a boxed");
        return;
    }

    if (fieldInfo->InternalFieldCount() == 0) {
        Nan::ThrowError("StructFieldGetter: field info is invalid");
        return;
    }

    void        *boxed = GNodeJS::BoxedFromWrapper(boxedWrapper);
    GIFieldInfo *field = (GIFieldInfo *) GNodeJS::BoxedFromWrapper(fieldInfo);

    if (boxed == NULL) {
        Nan::ThrowError("StructFieldGetter: instance is NULL");
        return;
    }

    if (field == NULL) {
        Nan::ThrowError("StructFieldGetter: field info is NULL");
        return;
    }

    GIArgument value;
    if (!g_field_info_get_field(field, boxed, &value)) {
        Nan::ThrowError("Unable to get field (complex types not allowed)");
        return;
    }

    GITypeInfo  *field_type = g_field_info_get_type(field);
    RETURN(GNodeJS::GIArgumentToV8(field_type, &value));
    g_base_info_unref (field_type);
}

NAN_METHOD(StartLoop) {
    GNodeJS::StartLoop ();
}

NAN_METHOD(PointerToString) {
    if (info[0]->ToObject()->InternalFieldCount() == 0) {
        Nan::ThrowReferenceError("Object doesnt have any internal field.");
        return;
    }
    void *boxed = GNodeJS::BoxedFromWrapper(info[0]);
    char *address = g_strdup_printf("%#zx", (unsigned long)boxed);
    info.GetReturnValue().Set(UTF8(address));
    g_free(address);
}

NAN_METHOD(InternalFieldCount) {
    Local<Object> obj = info[0].As<Object>();
    RETURN(obj->InternalFieldCount());
}

NAN_METHOD(GetBaseClass) {
    auto tpl = GNodeJS::GetBaseClassTemplate ();
    auto fn = tpl->GetFunction();
    info.GetReturnValue().Set(fn);
}

NAN_METHOD(GetTypeSize) {
    GITypeInfo *gi_info = (GITypeInfo *) GNodeJS::BoxedFromWrapper (info[0]);
    auto size = GNodeJS::GetTypeSize (gi_info);
    info.GetReturnValue().Set(Nan::New<Number>(size));
}

NAN_METHOD(GetLoopStack) {
    auto stack = GNodeJS::GetLoopStack();
    info.GetReturnValue().Set(stack);
}

void InitModule(Local<Object> exports, Local<Value> module, void *priv) {
    NAN_EXPORT(exports, Bootstrap);
    NAN_EXPORT(exports, GetModuleCache);
    NAN_EXPORT(exports, GetConstantValue);
    NAN_EXPORT(exports, MakeBoxedClass);
    NAN_EXPORT(exports, MakeObjectClass);
    NAN_EXPORT(exports, MakeFunction);
    NAN_EXPORT(exports, MakeVirtualFunction);
    NAN_EXPORT(exports, StructFieldGetter);
    NAN_EXPORT(exports, StructFieldSetter);
    NAN_EXPORT(exports, ObjectPropertyGetter);
    NAN_EXPORT(exports, ObjectPropertySetter);
    NAN_EXPORT(exports, StartLoop);
    NAN_EXPORT(exports, PointerToString);
    NAN_EXPORT(exports, InternalFieldCount);
    NAN_EXPORT(exports, GetBaseClass);
    NAN_EXPORT(exports, GetTypeSize);
    NAN_EXPORT(exports, GetLoopStack);
}

NODE_MODULE(node_gtk, InitModule)
<commit_msg>refactor gi.cc<commit_after>#include <gobject-introspection-1.0/girepository.h>
#include <node.h>
#include <nan.h>

#include "boxed.h"
#include "debug.h"
#include "function.h"
#include "gi.h"
#include "gobject.h"
#include "loop.h"
#include "type.h"
#include "util.h"
#include "value.h"

using namespace v8;
using GNodeJS::BaseInfo;

namespace GNodeJS {

    G_DEFINE_QUARK(gnode_js_object,      object);
    G_DEFINE_QUARK(gnode_js_template,    template);
    G_DEFINE_QUARK(gnode_js_constructor, constructor);

    Nan::Persistent<Object> moduleCache(Nan::New<Object>());

    Local<Object> GetModuleCache() {
        return Nan::New<Object>(GNodeJS::moduleCache);
    }
}

static void DefineFunction(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info) {
    const char *function_name = g_base_info_get_name ((GIBaseInfo *) info);
    Local<Function> fn = GNodeJS::MakeFunction (info);

    module_obj->Set(String::NewFromUtf8(isolate, function_name), fn);
}

static void DefineFunction(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info, const char *base_name) {
    Local<Function> fn = GNodeJS::MakeFunction (info);

    char *function_name = g_strdup_printf ("%s_%s", base_name, g_base_info_get_name(info));
    Nan::Set(module_obj, UTF8(function_name), fn);
    g_free (function_name);
}

static void DefineObjectFunctions(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info) {
    const char *object_name = g_base_info_get_name ((GIBaseInfo *) info);

    int n_methods = g_object_info_get_n_methods (info);
    for (int i = 0; i < n_methods; i++) {
        GIFunctionInfo *meth_info = g_object_info_get_method (info, i);
        DefineFunction (isolate, module_obj, meth_info, object_name);
        g_base_info_unref ((GIBaseInfo *) meth_info);
    }
}

static void DefineBoxedFunctions(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info) {
    const char *object_name = g_base_info_get_name ((GIBaseInfo *) info);

    int n_methods = g_struct_info_get_n_methods (info);
    for (int i = 0; i < n_methods; i++) {
        GIFunctionInfo *meth_info = g_struct_info_get_method (info, i);
        DefineFunction (isolate, module_obj, meth_info, object_name);
        g_base_info_unref ((GIBaseInfo *) meth_info);
    }
}

static void DefineBootstrapInfo(Isolate *isolate, Local<Object> module_obj, GIBaseInfo *info) {
    GIInfoType type = g_base_info_get_type (info);

    switch (type) {
    case GI_INFO_TYPE_FUNCTION:
        DefineFunction (isolate, module_obj, info);
        break;
    case GI_INFO_TYPE_OBJECT:
        DefineObjectFunctions (isolate, module_obj, info);
        break;
    case GI_INFO_TYPE_BOXED:
    case GI_INFO_TYPE_STRUCT:
        DefineBoxedFunctions (isolate, module_obj, info);
        break;
    default:
        break;
    }
}

NAN_METHOD(Bootstrap) {
    Isolate *isolate = info.GetIsolate();

    GIRepository *repo = g_irepository_get_default ();
    GError *error = NULL;

    const char *ns = "GIRepository";
    g_irepository_require (repo, ns, NULL, (GIRepositoryLoadFlags) 0, &error);

    if (error) {
        Nan::ThrowError( error->message );
        return;
    }

    Local<Object> module_obj = Object::New (isolate);

    int n = g_irepository_get_n_infos (repo, ns);
    for (int i = 0; i < n; i++) {
        BaseInfo baseInfo(g_irepository_get_info(repo, ns, i));
        DefineBootstrapInfo(isolate, module_obj, baseInfo.info());
    }

    info.GetReturnValue().Set(module_obj);
}

NAN_METHOD(GetConstantValue) {
    GIBaseInfo *gi_info = (GIBaseInfo *) GNodeJS::BoxedFromWrapper (info[0]);
    GITypeInfo *type = g_constant_info_get_type ((GIConstantInfo *) gi_info);

    if (type == NULL) {
        info.GetReturnValue().SetNull();
        return;
    }

    GIArgument gi_arg;
    g_constant_info_get_value((GIConstantInfo *) gi_info, &gi_arg);
    info.GetReturnValue().Set(GNodeJS::GIArgumentToV8 (type, &gi_arg));
}

NAN_METHOD(MakeFunction) {
    BaseInfo gi_info(info[0]);
    Local<Function> fn = GNodeJS::MakeFunction(*gi_info);
    info.GetReturnValue().Set(fn);
}

NAN_METHOD(MakeVirtualFunction) {
    if (info.Length() < 2 || !info[0]->IsObject() || !info[1]->IsNumber()) {
        Nan::ThrowTypeError("Incorrect arguments. Expecting (GIBaseInfo, GType)");
        return;
    }

    BaseInfo gi_info(info[0]);
    GType implementor = (gulong) info[1]->NumberValue ();

    MaybeLocal<Function> maybeFn = GNodeJS::MakeVirtualFunction(*gi_info, implementor);

    if (maybeFn.IsEmpty())
        return;

    info.GetReturnValue().Set(maybeFn.ToLocalChecked());
}

NAN_METHOD(MakeObjectClass) {
    BaseInfo gi_info(info[0]);
    info.GetReturnValue().Set(GNodeJS::MakeClass(*gi_info));
}

NAN_METHOD(MakeBoxedClass) {
    BaseInfo gi_info(info[0]);
    info.GetReturnValue().Set(GNodeJS::MakeBoxedClass(*gi_info));
}

NAN_METHOD(ObjectPropertyGetter) {
    GObject *gobject = GNodeJS::GObjectFromWrapper (info[0]);

    g_assert(gobject != NULL);

    Nan::Utf8String prop_name_v (info[1]->ToString ());
    const char *prop_name = *prop_name_v;

    GParamSpec *pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (gobject), prop_name);

    if (pspec == NULL) {
        WARN("ObjectPropertyGetter: no property %s", prop_name);
        return;
    }

    GValue value = {};
    g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
    g_object_get_property (gobject, prop_name, &value);

    RETURN(GNodeJS::GValueToV8(&value));
}

NAN_METHOD(ObjectPropertySetter) {
    GObject* gobject = GNodeJS::GObjectFromWrapper(info[0]);
    Nan::Utf8String prop_name_v (info[1]->ToString ());
    const char *prop_name = *prop_name_v;

    if (gobject == NULL) {
        WARN("ObjectPropertySetter: null GObject; cant get %s", prop_name);
        RETURN(Nan::False());
    }

    GParamSpec *pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (gobject), prop_name);

    if (pspec == NULL) {
        WARN("ObjectPropertySetter: no property %s", prop_name);
        Nan::ThrowError("Unexistent property");
        return;
    }

    GValue value = {};
    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (pspec));

    if (GNodeJS::V8ToGValue (&value, info[2])) {
        g_object_set_property (gobject, prop_name, &value);

        RETURN(Nan::True());
    } else {
        Nan::ThrowError("ObjectPropertySetter: could not convert value");

        RETURN(Nan::False());
    }
}

NAN_METHOD(StructFieldSetter) {
    Local<Object> boxedWrapper = info[0].As<Object>();
    Local<Object> fieldInfo    = info[1].As<Object>();
    Local<Value>  value        = info[2];

    void        *boxed = GNodeJS::BoxedFromWrapper(boxedWrapper);
    GIFieldInfo *field = (GIFieldInfo *) GNodeJS::BoxedFromWrapper(fieldInfo);
    GITypeInfo  *field_type = g_field_info_get_type(field);

    g_assert(boxed);
    g_assert(field);
    g_assert(field_type);

    GIArgument arg;

    if (!GNodeJS::V8ToGIArgument(field_type, &arg, value, true)) {
        char *message = g_strdup_printf("Couldn't convert value for field '%s'",
                g_base_info_get_name(field));
        Nan::ThrowTypeError (message);
        g_free(message);

        RETURN (Nan::Undefined());

    } else {

        if (g_field_info_set_field(field, boxed, &arg) == FALSE) {
            Nan::ThrowError("Unable to set field (complex types not allowed)");
            RETURN (Nan::Undefined());
        }

        /*
         * g_field_info_set_field:
         *   This only handles fields of simple C types. It will fail for a field of
         *   a composite type like a nested structure or union even if that is actually
         *   writable. Note also that that it will refuse to write fields where memory
         *   management would by required. A field with a type such as 'char *' must be
         *   set with a setter function.
         * Therefore, no need to free GIArgument.
         */

    }

    g_base_info_unref (field_type);
}

NAN_METHOD(StructFieldGetter) {
    Local<Object> boxedWrapper = info[0].As<Object>();
    Local<Object> fieldInfo    = info[1].As<Object>();

    if (boxedWrapper->InternalFieldCount() == 0) {
        Nan::ThrowError("StructFieldGetter: instance is not a boxed");
        return;
    }

    if (fieldInfo->InternalFieldCount() == 0) {
        Nan::ThrowError("StructFieldGetter: field info is invalid");
        return;
    }

    void        *boxed = GNodeJS::BoxedFromWrapper(boxedWrapper);
    GIFieldInfo *field = (GIFieldInfo *) GNodeJS::BoxedFromWrapper(fieldInfo);

    if (boxed == NULL) {
        Nan::ThrowError("StructFieldGetter: instance is NULL");
        return;
    }

    if (field == NULL) {
        Nan::ThrowError("StructFieldGetter: field info is NULL");
        return;
    }

    GIArgument value;
    if (!g_field_info_get_field(field, boxed, &value)) {
        Nan::ThrowError("Unable to get field (complex types not allowed)");
        return;
    }

    GITypeInfo  *field_type = g_field_info_get_type(field);
    RETURN(GNodeJS::GIArgumentToV8(field_type, &value));
    g_base_info_unref (field_type);
}

NAN_METHOD(StartLoop) {
    GNodeJS::StartLoop ();
}

NAN_METHOD(InternalFieldCount) {
    Local<Object> obj = info[0].As<Object>();
    RETURN(obj->InternalFieldCount());
}

NAN_METHOD(GetBaseClass) {
    auto tpl = GNodeJS::GetBaseClassTemplate ();
    auto fn = tpl->GetFunction();
    info.GetReturnValue().Set(fn);
}

NAN_METHOD(GetTypeSize) {
    GITypeInfo *gi_info = (GITypeInfo *) GNodeJS::BoxedFromWrapper (info[0]);
    auto size = GNodeJS::GetTypeSize (gi_info);
    info.GetReturnValue().Set(Nan::New<Number>(size));
}

NAN_METHOD(GetLoopStack) {
    auto stack = GNodeJS::GetLoopStack();
    info.GetReturnValue().Set(stack);
}

NAN_METHOD(GetModuleCache) {
    info.GetReturnValue().Set(Nan::New<Object>(GNodeJS::moduleCache));
}

void InitModule(Local<Object> exports, Local<Value> module, void *priv) {
    NAN_EXPORT(exports, Bootstrap);
    NAN_EXPORT(exports, GetModuleCache);
    NAN_EXPORT(exports, GetConstantValue);
    NAN_EXPORT(exports, MakeBoxedClass);
    NAN_EXPORT(exports, MakeObjectClass);
    NAN_EXPORT(exports, MakeFunction);
    NAN_EXPORT(exports, MakeVirtualFunction);
    NAN_EXPORT(exports, StructFieldGetter);
    NAN_EXPORT(exports, StructFieldSetter);
    NAN_EXPORT(exports, ObjectPropertyGetter);
    NAN_EXPORT(exports, ObjectPropertySetter);
    NAN_EXPORT(exports, StartLoop);
    NAN_EXPORT(exports, InternalFieldCount);
    NAN_EXPORT(exports, GetBaseClass);
    NAN_EXPORT(exports, GetTypeSize);
    NAN_EXPORT(exports, GetLoopStack);
}

NODE_MODULE(node_gtk, InitModule)
<|endoftext|>


<commit_before>/*
 * article.cpp
 *
 * Copyright (c) 2001, 2002, 2003, 2004 Frerich Raabe <raabe@kde.org>
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. For licensing and distribution details, check the
 * accompanying file 'COPYING'.
 */
#include "article.h"
#include "tools_p.h"
#include "enclosure.h"
#include "category.h"

#include <kdebug.h>
#include <krfcdate.h>
#include <kurl.h>
#include <kurllabel.h>
#include <kmdcodec.h>

#include <qdatetime.h>
#include <qdom.h>

using namespace RSS;
namespace RSS
{
    KMD5 md5Machine;
}

struct Article::Private : public Shared
{
	QString title;
	KURL link;
	QString description;
	QDateTime pubDate;
	QString guid;
	bool guidIsPermaLink;
    MetaInfoMap meta;
	KURL commentsLink;
        int numComments;
        Enclosure enclosure;
	QValueList<Category> categories;
};

Article::Article() : d(new Private)
{
}

Article::Article(const Article &other) : d(0)
{
	*this = other;
}

Enclosure Article::enclosure() const
{
    return d->enclosure;
}

QValueList<Category> Article::categories() const
{
    return d->categories;
}

Article::Article(const QDomNode &node, Format format, Version version) : d(new Private)
{
	QString elemText;

	d->numComments=0;

	if (!(elemText = extractTitle(node)).isNull())
		d->title = elemText;

	if (format==AtomFeed)
	{
		QDomNode n;
		for (n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
			const QDomElement e = n.toElement();
			if ( (e.tagName()==QString::fromLatin1("link")) &&
				(e.attribute(QString::fromLatin1("rel"))==QString::fromLatin1("alternate")))
				{
					d->link=n.toElement().attribute(QString::fromLatin1("href"));
					break;
				}
		}
	}
	else
	{
		if (!(elemText = extractNode(node, QString::fromLatin1("link"))).isNull())
			d->link = elemText;
	}

    // prefer content/content:encoded over summary/description for feeds that provide it
    QString tagName=(format==AtomFeed)? QString::fromLatin1("content"): QString::fromLatin1("content:encoded");

    if (!(elemText = extractNode(node, tagName, false)).isNull())
        d->description = elemText;

    if (d->description.isEmpty())
    {
		if (!(elemText = extractNode(node, QString::fromLatin1("body"), false)).isNull())
			d->description = elemText;

		if (d->description.isEmpty())  // 3rd try: see http://www.intertwingly.net/blog/1299.html
		{
			if (!(elemText = extractNode(node, QString::fromLatin1((format==AtomFeed)? "summary" : "description"), false)).isNull())
				d->description = elemText;
		}
	}

	time_t time = 0;

	if (format == AtomFeed)
	{
        if (version == vAtom_1_0)
            elemText = extractNode(node, QString::fromLatin1("updated"));
        else
           elemText = extractNode(node, QString::fromLatin1("issued"));

		if (!elemText.isNull())
			time = parseISO8601Date(elemText);
	}
	else
	{
		elemText = extractNode(node, QString::fromLatin1("pubDate"));
		if (!elemText.isNull())
			time = KRFCDate::parseDate(elemText);
	}

	if (!(elemText = extractNode(node, QString::fromLatin1("dc:date"))).isNull())
	{
		time = parseISO8601Date(elemText);
	}

	// 0 means invalid, not epoch (parsers return epoch+1 when parsing epoch, see the KRFCDate::parseDate() docs)
        if (time != 0)
		d->pubDate.setTime_t(time);

	if (!(elemText = extractNode(node, QString::fromLatin1("wfw:comment"))).isNull()) {
		d->commentsLink = elemText;
	}

    if (!(elemText = extractNode(node, QString::fromLatin1("slash:comments"))).isNull()) {
        d->numComments = elemText.toInt();
    }

    QDomElement element = QDomNode(node).toElement();

    // in RSS 1.0, we use <item about> attribute as ID
    // FIXME: pass format version instead of checking for attribute

    if (!element.isNull() && element.hasAttribute(QString::fromLatin1("rdf:about")))
    {
        d->guid = element.attribute(QString::fromLatin1("rdf:about")); // HACK: using ns properly did not work
        d->guidIsPermaLink = false;
    }
    else
    {
        tagName=(format==AtomFeed)? QString::fromLatin1("id"): QString::fromLatin1("guid");
        QDomNode n = node.namedItem(tagName);
	    if (!n.isNull())
        {
            d->guidIsPermaLink = (format==AtomFeed)? false : true;
            if (n.toElement().attribute(QString::fromLatin1("isPermaLink"), "true") == "false") d->guidIsPermaLink = false;
            if (!(elemText = extractNode(node, tagName)).isNull())
                d->guid = elemText;
        }
    }

	if(d->guid.isEmpty()) {
		d->guidIsPermaLink = false;

		md5Machine.reset();
		QDomNode n(node);
		md5Machine.update(d->title.utf8());
		md5Machine.update(d->description.utf8());
		d->guid = QString(md5Machine.hexDigest().data());
        d->meta[QString::fromLatin1("guidIsHash")] = QString::fromLatin1("true");
	}

    QDomNode enclosure = element.namedItem(QString::fromLatin1("enclosure"));
    if (enclosure.isElement())
        d->enclosure = Enclosure::fromXML(enclosure.toElement());

    for (QDomNode i = node.firstChild(); !i.isNull(); i = i.nextSibling())
    {
        if (i.isElement())
        {
            if (i.toElement().tagName() == QString::fromLatin1("metaInfo:meta"))
            {
                QString type = i.toElement().attribute(QString::fromLatin1("type"));
                d->meta[type] = i.toElement().text();
            }
            else if (i.toElement().tagName() == QString::fromLatin1("category"))
            {
                d->categories.append(Category::fromXML(i.toElement()));
            }
        }
    }
}

Article::~Article()
{
	if (d->deref())
		delete d;
}

QString Article::title() const
{
	return d->title;
}

const KURL &Article::link() const
{
	return d->link;
}

QString Article::description() const
{
	return d->description;
}

QString Article::guid() const
{
	return d->guid;
}

bool Article::guidIsPermaLink() const
{
	return d->guidIsPermaLink;
}

const QDateTime &Article::pubDate() const
{
	return d->pubDate;
}

const KURL &Article::commentsLink() const
{
	return d->commentsLink;
}

int Article::comments() const
{
	return d->numComments;
}

QString Article::meta(const QString &key) const
{
    return d->meta[key];
}

KURLLabel *Article::widget(QWidget *parent, const char *name) const
{
	KURLLabel *label = new KURLLabel(d->link.url(), d->title, parent, name);
	label->setUseTips(true);
	if (!d->description.isNull())
		label->setTipText(d->description);

	return label;
}

Article &Article::operator=(const Article &other)
{
	if (this != &other) {
		other.d->ref();
		if (d && d->deref())
			delete d;
		d = other.d;
	}
	return *this;
}

bool Article::operator==(const Article &other) const
{
	return d->guid == other.guid();
}

// vim:noet:ts=4
<commit_msg>Set "rel" attribute default to "alternate", as requested by Atom specification BUG:122409<commit_after>/*
 * article.cpp
 *
 * Copyright (c) 2001, 2002, 2003, 2004 Frerich Raabe <raabe@kde.org>
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. For licensing and distribution details, check the
 * accompanying file 'COPYING'.
 */
#include "article.h"
#include "tools_p.h"
#include "enclosure.h"
#include "category.h"

#include <kdebug.h>
#include <krfcdate.h>
#include <kurl.h>
#include <kurllabel.h>
#include <kmdcodec.h>

#include <qdatetime.h>
#include <qdom.h>

using namespace RSS;
namespace RSS
{
    KMD5 md5Machine;
}

struct Article::Private : public Shared
{
	QString title;
	KURL link;
	QString description;
	QDateTime pubDate;
	QString guid;
	bool guidIsPermaLink;
    MetaInfoMap meta;
	KURL commentsLink;
        int numComments;
        Enclosure enclosure;
	QValueList<Category> categories;
};

Article::Article() : d(new Private)
{
}

Article::Article(const Article &other) : d(0)
{
	*this = other;
}

Enclosure Article::enclosure() const
{
    return d->enclosure;
}

QValueList<Category> Article::categories() const
{
    return d->categories;
}

Article::Article(const QDomNode &node, Format format, Version version) : d(new Private)
{
	QString elemText;

	d->numComments=0;

	if (!(elemText = extractTitle(node)).isNull())
		d->title = elemText;

	if (format==AtomFeed)
	{
		QDomNode n;
		for (n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
			const QDomElement e = n.toElement();
			if ( (e.tagName()==QString::fromLatin1("link")) &&
				(e.attribute(QString::fromLatin1("rel"), QString::fromLatin1("alternate"))==QString::fromLatin1("alternate")))
				{
					d->link=n.toElement().attribute(QString::fromLatin1("href"));
					break;
				}
		}
	}
	else
	{
		if (!(elemText = extractNode(node, QString::fromLatin1("link"))).isNull())
			d->link = elemText;
	}

    // prefer content/content:encoded over summary/description for feeds that provide it
    QString tagName=(format==AtomFeed)? QString::fromLatin1("content"): QString::fromLatin1("content:encoded");

    if (!(elemText = extractNode(node, tagName, false)).isNull())
        d->description = elemText;

    if (d->description.isEmpty())
    {
		if (!(elemText = extractNode(node, QString::fromLatin1("body"), false)).isNull())
			d->description = elemText;

		if (d->description.isEmpty())  // 3rd try: see http://www.intertwingly.net/blog/1299.html
		{
			if (!(elemText = extractNode(node, QString::fromLatin1((format==AtomFeed)? "summary" : "description"), false)).isNull())
				d->description = elemText;
		}
	}

	time_t time = 0;

	if (format == AtomFeed)
	{
        if (version == vAtom_1_0)
            elemText = extractNode(node, QString::fromLatin1("updated"));
        else
           elemText = extractNode(node, QString::fromLatin1("issued"));

		if (!elemText.isNull())
			time = parseISO8601Date(elemText);
	}
	else
	{
		elemText = extractNode(node, QString::fromLatin1("pubDate"));
		if (!elemText.isNull())
			time = KRFCDate::parseDate(elemText);
	}

	if (!(elemText = extractNode(node, QString::fromLatin1("dc:date"))).isNull())
	{
		time = parseISO8601Date(elemText);
	}

	// 0 means invalid, not epoch (parsers return epoch+1 when parsing epoch, see the KRFCDate::parseDate() docs)
        if (time != 0)
		d->pubDate.setTime_t(time);

	if (!(elemText = extractNode(node, QString::fromLatin1("wfw:comment"))).isNull()) {
		d->commentsLink = elemText;
	}

    if (!(elemText = extractNode(node, QString::fromLatin1("slash:comments"))).isNull()) {
        d->numComments = elemText.toInt();
    }

    QDomElement element = QDomNode(node).toElement();

    // in RSS 1.0, we use <item about> attribute as ID
    // FIXME: pass format version instead of checking for attribute

    if (!element.isNull() && element.hasAttribute(QString::fromLatin1("rdf:about")))
    {
        d->guid = element.attribute(QString::fromLatin1("rdf:about")); // HACK: using ns properly did not work
        d->guidIsPermaLink = false;
    }
    else
    {
        tagName=(format==AtomFeed)? QString::fromLatin1("id"): QString::fromLatin1("guid");
        QDomNode n = node.namedItem(tagName);
	    if (!n.isNull())
        {
            d->guidIsPermaLink = (format==AtomFeed)? false : true;
            if (n.toElement().attribute(QString::fromLatin1("isPermaLink"), "true") == "false") d->guidIsPermaLink = false;
            if (!(elemText = extractNode(node, tagName)).isNull())
                d->guid = elemText;
        }
    }

	if(d->guid.isEmpty()) {
		d->guidIsPermaLink = false;

		md5Machine.reset();
		QDomNode n(node);
		md5Machine.update(d->title.utf8());
		md5Machine.update(d->description.utf8());
		d->guid = QString(md5Machine.hexDigest().data());
        d->meta[QString::fromLatin1("guidIsHash")] = QString::fromLatin1("true");
	}

    QDomNode enclosure = element.namedItem(QString::fromLatin1("enclosure"));
    if (enclosure.isElement())
        d->enclosure = Enclosure::fromXML(enclosure.toElement());

    for (QDomNode i = node.firstChild(); !i.isNull(); i = i.nextSibling())
    {
        if (i.isElement())
        {
            if (i.toElement().tagName() == QString::fromLatin1("metaInfo:meta"))
            {
                QString type = i.toElement().attribute(QString::fromLatin1("type"));
                d->meta[type] = i.toElement().text();
            }
            else if (i.toElement().tagName() == QString::fromLatin1("category"))
            {
                d->categories.append(Category::fromXML(i.toElement()));
            }
        }
    }
}

Article::~Article()
{
	if (d->deref())
		delete d;
}

QString Article::title() const
{
	return d->title;
}

const KURL &Article::link() const
{
	return d->link;
}

QString Article::description() const
{
	return d->description;
}

QString Article::guid() const
{
	return d->guid;
}

bool Article::guidIsPermaLink() const
{
	return d->guidIsPermaLink;
}

const QDateTime &Article::pubDate() const
{
	return d->pubDate;
}

const KURL &Article::commentsLink() const
{
	return d->commentsLink;
}

int Article::comments() const
{
	return d->numComments;
}

QString Article::meta(const QString &key) const
{
    return d->meta[key];
}

KURLLabel *Article::widget(QWidget *parent, const char *name) const
{
	KURLLabel *label = new KURLLabel(d->link.url(), d->title, parent, name);
	label->setUseTips(true);
	if (!d->description.isNull())
		label->setTipText(d->description);

	return label;
}

Article &Article::operator=(const Article &other)
{
	if (this != &other) {
		other.d->ref();
		if (d && d->deref())
			delete d;
		d = other.d;
	}
	return *this;
}

bool Article::operator==(const Article &other) const
{
	return d->guid == other.guid();
}

// vim:noet:ts=4
<|endoftext|>


<commit_before>#pragma once

#include <math.h>

namespace rack {

////////////////////
// integer functions
////////////////////

inline int mini(int a, int b) {
	return a < b ? a : b;
}

inline int maxi(int a, int b) {
	return a > b ? a : b;
}

/** Limits a value between a minimum and maximum */
inline int clampi(int x, int min, int max) {
	return x > max ? max : x < min ? min : x;
}

inline int absi(int a) {
	return a >= 0 ? a : -a;
}

// Euclidean modulus, always returns 0 <= mod < base for positive base
// Assumes this architecture's division is non-Euclidean
inline int eucmodi(int a, int base) {
	int mod = a % base;
	return mod < 0 ? mod + base : mod;
}

inline int log2i(int n) {
	int i = 0;
	while (n >>= 1) {
		i++;
	}
	return i;
}

inline bool ispow2i(int n) {
	return n > 0 && (n & (n - 1)) == 0;
}

////////////////////
// float functions
////////////////////

/** Returns 1.0 for positive numbers and -1.0 for negative numbers (including positive/negative zero) */
inline float sgnf(float x) {
	return copysignf(1.0, x);
}

inline float eucmodf(float a, float base) {
	float mod = fmodf(a, base);
	return mod < 0.0 ? mod + base : mod;
}

/** Limits a value between a minimum and maximum
If min < max, returns max
*/
inline float clampf(float x, float min, float max) {
	return x > max ? max : x < min ? min : x;
}

/** If the magnitude of x if less than eps, return 0 */
inline float chopf(float x, float eps) {
	return -eps < x && x < eps ? 0.0 : x;
}

inline float rescalef(float x, float xMin, float xMax, float yMin, float yMax) {
	return yMin + (x - xMin) / (xMax - xMin) * (yMax - yMin);
}

inline float crossf(float a, float b, float frac) {
	return (1.0 - frac) * a + frac * b;
}

inline float quadraticBipolar(float x) {
	float x2 = x*x;
	return x >= 0.0 ? x2 : -x2;
}

inline float cubic(float x) {
	return x*x*x;
}

inline float quarticBipolar(float x) {
	return x >= 0.0 ? x*x*x*x : -x*x*x*x;
}

inline float quintic(float x) {
	// optimal with --fast-math
	return x*x*x*x*x;
}

inline float sqrtBipolar(float x) {
	return x >= 0.0 ? sqrtf(x) : -sqrtf(-x);
}

/** This is pretty much a scaled sinh */
inline float exponentialBipolar(float b, float x) {
	const float a = b - 1.0 / b;
	return (powf(b, x) - powf(b, -x)) / a;
}

inline float sincf(float x) {
	if (x == 0.0)
		return 1.0;
	x *= M_PI;
	return sinf(x) / x;
}

inline float getf(const float *p, float v = 0.0) {
	return p ? *p : v;
}

inline void setf(float *p, float v) {
	if (p)
		*p = v;
}

/** Linearly interpolate an array `p` with index `x`
Assumes that the array at `p` is of length at least floor(x)+1.
*/
inline float interpf(const float *p, float x) {
	int xi = x;
	float xf = x - xi;
	return crossf(p[xi], p[xi+1], xf);
}

/** Complex multiply c = a * b
It is of course acceptable to reuse arguments
i.e. cmultf(&ar, &ai, ar, ai, br, bi)
*/
inline void cmultf(float *cr, float *ci, float ar, float ai, float br, float bi) {
	*cr = ar * br - ai * bi;
	*ci = ar * bi + ai * br;
}

////////////////////
// 2D float vector
////////////////////

struct Vec {
	float x, y;

	Vec() : x(0.0), y(0.0) {}
	Vec(float x, float y) : x(x), y(y) {}

	Vec neg() {
		return Vec(-x, -y);
	}
	Vec plus(Vec b) {
		return Vec(x + b.x, y + b.y);
	}
	Vec minus(Vec b) {
		return Vec(x - b.x, y - b.y);
	}
	Vec mult(float s) {
		return Vec(x * s, y * s);
	}
	Vec div(float s) {
		return Vec(x / s, y / s);
	}
	float dot(Vec b) {
		return x * b.x + y * b.y;
	}
	float norm() {
		return hypotf(x, y);
	}
	Vec min(Vec b) {
		return Vec(fminf(x, b.x), fminf(y, b.y));
	}
	Vec max(Vec b) {
		return Vec(fmaxf(x, b.x), fmaxf(y, b.y));
	}
	Vec round() {
		return Vec(roundf(x), roundf(y));
	}
	bool isZero() {
		return x == 0.0 && y == 0.0;
	}
};

struct Rect {
	Vec pos;
	Vec size;

	Rect() {}
	Rect(Vec pos, Vec size) : pos(pos), size(size) {}
	static Rect fromMinMax(Vec min, Vec max) {
		return Rect(min, max.minus(min));
	}

	/** Returns whether this Rect contains another Rect, inclusive on the top/left, non-inclusive on the bottom/right */
	bool contains(Vec v) {
		return pos.x <= v.x && v.x < pos.x + size.x
			&& pos.y <= v.y && v.y < pos.y + size.y;
	}
	/** Returns whether this Rect overlaps with another Rect */
	bool intersects(Rect r) {
		return (pos.x + size.x > r.pos.x && r.pos.x + r.size.x > pos.x)
			&& (pos.y + size.y > r.pos.y && r.pos.y + r.size.y > pos.y);
	}
	Vec getCenter() {
		return pos.plus(size.mult(0.5));
	}
	Vec getTopRight() {
		return pos.plus(Vec(size.x, 0.0));
	}
	Vec getBottomLeft() {
		return pos.plus(Vec(0.0, size.y));
	}
	Vec getBottomRight() {
		return pos.plus(size);
	}
	/** Clamps the position to fix inside a bounding box */
	Rect clamp(Rect bound) {
		Rect r;
		r.size = size;
		r.pos.x = clampf(pos.x, bound.pos.x, bound.pos.x + bound.size.x - size.x);
		r.pos.y = clampf(pos.y, bound.pos.y, bound.pos.y + bound.size.y - size.y);
		return r;
	}
};

} // namespace rack
<commit_msg>Fix flicker again<commit_after>#pragma once

#include <math.h>

namespace rack {

////////////////////
// integer functions
////////////////////

inline int mini(int a, int b) {
	return a < b ? a : b;
}

inline int maxi(int a, int b) {
	return a > b ? a : b;
}

/** Limits a value between a minimum and maximum */
inline int clampi(int x, int min, int max) {
	return x > max ? max : x < min ? min : x;
}

inline int absi(int a) {
	return a >= 0 ? a : -a;
}

// Euclidean modulus, always returns 0 <= mod < base for positive base
// Assumes this architecture's division is non-Euclidean
inline int eucmodi(int a, int base) {
	int mod = a % base;
	return mod < 0 ? mod + base : mod;
}

inline int log2i(int n) {
	int i = 0;
	while (n >>= 1) {
		i++;
	}
	return i;
}

inline bool ispow2i(int n) {
	return n > 0 && (n & (n - 1)) == 0;
}

////////////////////
// float functions
////////////////////

/** Returns 1.0 for positive numbers and -1.0 for negative numbers (including positive/negative zero) */
inline float sgnf(float x) {
	return copysignf(1.0, x);
}

inline float eucmodf(float a, float base) {
	float mod = fmodf(a, base);
	return mod < 0.0 ? mod + base : mod;
}

/** Limits a value between a minimum and maximum
If min < max, returns max
*/
inline float clampf(float x, float min, float max) {
	return fmaxf(fminf(x, max), min);
}

/** If the magnitude of x if less than eps, return 0 */
inline float chopf(float x, float eps) {
	return -eps < x && x < eps ? 0.0 : x;
}

inline float rescalef(float x, float xMin, float xMax, float yMin, float yMax) {
	return yMin + (x - xMin) / (xMax - xMin) * (yMax - yMin);
}

inline float crossf(float a, float b, float frac) {
	return (1.0 - frac) * a + frac * b;
}

inline float quadraticBipolar(float x) {
	float x2 = x*x;
	return x >= 0.0 ? x2 : -x2;
}

inline float cubic(float x) {
	return x*x*x;
}

inline float quarticBipolar(float x) {
	return x >= 0.0 ? x*x*x*x : -x*x*x*x;
}

inline float quintic(float x) {
	// optimal with --fast-math
	return x*x*x*x*x;
}

inline float sqrtBipolar(float x) {
	return x >= 0.0 ? sqrtf(x) : -sqrtf(-x);
}

/** This is pretty much a scaled sinh */
inline float exponentialBipolar(float b, float x) {
	const float a = b - 1.0 / b;
	return (powf(b, x) - powf(b, -x)) / a;
}

inline float sincf(float x) {
	if (x == 0.0)
		return 1.0;
	x *= M_PI;
	return sinf(x) / x;
}

inline float getf(const float *p, float v = 0.0) {
	return p ? *p : v;
}

inline void setf(float *p, float v) {
	if (p)
		*p = v;
}

/** Linearly interpolate an array `p` with index `x`
Assumes that the array at `p` is of length at least floor(x)+1.
*/
inline float interpf(const float *p, float x) {
	int xi = x;
	float xf = x - xi;
	return crossf(p[xi], p[xi+1], xf);
}

/** Complex multiply c = a * b
It is of course acceptable to reuse arguments
i.e. cmultf(&ar, &ai, ar, ai, br, bi)
*/
inline void cmultf(float *cr, float *ci, float ar, float ai, float br, float bi) {
	*cr = ar * br - ai * bi;
	*ci = ar * bi + ai * br;
}

////////////////////
// 2D float vector
////////////////////

struct Vec {
	float x, y;

	Vec() : x(0.0), y(0.0) {}
	Vec(float x, float y) : x(x), y(y) {}

	Vec neg() {
		return Vec(-x, -y);
	}
	Vec plus(Vec b) {
		return Vec(x + b.x, y + b.y);
	}
	Vec minus(Vec b) {
		return Vec(x - b.x, y - b.y);
	}
	Vec mult(float s) {
		return Vec(x * s, y * s);
	}
	Vec div(float s) {
		return Vec(x / s, y / s);
	}
	float dot(Vec b) {
		return x * b.x + y * b.y;
	}
	float norm() {
		return hypotf(x, y);
	}
	Vec min(Vec b) {
		return Vec(fminf(x, b.x), fminf(y, b.y));
	}
	Vec max(Vec b) {
		return Vec(fmaxf(x, b.x), fmaxf(y, b.y));
	}
	Vec round() {
		return Vec(roundf(x), roundf(y));
	}
	bool isZero() {
		return x == 0.0 && y == 0.0;
	}
};

struct Rect {
	Vec pos;
	Vec size;

	Rect() {}
	Rect(Vec pos, Vec size) : pos(pos), size(size) {}
	static Rect fromMinMax(Vec min, Vec max) {
		return Rect(min, max.minus(min));
	}

	/** Returns whether this Rect contains another Rect, inclusive on the top/left, non-inclusive on the bottom/right */
	bool contains(Vec v) {
		return pos.x <= v.x && v.x < pos.x + size.x
			&& pos.y <= v.y && v.y < pos.y + size.y;
	}
	/** Returns whether this Rect overlaps with another Rect */
	bool intersects(Rect r) {
		return (pos.x + size.x > r.pos.x && r.pos.x + r.size.x > pos.x)
			&& (pos.y + size.y > r.pos.y && r.pos.y + r.size.y > pos.y);
	}
	Vec getCenter() {
		return pos.plus(size.mult(0.5));
	}
	Vec getTopRight() {
		return pos.plus(Vec(size.x, 0.0));
	}
	Vec getBottomLeft() {
		return pos.plus(Vec(0.0, size.y));
	}
	Vec getBottomRight() {
		return pos.plus(size);
	}
	/** Clamps the position to fix inside a bounding box */
	Rect clamp(Rect bound) {
		Rect r;
		r.size = size;
		r.pos.x = clampf(pos.x, bound.pos.x, bound.pos.x + bound.size.x - size.x);
		r.pos.y = clampf(pos.y, bound.pos.y, bound.pos.y + bound.size.y - size.y);
		return r;
	}
};

} // namespace rack
<|endoftext|>


<commit_before>/**
* * \file main.cpp
* \brief test/demo program
* \author Arthur Brainville
*
* Annwvyn test program http://annwvyn.org/
*
*/
#include "stdafx.h"

//Annwvyn
#include <Annwvyn.h>
#include <Ann3DTextPlane.hpp>
#include "TestLevel.hpp"
#include "DemoLevel.hpp"

using namespace std;
using namespace Annwvyn;

timerID demoTimer;

class MySaveTest : public AnnSaveDataInterpretor
{
public:
	MySaveTest(std::shared_ptr<AnnSaveFileData> data) : AnnSaveDataInterpretor(data),
	pi(0),
	lives(0)
	{
	}

	AnnVect3 getPosition()
	{
		return pos;
	}

	AnnQuaternion getOrientation()
	{
		return orient;
	}

	float getPi()
	{
		return pi;
	}

	int getLives()
	{
		return lives;
	}

	virtual void extract()
	{
		pos = keyStringToVect3("pos");
		orient = keyStringToQuaternion("orient");
		pi = keyStringToFloat("PI");
		lives = keyStringToInt("lives");
	}
private:
	AnnVect3 pos;
	AnnQuaternion orient;
	float pi;
	int lives;
};

class DebugListener : LISTENER
{
public:
	DebugListener() : constructListener()
	{
	}

	void TimeEvent(AnnTimeEvent e)
	{
		AnnDebug() << "TimeEvent id : " << e.getID();
		if(e.getID() == demoTimer)
			AnnDebug() << "This is the demoTimer that was launched on the main function !";
	}
	void TriggerEvent(AnnTriggerEvent e)
	{
		AnnDebug() << "TriggerEvent contact status : " << e.getContactStatus() << " from " << e.getSender();
	}

	void testFileIO()
	{
		auto testFile = AnnGetFileSystemManager()->crateSaveFileDataObject("test");
		testFile->setValue("KEY0", "Thing");
		testFile->setValue("KEY1", "otherThing");
		testFile->setValue("lives", 10);
		testFile->setValue("PI", 3.14f);
		testFile->setValue("pos", AnnVect3(2.5, 4.8, Ogre::Math::HALF_PI));
		testFile->setValue("orient", AnnQuaternion(AnnDegree(90), AnnVect3(.5, .5, .5)));

		auto writer(AnnGetFileSystemManager()->getFileWriter());
		writer->write(testFile);

		auto reader(AnnGetFileSystemManager()->getFileReader());
		auto data = reader->read("test");

		AnnDebug() << "KEY0 val : " << data->getValue("KEY0");
		AnnDebug() << "KEY1 val : " << data->getValue("KEY1");

		MySaveTest tester(data);
		tester.extract();
		AnnDebug() << "stored vector value : " << tester.getPosition();
		AnnDebug() << "stored quaternion value : " << tester.getOrientation();
		AnnDebug() << "stored pi value : " << tester.getPi();
		AnnDebug() << "stored lives value : " << tester.getLives();

	}

	void KeyEvent(AnnKeyEvent e)
	{
		if (e.isPressed() && e.getKey() == KeyCode::h)
			testFileIO();
	}

	void StickEvent(AnnStickEvent e)
	{
		if (e.getStickID() == 0)
		{
			AnnStickPov pov = e.getPov(0);
		//	AnnDebug() << pov.getNorth() << pov.getSouth() << pov.getEast() << pov.getWest();
		}
	}
};

class DummySubsystem : public AnnUserSubSystem
{
public:
	DummySubsystem(std::string name = "Dummy") : AnnUserSubSystem(name),
		call(0)
	{

	}

	virtual ~DummySubsystem()
	{
		AnnDebug() << "Dummy is no more. ";
	}

	void dummyMethod()
	{
		AnnDebug() << "access from smart poiner casted through the stupid macro ACTUALLY WORKS!";
	}

protected:
	bool needUpdate()
	{
		return true;
	}

	void update()
	{
		AnnDebug() << "Dummy debug " << ++call;;
	}
	unsigned long call;
};

AnnMain()
{
	//Only usefull on windows : Open a debug console to get stdout/stderr
	AnnEngine::openConsole();

	AnnInit("AnnTest");

	//Init some player body parameters
	AnnGetEngine()->initPlayerPhysics();
	AnnGetPhysicsEngine()->setDebugPhysics(false);
	AnnGetEventManager()->useDefaultEventListener();
	AnnGetVRRenderer()->recenter();

	//load ressources
	AnnGetResourceManager()->loadDir("media/environement");
	AnnGetResourceManager()->loadDir("media/debug");
	AnnGetResourceManager()->initResources();

	//AnnGetLevelManager()->addLevel(make_shared<TestLevel>());
	AnnGetLevelManager()->addLevel(make_shared<DemoHub>());
	AnnGetLevelManager()->addLevel(make_shared<Demo0>());

	AnnGetLevelManager()->jump(AnnGetLevelManager()->getFirstLevelLoaded());

	AnnRadian(Ogre::Degree(90));
	AnnDegree(Ogre::Radian(3.14));
	AnnDebug() << "Starting the render loop";
	do
	{
		if(AnnGetEngine()->isKeyDown(OIS::KC_Q))
			AnnGetEngine()->getLevelManager()->unloadCurrentLevel();
		if(AnnGetEngine()->isKeyDown(OIS::KC_E))
			AnnGetEngine()->getLevelManager()->jumpToFirstLevel();
	}
	while(AnnGetEngine()->refresh());

	AnnQuit();

	return EXIT_SUCCESS;
}
<commit_msg>minor removal of stuff from the main funciton<commit_after>/**
* * \file main.cpp
* \brief test/demo program
* \author Arthur Brainville
*
* Annwvyn test program http://annwvyn.org/
*
*/
#include "stdafx.h"

//Annwvyn
#include <Annwvyn.h>
#include <Ann3DTextPlane.hpp>
#include "TestLevel.hpp"
#include "DemoLevel.hpp"

using namespace std;
using namespace Annwvyn;

timerID demoTimer;

class MySaveTest : public AnnSaveDataInterpretor
{
public:
	MySaveTest(std::shared_ptr<AnnSaveFileData> data) : AnnSaveDataInterpretor(data),
	pi(0),
	lives(0)
	{
	}

	AnnVect3 getPosition()
	{
		return pos;
	}

	AnnQuaternion getOrientation()
	{
		return orient;
	}

	float getPi()
	{
		return pi;
	}

	int getLives()
	{
		return lives;
	}

	virtual void extract()
	{
		pos = keyStringToVect3("pos");
		orient = keyStringToQuaternion("orient");
		pi = keyStringToFloat("PI");
		lives = keyStringToInt("lives");
	}
private:
	AnnVect3 pos;
	AnnQuaternion orient;
	float pi;
	int lives;
};

class DebugListener : LISTENER
{
public:
	DebugListener() : constructListener()
	{
	}

	void TimeEvent(AnnTimeEvent e)
	{
		AnnDebug() << "TimeEvent id : " << e.getID();
		if(e.getID() == demoTimer)
			AnnDebug() << "This is the demoTimer that was launched on the main function !";
	}
	void TriggerEvent(AnnTriggerEvent e)
	{
		AnnDebug() << "TriggerEvent contact status : " << e.getContactStatus() << " from " << e.getSender();
	}

	void testFileIO()
	{
		auto testFile = AnnGetFileSystemManager()->crateSaveFileDataObject("test");
		testFile->setValue("KEY0", "Thing");
		testFile->setValue("KEY1", "otherThing");
		testFile->setValue("lives", 10);
		testFile->setValue("PI", 3.14f);
		testFile->setValue("pos", AnnVect3(2.5, 4.8, Ogre::Math::HALF_PI));
		testFile->setValue("orient", AnnQuaternion(AnnDegree(90), AnnVect3(.5, .5, .5)));

		auto writer(AnnGetFileSystemManager()->getFileWriter());
		writer->write(testFile);

		auto reader(AnnGetFileSystemManager()->getFileReader());
		auto data = reader->read("test");

		AnnDebug() << "KEY0 val : " << data->getValue("KEY0");
		AnnDebug() << "KEY1 val : " << data->getValue("KEY1");

		MySaveTest tester(data);
		tester.extract();
		AnnDebug() << "stored vector value : " << tester.getPosition();
		AnnDebug() << "stored quaternion value : " << tester.getOrientation();
		AnnDebug() << "stored pi value : " << tester.getPi();
		AnnDebug() << "stored lives value : " << tester.getLives();

	}

	void KeyEvent(AnnKeyEvent e)
	{
		if (e.isPressed() && e.getKey() == KeyCode::h)
			testFileIO();
	}

	void StickEvent(AnnStickEvent e)
	{
		if (e.getStickID() == 0)
		{
			AnnStickPov pov = e.getPov(0);
		//	AnnDebug() << pov.getNorth() << pov.getSouth() << pov.getEast() << pov.getWest();
		}
	}
};

class DummySubsystem : public AnnUserSubSystem
{
public:
	DummySubsystem(std::string name = "Dummy") : AnnUserSubSystem(name),
		call(0)
	{

	}

	virtual ~DummySubsystem()
	{
		AnnDebug() << "Dummy is no more. ";
	}

	void dummyMethod()
	{
		AnnDebug() << "access from smart poiner casted through the stupid macro ACTUALLY WORKS!";
	}

protected:
	bool needUpdate()
	{
		return true;
	}

	void update()
	{
		AnnDebug() << "Dummy debug " << ++call;;
	}
	unsigned long call;
};

AnnMain()
{
	//Only usefull on windows : Open a debug console to get stdout/stderr
	AnnEngine::openConsole();

	AnnInit("AnnTest");

	//Init some player body parameters
	AnnGetEngine()->initPlayerPhysics();
	AnnGetPhysicsEngine()->setDebugPhysics(false);
	AnnGetEventManager()->useDefaultEventListener();
	AnnGetVRRenderer()->recenter();

	//load ressources
	AnnGetResourceManager()->loadDir("media/environement");
	AnnGetResourceManager()->loadDir("media/debug");
	AnnGetResourceManager()->initResources();

	//AnnGetLevelManager()->addLevel(make_shared<TestLevel>());
	AnnGetLevelManager()->addLevel(make_shared<DemoHub>());
	AnnGetLevelManager()->addLevel(make_shared<Demo0>());

	AnnGetLevelManager()->jump(AnnGetLevelManager()->getFirstLevelLoaded());

	AnnDebug() << "Starting the render loop";
	do
	{
		//This is just for debugging stuff with the level manager
		if(AnnGetEngine()->isKeyDown(OIS::KC_Q))
			AnnGetEngine()->getLevelManager()->unloadCurrentLevel();
		if(AnnGetEngine()->isKeyDown(OIS::KC_E))
			AnnGetEngine()->getLevelManager()->jumpToFirstLevel();
	}
	while(AnnGetEngine()->refresh());

	AnnQuit();

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "app/SimpleApp.h"
#include "sys/AbstractThread.h"
#include "sys/StopWatch.h"
#include "trace/log.h"
#include "trace/UdpBackEnd.h"

namespace
{
    class Th1 : public ::sys::AbstractThread
    {
    public:
        explicit Th1( const uint32_t id )
            : ::sys::AbstractThread( ::std::to_string( id ) )
            , m_char( 'A' + id )
        {
        }

    private:
        virtual void run()
        {
            uint32_t i = 200;
            while ( i != 0U )
            {
                if ( isStopRequested() )
                {
                    LOG_DEV_C( "Thread '%c' requested to stop on i = %u", m_char, i );
                    break;
                }

                LOG_INFO_C( "TH: %c, i = %u", m_char, i );
                sleep( 50 + ( m_char * 2U ) );
                --i;
            }
        }

        const char m_char;
    };
}

class DemoApp : public ::app::SimpleApp
{
public:
    DemoApp()
        : ::app::SimpleApp( "TraceLogDemo" )
    {

    }

private:
    virtual int32_t onRun( const TStringVector& args )
    {
        const size_t NUM_TH = 26U;

        ::sys::StopWatch sw( true );

        Th1* threads[ NUM_TH ];

        for ( size_t i = 0U; i < NUM_TH; i++ )
        {
            threads[ i ] = new Th1( i );
            threads[ i ]->start();
        }

        //LOG_ASSERT( false, "poop!" );

        if ( waitForExit( 15000U ) )
        {
            LOG_INFO_C( "Example running until end" );
        }
        else
        {
            LOG_WARN_C( "Example Timeout" );
        }

        for ( size_t i = 0U; i < NUM_TH; i++ )
        {
            threads[ i ]->requestStop();
            threads[ i ]->join();

            delete threads[ i ];
        }

        LOG_INFO_C( "Took: %u", sw.stop() );

        return 0;
    }
};

int32_t main( int argc, const char * const * argv )
{
    LOGGER_INIT_BE_FILE;

    LOG_INFO_C( "App Started: %c", 'a' );
    int32_t result = ::DemoApp().run( argc, argv );
    LOG_INFO_C( "App Exited: %d" , result );
    LOG_INFO_C( "- bye! -" );

    LOGGER_SHUTDOWN();

    return result;
}
<commit_msg>Apply changes according to the ESys API modifications<commit_after>#include "app/SimpleApp.h"
#include "sys/AbstractThread.h"
#include "sys/StopWatch.h"
#include "trace/log.h"
#include "trace/UdpBackEnd.h"

namespace
{
    class Th1 : public ::sys::AbstractThread
    {
    public:
        explicit Th1( const uint32_t id )
            : ::sys::AbstractThread( ::std::to_string( id ).c_str() )
            , m_char( 'A' + id )
        {
        }

    private:
        virtual void run()
        {
            uint32_t i = 200;
            while ( i != 0U )
            {
                if ( isStopRequested() )
                {
                    LOG_DEV_C( "Thread '%c' requested to stop on i = %u", m_char, i );
                    break;
                }

                LOG_INFO_C( "TH: %c, i = %u", m_char, i );
                sleep( 50 + ( m_char * 2U ) );
                --i;
            }
        }

        const char m_char;
    };
}

class DemoApp : public ::app::SimpleApp
{
public:
    DemoApp()
        : ::app::SimpleApp( "TraceLogDemo" )
    {

    }

private:
    virtual int32_t onRun( const TStringVector& args )
    {
        const size_t NUM_TH = 26U;

        ::sys::StopWatch sw( true );

        Th1* threads[ NUM_TH ];

        for ( size_t i = 0U; i < NUM_TH; i++ )
        {
            threads[ i ] = new Th1( i );
            threads[ i ]->start();
        }

        //LOG_ASSERT( false, "poop!" );

        if ( waitForExit( 15000U ) )
        {
            LOG_INFO_C( "Example running until end" );
        }
        else
        {
            LOG_WARN_C( "Example Timeout" );
        }

        for ( size_t i = 0U; i < NUM_TH; i++ )
        {
            threads[ i ]->requestStop();
            threads[ i ]->join();

            delete threads[ i ];
        }

        LOG_INFO_C( "Took: %u", sw.stop() );

        return 0;
    }
};

int32_t main( int argc, const char * const * argv )
{
    LOGGER_INIT_BE_UDP;

    LOG_INFO_C( "App Started: %c", 'a' );
    int32_t result = ::DemoApp().run( argc, argv );
    LOG_INFO_C( "App Exited: %d" , result );
    LOG_INFO_C( "- bye! -" );

    LOGGER_SHUTDOWN();

    return result;
}
<|endoftext|>


<commit_before>/* -----------------------------------------------------------------------------
Copyright 2017 Google Inc.

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.
----------------------------------------------------------------------------- */

// Author: Kevin P. Barry [ta0kira@gmail.com] [kevinbarry@google.com]

#include <cassert>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include "thread-capture.h"

using capture_thread::ThreadCapture;

// A helper class for building paths from components.
class PathBuilder {
 public:
  std::string String() const { return path_.str(); }

  PathBuilder& Add(const std::string& component) {
    if (!component.empty()) {
      if (component.front() == '/') {
        path_.str("");
        path_ << component;
      } else {
        if (!trailing_slash_) {
          path_ << '/';
        }
        path_ << component;
      }
      trailing_slash_ = component.back() == '/';
    }
    return *this;
  }

 private:
  bool trailing_slash_ = true;
  std::ostringstream path_;
};

// Tracks persistent root and local paths.
class Path : public ThreadCapture<Path> {
 public:
  static std::string Root() {
    if (GetCurrent()) {
      return GetCurrent()->RootPath();
    } else {
      return "";
    }
  }

  static std::string Working() {
    if (GetCurrent()) {
      PathBuilder builder;
      builder.Add(Root());
      GetCurrent()->AppendLocalPath(&builder);
      return builder.String();
    } else {
      return Root();
    }
  }

 protected:
  virtual std::string RootPath() const = 0;
  virtual void AppendLocalPath(PathBuilder* builder) const = 0;

  static std::string DelegateRootPath(const Path& path) {
    return path.RootPath();
  }

  static void DelegateLocalPath(const Path& path, PathBuilder* builder) {
    path.AppendLocalPath(builder);
  }
};

// Sets the root path, which persists while the instance is in scope.
class InRootPath : public Path {
 public:
  InRootPath(const std::string& root_path)
      : root_path_(root_path), capture_to_(this) {}

 protected:
  std::string RootPath() const override { return root_path_; }

  void AppendLocalPath(PathBuilder* builder) const override {
    assert(builder);
    const auto previous = capture_to_.Previous();
    if (previous) {
      DelegateLocalPath(*previous, builder);
    }
  }

 private:
  const std::string root_path_;
  const ScopedCapture capture_to_;
};

// Sets the local path relative to the current root + local path.
class InLocalPath : public Path {
 public:
  InLocalPath(const std::string& local_path)
      : local_path_(local_path), capture_to_(this) {}

 protected:
  std::string RootPath() const override {
    const auto previous = capture_to_.Previous();
    return previous ? DelegateRootPath(*previous) : "";
  }

  void AppendLocalPath(PathBuilder* builder) const override {
    assert(builder);
    const auto previous = capture_to_.Previous();
    if (previous) {
      DelegateLocalPath(*previous, builder);
    }
    builder->Add(local_path_);
  }

 private:
  const std::string local_path_;
  const ScopedCapture capture_to_;
};

// Simulates installing project binaries.
void InstallBin(const std::vector<std::string>& targets) {
  InLocalPath file("bin");
  for (const auto& target : targets) {
    InLocalPath file(target);
    std::cerr << "Installing binary " << Path::Working() << std::endl;
  }
}

// Simulates installing project libraries.
void InstallLib(const std::vector<std::string>& targets) {
  InLocalPath file("lib");
  for (const auto& target : targets) {
    InLocalPath file(target);
    std::cerr << "Installing library " << Path::Working() << std::endl;
  }
}

// Simulates installing the project.
void InstallProjectIn(const std::string& path) {
  InRootPath root(path);
  std::cerr << "Installing project in " << Path::Root() << std::endl;
  InstallBin({"binary1", "binary2"});
  InstallLib({"lib1.so", "lib2.so"});
}

int main() { InstallProjectIn("/usr/local"); }
<commit_msg>Trivial fixes to paths example.<commit_after>/* -----------------------------------------------------------------------------
Copyright 2017 Google Inc.

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.
----------------------------------------------------------------------------- */

// Author: Kevin P. Barry [ta0kira@gmail.com] [kevinbarry@google.com]

#include <cassert>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include "thread-capture.h"

using capture_thread::ThreadCapture;

// A helper class for building paths from components.
class PathBuilder {
 public:
  std::string String() const { return path_.str(); }

  PathBuilder& Add(const std::string& component) {
    if (!component.empty()) {
      if (component.front() == '/') {
        path_.str("");
        path_ << component;
      } else {
        if (!trailing_slash_) {
          path_ << '/';
        }
        path_ << component;
      }
      trailing_slash_ = component.back() == '/';
    }
    return *this;
  }

 private:
  bool trailing_slash_ = true;
  std::ostringstream path_;
};

// Tracks persistent root and local paths.
class Path : public ThreadCapture<Path> {
 public:
  static std::string Root() {
    if (GetCurrent()) {
      return GetCurrent()->RootPath();
    } else {
      return "";
    }
  }

  static std::string Working() {
    if (GetCurrent()) {
      PathBuilder builder;
      builder.Add(Root());
      GetCurrent()->AppendLocalPath(&builder);
      return builder.String();
    } else {
      return Root();
    }
  }

 protected:
  virtual std::string RootPath() const = 0;
  virtual void AppendLocalPath(PathBuilder* builder) const = 0;

  static std::string DelegateRootPath(const Path& path) {
    return path.RootPath();
  }

  static void DelegateLocalPath(const Path& path, PathBuilder* builder) {
    path.AppendLocalPath(builder);
  }
};

// Sets the root path, which persists while the instance is in scope.
class InRootPath : public Path {
 public:
  InRootPath(const std::string& root_path)
      : root_path_(root_path), capture_to_(this) {}

 protected:
  std::string RootPath() const override { return root_path_; }

  void AppendLocalPath(PathBuilder* builder) const override {
    const auto previous = capture_to_.Previous();
    if (previous) {
      DelegateLocalPath(*previous, builder);
    }
  }

 private:
  const std::string root_path_;
  const ScopedCapture capture_to_;
};

// Sets the local path relative to the current root + local path.
class InLocalPath : public Path {
 public:
  InLocalPath(const std::string& local_path)
      : local_path_(local_path), capture_to_(this) {}

 protected:
  std::string RootPath() const override {
    const auto previous = capture_to_.Previous();
    return previous ? DelegateRootPath(*previous) : "";
  }

  void AppendLocalPath(PathBuilder* builder) const override {
    assert(builder);
    const auto previous = capture_to_.Previous();
    if (previous) {
      DelegateLocalPath(*previous, builder);
    }
    builder->Add(local_path_);
  }

 private:
  const std::string local_path_;
  const ScopedCapture capture_to_;
};

// Simulates installing project binaries.
void InstallBin(const std::vector<std::string>& targets) {
  InLocalPath path("bin");
  for (const auto& target : targets) {
    InLocalPath file(target);
    std::cerr << "Installing binary " << Path::Working() << std::endl;
  }
}

// Simulates installing project libraries.
void InstallLib(const std::vector<std::string>& targets) {
  InLocalPath path("lib");
  for (const auto& target : targets) {
    InLocalPath file(target);
    std::cerr << "Installing library " << Path::Working() << std::endl;
  }
}

// Simulates installing the project.
void InstallProjectIn(const std::string& path) {
  InRootPath root(path);
  std::cerr << "Installing project in " << Path::Root() << std::endl;
  InstallBin({"binary1", "binary2"});
  InstallLib({"lib1.so", "lib2.so"});
}

int main() { InstallProjectIn("/usr/local"); }
<|endoftext|>


<commit_before>namespace mant {
  namespace bbob2009 {
    class CompositeGriewankRosenbrockFunctionF8F2 : public BlackBoxOptimisationBenchmark2009 {
      public:
        inline explicit CompositeGriewankRosenbrockFunctionF8F2(
            const unsigned int numberOfDimensions) noexcept;

        inline std::string toString() const noexcept override;

      protected:
        inline double getObjectiveValueImplementation(
            const arma::Col<double>& parameter) const noexcept override;

#if defined(MANTELLA_USE_PARALLEL)
        friend class cereal::access;

        template <typename Archive>
        void serialize(
            Archive& archive) noexcept {
          archive(cereal::make_nvp("BlackBoxOptimisationBenchmark2009", cereal::base_class<BlackBoxOptimisationBenchmark2009>(this)));
          archive(cereal::make_nvp("numberOfDimensions", numberOfDimensions_));
        }

        template <typename Archive>
        static void load_and_construct(
            Archive& archive,
            cereal::construct<CompositeGriewankRosenbrockFunctionF8F2>& construct) noexcept {
          unsigned int numberOfDimensions;
          archive(cereal::make_nvp("numberOfDimensions", numberOfDimensions));
          construct(numberOfDimensions);

          archive(cereal::make_nvp("BlackBoxOptimisationBenchmark2009", cereal::base_class<BlackBoxOptimisationBenchmark2009>(construct.ptr())));
        }
#endif
    };

    //
    // Implementation
    //

    inline CompositeGriewankRosenbrockFunctionF8F2::CompositeGriewankRosenbrockFunctionF8F2(
        const unsigned int numberOfDimensions) noexcept
      : BlackBoxOptimisationBenchmark2009(numberOfDimensions),
        max_(std::max(1.0, std::sqrt(static_cast<double>(numberOfDimensions_)) / 8.0)) {
      setParameterRotation(getRandomRotationMatrix(numberOfDimensions_));
    }

    inline void CompositeGriewankRosenbrockFunctionF8F2::setParameterRotationR(
        const arma::Mat<double>& parameterRotationR) {
      isEqual("The number of rows", parameterRotationR.n_rows, "the number of dimensions", numberOfDimensions_);
      isRotationMatrix("The matrix", parameterRotationR);

      parameterRotationR_ = parameterRotationR;
    }

    inline double CompositeGriewankRosenbrockFunctionF8F2::getObjectiveValueImplementation(
        const arma::Col<double>& parameter) const noexcept {
      const arma::Col<double>& z = 100.0 * arma::square(arma::square(parameter.head(parameter.n_elem - 1)) - parameter.tail(parameter.n_elem - 1)) + arma::square(1.0 - parameter.head(parameter.n_elem - 1));

      return 10.0 * (arma::mean(z / 4000.0 - arma::cos(z)) + 1);
    }

    inline std::string CompositeGriewankRosenbrockFunctionF8F2::toString() const noexcept {
      return "bbob2009_composite_griewank_rosenbrock_function_f8f2";
    }
  }
}

#if defined(MANTELLA_USE_PARALLEL)
CEREAL_REGISTER_TYPE(mant::bbob2009::CompositeGriewankRosenbrockFunctionF8F2);
#endif
<commit_msg>Use scaling and translation within the composite Griewank-Rosenbrock function f8f2<commit_after>namespace mant {
  namespace bbob2009 {
    class CompositeGriewankRosenbrockFunctionF8F2 : public BlackBoxOptimisationBenchmark2009 {
      public:
        inline explicit CompositeGriewankRosenbrockFunctionF8F2(
            const unsigned int numberOfDimensions) noexcept;

        inline std::string toString() const noexcept override;

      protected:
        inline double getObjectiveValueImplementation(
            const arma::Col<double>& parameter) const noexcept override;

#if defined(MANTELLA_USE_PARALLEL)
        friend class cereal::access;

        template <typename Archive>
        void serialize(
            Archive& archive) noexcept {
          archive(cereal::make_nvp("BlackBoxOptimisationBenchmark2009", cereal::base_class<BlackBoxOptimisationBenchmark2009>(this)));
          archive(cereal::make_nvp("numberOfDimensions", numberOfDimensions_));
        }

        template <typename Archive>
        static void load_and_construct(
            Archive& archive,
            cereal::construct<CompositeGriewankRosenbrockFunctionF8F2>& construct) noexcept {
          unsigned int numberOfDimensions;
          archive(cereal::make_nvp("numberOfDimensions", numberOfDimensions));
          construct(numberOfDimensions);

          archive(cereal::make_nvp("BlackBoxOptimisationBenchmark2009", cereal::base_class<BlackBoxOptimisationBenchmark2009>(construct.ptr())));
        }
#endif
    };

    //
    // Implementation
    //

    inline CompositeGriewankRosenbrockFunctionF8F2::CompositeGriewankRosenbrockFunctionF8F2(
        const unsigned int numberOfDimensions) noexcept
      : BlackBoxOptimisationBenchmark2009(numberOfDimensions) {
      // A vector with all elements set to max(1, numberOfDimensions / 8).
      setParameterScaling(arma::zeros<arma::Col<ParameterType>>(numberOfDimensions_) + std::max(1.0, std::sqrt(static_cast<double>(numberOfDimensions_)) / 8.0));
      // A vector with all elements set to 0.5.
      setParameterTranslation(arma::zeros<arma::Col<ParameterType>>(numberOfDimensions_) + 0.5);
      setParameterRotation(getRandomRotationMatrix(numberOfDimensions_));
    }

    inline void CompositeGriewankRosenbrockFunctionF8F2::setParameterRotationR(
        const arma::Mat<double>& parameterRotationR) {
      isEqual("The number of rows", parameterRotationR.n_rows, "the number of dimensions", numberOfDimensions_);
      isRotationMatrix("The matrix", parameterRotationR);

      parameterRotationR_ = parameterRotationR;
    }

    inline double CompositeGriewankRosenbrockFunctionF8F2::getObjectiveValueImplementation(
        const arma::Col<double>& parameter) const noexcept {
      const arma::Col<double>& z = 100.0 * arma::square(arma::square(parameter.head(parameter.n_elem - 1)) - parameter.tail(parameter.n_elem - 1)) + arma::square(1.0 - parameter.head(parameter.n_elem - 1));

      return 10.0 * (arma::mean(z / 4000.0 - arma::cos(z)) + 1);
    }

    inline std::string CompositeGriewankRosenbrockFunctionF8F2::toString() const noexcept {
      return "bbob2009_composite_griewank_rosenbrock_function_f8f2";
    }
  }
}

#if defined(MANTELLA_USE_PARALLEL)
CEREAL_REGISTER_TYPE(mant::bbob2009::CompositeGriewankRosenbrockFunctionF8F2);
#endif
<|endoftext|>