summaryrefslogblamecommitdiffstatshomepage
path: root/src/lib/formats/ioprocs.cpp
blob: 69943c13dc0eb7f3e6e706e15a1ce819efa54b5d (plain) (tree)
1
2
3
4
5
6
7
8

                                 

                   
                   
                    
                    
                     










                                                                      
                                                                 













                                                                            
                                              





















                                             
                





                          





                                                                      
                                      

 
                                                                    
 
                                                              



                                                                        
                                                              



                                                                               
                                                               

 
                                                 
 

                                                        
                                   

                                                         

                                    












                                                
                





                             





                                                                      
                                                                      
 
                                                              



 
                                               
 

                                                     



 
                                                                                            
 
                      

                          
                                      





                               

                                                                                 
         
                                                                                      



 
                                                                                                   
 
                                 

                                 
                      
 
                                      






                                            
                                       


                        
                                                                            


                                                                                                                              
                                                                                            





                                                      
                                                                     



 
                                                                                                      
 
                            

                           
                                                                 


                         
                                                               
                                                                     






                                      
                                                  
 
                                                       
 
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "osdcore.h"
#include "ioprocs.h"
#include "corefile.h"


/*********************************************************************
    ioprocs implementation on stdio
*********************************************************************/

static void stdio_closeproc(void *file)
{
	fclose((FILE*)file);
}

static int stdio_seekproc(void *file, int64_t offset, int whence)
{
	return fseek((FILE*)file, (long) offset, whence);
}

static size_t stdio_readproc(void *file, void *buffer, size_t length)
{
	return fread(buffer, 1, length, (FILE*)file);
}

static size_t stdio_writeproc(void *file, const void *buffer, size_t length)
{
	return fwrite(buffer, 1, length, (FILE*)file);
}

static uint64_t stdio_filesizeproc(void *file)
{
	long l, sz;
	l = ftell((FILE*)file);
	if (fseek((FILE*)file, 0, SEEK_END))
		return (size_t) -1;
	sz = ftell((FILE*)file);
	if (fseek((FILE*)file, l, SEEK_SET))
		return (size_t) -1;
	return (size_t) sz;
}

const struct io_procs stdio_ioprocs =
{
	stdio_closeproc,
	stdio_seekproc,
	stdio_readproc,
	stdio_writeproc,
	stdio_filesizeproc
};

const struct io_procs stdio_ioprocs_noclose =
{
	nullptr,
	stdio_seekproc,
	stdio_readproc,
	stdio_writeproc,
	stdio_filesizeproc
};

/*********************************************************************
    ioprocs implementation on corefile
*********************************************************************/

static void corefile_closeproc(void *file)
{
	delete (util::core_file*)file;
}

static int corefile_seekproc(void *file, int64_t offset, int whence)
{
	return ((util::core_file*)file)->seek(offset, whence);
}

static size_t corefile_readproc(void *file, void *buffer, size_t length)
{
	return ((util::core_file*)file)->read(buffer, length);
}

static size_t corefile_writeproc(void *file, const void *buffer, size_t length)
{
	return ((util::core_file*)file)->write(buffer, length);
}

static uint64_t corefile_filesizeproc(void *file)
{
	const auto l = ((util::core_file*)file)->tell();
	if (((util::core_file*)file)->seek(0, SEEK_END))
		return (size_t) -1;
	const auto sz = ((util::core_file*)file)->tell();
	if (((util::core_file*)file)->seek(l, SEEK_SET))
		return uint64_t(-1);
	return uint64_t(sz);
}

const struct io_procs corefile_ioprocs =
{
	corefile_closeproc,
	corefile_seekproc,
	corefile_readproc,
	corefile_writeproc,
	corefile_filesizeproc
};

const struct io_procs corefile_ioprocs_noclose =
{
	nullptr,
	corefile_seekproc,
	corefile_readproc,
	corefile_writeproc,
	corefile_filesizeproc
};



/*********************************************************************
    calls for accessing generic IO
*********************************************************************/

static void io_generic_seek(struct io_generic *genio, uint64_t offset)
{
	genio->procs->seekproc(genio->file, offset, SEEK_SET);
}



void io_generic_close(struct io_generic *genio)
{
	if (genio->procs->closeproc)
		genio->procs->closeproc(genio->file);
}



void io_generic_read(struct io_generic *genio, void *buffer, uint64_t offset, size_t length)
{
	uint64_t size;
	size_t bytes_read;

	size = io_generic_size(genio);
	if (size <= offset)
	{
		bytes_read = 0;
	}
	else
	{
		io_generic_seek(genio, offset);
		bytes_read = genio->procs->readproc(genio->file, buffer, length);
	}
	memset(((uint8_t *) buffer) + bytes_read, genio->filler, length - bytes_read);
}



void io_generic_write(struct io_generic *genio, const void *buffer, uint64_t offset, size_t length)
{
	uint64_t filler_size = 0;
	char filler_buffer[1024];
	size_t bytes_to_write;
	uint64_t size;

	size = io_generic_size(genio);

	if (size < offset)
	{
		filler_size = offset - size;
		offset = size;
	}

	io_generic_seek(genio, offset);

	if (filler_size)
	{
		memset(filler_buffer, genio->filler, sizeof(filler_buffer));
		do
		{
			bytes_to_write = (filler_size > sizeof(filler_buffer)) ? sizeof(filler_buffer) : (size_t) filler_size;
			genio->procs->writeproc(genio->file, filler_buffer, bytes_to_write);
			filler_size -= bytes_to_write;
		}
		while(filler_size > 0);
	}

	if (length > 0)
		genio->procs->writeproc(genio->file, buffer, length);
}



void io_generic_write_filler(struct io_generic *genio, uint8_t filler, uint64_t offset, size_t length)
{
	uint8_t buffer[512];
	size_t this_length;

	memset(buffer, filler, std::min(length, sizeof(buffer)));

	while(length > 0)
	{
		this_length = std::min(length, sizeof(buffer));
		io_generic_write(genio, buffer, offset, this_length);
		offset += this_length;
		length -= this_length;
	}
}



uint64_t io_generic_size(struct io_generic *genio)
{
	return genio->procs->filesizeproc(genio->file);
}