/*
 * Copyright (c) 2019, 2021 Qualcomm Technologies, Inc.
 * All Rights Reserved.
 * Confidential and Proprietary - Qualcomm Technologies, Inc.
 */

#include <cstddef>
#include <cstdint>
#include <new>

#include "CSMCIExample_open.h"
#include "ISMCIExample_invoke.hpp"
#include "object.h"

extern "C" {
#include "qsee_log.h"
}

/** @cond */
class CSMCIExample : public ISMCIExampleImplBase
{
 public:
  CSMCIExample();
  virtual ~CSMCIExample();

  virtual int32_t add(uint32_t int1_val, uint32_t int2_val, uint32_t *result_ptr);

 private:
  /*
   * We use a simple instance counter to create an index for ISMCIExample objects.
   * We never reset its value in this example.
   */
  int index;             ///< Index to identify an ISMCIExample object. */
  static int instances;  ///< Instance counter to create index.
  /** @endcond */
};

int CSMCIExample::instances = 0;

CSMCIExample::CSMCIExample() : index(instances++)
{
  qsee_log(QSEE_LOG_MSG_DEBUG, "Creating new instance with index: %d", index);
}

CSMCIExample::~CSMCIExample()
{
  qsee_log(QSEE_LOG_MSG_DEBUG, "Freeing last reference to instance with index %d", index);
}

/**
 * A simple example showing how to add two values inside the TA and return the
 * result back to the CA.
 */
int32_t CSMCIExample::add(uint32_t val1, uint32_t val2, uint32_t *result_ptr)
{
  qsee_log(QSEE_LOG_MSG_DEBUG, "CSMCIExample::add called for instance index %d", index);

  /* We use saturated math to ensure that the addition doesn't overflow. */
  if (val1 >= UINT32_MAX - val2) {
    *result_ptr = UINT32_MAX;
  } else {
    *result_ptr = val1 + val2;
  }

  return Object_OK;
}

/**
 * This function creates a new ISMCIExample object.
 */
int32_t CSMCIExample_open(Object *objOut)
{
  CSMCIExample *me = new (std::nothrow) CSMCIExample();
  if (!me) {
    qsee_log(QSEE_LOG_MSG_ERROR, "Memory allocation for CSMCIExample failed!");
    return Object_ERROR_MEM;
  }

  *objOut = (Object){ImplBase::invoke, me};
  return Object_OK;
}
