I've the following C function in a Windows API project that reads a file and based on the line endings (UNIX, MAC, DOS) it replaces the line endings with the right line-endings for Windows (\r\n
):
// Standard C header needed for string functions
#include <string.h>
// Defines for line-ending conversion function
#define LESTATUS INT
#define LE_NO_CHANGES_NEEDED (0)
#define LE_CHANGES_SUCCEEDED (1)
#define LE_CHANGES_FAILED (-1)
/// <summary>
/// If the line endings in a block of data loaded from a file contain UNIX (\n) or MAC (\r) line endings, this function replaces it with DOS (\r\n) endings.
/// </summary>
/// <param name="inData">An array of bytes of input data.</param>
/// <param name="inLen">The size, in bytes, of inData.</param>
/// <param name="outData">An array of bytes to be populated with output data. This array must already be allocated</param>
/// <param name="outLen">The maximum number of bytes that can be stored in outData.</param>
/// <param name="bytesWritten">A pointer to an integer that receives the number of bytes written into outData.</param>
/// <returns>
/// If no changes were necessary (the file already contains \r\n line endings), then the return value is LE_NO_CHANGES_NEEDED.<br/>
/// If changes were necessary, and it was possible to store the entire output buffer, the return value is LE_CHANGES_SUCCEEDED.<br/>
/// If changes were necessary but the output buffer was too small, the return value is LE_CHANGES_FAILED.<br/>
/// </returns>
LESTATUS ConvertLineEndings(BYTE* inData, INT inLen, BYTE* outData, INT outLen, INT* bytesWritten)
{
char *posR = strstr(inData, "\r");
char *posN = strstr(inData, "\n");
// Case 1: the file already contains DOS/Windows line endings.
// So, copy the input array into the output array as-is (if we can)
// Report an error if the output array is too small to hold the input array; report success otherwise.
if (posN != NULL && posR != NULL)
{
if (outLen >= inLen)
{
strcpy(outData, inData);
return LE_NO_CHANGES_NEEDED;
}
return LE_CHANGES_FAILED;
}
// Case 2: the file contains UNIX line endings.
else if (posN != NULL && posR == NULL)
{
int i = 0;
int track = 0;
for (i = 0; i < inLen; i++)
{
if (inData[i] != '\n')
{
outData[track] = inData[i];
track++;
if (track>outLen) return LE_CHANGES_FAILED;
}
else
{
outData[track] = '\r';
track++;
if (track > outLen) return LE_CHANGES_FAILED;
outData[track] = '\n';
track++;
if (track > outLen) return LE_CHANGES_FAILED;
}
*bytesWritten = track;
}
}
// Case 3: the file contains Mac-style line endings.
else if (posN == NULL && posR != NULL)
{
int i = 0;
int track = 0;
for (i = 0; i < inLen; i++)
{
if (inData[i] != '\r')
{
outData[track] = inData[i];
track++;
if (track>outLen) return LE_CHANGES_FAILED;
}
else
{
outData[track] = '\r';
track++;
if (track > outLen) return LE_CHANGES_FAILED;
outData[track] = '\n';
track++;
if (track > outLen) return LE_CHANGES_FAILED;
}
*bytesWritten = track;
}
}
return LE_CHANGES_SUCCEEDED;
}
However, I feel like this function is very long (almost 70 lines) and could be reduced somehow. I've searched on Google but couldn't find anything useful; is there any function in either the C library or the Windows API that will allow me to perform a string-replace rather than manually searching the string byte-by-byte in O(n) time?