windows-nt/Source/XPSP1/NT/multimedia/opengl/gls/lib/read.c

409 lines
13 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*
** Copyright 1995-2095, Silicon Graphics, Inc.
** All Rights Reserved.
**
** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
** the contents of this file may not be disclosed to third parties, copied or
** duplicated in any form, in whole or in part, without the prior written
** permission of Silicon Graphics, Inc.
**
** RESTRICTED RIGHTS LEGEND:
** Use, duplication or disclosure by the Government is subject to restrictions
** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
** rights reserved under the Copyright Laws of the United States.
*/
#include "glslib.h"
#include <stdlib.h>
#include <string.h>
/******************************************************************************
__GLSreadStream
******************************************************************************/
__GLSreadStream* __glsReadStream_create(const GLubyte *inName) {
__GLScontext *const ctx = __GLS_CONTEXT;
__GLSreadStream *const outStream = __glsCalloc(
1, sizeof(__GLSreadStream)
);
if (!outStream) return GLS_NONE;
__glsString_init(&outStream->name);
outStream->unreadFunc = ctx->unreadFunc;
if (inName[0]) {
const GLubyte *openName;
__GLS_ITERLIST_FIRST(&ctx->readPrefixList);
while (ctx->readPrefixList.iterElem) {
if (
!__glsListString_prefix(
ctx->readPrefixList.iterElem, inName, &outStream->name
) ||
!(openName = __glsUCS1String(outStream->name.head))
) {
return __glsReadStream_destroy(outStream);
}
outStream->channel = fopen((const char *)openName, "rb");
if (openName != outStream->name.head) free((GLvoid *)openName);
if (outStream->channel) {
setbuf(outStream->channel, GLS_NONE);
outStream->opened = GL_TRUE;
return outStream;
}
__GLS_ITERLIST_NEXT(&ctx->readPrefixList);
}
if (
!__glsListString_prefix(
ctx->writePrefix, inName, &outStream->name
) ||
!(openName = __glsUCS1String(outStream->name.head))
) {
return __glsReadStream_destroy(outStream);
}
outStream->channel = fopen((const char *)openName, "rb");
if (openName != outStream->name.head) free((GLvoid *)openName);
if (outStream->channel) {
setbuf(outStream->channel, GLS_NONE);
outStream->opened = GL_TRUE;
return outStream;
}
return __glsReadStream_destroy(outStream);
} else {
outStream->readFunc = ctx->readFunc;
if (!outStream->readFunc) outStream->channel = ctx->defaultReadChannel;
return outStream;
}
}
__GLSreadStream* __glsReadStream_destroy(__GLSreadStream *inStream) {
if (!inStream) return GLS_NONE;
if (inStream->opened && fclose(inStream->channel)) {
__GLS_RAISE_ERROR(GLS_STREAM_CLOSE_ERROR);
}
__glsString_final(&inStream->name);
free(inStream);
return GLS_NONE;
}
GLbitfield __glsReadStream_getAttrib(const __GLSreadStream *inStream) {
GLbitfield outVal = GLS_STREAM_READABLE_BIT;
if (inStream->opened) {
const GLubyte *const openName = __glsUCS1String(inStream->name.head);
FILE *channel;
if (!openName) return GLS_NONE;
channel = fopen((const char *)openName, "ab");
if (openName != inStream->name.head) free((GLvoid *)openName);
if (channel) {
fclose(channel);
outVal |= GLS_STREAM_WRITABLE_BIT;
}
outVal |= GLS_STREAM_NAMED_BIT;
}
if (!fseek(inStream->channel, 0, SEEK_CUR)) {
outVal |= GLS_STREAM_SEEKABLE_BIT;
}
return outVal;
}
size_t __glsReadStream_getByteCount(const __GLSreadStream *inStream) {
long outVal;
fpos_t pos;
if (!inStream->channel) return 0;
if (
fgetpos(inStream->channel, &pos) ||
fseek(inStream->channel, 0, SEEK_END)
) {
return 0;
}
outVal = ftell(inStream->channel);
fsetpos(inStream->channel, &pos);
return outVal == -1L ? 0 : (size_t)outVal;
}
GLuint __glsReadStream_getCRC32(const __GLSreadStream *inStream) {
GLubyte buf[__GLS_CHECKSUM_BUF_BYTES];
size_t i, n;
GLuint outVal = 0xffffffff;
fpos_t pos;
if (!inStream->channel) return 0;
if (
fgetpos(inStream->channel, &pos) ||
fseek(inStream->channel, 0, SEEK_SET)
) {
return 0;
}
while (n = fread(buf, 1, __GLS_CHECKSUM_BUF_BYTES, inStream->channel)) {
for (i = 0 ; i < n ; ++i) __GLS_CRC32_STEP(outVal, buf[i]);
}
fsetpos(inStream->channel, &pos);
if (ferror(inStream->channel)) {
__GLS_RAISE_ERROR(GLS_STREAM_READ_ERROR);
clearerr(inStream->channel);
return 0;
}
return ~outVal;
}
GLSenum __glsReadStream_getType(const __GLSreadStream *inStream) {
__GLSreader reader;
if (!inStream->channel) return GLS_NONE;
if (fseek(inStream->channel, 0, SEEK_CUR)) return GLS_UNKNOWN;
if (__glsReader_init_stream(&reader, inStream, 256)) {
const GLenum outType = reader.type;
__glsReader_final(&reader);
return outType;
} else {
return GLS_NONE;
}
}
/******************************************************************************
__GLSreader
******************************************************************************/
GLvoid* __glsReader_allocCallBuf(
__GLSreader *inoutReader, size_t inByteCount
) {
GLvoid *outVal;
if (inoutReader->error) return GLS_NONE;
outVal = __glsMalloc(inByteCount);
if (!outVal) __glsReader_raiseError(inoutReader, GLS_OUT_OF_MEMORY);
return outVal;
}
GLvoid* __glsReader_allocFeedbackBuf(
__GLSreader *inoutReader, size_t inByteCount
) {
GLvoid *outVal;
if (inoutReader->error) return GLS_NONE;
outVal = __glsContext_allocFeedbackBuf(__GLS_CONTEXT, inByteCount);
if (!outVal) __glsReader_raiseError(inoutReader, GLS_OUT_OF_MEMORY);
return outVal;
}
GLvoid* __glsReader_allocSelectBuf(
__GLSreader *inoutReader, size_t inByteCount
) {
GLvoid *outVal;
if (inoutReader->error) return GLS_NONE;
outVal = __glsContext_allocSelectBuf(__GLS_CONTEXT, inByteCount);
if (!outVal) __glsReader_raiseError(inoutReader, GLS_OUT_OF_MEMORY);
return outVal;
}
#if __GL_EXT_vertex_array
GLvoid* __glsReader_allocVertexArrayBuf(
__GLSreader *inoutReader, GLSopcode inOpcode, size_t inByteCount
) {
GLvoid *outVal;
if (inoutReader->error) return GLS_NONE;
outVal = __glsContext_allocVertexArrayBuf(
__GLS_CONTEXT, inOpcode, inByteCount
);
if (!outVal) __glsReader_raiseError(inoutReader, GLS_OUT_OF_MEMORY);
return outVal;
}
#endif /* __GL_EXT_vertex_array */
void __glsReader_call(__GLSreader *inoutReader) {
GLboolean callSave;
__GLScontext *const ctx = __GLS_CONTEXT;
callSave = ctx->contextCall;
ctx->contextCall = GL_FALSE;
while (inoutReader->type != GLS_NONE) {
#ifndef __GLS_PLATFORM_WIN32
// DrewB
ctx->dispatchDecode_bin[GLS_OP_glsBeginGLS](
(GLubyte *)&inoutReader->version
);
#else
ctx->dispatchDecode_bin[GLS_OP_glsBeginGLS](
ctx, (GLubyte *)&inoutReader->version
);
#endif
if (inoutReader->type == GLS_TEXT) {
if (!__glsReader_call_text(inoutReader)) break;
inoutReader->readHead = inoutReader->readPtr;
__GLS_GET_SPACE(inoutReader);
} else if (inoutReader->type == __GLS_BINARY_SWAP0) {
if (!__glsReader_call_bin(inoutReader)) break;
inoutReader->readHead = inoutReader->readPtr;
} else {
if (!__glsReader_call_bin_swap(inoutReader)) break;
inoutReader->readHead = inoutReader->readPtr;
}
#ifndef __GLS_PLATFORM_WIN32
// DrewB
ctx->dispatchDecode_bin[GLS_OP_glsEndGLS](GLS_NONE);
#else
ctx->dispatchDecode_bin[GLS_OP_glsEndGLS](ctx, GLS_NONE);
#endif
inoutReader->type = __glsReader_readBeginGLS_bin(
inoutReader, &inoutReader->version
);
if (inoutReader->type == GLS_NONE) {
inoutReader->type = __glsReader_readBeginGLS_text(
inoutReader, &inoutReader->version
);
}
if (inoutReader->type == GLS_NONE) {
inoutReader->readPtr = inoutReader->readHead;
}
inoutReader->readHead = GLS_NONE;
}
ctx->contextCall = callSave;
}
__GLSreader* __glsReader_final(__GLSreader *inoutReader) {
if (inoutReader && inoutReader->stream) {
const ptrdiff_t excess = inoutReader->readTail - inoutReader->readPtr;
if (excess > 0) {
if (
(
!inoutReader->stream->channel ||
fseek(
inoutReader->stream->channel,
-1 * (long)excess,
SEEK_CUR
)
) &&
__GLS_CONTEXT->unreadFunc
) {
__GLS_CONTEXT->unreadFunc(
(size_t)excess, inoutReader->readPtr
);
}
}
free(inoutReader->buf);
}
return GLS_NONE;
}
GLboolean __glsReader_fillBuf(
__GLSreader *inoutReader, size_t inMinBytes, GLboolean inRealign
) {
FILE *channel;
size_t keepBytes, needBytes, padBytes, unreadBytes;
GLubyte *ptr, *readHead;
if (!inoutReader->readPtr || !inoutReader->stream) return GL_FALSE;
readHead = (
inoutReader->readHead ? inoutReader->readHead : inoutReader->readPtr
);
keepBytes = (size_t)((ULONG_PTR)(inoutReader->readPtr - readHead));
unreadBytes = (size_t)((ULONG_PTR)(inoutReader->readTail - inoutReader->readPtr));
if (inRealign) {
padBytes = (size_t)((ULONG_PTR)(readHead - inoutReader->buf) & (__GLS_MAX_ALIGN_BYTES - 4));
} else if (keepBytes % __GLS_MAX_ALIGN_BYTES) {
padBytes = __GLS_MAX_ALIGN_BYTES - keepBytes % __GLS_MAX_ALIGN_BYTES;
} else {
padBytes = 0;
}
needBytes = padBytes + keepBytes + __GLS_MAX(inMinBytes, unreadBytes);
if (needBytes > inoutReader->bufSize) {
GLubyte *const buf = __glsMalloc(needBytes);
if (!buf) goto eos;
ptr = buf + padBytes;
while (readHead < inoutReader->readTail) *ptr++ = *readHead++;
free(inoutReader->buf);
inoutReader->buf = buf;
inoutReader->bufSize = needBytes;
} else {
ptr = inoutReader->buf + padBytes;
if (ptr != readHead) memmove(ptr, readHead, keepBytes + unreadBytes);
}
readHead = inoutReader->buf + padBytes;
if (inoutReader->readHead) inoutReader->readHead = readHead;
inoutReader->readPtr = readHead + keepBytes;
inoutReader->readTail = inoutReader->readPtr + unreadBytes;
channel = inoutReader->stream->channel;
for (;;) {
if (
(size_t)(inoutReader->readTail - inoutReader->readPtr) >=
inMinBytes
) {
return GL_TRUE;
}
ptr = inoutReader->readTail;
if (channel) {
inoutReader->readTail += fread(
ptr,
1,
(size_t)((ULONG_PTR)(inoutReader->buf + inoutReader->bufSize - ptr)),
channel
);
if (ferror(channel)) {
__GLS_RAISE_ERROR(GLS_STREAM_READ_ERROR);
clearerr(channel);
}
} else {
inoutReader->readTail += inoutReader->stream->readFunc(
(size_t)((ULONG_PTR)(inoutReader->buf + inoutReader->bufSize - ptr)), ptr
);
}
if (inoutReader->readTail <= ptr) break;
}
eos:
inoutReader->readHead = GLS_NONE;
inoutReader->readPtr = GLS_NONE;
inoutReader->readTail = GLS_NONE;
return GL_FALSE;
}
__GLSreader* __glsReader_init_array(
__GLSreader *outReader, const GLubyte *inArray, size_t inCount
) {
memset(outReader, 0, sizeof(__GLSreader));
outReader->buf = (GLubyte *)inArray;
outReader->bufSize = inCount;
outReader->readPtr = outReader->buf;
outReader->readTail = outReader->buf + inCount;
return outReader;
}
__GLSreader* __glsReader_init_stream(
__GLSreader *outReader, const __GLSreadStream *inStream, size_t inBufSize
) {
memset(outReader, 0, sizeof(__GLSreader));
outReader->stream = inStream;
outReader->buf = __glsMalloc(inBufSize);
if (!outReader->buf) return __glsReader_final(outReader);
outReader->bufSize = inBufSize;
outReader->readPtr = outReader->buf;
outReader->readTail = outReader->buf;
outReader->readHead = outReader->readPtr;
outReader->type = __glsReader_readBeginGLS_bin(
outReader, &outReader->version
);
if (outReader->type == GLS_NONE) {
outReader->type = __glsReader_readBeginGLS_text(
outReader, &outReader->version
);
}
if (outReader->type == GLS_NONE) {
outReader->readPtr = outReader->readHead;
return __glsReader_final(outReader);
}
outReader->readHead = GLS_NONE;
return outReader;
}
void __glsReader_raiseError(__GLSreader *inoutReader, GLSenum inError) {
if (!inoutReader->error) inoutReader->error = inError;
}