mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-11-17 12:08:43 +00:00
1 line
13 KiB
C
1 line
13 KiB
C
|
|
/*
|
|
* Copyright (c) Kopriha Software, 1990-1991
|
|
* All Rights Reserved
|
|
*
|
|
* Read.CC
|
|
*
|
|
* Description:
|
|
* This module exists to abstract the data of the file I/O
|
|
* primitives of GS/OS.
|
|
*
|
|
*
|
|
* History:Oct 13, 1990 Dave Created this file
|
|
*
|
|
* Feb 25, 1991 Dave Added I/O buffering
|
|
*
|
|
* May 26, 1991 Dave Added set EOF
|
|
*
|
|
* Jun 07, 1991 Dave Broke the single source into lots
|
|
* of small sources so we can build
|
|
* a library to use...
|
|
*
|
|
* Jun 30, 1991 Dave Added support for no target buffer
|
|
* (IE: This allows me to open a file
|
|
* with a buffer then do I/O to only
|
|
* that buffer - we will assume that
|
|
* the caller will know what he is doing).
|
|
*
|
|
* This functionallity is invoked when
|
|
* we are called with a data_buffer
|
|
* pointer to NULL (then the user must
|
|
* understand that the file_ptr->buffer
|
|
* is where he will find his data).
|
|
*
|
|
* Note: This functionallity is only
|
|
* implemented for the buffered I/O case!
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* define DEBUG_CODE
|
|
* - add # to define to create the local
|
|
* debug code (IE:module)
|
|
*/
|
|
|
|
#ifndef _KS_FILEIO_
|
|
#include "ks.fileio.h"
|
|
#endif
|
|
|
|
#pragma noroot
|
|
|
|
|
|
/* ****************************************************************** *
|
|
* ks_file_read - Perform an read from an open file (possibly using *
|
|
* an internal buffer). *
|
|
* *
|
|
* History: Feb 26, 1991 Dave Created this routine *
|
|
* ****************************************************************** */
|
|
|
|
#undef ROUTINE_NAME
|
|
#define ROUTINE_NAME "ks_file_read"
|
|
|
|
KS_E_ERROR ks_file_read(KS_FILE_PTR file_ptr,
|
|
LongWord position,
|
|
LongWord data_size,
|
|
Pointer data_buffer)
|
|
{
|
|
/* ************************************************************** *
|
|
* Local declarations: *
|
|
* ************************************************************** */
|
|
|
|
KS_E_ERROR error; /* Holds error codes for subroutine*/
|
|
/* calls */
|
|
LongWord data_offset; /* Offset into the buffer to return*/
|
|
LongWord remaining_space; /* Space remaining in file buffer */
|
|
LongWord buffer_request; /* Size of each copy from the */
|
|
/* file buffer */
|
|
|
|
|
|
ROUTINE_ENTER();
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Verify the structure ID passed in is the correct one. *
|
|
* ************************************************************** */
|
|
|
|
if (file_ptr->struct_id != KS_FILE_ID)
|
|
{
|
|
KS_ERROR(KS_E_INVALID_STRUCT_ID, KS_FILE_ID);
|
|
};
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Zero the number of bytes transfered in the KS_FILE structure. *
|
|
* ************************************************************** */
|
|
|
|
file_ptr->data_size = 0;
|
|
|
|
|
|
/* ************************************************************** *
|
|
* If there is a buffer, then lets get data from the file buffer.*
|
|
* ************************************************************** */
|
|
|
|
if (file_ptr->buffer_size != NULL)
|
|
{
|
|
|
|
/* ********************************************************** *
|
|
* If we hit the end of file last time, then we have no *
|
|
* choice but to return an error. *
|
|
* ********************************************************** */
|
|
|
|
if (file_ptr->end_of_file == TRUE)
|
|
{
|
|
error = eofEncountered;
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
|
|
/* ********************************************************** *
|
|
* Loop till we satisfy the request (or take an error) *
|
|
* ********************************************************** */
|
|
|
|
data_offset = 0;
|
|
|
|
while (data_size > 0)
|
|
{
|
|
|
|
/* ****************************************************** *
|
|
* Calculate the remaining space in the buffer. If *
|
|
* there is any space left in the buffer then lets copy *
|
|
* as much as we need to into the output buffer. *
|
|
* ****************************************************** */
|
|
|
|
remaining_space = (file_ptr->buffer_available) -
|
|
(file_ptr->buffer_offset);
|
|
|
|
if (remaining_space > 0)
|
|
{
|
|
buffer_request = MIN(data_size,
|
|
remaining_space);
|
|
|
|
|
|
/* ************************************************** *
|
|
* Copy the available bytes (or the required bytes) *
|
|
* to the target buffer (if one was supplied). *
|
|
* ************************************************** */
|
|
|
|
if (data_buffer != NULL)
|
|
{
|
|
COPY_BYTES(file_ptr->buffer,
|
|
file_ptr->buffer_offset,
|
|
data_buffer,
|
|
data_offset,
|
|
buffer_request);
|
|
};
|
|
|
|
|
|
/* ************************************************** *
|
|
* Now modify the parameters of the buffers by: *
|
|
* *
|
|
* 1) Adding the size of the request to the file *
|
|
* buffer ofset and the data offset (IE: Indices to *
|
|
* the file buffer and the read request buffer). *
|
|
* *
|
|
* 2) Subtracting the request size from the read *
|
|
* request size and the remaining number of *
|
|
* characters in the file buffer. *
|
|
* ************************************************** */
|
|
|
|
file_ptr->buffer_offset = file_ptr->buffer_offset +
|
|
buffer_request;
|
|
|
|
data_offset = data_offset + buffer_request;
|
|
|
|
file_ptr->data_size = data_offset;
|
|
|
|
data_size = data_size - buffer_request;
|
|
|
|
remaining_space = remaining_space - buffer_request;
|
|
};
|
|
|
|
|
|
/* ****************************************************** *
|
|
* If isn't anything in the file buffer, the we have to *
|
|
* re-fill it. The problem is that the buffer size may *
|
|
* have changed due to what our user wants (users are *
|
|
* bound to be the end of all computing...). This means *
|
|
* that we'll junp through a few hoops if we must change *
|
|
* buffer sizes - so expect some weirdness here. *
|
|
* ****************************************************** */
|
|
|
|
if (remaining_space == 0)
|
|
{
|
|
|
|
/* ************************************************** *
|
|
* This is the above mentioned weirdness - if the *
|
|
* user specified a different size buffer we will *
|
|
* no comply with their wishes. *
|
|
* ************************************************** */
|
|
|
|
if (file_ptr->buffer_size != KSf_FileBufferSize)
|
|
{
|
|
KS_MEMORY_DEALLOCATE(file_ptr->buffer_handle,
|
|
error);
|
|
|
|
if (error != KS_E_SUCCESS)
|
|
{
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
KS_MEMORY_ALLOCATE(attrFixed + attrLocked,
|
|
KSf_FileBufferSize,
|
|
BUFFER_USERID,
|
|
file_ptr->buffer_handle,
|
|
error);
|
|
|
|
if (error != KS_E_SUCCESS)
|
|
{
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
file_ptr->buffer = (Byte *)
|
|
*(file_ptr->buffer_handle);
|
|
|
|
file_ptr->buffer_size = KSf_FileBufferSize;
|
|
|
|
file_ptr->buffer_available = KSf_FileBufferSize;
|
|
};
|
|
|
|
|
|
/* ************************************************** *
|
|
* Issue a Read to the file into our buffer. *
|
|
* ************************************************** */
|
|
|
|
KSf_pkts.IO.pCount = 4;
|
|
KSf_pkts.IO.refNum = file_ptr->refNum;
|
|
KSf_pkts.IO.dataBuffer = TO_POINTER(file_ptr->buffer);
|
|
KSf_pkts.IO.requestCount = file_ptr->buffer_size;
|
|
|
|
ReadGS(&KSf_pkts.IO);
|
|
|
|
|
|
/* ************************************************** *
|
|
* Now for the error processing. *
|
|
* *
|
|
* Any error means we return to our caller. *
|
|
* *
|
|
* The end of file error (eofEncountered or $4c) is *
|
|
* special. At EOF we mark the KS_FILE structure *
|
|
* so the next READ call will return EOF right away. *
|
|
* We will return SUCCESS in this case because the *
|
|
* user will be able to find some data in the input *
|
|
* buffer (total amount == ).
|
|
* ************************************************** */
|
|
|
|
if ((error = GET_ERROR()) != KS_E_SUCCESS)
|
|
{
|
|
if (error == eofEncountered)
|
|
{
|
|
error = KS_E_SUCCESS;
|
|
file_ptr->end_of_file = TRUE;
|
|
}
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
file_ptr->buffer_available = KSf_pkts.IO.transferCount;
|
|
file_ptr->buffer_offset = 0;
|
|
|
|
}; /* End if there is no remaining buffer space */
|
|
|
|
}; /* End while there are characters to be read... */
|
|
|
|
KS_SUCCESS();
|
|
|
|
}; /* End if we are doing buffer I/O from the file */
|
|
|
|
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Ok, we've done enough buffering... lets do some real input... *
|
|
* *
|
|
* Position the 'mark' (where we will read from) in the file. *
|
|
* Note: We'll move the mark only if our user asks us to. *
|
|
* ************************************************************** */
|
|
|
|
if (position != KS_NEXT_FILE_POSITION)
|
|
{
|
|
KSf_pkts.position.pCount = 3;
|
|
KSf_pkts.position.refNum = file_ptr->refNum;
|
|
KSf_pkts.position.base = startPlus;
|
|
KSf_pkts.position.displacement = position;
|
|
|
|
SetMarkGS(&KSf_pkts.position);
|
|
|
|
if ((error = GET_ERROR()) != KS_E_SUCCESS)
|
|
{
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
}; /* End if we must change the file position */
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Setup the I/O packet and read what our user is asking for. *
|
|
* ************************************************************** */
|
|
|
|
KSf_pkts.IO.pCount = 4;
|
|
KSf_pkts.IO.refNum = file_ptr->refNum;
|
|
KSf_pkts.IO.dataBuffer = data_buffer;
|
|
KSf_pkts.IO.requestCount = data_size;
|
|
|
|
ReadGS(&KSf_pkts.IO);
|
|
|
|
if ((error = GET_ERROR()) != KS_E_SUCCESS)
|
|
{
|
|
goto EXIT_NOW;
|
|
};
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Save the number of bytes transfered in the KS_FILE structure. *
|
|
* ************************************************************** */
|
|
|
|
file_ptr->data_size = KSf_pkts.IO.transferCount;
|
|
|
|
|
|
/* ************************************************************** *
|
|
* Return the status back to our caller. *
|
|
* ************************************************************** */
|
|
|
|
EXIT_NOW:
|
|
|
|
if (error != KS_E_SUCCESS)
|
|
{
|
|
KS_ERROR(error, KS_FILE_ID);
|
|
};
|
|
|
|
KS_SUCCESS();
|
|
|
|
} /* End of ks_file_read() */
|
|
|
|
|