home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Found / FWStream / SLBufSin.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  22.1 KB  |  669 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                SLBufSin.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFound.hpp"
  11.  
  12. #include <Limits.h>
  13.  
  14. #ifndef FWEXCDEF_H
  15. #include "FWExcDef.h"
  16. #endif
  17.  
  18. #ifndef FWPRIDEB_H
  19. #include "FWPriDeb.h"
  20. #endif
  21.  
  22. #ifndef SLSTRMRW_H
  23. #include "SLStrmRW.h"
  24. #endif
  25.  
  26. #ifdef FW_BUILD_MAC
  27. #pragma segment FWStream
  28. #endif
  29.  
  30.  
  31. /*
  32.  *  This file was generated by the SOM Compiler.
  33.  *  Generated using: 
  34.  *      SOM Emitter emitxtm.dll: 2.33
  35.  */
  36.  
  37. #define VARIABLE_MACROS
  38. #define FW_OBufferedSink_Class_Source
  39. #include "SLBufSin.xih"
  40.  
  41. // [KVV] Work around a Visual C++ 4.0 bug.  FW_Minimum is a C++ template function
  42. //    and can't be used inside of SOMLINK (extern "C") functions.
  43.  
  44. inline long FW_Minimum(long a, long b)
  45.     { return a < b ? a : b; }
  46.  
  47. //========================================================================================
  48. //    class FW_CPrivSinkBuffer
  49. //
  50. //  This class implements a buffer for use with FW_OSinks, especially FW_CStorageUnitSinks.  
  51. //    Each call to FW_CStorageUnitSink::Read() results in the creation and destruction of an
  52. //    intermediate FW_CByteArray.  To eliminate some of the expense associated with that 
  53. //    operation, ReadPeek() and WritePeek() methods of FW_CStorageUnitSink use this class 
  54. //    to allow the buffering of data being read and/or written to/from a storage unit.
  55. //
  56. //    Note that none of the methods of this class actually do any reading or writing.
  57. //    The FW_OSink instance must obtain a pointer to the buffer in memory and fill it 
  58. //    with data.  This class is responsible only for maintaining the buffer and data 
  59. //    pertaining directly to it.
  60. //
  61. //    The "initialPosition" is the offset within the storage unit of the start of the
  62. //    buffer.  To write the bufffer, seek to GetInitialPosition() and write from GetAddress() 
  63. //    for GetBytesWritten() bytes.  To read, get the current position and pass it as the 
  64. //    'initialPosition' argument to Initialize().  When items are read using ReadPeek() 
  65. //    and ReadPeekAdvance(), do a su->GetPosition() and pass that as the first argument 
  66. //    to ReakPeek().  
  67. //
  68. //    Physically, the class *is* an FW_OBufferedSinkData.  Consequently, we can safely cast 
  69. //    from an FW_OBufferedSinkData* to an FW_CPrivSinkBuffer*.
  70. //
  71. //========================================================================================
  72.  
  73. class FW_CPrivSinkBuffer : public FW_OBufferedSinkData
  74. {
  75. public:
  76.     enum EBufferKind {
  77.         kInvalid,
  78.         kReadPeek,
  79.         kWritePeek
  80.     };
  81.  
  82.     enum {
  83.         kInvalidPosition = 0xDEADBABE
  84.     };
  85.  
  86.     // ----- Constructors, destructor, operators -----
  87.  
  88.     void Construct(FW_ORandomAccessSink* aSink, long fCapacity);
  89.     void Destruct();
  90.     
  91.     // ----- Getters & setters -----
  92.  
  93.     char*        GetAddress() const;
  94.     long        GetCapacity() const;
  95.     long        GetInitialPosition() const;
  96.     long        GetBytesWritten() const;
  97.     FW_Boolean     IsDirty() const;
  98.     FW_Boolean     IsValid() const;
  99.     
  100.     // ----- Buffer-management routines -----
  101.  
  102.     void         Initialize(EBufferKind kind, long initialPosition, long validBytes);
  103.         // Initializes the type and validity of the buffer.
  104.  
  105.     void        Invalidate();
  106.         // Marks the buffer as containing invalid data.  The buffer must
  107.         //   be re-initialized before the next ReadPeek or WritePeek.
  108.  
  109.     void*        ReadPeek(Environment* ev, long& availableReadBytes);
  110.         // Returns a pointer to the data in the buffer starting at currentPosition.
  111.         //   availableReadBytes returns the number of valid bytes in the buffer
  112.         //   returned.
  113.                    
  114.     void        ReadPeekAdvance(Environment* ev, long bytesRead);
  115.         // Advances the ReadPeek buffer to indicate that the user has read the
  116.         //   number of bytes specified by bytesRead.  
  117.         // This routine should be called after the user uses the data from the buffer.
  118.         //   Otherwise, the same bytes will be returned by the next ReadPeek.
  119.                          
  120.     void*        WritePeek(Environment* ev, long& availableWriteBytes);
  121.         // Returns a pointer to the buffer starting at currentPosition.  The
  122.         //   number of bytes available for writing is returned in availableWriteBytes.
  123.                     
  124.     void        WritePeekAdvance(Environment* ev, long bytesWritten);
  125.         // Advances the WritePeek buffer to indicate that the user has written the
  126.         //   number of bytes specified by bytesWritten starting at currentPosition.
  127.         // This routine should be alled after the user writes the data.  Otherwise,
  128.         //   the data could be overwritten by future writes.
  129.  
  130.     void        FlushAndInvalidate(Environment* ev);
  131.         // If the buffer is "dirty", it needs to be written to disk. 
  132.  
  133. private:
  134.  
  135.     FW_CPrivSinkBuffer(){}
  136.     ~FW_CPrivSinkBuffer(){}
  137.  
  138.     FW_CPrivSinkBuffer(const FW_CPrivSinkBuffer& otherBuffer);
  139.     FW_CPrivSinkBuffer& operator=(const FW_CPrivSinkBuffer&);
  140. };
  141.  
  142. //----------------------------------------------------------------------------------------
  143. //    FW_CPrivSinkBuffer::GetAddress
  144. //----------------------------------------------------------------------------------------
  145.  
  146. inline char* FW_CPrivSinkBuffer::GetAddress() const
  147. {
  148.     return fBuffer;
  149. }
  150.  
  151. //----------------------------------------------------------------------------------------
  152. //    FW_CPrivSinkBuffer::GetCapacity
  153. //----------------------------------------------------------------------------------------
  154.  
  155. inline long FW_CPrivSinkBuffer::GetCapacity() const
  156. {
  157.     return fCapacity;
  158. }
  159.  
  160. //----------------------------------------------------------------------------------------
  161. //    FW_CPrivSinkBuffer::GetBytesWritten
  162. //----------------------------------------------------------------------------------------
  163.  
  164. inline long FW_CPrivSinkBuffer::GetBytesWritten() const
  165. {
  166.     return fBytesWritten;
  167. }
  168.  
  169. //----------------------------------------------------------------------------------------
  170. //    FW_CPrivSinkBuffer::GetInitialPosition
  171. //----------------------------------------------------------------------------------------
  172.  
  173. inline long FW_CPrivSinkBuffer::GetInitialPosition() const
  174. {
  175.     return fInitialPosition;
  176. }
  177.  
  178. //----------------------------------------------------------------------------------------
  179. //    FW_CPrivSinkBuffer::IsDirty
  180. //----------------------------------------------------------------------------------------
  181.  
  182. inline FW_Boolean FW_CPrivSinkBuffer::IsDirty() const
  183. {
  184.     return fType == kWritePeek && GetBytesWritten() != 0;
  185. }
  186.  
  187. //----------------------------------------------------------------------------------------
  188. //    FW_CPrivSinkBuffer::IsValid
  189. //----------------------------------------------------------------------------------------
  190.  
  191. inline FW_Boolean FW_CPrivSinkBuffer::IsValid() const
  192. {
  193.     return fType != kInvalid && fInitialPosition != kInvalidPosition;
  194. }
  195.  
  196. //----------------------------------------------------------------------------------------
  197. //    FW_CPrivSinkBuffer::Invalidate
  198. //----------------------------------------------------------------------------------------
  199.  
  200. inline void FW_CPrivSinkBuffer::Invalidate()
  201. {
  202.     Initialize(kInvalid, kInvalidPosition, 0);
  203. }
  204.  
  205. //----------------------------------------------------------------------------------------
  206. //    FW_CPrivSinkBuffer::Construct
  207. //
  208. //    This constructor just initializes some fields--no memory is actually allocated
  209. //    for the buffer until Initialize() is called.
  210. //----------------------------------------------------------------------------------------
  211.  
  212. void FW_CPrivSinkBuffer::Construct(FW_ORandomAccessSink* aSink, long capacity)
  213. {
  214.     fWrappedSink        = aSink;
  215.     fBuffer                = new char[capacity];
  216.     fCapacity            = capacity;
  217.     fValidBytes            = 0;
  218.     fInitialPosition    = kInvalidPosition;
  219.     fBytesWritten        = 0;
  220.     fType                = kInvalid;
  221. }
  222.  
  223. //----------------------------------------------------------------------------------------
  224. //    FW_CPrivSinkBuffer::Destruct
  225. //----------------------------------------------------------------------------------------
  226.  
  227. void FW_CPrivSinkBuffer::Destruct()
  228. {
  229.     delete [] fBuffer;
  230.     fBuffer = 0;
  231. }
  232.  
  233. //----------------------------------------------------------------------------------------
  234. //    FW_CPrivSinkBuffer::Initialize
  235. //----------------------------------------------------------------------------------------
  236.  
  237. void FW_CPrivSinkBuffer::Initialize(EBufferKind kind, long initialPosition, long validBytes)
  238. {
  239.     fValidBytes         = validBytes;
  240.     fInitialPosition = initialPosition;
  241.     fBytesWritten     = 0;
  242.     fType             = kind;
  243. }
  244.  
  245. //----------------------------------------------------------------------------------------
  246. //    FW_CPrivSinkBuffer::ReadPeek
  247. //----------------------------------------------------------------------------------------
  248.  
  249. void* FW_CPrivSinkBuffer::ReadPeek(Environment* ev, long& availableReadBytes)
  250. {
  251.     long currentPosition = fWrappedSink->GetPosition(ev);
  252.     void* source = 0;
  253.     availableReadBytes = 0;
  254.  
  255.     if (fType == kReadPeek && currentPosition >= fInitialPosition)
  256.     {
  257.         const long offsetInBuffer = currentPosition - fInitialPosition;
  258.  
  259.         if (offsetInBuffer < fValidBytes)
  260.         {
  261.             source = GetAddress() + offsetInBuffer;
  262.             availableReadBytes = fValidBytes - offsetInBuffer;
  263.         }
  264.     }
  265.  
  266.     // If there is no buffered data available, load the buffer.
  267.     if (availableReadBytes == 0)
  268.     {
  269.         // Write out any dirty data, mark the buffer invalid.  Stay at this seek position
  270.         if (IsDirty)
  271.         {
  272.             FlushAndInvalidate(ev);
  273.             fWrappedSink->SetPosition(ev, currentPosition);
  274.         }
  275.         else
  276.             Invalidate();
  277.  
  278.         // Determine the amount of data which will fit into the buffer and read it.  Seek
  279.         //    back to the point where the read began.  The buffer is still invalid: if an 
  280.         //    exception occurs, it remains invalid.  Only when the read&seek complete is the 
  281.         //    buffer marked as valid
  282.         availableReadBytes = FW_Minimum(fWrappedSink->GetReadableBytes(ev), GetCapacity());
  283.         fWrappedSink->Read(ev, GetAddress(), availableReadBytes);
  284.         fWrappedSink->SetPosition(ev, currentPosition);
  285.  
  286.         // Mark the buffer as containing valid data, peek into the buffer
  287.         Initialize(kReadPeek, currentPosition, availableReadBytes);
  288.         source = GetAddress();
  289.     }
  290.  
  291.     return source;
  292. }
  293.  
  294. //----------------------------------------------------------------------------------------
  295. //    FW_CPrivSinkBuffer::ReadPeekAdvance
  296. //----------------------------------------------------------------------------------------
  297.  
  298. void FW_CPrivSinkBuffer::ReadPeekAdvance(Environment* ev, long bytesRead)
  299. {
  300.     long currentPosition = fWrappedSink->GetPosition(ev);
  301.  
  302.     fWrappedSink->SetPosition(ev, currentPosition + bytesRead);
  303.  
  304. #ifdef FW_DEBUG
  305.     FW_ASSERT(fType == kReadPeek);
  306.     FW_ASSERT(fInitialPosition <= currentPosition);
  307.     FW_ASSERT(bytesRead >= 0);
  308.     FW_ASSERT((currentPosition - fInitialPosition + bytesRead) <= fValidBytes);
  309. #endif
  310. }
  311.  
  312. //----------------------------------------------------------------------------------------
  313. //    FW_CPrivSinkBuffer::WritePeek
  314. //----------------------------------------------------------------------------------------
  315.  
  316. void* FW_CPrivSinkBuffer::WritePeek(Environment* ev, long& availableWriteBytes)
  317. {
  318.     long currentPosition = fWrappedSink->GetPosition(ev);
  319.     void* destination = 0;
  320.     availableWriteBytes = 0;
  321.  
  322.     // If no seeking has occurred, then the buffer is valid
  323.     if (fType == kWritePeek && currentPosition == fInitialPosition)
  324.     {
  325.         destination = GetAddress() + GetBytesWritten();
  326.         availableWriteBytes = fValidBytes - GetBytesWritten();
  327.     }
  328.  
  329.     // If buffer is invalid (for whatever reason), write the buffer and prepare for more.
  330.     if (availableWriteBytes == 0)
  331.     {
  332.         FW_Boolean repositionCursor = false;
  333.  
  334.         // Assure fWrappedSink->GetPosition(ev) == currentPosition after the
  335.         // call to FlushAndInvalidate()
  336.         if (IsDirty())
  337.         {
  338.             repositionCursor = (currentPosition != fInitialPosition);
  339.             if (!repositionCursor)
  340.                 currentPosition = GetInitialPosition() + GetBytesWritten();
  341.         }
  342.  
  343.         // Write out any dirty data, mark the buffer invalid.
  344.         FlushAndInvalidate(ev);
  345.  
  346.         // If the cursor is not where we want it, reposition it
  347.         if (repositionCursor)
  348.             fWrappedSink->SetPosition(ev, currentPosition);
  349.  
  350.         // The invariant.
  351.         FW_ASSERT(fWrappedSink->GetPosition(ev) == currentPosition);
  352.  
  353.         // Set the writable size for the buffer, peek into the buffer
  354.         availableWriteBytes = FW_Minimum(fWrappedSink->GetWritableBytes(ev), GetCapacity());
  355.         Initialize(kWritePeek, currentPosition, availableWriteBytes);
  356.         destination = GetAddress();
  357.     }
  358.  
  359.     return destination;
  360. }
  361.  
  362. //----------------------------------------------------------------------------------------
  363. //    FW_CPrivSinkBuffer::WritePeekAdvance
  364. //----------------------------------------------------------------------------------------
  365.  
  366. void FW_CPrivSinkBuffer::WritePeekAdvance(Environment* ev, long bytesWritten)
  367. {
  368. #ifndef FW_DEBUG
  369.     FW_UNUSED(ev);
  370. #else
  371.     long currentPosition = fWrappedSink->GetPosition(ev);
  372.     FW_ASSERT(fType == kWritePeek);
  373. //    FW_ASSERT(GetBytesWritten() == (currentPosition - fInitialPosition));
  374.     FW_ASSERT(bytesWritten >= 0);
  375.     FW_ASSERT((GetBytesWritten() + bytesWritten) <= fValidBytes);
  376. #endif
  377.  
  378.     fBytesWritten += bytesWritten;
  379. }
  380.  
  381.  
  382. //----------------------------------------------------------------------------------------
  383. // FW_CPrivSinkBuffer::FlushAndInvalidate
  384. //----------------------------------------------------------------------------------------
  385. void FW_CPrivSinkBuffer::FlushAndInvalidate(Environment *ev)
  386. {
  387.     // If the buffer is dirty, write its contents
  388.     if (IsDirty())
  389.     {
  390.         fWrappedSink->SetPosition(ev, GetInitialPosition());
  391.         fWrappedSink->Write(ev, GetAddress(), GetBytesWritten());
  392.     }
  393.  
  394.     // Invalidate the buffer
  395.     Invalidate();
  396. }
  397.  
  398.  
  399. //----------------------------------------------------------------------------------------
  400. // FW_OBufferedSink__InitFromSink
  401. //----------------------------------------------------------------------------------------
  402.  
  403. SOM_Scope void  SOMLINK FW_OBufferedSink__InitFromSink(FW_OBufferedSink *somSelf, Environment *ev,
  404.         FW_ORandomAccessSink* aSink,
  405.         long bufferCapacity)
  406. {
  407.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  408.  
  409.     FW_SOM_TRY
  410.     {
  411.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  412.         aSinkBuffer->Construct(aSink, bufferCapacity);
  413.     }
  414.     FW_SOM_CATCH
  415. }
  416.  
  417. //----------------------------------------------------------------------------------------
  418. // FW_OBufferedSink__GetORandomAccessSink
  419. //----------------------------------------------------------------------------------------
  420.  
  421. SOM_Scope FW_ORandomAccessSink*  SOMLINK FW_OBufferedSink__GetORandomAccessSink(FW_OBufferedSink *somSelf, Environment *ev)
  422. {
  423. FW_UNUSED(ev);
  424.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  425.     return _fWrappedSink;
  426. }
  427.  
  428. //----------------------------------------------------------------------------------------
  429. // FW_OBufferedSink__Flush
  430. //----------------------------------------------------------------------------------------
  431.  
  432. SOM_Scope void  SOMLINK FW_OBufferedSink__Flush(FW_OBufferedSink *somSelf, Environment *ev)
  433. {
  434.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  435.  
  436.     FW_SOM_TRY
  437.     {
  438.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  439.         aSinkBuffer->FlushAndInvalidate(ev);
  440.     }
  441.     FW_SOM_CATCH
  442. }
  443.  
  444. //----------------------------------------------------------------------------------------
  445. // FW_OBufferedSink__GetReadableBytes
  446. //----------------------------------------------------------------------------------------
  447.  
  448. SOM_Scope long  SOMLINK FW_OBufferedSink__GetReadableBytes(FW_OBufferedSink *somSelf, Environment *ev)
  449. {
  450.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  451.  
  452.     FW_SOM_TRY
  453.     {
  454.         return _fWrappedSink->GetReadableBytes(ev);
  455.     }
  456.     FW_SOM_CATCH
  457.     return 0;
  458. }
  459.  
  460. //----------------------------------------------------------------------------------------
  461. // FW_OBufferedSink__Read
  462. //----------------------------------------------------------------------------------------
  463.  
  464. SOM_Scope void  SOMLINK FW_OBufferedSink__Read(FW_OBufferedSink *somSelf, Environment *ev,
  465.         void* destination,
  466.         long count)
  467. {
  468.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  469.  
  470.     FW_SOM_TRY
  471.     {
  472.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  473.         long availableReadBytes;
  474.         const char* currentSource = (char*)aSinkBuffer->ReadPeek(ev, availableReadBytes);
  475.         long bytesToReadThisTime = FW_Minimum(count, availableReadBytes);
  476.  
  477.         // [jkp] 960215 Optimizing large data transfers
  478.         //    Possible future optimization is to check if "availableReadBytes" is 
  479.         //    greater than "bytesToReadThisTime + _fCapacity".  In that case, we 
  480.         //    can read what's in the buffer, invalidate the buffer, read the remainder 
  481.         //    directly from the sink.  This avoids double-copying of the data: once 
  482.         //    from the sink to the buffer, then from the buffer to the destination.
  483.         //
  484.         //    This hasn't been done because streams are used for many transfers of small 
  485.         //    data: buffering wins.  Also, the developer can grab the underlying sink and 
  486.         //    transfer directly.  The buffered sink "catches up" when the seek pointer has 
  487.         //    moved.
  488.         while (bytesToReadThisTime != 0)
  489.         {
  490.             FW_PrimitiveCopyMemory(currentSource, destination, bytesToReadThisTime);
  491.             aSinkBuffer->ReadPeekAdvance(ev, bytesToReadThisTime);
  492.             destination = (char*)destination + bytesToReadThisTime;
  493.             count -= bytesToReadThisTime;
  494.             if (count == 0)
  495.                 break;
  496.             currentSource = (const char*)aSinkBuffer->ReadPeek(ev, availableReadBytes);
  497.             bytesToReadThisTime = FW_Minimum(count, availableReadBytes);
  498.         }
  499.  
  500.         if (count != 0)
  501.             FW_Failure(FW_xReadableStream);
  502.     }
  503.     FW_SOM_CATCH
  504. }
  505.  
  506. //----------------------------------------------------------------------------------------
  507. // FW_OBufferedSink__GetWritableBytes
  508. //----------------------------------------------------------------------------------------
  509.  
  510. SOM_Scope long  SOMLINK FW_OBufferedSink__GetWritableBytes(FW_OBufferedSink *somSelf, Environment *ev)
  511. {
  512.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  513.  
  514.     FW_SOM_TRY
  515.     {
  516.         return _fWrappedSink->GetWritableBytes(ev);
  517.     }
  518.     FW_SOM_CATCH
  519.     return 0;
  520. }
  521.  
  522. //----------------------------------------------------------------------------------------
  523. // FW_OBufferedSink__Write
  524. //----------------------------------------------------------------------------------------
  525.  
  526. SOM_Scope void  SOMLINK FW_OBufferedSink__Write(FW_OBufferedSink *somSelf, Environment *ev,
  527.         void* source,
  528.         long count)
  529. {
  530.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  531.  
  532.     FW_SOM_TRY
  533.     {
  534.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  535.         long availableWriteBytes;
  536.         char* currentDestination = (char*)aSinkBuffer->WritePeek(ev, availableWriteBytes);
  537.         long bytesToWriteThisTime = FW_Minimum(count, availableWriteBytes);
  538.  
  539.         while (bytesToWriteThisTime != 0)
  540.         {
  541.             FW_PrimitiveCopyMemory(source, currentDestination, bytesToWriteThisTime);
  542.             aSinkBuffer->WritePeekAdvance(ev, bytesToWriteThisTime);
  543.             source = (char*)source + bytesToWriteThisTime;
  544.             count -= bytesToWriteThisTime;
  545.             if (count == 0)
  546.                 break;
  547.             currentDestination = (char*)aSinkBuffer->WritePeek(ev, availableWriteBytes);
  548.             bytesToWriteThisTime = FW_Minimum(count, availableWriteBytes);
  549.         }
  550.  
  551.         if (count != 0)
  552.             FW_Failure(FW_xWritableStream);
  553.     }
  554.     FW_SOM_CATCH
  555. }
  556.  
  557. //----------------------------------------------------------------------------------------
  558. // FW_OBufferedSink__GetLength
  559. //----------------------------------------------------------------------------------------
  560.  
  561. SOM_Scope long  SOMLINK FW_OBufferedSink__GetLength(FW_OBufferedSink *somSelf, Environment *ev)
  562. {
  563.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  564.  
  565.     FW_SOM_TRY
  566.     {
  567.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  568.  
  569.         if (aSinkBuffer->IsDirty())
  570.             aSinkBuffer->FlushAndInvalidate(ev);
  571.         return _fWrappedSink->GetLength(ev);
  572.     }
  573.     FW_SOM_CATCH
  574.     return 0;
  575. }
  576.  
  577. //----------------------------------------------------------------------------------------
  578. // FW_OBufferedSink__SetLength
  579. //----------------------------------------------------------------------------------------
  580.  
  581. SOM_Scope void  SOMLINK FW_OBufferedSink__SetLength(FW_OBufferedSink *somSelf, Environment *ev,
  582.         long length)
  583. {
  584.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  585.  
  586.     FW_SOM_TRY
  587.     {
  588.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  589.  
  590.         aSinkBuffer->FlushAndInvalidate(ev);
  591.         _fWrappedSink->SetLength(ev, length);
  592.     }
  593.     FW_SOM_CATCH
  594. }
  595.  
  596. //----------------------------------------------------------------------------------------
  597. // FW_OBufferedSink__GetPosition
  598. //----------------------------------------------------------------------------------------
  599.  
  600. SOM_Scope long  SOMLINK FW_OBufferedSink__GetPosition(FW_OBufferedSink *somSelf, Environment *ev)
  601. {
  602.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  603.  
  604.     FW_SOM_TRY
  605.     {
  606.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  607.  
  608.         if (aSinkBuffer->IsDirty())
  609.             aSinkBuffer->FlushAndInvalidate(ev);
  610.         return _fWrappedSink->GetPosition(ev);
  611.     }
  612.     FW_SOM_CATCH
  613.     return 0;
  614. }
  615.  
  616. //----------------------------------------------------------------------------------------
  617. // FW_OBufferedSink__SetPosition
  618. //----------------------------------------------------------------------------------------
  619.  
  620. SOM_Scope void  SOMLINK FW_OBufferedSink__SetPosition(FW_OBufferedSink *somSelf, Environment *ev,
  621.         long position)
  622. {
  623.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  624.  
  625.     FW_SOM_TRY
  626.     {
  627.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  628.  
  629.         if (aSinkBuffer->IsDirty())
  630.             aSinkBuffer->FlushAndInvalidate(ev);
  631.         _fWrappedSink->SetPosition(ev, position);
  632.     }
  633.     FW_SOM_CATCH
  634. }
  635.  
  636. //----------------------------------------------------------------------------------------
  637. // FW_OBufferedSink__somInit
  638. //----------------------------------------------------------------------------------------
  639.  
  640. SOM_Scope void  SOMLINK FW_OBufferedSink__somInit(FW_OBufferedSink *somSelf)
  641. {
  642. FW_UNUSED(somSelf);
  643. //    FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  644.  
  645. //    FW_OBufferedSink_parent_FW_ORandomAccessSink_somInit(somSelf);
  646. }
  647.  
  648. //----------------------------------------------------------------------------------------
  649. // FW_OBufferedSink__somUninit
  650. //----------------------------------------------------------------------------------------
  651.  
  652. SOM_Scope void  SOMLINK FW_OBufferedSink__somUninit(FW_OBufferedSink *somSelf)
  653. {
  654.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  655.  
  656.     FW_SOM_UNINIT_TRY
  657.     {
  658.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  659.         FW_SOMEnvironment ev;
  660.  
  661.         // Flush out any data which hasn't been written, then reclaim memory.
  662.         aSinkBuffer->FlushAndInvalidate(ev);
  663.         aSinkBuffer->Destruct();
  664.  
  665. //        FW_OBufferedSink_parent_FW_ORandomAccessSink_somInit(somSelf);
  666.     }
  667.     FW_SOM_UNINIT_CATCH
  668. }
  669.