/* ** 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 #include /****************************************************************************** __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; }