home *** CD-ROM | disk | FTP | other *** search
/ synchro.net / synchro.net.tar / synchro.net / main / BBS / ODOORS62.ZIP / ODUtil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-07  |  13.9 KB  |  456 lines

  1. /* OpenDoors Online Software Programming Toolkit
  2.  * (C) Copyright 1991 - 1999 by Brian Pirie.
  3.  *
  4.  * This library is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU Lesser General Public
  6.  * License as published by the Free Software Foundation; either
  7.  * version 2 of the License, or (at your option) any later version.
  8.  *
  9.  * This library is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.  * Lesser General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU Lesser General Public
  15.  * License along with this library; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.  *
  18.  *
  19.  *        File: ODUtil.c
  20.  *
  21.  * Description: Implements the non-platform specific utility functions that
  22.  *              are defined in odutil.h. Platform specific utility functions
  23.  *              are implemented in odplat.c.
  24.  *
  25.  *
  26.  *   Revisions: Date          Ver   Who  Change
  27.  *              ---------------------------------------------------------------
  28.  *              Nov 01, 1994  6.00  BP   Created.
  29.  *              Dec 31, 1994  6.00  BP   Added ODMakeFilename().
  30.  *              Nov 13, 1995  6.00  BP   32-bit portability.
  31.  *              Nov 23, 1995  6.00  BP   Added ODDWordDivide().
  32.  *              Nov 23, 1995  6.00  BP   Added ODDStringHasTail().
  33.  *              Nov 23, 1995  6.00  BP   Added ODFileSize().
  34.  *              Nov 24, 1995  6.00  BP   ODMakeFilename(): handle empty path.
  35.  *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
  36.  *              Mar 03, 1996  6.10  BP   Begin version 6.10.
  37.  *              Mar 06, 1996  6.10  BP   Added ODDWordMultiply().
  38.  */
  39.  
  40. #define BUILDING_OPENDOORS
  41.  
  42. #include <string.h>
  43. #include <stdio.h>
  44.  
  45. #include "OpenDoor.h"
  46. #include "ODUtil.h"
  47. #include "ODGen.h"
  48.  
  49.  
  50. /* ========================================================================= */
  51. /* General string manipulation functions.                                    */
  52. /* ========================================================================= */
  53.  
  54. /* ----------------------------------------------------------------------------
  55.  * ODStringCopy()
  56.  *
  57.  * Safely copies one string to another. Unlike strncpy(), ODStringCopy()
  58.  * ensures that the destination string is always '\0' terminated.
  59.  *
  60.  * Parameters: pszDest     - Pointer to destination string to which to copy
  61.  *                           characters.
  62.  *
  63.  *             pszSource   - Pointer to source string from which to copy
  64.  *                           characters.
  65.  *
  66.  *             nSizeOfDest - Maximum number of characters to place in pszDest,
  67.  *                           INCLUDING the '\0' string terminator.
  68.  *
  69.  *     Return: void
  70.  */
  71. void ODStringCopy(char *pszDest, CONST char *pszSource, INT nSizeofDest)
  72. {
  73.    ASSERT(pszDest != NULL);
  74.    ASSERT(pszSource != NULL);
  75.    ASSERT(nSizeofDest > 0);
  76.  
  77.    /* Copy at most the specified number of bytes from source to dest, using */
  78.    /* (presumably well optimized) strncpy().                                */
  79.    strncpy(pszDest, pszSource, nSizeofDest);
  80.  
  81.    /* Ensure that destination string is '\0' terminated. This will not */
  82.    /* already be the case if strlen(pszSource) >= nSizeofDest.         */
  83.    pszDest[nSizeofDest - 1] = '\0';
  84. }
  85.  
  86.  
  87. /* ----------------------------------------------------------------------------
  88.  * ODStringCToPascal()
  89.  *
  90.  * Converts a string from C's zero-terminated string format to Pascal's
  91.  * length byte + string data format.
  92.  *
  93.  * Parameters: psPascalString    - Pointer to the destination string.
  94.  *
  95.  *             btMaxPascalLength - Size of the destination string, as declared
  96.  *                                 in Pascal.
  97.  *
  98.  *             pszCString        - Pointer to the source string, in C format.
  99.  *
  100.  *     Return: A pointer to psPascalString.
  101.  */
  102. char *ODStringCToPascal(char *psPascalString, BYTE btMaxPascalLength,
  103.    char *pszCString)
  104. {
  105.    BYTE btCStringLength = strlen(pszCString);
  106.  
  107.    ASSERT(psPascalString != NULL);
  108.    ASSERT(btMaxPascalLength > 0);
  109.    ASSERT(pszCString != NULL);
  110.  
  111.    memcpy((char *)psPascalString + 1,
  112.       pszCString, *psPascalString = (btCStringLength < btMaxPascalLength)
  113.       ? btCStringLength : btMaxPascalLength);
  114.    return(psPascalString);
  115. }
  116.  
  117.  
  118. /* ----------------------------------------------------------------------------
  119.  * ODStringPascalToC()
  120.  *
  121.  * Converts a string from Pascal's length byte + string data format to C's
  122.  * zero-terminated string format.
  123.  *
  124.  * Parameters: pszCString     - Pointer to destination string.
  125.  *
  126.  *             psPascalString - Pointer to Pascal format source string.
  127.  *
  128.  *             btMaxLength    - Length of C string.
  129.  *
  130.  *     Return: A pointer to pszCString.
  131.  */
  132. char *ODStringPascalToC(char *pszCString, char *psPascalString,
  133.    BYTE btMaxLength)
  134. {
  135.    ASSERT(pszCString != NULL);
  136.    ASSERT(psPascalString != NULL);
  137.    ASSERT(btMaxLength > 0);
  138.  
  139.    if(*(BYTE *)psPascalString <= btMaxLength)
  140.    {
  141.       memcpy(pszCString, (char *)psPascalString + 1, *psPascalString);
  142.       pszCString[*psPascalString] = '\0';
  143.    }
  144.    else
  145.    {
  146.       pszCString[0] = '\0';
  147.    }
  148.    return(pszCString);
  149. }
  150.  
  151.  
  152. /* ----------------------------------------------------------------------------
  153.  * ODStringHasTail()
  154.  *
  155.  * Determines whether a string ends in exactly the specified sequence of
  156.  * characters.
  157.  *
  158.  * Parameters: pszFullString  - String to examine.
  159.  *
  160.  *             pszTail        - String to look for at the end of
  161.  *                              pszFullString.
  162.  *
  163.  *     Return: TRUE if the pszFullString does end with pszTail, FALSE if
  164.  *             it does not.
  165.  */
  166. BOOL ODStringHasTail(char *pszFullString, char *pszTail)
  167. {
  168.    INT nTailLength = strlen(pszTail);
  169.    INT nFullStringLength = strlen(pszFullString);
  170.  
  171.    ASSERT(pszFullString != NULL);
  172.    ASSERT(pszTail != NULL);
  173.  
  174.    if(nFullStringLength < nTailLength)
  175.    {
  176.       return(FALSE);
  177.    }
  178.  
  179.    return(stricmp(pszFullString + (nFullStringLength - nTailLength), pszTail) == 0);
  180. }
  181.  
  182.  
  183. /* ========================================================================= */
  184. /* File-related functions.                                                   */
  185. /* ========================================================================= */
  186.  
  187. /* ----------------------------------------------------------------------------
  188.  * ODMakeFilename()
  189.  *
  190.  * Generates a fully-qualified filename from a path and base filename.
  191.  *
  192.  * Parameters: pszOut      - String to store generated filename in.
  193.  *
  194.  *             pszPath     - Directory name. May be the same as pszOut, or
  195.  *                           may be different.
  196.  *
  197.  *             pszFilename - Base filename.
  198.  *
  199.  *             nMaxOutSize - Size of pszOut. This value should be one more
  200.  *                           than the maximum number of characters to be
  201.  *                           stored in the output string.
  202.  *
  203.  *     Return: kODRCSuccess on success, or an error code on failure.
  204.  */
  205. tODResult ODMakeFilename(char *pszOut, CONST char *pszPath,
  206.    CONST char *pszFilename, INT nMaxOutSize)
  207. {
  208.    /* Validate parameters in debug mode */
  209.    ASSERT(pszPath != NULL);
  210.    ASSERT(pszFilename != NULL);
  211.    ASSERT(pszOut != NULL);
  212.    ASSERT(pszFilename != pszOut);
  213.    ASSERT(nMaxOutSize > 0);
  214.  
  215.    /* Check that there is enough room in the destination string to hold */
  216.    /* both source strings plus possibly an additional \-seperator.      */
  217.    if((INT)(strlen(pszPath) + strlen(pszFilename) + 1) > nMaxOutSize - 1)
  218.    {
  219.       return(kODRCFilenameTooLong);
  220.    }
  221.  
  222.    /* Copy path to output filename, if the addresses are different. */
  223.    if(pszPath != pszOut)
  224.    {
  225.       strcpy(pszOut, pszPath);
  226.    }
  227.  
  228.    /* Ensure there is a trailing backslash, if path was not empty. */
  229.    if(pszOut[strlen(pszOut) - 1] != '\\' && strlen(pszOut) > 0)
  230.    {
  231.       strcat(pszOut, "\\");
  232.    }
  233.  
  234.    /* Append base filename. */
  235.    strcat(pszOut, pszFilename);
  236.  
  237.    return(kODRCSuccess);
  238. }
  239.  
  240.  
  241. /* ----------------------------------------------------------------------------
  242.  * ODFileSize()
  243.  *
  244.  * Determines the size of a currently open file.
  245.  *
  246.  * Parameters: pfFile - Pointer to an already open file to examine.
  247.  *
  248.  *     Return: The size of the file. In the case of a file that is open in
  249.  *             binary mode, this will be the file length in bytes.
  250.  */
  251. DWORD ODFileSize(FILE *pfFile)
  252. {
  253.    DWORD dwOriginal;
  254.    DWORD dwFileSize;
  255.  
  256.    ASSERT(pfFile != NULL);
  257.  
  258.    dwOriginal = ftell(pfFile);
  259.    fseek(pfFile, 0L, SEEK_END);
  260.    dwFileSize = ftell(pfFile);
  261.    fseek(pfFile, dwOriginal, SEEK_SET);
  262.    return(dwFileSize);
  263. }
  264.  
  265.  
  266. /* ========================================================================= */
  267. /* DWORD math functions.                                                     */
  268. /* ========================================================================= */
  269.  
  270. /* ----------------------------------------------------------------------------
  271.  * ODDWordShiftLeft()
  272.  *
  273.  * Shifts a DWORD to the left by the specified number of bits.
  274.  *
  275.  * Parameters: dwValue    - Value to be shifted.
  276.  *
  277.  *             btDistance - Distance to shift dwValue by.
  278.  *
  279.  *     Return: Result of the shift operation.
  280.  */
  281. DWORD ODDWordShiftLeft(DWORD dwValue, BYTE btDistance)
  282. {
  283.    WORD wUpper;
  284.    WORD wLower;
  285.  
  286.    wLower = (WORD)dwValue;
  287.    wUpper = *(WORD *)(((BYTE *)(&dwValue)) + 2);
  288.  
  289.    while(btDistance--)
  290.    {
  291.       wUpper <<= 1;
  292.       wUpper |= (wLower & 0x8000) >> 15;
  293.       wLower <<= 1;
  294.    }
  295.  
  296.    dwValue = wLower;
  297.    *(WORD *)(((BYTE *)(&dwValue)) + 2) = wUpper;
  298.  
  299.    return(dwValue);
  300. }
  301.  
  302.  
  303. /* ----------------------------------------------------------------------------
  304.  * ODDWordShiftRight()
  305.  *
  306.  * Shifts a DWORD to the right by the specified number of bits.
  307.  *
  308.  * Parameters: dwValue    - Value to be shifted.
  309.  *
  310.  *             btDistance - Distance to shift dwValue by.
  311.  *
  312.  *     Return: Result of the shift operation.
  313.  */
  314. DWORD ODDWordShiftRight(DWORD dwValue, BYTE btDistance)
  315. {
  316.    WORD wUpper;
  317.    WORD wLower;
  318.  
  319.    wLower = (WORD)dwValue;
  320.    wUpper = *(WORD *)(((BYTE *)(&dwValue)) + 2);
  321.  
  322.    while(btDistance--)
  323.    {
  324.       wLower >>= 1;
  325.       wLower |= (wUpper & 0x0001) << 15;
  326.       wUpper >>= 1;
  327.    }
  328.  
  329.    dwValue=wLower;
  330.    *(WORD *)(((BYTE *)(&dwValue)) + 2) = wUpper;
  331.    return(dwValue);
  332. }
  333.  
  334.  
  335. /* ----------------------------------------------------------------------------
  336.  * ODDWordDivide()
  337.  *
  338.  * Divides one DWORD by another DWORD, calculating the quotient and remainder.
  339.  *
  340.  * Parameters: pdwQuotient   - Location where the quotient should be stored,
  341.  *                             or NULL if quotient is not required.
  342.  *
  343.  *             pdwRemainder  - Location where remainder should be stored,
  344.  *                             or NULL if remainder is not required.
  345.  *
  346.  *             dwDividend    - Dividend to be divided by divisor.
  347.  *
  348.  *             dwDivisor     - Divisor to divide dividend by.
  349.  *
  350.  *     Return: TRUE on success or FALSE on failure.
  351.  */
  352. BOOL ODDWordDivide(DWORD *pdwQuotient, DWORD *pdwRemainder,
  353.    DWORD dwDividend, DWORD dwDivisor)
  354. {
  355.    INT nTimes = 0;
  356.    DWORD dwQuotient;
  357.    DWORD dwRemainder;
  358.  
  359.    /* Check for divide by zero in debug versions. */
  360.    ASSERT(dwDivisor != 0);
  361.  
  362.    /* Check that divisor is not zero. (An attempt to divide by zero will */
  363.    /* put this algorithm into an infinite loop, rather than triggering   */
  364.    /* a divide fault.)                                                   */
  365.    if(dwDivisor == 0L)
  366.    {
  367.       return(FALSE);
  368.    }
  369.  
  370.    /* Initialize remainder to be entire dividend */
  371.    dwRemainder = dwDividend;
  372.  
  373.    /* Initialize quotient to 0 */
  374.    dwQuotient = 0L;
  375.  
  376.    /* Determine largest required multiple of divisor */
  377.    while(dwRemainder >=  dwDivisor)
  378.    {
  379.       dwDivisor = ODDWordShiftLeft(dwDivisor, 1);
  380.       ++nTimes;
  381.    }
  382.  
  383.    /* Loop across for all multiples of divisor, beginning with the largest */
  384.    do
  385.    {
  386.       dwQuotient = ODDWordShiftLeft(dwQuotient, 1);
  387.  
  388.       /* If current remainder is >= this multiple of the divisor */
  389.       if(dwRemainder >= dwDivisor)
  390.       {
  391.          /* Subtract the multiple of the divisor from the remainder */
  392.          dwRemainder -= dwDivisor;
  393.  
  394.          /* The next bit of the quotient should be a 1 */
  395.          dwQuotient |= 1L;
  396.       }
  397.  
  398.       /* Divide current multiple of divisor by two */
  399.       dwDivisor = ODDWordShiftRight(dwDivisor, 1);
  400.  
  401.       /* Repeat for all multiples of the divisor */
  402.    } while(nTimes--);
  403.  
  404.    /* If caller asked for quotient, then return it */
  405.    if(pdwQuotient != NULL)
  406.    {
  407.       *pdwQuotient = dwQuotient;
  408.    }
  409.  
  410.    /* If caller asked for remainder, then return it */
  411.    if(pdwRemainder != NULL)
  412.    {
  413.       *pdwRemainder = dwRemainder;
  414.    }
  415.  
  416.    return(TRUE);
  417. }
  418.  
  419.  
  420. /* ----------------------------------------------------------------------------
  421.  * ODDWordDivide()
  422.  *
  423.  * Multiplies one DWORD by another, returning the product. Multiplication
  424.  * is performed by using at most 32 additions.
  425.  *
  426.  * Parameters: dwMultiplicand - The multiplicand.
  427.  *
  428.  *             dwMultiplier   - The multiplier.
  429.  *
  430.  *     Return: Result of the multiplication.
  431.  */
  432. DWORD ODDWordMultiply(DWORD dwMultiplicand, DWORD dwMultiplier)
  433. {
  434.    DWORD dwResult = 0;
  435.  
  436.    /* Loop while multiplier is not zero */
  437.    while(dwMultiplier != 0)
  438.    {
  439.       /* If least significant bit of multiplier is set */
  440.       if(dwMultiplier & 0x00000001)
  441.       {
  442.          /* Add multiplicand to product */
  443.          dwResult += dwMultiplicand;
  444.       }
  445.  
  446.       /* Shift multiplicand left one bit */
  447.       dwMultiplicand = ODDWordShiftLeft(dwMultiplicand, 1);
  448.  
  449.       /* Shift multiplier right one bit */
  450.       dwMultiplier = ODDWordShiftRight(dwMultiplier, 1);
  451.    }
  452.  
  453.    /* Return the final result to the caller. */
  454.    return(dwResult);
  455. }
  456.