home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / Level 1 Extensions 29Sep94 / DataMunging.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  11.2 KB  |  426 lines  |  [TEXT/KAHL]

  1. /* DataMunging.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    System Dependency Library for Building Portable Software               */
  5. /*    Macintosh Version                                                      */
  6. /*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
  7. /*                                                                           */
  8. /*    This file is Public Domain; it may be used for any purpose whatsoever  */
  9. /*    without restriction.                                                   */
  10. /*                                                                           */
  11. /*    This package is distributed in the hope that it will be useful,        */
  12. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  13. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
  14. /*                                                                           */
  15. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  16. /*                                                                           */
  17. /*****************************************************************************/
  18.  
  19. #include "MiscInfo.h"
  20. #include "Debug.h"
  21. #include "Audit.h"
  22. #include "Definitions.h"
  23.  
  24. #include "DataMunging.h"
  25. #include "Memory.h"
  26.  
  27.  
  28. /* Make a copy of the supplied Ptr.  If there is not enough memory to copy */
  29. /* the Ptr, NIL is returned. */
  30. char*                    CopyPtr(char* ThePtr)
  31.     {
  32.         char*                Dup;
  33.         long                Size;
  34.  
  35.         Size = PtrSize(ThePtr);
  36.         Dup = AllocPtrCanFail(Size,"CopyPtr");
  37.         if (Dup != NIL)
  38.             {
  39.                 CopyData(ThePtr,Dup,Size);
  40.             }
  41.         return Dup;
  42.     }
  43.  
  44.  
  45. /* return the length of a null-terminated string */
  46. long                    StrLen(char* String)
  47.     {
  48.         long                Scan;
  49.  
  50.         Scan = 0;
  51.         while (String[Scan] != 0)
  52.             {
  53.                 Scan += 1;
  54.             }
  55.         return Scan;
  56.     }
  57.  
  58.  
  59. /* make a new copy of the Ptr containing a null-terminated string.  The */
  60. /* returned Ptr will NOT contain a null at the end.  Returns NIL if the */
  61. /* routine failed */
  62. char*                    StringToBlockCopy(char* String)
  63.     {
  64.         long                Index;
  65.         char*                Block;
  66.  
  67.         Index = StrLen(String);
  68.         Block = AllocPtrCanFail(Index,"StringToBlockCopy");
  69.         if (Block != NIL)
  70.             {
  71.                 CopyData(String,Block,Index);
  72.             }
  73.         return Block;
  74.     }
  75.  
  76.  
  77. /* Make a copy of the specified block Ptr, appending a null to the end */
  78. /* to make it into a null-terminated string.  Returns NIL if it failed */
  79. char*                    BlockToStringCopy(char* Block)
  80.     {
  81.         long                    Index;
  82.         char*                    String;
  83.  
  84.         Index = PtrSize(Block);
  85.         String = AllocPtrCanFail(Index + 1,"BlockToStringCopy");
  86.         if (String != NIL)
  87.             {
  88.                 CopyData(Block,String,Index);
  89.                 String[Index] = 0;
  90.             }
  91.         return String;
  92.     }
  93.  
  94.  
  95. /* allocate a block and copy the raw data to it.  Returns NIL if it failed. */
  96. char*                    BlockFromRaw(char* Data, long Length)
  97.     {
  98.         char*                Stuff;
  99.  
  100.         Stuff = AllocPtrCanFail(Length,"BlockFromRaw");
  101.         if (Stuff != NIL)
  102.             {
  103.                 CopyData(Data,Stuff,Length);
  104.             }
  105.         return Stuff;
  106.     }
  107.  
  108.  
  109. /* allocate a block and copy the null-terminated string (including the null) */
  110. /* to it.  Returns NIL if the routine failed. */
  111. char*                    StringFromRaw(char* Data)
  112.     {
  113.         char*                Stuff;
  114.         long                Length;
  115.  
  116.         Length = StrLen(Data);
  117.         Stuff = AllocPtrCanFail(Length + 1,"StringFromRaw");
  118.         if (Stuff != NIL)
  119.             {
  120.                 CopyData(Data,Stuff,Length);
  121.                 Stuff[Length] = 0;
  122.             }
  123.         return Stuff;
  124.     }
  125.  
  126.  
  127. /* allocate a copy of the specified Ptr, appending the character at the end */
  128. /* returns NIL if the routine failed */
  129. char*                    AppendCharToBlockCopy(char* ThePtr, char TheChar)
  130.     {
  131.         long                Index;
  132.         char*                Copy;
  133.  
  134.         Index = PtrSize(ThePtr);
  135.         Copy = AllocPtrCanFail(Index + 1,"AppendCharToBlockCopy");
  136.         if (Copy != NIL)
  137.             {
  138.                 CopyData(ThePtr,Copy,Index);
  139.                 Copy[Index] = TheChar;
  140.             }
  141.         return Copy;
  142.     }
  143.  
  144.  
  145. /* compare memory ranges and return True if they are equal or False if not. */
  146. MyBoolean            MemEqu(char* Left, char* Right, long NumBytes)
  147.     {
  148.         ERROR(NumBytes < 0,PRERR(ForceAbort,"MemEqu:  Comparison of negative bytes"));
  149.         while (NumBytes > 0)
  150.             {
  151.                 if (Left[0] != Right[0])
  152.                     {
  153.                         return False; /* not equal */
  154.                     }
  155.                 Left += 1;
  156.                 Right += 1;
  157.                 NumBytes -= 1;
  158.             }
  159.         return True; /* no differences found, must be the same */
  160.     }
  161.  
  162.  
  163. /* compare memory ranges, but treat uppercase and lowercase letters as equal */
  164. MyBoolean            MemEquNoCase(char* First, char* Second, long NumBytes)
  165.     {
  166.         ERROR(NumBytes < 0,PRERR(ForceAbort,"MemEquNoCase:  negative number of bytes"));
  167.         while (NumBytes > 0)
  168.             {
  169.                 char                F,S;
  170.  
  171.                 F = First[0];
  172.                 S = Second[0];
  173.                 if ((F >= 'A') && (F <= 'Z'))
  174.                     {
  175.                         F = F - 'A' + 'a';
  176.                     }
  177.                 if ((S >= 'A') && (S <= 'Z'))
  178.                     {
  179.                         S = S - 'A' + 'a';
  180.                     }
  181.                 if (F != S)
  182.                     {
  183.                         return False; /* not equal */
  184.                     }
  185.                 First += 1;
  186.                 Second += 1;
  187.                 NumBytes -= 1;
  188.             }
  189.         return True; /* no differences found, must be the same */
  190.     }
  191.  
  192.  
  193. /* return true if the null terminated strings are equal, or false if not */
  194. MyBoolean            StrEqu(char* Left, char* Right)
  195.     {
  196.      LoopPoint:
  197.         if (*Left == 0)
  198.             {
  199.                 return (*Right == 0);
  200.             }
  201.         if (*Right == 0)
  202.             {
  203.                 return False;
  204.             }
  205.         if (*Left != *Right)
  206.             {
  207.                 return False;
  208.             }
  209.         Left += 1;
  210.         Right += 1;
  211.         goto LoopPoint;
  212.     }
  213.  
  214.  
  215. /* insert the specified block of raw data into the Ptr and return the new copy */
  216. /* returns NIL if the routine failed */
  217. char*                    InsertBlockIntoBlockCopy(char* Block, char* NewData,
  218.                                 long Where, long Length)
  219.     {
  220.         long                BlockLen;
  221.         char*                Copy;
  222.  
  223.         BlockLen = PtrSize(Block);
  224.         Copy = AllocPtrCanFail(BlockLen + Length,"InsertBlockIntoBlockCopy");
  225.         if (Copy != NIL)
  226.             {
  227.                 /* copy first part (before insertion) of data over */
  228.                 PRNGCHK(Block,&(Block[0]),Where);
  229.                 PRNGCHK(Copy,&(Copy[0]),Where);
  230.                 CopyData(&(Block[0]),&(Copy[0]),Where);
  231.                 /* copy new data over */
  232.                 PRNGCHK(Copy,&(Copy[Where]),Length);
  233.                 CopyData(NewData,&(Copy[Where]),Length);
  234.                 /* copy rest (after insertion) of data over */
  235.                 PRNGCHK(Block,&(Block[Where]),BlockLen - Where);
  236.                 PRNGCHK(Copy,&(Copy[Where + Length]),BlockLen - Where);
  237.                 CopyData(&(Block[Where]),&(Copy[Where + Length]),BlockLen - Where);
  238.             }
  239.         return Copy;
  240.     }
  241.  
  242.  
  243. /* remove the specified area from the Ptr and return the copy or NIL if it failed */
  244. char*                    RemoveBlockFromBlockCopy(char* Block, long Where, long Length)
  245.     {
  246.         long                BlockLen;
  247.         char*                Copy;
  248.  
  249.         BlockLen = PtrSize(Block);
  250.         ERROR((Where < 0) || (Where > PtrSize(Block)) || (Length < 0)
  251.             || (Length + Where > PtrSize(Block)),PRERR(ForceAbort,
  252.             "RemoveBlockFromBlockCopy:  Block specifier out of range"));
  253.         Copy = AllocPtrCanFail(BlockLen - Length,"RemoveBlockFromBlockCopy");
  254.         if (Copy != NIL)
  255.             {
  256.                 PRNGCHK(Copy,&(Copy[0]),Where);
  257.                 CopyData(&(Block[0]),&(Copy[0]),Where);
  258.                 PRNGCHK(Copy,&(Copy[Where]),BlockLen - Where - Length);
  259.                 CopyData(&(Block[Where + Length]),&(Copy[Where]),
  260.                     BlockLen - Where - Length);
  261.             }
  262.         return Copy;
  263.     }
  264.  
  265.  
  266. /* identical to InsertBlockIntoBlockCopy but allows element size to be specified */
  267. char*                    InsertEntryIntoArrayCopy(char* Array, char* NewEntry,
  268.                                 long Where, long ElementSize)
  269.     {
  270.         ERROR((PtrSize(Array) % ElementSize) != 0,
  271.             PRERR(ForceAbort,"InsertEntryIntoArray:  array contains an incomplete object"));
  272.         return InsertBlockIntoBlockCopy(Array,NewEntry,Where * ElementSize,ElementSize);
  273.     }
  274.  
  275.  
  276. /* Identical to RemoveBlockFromBlockCopy but allows element size to be specified */
  277. char*                    RemoveEntryFromArrayCopy(char* Array, long EntryIndex, long ElementSize)
  278.     {
  279.         ERROR((PtrSize(Array) % ElementSize) != 0,
  280.             PRERR(ForceAbort,"RemoveEntryFromArray:  array contains an incomplete object"));
  281.         return RemoveBlockFromBlockCopy(Array,EntryIndex * ElementSize,ElementSize);
  282.     }
  283.  
  284.  
  285. /* search for the first occurrence of Key in Block and replace the data with */
  286. /* Replacement, returning a copy of the data or NIL if it failed */
  287. char*                    ReplaceBlockCopy(char* Block, char* Key, char* Replacement)
  288.     {
  289.         long                    Scan;
  290.         long                    KeySize;
  291.         long                    BlockSize;
  292.         long                    ReplacementSize;
  293.  
  294.         KeySize = PtrSize(Key);
  295.         BlockSize = PtrSize(Block);
  296.         for (Scan = 0; Scan <= BlockSize - KeySize; Scan += 1)
  297.             {
  298.                 if (MemEqu(&(Block[Scan]),Key,KeySize))
  299.                     {
  300.                         char*                    Temp;
  301.  
  302.                         /* here we found a replacement */
  303.                         ReplacementSize = PtrSize(Replacement);
  304.                         Temp = AllocPtrCanFail(BlockSize - KeySize
  305.                             + ReplacementSize,"ReplaceBlock");
  306.                         if (Temp != NIL)
  307.                             {
  308.                                 /* copying over preceding characters */
  309.                                 PRNGCHK(Temp,&(Temp[0]),Scan);
  310.                                 CopyData(&(Block[0]),&(Temp[0]),Scan);
  311.                                 /* copying over replacement */
  312.                                 PRNGCHK(Temp,&(Temp[Scan]),ReplacementSize);
  313.                                 CopyData(Replacement,&(Temp[Scan]),ReplacementSize);
  314.                                 /* copying over remainder */
  315.                                 PRNGCHK(Temp,&(Temp[Scan + ReplacementSize]),
  316.                                     BlockSize - KeySize - Scan);
  317.                                 CopyData(&(Block[Scan + KeySize]),
  318.                                     &(Temp[Scan + ReplacementSize]),
  319.                                     BlockSize - KeySize - Scan);
  320.                             }
  321.                         return Temp;
  322.                     }
  323.             }
  324.         /* we return a new copy if we could replace.  Since we always have to return */
  325.         /* a copy, we make a copy here */
  326.         return CopyPtr(Block);
  327.     }
  328.  
  329.  
  330. /* concatenate two blocks, returning the new block or NIL if it failed */
  331. char*                    ConcatBlockCopy(char* Left, char* Right)
  332.     {
  333.         long                TotalSize;
  334.         char*                Accumulator;
  335.         long                LeftSize;
  336.         long                RightSize;
  337.  
  338.         LeftSize = PtrSize(Left);
  339.         RightSize = PtrSize(Right);
  340.         TotalSize = LeftSize + RightSize;
  341.         Accumulator = AllocPtrCanFail(TotalSize,"ConcatBlock");
  342.         if (Accumulator != NIL)
  343.             {
  344.                 PRNGCHK(Accumulator,Accumulator,LeftSize);
  345.                 CopyData(Left,Accumulator,LeftSize);
  346.                 PRNGCHK(Accumulator,&(Accumulator[LeftSize]),RightSize);
  347.                 CopyData(Right,&(Accumulator[LeftSize]),RightSize);
  348.             }
  349.         return Accumulator;
  350.     }
  351.  
  352.  
  353. /* return a middle section of the block or NIL if it failed */
  354. char*                    MidBlockCopy(char* Block, long Start, long NumChars)
  355.     {
  356.         long                TotalLength;
  357.         char*                New;
  358.  
  359.         if (Start < 0)
  360.             {
  361.                 NumChars = NumChars - (-Start);
  362.                 Start = 0;
  363.             }
  364.         if (NumChars < 0)
  365.             {
  366.                 NumChars = 0;
  367.             }
  368.         TotalLength = PtrSize(Block);
  369.         if (Start >= TotalLength)
  370.             {
  371.                 /* degenerate result */
  372.                 NumChars = 0;
  373.             }
  374.          else
  375.             {
  376.                 if (TotalLength - Start < NumChars)
  377.                     {
  378.                         NumChars = TotalLength - Start;
  379.                     }
  380.             }
  381.         New = AllocPtrCanFail(NumChars,"MidBlock");
  382.         if (New != NIL)
  383.             {
  384.                 PRNGCHK(New,New,NumChars);
  385.                 CopyData(&(Block[Start]),New,NumChars);
  386.             }
  387.         return New;
  388.     }
  389.  
  390.  
  391. /* return a block from which a section has been stripped, or NIL if it failed. */
  392. char*                    ReduceBlockCopy(char* Block, long Start, long NumChars)
  393.     {
  394.         long                TotalLength;
  395.         char*                Result;
  396.  
  397.         if (Start < 0)
  398.             {
  399.                 NumChars = NumChars - (-Start);
  400.                 Start = 0;
  401.             }
  402.         if (NumChars < 0)
  403.             {
  404.                 NumChars = 0;
  405.             }
  406.         TotalLength = PtrSize(Block);
  407.         if (Start >= TotalLength)
  408.             {
  409.                 return Block;
  410.             }
  411.         if (TotalLength - Start < NumChars)
  412.             {
  413.                 NumChars = TotalLength - Start;
  414.             }
  415.         Result = AllocPtrCanFail(TotalLength - NumChars,"ReduceBlock");
  416.         if (Result != NIL)
  417.             {
  418.                 PRNGCHK(Result,Result,Start);
  419.                 CopyData(Block,Result,Start); /* perform leading copy */
  420.                 PRNGCHK(Result,&(Result[Start]),TotalLength - NumChars - Start);
  421.                 CopyData(&(Block[Start + NumChars]),&(Result[Start]),
  422.                     TotalLength - NumChars - Start);
  423.             }
  424.         return Result;
  425.     }
  426.