123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- /* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * File: ODUtil.c
- *
- * Description: Implements the non-platform specific utility functions that
- * are defined in odutil.h. Platform specific utility functions
- * are implemented in odplat.c.
- *
- *
- * Revisions: Date Ver Who Change
- * ---------------------------------------------------------------
- * Nov 01, 1994 6.00 BP Created.
- * Dec 31, 1994 6.00 BP Added ODMakeFilename().
- * Nov 13, 1995 6.00 BP 32-bit portability.
- * Nov 23, 1995 6.00 BP Added ODDWordDivide().
- * Nov 23, 1995 6.00 BP Added ODDStringHasTail().
- * Nov 23, 1995 6.00 BP Added ODFileSize().
- * Nov 24, 1995 6.00 BP ODMakeFilename(): handle empty path.
- * Feb 19, 1996 6.00 BP Changed version number to 6.00.
- * Mar 03, 1996 6.10 BP Begin version 6.10.
- * Mar 06, 1996 6.10 BP Added ODDWordMultiply().
- * Aug 10, 2003 6.23 SH *nix support
- */
- #define BUILDING_OPENDOORS
- #include <string.h>
- #include <stdio.h>
- #include "OpenDoor.h"
- #include "ODStr.h"
- #include "ODUtil.h"
- #include "ODGen.h"
- /* ========================================================================= */
- /* General string manipulation functions. */
- /* ========================================================================= */
- /* ----------------------------------------------------------------------------
- * ODStringCopy()
- *
- * Safely copies one string to another. Unlike strncpy(), ODStringCopy()
- * ensures that the destination string is always '\0' terminated.
- *
- * Parameters: pszDest - Pointer to destination string to which to copy
- * characters.
- *
- * pszSource - Pointer to source string from which to copy
- * characters.
- *
- * nSizeOfDest - Maximum number of characters to place in pszDest,
- * INCLUDING the '\0' string terminator.
- *
- * Return: void
- */
- void ODStringCopy(char *pszDest, CONST char *pszSource, INT nSizeofDest)
- {
- ASSERT(pszDest != NULL);
- ASSERT(pszSource != NULL);
- ASSERT(nSizeofDest > 0);
- /* Copy at most the specified number of bytes from source to dest, using */
- /* (presumably well optimized) strncpy(). */
- strncpy(pszDest, pszSource, nSizeofDest);
- /* Ensure that destination string is '\0' terminated. This will not */
- /* already be the case if strlen(pszSource) >= nSizeofDest. */
- pszDest[nSizeofDest - 1] = '\0';
- }
- /* ----------------------------------------------------------------------------
- * ODStringCToPascal()
- *
- * Converts a string from C's zero-terminated string format to Pascal's
- * length byte + string data format.
- *
- * Parameters: psPascalString - Pointer to the destination string.
- *
- * btMaxPascalLength - Size of the destination string, as declared
- * in Pascal.
- *
- * pszCString - Pointer to the source string, in C format.
- *
- * Return: A pointer to psPascalString.
- */
- char *ODStringCToPascal(char *psPascalString, BYTE btMaxPascalLength,
- char *pszCString)
- {
- BYTE btCStringLength = strlen(pszCString);
- ASSERT(psPascalString != NULL);
- ASSERT(btMaxPascalLength > 0);
- ASSERT(pszCString != NULL);
- memcpy((char *)psPascalString + 1,
- pszCString, *psPascalString = (btCStringLength < btMaxPascalLength)
- ? btCStringLength : btMaxPascalLength);
- return(psPascalString);
- }
- /* ----------------------------------------------------------------------------
- * ODStringPascalToC()
- *
- * Converts a string from Pascal's length byte + string data format to C's
- * zero-terminated string format.
- *
- * Parameters: pszCString - Pointer to destination string.
- *
- * psPascalString - Pointer to Pascal format source string.
- *
- * btMaxLength - Length of C string.
- *
- * Return: A pointer to pszCString.
- */
- char *ODStringPascalToC(char *pszCString, char *psPascalString,
- BYTE btMaxLength)
- {
- ASSERT(pszCString != NULL);
- ASSERT(psPascalString != NULL);
- ASSERT(btMaxLength > 0);
- if(*(BYTE *)psPascalString <= btMaxLength)
- {
- memcpy(pszCString, (char *)psPascalString + 1, *psPascalString);
- pszCString[(int)psPascalString[0]] = '\0';
- }
- else
- {
- pszCString[0] = '\0';
- }
- return(pszCString);
- }
- /* ----------------------------------------------------------------------------
- * ODStringHasTail()
- *
- * Determines whether a string ends in exactly the specified sequence of
- * characters.
- *
- * Parameters: pszFullString - String to examine.
- *
- * pszTail - String to look for at the end of
- * pszFullString.
- *
- * Return: TRUE if the pszFullString does end with pszTail, FALSE if
- * it does not.
- */
- BOOL ODStringHasTail(char *pszFullString, char *pszTail)
- {
- INT nTailLength = strlen(pszTail);
- INT nFullStringLength = strlen(pszFullString);
- ASSERT(pszFullString != NULL);
- ASSERT(pszTail != NULL);
- if(nFullStringLength < nTailLength)
- {
- return(FALSE);
- }
- return(stricmp(pszFullString + (nFullStringLength - nTailLength), pszTail) == 0);
- }
- /* ========================================================================= */
- /* File-related functions. */
- /* ========================================================================= */
- /* ----------------------------------------------------------------------------
- * ODMakeFilename()
- *
- * Generates a fully-qualified filename from a path and base filename.
- *
- * Parameters: pszOut - String to store generated filename in.
- *
- * pszPath - Directory name. May be the same as pszOut, or
- * may be different.
- *
- * pszFilename - Base filename.
- *
- * nMaxOutSize - Size of pszOut. This value should be one more
- * than the maximum number of characters to be
- * stored in the output string.
- *
- * Return: kODRCSuccess on success, or an error code on failure.
- */
- tODResult ODMakeFilename(char *pszOut, CONST char *pszPath,
- CONST char *pszFilename, INT nMaxOutSize)
- {
- /* Validate parameters in debug mode */
- ASSERT(pszPath != NULL);
- ASSERT(pszFilename != NULL);
- ASSERT(pszOut != NULL);
- ASSERT(pszFilename != pszOut);
- ASSERT(nMaxOutSize > 0);
- /* Check that there is enough room in the destination string to hold */
- /* both source strings plus possibly an additional \-seperator. */
- if((INT)(strlen(pszPath) + strlen(pszFilename) + 1) > nMaxOutSize - 1)
- {
- return(kODRCFilenameTooLong);
- }
- /* Copy path to output filename, if the addresses are different. */
- if(pszPath != pszOut)
- {
- strcpy(pszOut, pszPath);
- }
- /* Ensure there is a trailing backslash, if path was not empty. */
- #ifdef ODPLAT_NIX
- #else
- if(pszOut[strlen(pszOut) - 1] != DIRSEP && strlen(pszOut) > 0)
- {
- strcat(pszOut, DIRSEP_STR);
- }
- #endif
- /* Append base filename. */
- strcat(pszOut, pszFilename);
- return(kODRCSuccess);
- }
- /* ----------------------------------------------------------------------------
- * ODFileSize()
- *
- * Determines the size of a currently open file.
- *
- * Parameters: pfFile - Pointer to an already open file to examine.
- *
- * Return: The size of the file. In the case of a file that is open in
- * binary mode, this will be the file length in bytes.
- */
- DWORD ODFileSize(FILE *pfFile)
- {
- DWORD dwOriginal;
- DWORD dwFileSize;
- ASSERT(pfFile != NULL);
- dwOriginal = ftell(pfFile);
- fseek(pfFile, 0L, SEEK_END);
- dwFileSize = ftell(pfFile);
- fseek(pfFile, dwOriginal, SEEK_SET);
- return(dwFileSize);
- }
- /* ========================================================================= */
- /* DWORD math functions. */
- /* ========================================================================= */
- /* ----------------------------------------------------------------------------
- * ODDWordShiftLeft()
- *
- * Shifts a DWORD to the left by the specified number of bits.
- *
- * Parameters: dwValue - Value to be shifted.
- *
- * btDistance - Distance to shift dwValue by.
- *
- * Return: Result of the shift operation.
- */
- DWORD ODDWordShiftLeft(DWORD dwValue, BYTE btDistance)
- {
- WORD wUpper;
- WORD wLower;
- wLower = (WORD)dwValue;
- wUpper = *(WORD *)(((BYTE *)(&dwValue)) + 2);
- while(btDistance--)
- {
- wUpper <<= 1;
- wUpper |= (wLower & 0x8000) >> 15;
- wLower <<= 1;
- }
- dwValue = wLower;
- *(WORD *)(((BYTE *)(&dwValue)) + 2) = wUpper;
- return(dwValue);
- }
- /* ----------------------------------------------------------------------------
- * ODDWordShiftRight()
- *
- * Shifts a DWORD to the right by the specified number of bits.
- *
- * Parameters: dwValue - Value to be shifted.
- *
- * btDistance - Distance to shift dwValue by.
- *
- * Return: Result of the shift operation.
- */
- DWORD ODDWordShiftRight(DWORD dwValue, BYTE btDistance)
- {
- WORD wUpper;
- WORD wLower;
- wLower = (WORD)dwValue;
- wUpper = *(WORD *)(((BYTE *)(&dwValue)) + 2);
- while(btDistance--)
- {
- wLower >>= 1;
- wLower |= (wUpper & 0x0001) << 15;
- wUpper >>= 1;
- }
- dwValue=wLower;
- *(WORD *)(((BYTE *)(&dwValue)) + 2) = wUpper;
- return(dwValue);
- }
- /* ----------------------------------------------------------------------------
- * ODDWordDivide()
- *
- * Divides one DWORD by another DWORD, calculating the quotient and remainder.
- *
- * Parameters: pdwQuotient - Location where the quotient should be stored,
- * or NULL if quotient is not required.
- *
- * pdwRemainder - Location where remainder should be stored,
- * or NULL if remainder is not required.
- *
- * dwDividend - Dividend to be divided by divisor.
- *
- * dwDivisor - Divisor to divide dividend by.
- *
- * Return: TRUE on success or FALSE on failure.
- */
- BOOL ODDWordDivide(DWORD *pdwQuotient, DWORD *pdwRemainder,
- DWORD dwDividend, DWORD dwDivisor)
- {
- INT nTimes = 0;
- DWORD dwQuotient;
- DWORD dwRemainder;
- /* Check for divide by zero in debug versions. */
- ASSERT(dwDivisor != 0);
- /* Check that divisor is not zero. (An attempt to divide by zero will */
- /* put this algorithm into an infinite loop, rather than triggering */
- /* a divide fault.) */
- if(dwDivisor == 0L)
- {
- return(FALSE);
- }
- /* Initialize remainder to be entire dividend */
- dwRemainder = dwDividend;
- /* Initialize quotient to 0 */
- dwQuotient = 0L;
- /* Determine largest required multiple of divisor */
- while(dwRemainder >= dwDivisor)
- {
- dwDivisor = ODDWordShiftLeft(dwDivisor, 1);
- ++nTimes;
- }
- /* Loop across for all multiples of divisor, beginning with the largest */
- do
- {
- dwQuotient = ODDWordShiftLeft(dwQuotient, 1);
- /* If current remainder is >= this multiple of the divisor */
- if(dwRemainder >= dwDivisor)
- {
- /* Subtract the multiple of the divisor from the remainder */
- dwRemainder -= dwDivisor;
- /* The next bit of the quotient should be a 1 */
- dwQuotient |= 1L;
- }
- /* Divide current multiple of divisor by two */
- dwDivisor = ODDWordShiftRight(dwDivisor, 1);
- /* Repeat for all multiples of the divisor */
- } while(nTimes--);
- /* If caller asked for quotient, then return it */
- if(pdwQuotient != NULL)
- {
- *pdwQuotient = dwQuotient;
- }
- /* If caller asked for remainder, then return it */
- if(pdwRemainder != NULL)
- {
- *pdwRemainder = dwRemainder;
- }
- return(TRUE);
- }
- /* ----------------------------------------------------------------------------
- * ODDWordDivide()
- *
- * Multiplies one DWORD by another, returning the product. Multiplication
- * is performed by using at most 32 additions.
- *
- * Parameters: dwMultiplicand - The multiplicand.
- *
- * dwMultiplier - The multiplier.
- *
- * Return: Result of the multiplication.
- */
- DWORD ODDWordMultiply(DWORD dwMultiplicand, DWORD dwMultiplier)
- {
- DWORD dwResult = 0;
- /* Loop while multiplier is not zero */
- while(dwMultiplier != 0)
- {
- /* If least significant bit of multiplier is set */
- if(dwMultiplier & 0x00000001)
- {
- /* Add multiplicand to product */
- dwResult += dwMultiplicand;
- }
- /* Shift multiplicand left one bit */
- dwMultiplicand = ODDWordShiftLeft(dwMultiplicand, 1);
- /* Shift multiplier right one bit */
- dwMultiplier = ODDWordShiftRight(dwMultiplier, 1);
- }
- /* Return the final result to the caller. */
- return(dwResult);
- }
|