home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 June: Reference Library / Dev.CD Jun 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 28 / develop issue 28 code / sketch / source / utilities / stringutils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-11  |  12.1 KB  |  475 lines

  1. /****************************************************************************
  2.  * 
  3.  * StringUtils.c
  4.  * 
  5.  * General string manipulation functions
  6.  *
  7.  ****************************************************************************/
  8. #include <stdio.h>
  9. #include <stdarg.h>
  10. #include <string.h>
  11. #include <limits.h>
  12.  
  13. #include "StringUtils.h"
  14. #include "Assertion.h"
  15.  
  16. /*****************************************************************************
  17.  * 
  18.  * UpperChar
  19.  * 
  20.  *****************************************************************************/
  21. char UpperChar(char chr)
  22. {
  23.     if ((chr >= 'a') && (chr <= 'z'))
  24.         chr -= 'a' - 'A';
  25.         
  26.     return chr;
  27. }
  28.  
  29. /*****************************************************************************
  30.  * 
  31.  * C STRINGS
  32.  * 
  33.  * Various strings for manipulating existing C strings as well as for
  34.  * converting to Pascal style strings
  35.  *      
  36.  *****************************************************************************/
  37. /*****************************************************************************
  38.  * 
  39.  * CStringCompare
  40.  * 
  41.  * Compares two C-style strings and returns the following with case sensitivity
  42.  * as an option.
  43.  * 
  44.  *        -2        if either string pointer is nil
  45.  *     -1        if string 1 is less than string 2
  46.  *      0        if the strings are equal
  47.  *      1        if string 2 is greater than string 1
  48.  *      
  49.  *****************************************************************************/
  50. short CStringCompare(const char *s1, const char *s2, Boolean caseSensitive)
  51. {
  52.     long    len, len1, len2;
  53.     char    chr1, chr2;
  54.     
  55.  
  56.     if ((!s1) || (!s2))                                // sanity check for nil pointers
  57.         return -2;
  58.         
  59.     len1 = CStringLength(s1);                        // get lengths of each string
  60.     len2 = CStringLength(s2);
  61.     len  = (len1 < len2) ? len1 : len2;            // begin by only comparing common portions
  62.         
  63.     while(--len >= 0)                                    // compare common portions
  64.     {                                                        // if there is a difference return 1 or -1
  65.         chr1 = *s1++;                                    // get characters and move pointers
  66.         chr2 = *s2++;
  67.         
  68.         if (!caseSensitive)                            // uppercase if need be
  69.         {
  70.             chr1 = UpperChar(chr1);
  71.             chr2 = UpperChar(chr2);
  72.         }
  73.             
  74.         if (chr1 > chr2)
  75.             return 1;
  76.         else if (chr1 < chr2)
  77.             return -1;
  78.     }
  79.  
  80.     if (len1 == len2)                                    // common portions were identical, if lengths were
  81.         return 0;                                        // equal than strings are identical
  82.     else if (len1 < len2)                            // otherwise if string 1 is shorter, than return
  83.         return -1;                                        // -1 (it's less than string 2) otherwise string 2
  84.     else                                                    // is shorter and thus return (1).
  85.         return 1;
  86. }
  87.  
  88.  
  89. /*****************************************************************************
  90.  * 
  91.  * CStringConcat
  92.  * 
  93.  * Concatenates two C-style strings.
  94.  * 
  95.  * NOTE: It is assumed there is enough space at s1 to concat s2!
  96.  *
  97.  *****************************************************************************/
  98. void CStringConcat(char *s1, const char *s2)
  99. {
  100.     if ((!s1) || (!s2))                                // sanity check for nil pointers
  101.         return;
  102.         
  103.     while (*s1)                                            // move to the end of the first string
  104.         s1++;                                                // halt when we hit null char
  105.         
  106.     #pragma warn_possunwant off
  107.  
  108.     while (*s1++ = *s2++)                            // copy second string to first string
  109.         ;                                                    // halt when we hit null char
  110.  
  111.     #pragma warn_possunwant reset
  112. }
  113.  
  114.  
  115.  
  116. /*****************************************************************************
  117.  * 
  118.  * CStringEqual
  119.  * 
  120.  * Returns true if the two C-style strings are equal.
  121.  * 
  122.  *****************************************************************************/
  123. Boolean CStringEqual(const char *s1, const char *s2, Boolean caseSensitive)
  124. {
  125.     short        len;
  126.     char        chr1, chr2;    
  127.     
  128.     
  129.     if ((!s1) || (!s2))                                // sanity check for nil pointers
  130.         return false;
  131.  
  132.     len = CStringLength(s1);                        // get length of first string
  133.     
  134.     if (len != CStringLength(s2))                    // length of second string must equal first
  135.         return false;
  136.         
  137.     while (--len >= 0)                                // check that every character in each string
  138.     {
  139.         chr1 = *s1++;                                    // get characters and move pointers
  140.         chr2 = *s2++;
  141.         
  142.         if (!caseSensitive)                            // uppercase if need be
  143.         {
  144.             chr1 = UpperChar(chr1);
  145.             chr2 = UpperChar(chr2);
  146.         }
  147.             
  148.         if (chr2 != chr1)                                // match--stop at first one that doesn't
  149.             return false;
  150.     }
  151.  
  152.     return true;                                        // we have a match
  153. }
  154.  
  155.  
  156. /*****************************************************************************
  157.  * 
  158.  * CStringLength
  159.  * 
  160.  * Returns the length of a C-style string (null terminated)
  161.  * 
  162.  *****************************************************************************/
  163. long CStringLength(const char *s)
  164. {
  165.     long    len;
  166.  
  167.     if (!s)                                                // sanity check for nil pointer
  168.         return 0;
  169.         
  170.     len = 0;                                                // no characters yet
  171.     
  172.     while (*s++)                                        // while current character is not nil,
  173.         len++;                                            // increment pointer and increment length
  174.         
  175.     return len;                                            // return length
  176. }
  177.  
  178.  
  179. /*****************************************************************************
  180.  * 
  181.  * CToPString
  182.  * 
  183.  * Copies the specified C-style string to a Pascal-style string This
  184.  * function can convert the string in place: 
  185.  *
  186.  *        CToPString(s, (StringPtr) s);
  187.  * 
  188.  *****************************************************************************/
  189. void CToPString(const char *cs, StringPtr ps)
  190. {
  191.     short        len;
  192.     char        *t;
  193.  
  194.  
  195.     if ((!cs) || (!ps))                                                                        // sanity check for nil pointers
  196.         return;
  197.         
  198.     len = 0;
  199.     t     = (char *) cs;
  200.     
  201.     while (*t++)                                                                                // find length by searching
  202.         len++;                                                                                    // string for a null byte
  203.  
  204.     Assert(len <= 255, "STRING UTILS: String is too long to convert from C to Pascal without truncation.");
  205.     
  206.     if (len > 255)
  207.       len = 255;
  208.  
  209.     if ((void *) cs == (void *) ps)                                                        // are we copying back to the same buffer?
  210.     {                                                                                                // if so, just use BlockMoveData
  211.         BlockMoveData(cs, ps+1, len);
  212.         *ps = len;
  213.     }
  214.     else
  215.     {
  216.         
  217.         *ps++ = len;                                                                            // stuff in new length and step past it
  218.         
  219.         while (len-- >= 0)                                                                    // copy each character over
  220.             *ps++ = *cs++;
  221.     }
  222. }
  223.  
  224.  
  225.  
  226. /*****************************************************************************
  227.  * 
  228.  * PStringConcat
  229.  * 
  230.  * Concatenates two Pascal-style strings. If the concatenation would overflow
  231.  *    the maximum Pascal-style string (255 characters) it is halted at that point.
  232.  *
  233.  *****************************************************************************/
  234. void PStringConcat(StringPtr s1, StringPtr s2)
  235. {
  236.     short    len1, len2;
  237.  
  238.     if ((!s1) || (!s2))                                // sanity check for nil pointers
  239.         return;
  240.         
  241.     len1 = *s1;
  242.     len2 = *s2;
  243.  
  244.     if ((len1 + len2) > 255)                        // ensure we don't overflow!
  245.         len2 = (255 - len1);
  246.  
  247.     *s1 = len1 + len2;                                // stuff in new length
  248.  
  249.     *s1++;                                                // skip length bytes
  250.     *s2++;
  251.     
  252.     while (--len1 >= 0)                                // move to the end of the first string
  253.         s1++;
  254.         
  255.     while (--len2 >= 0)                                // copy second string to first string
  256.         *s1++ = *s2++;
  257. }
  258.  
  259.  
  260. /*****************************************************************************
  261.  * 
  262.  * PStringCopy
  263.  * 
  264.  * Copies the specified string to a duplicate string
  265.  * 
  266.  *****************************************************************************/
  267. void PStringCopy(StringPtr original, StringPtr duplicate)
  268. {
  269.     short    len;
  270.  
  271.  
  272.     if (!original)                                        // if original is nil
  273.         if (duplicate)                                    // and duplicate exists
  274.         {                                                    // set duplicate to a null string
  275.             *duplicate = (char) 0;
  276.             return;
  277.         }
  278.  
  279.     len = (short) *original;                        // how many bytes to copy?
  280.             
  281.     if (duplicate)                                        // ensure duplicate exists
  282.         while (len-- >= 0)                            // for every byte + 1 (include length byte)
  283.             *duplicate++ = *original++;            // copy original contents over to duplicate
  284. }
  285.  
  286. /*****************************************************************************
  287.  * 
  288.  * PToCString
  289.  * 
  290.  * Copies the specified Pascal-style string to a C-style string. This function
  291.  * can convert the string in place: 
  292.  *
  293.  *        PToString(string, (char *) string);
  294.  * 
  295.  *****************************************************************************/
  296. void PToCString(StringPtr ps, char *cs)
  297. {
  298.     short        len;
  299.  
  300.  
  301.     if ((!cs) || (!ps))                                // sanity check for nil pointers
  302.         return;
  303.         
  304.     len = (short) *ps++;                                // get length and skip length byte
  305.  
  306.     while (len--)                                        // while there is at least one more character...
  307.         *cs++ = *ps++;                                    // copy it and advance pointers
  308.     
  309.     *cs = (char) 0;                                    // stick in a null byte
  310. }
  311.  
  312. /*****************************************************************************
  313.  * 
  314.  * TEXT BLOCKS
  315.  * 
  316.  * Conversions between C- and Pascal-Style string to text, which is a contiguous
  317.  * series of characters with neither a prefix length nor a trailing null character.
  318.  * AppleEvents use this form of text to pass data around.
  319.  *      
  320.  *****************************************************************************/
  321. /*****************************************************************************
  322.  * 
  323.  * PStringToText
  324.  * 
  325.  * Converts a Pascal-style string into a handle to a block of text.
  326.  *
  327.  ****************************************************************************/
  328. void PStringToText(const StringPtr pString, Handle textBlock)
  329. {
  330.     long numBytes = (long)pString[0];
  331.     
  332.     if (GetHandleSize(textBlock) < numBytes)
  333.         ReallocateHandle(textBlock, numBytes);
  334.  
  335.     BlockMoveData(pString+1, *textBlock, numBytes);
  336. }
  337.  
  338.  
  339. /*****************************************************************************
  340.  *
  341.  *  CStringToText   
  342.  *
  343.  * Converts a C-style string into a handle to a block of text.
  344.  *
  345.  ****************************************************************************/
  346. void CStringToText(const char *cString, Handle textBlock)
  347. {
  348.     long  numBytes   = strlen(cString);
  349.     
  350.     if (GetHandleSize(textBlock) < numBytes)
  351.         ReallocateHandle(textBlock, numBytes);
  352.  
  353.     BlockMoveData(cString, *textBlock, numBytes);
  354. }
  355.  
  356.  
  357. /*****************************************************************************
  358.  *
  359.  * TextToPString
  360.  *
  361.  * Converts a handle to a block of text into a Pascal-style string.
  362.  *
  363.  ****************************************************************************/
  364. void TextToPString(const Handle textBlock, StringPtr pString)
  365. {
  366.     long numBytes = GetHandleSize(textBlock);
  367.  
  368.     if (numBytes > 255) 
  369.         numBytes = 255;
  370.         
  371.     pString[0] = (char)numBytes;
  372.     
  373.     BlockMoveData(*textBlock, pString+1, numBytes);
  374. }
  375.  
  376.  
  377. /*****************************************************************************
  378.  *
  379.  *    TextToCString
  380.  *
  381.  * Converts a handle to a block of text into a C-style string.
  382.  *
  383.  ****************************************************************************/
  384. void TextToCString(const Handle textBlock, char *cString, Size maxLen)
  385. {
  386.     long numBytes = GetHandleSize(textBlock);
  387.  
  388.     if (numBytes >= maxLen) 
  389.         numBytes = maxLen-1;
  390.         
  391.     BlockMoveData(*textBlock, cString, numBytes);
  392.     
  393.     cString[numBytes] = '\0';
  394. }
  395.  
  396.  
  397. /*****************************************************************************
  398.  * 
  399.  * OSTypeToCString
  400.  * 
  401.  * Converts a Macintosh OSType like 'cPar' to a c-style string like "cPar"
  402.  *
  403.  *****************************************************************************/
  404. void OSTypeToCString(OSType type, char *buffer)
  405. {
  406.  
  407.     short i = 0;
  408.     OSType tempType = type;
  409.     
  410.     for (i = 0; i <= 3; i++)
  411.     {
  412.         buffer[3-i] = (char)(tempType & 0x000000FF);
  413.         tempType = tempType >> 8;
  414.     }
  415.     
  416.     buffer[4] = '\0';
  417. }
  418.  
  419.  
  420. /*****************************************************************************
  421.  * 
  422.  * OSTypeToPString
  423.  * 
  424.  * Converts a Macintosh OSType like 'cPar' to a Pascal-style string like "\pcPar"
  425.  *
  426.  *****************************************************************************/
  427. void OSTypeToPString(OSType theType, char *buffer)
  428. {
  429.     buffer[0] = 0x04;
  430.     BlockMoveData(&theType, &buffer[1], 4);
  431. }
  432.  
  433.  
  434.  
  435.  
  436. /*****************************************************************************
  437.  * 
  438.  * VersionString
  439.  * 
  440.  * Extracts the version number string from the specified 'vers' resource and
  441.  * concats it onto the end of the specified string (Pascal-style). The short
  442.  * version number string is extracted.
  443.  * 
  444.  *****************************************************************************/
  445. OSErr VersionString(short rID, StringPtr version)
  446. {
  447.     VersRecHndl        versionH;
  448.     OSErr                error;
  449.  
  450.     error         = resNotFound;
  451.     versionH = (VersRecHndl) GetResource('vers', rID);        
  452.     
  453.     if (versionH)
  454.     {
  455.         HLock((Handle) versionH);
  456.         PStringConcat(version,(**versionH).shortVersion);
  457.         HUnlock((Handle) versionH);
  458.         ReleaseResource((Handle) versionH);
  459.         error = noErr;
  460.     }
  461.     else
  462.         PStringConcat(version,"\p<unknown>");
  463.  
  464.     return error;
  465. }
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.