<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 *
 * 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 "DeviceKey.h"
#include "mbedtls/config.h"
#include "mbedtls/cmac.h"
#include "nvstore.h"
#include "trng_api.h"
#include "mbed_wait_api.h"
#include "stdlib.h"

#if !defined(MBEDTLS_CMAC_C)
#error [NOT_SUPPORTED] MBEDTLS_CMAC_C needs to be enabled for this driver
#else

#if NVSTORE_ENABLED

namespace mbed {

#define DEVKEY_WRITE_UINT32_LE( dst, src )                              \
    do                                                                  \
    {                                                                   \
        (dst)[0] = ( (src) >> 0 ) & 0xFF;                               \
        (dst)[1] = ( (src) >> 8 ) & 0xFF;                               \
        (dst)[2] = ( (src) >> 16 ) & 0xFF;                              \
        (dst)[3] = ( (src) >> 24 ) & 0xFF;                              \
    } while( 0 )

#define DEVKEY_WRITE_UINT8_LE( dst, src )                               \
    do                                                                  \
    {                                                                   \
        (dst)[0] = (src) & 0xFF;                                        \
    } while( 0 )

DeviceKey::DeviceKey()
{
    return;
}

DeviceKey::~DeviceKey()
{
    return;
}

int DeviceKey::generate_derived_key(const unsigned char *salt, size_t isalt_size, unsigned char *output,
                                    uint16_t ikey_type)
{
    uint32_t key_buff[DEVICE_KEY_32BYTE / sizeof(uint32_t)];
    size_t actual_size = DEVICE_KEY_32BYTE;

    if (DEVICE_KEY_16BYTE != ikey_type && DEVICE_KEY_32BYTE != ikey_type) {
        return DEVICEKEY_INVALID_KEY_TYPE;
    }

    //First try to read the key from NVStore
    int ret = read_key_from_nvstore(key_buff, actual_size);
    if (DEVICEKEY_SUCCESS != ret && DEVICEKEY_NOT_FOUND != ret) {
        return ret;
    }

    if (DEVICE_KEY_16BYTE != actual_size && DEVICE_KEY_32BYTE != actual_size) {
        return DEVICEKEY_READ_FAILED;
    }

    //If the key was not found in NVStore we will create it by using TRNG and then save it to NVStore
    if (DEVICEKEY_NOT_FOUND == ret) {
        ret = generate_key_by_trng(key_buff, actual_size);
        if (DEVICEKEY_SUCCESS != ret) {
            return ret;
        }

        ret = device_inject_root_of_trust(key_buff, actual_size);
        if (DEVICEKEY_SUCCESS != ret) {
            return ret;
        }
    }

    ret = get_derived_key(key_buff, actual_size, salt, isalt_size, output, ikey_type);
    return ret;
}

int DeviceKey::device_inject_root_of_trust(uint32_t *value, size_t isize)
{
    return write_key_to_nvstore(value, isize);
}

int DeviceKey::write_key_to_nvstore(uint32_t *input, size_t isize)
{
    if (DEVICE_KEY_16BYTE != isize && DEVICE_KEY_32BYTE != isize) {
        return DEVICEKEY_INVALID_KEY_SIZE;
    }

    //First we read if key exist. If it is exists, we return DEVICEKEY_ALREADY_EXIST error
    uint32_t read_key[DEVICE_KEY_32BYTE / sizeof(uint32_t)] = {0};
    size_t read_size = DEVICE_KEY_32BYTE;
    int ret = read_key_from_nvstore(read_key, read_size);
    if (DEVICEKEY_SUCCESS == ret) {
        return DEVICEKEY_ALREADY_EXIST;
    }
    if (DEVICEKEY_NOT_FOUND != ret) {
        return ret;
    }

    NVStore& nvstore = NVStore::get_instance();
    ret = nvstore.set(NVSTORE_DEVICEKEY_KEY, (uint16_t)isize, input);
    if (NVSTORE_WRITE_ERROR == ret || NVSTORE_BUFF_TOO_SMALL == ret) {
        return DEVICEKEY_SAVE_FAILED;
    }

    if (NVSTORE_SUCCESS != ret) {
        return DEVICEKEY_NVSTORE_UNPREDICTED_ERROR;
    }

    return DEVICEKEY_SUCCESS;
}

int DeviceKey::read_key_from_nvstore(uint32_t *output, size_t& size)
{
    if (size > UINT16_MAX) {
        return DEVICEKEY_INVALID_PARAM;
    }

    uint16_t in_size = size;
    uint16_t out_size = 0;
    NVStore& nvstore = NVStore::get_instance();
    int nvStatus = nvstore.get(NVSTORE_DEVICEKEY_KEY, in_size, output, out_size);
    if (NVSTORE_NOT_FOUND == nvStatus) {
        return DEVICEKEY_NOT_FOUND;
    }

    if (NVSTORE_READ_ERROR == nvStatus || NVSTORE_BUFF_TOO_SMALL == nvStatus) {
        return DEVICEKEY_READ_FAILED;
    }

    if (NVSTORE_SUCCESS != nvStatus) {
        return DEVICEKEY_NVSTORE_UNPREDICTED_ERROR;
    }

    size = out_size;
    return DEVICEKEY_SUCCESS;
}

int DeviceKey::get_derived_key(uint32_t *ikey_buff, size_t ikey_size, const unsigned char *isalt,
                               size_t isalt_size, unsigned char *output, uint32_t ikey_type)
{
    //KDF in counter mode implementation as described in Section 5.1
    //of NIST SP 800-108, Recommendation for Key Derivation Using Pseudorandom Functions
    int ret;
    size_t counter = 0;
    char separator = 0x00;
    mbedtls_cipher_context_t ctx;
    unsigned char output_len_enc[ 4 ] = {0};
    unsigned char counter_enc[ 1 ] = {0};

    DEVKEY_WRITE_UINT32_LE(output_len_enc, ikey_type);

    mbedtls_cipher_type_t mbedtls_cipher_type = MBEDTLS_CIPHER_AES_128_ECB;
    if (DEVICE_KEY_32BYTE == ikey_size) {
        mbedtls_cipher_type = MBEDTLS_CIPHER_AES_256_ECB;
    }

    const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type(mbedtls_cipher_type);

    mbedtls_cipher_init(&ctx);
    ret = mbedtls_cipher_setup(&ctx, cipher_info);
    if (ret != 0) {
        goto finish;
    }

    do {

        ret = mbedtls_cipher_cmac_starts(&ctx, (unsigned char *)ikey_buff, ikey_size * 8);
        if (ret != 0) {
            goto finish;
        }

        DEVKEY_WRITE_UINT8_LE(counter_enc, (counter+1));

        ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)counter_enc, sizeof(counter_enc));
        if (ret != 0) {
            goto finish;
        }

        ret = mbedtls_cipher_cmac_update(&ctx, isalt, isalt_size);
        if (ret != 0) {
            goto finish;
        }

        ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&separator, sizeof(char));
        if (ret != 0) {
            goto finish;
        }

        ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&output_len_enc, sizeof(output_len_enc));
        if (ret != 0) {
            goto finish;
        }

        ret = mbedtls_cipher_cmac_finish(&ctx, output + (DEVICE_KEY_16BYTE * (counter)));
        if (ret != 0) {
            goto finish;
        }

        counter++;

    } while (DEVICE_KEY_16BYTE * counter < ikey_type);

finish:
    mbedtls_cipher_free( &ctx );

    if (DEVICEKEY_SUCCESS != ret) {
        return DEVICEKEY_ERR_CMAC_GENERIC_FAILURE;
    }

    return DEVICEKEY_SUCCESS;
}

int DeviceKey::generate_key_by_trng(uint32_t *output, size_t& size)
{
#if defined(DEVICE_TRNG)
    size_t in_size;
    size_t ongoing_size;
    size_t final_size;
    trng_t trng_obj;
    int ret = DEVICEKEY_SUCCESS;
    unsigned char *pBuffer = (unsigned char *)output;

    memset(output, 0, size);

    if (DEVICE_KEY_16BYTE > size) {
        return DEVICEKEY_BUFFER_TOO_SMALL;
    } else if (DEVICE_KEY_16BYTE <= size && DEVICE_KEY_32BYTE > size) {
        size = DEVICE_KEY_16BYTE;
    } else {
        size = DEVICE_KEY_32BYTE;
    }

    trng_init(&trng_obj);

    final_size = 0;
    in_size = size;
    while (true) {

        ongoing_size = 0;
        ret = trng_get_bytes(&trng_obj, (unsigned char *)pBuffer, in_size, &ongoing_size);
        final_size += ongoing_size;
        if (DEVICEKEY_SUCCESS != ret) {
            ret = DEVICEKEY_TRNG_ERROR;
            goto finish;
        }

        if (DEVICEKEY_SUCCESS == ret && final_size == size) {
            break;
        }

        wait_ms(5);
        pBuffer += ongoing_size;
        in_size -= ongoing_size;
    }

    ret = DEVICEKEY_SUCCESS;

finish:
    trng_free(&trng_obj);
    size = final_size;
    return ret;

#else
    return DEVICEKEY_NO_KEY_INJECTED;
#endif
}

} // namespace mbed

#endif //NVSTORE_ENABLED
#endif

<commit_msg>Changed trng loop condition<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 *
 * 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 "DeviceKey.h"
#include "mbedtls/config.h"
#include "mbedtls/cmac.h"
#include "nvstore.h"
#include "trng_api.h"
#include "mbed_wait_api.h"
#include "stdlib.h"

#if !defined(MBEDTLS_CMAC_C)
#error [NOT_SUPPORTED] MBEDTLS_CMAC_C needs to be enabled for this driver
#else

#if NVSTORE_ENABLED

namespace mbed {

#define DEVKEY_WRITE_UINT32_LE( dst, src )                              \
    do                                                                  \
    {                                                                   \
        (dst)[0] = ( (src) >> 0 ) & 0xFF;                               \
        (dst)[1] = ( (src) >> 8 ) & 0xFF;                               \
        (dst)[2] = ( (src) >> 16 ) & 0xFF;                              \
        (dst)[3] = ( (src) >> 24 ) & 0xFF;                              \
    } while( 0 )

#define DEVKEY_WRITE_UINT8_LE( dst, src )                               \
    do                                                                  \
    {                                                                   \
        (dst)[0] = (src) & 0xFF;                                        \
    } while( 0 )

DeviceKey::DeviceKey()
{
    return;
}

DeviceKey::~DeviceKey()
{
    return;
}

int DeviceKey::generate_derived_key(const unsigned char *salt, size_t isalt_size, unsigned char *output,
                                    uint16_t ikey_type)
{
    uint32_t key_buff[DEVICE_KEY_32BYTE / sizeof(uint32_t)];
    size_t actual_size = DEVICE_KEY_32BYTE;

    if (DEVICE_KEY_16BYTE != ikey_type && DEVICE_KEY_32BYTE != ikey_type) {
        return DEVICEKEY_INVALID_KEY_TYPE;
    }

    //First try to read the key from NVStore
    int ret = read_key_from_nvstore(key_buff, actual_size);
    if (DEVICEKEY_SUCCESS != ret && DEVICEKEY_NOT_FOUND != ret) {
        return ret;
    }

    if (DEVICE_KEY_16BYTE != actual_size && DEVICE_KEY_32BYTE != actual_size) {
        return DEVICEKEY_READ_FAILED;
    }

    //If the key was not found in NVStore we will create it by using TRNG and then save it to NVStore
    if (DEVICEKEY_NOT_FOUND == ret) {
        ret = generate_key_by_trng(key_buff, actual_size);
        if (DEVICEKEY_SUCCESS != ret) {
            return ret;
        }

        ret = device_inject_root_of_trust(key_buff, actual_size);
        if (DEVICEKEY_SUCCESS != ret) {
            return ret;
        }
    }

    ret = get_derived_key(key_buff, actual_size, salt, isalt_size, output, ikey_type);
    return ret;
}

int DeviceKey::device_inject_root_of_trust(uint32_t *value, size_t isize)
{
    return write_key_to_nvstore(value, isize);
}

int DeviceKey::write_key_to_nvstore(uint32_t *input, size_t isize)
{
    if (DEVICE_KEY_16BYTE != isize && DEVICE_KEY_32BYTE != isize) {
        return DEVICEKEY_INVALID_KEY_SIZE;
    }

    //First we read if key exist. If it is exists, we return DEVICEKEY_ALREADY_EXIST error
    uint32_t read_key[DEVICE_KEY_32BYTE / sizeof(uint32_t)] = {0};
    size_t read_size = DEVICE_KEY_32BYTE;
    int ret = read_key_from_nvstore(read_key, read_size);
    if (DEVICEKEY_SUCCESS == ret) {
        return DEVICEKEY_ALREADY_EXIST;
    }
    if (DEVICEKEY_NOT_FOUND != ret) {
        return ret;
    }

    NVStore& nvstore = NVStore::get_instance();
    ret = nvstore.set(NVSTORE_DEVICEKEY_KEY, (uint16_t)isize, input);
    if (NVSTORE_WRITE_ERROR == ret || NVSTORE_BUFF_TOO_SMALL == ret) {
        return DEVICEKEY_SAVE_FAILED;
    }

    if (NVSTORE_SUCCESS != ret) {
        return DEVICEKEY_NVSTORE_UNPREDICTED_ERROR;
    }

    return DEVICEKEY_SUCCESS;
}

int DeviceKey::read_key_from_nvstore(uint32_t *output, size_t& size)
{
    if (size > UINT16_MAX) {
        return DEVICEKEY_INVALID_PARAM;
    }

    uint16_t in_size = size;
    uint16_t out_size = 0;
    NVStore& nvstore = NVStore::get_instance();
    int nvStatus = nvstore.get(NVSTORE_DEVICEKEY_KEY, in_size, output, out_size);
    if (NVSTORE_NOT_FOUND == nvStatus) {
        return DEVICEKEY_NOT_FOUND;
    }

    if (NVSTORE_READ_ERROR == nvStatus || NVSTORE_BUFF_TOO_SMALL == nvStatus) {
        return DEVICEKEY_READ_FAILED;
    }

    if (NVSTORE_SUCCESS != nvStatus) {
        return DEVICEKEY_NVSTORE_UNPREDICTED_ERROR;
    }

    size = out_size;
    return DEVICEKEY_SUCCESS;
}

int DeviceKey::get_derived_key(uint32_t *ikey_buff, size_t ikey_size, const unsigned char *isalt,
                               size_t isalt_size, unsigned char *output, uint32_t ikey_type)
{
    //KDF in counter mode implementation as described in Section 5.1
    //of NIST SP 800-108, Recommendation for Key Derivation Using Pseudorandom Functions
    int ret;
    size_t counter = 0;
    char separator = 0x00;
    mbedtls_cipher_context_t ctx;
    unsigned char output_len_enc[ 4 ] = {0};
    unsigned char counter_enc[ 1 ] = {0};

    DEVKEY_WRITE_UINT32_LE(output_len_enc, ikey_type);

    mbedtls_cipher_type_t mbedtls_cipher_type = MBEDTLS_CIPHER_AES_128_ECB;
    if (DEVICE_KEY_32BYTE == ikey_size) {
        mbedtls_cipher_type = MBEDTLS_CIPHER_AES_256_ECB;
    }

    const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type(mbedtls_cipher_type);

    mbedtls_cipher_init(&ctx);
    ret = mbedtls_cipher_setup(&ctx, cipher_info);
    if (ret != 0) {
        goto finish;
    }

    do {

        ret = mbedtls_cipher_cmac_starts(&ctx, (unsigned char *)ikey_buff, ikey_size * 8);
        if (ret != 0) {
            goto finish;
        }

        DEVKEY_WRITE_UINT8_LE(counter_enc, (counter+1));

        ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)counter_enc, sizeof(counter_enc));
        if (ret != 0) {
            goto finish;
        }

        ret = mbedtls_cipher_cmac_update(&ctx, isalt, isalt_size);
        if (ret != 0) {
            goto finish;
        }

        ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&separator, sizeof(char));
        if (ret != 0) {
            goto finish;
        }

        ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&output_len_enc, sizeof(output_len_enc));
        if (ret != 0) {
            goto finish;
        }

        ret = mbedtls_cipher_cmac_finish(&ctx, output + (DEVICE_KEY_16BYTE * (counter)));
        if (ret != 0) {
            goto finish;
        }

        counter++;

    } while (DEVICE_KEY_16BYTE * counter < ikey_type);

finish:
    mbedtls_cipher_free( &ctx );

    if (DEVICEKEY_SUCCESS != ret) {
        return DEVICEKEY_ERR_CMAC_GENERIC_FAILURE;
    }

    return DEVICEKEY_SUCCESS;
}

int DeviceKey::generate_key_by_trng(uint32_t *output, size_t& size)
{
#if defined(DEVICE_TRNG)
    size_t in_size;
    size_t ongoing_size;
    size_t final_size;
    trng_t trng_obj;
    int ret = DEVICEKEY_SUCCESS;
    unsigned char *pBuffer = (unsigned char *)output;

    memset(output, 0, size);

    if (DEVICE_KEY_16BYTE > size) {
        return DEVICEKEY_BUFFER_TOO_SMALL;
    } else if (DEVICE_KEY_16BYTE <= size && DEVICE_KEY_32BYTE > size) {
        size = DEVICE_KEY_16BYTE;
    } else {
        size = DEVICE_KEY_32BYTE;
    }

    trng_init(&trng_obj);

    final_size = 0;
    in_size = size;
    while (DEVICEKEY_SUCCESS == ret && final_size < size) {

        ongoing_size = 0;
        ret = trng_get_bytes(&trng_obj, (unsigned char *)pBuffer, in_size, &ongoing_size);
        final_size += ongoing_size;
        if (DEVICEKEY_SUCCESS != ret) {
            ret = DEVICEKEY_TRNG_ERROR;
            goto finish;
        }

        pBuffer += ongoing_size;
        in_size -= ongoing_size;
    }

    ret = DEVICEKEY_SUCCESS;

finish:
    trng_free(&trng_obj);
    size = final_size;
    return ret;

#else
    return DEVICEKEY_NO_KEY_INJECTED;
#endif
}

} // namespace mbed

#endif //NVSTORE_ENABLED
#endif

<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)
//
// 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 "gjstest/internal/cpp/test_case.h"

#include "base/callback.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "base/timer.h"
#include "gjstest/internal/cpp/v8_utils.h"

using v8::Arguments;
using v8::Context;
using v8::Function;
using v8::Handle;
using v8::Local;
using v8::Object;
using v8::TryCatch;
using v8::Value;

namespace gjstest {

// Get a reference to the function of the supplied name.
static Local<Function> GetFunctionNamed(const string& name) {
  const Local<Value> result = ExecuteJs(name, "");
  CHECK(result->IsFunction()) << "Error getting reference to " << name;
  return Local<Function>::Cast(result);
}

// Log the supplied string to the test's output.
static Handle<Value> LogString(TestCase* test_case, const Arguments& args) {
  CHECK_EQ(1, args.Length());
  const string& message = ConvertToString(args[0]);
  StringAppendF(&test_case->output, "%s\n", message.c_str());

  return v8::Undefined();
}

// Record the test as having failed, and extract a failure message from the JS
// arguments and append it to the existing messages, if any.
static Handle<Value> RecordFailure(TestCase* test_case, const Arguments& args) {
  CHECK_EQ(1, args.Length());
  const string& message = ConvertToString(args[0]);

  test_case->succeeded = false;
  StringAppendF(&test_case->output, "%s\n\n", message.c_str());
  StringAppendF(&test_case->failure_output, "%s\n\n", message.c_str());

  return v8::Undefined();
}

TestCase::TestCase(
    const Handle<Function>& test_function)
    : succeeded(false),
      duration_ms(kuint32max),
      test_function_(test_function) {
  CHECK(test_function_->IsFunction());
}

void TestCase::Run() {
  CycleTimer timer;
  timer.Start();

  // Assume we succeeded by default.
  succeeded = true;

  // Grab references to runTest, getCurrentStack, and the TestEnvironment
  // constructor.
  const Local<Function> run_test = GetFunctionNamed("gjstest.internal.runTest");

  const Local<Function> get_current_stack =
      GetFunctionNamed("gjstest.internal.getCurrentStack");

  const Local<Function> test_env_constructor =
      GetFunctionNamed("gjstest.internal.TestEnvironment");

  // Create log and reportFailure functions.
  const Local<Function> log =
      MakeFunction("log", NewPermanentCallback(&LogString, this));

  const Local<Function> report_failure =
      MakeFunction(
          "reportFailure",
          NewPermanentCallback(&RecordFailure, this));

  // Create a test environment.
  Handle<Value> test_env_args[] = { log, report_failure, get_current_stack };
  const Local<Object> test_env =
      test_env_constructor->NewInstance(
          arraysize(test_env_args),
          test_env_args);
  CHECK(!test_env.IsEmpty());

  // Run the test.
  TryCatch try_catch;
  Handle<Value> args[] = { test_function_, test_env };
  const Local<Value> result =
      run_test->Call(Context::GetCurrent()->Global(), arraysize(args), args);

  // Was there an exception while running the test?
  if (result.IsEmpty()) {
    succeeded = false;

    const string description = DescribeError(try_catch);
    StringAppendF(&output, "%s\n", description.c_str());
    StringAppendF(&failure_output, "%s\n", description.c_str());
  }

  // Record the test time.
  timer.Stop();
  duration_ms = timer.GetInMs();
}

}  // namespace gjstest
<commit_msg>Fixed two memory errors.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)
//
// 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 "gjstest/internal/cpp/test_case.h"

#include "base/callback.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "base/timer.h"
#include "gjstest/internal/cpp/v8_utils.h"

using v8::Arguments;
using v8::Context;
using v8::Function;
using v8::Handle;
using v8::Local;
using v8::Object;
using v8::TryCatch;
using v8::Value;

namespace gjstest {

// Get a reference to the function of the supplied name.
static Local<Function> GetFunctionNamed(const string& name) {
  const Local<Value> result = ExecuteJs(name, "");
  CHECK(result->IsFunction()) << "Error getting reference to " << name;
  return Local<Function>::Cast(result);
}

// Log the supplied string to the test's output.
static Handle<Value> LogString(TestCase* test_case, const Arguments& args) {
  CHECK_EQ(1, args.Length());
  const string message = ConvertToString(args[0]);
  StringAppendF(&test_case->output, "%s\n", message.c_str());

  return v8::Undefined();
}

// Record the test as having failed, and extract a failure message from the JS
// arguments and append it to the existing messages, if any.
static Handle<Value> RecordFailure(TestCase* test_case, const Arguments& args) {
  CHECK_EQ(1, args.Length());
  const string message = ConvertToString(args[0]);

  test_case->succeeded = false;
  StringAppendF(&test_case->output, "%s\n\n", message.c_str());
  StringAppendF(&test_case->failure_output, "%s\n\n", message.c_str());

  return v8::Undefined();
}

TestCase::TestCase(
    const Handle<Function>& test_function)
    : succeeded(false),
      duration_ms(kuint32max),
      test_function_(test_function) {
  CHECK(test_function_->IsFunction());
}

void TestCase::Run() {
  CycleTimer timer;
  timer.Start();

  // Assume we succeeded by default.
  succeeded = true;

  // Grab references to runTest, getCurrentStack, and the TestEnvironment
  // constructor.
  const Local<Function> run_test = GetFunctionNamed("gjstest.internal.runTest");

  const Local<Function> get_current_stack =
      GetFunctionNamed("gjstest.internal.getCurrentStack");

  const Local<Function> test_env_constructor =
      GetFunctionNamed("gjstest.internal.TestEnvironment");

  // Create log and reportFailure functions.
  const Local<Function> log =
      MakeFunction("log", NewPermanentCallback(&LogString, this));

  const Local<Function> report_failure =
      MakeFunction(
          "reportFailure",
          NewPermanentCallback(&RecordFailure, this));

  // Create a test environment.
  Handle<Value> test_env_args[] = { log, report_failure, get_current_stack };
  const Local<Object> test_env =
      test_env_constructor->NewInstance(
          arraysize(test_env_args),
          test_env_args);
  CHECK(!test_env.IsEmpty());

  // Run the test.
  TryCatch try_catch;
  Handle<Value> args[] = { test_function_, test_env };
  const Local<Value> result =
      run_test->Call(Context::GetCurrent()->Global(), arraysize(args), args);

  // Was there an exception while running the test?
  if (result.IsEmpty()) {
    succeeded = false;

    const string description = DescribeError(try_catch);
    StringAppendF(&output, "%s\n", description.c_str());
    StringAppendF(&failure_output, "%s\n", description.c_str());
  }

  // Record the test time.
  timer.Stop();
  duration_ms = timer.GetInMs();
}

}  // namespace gjstest
<|endoftext|>


<commit_before>#include <assert.h>
#include <utility>

#include "common/configmanager/configmanager.h"
#include "log/clog.h"
#include "simhub.h"

// TODO: FIX EVERYTHING

std::shared_ptr<SimHubEventController> SimHubEventController::_EventControllerInstance = NULL;

GenericTLV *AttributeToCGeneric(std::shared_ptr<Attribute> value)
{
    GenericTLV *retVal = (GenericTLV *)malloc(sizeof(GenericTLV));

    retVal->name = (char *)calloc(value->_name.size() + 1, 1);
    strncpy(retVal->name, value->_name.c_str(), value->_name.size());

    switch (value->_type) {
    case BOOL_ATTRIBUTE:
        retVal->type = CONFIG_BOOL;
        retVal->value.bool_value = value->getValue<bool>();
        break;

    case FLOAT_ATTRIBUTE:
        retVal->type = CONFIG_FLOAT;
        retVal->value.float_value = value->getValue<float>();
        break;

    case INT_ATTRIBUTE:
        retVal->type = CONFIG_INT;
        retVal->value.int_value = value->getValue<int>();
        break;

    case STRING_ATTRIBUTE:
        retVal->type = CONFIG_STRING;
        retVal->value.string_value = (char *)calloc(value->getValue<std::string>().size() + 1, 1);
        strncpy(retVal->value.string_value, value->getValue<std::string>().c_str(), value->getValue<std::string>().size());
        break;

    default:
        assert(false);
        break;
    }

    return retVal;
}

//! marshals the C generic struct instance into an Attribute C++ generic container
std::shared_ptr<Attribute> AttributeFromCGeneric(GenericTLV *generic)
{
    std::shared_ptr<Attribute> retVal(new Attribute());

    switch (generic->type) {
    case CONFIG_BOOL:
        retVal->setValue<bool>(generic->value.bool_value);
        retVal->_type = BOOL_ATTRIBUTE;
        break;
    case CONFIG_FLOAT:
        retVal->setValue<float>(generic->value.float_value);
        retVal->_type = FLOAT_ATTRIBUTE;
        break;
    case CONFIG_INT:
        retVal->setValue<int>(generic->value.int_value);
        retVal->_type = INT_ATTRIBUTE;
        break;
    case CONFIG_STRING:
        retVal->setValue<std::string>(generic->value.string_value);
        retVal->_type = STRING_ATTRIBUTE;
        break;
    default:
        assert(false);
        break;
    }

    retVal->_name = generic->name;

    return retVal;
}

//! static singleton accessor
std::shared_ptr<SimHubEventController> SimHubEventController::EventControllerInstance(void)
{
    if (!_EventControllerInstance)
        _EventControllerInstance.reset(new SimHubEventController());

    return SimHubEventController::_EventControllerInstance;
}

SimHubEventController::SimHubEventController()
{
    _prepare3dMethods.plugin_instance = NULL;
    _pokeyMethods.plugin_instance = NULL;
    _configManager = NULL;

    logger.log(LOG_INFO, "Starting event controller");
}

SimHubEventController::~SimHubEventController(void)
{
    terminate();
}

void SimHubEventController::setConfigManager(ConfigManager *configManager)
{
    _configManager = configManager;
}

bool SimHubEventController::deliverPokeyPluginValue(std::shared_ptr<Attribute> value)
{
    assert(_pokeyMethods.simplug_deliver_value);

    GenericTLV *c_value = AttributeToCGeneric(value);
    bool retVal = !_pokeyMethods.simplug_deliver_value(_pokeyMethods.plugin_instance, c_value);

    if (c_value->type == CONFIG_STRING)
        free(c_value->value.string_value);
    free(c_value->name);
    free(c_value);

    return retVal;
}
// these callbacks will be called from the thread of the event
// generator which is assumed to not be the thread of the for
// loop below

void SimHubEventController::prepare3dEventCallback(SPHANDLE eventSource, void *eventData)
{
    GenericTLV *data = static_cast<GenericTLV *>(eventData);
    assert(data != NULL);

    std::shared_ptr<Attribute> attribute = AttributeFromCGeneric(data);
    MapEntry *mapEntry;

    if (_configManager->mapManager()->find(data->name, &mapEntry)) {
        // std::cout << "prepare3dEventCallback" << data->name << "--->" << mapEntry->second.c_str() << " FIND TARGET HERE" << std::endl;
        _eventQueue.push(attribute);
    }
}

void SimHubEventController::pokeyEventCallback(SPHANDLE eventSource, void *eventData)
{
    GenericTLV *data = static_cast<GenericTLV *>(eventData);
    assert(data != NULL);

    std::shared_ptr<Attribute> attribute = AttributeFromCGeneric(data);
    MapEntry *mapEntry;

    if (_configManager->mapManager()->find(data->name, &mapEntry)) {
        std::cout << "pokeyEventCallback" << data->name << "--->" << mapEntry->second.c_str() << " FIND TARGET HERE" << std::endl;
        _eventQueue.push(attribute);
    }
}

void SimHubEventController::LoggerWrapper(const int category, const char *msg, ...)
{
    // TODO: make logger a class instance member
    char buff[MAX_VA_LENGTH];
    va_list args;
    va_start(args, msg);
    vsprintf(buff, msg, args);
    va_end(args);

    logger.log(category, buff);
}

simplug_vtable SimHubEventController::loadPlugin(std::string dylibName, libconfig::Config *pluginConfig, EnqueueEventHandler eventCallback)
{
    SPHANDLE pluginInstance = NULL;
    simplug_vtable pluginMethods;

    memset(&pluginMethods, sizeof(simplug_vtable), 0);

    // TODO: use correct path
    std::string fullPath("plugins/");
    fullPath += dylibName + LIB_EXT;
    int err = simplug_bootstrap(fullPath.c_str(), &pluginMethods);

    if (err == 0) {
        err = pluginMethods.simplug_init(&pluginInstance, SimHubEventController::LoggerWrapper);

        pluginMethods.plugin_instance = pluginInstance;

        // -- temporary solution to the plugin configuration conundrom:
        //    - iterate over the list of libconfig::Setting instances we've
        //    - been given for this plugin and pass them through

        pluginMethods.simplug_config_passthrough(pluginInstance, pluginConfig);
        // TODO: add error checking

        if (pluginMethods.simplug_preflight_complete(pluginInstance) == 0) {
            // proxy the C style lambda call through to the member
            // function above
            pluginMethods.simplug_commence_eventing(pluginInstance, eventCallback, this);
        }
        else {
            assert(false);
        }
    }
    else {
        assert(false);
    }

    return pluginMethods;
}

void SimHubEventController::loadPrepare3dPlugin(void)
{
    auto prepare3dCallback = [](SPHANDLE eventSource, void *eventData, void *arg) { static_cast<SimHubEventController *>(arg)->prepare3dEventCallback(eventSource, eventData); };

    _prepare3dMethods = loadPlugin("libprepare3d", _prepare3dDeviceConfig, prepare3dCallback);
}

void SimHubEventController::loadPokeyPlugin(void)
{
    auto pokeyCallback = [](SPHANDLE eventSource, void *eventData, void *arg) { static_cast<SimHubEventController *>(arg)->pokeyEventCallback(eventSource, eventData); };

    _pokeyMethods = loadPlugin("libpokey", _pokeyDeviceConfig, pokeyCallback);
}

//! perform shutdown ceremonies on both plugins - this unloads both plugins
void SimHubEventController::terminate(void)
{
    shutdownPlugin(_prepare3dMethods);
    shutdownPlugin(_pokeyMethods);
}

//! private support method - gracefully closes plugin instance represented by pluginMethods
void SimHubEventController::shutdownPlugin(simplug_vtable &pluginMethods)
{
    if (pluginMethods.plugin_instance) {
        pluginMethods.simplug_cease_eventing(pluginMethods.plugin_instance);
        pluginMethods.simplug_release(pluginMethods.plugin_instance);
        pluginMethods.plugin_instance = NULL;
    }
}
<commit_msg>handle CONFIG_UINT<commit_after>#include <assert.h>
#include <utility>

#include "common/configmanager/configmanager.h"
#include "log/clog.h"
#include "simhub.h"

// TODO: FIX EVERYTHING

std::shared_ptr<SimHubEventController> SimHubEventController::_EventControllerInstance = NULL;

GenericTLV *AttributeToCGeneric(std::shared_ptr<Attribute> value)
{
    GenericTLV *retVal = (GenericTLV *)malloc(sizeof(GenericTLV));

    retVal->name = (char *)calloc(value->_name.size() + 1, 1);
    strncpy(retVal->name, value->_name.c_str(), value->_name.size());

    switch (value->_type) {
    case BOOL_ATTRIBUTE:
        retVal->type = CONFIG_BOOL;
        retVal->value.bool_value = value->getValue<bool>();
        break;

    case FLOAT_ATTRIBUTE:
        retVal->type = CONFIG_FLOAT;
        retVal->value.float_value = value->getValue<float>();
        break;

    case INT_ATTRIBUTE:
        retVal->type = CONFIG_INT;
        retVal->value.int_value = value->getValue<int>();
        break;

    case STRING_ATTRIBUTE:
        retVal->type = CONFIG_STRING;
        retVal->value.string_value = (char *)calloc(value->getValue<std::string>().size() + 1, 1);
        strncpy(retVal->value.string_value, value->getValue<std::string>().c_str(), value->getValue<std::string>().size());
        break;

    default:
        assert(false);
        break;
    }

    return retVal;
}

//! marshals the C generic struct instance into an Attribute C++ generic container
std::shared_ptr<Attribute> AttributeFromCGeneric(GenericTLV *generic)
{
    std::shared_ptr<Attribute> retVal(new Attribute());

    switch (generic->type) {
    case CONFIG_BOOL:
        retVal->setValue<bool>(generic->value.bool_value);
        retVal->_type = BOOL_ATTRIBUTE;
        break;
    case CONFIG_FLOAT:
        retVal->setValue<float>(generic->value.float_value);
        retVal->_type = FLOAT_ATTRIBUTE;
        break;
    case CONFIG_INT:
        retVal->setValue<int>(generic->value.int_value);
        retVal->_type = INT_ATTRIBUTE;
        break;
    case CONFIG_UINT:
        retVal->setValue<int>(generic->value.uint_value);
        retVal->_type = UINT_ATTRIBUTE;
        break;
    case CONFIG_STRING:
        retVal->setValue<std::string>(generic->value.string_value);
        retVal->_type = STRING_ATTRIBUTE;
        break;
    default:
        logger.log(LOG_ERROR, "Unknown attribute type %d %s ", (int)generic->type, generic->name);

        break;
    }

    retVal->_name = generic->name;

    return retVal;
}

//! static singleton accessor
std::shared_ptr<SimHubEventController> SimHubEventController::EventControllerInstance(void)
{
    if (!_EventControllerInstance)
        _EventControllerInstance.reset(new SimHubEventController());

    return SimHubEventController::_EventControllerInstance;
}

SimHubEventController::SimHubEventController()
{
    _prepare3dMethods.plugin_instance = NULL;
    _pokeyMethods.plugin_instance = NULL;
    _configManager = NULL;

    logger.log(LOG_INFO, "Starting event controller");
}

SimHubEventController::~SimHubEventController(void)
{
    terminate();
}

void SimHubEventController::setConfigManager(ConfigManager *configManager)
{
    _configManager = configManager;
}

bool SimHubEventController::deliverPokeyPluginValue(std::shared_ptr<Attribute> value)
{
    assert(_pokeyMethods.simplug_deliver_value);

    GenericTLV *c_value = AttributeToCGeneric(value);
    bool retVal = !_pokeyMethods.simplug_deliver_value(_pokeyMethods.plugin_instance, c_value);

    if (c_value->type == CONFIG_STRING)
        free(c_value->value.string_value);
    free(c_value->name);
    free(c_value);

    return retVal;
}
// these callbacks will be called from the thread of the event
// generator which is assumed to not be the thread of the for
// loop below

void SimHubEventController::prepare3dEventCallback(SPHANDLE eventSource, void *eventData)
{
    GenericTLV *data = static_cast<GenericTLV *>(eventData);
    assert(data != NULL);

    std::shared_ptr<Attribute> attribute = AttributeFromCGeneric(data);
    MapEntry *mapEntry;

    if (_configManager->mapManager()->find(data->name, &mapEntry)) {
        _eventQueue.push(attribute);
    }
}

void SimHubEventController::pokeyEventCallback(SPHANDLE eventSource, void *eventData)
{
    GenericTLV *data = static_cast<GenericTLV *>(eventData);
    assert(data != NULL);

    std::shared_ptr<Attribute> attribute = AttributeFromCGeneric(data);
    MapEntry *mapEntry;

    if (_configManager->mapManager()->find(data->name, &mapEntry)) {
        _eventQueue.push(attribute);
    }
}

void SimHubEventController::LoggerWrapper(const int category, const char *msg, ...)
{
    // TODO: make logger a class instance member
    char buff[MAX_VA_LENGTH];
    va_list args;
    va_start(args, msg);
    vsprintf(buff, msg, args);
    va_end(args);

    logger.log(category, buff);
}

simplug_vtable SimHubEventController::loadPlugin(std::string dylibName, libconfig::Config *pluginConfig, EnqueueEventHandler eventCallback)
{
    SPHANDLE pluginInstance = NULL;
    simplug_vtable pluginMethods;

    memset(&pluginMethods, sizeof(simplug_vtable), 0);

    // TODO: use correct path
    std::string fullPath("plugins/");
    fullPath += dylibName + LIB_EXT;
    int err = simplug_bootstrap(fullPath.c_str(), &pluginMethods);

    if (err == 0) {
        err = pluginMethods.simplug_init(&pluginInstance, SimHubEventController::LoggerWrapper);

        pluginMethods.plugin_instance = pluginInstance;

        // -- temporary solution to the plugin configuration conundrom:
        //    - iterate over the list of libconfig::Setting instances we've
        //    - been given for this plugin and pass them through

        pluginMethods.simplug_config_passthrough(pluginInstance, pluginConfig);
        // TODO: add error checking

        if (pluginMethods.simplug_preflight_complete(pluginInstance) == 0) {
            // proxy the C style lambda call through to the member
            // function above
            pluginMethods.simplug_commence_eventing(pluginInstance, eventCallback, this);
        }
        else {
            assert(false);
        }
    }
    else {
        assert(false);
    }

    return pluginMethods;
}

void SimHubEventController::loadPrepare3dPlugin(void)
{
    auto prepare3dCallback = [](SPHANDLE eventSource, void *eventData, void *arg) { static_cast<SimHubEventController *>(arg)->prepare3dEventCallback(eventSource, eventData); };

    _prepare3dMethods = loadPlugin("libprepare3d", _prepare3dDeviceConfig, prepare3dCallback);
}

void SimHubEventController::loadPokeyPlugin(void)
{
    auto pokeyCallback = [](SPHANDLE eventSource, void *eventData, void *arg) { static_cast<SimHubEventController *>(arg)->pokeyEventCallback(eventSource, eventData); };

    _pokeyMethods = loadPlugin("libpokey", _pokeyDeviceConfig, pokeyCallback);
}

//! perform shutdown ceremonies on both plugins - this unloads both plugins
void SimHubEventController::terminate(void)
{
    shutdownPlugin(_prepare3dMethods);
    shutdownPlugin(_pokeyMethods);
}

//! private support method - gracefully closes plugin instance represented by pluginMethods
void SimHubEventController::shutdownPlugin(simplug_vtable &pluginMethods)
{
    if (pluginMethods.plugin_instance) {
        pluginMethods.simplug_cease_eventing(pluginMethods.plugin_instance);
        pluginMethods.simplug_release(pluginMethods.plugin_instance);
        pluginMethods.plugin_instance = NULL;
    }
}
<|endoftext|>


<commit_before>//===--- lldb-moduleimport-test.cpp - LLDB moduleimport tester ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This program simulates LLDB importing modules from the __apple_ast
// section in Mach-O files. We use it to test for regressions in the
// deserialization API.
//
//===----------------------------------------------------------------------===//

#include "swift/ASTSectionImporter/ASTSectionImporter.h"
#include "swift/Frontend/Frontend.h"
#include "swift/IDE/Utils.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Serialization/Validation.h"
#include "swift/Basic/Dwarf.h"
#include "llvm/Object/ELFObjectFile.h"
#include "swift/Basic/LLVMInitialize.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ManagedStatic.h"
#include <fstream>
#include <sstream>

void anchorForGetMainExecutable() {}

using namespace llvm::MachO;

static bool
validateModule(llvm::StringRef data, bool Verbose,
               swift::serialization::ValidationInfo &info,
               swift::serialization::ExtendedValidationInfo &extendedInfo) {
  info = swift::serialization::validateSerializedAST(data, &extendedInfo);
  if (info.status != swift::serialization::Status::Valid)
    return false;

  swift::CompilerInvocation CI;
  if (CI.loadFromSerializedAST(data) != swift::serialization::Status::Valid)
    return false;

  if (Verbose) {
    if (!info.shortVersion.empty())
      llvm::outs() << "- Swift Version: " << info.shortVersion << "\n";
    llvm::outs() << "- Compatibility Version: "
                 << CI.getLangOptions()
                        .EffectiveLanguageVersion.asAPINotesVersionString()
                 << "\n";
    llvm::outs() << "- Target: " << info.targetTriple << "\n";
    if (!extendedInfo.getSDKPath().empty())
      llvm::outs() << "- SDK path: " << extendedInfo.getSDKPath() << "\n";
    if (!extendedInfo.getExtraClangImporterOptions().empty()) {
      llvm::outs() << "- -Xcc options:";
      for (llvm::StringRef option : extendedInfo.getExtraClangImporterOptions())
        llvm::outs() << " " << option;
      llvm::outs() << "\n";
    }
  }

  return true;
}

static void resolveDeclFromMangledNameList(
    swift::ASTContext &Ctx, llvm::ArrayRef<std::string> MangledNames) {
  std::string Error;
  for (auto &Mangled : MangledNames) {
    swift::Decl *ResolvedDecl =
        swift::ide::getDeclFromMangledSymbolName(Ctx, Mangled, Error);
    if (!ResolvedDecl) {
      llvm::errs() << "Can't resolve decl of " << Mangled << "\n";
    } else {
      ResolvedDecl->print(llvm::errs());
      llvm::errs() << "\n";
    }
  }
}

static void resolveTypeFromMangledNameList(
    swift::ASTContext &Ctx, llvm::ArrayRef<std::string> MangledNames) {
  std::string Error;
  for (auto &Mangled : MangledNames) {
    swift::Type ResolvedType =
        swift::ide::getTypeFromMangledSymbolname(Ctx, Mangled, Error);
    if (!ResolvedType) {
      llvm::errs() << "Can't resolve type of " << Mangled << "\n";
    } else {
      ResolvedType->print(llvm::errs());
      llvm::errs() << "\n";
    }
  }
}

static void
collectMangledNames(const std::string &FilePath,
                    llvm::SmallVectorImpl<std::string> &MangledNames) {
  std::string Name;
  std::ifstream InputStream(FilePath);
  while (std::getline(InputStream, Name)) {
    if (Name.empty())
      continue;
    MangledNames.push_back(Name);
  }
}

llvm::BumpPtrAllocator Alloc;

static bool
collectASTModules(llvm::cl::list<std::string> &InputNames,
                  llvm::SmallVectorImpl<std::pair<char *, uint64_t>> &Modules) {
  for (auto &name : InputNames) {
    auto OF = llvm::object::ObjectFile::createObjectFile(name);
    if (!OF) {
      llvm::outs() << "error: " << name << " "
                   << errorToErrorCode(OF.takeError()).message() << "\n";
      return false;
    }
    auto *Obj = OF->getBinary();
    auto *MachO = llvm::dyn_cast<llvm::object::MachOObjectFile>(Obj);
    auto *ELF = llvm::dyn_cast<llvm::object::ELFObjectFileBase>(Obj);

    if (MachO) {
      for (auto &Symbol : Obj->symbols()) {
        auto RawSym = Symbol.getRawDataRefImpl();
        llvm::MachO::nlist nlist = MachO->getSymbolTableEntry(RawSym);
        if (nlist.n_type != N_AST)
          continue;
        auto Path = MachO->getSymbolName(RawSym);
        if (!Path) {
          llvm::outs() << "Cannot get symbol name\n;";
          return false;
        }

        auto fileBuf = llvm::MemoryBuffer::getFile(*Path);
        if (!fileBuf) {
          llvm::outs() << "Cannot read from '" << *Path
                       << "': " << fileBuf.getError().message();
          return false;
        }

        uint64_t Size = fileBuf.get()->getBufferSize();
        char *Module = Alloc.Allocate<char>(Size);
        std::memcpy(Module, (void *)fileBuf.get()->getBufferStart(), Size);
        Modules.push_back({Module, Size});
      }
    }

    for (auto &Section : Obj->sections()) {
      llvm::StringRef Name;
      Section.getName(Name);
      if ((MachO && Name == swift::MachOASTSectionName) ||
          (ELF && Name == swift::ELFASTSectionName)) {
        uint64_t Size = Section.getSize();
        StringRef ContentsReference;
        Section.getContents(ContentsReference);
        char *Module = Alloc.Allocate<char>(Size);
        std::memcpy(Module, (void *)ContentsReference.begin(), Size);
        Modules.push_back({Module, Size});
      }
    }
  }
  return true;
}

int main(int argc, char **argv) {
  PROGRAM_START(argc, argv);
  INITIALIZE_LLVM();

  // Command line handling.
  llvm::cl::list<std::string> InputNames(
    llvm::cl::Positional, llvm::cl::desc("compiled_swift_file1.o ..."),
    llvm::cl::OneOrMore);

  llvm::cl::opt<bool> DumpModule(
    "dump-module", llvm::cl::desc(
      "Dump the imported module after checking it imports just fine"));

  llvm::cl::opt<bool> Verbose(
      "verbose", llvm::cl::desc("Dump informations on the loaded module"));

  llvm::cl::opt<std::string> ModuleCachePath(
    "module-cache-path", llvm::cl::desc("Clang module cache path"));

  llvm::cl::opt<std::string> DumpDeclFromMangled(
      "decl-from-mangled", llvm::cl::desc("dump decl from mangled names list"));

  llvm::cl::opt<std::string> DumpTypeFromMangled(
      "type-from-mangled", llvm::cl::desc("dump type from mangled names list"));

  llvm::cl::opt<std::string> ResourceDir("resource-dir",
      llvm::cl::desc("The directory that holds the compiler resource files"));

  llvm::cl::ParseCommandLineOptions(argc, argv);
  // Unregister our options so they don't interfere with the command line
  // parsing in CodeGen/BackendUtil.cpp.
  ModuleCachePath.removeArgument();
  DumpModule.removeArgument();
  DumpTypeFromMangled.removeArgument();
  InputNames.removeArgument();

  auto validateInputFile = [](std::string Filename) {
    if (Filename.empty())
      return true;
    if (!llvm::sys::fs::exists(llvm::Twine(Filename))) {
      llvm::errs() << Filename << " does not exists, exiting.\n";
      return false;
    }
    if (!llvm::sys::fs::is_regular_file(llvm::Twine(Filename))) {
      llvm::errs() << Filename << " is not a regular file, exiting.\n";
      return false;
    }
    return true;
  };

  if (!validateInputFile(DumpTypeFromMangled))
    return 1;
  if (!validateInputFile(DumpDeclFromMangled))
    return 1;

  // Fetch the serialized module bitstreams from the Mach-O files and
  // register them with the module loader.
  llvm::SmallVector<std::pair<char *, uint64_t>, 8> Modules;
  if (!collectASTModules(InputNames, Modules))
    return 1;

  if (Modules.empty())
    return 0;

  swift::serialization::ValidationInfo info;
  swift::serialization::ExtendedValidationInfo extendedInfo;
  for (auto &Module : Modules) {
    if (!validateModule(StringRef(Module.first, Module.second), Verbose, info,
                        extendedInfo)) {
      llvm::errs() << "Malformed module!\n";
      return 1;
    }
  }

  // Create a Swift compiler.
  llvm::SmallVector<std::string, 4> modules;
  swift::CompilerInstance CI;
  swift::CompilerInvocation Invocation;

  Invocation.setMainExecutablePath(
      llvm::sys::fs::getMainExecutable(argv[0],
          reinterpret_cast<void *>(&anchorForGetMainExecutable)));

  // Infer SDK and Target triple from the module.
  Invocation.setSDKPath(extendedInfo.getSDKPath());
  Invocation.setTargetTriple(info.targetTriple);

  Invocation.setModuleName("lldbtest");
  Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;

  if (!ResourceDir.empty()) {
    Invocation.setRuntimeResourcePath(ResourceDir);
  }

  if (CI.setup(Invocation))
    return 1;

  for (auto &Module : Modules)
    if (!parseASTSection(CI.getSerializedModuleLoader(),
                         StringRef(Module.first, Module.second), modules))
      return 1;

  // Attempt to import all modules we found.
  for (auto path : modules) {
    if (Verbose)
      llvm::outs() << "Importing " << path << "... ";

#ifdef SWIFT_SUPPORTS_SUBMODULES
    std::vector<std::pair<swift::Identifier, swift::SourceLoc> > AccessPath;
    for (auto i = llvm::sys::path::begin(path);
         i != llvm::sys::path::end(path); ++i)
      if (!llvm::sys::path::is_separator((*i)[0]))
          AccessPath.push_back({ CI.getASTContext().getIdentifier(*i),
                                 swift::SourceLoc() });
#else
    std::vector<std::pair<swift::Identifier, swift::SourceLoc> > AccessPath;
    AccessPath.push_back({ CI.getASTContext().getIdentifier(path),
                           swift::SourceLoc() });
#endif

    auto Module = CI.getASTContext().getModule(AccessPath);
    if (!Module) {
      if (Verbose)
        llvm::errs() << "FAIL!\n";
      return 1;
    }
    if (Verbose)
      llvm::outs() << "ok!\n";
    if (DumpModule) {
      llvm::SmallVector<swift::Decl*, 10> Decls;
      Module->getTopLevelDecls(Decls);
      for (auto Decl : Decls) {
        Decl->dump(llvm::outs());
      }
    }
    if (!DumpTypeFromMangled.empty()) {
      llvm::SmallVector<std::string, 8> MangledNames;
      collectMangledNames(DumpTypeFromMangled, MangledNames);
      resolveTypeFromMangledNameList(CI.getASTContext(), MangledNames);
    }
    if (!DumpDeclFromMangled.empty()) {
      llvm::SmallVector<std::string, 8> MangledNames;
      collectMangledNames(DumpDeclFromMangled, MangledNames);
      resolveDeclFromMangledNameList(CI.getASTContext(), MangledNames);
    }
  }
  return 0;
}
<commit_msg>Hide irreleveant command line options of lldb-moduleimport-test<commit_after>//===--- lldb-moduleimport-test.cpp - LLDB moduleimport tester ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This program simulates LLDB importing modules from the __apple_ast
// section in Mach-O files. We use it to test for regressions in the
// deserialization API.
//
//===----------------------------------------------------------------------===//

#include "swift/ASTSectionImporter/ASTSectionImporter.h"
#include "swift/Frontend/Frontend.h"
#include "swift/IDE/Utils.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Serialization/Validation.h"
#include "swift/Basic/Dwarf.h"
#include "llvm/Object/ELFObjectFile.h"
#include "swift/Basic/LLVMInitialize.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ManagedStatic.h"
#include <fstream>
#include <sstream>

void anchorForGetMainExecutable() {}

using namespace llvm::MachO;

static bool
validateModule(llvm::StringRef data, bool Verbose,
               swift::serialization::ValidationInfo &info,
               swift::serialization::ExtendedValidationInfo &extendedInfo) {
  info = swift::serialization::validateSerializedAST(data, &extendedInfo);
  if (info.status != swift::serialization::Status::Valid)
    return false;

  swift::CompilerInvocation CI;
  if (CI.loadFromSerializedAST(data) != swift::serialization::Status::Valid)
    return false;

  if (Verbose) {
    if (!info.shortVersion.empty())
      llvm::outs() << "- Swift Version: " << info.shortVersion << "\n";
    llvm::outs() << "- Compatibility Version: "
                 << CI.getLangOptions()
                        .EffectiveLanguageVersion.asAPINotesVersionString()
                 << "\n";
    llvm::outs() << "- Target: " << info.targetTriple << "\n";
    if (!extendedInfo.getSDKPath().empty())
      llvm::outs() << "- SDK path: " << extendedInfo.getSDKPath() << "\n";
    if (!extendedInfo.getExtraClangImporterOptions().empty()) {
      llvm::outs() << "- -Xcc options:";
      for (llvm::StringRef option : extendedInfo.getExtraClangImporterOptions())
        llvm::outs() << " " << option;
      llvm::outs() << "\n";
    }
  }

  return true;
}

static void resolveDeclFromMangledNameList(
    swift::ASTContext &Ctx, llvm::ArrayRef<std::string> MangledNames) {
  std::string Error;
  for (auto &Mangled : MangledNames) {
    swift::Decl *ResolvedDecl =
        swift::ide::getDeclFromMangledSymbolName(Ctx, Mangled, Error);
    if (!ResolvedDecl) {
      llvm::errs() << "Can't resolve decl of " << Mangled << "\n";
    } else {
      ResolvedDecl->print(llvm::errs());
      llvm::errs() << "\n";
    }
  }
}

static void resolveTypeFromMangledNameList(
    swift::ASTContext &Ctx, llvm::ArrayRef<std::string> MangledNames) {
  std::string Error;
  for (auto &Mangled : MangledNames) {
    swift::Type ResolvedType =
        swift::ide::getTypeFromMangledSymbolname(Ctx, Mangled, Error);
    if (!ResolvedType) {
      llvm::errs() << "Can't resolve type of " << Mangled << "\n";
    } else {
      ResolvedType->print(llvm::errs());
      llvm::errs() << "\n";
    }
  }
}

static void
collectMangledNames(const std::string &FilePath,
                    llvm::SmallVectorImpl<std::string> &MangledNames) {
  std::string Name;
  std::ifstream InputStream(FilePath);
  while (std::getline(InputStream, Name)) {
    if (Name.empty())
      continue;
    MangledNames.push_back(Name);
  }
}

llvm::BumpPtrAllocator Alloc;

static bool
collectASTModules(llvm::cl::list<std::string> &InputNames,
                  llvm::SmallVectorImpl<std::pair<char *, uint64_t>> &Modules) {
  for (auto &name : InputNames) {
    auto OF = llvm::object::ObjectFile::createObjectFile(name);
    if (!OF) {
      llvm::outs() << "error: " << name << " "
                   << errorToErrorCode(OF.takeError()).message() << "\n";
      return false;
    }
    auto *Obj = OF->getBinary();
    auto *MachO = llvm::dyn_cast<llvm::object::MachOObjectFile>(Obj);
    auto *ELF = llvm::dyn_cast<llvm::object::ELFObjectFileBase>(Obj);

    if (MachO) {
      for (auto &Symbol : Obj->symbols()) {
        auto RawSym = Symbol.getRawDataRefImpl();
        llvm::MachO::nlist nlist = MachO->getSymbolTableEntry(RawSym);
        if (nlist.n_type != N_AST)
          continue;
        auto Path = MachO->getSymbolName(RawSym);
        if (!Path) {
          llvm::outs() << "Cannot get symbol name\n;";
          return false;
        }

        auto fileBuf = llvm::MemoryBuffer::getFile(*Path);
        if (!fileBuf) {
          llvm::outs() << "Cannot read from '" << *Path
                       << "': " << fileBuf.getError().message();
          return false;
        }

        uint64_t Size = fileBuf.get()->getBufferSize();
        char *Module = Alloc.Allocate<char>(Size);
        std::memcpy(Module, (void *)fileBuf.get()->getBufferStart(), Size);
        Modules.push_back({Module, Size});
      }
    }

    for (auto &Section : Obj->sections()) {
      llvm::StringRef Name;
      Section.getName(Name);
      if ((MachO && Name == swift::MachOASTSectionName) ||
          (ELF && Name == swift::ELFASTSectionName)) {
        uint64_t Size = Section.getSize();
        StringRef ContentsReference;
        Section.getContents(ContentsReference);
        char *Module = Alloc.Allocate<char>(Size);
        std::memcpy(Module, (void *)ContentsReference.begin(), Size);
        Modules.push_back({Module, Size});
      }
    }
  }
  return true;
}

int main(int argc, char **argv) {
  PROGRAM_START(argc, argv);
  INITIALIZE_LLVM();

  // Command line handling.
  using namespace llvm::cl;
  static OptionCategory Visible("Specific Options");
  HideUnrelatedOptions({&Visible});

  list<std::string> InputNames(Positional, desc("compiled_swift_file1.o ..."),
                               OneOrMore, cat(Visible));

  opt<bool> DumpModule(
      "dump-module",
      desc("Dump the imported module after checking it imports just fine"),
      cat(Visible));

  opt<bool> Verbose("verbose", desc("Dump informations on the loaded module"),
                    cat(Visible));

  opt<std::string> ModuleCachePath(
      "module-cache-path", desc("Clang module cache path"), cat(Visible));

  opt<std::string> DumpDeclFromMangled(
      "decl-from-mangled", desc("dump decl from mangled names list"),
      cat(Visible));

  opt<std::string> DumpTypeFromMangled(
      "type-from-mangled", desc("dump type from mangled names list"),
      cat(Visible));

  opt<std::string> ResourceDir(
      "resource-dir",
      desc("The directory that holds the compiler resource files"),
      cat(Visible));

  ParseCommandLineOptions(argc, argv);
  // Unregister our options so they don't interfere with the command line
  // parsing in CodeGen/BackendUtil.cpp.
  ModuleCachePath.removeArgument();
  DumpModule.removeArgument();
  DumpTypeFromMangled.removeArgument();
  InputNames.removeArgument();

  auto validateInputFile = [](std::string Filename) {
    if (Filename.empty())
      return true;
    if (!llvm::sys::fs::exists(llvm::Twine(Filename))) {
      llvm::errs() << Filename << " does not exists, exiting.\n";
      return false;
    }
    if (!llvm::sys::fs::is_regular_file(llvm::Twine(Filename))) {
      llvm::errs() << Filename << " is not a regular file, exiting.\n";
      return false;
    }
    return true;
  };

  if (!validateInputFile(DumpTypeFromMangled))
    return 1;
  if (!validateInputFile(DumpDeclFromMangled))
    return 1;

  // Fetch the serialized module bitstreams from the Mach-O files and
  // register them with the module loader.
  llvm::SmallVector<std::pair<char *, uint64_t>, 8> Modules;
  if (!collectASTModules(InputNames, Modules))
    return 1;

  if (Modules.empty())
    return 0;

  swift::serialization::ValidationInfo info;
  swift::serialization::ExtendedValidationInfo extendedInfo;
  for (auto &Module : Modules) {
    if (!validateModule(StringRef(Module.first, Module.second), Verbose, info,
                        extendedInfo)) {
      llvm::errs() << "Malformed module!\n";
      return 1;
    }
  }

  // Create a Swift compiler.
  llvm::SmallVector<std::string, 4> modules;
  swift::CompilerInstance CI;
  swift::CompilerInvocation Invocation;

  Invocation.setMainExecutablePath(
      llvm::sys::fs::getMainExecutable(argv[0],
          reinterpret_cast<void *>(&anchorForGetMainExecutable)));

  // Infer SDK and Target triple from the module.
  Invocation.setSDKPath(extendedInfo.getSDKPath());
  Invocation.setTargetTriple(info.targetTriple);

  Invocation.setModuleName("lldbtest");
  Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;

  if (!ResourceDir.empty()) {
    Invocation.setRuntimeResourcePath(ResourceDir);
  }

  if (CI.setup(Invocation))
    return 1;

  for (auto &Module : Modules)
    if (!parseASTSection(CI.getSerializedModuleLoader(),
                         StringRef(Module.first, Module.second), modules))
      return 1;

  // Attempt to import all modules we found.
  for (auto path : modules) {
    if (Verbose)
      llvm::outs() << "Importing " << path << "... ";

#ifdef SWIFT_SUPPORTS_SUBMODULES
    std::vector<std::pair<swift::Identifier, swift::SourceLoc> > AccessPath;
    for (auto i = llvm::sys::path::begin(path);
         i != llvm::sys::path::end(path); ++i)
      if (!llvm::sys::path::is_separator((*i)[0]))
          AccessPath.push_back({ CI.getASTContext().getIdentifier(*i),
                                 swift::SourceLoc() });
#else
    std::vector<std::pair<swift::Identifier, swift::SourceLoc> > AccessPath;
    AccessPath.push_back({ CI.getASTContext().getIdentifier(path),
                           swift::SourceLoc() });
#endif

    auto Module = CI.getASTContext().getModule(AccessPath);
    if (!Module) {
      if (Verbose)
        llvm::errs() << "FAIL!\n";
      return 1;
    }
    if (Verbose)
      llvm::outs() << "ok!\n";
    if (DumpModule) {
      llvm::SmallVector<swift::Decl*, 10> Decls;
      Module->getTopLevelDecls(Decls);
      for (auto Decl : Decls) {
        Decl->dump(llvm::outs());
      }
    }
    if (!DumpTypeFromMangled.empty()) {
      llvm::SmallVector<std::string, 8> MangledNames;
      collectMangledNames(DumpTypeFromMangled, MangledNames);
      resolveTypeFromMangledNameList(CI.getASTContext(), MangledNames);
    }
    if (!DumpDeclFromMangled.empty()) {
      llvm::SmallVector<std::string, 8> MangledNames;
      collectMangledNames(DumpDeclFromMangled, MangledNames);
      resolveDeclFromMangledNameList(CI.getASTContext(), MangledNames);
    }
  }
  return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperQtWidgetView.h"

#include "otbWrapperQtWidgetParameterGroup.h"
#include "otbWrapperQtWidgetParameterFactory.h"

#include "otbWrapperOutputImageParameter.h"

#include "itksys/SystemTools.hxx"

namespace otb
{
namespace Wrapper
{

QtWidgetView::QtWidgetView(Application* app)
{

  m_Model = new QtWidgetModel(app);
  m_Application = app;
  //m_MainWindow = new QWidget();
  //m_Application->RegisterListener( this );

}

QtWidgetView::~QtWidgetView()
{

}

void QtWidgetView::CreateGui()
{
  // Create a VBoxLayout with the header, the input widgets, and the footer
  QVBoxLayout *mainLayout = new QVBoxLayout();

  mainLayout->addWidget(CreateHeader());
  mainLayout->addWidget(CreateInputWidgets());
  mainLayout->addWidget(CreateFooter());

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(mainLayout);

  // Put the main group inside a scroll area
  QScrollArea *scrollArea = new QScrollArea;
  scrollArea->setWidget(mainGroup);
  scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

  QVBoxLayout *scrollLayout = new QVBoxLayout();
  scrollLayout->addWidget(scrollArea);

  // Make the scroll layout the main layout
  this->setLayout(scrollLayout);
  this->setWindowIcon(QIcon( ":/otb_small.png" ));
  this->setWindowTitle(QString(m_Model->GetApplication()->GetName()).append(" - version ").append(OTB_VERSION_STRING));

  this->show();
}

QWidget* QtWidgetView::CreateHeader()
{
  // an HLayout with the description of the application, and two icons
  QHBoxLayout *headerLayout = new QHBoxLayout;

  QGroupBox *headerGroup = new QGroupBox;
  headerGroup->setStyleSheet("border: 1px solid gray");

  headerGroup->setFixedHeight(50);
  headerGroup->setContentsMargins(0,0,0,0);
  headerLayout->setContentsMargins(5,5,5,5);

  QLabel *iconOTBLabel = new QLabel;
  iconOTBLabel->setStyleSheet("border-style: none");
  //iconOTBLabel->setPixmap(QIcon( ":/otb_big.png" ).pixmap(32, QIcon::Normal, QIcon::On));

  QLabel *descriptionLabel = new QLabel;
  descriptionLabel->setStyleSheet("border-style: none");
  QString descriptionLabelText(m_Model->GetApplication()->GetDescription());
  descriptionLabel->setText(descriptionLabelText);

  QLabel *iconCNESLabel = new QLabel;
  iconCNESLabel->setStyleSheet("border-style: none");
  //iconCNESLabel->setPixmap(QIcon( ":/cnes.png" ).pixmap(32, QIcon::Normal, QIcon::On));

  headerLayout->addWidget(iconOTBLabel);
  headerLayout->addStretch();
  headerLayout->addWidget(descriptionLabel);
  headerLayout->addStretch();
  headerLayout->addWidget(iconCNESLabel);
  headerGroup->setLayout(headerLayout);

  return headerGroup;
}

QWidget* QtWidgetView::CreateInputWidgets()
{
  QtWidgetParameterBase* params = QtWidgetParameterFactory::CreateQtWidget(m_Model->GetApplication()->GetParameterList(), m_Model);
  return params;
}

QWidget* QtWidgetView::CreateFooter()
{
  // an HLayout with two buttons : Execute and Quit
  QGroupBox *footerGroup = new QGroupBox;
  QHBoxLayout *footerLayout = new QHBoxLayout;

  footerGroup->setFixedHeight(40);
  footerGroup->setContentsMargins(0,0,0,0);
  footerLayout->setContentsMargins(5,5,5,5);

  m_ExecButton = new QPushButton(footerGroup);
  m_ExecButton->setDefault(true);
  m_ExecButton->setText(QObject::tr("Execute"));
  connect( m_ExecButton, SIGNAL(clicked()), this, SLOT(ExecuteAndWriteOutputSlot() ) );

  m_QuitButton = new QPushButton(footerGroup);
  m_QuitButton->setText(QObject::tr("Quit"));
  connect( m_QuitButton, SIGNAL(clicked()), this, SLOT(CloseSlot()) );

  // Put the buttons on the right
  //footerLayout->addWidget(m_ProgressLabel);
  footerLayout->addStretch();
  footerLayout->addWidget(m_ExecButton);
  footerLayout->addWidget(m_QuitButton);
  footerGroup->setLayout(footerLayout);

  return footerGroup;
}

void QtWidgetView::ExecuteAndWriteOutputSlot()
{
  m_Model->ExecuteAndWriteOutput();

  QWidget * progWin = new QWidget();
  progWin->setWindowTitle( "Progress reporting..." );

  QVBoxLayout *layout = new QVBoxLayout;

  std::vector< QProgressBar * > barListIntern, barListWriter;
  std::vector< QLabel * > labelListIntern, labelListWriter;
  if( m_Application->GetInternalProcessList().size() != m_Application->GetInternalProcessListName().size())
    {
      itkGenericExceptionMacro ("Internal process list and list name size mismatch...");
    }

  // Build the window : First internal process
  for(unsigned int ii=0; ii<m_Application->GetInternalProcessList().size(); ii++)
    {
      QLabel *label = new QLabel(QString(m_Application->GetInternalProcessListName()[ii].c_str()));
      QProgressBar * bar = new QProgressBar();
      layout->addWidget(label);
      layout->addWidget(bar);
      barListIntern.push_back(bar);
      labelListIntern.push_back(label);
    }

  // Build the window : then writers
  unsigned int nbOutput = 0;
  std::vector<std::string> paramList = m_Application->GetParametersKeys(true);
  for (std::vector<std::string>::const_iterator it = paramList.begin();
       it != paramList.end();
       ++it)
    {
      if ( m_Application->GetParameterType(*it) == ParameterType_OutputImage)
        {
          itk::OStringStream oss;
          // create the label including the output description
          Parameter* param =  m_Application->GetParameterByKey(*it);
          OutputImageParameter* outputParam = dynamic_cast<OutputImageParameter*>(param);
          oss << "Writer "<< nbOutput << ": ";
          oss << outputParam->GetName() <<".";
          QLabel *label = new QLabel(QString(oss.str().c_str()));
          QProgressBar * bar = new QProgressBar();
          bar->setToolTip( QString( outputParam->GetDescription()) );
          layout->addWidget(label);
          layout->addWidget(bar);
          barListWriter.push_back(bar);
          labelListWriter.push_back(label);
          nbOutput++;
        }
    }

  // Display the window
  progWin->setLayout(layout);
  progWin->update();
  progWin->show();
  // PAY ATTENTION : launching a GUI modification in a slot is simple : you have to call the following method
  // to update the general GUI
  QCoreApplication::processEvents();

  // Watch process
  double curWriterProgress = 0;
  unsigned int curWriter = 0;
  unsigned int countt = 0;
  while( m_Application->GetExecuteAndWriteOutputDone() == false )
    {
      itk::OStringStream oss;
      oss.str("");

      // Internal DoExecute process watcher
      std::vector<double> progCount = m_Application->GetDoExecuteProgress();
      for(unsigned int i=0; i<progCount.size(); i++)
        {
          barListIntern[i]->setValue( static_cast<int>(progCount[i]*100 ));
          progWin->update();
          QCoreApplication::processEvents();
        }

      // Writer watcher
      if(  nbOutput > 0)
        {
          double curProg = m_Application->GetExecuteProgress();

          if( curProg > -1 )
            {
              if( curWriterProgress > curProg )
                {
                  curWriter++;
                }

              barListWriter[curWriter]->setValue( static_cast<int>(curProg*100) );
              curWriterProgress = curProg;
              progWin->update();
              QCoreApplication::processEvents();
            }
        }

      itksys::SystemTools::sleep(1);

    }
  progWin->close();
}

void QtWidgetView::CloseSlot()
{
  this->close();
}

}
}
<commit_msg>BUG: wrong previous commit<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperQtWidgetView.h"

#include "otbWrapperQtWidgetParameterGroup.h"
#include "otbWrapperQtWidgetParameterFactory.h"

#include "otbWrapperOutputImageParameter.h"

#include "itksys/SystemTools.hxx"

namespace otb
{
namespace Wrapper
{

QtWidgetView::QtWidgetView(Application* app)
{

  m_Model = new QtWidgetModel(app);
  m_Application = app;
  //m_MainWindow = new QWidget();
  //m_Application->RegisterListener( this );

}

QtWidgetView::~QtWidgetView()
{

}

void QtWidgetView::CreateGui()
{
  // Create a VBoxLayout with the header, the input widgets, and the footer
  QVBoxLayout *mainLayout = new QVBoxLayout();

  mainLayout->addWidget(CreateHeader());
  mainLayout->addWidget(CreateInputWidgets());
  mainLayout->addWidget(CreateFooter());

  QGroupBox *mainGroup = new QGroupBox();
  mainGroup->setLayout(mainLayout);

  // Put the main group inside a scroll area
  QScrollArea *scrollArea = new QScrollArea;
  scrollArea->setWidget(mainGroup);
  scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

  QVBoxLayout *scrollLayout = new QVBoxLayout();
  scrollLayout->addWidget(scrollArea);

  // Make the scroll layout the main layout
  this->setLayout(scrollLayout);
  this->setWindowIcon(QIcon( ":/otb_small.png" ));
  this->setWindowTitle(QString(m_Model->GetApplication()->GetName()).append(" - version ").append(OTB_VERSION_STRING));

  this->show();
}

QWidget* QtWidgetView::CreateHeader()
{
  // an HLayout with the description of the application, and two icons
  QHBoxLayout *headerLayout = new QHBoxLayout;

  QGroupBox *headerGroup = new QGroupBox;
  headerGroup->setStyleSheet("border: 1px solid gray");

  headerGroup->setFixedHeight(50);
  headerGroup->setContentsMargins(0,0,0,0);
  headerLayout->setContentsMargins(5,5,5,5);

  QLabel *iconOTBLabel = new QLabel;
  iconOTBLabel->setStyleSheet("border-style: none");
  //iconOTBLabel->setPixmap(QIcon( ":/otb_big.png" ).pixmap(32, QIcon::Normal, QIcon::On));

  QLabel *descriptionLabel = new QLabel;
  descriptionLabel->setStyleSheet("border-style: none");
  QString descriptionLabelText(m_Model->GetApplication()->GetDescription());
  descriptionLabel->setText(descriptionLabelText);

  QLabel *iconCNESLabel = new QLabel;
  iconCNESLabel->setStyleSheet("border-style: none");
  //iconCNESLabel->setPixmap(QIcon( ":/cnes.png" ).pixmap(32, QIcon::Normal, QIcon::On));

  headerLayout->addWidget(iconOTBLabel);
  headerLayout->addStretch();
  headerLayout->addWidget(descriptionLabel);
  headerLayout->addStretch();
  headerLayout->addWidget(iconCNESLabel);
  headerGroup->setLayout(headerLayout);

  return headerGroup;
}

QWidget* QtWidgetView::CreateInputWidgets()
{
  QtWidgetParameterBase* params = QtWidgetParameterFactory::CreateQtWidget(m_Model->GetApplication()->GetParameterList(), m_Model);
  return params;
}

QWidget* QtWidgetView::CreateFooter()
{
  // an HLayout with two buttons : Execute and Quit
  QGroupBox *footerGroup = new QGroupBox;
  QHBoxLayout *footerLayout = new QHBoxLayout;

  footerGroup->setFixedHeight(40);
  footerGroup->setContentsMargins(0,0,0,0);
  footerLayout->setContentsMargins(5,5,5,5);

  m_ExecButton = new QPushButton(footerGroup);
  m_ExecButton->setDefault(true);
  m_ExecButton->setText(QObject::tr("Execute"));
  connect( m_ExecButton, SIGNAL(clicked()), this, SLOT(ExecuteAndWriteOutputSlot() ) );

  m_QuitButton = new QPushButton(footerGroup);
  m_QuitButton->setText(QObject::tr("Quit"));
  connect( m_QuitButton, SIGNAL(clicked()), this, SLOT(CloseSlot()) );

  // Put the buttons on the right
  //footerLayout->addWidget(m_ProgressLabel);
  footerLayout->addStretch();
  footerLayout->addWidget(m_ExecButton);
  footerLayout->addWidget(m_QuitButton);
  footerGroup->setLayout(footerLayout);

  return footerGroup;
}

void QtWidgetView::ExecuteAndWriteOutputSlot()
{
  m_Model->ExecuteAndWriteOutput();

  QWidget * progWin = new QWidget();
  progWin->setWindowTitle( "Progress reporting..." );

  QVBoxLayout *layout = new QVBoxLayout;

  std::vector< QProgressBar * > barListIntern, barListWriter;
  std::vector< QLabel * > labelListIntern, labelListWriter;
  if( m_Application->GetInternalProcessList().size() != m_Application->GetInternalProcessListName().size())
    {
      itkGenericExceptionMacro ("Internal process list and list name size mismatch...");
    }

  // Build the window : First internal process
  for(unsigned int ii=0; ii<m_Application->GetInternalProcessList().size(); ii++)
    {
      QLabel *label = new QLabel(QString(m_Application->GetInternalProcessListName()[ii].c_str()));
      QProgressBar * bar = new QProgressBar();
      layout->addWidget(label);
      layout->addWidget(bar);
      barListIntern.push_back(bar);
      labelListIntern.push_back(label);
    }

  // Build the window : then writers
  unsigned int nbOutput = 0;
  std::vector<std::string> paramList = m_Application->GetParametersKeys(true);
  for (std::vector<std::string>::const_iterator it = paramList.begin();
       it != paramList.end();
       ++it)
    {
      if ( m_Application->GetParameterType(*it) == ParameterType_OutputImage)
        {
          itk::OStringStream oss;
          // create the label including the output description
          Parameter* param =  m_Application->GetParameterByKey(*it);
          OutputImageParameter* outputParam = dynamic_cast<OutputImageParameter*>(param);
          oss << "Writer "<< nbOutput << ": ";
          oss << outputParam->GetName() <<".";
          QLabel *label = new QLabel(QString(oss.str().c_str()));
          QProgressBar * bar = new QProgressBar();
          bar->setToolTip( QString( outputParam->GetDescription()) );
          layout->addWidget(label);
          layout->addWidget(bar);
          barListWriter.push_back(bar);
          labelListWriter.push_back(label);
          nbOutput++;
        }
    }

  // Display the window
  progWin->setLayout(layout);
  progWin->update();
  progWin->show();
  // PAY ATTENTION : launching a GUI modification in a slot is simple : you have to call the following method
  // to update the general GUI
  QCoreApplication::processEvents();

  // Watch process
  double curWriterProgress = 0;
  unsigned int curWriter = 0;
  unsigned int countt = 0;
  while( m_Application->GetExecuteAndWriteOutputDone() == false )
    {
      itk::OStringStream oss;
      oss.str("");

      // Internal DoExecute process watcher
      std::vector<double> progCount = m_Application->GetDoExecuteProgress();
      for(unsigned int i=0; i<progCount.size(); i++)
        {
          barListIntern[i]->setValue( static_cast<int>(progCount[i]*100 ));
          progWin->update();
          QCoreApplication::processEvents();
        }

      // Writer watcher
      if(  nbOutput > 0)
        {
          double curProg = m_Application->GetExecuteProgress();

          if( curProg > -1 )
            {
              if( curWriterProgress > curProg )
                {
                  curWriter++;
                }

              barListWriter[curWriter]->setValue( static_cast<int>(curProg*100) );
              curWriterProgress = curProg;
              progWin->update();
              QCoreApplication::processEvents();
            }
        }

      itksys::SystemTools::Delay(1000);

    }
  progWin->close();
}

void QtWidgetView::CloseSlot()
{
  this->close();
}

}
}
<|endoftext|>


<commit_before>#include "calibration/Angular_Velocity_Calibration_Wizard.h"
#include <QPushButton>

#include "sz_math.hpp"
#include "sz_Calibration_Data.hpp"

#include "ui_Angular_Velocity_Calibration_Wizard_Reset.h"
#include "ui_Angular_Velocity_Calibration_Wizard_Instructions.h"
#include "ui_Angular_Velocity_Calibration_Wizard_Collect.h"
#include "ui_Angular_Velocity_Calibration_Wizard_Done.h"

constexpr std::chrono::seconds DATA_COLLECTION_DURATION(10);

Angular_Velocity_Calibration_Wizard::Angular_Velocity_Calibration_Wizard(silk::HAL& hal, silk::Comms& comms, silk::node::gs::Node_ptr node, size_t output_idx, QWidget* parent)
    : QDialog(parent)
    , m_hal(hal)
    , m_comms(comms)
    , m_node(node)
    , m_output(node->outputs[output_idx])
{
    m_stream = std::static_pointer_cast<silk::stream::gs::Angular_Velocity>(m_output.stream);

    m_hal.set_stream_telemetry_active(m_output.stream->name, true);

    m_initial_calibration = get_calibration_points();
    set_calibration_points(sz::calibration::Angular_Velocity_Points());

    m_step = Step::RESET;

    setLayout(new QVBoxLayout(this));
    layout()->setMargin(0);
    layout()->setSpacing(0);
    layout()->setContentsMargins(4, 4, 4, 4);

    prepare_step();
}

void Angular_Velocity_Calibration_Wizard::advance()
{
    if (m_step == Step::RESET)
    {
        m_step = Step::SHOW_INSTRUCTIONS;
    }
    else if (m_step == Step::SHOW_INSTRUCTIONS)
    {
        m_step = Step::COLLECT;
    }
    else if (m_step == Step::COLLECT)
    {
        m_connection.disconnect();
        m_step = Step::DONE;
    }

    prepare_step();
}

void Angular_Velocity_Calibration_Wizard::cancel()
{
    m_connection.disconnect();

    set_calibration_points(m_initial_calibration);

    close();
}

void Angular_Velocity_Calibration_Wizard::prepare_step()
{
    delete m_content;
    m_content = nullptr;

    if (m_step == Step::RESET)
    {
        m_content = new QWidget(this);
        layout()->addWidget(m_content);

        Ui::Angular_Velocity_Calibration_Wizard_Reset ui;
        ui.setupUi(m_content);
        if (m_initial_calibration.points.size() > 0)
        {
            ui.info->setText(q::util::format2<std::string>("There are currently {} calibration points.\n"
                                                           "Do you want to clear these points or keep them?", m_initial_calibration.points.size()).c_str());
            auto* clear = ui.buttonBox->addButton("Clear", QDialogButtonBox::ResetRole);
            QObject::connect(clear, &QPushButton::released, [this]() { advance(); });

            auto* keep = ui.buttonBox->addButton("Keep", QDialogButtonBox::AcceptRole);
            QObject::connect(keep, &QPushButton::released, [this]() { m_crt_calibration = m_initial_calibration; advance(); });
        }
        else
        {
            ui.info->setText("There are no existing calibration data points.\nLet's add one");
            auto* ok = ui.buttonBox->addButton("Ok", QDialogButtonBox::AcceptRole);
            QObject::connect(ok, &QPushButton::released, [this]() { advance(); });
        }

        QObject::connect(ui.buttonBox, &QDialogButtonBox::rejected, [this]() { cancel(); });
    }
    else if (m_step == Step::SHOW_INSTRUCTIONS)
    {
        m_content = new QWidget(this);
        layout()->addWidget(m_content);

        Ui::Angular_Velocity_Calibration_Wizard_Instructions ui;
        ui.setupUi(m_content);
        ui.instructions->setText(q::util::format2<std::string>(
                                    "Please keep the UAV perfectly still for {} seconds.\n"
                                    "\n"
                                    "Ready?", DATA_COLLECTION_DURATION).c_str());

        QObject::connect(ui.buttonBox, &QDialogButtonBox::accepted, [this]() { advance(); });
        QObject::connect(ui.buttonBox, &QDialogButtonBox::rejected, [this]() { cancel(); });
    }
    else if (m_step == Step::COLLECT)
    {
        m_content = new QWidget(this);
        layout()->addWidget(m_content);

        Ui::Angular_Velocity_Calibration_Wizard_Collect ui;
        ui.setupUi(m_content);
        auto* info = ui.info;
        auto* progress = ui.progressBar;

        m_samples.clear();

        QObject::connect(ui.buttonBox, &QDialogButtonBox::rejected, [this]() { cancel(); });

        m_connection = m_stream->samples_available_signal.connect([this, info, progress](silk::stream::gs::Angular_Velocity::Samples const& samples)
        {
            on_samples_received(samples);
            info->setText(q::util::format2<std::string>("Collected {} samples...", m_samples.size()).c_str());
            size_t needed_samples = std::chrono::seconds(DATA_COLLECTION_DURATION).count() * m_output.rate;
            progress->setValue(float(m_samples.size() * 100.f) / float(needed_samples));
            if (m_samples.size() >= needed_samples)
            {
                advance();
            }
        });
    }
    else if (m_step == Step::DONE)
    {
        math::vec3f bias = std::accumulate(m_samples.begin(), m_samples.end(), math::vec3f());
        bias /= static_cast<float>(m_samples.size());

        m_content = new QWidget(this);
        layout()->addWidget(m_content);

        Ui::Angular_Velocity_Calibration_Wizard_Done ui;
        ui.setupUi(m_content);

        ui.info->setText("Done!\n"
                         "The new Bias is:");
        ui.bias->setText(q::util::format2<std::string>("{}", bias).c_str());

        sz::calibration::Angular_Velocity point;
        point.temperature = 0;
        point.bias = math::vec3f(bias);
        m_crt_calibration.points.push_back(point);

        QObject::connect(ui.temperature, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value)
        {
            m_crt_calibration.points.back().temperature = static_cast<float>(value);
        });

        QObject::connect(ui.buttonBox, &QDialogButtonBox::accepted, [this]()
        {
            set_calibration_points(m_crt_calibration);
            this->accept();
        });
        QObject::connect(ui.buttonBox, &QDialogButtonBox::rejected, [this]() { cancel(); });
    }
}

void Angular_Velocity_Calibration_Wizard::set_calibration_points(sz::calibration::Angular_Velocity_Points const& data)
{
    rapidjson::Document calibrationj;
    calibrationj.SetObject();
    autojsoncxx::to_document(data, calibrationj);

    q::Path path("Calibration");
    path += m_output.name;

    rapidjson::Document configj = jsonutil::clone_value(m_node->config);
    if (!jsonutil::remove_value(configj, path))
    {
        QASSERT(0);
        return;
    }

    if (!jsonutil::add_value(configj, path, std::move(calibrationj), configj.GetAllocator()))
    {
        QASSERT(0);
        return;
    }

    m_hal.set_node_config(m_node, configj);
}

auto Angular_Velocity_Calibration_Wizard::get_calibration_points() const -> sz::calibration::Angular_Velocity_Points
{
    q::Path path("Calibration");
    path += m_output.name;
    auto const* calibrationj = jsonutil::find_value(m_node->config, path);
    if (!calibrationj)
    {
        QASSERT(0);
        return sz::calibration::Angular_Velocity_Points();
    }
    sz::calibration::Angular_Velocity_Points calibration;
    autojsoncxx::error::ErrorStack result;
    if (!autojsoncxx::from_value(calibration, *calibrationj, result))
    {
        QASSERT(0);
        return sz::calibration::Angular_Velocity_Points();
    }
    return calibration;
}

void Angular_Velocity_Calibration_Wizard::on_samples_received(silk::stream::gs::Angular_Velocity::Samples const& samples)
{
    m_samples.reserve(m_samples.size() + samples.size());
    for (auto const& s: samples)
    {
        m_samples.push_back(s.value);
    }
}

<commit_msg>Fixed broken cancel<commit_after>#include "calibration/Angular_Velocity_Calibration_Wizard.h"
#include <QPushButton>

#include "sz_math.hpp"
#include "sz_Calibration_Data.hpp"

#include "ui_Angular_Velocity_Calibration_Wizard_Reset.h"
#include "ui_Angular_Velocity_Calibration_Wizard_Instructions.h"
#include "ui_Angular_Velocity_Calibration_Wizard_Collect.h"
#include "ui_Angular_Velocity_Calibration_Wizard_Done.h"

constexpr std::chrono::seconds DATA_COLLECTION_DURATION(10);

Angular_Velocity_Calibration_Wizard::Angular_Velocity_Calibration_Wizard(silk::HAL& hal, silk::Comms& comms, silk::node::gs::Node_ptr node, size_t output_idx, QWidget* parent)
    : QDialog(parent)
    , m_hal(hal)
    , m_comms(comms)
    , m_node(node)
    , m_output(node->outputs[output_idx])
{
    m_stream = std::static_pointer_cast<silk::stream::gs::Angular_Velocity>(m_output.stream);

    m_hal.set_stream_telemetry_active(m_output.stream->name, true);

    m_initial_calibration = get_calibration_points();
    set_calibration_points(sz::calibration::Angular_Velocity_Points());

    m_step = Step::RESET;

    setLayout(new QVBoxLayout(this));
    layout()->setMargin(0);
    layout()->setSpacing(0);
    layout()->setContentsMargins(4, 4, 4, 4);

    prepare_step();
}

void Angular_Velocity_Calibration_Wizard::advance()
{
    if (m_step == Step::RESET)
    {
        m_step = Step::SHOW_INSTRUCTIONS;
    }
    else if (m_step == Step::SHOW_INSTRUCTIONS)
    {
        m_step = Step::COLLECT;
    }
    else if (m_step == Step::COLLECT)
    {
        m_connection.disconnect();
        m_step = Step::DONE;
    }

    prepare_step();
}

void Angular_Velocity_Calibration_Wizard::cancel()
{
    m_connection.disconnect();

    set_calibration_points(m_initial_calibration);

    close();
}

void Angular_Velocity_Calibration_Wizard::prepare_step()
{
    delete m_content;
    m_content = nullptr;

    if (m_step == Step::RESET)
    {
        m_content = new QWidget(this);
        layout()->addWidget(m_content);

        Ui::Angular_Velocity_Calibration_Wizard_Reset ui;
        ui.setupUi(m_content);
        if (m_initial_calibration.points.size() > 0)
        {
            ui.info->setText(q::util::format2<std::string>("There are currently {} calibration points.\n"
                                                           "Do you want to clear these points or keep them?", m_initial_calibration.points.size()).c_str());
            auto* clear = ui.buttonBox->addButton("Clear", QDialogButtonBox::ResetRole);
            QObject::connect(clear, &QPushButton::released, [this]() { advance(); });

            auto* keep = ui.buttonBox->addButton("Keep", QDialogButtonBox::AcceptRole);
            QObject::connect(keep, &QPushButton::released, [this]() { m_crt_calibration = m_initial_calibration; advance(); });
        }
        else
        {
            ui.info->setText("There are no existing calibration data points.\nLet's add one");
            auto* ok = ui.buttonBox->addButton("Ok", QDialogButtonBox::AcceptRole);
            QObject::connect(ok, &QPushButton::released, [this]() { advance(); });
        }

        QObject::connect(ui.buttonBox, &QDialogButtonBox::rejected, [this]()
        {
            cancel();
        });
    }
    else if (m_step == Step::SHOW_INSTRUCTIONS)
    {
        m_content = new QWidget(this);
        layout()->addWidget(m_content);

        Ui::Angular_Velocity_Calibration_Wizard_Instructions ui;
        ui.setupUi(m_content);
        ui.instructions->setText(q::util::format2<std::string>(
                                    "Please keep the UAV perfectly still for {} seconds.\n"
                                    "\n"
                                    "Ready?", DATA_COLLECTION_DURATION).c_str());

        QObject::connect(ui.buttonBox, &QDialogButtonBox::accepted, [this]()
        {
            advance();
        });
        QObject::connect(ui.buttonBox, &QDialogButtonBox::rejected, [this]()
        {
            cancel();
        });
    }
    else if (m_step == Step::COLLECT)
    {
        m_content = new QWidget(this);
        layout()->addWidget(m_content);

        Ui::Angular_Velocity_Calibration_Wizard_Collect ui;
        ui.setupUi(m_content);
        auto* info = ui.info;
        auto* progress = ui.progressBar;

        m_samples.clear();

        QObject::connect(ui.buttonBox, &QDialogButtonBox::rejected, [this]() { cancel(); });

        m_connection = m_stream->samples_available_signal.connect([this, info, progress](silk::stream::gs::Angular_Velocity::Samples const& samples)
        {
            on_samples_received(samples);
            info->setText(q::util::format2<std::string>("Collected {} samples...", m_samples.size()).c_str());
            size_t needed_samples = std::chrono::seconds(DATA_COLLECTION_DURATION).count() * m_output.rate;
            progress->setValue(float(m_samples.size() * 100.f) / float(needed_samples));
            if (m_samples.size() >= needed_samples)
            {
                advance();
            }
        });
    }
    else if (m_step == Step::DONE)
    {
        math::vec3f bias = std::accumulate(m_samples.begin(), m_samples.end(), math::vec3f());
        bias /= static_cast<float>(m_samples.size());

        m_content = new QWidget(this);
        layout()->addWidget(m_content);

        Ui::Angular_Velocity_Calibration_Wizard_Done ui;
        ui.setupUi(m_content);

        ui.info->setText("Done!\n"
                         "The new Bias is:");
        ui.bias->setText(q::util::format2<std::string>("{}", bias).c_str());

        sz::calibration::Angular_Velocity point;
        point.temperature = 0;
        point.bias = math::vec3f(bias);
        m_crt_calibration.points.push_back(point);

        QObject::connect(ui.temperature, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value)
        {
            m_crt_calibration.points.back().temperature = static_cast<float>(value);
        });

        QObject::connect(ui.buttonBox, &QDialogButtonBox::accepted, [this]()
        {
            set_calibration_points(m_crt_calibration);
            this->accept();
        });

        QDialogButtonBox* buttonBox = ui.buttonBox;//make a copy as the ui will go out of scope
        QObject::connect(ui.buttonBox, &QDialogButtonBox::clicked, [buttonBox, this](QAbstractButton* button)
        {
            if (buttonBox->buttonRole(button) == QDialogButtonBox::DestructiveRole)
            {
                cancel();
            }
        });
    }
}

void Angular_Velocity_Calibration_Wizard::set_calibration_points(sz::calibration::Angular_Velocity_Points const& data)
{
    rapidjson::Document calibrationj;
    calibrationj.SetObject();
    autojsoncxx::to_document(data, calibrationj);

    q::Path path("Calibration");
    path += m_output.name;

    rapidjson::Document configj = jsonutil::clone_value(m_node->config);
    if (!jsonutil::remove_value(configj, path))
    {
        QASSERT(0);
        return;
    }

    if (!jsonutil::add_value(configj, path, std::move(calibrationj), configj.GetAllocator()))
    {
        QASSERT(0);
        return;
    }

    m_hal.set_node_config(m_node, configj);
}

auto Angular_Velocity_Calibration_Wizard::get_calibration_points() const -> sz::calibration::Angular_Velocity_Points
{
    q::Path path("Calibration");
    path += m_output.name;
    auto const* calibrationj = jsonutil::find_value(m_node->config, path);
    if (!calibrationj)
    {
        QASSERT(0);
        return sz::calibration::Angular_Velocity_Points();
    }
    sz::calibration::Angular_Velocity_Points calibration;
    autojsoncxx::error::ErrorStack result;
    if (!autojsoncxx::from_value(calibration, *calibrationj, result))
    {
        QASSERT(0);
        return sz::calibration::Angular_Velocity_Points();
    }
    return calibration;
}

void Angular_Velocity_Calibration_Wizard::on_samples_received(silk::stream::gs::Angular_Velocity::Samples const& samples)
{
    m_samples.reserve(m_samples.size() + samples.size());
    for (auto const& s: samples)
    {
        m_samples.push_back(s.value);
    }
}

<|endoftext|>