home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / opendc12.zip / od124os2.exe / od12osr1.exe / src / EmbedHdr.cpp < prev    next >
C/C++ Source or Header  |  1997-03-21  |  17KB  |  565 lines

  1. /* @(#)Z 1.6 com/src/bento/EmbedHdr.cpp, odstorage, od96os2, odos29712d 97/03/21 17:19:18 (96/10/29 09:12:18) */
  2. //====START_GENERATED_PROLOG======================================
  3. //
  4. //
  5. //   COMPONENT_NAME: odstorage
  6. //
  7. //   CLASSES: none
  8. //
  9. //   ORIGINS: 82,27
  10. //
  11. //
  12. //   (C) COPYRIGHT International Business Machines Corp. 1995,1996
  13. //   All Rights Reserved
  14. //   Licensed Materials - Property of IBM
  15. //   US Government Users Restricted Rights - Use, duplication or
  16. //   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  17. //       
  18. //   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  19. //   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  20. //   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  21. //   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  22. //   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  23. //   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  24. //   OR PERFORMANCE OF THIS SOFTWARE.
  25. //
  26. //====END_GENERATED_PROLOG========================================
  27. //
  28.  
  29. /*
  30.     File:        EmbedHdr.cpp
  31.  
  32.     Contains:    Class definition for ODEmbeddedHandlers class.
  33.  
  34.     Owned by:    Vincent Lo
  35.  
  36.     Copyright:    ⌐ 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  37.  
  38.     Change History (most recent first):
  39.  
  40.          <8>    10/24/95    jpa        1293441: Bento memory reserve & fatal
  41.                                     container err.
  42.          <7>     5/26/95    VL        1251403: Multithreading naming support.
  43.          <6>     5/11/95    EL        1245113: fix bug of writing out garbage
  44.                                     with buffering.
  45.          <5>      4/7/95    EL        1213321: Use a different buffering scheme.
  46.          <4>    11/14/94    VL        1188257: Use Bento errors in BenotDef.h.
  47.          <3>     8/26/94    EL        #1182275 Allows writing embeded value in
  48.                                     large block to decrease fragmentation.
  49.                                     #1182308 Allows non-byte swapping
  50.                                     format/extract
  51.          <2>     6/18/94    MB        Correct memory includes
  52.          <1>     5/27/94    VL        first checked in
  53.  
  54.     To Do:
  55.         1) Move ContainerLabelFmt to some common location.
  56.         2) Use Exceptions instead of printf.
  57.         3) Share ODFlipMove among handlers.
  58.     In Progress:
  59.         
  60. */
  61.  
  62. #ifndef    _ODTYPES_
  63. #include "ODTypes.h"
  64. #endif
  65.  
  66. #ifndef _BENTOHDR_
  67. #include "BentoHdr.h"
  68. #endif
  69.  
  70. #ifndef _EMBEDHDR_
  71. #include "EmbedHdr.h"
  72. #endif
  73.  
  74. #ifndef _SESSHDR_
  75. #include "SessHdr.h"
  76. #endif
  77.  
  78. #ifndef _INDHDR_
  79. #include "IndHdr.h"
  80. #endif
  81.  
  82. #ifndef _EXCEPT_
  83. #include "Except.h"
  84. #endif
  85.  
  86. #ifndef _FLIPEND_
  87. #include "FlipEnd.h"
  88. #endif
  89.  
  90. #ifndef __CM_API__
  91. #include "CMAPI.h"
  92. #endif
  93.  
  94. #ifndef _ODMEMORY_
  95. #include "ODMemory.h"
  96. #endif
  97.  
  98. #ifndef _ERRORDEF_
  99. #include "ErrorDef.xh"
  100. #endif
  101.  
  102. #ifndef __STRING__
  103. #include "string.h"        // For strcpy and strcmp
  104. #endif
  105.  
  106. #ifndef _BENTODEF_
  107. #include "BentoDef.h"
  108. #endif
  109.  
  110. #ifndef _SESSHDR_
  111. #include "SessHdr.h"
  112. #endif
  113.  
  114. //==============================================================================
  115. // Scalar Types
  116. //==============================================================================
  117.  
  118. struct ContainerLabelFmt {            /* Layout of a container label:            */
  119.  ODUByte magicBytes[8];                /* 8 bytes: the magic byte identifier    */
  120.  ODUShort flags;                    /* 2    the label flag                    */
  121.  ODUShort bufSize;                    /* 2    TOC buffer size / 1024            */
  122.  ODUShort majorVersion;                /* 2    major format version number        */
  123.  ODUShort minorVersion;                /* 2    minor format version number        */
  124.  ODULong tocOffset;                    /* 4    offset to start of TOC            */
  125.  ODULong tocSize;                    /* 4    total byte size of the TOC        */
  126. };
  127. typedef struct ContainerLabelFmt ContainerLabelFmt;
  128.  
  129.  
  130. #pragma segment EmbedHdr
  131.  
  132. static void ODFlipMove(ODPtr from, ODPtr to, ODULong size)
  133. {
  134.     char    *dest = (char *)to + size - 1;
  135.     char    *src = (char *)from;
  136.     
  137.     while (size--)
  138.         *dest-- = *src++;            
  139. }
  140.  
  141. //==============================================================================
  142. // ODEmbeddedHandlers
  143. //==============================================================================
  144.  
  145. ODEmbeddedHandlers::ODEmbeddedHandlers(CMSession session, CMValue parentValue)
  146. {
  147.     fParentValue = parentValue;
  148.     fSession = session;
  149. }
  150.  
  151. ODEmbeddedHandlers::~ODEmbeddedHandlers()
  152. {
  153. }
  154.  
  155. void ODEmbeddedHandlers::Initialize()
  156. {
  157.     ODSByte    typeName[kBentoTypeNameSize];
  158.     
  159.     CMContainer    container   = CMGetValueContainer(fParentValue);
  160.     CMSession    sessionData = CMGetSession(container);
  161.     
  162.     if (sessionData != fSession)
  163.         THROW(kODErrBentoErr);
  164.  
  165.     ODSessionMustHaveCMAllocReserve(container);
  166.     
  167.     CMSetMetaHandler(fSession, kODEmbeddedContainerTypeName, (CMMetaHandler) containerMetahandler);
  168.     
  169.     CMGetContainerInfo(container, kODNULL, kODNULL, kODNULL, typeName, kODNULL);
  170.     
  171.     fReverseEndian = 0;                        /* assume same endian-ness            */
  172.     fPosition    = 0;                        /* container not "open" yet            */
  173.     fSize    = 0;                            /* don't know size yet                */
  174. #if kLargeEmbeddedBlock
  175.     fBufferBegin = 0;
  176.     fBuffer = kODNULL;
  177. #endif
  178.     strcpy(fTypeName, typeName);            /* copy in the container typeName    */
  179.  
  180.     ODSessionRestoreCMAllocReserve(container);
  181. }
  182.  
  183. CMSession ODEmbeddedHandlers::GetCMSession()
  184. {
  185.     return fSession;
  186. }
  187.  
  188. CMRefCon ODEmbeddedHandlers::OpenHandler(CMOpenMode mode)
  189. {
  190.     /* Get the size of the value.  For writing it better be 0 and for reading non-zero...    */
  191.     
  192.     fSize = (ODULong) CMGetValueSize(fParentValue);
  193. #if kLargeEmbeddedBlock
  194.     fBufferBegin = fSize;
  195.     fBuffer = (ODSByte *)ODNewPtr(kEmbeddedBlockSize);
  196. #endif    
  197.     /* Check the open mode and do appropriate checks on size. Set appropriate position...    */
  198.     
  199.     if (strcmp((ODSByte*) mode, "wb+") == 0) {                /* writing...    */
  200.         if (fSize != 0) {                                    /* size must be zero    */
  201.             CMError(fSession, "Cannot create embedded container (type \"^0\") for a value that already has data!", fTypeName);
  202.             return kODNULL;
  203.         }
  204.         fPosition = 0;                                    /* position to 1st free byte    */
  205.     } else if (strcmp((ODSByte*) mode, "rb") == 0) {         /* reading...                    */
  206.         if (fSize == 0) {                                    /* size must be non-zero        */
  207.             CMError(fSession, "Cannot read embedded container (type \"^0\") for a value that doesn't have data!", fTypeName);
  208.             return kODNULL;
  209.         }
  210.         fPosition = 0;                                    /* position to 1st byte to read            */
  211.     } else if (strcmp((char *)mode, "rb+") == 0)              /* converting or updating...            */
  212.         fPosition = fSize;                                /* size can be anything(position at end)*/
  213.     else {                                                                                /* bad mode...                                                    */
  214.         CMError(fSession, "Invalid embedded container (type \"^0\") open mode (\"^1\")!", fTypeName, (char *)mode);
  215.             return kODNULL;
  216.     }
  217.     
  218.     return ((CMRefCon) this);
  219. }
  220.  
  221. void ODEmbeddedHandlers::CloseHandler()
  222. {
  223. #if kLargeEmbeddedBlock
  224.     if (fBuffer != kODNULL) {
  225.         (void) this->FlushHandler();
  226.         ODDisposePtr(fBuffer);
  227.         fBuffer = kODNULL;
  228.     }
  229. #endif
  230. }
  231.  
  232. CMSize ODEmbeddedHandlers::FlushHandler()
  233. {
  234.     Environment* ev = somGetGlobalEnvironment();
  235. #if kLargeEmbeddedBlock
  236.     /* write out the data in the buffer */
  237.     if (fBufferBegin != fSize) {
  238.         CMWriteValueData(fParentValue, fBuffer, fBufferBegin, (CMSize) (fSize - fBufferBegin));
  239.         fBufferBegin = fSize;
  240.     }
  241. #endif
  242.     return ((CMSize) 0);
  243. }
  244.  
  245. CMSize ODEmbeddedHandlers::SeekHandler(CM_LONG posOff, CMSeekMode mode)
  246. {
  247.     if (mode == kCMSeekSet)
  248.         fPosition = (ODULong) posOff;
  249.     else if (mode == kCMSeekEnd)
  250.         fPosition = (ODSLong) fSize + posOff;
  251.     else
  252.         fPosition = (ODSLong) fPosition + posOff;
  253.             
  254.     return 0;
  255. }
  256.  
  257. CMSize ODEmbeddedHandlers::TellHandler()
  258. {    
  259.     return fPosition;
  260. }
  261.  
  262. CMSize ODEmbeddedHandlers::ReadHandler(CMPtr buffer, CMSize elementSize, CMCount theCount)
  263. {
  264.         Environment* ev = somGetGlobalEnvironment();
  265.     ODULong    tryToRead = (ODULong) elementSize * (ODULong) theCount;
  266.  
  267. #if kLargeEmbeddedBlock
  268.     ODULong    amountRead = 0;
  269.     
  270.     if (fPosition < fBufferBegin) {
  271.         /* at least some of it on disk */
  272.         if (tryToRead > (fBufferBegin - fPosition)) {
  273.             /* first read from disk, later read from buffer */
  274.             amountRead = (ODULong) CMReadValueData(fParentValue, buffer, fPosition, 
  275.                                                       (CMSize) (fBufferBegin - fPosition));
  276.             if (amountRead != (fBufferBegin - fPosition)) {
  277.                 /* trouble, don't continue */
  278.                 fPosition += amountRead;            /* update position by amount read                */
  279.                 
  280.                 tryToRead = 0;        
  281.             }
  282.             else {
  283.                 fPosition += amountRead;            /* update position by amount read                */
  284.                 tryToRead -= amountRead;
  285.                 buffer = (CMPtr)((char *)buffer + amountRead);
  286.             }
  287.         }
  288.         else { /* it should all be from disk */
  289.             amountRead = (ODULong) CMReadValueData(fParentValue, buffer, fPosition, 
  290.                                                       (CMSize) tryToRead);
  291.             fPosition += amountRead;            /* update position by amount read                */
  292.             
  293.             return ((CMSize) amountRead);        
  294.         }
  295.     }
  296.  
  297.     if ((tryToRead) && (fPosition >= fBufferBegin)) {                /* it may be in the buffer                */
  298.         if (tryToRead > (fSize - fPosition))
  299.             tryToRead = fSize - fPosition;
  300.         ODBlockMove(fBuffer+fPosition-fBufferBegin, buffer, tryToRead);
  301.         amountRead += tryToRead;
  302.         fPosition += tryToRead;
  303.     }
  304.     
  305.     return ((CMSize) amountRead);        
  306.     
  307. #else
  308.     tryToRead = (ODULong) CMReadValueData(fParentValue,     
  309.                                             buffer,
  310.                                             fPosition, 
  311.                                             (CMSize) tryToRead);
  312.     
  313.     fPosition += tryToRead;                        /* update position by amount read                */
  314.     
  315.     return ((CMSize) tryToRead);        
  316. #endif
  317. }
  318.  
  319. CMSize ODEmbeddedHandlers::WriteHandler(CMPtr buffer, CMSize elementSize, CMCount theCount)
  320. {
  321.     ODULong tryWriteAmount = (ODULong) elementSize * (ODULong) theCount;
  322. #if kLargeEmbeddedBlock
  323.     ODULong amountWritten = 0;
  324.     
  325.     /* if there is any data in the portion that is already on disk, write those out first */
  326.     if (fPosition < fBufferBegin) {
  327.         if ((fPosition + tryWriteAmount) > fBufferBegin) { /* it goes over to the buffer */
  328.             amountWritten = fBufferBegin - fPosition;
  329.             tryWriteAmount -= amountWritten;
  330.         }
  331.         else {
  332.             amountWritten = tryWriteAmount;
  333.             tryWriteAmount = 0;
  334.         }
  335.         CMWriteValueData(fParentValue, buffer, fPosition, amountWritten);
  336.         fPosition += amountWritten;
  337.         buffer = (CMPtr)((char *)buffer + amountWritten);
  338.     }
  339.     
  340.     /* if there is any that should go into the buffer or extend to the buffer, move them there */
  341.     
  342.     while (tryWriteAmount > 0) {
  343.         if ((fPosition + tryWriteAmount) <= (fBufferBegin + kEmbeddedBlockSize)) {
  344.             /* we can put everything into the buffer                                        */
  345.             ODBlockMove(buffer, fBuffer + fPosition - fBufferBegin, tryWriteAmount);
  346.             amountWritten += tryWriteAmount;
  347.             fPosition += tryWriteAmount;
  348.             if (fPosition > fSize)
  349.                 fSize = fPosition;
  350.             tryWriteAmount = 0;        /* so we are done */            
  351.         }
  352.         else {
  353.             /* we go beyond the end of the buffer, so we cannot put there directly */
  354.             if (fBufferBegin < fSize) {
  355.                 /* if there are data in the buffer, flush it first, maybe there is room afterwards */
  356.                 (void) this->FlushHandler();
  357.             }
  358.             else {
  359.                 /* there is no data in buffer, yet it does not fit, so just write it out directly */
  360.                 CMWriteValueData(fParentValue, buffer, fPosition, (CMSize) tryWriteAmount);
  361.                 amountWritten += tryWriteAmount;
  362.                 fPosition += tryWriteAmount;
  363.                 fSize = fPosition;
  364.                 fBufferBegin = fSize;
  365.                 tryWriteAmount = 0;        /* so we are done */            
  366.             }
  367.         }
  368.     }
  369.     return amountWritten;
  370. #else
  371.     CMWriteValueData(fParentValue, buffer, fPosition, (CMSize) tryWriteAmount);
  372.     fPosition += tryWriteAmount;                    /* update position by amount written    */
  373.  
  374.     if (fPosition > fSize)                        /* if writing past end of value...        */
  375.         fSize = fPosition;                        /* ...set new value size                */
  376.     
  377.     return tryWriteAmount;
  378. #endif
  379.     
  380. }
  381.  
  382. CMEofStatus ODEmbeddedHandlers::EOFHandler()
  383. {
  384.     return ((CMEofStatus) kODFalse);
  385. }
  386.  
  387. CMBoolean ODEmbeddedHandlers::TruncHandler(CMSize containerSize)
  388. {
  389.         ODBoolean trunchandler = kODFalse;
  390.     if ((ODULong)containerSize <= fSize) {
  391. #if kLargeEmbeddedBlock
  392.         /* only need actually to delete if end result is nothing in the buffer */
  393.         if ((ODULong)containerSize <= fBufferBegin) {
  394.             ODULong    amountToDelete;
  395.             if (fSize > fBufferBegin)
  396.                 amountToDelete = fBufferBegin - (ODULong) containerSize;        /* don't delete amount in buffer */
  397.             else
  398.                 amountToDelete = fSize - (ODULong) containerSize;            /* else delete from end */
  399.             CMDeleteValueData(fParentValue,  (CMCount) containerSize, (CMSize) amountToDelete);
  400.             fBufferBegin = (ODULong) containerSize;        /* so it would match fSize => empty buffer */
  401.         }
  402. #else
  403.     CMDeleteValueData(fParentValue,                                         
  404.                         (CMCount) containerSize,
  405.                         (CMSize) (fSize - (ODULong) containerSize));
  406. #endif
  407.         fSize    = (ODULong) containerSize;    
  408.     
  409.         trunchandler =  kODTrue;
  410.     }
  411.     else
  412.         trunchandler =  kODFalse;
  413.        return trunchandler;
  414. }
  415.  
  416. CMSize ODEmbeddedHandlers::ContainerSizeHandler()
  417. {
  418.     fPosition = fSize;                        /* moral equivalent of seek/tell    */
  419.     
  420.     return ((CMSize) fSize);
  421. }
  422.  
  423. void ODEmbeddedHandlers::ReadLabelHandler(CMMagicBytes magicByteSequence,
  424.                                      CMContainerFlags *flags, CM_USHORT *bufSize,
  425.                                      CM_USHORT *majorVersion, CM_USHORT *minorVersion,
  426.                                      CMSize *tocOffset, CMSize *tocSize)
  427. {
  428.     ODULong            labelSize;
  429.     ContainerLabelFmt    theLabel;
  430.  
  431.     /* Seek to the end of the label at the end of the value and read it...                                */
  432.     
  433.     this->SeekHandler(-(ODSLong)sizeof(ContainerLabelFmt), kCMSeekEnd);
  434.     labelSize = (ODULong) this->ReadHandler((CMPtr) &theLabel,
  435.                                                 (CMSize) sizeof(ODUByte),
  436.                                                 (CMCount) sizeof(ContainerLabelFmt));
  437.     
  438.     if (labelSize != sizeof(ContainerLabelFmt)) {        /* must have read it all!                            */
  439.         CMError(fSession, "Embedded container (type \"^0\") label could not be read!", fTypeName);
  440.         return;
  441.     }
  442.     
  443.     /* Return all the label info...                                                                                                                */
  444.     
  445.     ODBlockMove(theLabel.magicBytes, magicByteSequence, 8);
  446. #if kCMDefaultEndian
  447.     /* little endian machine */
  448.     if ((theLabel.flags & kCMLittleEndianTwin) == 0) {
  449. #else
  450.     /* big endian machine */
  451.     if (theLabel.flags & kCMLittleEndianTwin) {
  452. #endif
  453.         fReverseEndian = kODTrue;
  454.         *flags = ODFlipShort(theLabel.flags);
  455.         *bufSize = ODFlipShort(theLabel.bufSize);
  456.         *majorVersion = ODFlipShort(theLabel.majorVersion);
  457.         *minorVersion = ODFlipShort(theLabel.minorVersion);
  458.         *tocOffset = ODFlipLong(theLabel.tocOffset);
  459.         *tocSize = ODFlipLong(theLabel.tocSize);
  460.     }
  461.     else {
  462.         *flags = (CMContainerFlags)theLabel.flags;
  463.         *bufSize = (CM_USHORT)theLabel.bufSize;
  464.         *majorVersion = (CM_USHORT)theLabel.majorVersion;
  465.         *minorVersion = (CM_USHORT)theLabel.minorVersion;
  466.         *tocOffset = (CMSize)theLabel.tocOffset;
  467.         *tocSize = (CMSize)theLabel.tocSize;
  468.     }
  469. }
  470.  
  471. void ODEmbeddedHandlers::WriteLabelHandler(CMMagicBytes magicByteSequence,
  472.                                         CMContainerFlags flags, CM_USHORT bufSize,
  473.                                         CM_USHORT majorVersion, CM_USHORT minorVersion,
  474.                                         CMSize tocOffset, CMSize tocSize)
  475. {
  476.     ODULong            labelSize;
  477.     ContainerLabelFmt    theLabel;
  478.  
  479.     /* Fill in the label buffer with the info...                                                                                    */
  480.     
  481.     flags = (CMContainerFlags) ((CM_USHORT)flags & ~kCMLittleEndianTwin);    /* ignore what is passed in */
  482.     if (fReverseEndian) {
  483.         theLabel.flags = ODFlipShort(flags | (kCMLittleEndianTwin & ~kCMDefaultEndian));
  484.         theLabel.bufSize = ODFlipShort(bufSize);
  485.         theLabel.majorVersion = ODFlipShort(majorVersion); 
  486.         theLabel.minorVersion = ODFlipShort(minorVersion);
  487.         theLabel.tocOffset = ODFlipLong(tocOffset);
  488.         theLabel.tocSize = ODFlipLong(tocSize);
  489.     }
  490.     else {
  491.         theLabel.flags = (ODUShort)(flags | kCMDefaultEndian);
  492.         theLabel.bufSize = (ODUShort)bufSize;
  493.         theLabel.majorVersion = (ODUShort)majorVersion; 
  494.         theLabel.minorVersion = (ODUShort)minorVersion;
  495.         theLabel.tocOffset = (ODULong)tocOffset;
  496.         theLabel.tocSize = (ODULong)tocSize;
  497.     }
  498.     
  499.     ODBlockMove(magicByteSequence, theLabel.magicBytes, 8);
  500.  
  501.     /* Write the label to the end of the embedded container value...*/
  502.     
  503.     this->SeekHandler(0, kCMSeekEnd);
  504.     labelSize = (ODULong) this->WriteHandler((CMPtr) &theLabel,
  505.                                             (CMSize) sizeof(unsigned char),
  506.                                             (CMCount) sizeof(ContainerLabelFmt));
  507.  
  508.     if (labelSize != sizeof(ContainerLabelFmt))
  509.         THROW(kODErrBentoErr);
  510. }
  511.  
  512. CMValue ODEmbeddedHandlers::ReturnParentValueHandler()
  513. {
  514.     return fParentValue;
  515. }
  516.  
  517. CM_UCHAR* ODEmbeddedHandlers::ReturnContainerNameHandler()
  518. {
  519.     return ((CM_UCHAR *) fTypeName);
  520. }
  521.  
  522. CMType ODEmbeddedHandlers::ReturnTargetTypeHandler(CMContainer container)
  523. {
  524.     CMType indirectType;
  525.     
  526.     CMSetMetaHandler(fSession,
  527.                     kODIndirectValueGlobalName,
  528.                     IndirectDynamicValueMetahandler);
  529.     indirectType = CMRegisterType(container, kODIndirectValueGlobalName);
  530.                         
  531.     return indirectType;
  532. }
  533.  
  534. void ODEmbeddedHandlers::ExtractDataHandler(CMDataBuffer buffer,
  535.                                                  CMSize size, CMPrivateData data)
  536. {
  537.     ODBoolean    reverseEndian = fReverseEndian;
  538.     
  539.     if ((long)size < 0) {    /* this means it is endian-ness netural    */
  540.         size = -(long)size;
  541.         reverseEndian = kODFalse;
  542.     }
  543.     
  544.     if (reverseEndian)
  545.         ODFlipMove(buffer, data, (size_t)size);
  546.     else
  547.         ODBlockMove(buffer, data, (size_t)size);
  548. }
  549.  
  550. void ODEmbeddedHandlers::FormatDataHandler(CMDataBuffer buffer,
  551.                                      CMSize size, CMPrivateData data)
  552. {
  553.     ODBoolean    reverseEndian = fReverseEndian;
  554.     
  555.     if ((long)size < 0) {    /* this means it is endian-ness netural    */
  556.         size = -(long)size;
  557.         reverseEndian = kODFalse;
  558.     }
  559.     
  560.     if (reverseEndian)
  561.         ODFlipMove(data, buffer, (size_t)size);
  562.     else
  563.         ODBlockMove(data, buffer, (size_t)size);
  564. }
  565.