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 / Internet / SLCySink.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  7.7 KB  |  257 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                SLCySink.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #ifndef SOM_FW_OCyberSink_xih
  11. #define SOM_Module_slcysink_Source
  12. #include <SLCySink.xih>
  13. #endif
  14.  
  15. #ifndef FWCYSTRM_H
  16. #include "FWCyStrm.h"
  17. #endif
  18.  
  19. #ifndef FWSOMENV_H
  20. #include "FWSOMEnv.h"
  21. #endif
  22.  
  23. //
  24. // Cyberdog
  25. //
  26.  
  27. #ifndef SOM_CyberStream_xh
  28. #include <CyberStream.xh>
  29. #endif
  30.  
  31. //========================================================================================
  32. // SOM Utilities
  33. //========================================================================================
  34. #pragma mark SOM Utilities
  35.  
  36. /*
  37.     Since we have a SOM interface, we have to make sure we don't try to
  38.     throw any C++ exceptions out of here; we need to catch them and convert
  39.     them into SOM exceptions.
  40. */
  41.  
  42. static const char FW_kInvalidException[] = "Unknown Exception!"; 
  43.  
  44. #define FW_SOM_CALLBACK_TRY            \
  45.     FW_TRY                            \
  46.     {
  47.  
  48. #define FW_SOM_CALLBACK_ENDTRY        \
  49.     }                                \
  50.     FW_CATCH_BEGIN                    \
  51.     FW_CATCH_REFERENCE(FW_XException, exception)\
  52.     {                                \
  53.         FW_SetException(ev, exception);\
  54.     }                                \
  55.     FW_CATCH_EVERYTHING()            \
  56.     {                                \
  57.         FW_DEBUG_MESSAGE(FW_kInvalidException);\
  58.         FW_SetEvError(ev, kODErrUndefined);\
  59.     }                                \
  60.     FW_CATCH_END
  61.  
  62. #pragma mark -
  63.  
  64.  
  65. //-----------------------------------------------------------------------------
  66. // Utilities
  67. //-----------------------------------------------------------------------------
  68.  
  69. #define FW_YET_ANOTHER_MIN(X,Y)    (((X) < (Y)) ? (X) : (Y))
  70.  
  71. //-----------------------------------------------------------------------------
  72. //    FW_GetAvailableBytes
  73. //-----------------------------------------------------------------------------
  74.  
  75. static long FW_GetAvailableBytes (Environment *ev, 
  76.     CyberStream*& fStream, Ptr& fBuffer, Size& fRead, Size& fSize)
  77. {
  78.     // Return how much data is available for reading.
  79.     //
  80.     // The result will be: size of buffer, if one is available, or 0.
  81.     // The number returned may be smaller than the true value (because
  82.     // there may be multiple buffers available).
  83.     //
  84.     // You will generally only use this if you are reading unstructured data, 
  85.     // and just want the data that is sitting in the network buffer so you can
  86.     // read it and process it right away.
  87.     
  88.     // If we don't have a buffer, try to get a new one. We will release a buffer
  89.     // if it is empty.
  90.     
  91.     if (fBuffer && (fSize-fRead) == 0) {
  92.         fStream->ReleaseBuffer (ev, fBuffer);
  93.         fBuffer = kODNULL;
  94.     }
  95.     
  96. check_buffer:
  97.     if (!fBuffer) {
  98.         short status = fStream->GetStreamStatus (ev);
  99.         if (status & kCDDataAvailable) {
  100.             fStream->GetBuffer (ev, &fBuffer, &fSize);
  101.             fRead = 0;
  102.         }
  103.         
  104.         // If we still have no buffer (and the connection is Ok) try to go to sleep.
  105.         short done = status & (kCDErrorOccurred | kCDDownloadComplete | kCDAbortComplete);
  106.         if (!fBuffer && !done) {
  107. #ifdef FW_DEBUG
  108.             ThreadID current;
  109.             FW_FailOnError (::GetCurrentThread (¤t));
  110.             // (1) Performing lengthy network activity during the main thread is rude.
  111.             // (2) Yielding from the main thread probably won't work anyway, because you won't
  112.             // have a second thread to yield *to*.
  113.             FW_ASSERT (("You should not block the main (user interface) thread!", current != kApplicationThreadID));
  114. #endif
  115.             FW_FailOnError (::YieldToAnyThread());
  116.             goto check_buffer;
  117.         }
  118.     }
  119.     
  120.     return fBuffer ? (fSize-fRead) : 0;
  121. }
  122.  
  123. static void FW_Read (Environment *ev, void* destination, long bytes, 
  124.     CyberStream*& fStream, Ptr& fBuffer, Size& fRead, Size& fSize)
  125. {
  126.     // Reads data from a CyberStream, sleeping as necessary.
  127.     // This is a blocking synchronous call. If all the data requested is not 
  128.     // available, will sleep. If all the data can not be read, will throw an 
  129.     // exception. If you want to read *up to* X bytes, call 
  130.     // FW_GetAvailableBytes first, and call FW_Read (max (available, X)).
  131.     
  132.     char* buffer = (char*) destination;
  133.     
  134.     while (0 < bytes) {
  135.         long available = FW_GetAvailableBytes (ev, fStream, fBuffer, fRead, fSize);
  136.         long toRead = FW_YET_ANOTHER_MIN (available, bytes);
  137.         if (toRead == 0)
  138.             FW_Failure (FW_xReadableStream);
  139.         memcpy (buffer, fBuffer + fRead, toRead);
  140.         fRead += toRead;
  141.         bytes -= toRead;
  142.         buffer += toRead;
  143.     }
  144. }
  145.  
  146. #pragma mark -
  147. //-----------------------------------------------------------------------------
  148. // Class FW_OCyberSink (SOM)
  149. //-----------------------------------------------------------------------------
  150. #pragma mark Class FW_OCyberSink (SOM)
  151.  
  152. //-----------------------------------------------------------------------------
  153. // SLCySink::somUninit
  154. //-----------------------------------------------------------------------------
  155.  
  156. SOM_Scope void  SOMLINK SLCySink__somUninit(FW_OCyberSink *somSelf)
  157. {
  158.     FW_SOMEnvironment ev;
  159.     FW_OCyberSinkData *somThis = FW_OCyberSinkGetData(somSelf);
  160.     
  161.     if (somThis->fStream) {
  162.         // Release any empty buffer we may have.
  163.         if (somThis->fBuffer) {
  164.             somThis->fStream->ReleaseBuffer (ev, somThis->fBuffer);
  165.             somThis->fBuffer = kODNULL;
  166.         }
  167.         // Do we need to abort the stream before deleting it?
  168.         short status = somThis->fStream->GetStreamStatus(ev);
  169.         if (!(status & FW_kCyberStreamDone)) {
  170.             somThis->fStream->Abort (ev);
  171.             do {
  172.                 ::SystemTask();
  173.                 status = somThis->fStream->GetStreamStatus(ev);
  174.             }
  175.             while (!(status & FW_kCyberStreamDone));
  176.         }
  177.         delete somThis->fStream;
  178.     }
  179.     
  180.     FW_OCyberSink_parent_FW_OSink_somUninit(somSelf);
  181. }
  182.  
  183. //-----------------------------------------------------------------------------
  184. // SLCySink::GetReadableBytes
  185. //-----------------------------------------------------------------------------
  186.  
  187. SOM_Scope long  SOMLINK SLCySink__GetReadableBytes(FW_OCyberSink *somSelf, Environment *ev)
  188. {
  189.     long available = 0;
  190.     FW_OCyberSinkData* somThis = FW_OCyberSinkGetData(somSelf);
  191.     
  192.     FW_SOM_CALLBACK_TRY
  193.         available = FW_GetAvailableBytes (ev, somThis->fStream, somThis->fBuffer, somThis->fRead, somThis->fSize);
  194.     FW_SOM_CALLBACK_ENDTRY
  195.     
  196.     return available;
  197. }
  198.  
  199. //-----------------------------------------------------------------------------
  200. // SLCySink::Read
  201. //-----------------------------------------------------------------------------
  202.  
  203. SOM_Scope void  SOMLINK SLCySink__Read(FW_OCyberSink* somSelf, Environment* ev,
  204.         void* destination,
  205.         long count)
  206. {
  207.     FW_OCyberSinkData* somThis = FW_OCyberSinkGetData(somSelf);
  208.     
  209.     FW_SOM_CALLBACK_TRY
  210.         FW_Read (ev, destination, count, somThis->fStream, somThis->fBuffer, somThis->fRead, somThis->fSize);
  211.     FW_SOM_CALLBACK_ENDTRY
  212. }
  213.  
  214. //-----------------------------------------------------------------------------
  215. // SLCySink::GetWritableBytes
  216. //-----------------------------------------------------------------------------
  217.  
  218. SOM_Scope long  SOMLINK SLCySink__GetWritableBytes(FW_OCyberSink* somSelf, Environment* ev)
  219. {
  220.     FW_UNUSED (somSelf);
  221.     FW_UNUSED (ev);
  222.     
  223.     FW_ASSERT (("CyberStream sinks are read-only.", false));
  224.     return 0;
  225. }
  226.  
  227. //-----------------------------------------------------------------------------
  228. // SLCySink::Write
  229. //-----------------------------------------------------------------------------
  230.  
  231. SOM_Scope void  SOMLINK SLCySink__Write(FW_OCyberSink* somSelf, Environment* ev,
  232.         void* source,
  233.         long count)
  234. {
  235.     FW_UNUSED (somSelf);
  236.     FW_UNUSED (ev);
  237.     FW_UNUSED (source);
  238.     FW_UNUSED (count);
  239.     
  240.     FW_ASSERT (("CyberStream sinks are read-only.", false));
  241.     FW_Failure (FW_xWritableStream);
  242. }
  243.  
  244. //-----------------------------------------------------------------------------
  245. // SLCySink::InitFromStream
  246. //-----------------------------------------------------------------------------
  247.  
  248. SOM_Scope void  SOMLINK SLCySink__InitFromStream(FW_OCyberSink *somSelf, Environment *ev,
  249.         CyberStream* cs)
  250. {
  251.     FW_UNUSED (ev);
  252.     
  253.     FW_OCyberSinkData *somThis = FW_OCyberSinkGetData(somSelf);
  254.     somThis->fStream = cs;
  255. }
  256.  
  257.