/*--[litlib.c]----------------------------------------------------------------- | Copyright (C) 2004 Digital Rights Software | | This file is part of the "openclit" library for processing .LIT files. | | "Openclit" is free software; you can redistribute it and/or modify | it under the terms of the GNU General Public License as published by | the Free Software Foundation; either version 2 of the License, or | (at your option) any later version. | | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU General Public License for more details. | | You should have received a copy of the GNU General Public License | along with this program; if not, write to the Free Software | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | | The GNU General Public License may also be available at the following | URL: http://www.gnu.org/licenses/gpl.html */ #include #include #include #include #include "litlib.h" #include "litinternal.h" int lit_i_utf8_len_to_bytes(U8 * src, int lenSrc, int sizeSrc); /*****************************************************************************/ /*--[strmerge]---------------------------------------------------------------- | Routine to "safely" merge strings, while reporting errors on failure | This keeps merging strings until it finds a NULL. | Bad things happens to the user that forgets that final NULL! */ char * lit_i_strmerge(const char * first, ...) { va_list ap; const char * s; char * new, *ptr; int len; s = first; len = 0; va_start(ap, first); do { len += strlen(s); s = va_arg(ap, char *); } while (s); ptr = new = (char *)malloc(len + 1); if (!new) { lit_error(0,"Unable to malloc %d bytes for a string.",len); return NULL; } s = first; va_start(ap, first); do { strcpy(ptr, s); ptr += strlen(ptr); s = va_arg(ap, char *); } while (s); *(ptr) = '\0'; va_end(ap); return new; } /*--[lit_i_read_utf8_string]--------------------------------------------------- | | This routine allocates memory for and copies an UTF8 string from the | current location. */ U8 * lit_i_read_utf8_string(U8 * p, int remaining, int * size) { U8 * sNew; int len, nbytes; len = 1; if (remaining < 1) goto out_of_bytes; len = *p; nbytes = lit_i_utf8_len_to_bytes((p + 1), len, remaining - 1); if (nbytes < 0) goto out_of_bytes; sNew = (U8 *)malloc(nbytes + 1); if (!sNew) { lit_error(ERR_R|ERR_LIBC,"malloc(%d) failed!",nbytes+1); return NULL; } if (!sNew) return NULL; memcpy( sNew, (p+1), nbytes); sNew[nbytes] = '\0'; if (size) *size = nbytes + 1; return sNew; out_of_bytes: lit_error(ERR_R, "utf8 reader tried to read past an internal file boundary!\n" "\tTried to read %d characters, but only %d bytes are left.", len, remaining); return NULL; } /*--[lit_i_utf8_len_to_bytes]-------------------------------------------------- | | This converts a count of UTF8 elements to the amount of bytes that it | consumes. This is for the parsing of '/manifest' files, where the length | field isn't the number of bytes as might be expected. | | Most other LIT strings (such as the directory) store byte counts for | the length. */ int lit_i_utf8_len_to_bytes(U8 * src, int lenSrc, int sizeSrc) { int nchars, nbytes; nbytes = 0; nchars = 0; while (nchars < lenSrc) { /* The only thing NOT counted in lenSrc is a character 10xx xxxx */ if ((*(src + nbytes) & 0xC0) != 0x80) nchars++; nbytes++; if (nbytes > sizeSrc) { return -1; } } /* Copy over any trailing unicode bytes */ while (( *(src + nbytes) & 0xC0) == 0x80) { nbytes++; if (nbytes > sizeSrc) { return -1; } } return nbytes; }