//------------------------------------------------------------------------------
// <copyright file="nsextend-inline.h" company="LiquidRobotics">
//
// Copyright (c) 2014 Liquid Robotics, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// This software is associated with a release.  Liquid Robotics makes no
// representation that the design, interfaces or component distribution will
// remain unchanged in future releases.
//
// </copyright>
//
// <summary>
//   Implementation of inline functions and classes used by nsextend module
// </summary>
//
// <owner>Mike Cookson</owner>
//------------------------------------------------------------------------------

#ifndef NSEXTEND_INLINE_H_
#define NSEXTEND_INLINE_H_

#include <string>
#include <stdio.h>
#include <string.h>

inline char __make_digit(int digitVal)
{
	char digitChar;

	if (digitVal < 10)
		digitChar = '0' + digitVal;
	else if (digitVal < 36)
		digitChar = 'A' + (digitVal-10);
	else if (digitVal < 62)
		digitChar = 'a' + (digitVal-36);
	else
		digitChar = '_';

	return digitChar;
}

template<typename T>
char* __num_to_a(const T& __val, char* __s, int __radix = 10)
{
	if ((__radix < 2) || (__radix > 62))
		return NULL;

	char* s = __s;
	T val = __val;

	if ( (((T) -1) < 0)
	  && (val < 0) )
	{
		*s++ = '-';
		val = -val;
	}

	char buffer[101];
	char* pBuffer = &buffer[sizeof(buffer)-1];

	*pBuffer = '\0';

	do
	{
		*--pBuffer = __make_digit(val % __radix);
		val /= __radix;
	} while(val);

	strcpy(s, pBuffer);
	return __s;
}

template<typename T>
std::string __num_to_str(const T& __val, int __radix = 10, std::string::size_type minDigits = 0, std::string::size_type leftPad = 0)
{
	std::string result;

	if ((__radix >= 2) && (__radix <= 62))
	{
		result.reserve((minDigits | leftPad) ? std::max(minDigits, leftPad) : 32);

		T val = __val;
		const bool neg = (((T) -1) < 0) && (val < 0);

		if (neg)
			val = -val;

		char buffer[101];
		char* pBuffer = &buffer[sizeof(buffer)-1];

		*pBuffer = '\0';

		do
		{
			*--pBuffer = __make_digit(val % __radix);
			val /= __radix;
		} while(val);

		result = pBuffer;

		if (minDigits)
		{
			const std::string::size_type minLength = neg ? (minDigits-1) : minDigits;

			if (minLength > result.length())
				result.insert(0, minLength-result.length(), '0');
		}

		if (leftPad)
		{
			const std::string::size_type minLength = neg ? (leftPad-1) : leftPad;

			if (minLength > result.length())
				result.insert(0, minLength-result.length(), ' ');
		}

		if (neg)
			result.insert(0, "-");
	}

	return result;
}

#endif /* NSEXTEND_H_ */
