/*========================== begin_copyright_notice ============================
Copyright (C) 2021 Intel Corporation

SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/

/*!
 * @file This file defines a general utilities library API to be implemented to support GTReplay
 */
#ifndef _GTREPLAY_CRT_H
#define _GTREPLAY_CRT_H
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <list>
#include <map>
#include <utility>
#include <string>
#include <ctime>
#ifndef PIN_CRT
#include <tuple>
#include <ratio>
#include <chrono>
#endif

#include "gtreplay_mutex.h"

using std::vector;
using std::list;
using std::map;
using std::pair;
using std::string;
#ifndef PIN_CRT
using std::tuple;
using namespace std::chrono;
#endif

#if !defined(_MSC_VER)
#   define memcpy_s(dest, destSize, src, count) memcpy(dest, src, count)
#endif

// Type definitions
typedef void* FileHandle;
typedef void* ThreadHandles;
typedef void(*RunHostThreadFunc)(void*);

/***********************************************
 *
 * File manipulation functions
 *
 ***********************************************/
/*
 * Opening a binary file
 *
 * @param[out] file - pointer to the file handle
 * @param[in]  name - the name of the file to be open
 * @return true if the operation succeeds, false otherwise
 */
bool OpenBinFile(FileHandle* file, string& name);

/*
 * Obtaining the size in bytes of a file
 *
 * @return the size in bytes of the file
 * @param[in] file - a file handle
 */
size_t GetFileSize(FileHandle file);

/*
 * Read a given number of characters from a file and stores them in a memory array
 *
 * @param[in] file - a file handle
 * @param[in] buffer - a pointer to an array of characters where to read the file content
 * @param[in] size   - the number of characters to read from the file
 * @note the caller is responsible to allocate a buffer big enough to include the required content
 */
void ReadBinFile(FileHandle file, char* buffer, size_t size);

/*
 * Closing a binary file
 *
 * @param[in] file - a file handle
 */
void CloseBinFile(FileHandle file);

/***********************************************
 *
 * Process and threads manipulation functions
 *
 ***********************************************/

/*
 * Put the process into a sleep state for a given number of seconds
 *
 * @param[in] file - a file handle
 */
void SleepSeconds(uint32_t seconds);

/*
 * Return the current thread ID
 *
 */
uint32_t CurrentThreadID();

/*
 * Create a given number of host threads with a specified entry point
 *
 * @param[in] numOfThreads - the number of threads to create
 * @param[in] func         - the function entry point to each thread
 * @param[in] param        - a parameter to be provided to the entry point function
 * @return an array of thread handles
 */
ThreadHandles CreateHostThreads(uint32_t numOfThreads, RunHostThreadFunc func, void* param);

/*
 * Waiting till all given threads finish
 *
 * @param[in] numOfThreads - the number of threads to create
 * @param[in] t            - an array of thread handles
 */
void JoinHostThreads(uint32_t numOfThreads, ThreadHandles t);


/***********************************************
 *
 * String manipulation
 *
 ***********************************************/

/*
 * Convert decimal number into string
 *
 * @param[in] num   - the number 
 * @param[in] width - amount of format characters
 */
string DecStr(uint32_t& num, unsigned int width = 0);

/*
 * Convert hexadecimal number into string
 *
 * @param[in] num   - the number 
 * @param[in] width - amount of format characters
 */
string HexStr(uint64_t num, int width = 0);

/*
 * Convert a pointer into string
 *
 * @param[in] ptr   - a pointer 
 * @param[in] width - amount of format characters
 */
string HexStr(void* ptr, int width = 0);

/*
 * Convert hexadecimal number into string with prefix
 *
 * @param[in] num    - the number 
 * @param[in] prefix - the prefix 
 * @param[in] width  - amount of format characters
 */
string HexStr(uint64_t num, string prefix, int width);


string ToLower(const string& str);

string ToUpper(const string& str);

void SplitString(const string& str, const char delim, vector<string>& tokens);

bool StrToInt(const string& str, uint32_t& res);

template<typename T>
constexpr bool IsPower2(T value) { return ((value & (value - 1)) == 0); }

// Return a parh separator character
char PathSeparator();

// Create a path from several subdirectories
template<typename T>
inline std::string JoinPath(const T& a)
{
    return a;
}
template<typename T1, typename T2, typename ... Args>
inline std::string JoinPath(const T1& a, const T2& b, const Args&... args)
{
    return a + std::string(1, PathSeparator()) + JoinPath(b, args...);
}

#endif //_GTREPLAY_CRT_H
