home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / Papers / Rentzsch / Code / Align / Align.c next >
Encoding:
Text File  |  2001-06-23  |  9.1 KB  |  314 lines

  1. /****************************************************************************************
  2.     Align.c
  3.         <http://redshed.net/align>
  4.  
  5.         A buzzard took a monkey for a ride in the air
  6.             The monkey thought that everything was on the square.
  7.         The buzzard tried to throw the monkey off of his back
  8.             But the monkey grabbed his neck and said "Now listen, jack".
  9.     
  10.     Copyright © 1999-2001 Red Shed Software. All rights reserved.
  11.     by Jonathan 'Wolf' Rentzsch (jon@redshed.net)
  12.  
  13.         Redistribution and use in source and binary forms, with or without modification,
  14.         are permitted provided that the following conditions are met:
  15.  
  16.         1. Redistributions of source code must retain the above copyright notice, this
  17.         list of conditions and the following disclaimer.
  18.  
  19.         2. Redistributions in binary form must reproduce the above copyright notice, this
  20.         list of conditions and the following disclaimer in the documentation and/or other
  21.         materials provided with the distribution.
  22.  
  23.         3. The names and trademarks of copyright holders may not be used in advertising
  24.         or publicity pertaining to the software without specific prior permission.
  25.  
  26.         This software is provided "as is" and any expressed or implied warranties,
  27.         including, but not limited to, the implied warranties of merchantability and
  28.         fitness for a particular purpose are disclaimed.  In no event shall the authors
  29.         or copyright holders be liable for any direct, indirect, incidental, special,
  30.         exemplary, or consequential damages (including, but not limited to, procurement
  31.         of substitute goods or services; loss of use, data, or profits; or business
  32.         interruption) however caused and on any theory of liability, whether in contract,
  33.         strict liability, or tort (including negligence or otherwise) arising in any way
  34.         out of the use of this software, even if advised of the possibility of such
  35.         damage.
  36.     
  37.     Commenter    Date                Comment
  38.     ---------    -----------------    -----------------------------------------------------
  39.     wolf        Fri, Feb 12, 1999    Created.
  40.     wolf        Mon, Apr 12, 1999    Added AlignX().
  41.                                     Rewrote Aligned template. Now supports 2, 8 and 16
  42.                                     byte-aligned data as well as 4.
  43.     wolf        Tue, Apr 13, 1999    Rewrote NewAlignedPtr() to take alignment as a
  44.                                     literal variable instead of a flag. This makes it
  45.                                     more symmetrical.
  46.     wolf        Fri, May 7, 1999    The Aligned template worked well for C data
  47.                                     structures but contained a flaw for C++ constructed
  48.                                     objects. The Constructor would be called on the
  49.                                     non-aligned pointer and then the pointer would be
  50.                                     aligned (moved). The result would that the
  51.                                     Constructor operated on the wrong section of memory.
  52.                                     
  53.                                     I now align the pointer *and then* call "placement
  54.                                     new" to call the Constructor on the correct section.
  55.                                     
  56.                                     The old Aligned template is still included under the
  57.                                     name OldAligned.
  58.                                     
  59.                                     Broke out Aligned and OldAligned templates into
  60.                                     their own header file, Aligned.h.
  61.     wolf        Mon, Nov 1, 1999    Added AlignDirect_(), which is functionally
  62.                                     identical to Align_() (where _ is either 2, 4, 8 or
  63.                                     16) except it takes a pointer as its parameter and
  64.                                     returns a pointer. This is unlike Align_(), which
  65.                                     takes a pointer to a pointer and returns nothing.
  66.                                     AlignDirect_() makes it possible to declare a
  67.                                     variable with an initial value
  68.                                     ("int *x = (int*) AlignDirect_( &alignedX );").
  69.                                     Used by the new ALIGN macro. By the way,
  70.                                     AlignDirect_() calls Align_() to do its work.
  71.                                     
  72.                                     Added a new macro: ALIGN. It works much like the
  73.                                     Aligned template except it's a macro, so it works
  74.                                     under C as well as C++.
  75.     wolf        Sat, Jan 22, 2000    Rewrote AlignX() to be faster.
  76.     wolf        Sun, Jan 23, 2000    Added Pad typedef.
  77.     wolf        Sun, Jan 30, 2000    Carbonized.
  78.     wolf        Fri, Feb 18, 2000    Added IsAligned().
  79.     wolf        Mon, Dec 11, 2000    Align 1.0.
  80.     wolf        Thu, Feb 8, 2001    Align 1.0.2. CodeWarrior Pro 6 breaks an idiom:
  81.                                     implicit casting of <type>** to void**. I had to make
  82.                                     all such casts explicit.
  83.     
  84.     ************************************************************************************/
  85.  
  86. #include    "Align.h"
  87. #include    "require.h"
  88.  
  89.     void
  90. Align2(
  91.     void    **ptr )
  92. {
  93.     RequirePtr( ptr );
  94.     RequirePtr( *ptr );
  95.     (*(long*)ptr) &= 0xFFFFFFFE;    //    Strip lower bit.
  96.     (*(long*)ptr) += 2;                //    Move pointer up 2 bytes.
  97.     RequirePtrAlign( *ptr, 2 );
  98. }
  99.  
  100.     void*
  101. AlignDirect2(
  102.     void    *ptr )
  103. {
  104.     RequirePtr( ptr );
  105.     Align2( &ptr );
  106.     RequirePtrAlign( ptr, 2 );
  107.     return( ptr );
  108. }
  109.  
  110.     void
  111. Align4(
  112.     void    **ptr )
  113. {
  114.     RequirePtr( ptr );
  115.     RequirePtr( *ptr );
  116.     (*(long*)ptr) &= 0xFFFFFFFC;    //    Strip lower 2 bits.
  117.     (*(long*)ptr) += 4;                //    Move pointer up 4 bytes.
  118.     RequirePtrAlign( *ptr, 4 );
  119. }
  120.  
  121.     void*
  122. AlignDirect4(
  123.     void    *ptr )
  124. {
  125.     RequirePtr( ptr );
  126.     Align4( &ptr );
  127.     RequirePtrAlign( ptr, 4 );
  128.     return( ptr );
  129. }
  130.  
  131.     void
  132. Align8(
  133.     void    **ptr )
  134. {
  135.     RequirePtr( ptr );
  136.     RequirePtr( *ptr );
  137.     (*(long*)ptr) &= 0xFFFFFFF8;    //    Strip lower 3 bits.
  138.     (*(long*)ptr) += 8;                //    Move pointer up 8 bytes.
  139.     RequirePtrAlign( *ptr, 8 );
  140. }
  141.  
  142.     void*
  143. AlignDirect8(
  144.     void    *ptr )
  145. {
  146.     RequirePtr( ptr );
  147.     Align8( &ptr );
  148.     RequirePtrAlign( ptr, 8 );
  149.     return( ptr );
  150. }
  151.  
  152.     void
  153. Align16(
  154.     void    **ptr )
  155. {
  156.     RequirePtr( ptr );
  157.     RequirePtr( *ptr );
  158.     (*(long*)ptr) &= 0xFFFFFFF0;    //    Strip lower 4 bits.
  159.     (*(long*)ptr) += 16;            //    Move pointer up 16 bytes.
  160.     RequirePtrAlign( *ptr, 16 );
  161. }
  162.  
  163.     void*
  164. AlignDirect16(
  165.     void    *ptr )
  166. {
  167.     RequirePtr( ptr );
  168.     Align16( &ptr );
  169.     RequirePtrAlign( ptr, 16 );
  170.     return( ptr );
  171. }
  172.  
  173.     void
  174. AlignX(
  175.     void    **ptr,
  176.     UInt32    alignment )
  177. {
  178.     long    ptrValue;
  179.     
  180.     RequirePtr( ptr );
  181.     RequirePtr( *ptr );
  182.     Require( alignment == 2 || alignment == 4 || alignment == 8 || alignment == 16 );
  183.     
  184.     ptrValue = (long) *ptr;
  185.     ptrValue &= ~(alignment - 1);
  186.     ptrValue += alignment;
  187.     
  188.     RequirePtrAlign( (void*) ptrValue, alignment );
  189.     *ptr = (void*) ptrValue;
  190. }
  191.  
  192.     void*
  193. AlignXDirect(
  194.     void    *ptr,
  195.     UInt32    alignment )
  196. {
  197.     long    ptrValue;
  198.     
  199.     RequirePtr( ptr );
  200.     Require( alignment == 2 || alignment == 4 || alignment == 8 || alignment == 16 );
  201.     
  202.     ptrValue = (long) ptr;
  203.     ptrValue &= ~(alignment - 1);
  204.     ptrValue += alignment;
  205.     
  206.     RequirePtrAlign( (void*) ptrValue, alignment );
  207.     return( (void*) ptrValue );
  208. }
  209.  
  210. /****************************************************************************************
  211.     Commenter    Date                Comment
  212.     ---------    -----------------    -----------------------------------------------------
  213.     wolf        Tue, Apr 13, 1999    Created.
  214.     wolf        Fri, May 7, 1999    Added three more requirements and added another
  215.                                     variable and renamed an existing variable. This was
  216.                                     done to make the code easier to read.
  217.     wolf        Sun, Jan 30, 2000    Carbonized. The fromSystemHeap must always be set to
  218.                                     false when compiling for Carbon (it's still okay
  219.                                     for Classic apps).
  220.     wolf        Fri, Mar 3, 2000    Now returns a nil pointer upon allocation failure.
  221.     
  222.     ************************************************************************************/
  223.  
  224.     OSErr
  225. NewAlignedPtr(
  226.     UInt32    size,
  227.     Boolean    fromSystemHeap,
  228.     Boolean    clearMemory,
  229.     UInt8    alignment,
  230.     void    **ptr )
  231. {
  232.     Ptr        macPtr, alignedPtr;
  233.     long    *unalignedPtr;
  234.     OSErr    err = noErr;
  235.     
  236.     RequireSInt32( size );
  237.     Require( alignment == 4 || alignment == 8 || alignment == 16 );
  238.     RequirePtr( ptr );
  239.     
  240.     //    A failure should result in a nil pointer.
  241.     *ptr = nil;
  242.     
  243.     //    Bump up the size request to factor in the padding.
  244.     size += alignment;
  245.     
  246.     //    Allocate the Ptr as requested.
  247. #if    TARGET_API_MAC_CARBON
  248.     Require( fromSystemHeap == false );
  249.     if( clearMemory )
  250.         macPtr = NewPtrClear( size );
  251.     else
  252.         macPtr = NewPtr( size );
  253. #else
  254.     if( fromSystemHeap ) {
  255.         macPtr = clearMemory ? NewPtrSysClear( (SInt32) size ) : NewPtrSys( (SInt32) size );
  256.     } else {
  257.         macPtr = clearMemory ? NewPtrClear( (SInt32) size ) : NewPtr( (SInt32) size );
  258.     }
  259. #endif
  260.     err = MemError();
  261.     //    There's a slight possiblity that NewPtr[Sys|Clear|SysClear] will fail,
  262.     //    setting macPtr to nil *and* MemError() returning noErr. Here we make sure
  263.     //    that a failed Ptr allocation gets an appropriate error code.
  264.     if( !macPtr && !err )
  265.         err = memFullErr;
  266.     
  267.     //    Stash the original pointer into the pad zone.
  268.     if( !err ) {
  269.         RequireMacPtr( macPtr );
  270.         
  271.         alignedPtr = macPtr;
  272.         AlignX( (void**) &alignedPtr, alignment );
  273.         unalignedPtr = (long*) alignedPtr;
  274.         --unalignedPtr;
  275.         *unalignedPtr = (long) macPtr;
  276.         *ptr = alignedPtr;
  277.         
  278.         RequireMacPtr( GetUnalignedPtr( *ptr ) );
  279.         Require( GetUnalignedPtr( *ptr ) == macPtr );
  280.     }
  281.     
  282.     return( err );
  283. }
  284.  
  285. /****************************************************************************************
  286.     Commenter    Date                Comment
  287.     ---------    -----------------    -----------------------------------------------------
  288.     wolf        Wed, Feb 17, 1999    Created.
  289.     
  290.     ************************************************************************************/
  291.  
  292.     Ptr
  293. GetUnalignedPtr(
  294.     void    *ptr )
  295. {
  296.     long    *p = (long*) ptr;
  297.     --p;
  298.     return( (Ptr) *p );
  299. }
  300.  
  301. /****************************************************************************************
  302.     Commenter    Date                Comment
  303.     ---------    -----------------    -----------------------------------------------------
  304.     wolf        Fri, Feb 18, 2000    Created.
  305.     
  306.     ************************************************************************************/
  307.  
  308.     Boolean
  309. IsAligned(
  310.     void    *ptr,
  311.     UInt8    alignment )
  312. {
  313.     return( ((long) ptr) % alignment == 0 );
  314. }