693 lines
18 KiB
C
693 lines
18 KiB
C
/*
|
|
** 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 <string.h>
|
|
#include <time.h>
|
|
|
|
static GLuint __glsContextCount = 0;
|
|
static GLuint __glsNextContext = 1;
|
|
|
|
typedef struct {
|
|
GLuint mask1;
|
|
GLuint val1;
|
|
GLuint shift;
|
|
GLuint mask4;
|
|
GLuint val4;
|
|
} __GLSutf8format;
|
|
|
|
static const __GLSutf8format __glsUTF8formats[] = {
|
|
{0x80, 0x00, 0, 0x0000007f, 0x00000000,},
|
|
{0xe0, 0xc0, 6, 0x000007ff, 0x00000080,},
|
|
{0xf0, 0xe0, 12, 0x0000ffff, 0x00000800,},
|
|
{0xf8, 0xf0, 18, 0x001fffff, 0x00010000,},
|
|
{0xfc, 0xf8, 24, 0x03ffffff, 0x00200000,},
|
|
{0xfe, 0xfc, 30, 0x7fffffff, 0x04000000,},
|
|
{0x00, 0x00, 0, 0x00000000, 0x00000000,},
|
|
};
|
|
|
|
GLSenum glsBinary(GLboolean inSwapped) {
|
|
return inSwapped ? __GLS_BINARY_SWAP1 : __GLS_BINARY_SWAP0;
|
|
}
|
|
|
|
GLSenum glsCommandAPI(GLSopcode inOpcode) {
|
|
const GLSenum outVal = __glsOpcodeAPI(inOpcode);
|
|
|
|
if (!outVal) __GLS_RAISE_ERROR(GLS_UNSUPPORTED_COMMAND);
|
|
return outVal;
|
|
}
|
|
|
|
const GLubyte* glsCommandString(GLSopcode inOpcode) {
|
|
if (!__glsValidateOpcode(inOpcode)) return GLS_NONE;
|
|
return __glsOpcodeString[__glsMapOpcode(inOpcode)];
|
|
}
|
|
|
|
void glsContext(GLuint inContext) {
|
|
__GLScontext *ctx = __GLS_CONTEXT;
|
|
__GLScontext *newCtx;
|
|
|
|
if (ctx && (ctx->callNesting || ctx->captureEntryCount)) {
|
|
__GLS_RAISE_ERROR(GLS_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
if (inContext) {
|
|
__glsBeginCriticalSection();
|
|
if (
|
|
newCtx = (__GLScontext *)__glsInt2PtrDict_find(
|
|
__glsContextDict, (GLint)inContext
|
|
)
|
|
) {
|
|
if (newCtx == ctx) {
|
|
newCtx = GLS_NONE;
|
|
} else {
|
|
if (newCtx->current) {
|
|
__GLS_RAISE_ERROR(GLS_INVALID_OPERATION);
|
|
newCtx = GLS_NONE;
|
|
} else {
|
|
newCtx->current = GL_TRUE;
|
|
if (ctx)
|
|
{
|
|
if (ctx->deleted)
|
|
{
|
|
__glsContext_destroy(ctx);
|
|
}
|
|
else
|
|
{
|
|
ctx->current = GL_FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
__GLS_RAISE_ERROR(GLS_NOT_FOUND);
|
|
}
|
|
__glsEndCriticalSection();
|
|
if (newCtx) {
|
|
__GLS_PUT_CONTEXT(newCtx);
|
|
__glsUpdateDispatchTables();
|
|
}
|
|
} else if (ctx) {
|
|
__glsBeginCriticalSection();
|
|
if (ctx->deleted) {
|
|
__glsContext_destroy(ctx);
|
|
} else {
|
|
ctx->current = GL_FALSE;
|
|
}
|
|
__glsEndCriticalSection();
|
|
__GLS_PUT_CONTEXT(GLS_NONE);
|
|
__glsUpdateDispatchTables();
|
|
}
|
|
}
|
|
|
|
void glsDeleteContext(GLuint inContext) {
|
|
if (inContext) {
|
|
__GLScontext *ctx;
|
|
|
|
__glsBeginCriticalSection();
|
|
if (
|
|
ctx = (__GLScontext *)__glsInt2PtrDict_find(
|
|
__glsContextDict, (GLint)inContext
|
|
)
|
|
) {
|
|
__glsIntDict_remove(__glsContextDict, (GLint)inContext);
|
|
__GLS_LIST_REMOVE(&__glsContextList, ctx);
|
|
--__glsContextCount;
|
|
if (ctx->current) {
|
|
ctx->deleted = GL_TRUE;
|
|
} else {
|
|
__glsContext_destroy(ctx);
|
|
}
|
|
} else {
|
|
__GLS_RAISE_ERROR(GLS_NOT_FOUND);
|
|
}
|
|
__glsEndCriticalSection();
|
|
} else {
|
|
__GLS_RAISE_ERROR(GLS_INVALID_VALUE);
|
|
}
|
|
}
|
|
|
|
const GLubyte* glsEnumString(GLSenum inAPI, GLSenum inEnum) {
|
|
GLint offset, page;
|
|
|
|
switch (inAPI) {
|
|
case GLS_API_GLS:
|
|
page = __GLS_ENUM_PAGE(inEnum);
|
|
offset = __GLS_ENUM_OFFSET(inEnum);
|
|
if (
|
|
page < __GLS_ENUM_PAGE_COUNT &&
|
|
offset < __glsEnumStringCount[page] &&
|
|
__glsEnumString[page][offset]
|
|
) {
|
|
return __glsEnumString[page][offset];
|
|
}
|
|
break;
|
|
case GLS_API_GL:
|
|
page = __GL_ENUM_PAGE(inEnum);
|
|
offset = __GL_ENUM_OFFSET(inEnum);
|
|
if (
|
|
page < __GL_ENUM_PAGE_COUNT &&
|
|
offset < __glEnumStringCount[page] &&
|
|
__glEnumString[page][offset]
|
|
) {
|
|
return __glEnumString[page][offset];
|
|
}
|
|
break;
|
|
}
|
|
__GLS_RAISE_ERROR(GLS_INVALID_ENUM);
|
|
return GLS_NONE;
|
|
}
|
|
|
|
GLuint glsGenContext(void) {
|
|
GLboolean added = GL_FALSE;
|
|
__GLScontext *ctx;
|
|
GLuint name;
|
|
|
|
__glsBeginCriticalSection();
|
|
name = __glsNextContext;
|
|
if (
|
|
(ctx = __glsContext_create(name)) &&
|
|
(added = __glsInt2PtrDict_add(__glsContextDict, (GLint)name, ctx))
|
|
) {
|
|
++__glsContextCount;
|
|
++__glsNextContext;
|
|
__GLS_LIST_APPEND(&__glsContextList, ctx);
|
|
}
|
|
__glsEndCriticalSection();
|
|
if (added) {
|
|
return name;
|
|
} else {
|
|
__glsContext_destroy(ctx);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
GLuint* glsGetAllContexts(void) {
|
|
GLuint *buf = GLS_NONE;
|
|
GLint i = 0;
|
|
|
|
__glsBeginCriticalSection();
|
|
if (buf = __glsMalloc((__glsContextCount + 1) * sizeof(GLuint))) {
|
|
__GLS_LIST_ITER(__GLScontext) iter;
|
|
|
|
__GLS_LIST_FIRST(&__glsContextList, &iter);
|
|
while (iter.elem) {
|
|
buf[i++] = iter.elem->name;
|
|
__GLS_LIST_NEXT(&__glsContextList, &iter);
|
|
}
|
|
buf[i] = 0;
|
|
}
|
|
__glsEndCriticalSection();
|
|
return buf;
|
|
}
|
|
|
|
GLScommandAlignment* glsGetCommandAlignment(
|
|
GLSopcode inOpcode,
|
|
GLSenum inExternStreamType,
|
|
GLScommandAlignment *outAlignment
|
|
) {
|
|
GLbitfield attrib;
|
|
|
|
if (!__glsValidateOpcode(inOpcode)) return GLS_NONE;
|
|
attrib = __glsOpcodeAttrib[__glsMapOpcode(inOpcode)];
|
|
switch (inExternStreamType) {
|
|
case GLS_BINARY_LSB_FIRST:
|
|
case GLS_BINARY_MSB_FIRST:
|
|
if (attrib & __GLS_COMMAND_ALIGN_EVEN32_BIT) {
|
|
outAlignment->mask = 7;
|
|
outAlignment->value = 0;
|
|
} else if (attrib & __GLS_COMMAND_ALIGN_ODD32_BIT) {
|
|
outAlignment->mask = 7;
|
|
outAlignment->value = 4;
|
|
} else {
|
|
outAlignment->mask = 3;
|
|
outAlignment->value = 0;
|
|
}
|
|
break;
|
|
case GLS_TEXT:
|
|
outAlignment->mask = 0;
|
|
outAlignment->value = 0;
|
|
break;
|
|
default:
|
|
__GLS_RAISE_ERROR(GLS_INVALID_ENUM);
|
|
return GLS_NONE;
|
|
}
|
|
return outAlignment;
|
|
}
|
|
|
|
GLbitfield glsGetCommandAttrib(GLSopcode inOpcode) {
|
|
if (!__glsValidateOpcode(inOpcode)) return GLS_NONE;
|
|
return (
|
|
__glsOpcodeAttrib[__glsMapOpcode(inOpcode)] &
|
|
__GLS_COMMAND_ATTRIB_MASK
|
|
);
|
|
}
|
|
|
|
GLint glsGetConsti(GLSenum inAttrib) {
|
|
switch (inAttrib) {
|
|
case GLS_API_COUNT:
|
|
return __GLS_API_COUNT;
|
|
case GLS_MAX_CALL_NESTING:
|
|
return __GLS_MAX_CALL_NESTING;
|
|
case GLS_MAX_CAPTURE_NESTING:
|
|
return __GLS_MAX_CAPTURE_NESTING;
|
|
case GLS_VERSION_MAJOR:
|
|
return __GLS_VERSION_MAJOR;
|
|
case GLS_VERSION_MINOR:
|
|
return __GLS_VERSION_MINOR;
|
|
}
|
|
__GLS_RAISE_ERROR(GLS_INVALID_ENUM);
|
|
return GLS_NONE;
|
|
}
|
|
|
|
const GLint* glsGetConstiv(GLSenum inAttrib) {
|
|
switch (inAttrib) {
|
|
case GLS_ALL_APIS:
|
|
return (const GLint *)__glsAllAPIs;
|
|
}
|
|
__GLS_RAISE_ERROR(GLS_INVALID_ENUM);
|
|
return GLS_NONE;
|
|
}
|
|
|
|
const GLubyte* glsGetConstubz(GLSenum inAttrib) {
|
|
switch (inAttrib) {
|
|
case GLS_EXTENSIONS:
|
|
return __glsExtensions;
|
|
case GLS_PLATFORM:
|
|
return glsCSTR(__GLS_PLATFORM);
|
|
case GLS_RELEASE:
|
|
return glsCSTR(__GLS_RELEASE);
|
|
case GLS_VENDOR:
|
|
return glsCSTR(__GLS_VENDOR);
|
|
}
|
|
__GLS_RAISE_ERROR(GLS_INVALID_ENUM);
|
|
return GLS_NONE;
|
|
}
|
|
|
|
GLuint glsGetCurrentContext(void) {
|
|
return __GLS_CONTEXT ? __GLS_CONTEXT->name : 0;
|
|
}
|
|
|
|
GLint* glsGetCurrentTime(GLint *outTime) {
|
|
GLint i;
|
|
const time_t t = time(GLS_NONE);
|
|
struct tm utc, *utcp;
|
|
|
|
__glsBeginCriticalSection();
|
|
if (utcp = gmtime(&t)) utc = *utcp;
|
|
__glsEndCriticalSection();
|
|
if (t != (time_t)-1 && utcp) {
|
|
outTime[0] = 1900 + utc.tm_year;
|
|
outTime[1] = 1 + utc.tm_mon;
|
|
outTime[2] = utc.tm_mday;
|
|
outTime[3] = utc.tm_hour;
|
|
outTime[4] = utc.tm_min;
|
|
outTime[5] = utc.tm_sec;
|
|
return outTime;
|
|
}
|
|
for (i = 0 ; i < 6 ; ++i) outTime[i] = 0;
|
|
return GLS_NONE;
|
|
}
|
|
|
|
GLSenum glsGetError(GLboolean inClear) {
|
|
const GLSenum outError = __GLS_ERROR;
|
|
|
|
if (inClear) __GLS_PUT_ERROR(GLS_NONE);
|
|
return outError;
|
|
}
|
|
|
|
GLint glsGetOpcodeCount(GLSenum inAPI) {
|
|
switch (inAPI) {
|
|
case GLS_API_GLS:
|
|
return __glsOpcodesGLSCount;
|
|
case GLS_API_GL:
|
|
return __glsOpcodesGLCount;
|
|
}
|
|
__GLS_RAISE_ERROR(GLS_INVALID_ENUM);
|
|
return GLS_NONE;
|
|
}
|
|
|
|
const GLSopcode* glsGetOpcodes(GLSenum inAPI) {
|
|
switch (inAPI) {
|
|
case GLS_API_GLS:
|
|
return __glsOpcodesGLS;
|
|
case GLS_API_GL:
|
|
return __glsOpcodesGL;
|
|
}
|
|
__GLS_RAISE_ERROR(GLS_INVALID_ENUM);
|
|
return GLS_NONE;
|
|
}
|
|
|
|
GLboolean glsIsContext(GLuint inContext) {
|
|
__GLScontext *ctx;
|
|
|
|
__glsBeginCriticalSection();
|
|
ctx = (__GLScontext *)__glsInt2PtrDict_find(
|
|
__glsContextDict, (GLint)inContext
|
|
);
|
|
__glsEndCriticalSection();
|
|
return (GLboolean)(ctx != GLS_NONE);
|
|
}
|
|
|
|
static GLboolean __glsFindExtension(
|
|
const GLubyte *inExtension, const GLubyte *inList
|
|
) {
|
|
const GLubyte *p0 = inList;
|
|
|
|
while (
|
|
p0 =
|
|
(const GLubyte *)strstr((const char *)p0, (const char *)inExtension)
|
|
) {
|
|
const GLubyte *const p1 = p0 + strlen((const char *)inExtension);
|
|
|
|
if (!*p1 || *p1 == ' ') return GL_TRUE;
|
|
p0 = p1;
|
|
}
|
|
return GL_FALSE;
|
|
}
|
|
|
|
GLboolean glsIsExtensionSupported(const GLubyte *inExtension) {
|
|
if (!__glsValidateString(inExtension)) return GL_FALSE;
|
|
if (!__glsFindExtension(inExtension, __glsExtensions)) return GL_FALSE;
|
|
if (!strncmp((const char *)inExtension, "GL_", 3)) {
|
|
const GLubyte *const p = glGetString(GL_EXTENSIONS);
|
|
|
|
if (!p || !__glsFindExtension(inExtension, p)) return GL_FALSE;
|
|
}
|
|
return GL_TRUE;
|
|
}
|
|
|
|
GLboolean glsIsUTF8String(const GLubyte *inString) {
|
|
GLuint b;
|
|
|
|
while (b = *inString) {
|
|
if (b & 0x80) goto slowPath;
|
|
++inString;
|
|
}
|
|
return GL_TRUE;
|
|
slowPath:
|
|
while (*inString) {
|
|
const GLint n = glsUTF8toUCS4(inString, &b);
|
|
|
|
if (!n) return GL_FALSE;
|
|
inString += n;
|
|
}
|
|
return GL_TRUE;
|
|
}
|
|
|
|
GLlong glsLong(GLint inHigh, GLuint inLow) {
|
|
#if __GLS_INT64
|
|
return ((GLlong)inHigh) << 32 | inLow;
|
|
#elif __GLS_MSB_FIRST
|
|
GLlong outVal;
|
|
|
|
outVal.uint0 = inHigh;
|
|
outVal.uint1 = inLow;
|
|
return outVal;
|
|
#else /* !__GLS_MSB_FIRST */
|
|
GLlong outVal;
|
|
|
|
outVal.uint0 = inLow;
|
|
outVal.uint1 = inHigh;
|
|
return outVal;
|
|
#endif /* __GLS_INT64 */
|
|
}
|
|
|
|
GLint glsLongHigh(GLlong inVal) {
|
|
#if __GLS_INT64
|
|
return (GLint)(inVal >> 32 & 0xffffffff);
|
|
#elif __GLS_MSB_FIRST
|
|
return inVal.uint0;
|
|
#else /* !__GLS_MSB_FIRST */
|
|
return inVal.uint1;
|
|
#endif /* __GLS_INT64 */
|
|
}
|
|
|
|
GLuint glsLongLow(GLlong inVal) {
|
|
#if __GLS_INT64
|
|
return (GLuint)(inVal & 0xffffffff);
|
|
#elif __GLS_MSB_FIRST
|
|
return inVal.uint1;
|
|
#else /* !__GLS_MSB_FIRST */
|
|
return inVal.uint0;
|
|
#endif /* __GLS_INT64 */
|
|
}
|
|
|
|
void glsPixelSetup(void) {
|
|
__glsPixelSetup_pack();
|
|
__glsPixelSetup_unpack();
|
|
}
|
|
|
|
GLulong glsULong(GLuint inHigh, GLuint inLow) {
|
|
#if __GLS_INT64
|
|
return ((GLulong)inHigh) << 32 | inLow;
|
|
#elif __GLS_MSB_FIRST
|
|
GLulong outVal;
|
|
|
|
outVal.uint0 = inHigh;
|
|
outVal.uint1 = inLow;
|
|
return outVal;
|
|
#else /* !__GLS_MSB_FIRST */
|
|
GLulong outVal;
|
|
|
|
outVal.uint0 = inLow;
|
|
outVal.uint1 = inHigh;
|
|
return outVal;
|
|
#endif /* __GLS_INT64 */
|
|
}
|
|
|
|
GLuint glsULongHigh(GLulong inVal) {
|
|
#if __GLS_INT64
|
|
return (GLuint)(inVal >> 32 & 0xffffffff);
|
|
#elif __GLS_MSB_FIRST
|
|
return inVal.uint0;
|
|
#else /* !__GLS_MSB_FIRST */
|
|
return inVal.uint1;
|
|
#endif /* __GLS_INT64 */
|
|
}
|
|
|
|
GLuint glsULongLow(GLulong inVal) {
|
|
#if __GLS_INT64
|
|
return (GLuint)(inVal & 0xffffffff);
|
|
#elif __GLS_MSB_FIRST
|
|
return inVal.uint1;
|
|
#else /* !__GLS_MSB_FIRST */
|
|
return inVal.uint0;
|
|
#endif /* __GLS_INT64 */
|
|
}
|
|
|
|
GLint glsUCS4toUTF8(GLuint inUCS4, GLubyte *outUTF8) {
|
|
const __GLSutf8format *format;
|
|
GLint outVal = 1;
|
|
|
|
for (format = __glsUTF8formats ; format->mask1 ; ++format, ++outVal) {
|
|
if (inUCS4 <= format->mask4) {
|
|
GLuint shift = format->shift;
|
|
|
|
*outUTF8++ = (GLubyte)(format->val1 | (inUCS4 >> shift));
|
|
while (shift) {
|
|
shift -= 6;
|
|
*outUTF8++ = (GLubyte)(0x80 | ((inUCS4 >> shift) & 0x3f));
|
|
}
|
|
return outVal;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
GLubyte* glsUCStoUTF8z(
|
|
size_t inUCSbytes,
|
|
const GLvoid *inUCSz,
|
|
size_t inUTF8max,
|
|
GLubyte *outUTF8z
|
|
) {
|
|
switch (inUCSbytes) {
|
|
case 1:
|
|
return glsUCS1toUTF8z(
|
|
(const GLubyte *)inUCSz, inUTF8max, outUTF8z
|
|
);
|
|
case 2:
|
|
return glsUCS2toUTF8z(
|
|
(const GLushort *)inUCSz, inUTF8max, outUTF8z
|
|
);
|
|
case 4:
|
|
return glsUCS4toUTF8z(
|
|
(const GLuint *)inUCSz, inUTF8max, outUTF8z
|
|
);
|
|
default:
|
|
__GLS_RAISE_ERROR(GLS_INVALID_VALUE);
|
|
return GLS_NONE;
|
|
}
|
|
}
|
|
|
|
GLubyte* glsUCS1toUTF8z(
|
|
const GLubyte *inUCS1z, size_t inUTF8max, GLubyte *outUTF8z
|
|
) {
|
|
GLuint b;
|
|
GLubyte *const limit = outUTF8z + inUTF8max - 1;
|
|
GLubyte *p = outUTF8z;
|
|
|
|
while (b = *inUCS1z++) {
|
|
if (p >= limit) return GLS_NONE;
|
|
p += glsUCS4toUTF8(b, p);
|
|
}
|
|
if (p > limit) return GLS_NONE;
|
|
*p = 0;
|
|
return outUTF8z;
|
|
}
|
|
|
|
GLubyte* glsUCS2toUTF8z(
|
|
const GLushort *inUCS2z, size_t inUTF8max, GLubyte *outUTF8z
|
|
) {
|
|
GLuint b;
|
|
GLubyte buf[3];
|
|
GLubyte *const limit = outUTF8z + inUTF8max - 1;
|
|
GLubyte *p = outUTF8z;
|
|
|
|
while (b = *inUCS2z++) {
|
|
GLubyte *bufPtr = buf;
|
|
GLubyte *p0 = p;
|
|
|
|
p += glsUCS4toUTF8(b, bufPtr);
|
|
if (p > limit) return GLS_NONE;
|
|
while (p0 < p) *p0++ = *bufPtr++;
|
|
}
|
|
*p = 0;
|
|
return outUTF8z;
|
|
}
|
|
|
|
GLubyte* glsUCS4toUTF8z(
|
|
const GLuint *inUCS4z, size_t inUTF8max, GLubyte *outUTF8z
|
|
) {
|
|
GLuint b;
|
|
GLubyte buf[6];
|
|
GLubyte *const limit = outUTF8z + inUTF8max - 1;
|
|
GLubyte *p = outUTF8z;
|
|
|
|
while (b = *inUCS4z++) {
|
|
GLubyte *bufPtr = buf;
|
|
GLubyte *p0 = p;
|
|
|
|
p += glsUCS4toUTF8(b, bufPtr);
|
|
if (p > limit) return GLS_NONE;
|
|
while (p0 < p) *p0++ = *bufPtr++;
|
|
}
|
|
*p = 0;
|
|
return outUTF8z;
|
|
}
|
|
|
|
GLint glsUTF8toUCS4(const GLubyte *inUTF8, GLuint *outUCS4) {
|
|
GLuint b, b0, ucs4;
|
|
const __GLSutf8format *format;
|
|
GLint outVal = 1;
|
|
|
|
ucs4 = b0 = *inUTF8++;
|
|
for (format = __glsUTF8formats ; format->mask1 ; ++format, ++outVal) {
|
|
if ((b0 & format->mask1) == format->val1) {
|
|
ucs4 &= format->mask4;
|
|
if (ucs4 < format->val4) return 0;
|
|
*outUCS4 = ucs4;
|
|
return outVal;
|
|
}
|
|
b = *inUTF8++ ^ 0x80;
|
|
if (b & 0xc0) return 0;
|
|
ucs4 = (ucs4 << 6) | b;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
GLboolean glsUTF8toUCSz(
|
|
size_t inUCSbytes,
|
|
const GLubyte *inUTF8z,
|
|
size_t inUCSmax,
|
|
GLvoid *outUCSz
|
|
) {
|
|
switch (inUCSbytes) {
|
|
case 1:
|
|
return glsUTF8toUCS1z(inUTF8z, inUCSmax, (GLubyte *)outUCSz);
|
|
case 2:
|
|
return glsUTF8toUCS2z(inUTF8z, inUCSmax, (GLushort *)outUCSz);
|
|
case 4:
|
|
return glsUTF8toUCS4z(inUTF8z, inUCSmax, (GLuint *)outUCSz);
|
|
default:
|
|
__GLS_RAISE_ERROR(GLS_INVALID_VALUE);
|
|
return GL_FALSE;
|
|
}
|
|
}
|
|
|
|
GLboolean glsUTF8toUCS1z(
|
|
const GLubyte *inUTF8z, size_t inUCS1max, GLubyte *outUCS1z
|
|
) {
|
|
GLuint b;
|
|
GLubyte *const limit = outUCS1z + inUCS1max - 1;
|
|
|
|
while (*inUTF8z) {
|
|
const GLint n = glsUTF8toUCS4(inUTF8z, &b);
|
|
|
|
if (n && b <= 0xff && outUCS1z < limit) {
|
|
inUTF8z += n;
|
|
*outUCS1z++ = (GLubyte)b;
|
|
} else {
|
|
return GL_FALSE;
|
|
}
|
|
}
|
|
if (outUCS1z > limit) return GL_FALSE;
|
|
*outUCS1z = 0;
|
|
return GL_TRUE;
|
|
}
|
|
|
|
GLboolean glsUTF8toUCS2z(
|
|
const GLubyte *inUTF8z, size_t inUCS2max, GLushort *outUCS2z
|
|
) {
|
|
GLuint b;
|
|
GLushort *const limit = outUCS2z + inUCS2max - 1;
|
|
|
|
while (*inUTF8z) {
|
|
const GLint n = glsUTF8toUCS4(inUTF8z, &b);
|
|
|
|
if (n && b <= 0xffff && outUCS2z < limit) {
|
|
inUTF8z += n;
|
|
*outUCS2z++ = (GLushort)b;
|
|
} else {
|
|
return GL_FALSE;
|
|
}
|
|
}
|
|
if (outUCS2z > limit) return GL_FALSE;
|
|
*outUCS2z = 0;
|
|
return GL_TRUE;
|
|
}
|
|
|
|
GLboolean glsUTF8toUCS4z(
|
|
const GLubyte *inUTF8z, size_t inUCS4max, GLuint *outUCS4z
|
|
) {
|
|
GLuint b;
|
|
GLuint *const limit = outUCS4z + inUCS4max - 1;
|
|
|
|
while (*inUTF8z) {
|
|
const GLint n = glsUTF8toUCS4(inUTF8z, &b);
|
|
|
|
if (n && outUCS4z < limit) {
|
|
inUTF8z += n;
|
|
*outUCS4z++ = b;
|
|
} else {
|
|
return GL_FALSE;
|
|
}
|
|
}
|
|
if (outUCS4z > limit) return GL_FALSE;
|
|
*outUCS4z = 0;
|
|
return GL_TRUE;
|
|
}
|