//
// This source code resides at www.jaeckel.org/ImpliedNormalVolatility.7z .
//
// ======================================================================================
// Copyright © 2022 Peter Jäckel.
//
// Permission to use, copy, modify, and distribute this software is freely granted,
// provided that this notice is preserved.
//
// WARRANTY DISCLAIMER
// The Software is provided "as is" without warranty of any kind, either express or implied,
// including without limitation any implied warranties of condition, uninterrupted use,
// merchantability, fitness for a particular purpose, or non-infringement.
// ======================================================================================
//

#include "XLFunctions.h"

#include <stdlib.h>
#include <limits.h>

#if defined(_MSC_VER)
# define snprintf(buffer,sizeOfBuffer,...) _snprintf_s((buffer),(sizeOfBuffer),_TRUNCATE,__VA_ARGS__)
#endif

static std::vector<XLFunction> &declared_functions() {
    static std::vector<XLFunction> functions;
    return functions;
}

const std::vector<XLFunction>& XLFunction::DeclaredFunctions(){ return declared_functions(); }

// i=1; while [ $i -le 20 ] ; do  echo -n ", const char *a$i" ; i=$[ $i + 1 ] ; done
// i=1; while [ $i -le 20 ] ; do  echo -n ", const std::string &a$i" ; i=$[ $i + 1 ] ; done
int XLFunction::Declare( const char *dll_name, const char *xl_name /* may be null */, const std::string &data_codes, const std::string &argument_names, const std::string &function_description, const char *a1, const char *a2, const char *a3, const char *a4, const char *a5, const char *a6, const char *a7, const char *a8, const char *a9, const char *a10, const char *a11, const char *a12, const char *a13, const char *a14, const char *a15, const char *a16, const char *a17, const char *a18, const char *a19, const char *a20){
    if (0 == xl_name || 0 == xl_name[0])
        xl_name = dll_name;
    std::vector<XLFunction> & functions = declared_functions();
    functions.push_back(XLFunction());
    XLFunction& f = functions[functions.size()-1];
    f.DLLName = dll_name;
    f.XLName = ('.' ==xl_name[0] && 0==xl_name[1]) ? '.' + f.DLLName : xl_name;
    f.DataCodes = data_codes;
    f.ArgumentNames = argument_names;
    f.FunctionDescription = function_description;
    // i=1; while [ $i -le 20 ] ; do  echo -n "a$i," ; i=$[ $i + 1 ] ; done
    const char* arg_descriptions[] = { a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20 };
    int n = 0;
    while (n<20 && 0!=arg_descriptions[n])
        ++n;
    f.ArgumentDescriptions.resize(n);
    for (int i=0;i<n;++i)
        f.ArgumentDescriptions[i] = arg_descriptions[i];
    return (int)functions.size();
}

int XLFunction::DeclareWithSynonyms( const char *dll_name, const char **xl_names /* must be null terminated */, const std::string &data_codes, const std::string &argument_names, const std::string &function_description, const char *a1, const char *a2, const char *a3, const char *a4, const char *a5, const char *a6, const char *a7, const char *a8, const char *a9, const char *a10, const char *a11, const char *a12, const char *a13, const char *a14, const char *a15, const char *a16, const char *a17, const char *a18, const char *a19, const char *a20){
  while (0 != *xl_names) {
    Declare(dll_name,*xl_names,data_codes,argument_names,function_description,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20);
    ++xl_names;
  }
  return 0;
}

int XLFunction::Declare( const char *dll_name, const std::vector<const char*> &xl_names /* need not be null terminated */, const std::string &data_codes, const std::string &argument_names, const std::string &function_description, const char *a1, const char *a2, const char *a3, const char *a4, const char *a5, const char *a6, const char *a7, const char *a8, const char *a9, const char *a10, const char *a11, const char *a12, const char *a13, const char *a14, const char *a15, const char *a16, const char *a17, const char *a18, const char *a19, const char *a20){
  for (int i=0;i<xl_names.size();++i)
    if (0 != xl_names[i])
      Declare(dll_name,xl_names[i],data_codes,argument_names,function_description,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20);
  return 0;
}
