/******************************************************************************
 jFileUtil.cc

	Useful functions for dealing with files.

	Copyright © 1996 by John Lindal. All rights reserved.

 ******************************************************************************/

#include <jFileUtil.h>
#include <jDirUtil.h>
#include <jStreamUtil.h>
#include <fstream.h>
#include <JRegex.h>
#include <JString.h>
#include <limits.h>
#include <jAssert.h>

static const JCharacter* kTempFilePrefix = "temp_file_";

/******************************************************************************
 JPrintFileSize

	Converts the given file size into a string with a reasonable precision.
	e.g. 1003280 -> 1MB

 ******************************************************************************/

JString
JPrintFileSize
	(
	const JSize size
	)
{
	if (size < 5000)
		{
		return JString(size, 0);
		}
	else if (size < 1000000)
		{
		return JString(size/1.0e3, 0) + "K";
		}
	else
		{
		return JString(size/1.0e6, 1) + "MB";
		}
}

/******************************************************************************
 JGetTempFileName

	Returns a unique file name for use in the specified directory.
	If path is empty, it uses the current working directory.

	We ignore the possibility of not finding a valid name because the file
	system will fill up long before we run out of possibilities.

 ******************************************************************************/

JString
JGetTempFileName
	(
	const JCharacter* path
	)
{
	return JGetUniqueDirEntryName(path, kTempFilePrefix);
}

/******************************************************************************
 JSearchFile

	Returns the index of the first line that contains the given string.

 ******************************************************************************/

JBoolean
JSearchFile
	(
	const JCharacter*	fileName,
	const JCharacter*	searchStr,
	const JBoolean		caseSensitive,
	JIndex*				lineIndex
	)
{
	ifstream input(fileName);

	*lineIndex = 0;
	while (!input.eof())
		{
		(*lineIndex)++;
		const JString line = JReadLine(input);
		if (input.fail())
			{
			break;
			}
		if (line.Contains(searchStr, caseSensitive))
			{
			return kTrue;
			}
		}

	return kFalse;
}

/******************************************************************************
 JExtractFileAndLine

	Extracts file name and line index from "file:line".

 ******************************************************************************/

void
JExtractFileAndLine
	(
	const JCharacter*	str,
	JString*			fileName,
	JIndex*				lineIndex
	)
{
	static JRegex lineIndexRegex(":[0-9]+$");

	*fileName = str;

	JIndexRange lineIndexRange;
	if (lineIndexRegex.Match(*fileName, &lineIndexRange))
		{
		const JString lineIndexStr =
			fileName->GetSubstring(lineIndexRange.first+1,
								   lineIndexRange.last);
		const JBoolean ok = lineIndexStr.ConvertToUInt(lineIndex);
		assert( ok );

		fileName->RemoveSubstring(lineIndexRange);
		}
	else
		{
		*lineIndex = 0;
		}
}

/******************************************************************************
 JCombineRootAndSuffix

	Combines the root and suffix with a period between them.

 ******************************************************************************/

JString
JCombineRootAndSuffix
	(
	const JCharacter* root,
	const JCharacter* suffix
	)
{
	JString name = root;
	if (suffix[0] != '.')
		{
		name.AppendCharacter('.');
		}
	name.Append(suffix);
	return name;
}

/******************************************************************************
 JSplitRootAndSuffix

	The root is everything before the last period.  The suffix is everything
	after the last period.

	Returns kTrue if *suffix is not empty.

 ******************************************************************************/

JBoolean
JSplitRootAndSuffix
	(
	const JCharacter*	name,
	JString*			root,
	JString*			suffix
	)
{
	*root = name;
	suffix->Clear();

	JIndex dotIndex;
	if (root->LocateLastSubstring(".", &dotIndex))
		{
		if (dotIndex < root->GetLength())
			{
			*suffix = root->GetSubstring(dotIndex+1, root->GetLength());
			}
		root->RemoveSubstring(dotIndex, root->GetLength());
		}

	return JNegate( suffix->IsEmpty() );
}
