
// zlib open source license
//
// Copyright (c) 2010 to 2013 David Forsgren Piuva
// 
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// 
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 
//    1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
// 
//    2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
// 
//    3. This notice may not be removed or altered from any source
//    distribution.

#include <windows.h>

const int Asci_Indent = 9;
const int Asci_Space = 32;
const int Asci_LineFeed = 10;
const int Asci_CarriageReturn = 13;

char GetChar(char* sInput, int index);
wchar_t GetChar(wchar_t* sInput, int index);
void SetChar(char* sOutput, int index, char newCharacter);
void SetChar(wchar_t* sOutput, int index, wchar_t newCharacter);
char GetSafeChar(char sInput[260], int index);
wchar_t GetSafeChar(wchar_t sInput[260], int index);
void SetSafeChar(char sOutput[260], int index, char newCharacter);
void SetSafeChar(wchar_t sOutput[260], int index, wchar_t newCharacter);

// Returns the index (from 0) to the first wchar_t cFind in wchar_t* sInput.
// iStart can be more than 0 to start searching from another index than 0.
// Example: firstOfLetter(0, L"abccba", L'b') = 1
// Example: firstOfLetter(3, L"abccba", L'b') = (firstOfLetter(0, L"cba", L'b') + 3) = 4
// No maximum length.
int firstOfLetter_wide(int iStart, wchar_t* sInput, wchar_t cFind);
int firstOfLetter(int iStart, char* sInput, char cFind);
// iStart can be less than lengthOfString_wide(sInput) - 1 to start searching from another index than the last character's.
int lastOfLetter_wide(int iStart, wchar_t* sInput, wchar_t cFind);
int lastOfLetter(int iStart, char* sInput, char cFind);
// Like lastOfLetter but always from the last visible wchar_t and looking for both / and \.
int lastSlash(wchar_t* sInput);

// Precondition: |sInput| < 260
// Example:
//     withoutPath(L"folder1\folder2\file.txt", MyString); writes L"file.txt" to MyString
// Example:
//     withoutPath(L"folder1/folder2/file.txt", MyString); writes L"file.txt" to MyString
bool withoutPath(wchar_t* sInput, wchar_t sOutput[260]);

// Returns the index of the first terminating wchar_t.
// lengthOfString_wide(L"abc") = 3 because
//     sInput[0] = L'a'
//     sInput[1] = L'b'
//     sInput[2] = L'c'
//     sInput[3] = L'\0'
// No maximum length.
int lengthOfString_wide(wchar_t* sInput);
int lengthOfString(char* sInput);

// Precondition: |sInput| + |sReplace| + 1 < 260
// Returns sInput with the part after the last L'.' replaced with sReplace.
// Returns sInput, L'.' and sPostfix if no dot exist.
// Example: replaceAfterDot(L"file.txt.zip", MyString, L"ini"); writes L"file.txt.ini" to MyString
// Example: replaceAfterDot(L"file.txt", MyString, L"ini"); writes L"file.ini" to MyString
// Example: replaceAfterDot(L"file", MyString, L"ini"); writes L"file.ini" to MyString
bool replaceAfterDot(wchar_t* sInput, wchar_t sOutput[260], wchar_t* sReplace);

// Writes a copy of sInput in sOutput as wchar_t[260].
// Example:
//     wchar_t* Input;
//     wchar_t Output[260];
//     Input = L"Testing";
//     CopyToFixedSizePath(Input, Output);
//     // Read from Output.
// The inverse conversion is not needed because a wchar_t array is a wchar_t pointer with it's own memory.
void CopyToFixedSizePath(wchar_t* sInput, wchar_t sOutput[260]);

// Returns a pointer to a new dynamic string with the same content as sInput
wchar_t* CopyToNewString(wchar_t* sInput);

// Returns true iff sA equals sB
bool CompareStrings_Exact(wchar_t* sA, wchar_t* sB);

// Returns true iff sA equals sB with case insensitive matching
bool CompareStrings_CaseInsensitive(wchar_t* sA, wchar_t* sB);

// Returns true iff the parts in sA and sB after the last slash equals with case insensitive matching.
bool CompareStrings_FileNames(wchar_t* sA, wchar_t* sB);

// Returns true iff sA equals sB with case insensitive matching.
// Precondition: [aStart..aEnd] must be a valid interval of sA.
bool CompareStrings_PartOfACaseInsensitive(wchar_t* sA, int aStart, int aEnd, wchar_t* sB);
bool CompareStrings_PartOfACaseInsensitive_Ansi(char* sA, int aStart, int aEnd, char* sB);

// A subsection of S from Start to End will be parsed and returned as a double.
// Only paking a part makes it fast to use this in a parser because no allocation is needed.
// This method ignore any error and try to only read what makes sense so that a corrupt file can be parsed and repaired in an editor.
double ParseDoubleFromPartOfString(wchar_t* sInput,int start,int end);

// As ParseDoubleFromPartOfString but using the whole string.
double ParseDouble(wchar_t* sInput);

// Precondition: sRef is a string representation of a floatingpoint value using ".". Integers are ignored.
// Side effect: Removes redundant L'0' and L'.' in the end.
// Example: L"23.760" -> L"23.76"
// Example: L"1.0" -> L"1"
void SimplifyFloatInString_wide(wchar_t* sRef);
void SimplifyFloatInString(char* sRef);

// Post condition: A pointer to a new string loaded from filename with ANSI encoding assumed. NULL is returned when failed.
char* LoadTextAsANSI(wchar_t* filename);
wchar_t* LoadTextAsANSI_wide(wchar_t* filename);

// Precondition: content may only contain ANSI compatible characters.
// Postcondition: An error code telling if saving worked.
// Success returns 0.
// Unable to save returns 1.
// Unable to map to ANSI returns 2.
// Side effect: Writing content to a file named by filename in ANSI encoding.
bool SaveTextAsANSI(wchar_t* filename,char* content);

// Postcondition: Returns true iff sRef only have ANSI characters.
bool IsANSI(wchar_t* sRef);

// Postcondition: Returns true iff sRef don't contain a forbidden character '<','>','(',')','[',']','{','}','*','?','"','|'.
bool IsSimpleName(wchar_t* sRef);

// Precondition: |sInput| < 260
// SideEffect: If a dot exist, the last dot and anything after will be removed.
// Postcondition: True iff the input was small enough.
bool removeExtension(wchar_t* sInput, wchar_t sOutput[260]);

// Precondition: sRef must contain at least 4 characters
// Postcondition: Returns the name of any known byte order mark found in sRef. NULL if no BOM is detected.
wchar_t* GetBOM_wide(wchar_t* sRef);
wchar_t* GetBOM(char* sRef);

// Side effect: Terminate sRef on it's last group of slashes. This means that the last slashes are not included.
void OnlyPath(wchar_t* sRef);

// Like ParseDouble but from char* to int.
int ParseIntFromPartOfString(char* sInput,int start,int end);

// Postcondition: Returns a 64 bit checksum for Content.
UINT64 CheckSumFromString(char* Content);

// sOutput = sInput with sDirName and backslash inserted after the last slash or in the beginning if there is no slash
// Returns false if the result is too long for a filename
bool AddSubDir(wchar_t* sInput, wchar_t sOutput[260], wchar_t* sDirName);
