/*****************************************************************************/
// Copyright 2006-2019 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE:  Adobe permits you to use, modify, and distribute this file in
// accordance with the terms of the Adobe license agreement accompanying it.
/*****************************************************************************/

#include "dng_file_stream.h"

#include "dng_exceptions.h"

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

dng_file_stream::dng_file_stream (const char *filename,
								  bool output,
								  uint32 bufferSize)

	:	dng_stream ((dng_abort_sniffer *) NULL,
					bufferSize,
					0)
	
	,	fFile (NULL)
	
	{

	fFile = fopen (filename, output ? "wb" : "rb");

	if (!fFile)
		{
		
		#if qDNGValidate

		ReportError ("Unable to open file",
					 filename);
					 
		ThrowSilentError ();
		
		#else
		
		ThrowOpenFile ();
		
		#endif

		}
	
	}

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

#if qWinOS

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

dng_file_stream::dng_file_stream (const wchar_t *filename,
								  bool output,
								  uint32 bufferSize)

	:	dng_stream ((dng_abort_sniffer *) NULL,
					bufferSize,
					0)
	
	,	fFile (NULL)
	
	{

	fFile = _wfopen (filename, output ? L"wb" : L"rb");

	if (!fFile)
		{
		
		#if qDNGValidate

		char filenameCString[256];

		size_t returnCount;

		wcstombs_s (&returnCount, 
					filenameCString, 
					256, 
					filename, 
					_TRUNCATE);

		ReportError ("Unable to open file",
					 filenameCString);
					 
		ThrowSilentError ();
		
		#else
		
		ThrowOpenFile ();
		
		#endif	// qDNGValidate

		}
	
	}

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

#endif	// qWinOS
		
/*****************************************************************************/

dng_file_stream::~dng_file_stream ()
	{
	
	if (fFile)
		{
		fclose (fFile);
		fFile = NULL;
		}
	
	}
		
/*****************************************************************************/

uint64 dng_file_stream::DoGetLength ()
	{
	
	if (fseek (fFile, 0, SEEK_END) != 0)
		{
		
		ThrowReadFile ();

		}
	
	return (uint64) ftell (fFile);
	
	}
		
/*****************************************************************************/

void dng_file_stream::DoRead (void *data,
							  uint32 count,
							  uint64 offset)
	{
	
	if (fseek (fFile, (long) offset, SEEK_SET) != 0)
		{
		
		ThrowReadFile ();

		}
	
	uint32 bytesRead = (uint32) fread (data, 1, count, fFile);
	
	if (bytesRead != count)
		{
		
		ThrowReadFile ();

		}
	
	}
		
/*****************************************************************************/

void dng_file_stream::DoWrite (const void *data,
							   uint32 count,
							   uint64 offset)
	{
	
	if (fseek (fFile, (uint32) offset, SEEK_SET) != 0)
		{
		
		ThrowWriteFile ();

		}
	
	uint32 bytesWritten = (uint32) fwrite (data, 1, count, fFile);
	
	if (bytesWritten != count)
		{
		
		ThrowWriteFile ();

		}
	
	}
		
/*****************************************************************************/
