home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Languages / python / PyObjC-0.47-MIHS / pyobjc-0.47-src / Modules / ObjCStreams.m < prev    next >
Encoding:
Text File  |  1996-11-13  |  20.8 KB  |  943 lines

  1. /* Copyright (c) 1996 by Lele Gaifax.  All Rights Reserved
  2.  *
  3.  * This software may be used and distributed freely for any purpose
  4.  * provided that this notice is included unchanged on any and all
  5.  * copies. The author does not warrant or guarantee this software in
  6.  * any way.
  7.  *
  8.  * This file is part of the PyObjC package.
  9.  *
  10.  * $RCSfile: ObjCStreams.m,v $
  11.  * $Revision: 1.1.1.3 $
  12.  * $Date: 1996/11/14 01:50:25 $
  13.  *
  14.  * Created Mon Oct  7 12:55:20 1996.
  15.  * 
  16.  */
  17.  
  18. #include "ObjC.h"
  19. #include "OC_Stream.h"
  20.  
  21. #ifndef WITH_FOUNDATION
  22.  
  23. /*********************************/
  24. /*** ObjCStream implementation ***/
  25. /*********************************/
  26.  
  27. static const char *
  28. stream_decode_error (NXHandler *handler)
  29. {
  30.   char *errorString = NULL;
  31.     
  32.   switch (handler->code)
  33.     {
  34.     case NX_illegalWrite:
  35.       errorString = "Illegal Write on Stream.";
  36.       break;
  37.  
  38.     case NX_illegalRead:
  39.       errorString = "Illegal Read on Stream.";
  40.       break;
  41.  
  42.     case NX_illegalSeek:
  43.       errorString = "Illegal Seek on Stream.";
  44.       break;
  45.  
  46.     case NX_illegalStream:
  47.       errorString = "Illegal Stream.";
  48.       break;
  49.       
  50.     case NX_streamVMError:
  51.       errorString = "Stream VM Error.";
  52.       break;
  53.  
  54.     case OC_closedStreamError:
  55.       errorString = "Inappropriate operation on closed stream.";
  56.       break;
  57.       
  58.     case OC_nonSeekableStreamError:
  59.       errorString = "Stream's position cannot change.";
  60.       break;
  61.  
  62.     case OC_nonWriteableStreamError:
  63.       errorString = "Non writable stream.";
  64.       break;
  65.  
  66.     case OC_nonReadableStreamError:
  67.       errorString = "Non readable stream.";
  68.       break;
  69.       
  70.     default:
  71.       {
  72. #define ERRMSG "Unknown error code: %d"
  73.     static char errmsg[sizeof ERRMSG + 6];
  74.     
  75.     sprintf(errmsg, ERRMSG, handler->code);
  76.     errorString = errmsg;
  77. #undef ERRMSG
  78.     break;
  79.       }
  80.     }
  81.  
  82.   return errorString;
  83. }
  84.  
  85. #define STREAM_DURING NX_DURING
  86.  
  87. #define STREAM_ENDDURING                              \
  88.     NX_HANDLER                                  \
  89.           const char *stream_err_msg = stream_decode_error (&NXLocalHandler); \
  90.                                           \
  91.           PyErr_SetString (ObjCStreams_Error, (char *) stream_err_msg);          \
  92.           Py_XDECREF ((PyObject *) retvalue);                      \
  93.           return NULL;                                  \
  94.         NX_ENDHANDLER
  95.  
  96. #define STREAM_ENDDURING_BLOCK_THREADS                          \
  97.     NX_HANDLER                                  \
  98.       const char *stream_err_msg = stream_decode_error (&NXLocalHandler); \
  99.                                           \
  100.           Py_BLOCK_THREADS                              \
  101.        PyErr_SetString (ObjCStreams_Error, (char *) stream_err_msg);       \
  102.           Py_XDECREF ((PyObject *) retvalue);                      \
  103.           return NULL;                                  \
  104.         NX_ENDHANDLER
  105.  
  106. #else /* WITH_FOUNDATION */
  107.  
  108. #include <Foundation/NSException.h>
  109.       
  110. #define STREAM_DURING NS_DURING
  111.  
  112. #define STREAM_ENDDURING                          \
  113.     NS_HANDLER                              \
  114.           const char *stream_err_msg = [[localException reason] cString]; \
  115.                                       \
  116.           PyErr_SetString (ObjCStreams_Error, (char *) stream_err_msg);      \
  117.           Py_XDECREF ((PyObject *) retvalue);                  \
  118.           return NULL;                              \
  119.         NS_ENDHANDLER
  120.  
  121. #define STREAM_ENDDURING_BLOCK_THREADS                      \
  122.     NS_HANDLER                              \
  123.       const char *stream_err_msg = [[localException reason] cString]; \
  124.                                       \
  125.           Py_BLOCK_THREADS                          \
  126.        PyErr_SetString (ObjCStreams_Error, (char *) stream_err_msg);      \
  127.           Py_XDECREF ((PyObject *) retvalue);                  \
  128.           return NULL;                              \
  129.         NS_ENDHANDLER
  130.       
  131. #endif /* ! WITH_FOUNDATION */
  132.  
  133. static void
  134. ObjCStream_dealloc (ObjCStream *self)
  135. {
  136.   [self->stream close];
  137. #ifndef WITH_FOUNDATION
  138.   [(id) self->stream free];
  139. #else
  140.   [self->stream release];
  141. #endif
  142.  
  143.   Py_XDECREF (self->from);
  144.   
  145.   PyMem_DEL (self);
  146. }
  147.  
  148. static PyObject *
  149. ObjCStream_close (ObjCStream *self, PyObject *args)
  150. {
  151.   if (PyArg_ParseTuple (args, ""))
  152.     {
  153.       [self->stream close];
  154.       Py_INCREF (Py_None);
  155.       return Py_None;
  156.     }
  157.  
  158.   return NULL;
  159. }
  160.  
  161. static PyObject *
  162. ObjCStream_flush (ObjCStream *self, PyObject *args)
  163. {
  164.   if (PyArg_ParseTuple (args, ""))
  165.     {
  166.       PyObject *retvalue = NULL;
  167.       
  168.       STREAM_DURING
  169.     [self->stream flushStream];
  170.       STREAM_ENDDURING
  171.     
  172.       Py_INCREF (Py_None);
  173.       return Py_None;
  174.     }
  175.  
  176.   return NULL;
  177. }
  178.  
  179. static PyObject *
  180. ObjCStream_read (ObjCStream *self, PyObject *args)
  181. {
  182.   int toread, rtotal, bufsize;
  183.   PyObject *retvalue;
  184.     
  185.   if ([self->stream isClosed])
  186.     {
  187.       PyErr_SetString (ObjCStreams_Error, "Inappropriate operation on closed stream.");
  188.       return NULL;
  189.     }
  190.  
  191.   toread = -1;
  192.   if (PyArg_ParseTuple(args, "|i;optional number of bytes ", &toread) == 0)
  193.     return NULL;
  194.  
  195.   if (toread == 0)
  196.     return PyString_FromString ("");
  197.   
  198.   bufsize = toread > 0 ? toread : BUFSIZ;
  199.   retvalue = PyString_FromStringAndSize ((char *)NULL, bufsize);
  200.   if (retvalue == NULL)
  201.     return NULL;
  202.  
  203.   rtotal = 0;
  204.   Py_BEGIN_ALLOW_THREADS
  205.     for (;;)
  206.       {
  207.     int rcount;
  208.     char *buf = PyString_AS_STRING ((PyStringObject *) retvalue);
  209.     
  210.     STREAM_DURING
  211.       rcount = [self->stream readBytes:buf+rtotal length:bufsize-rtotal];
  212.     STREAM_ENDDURING_BLOCK_THREADS
  213.       
  214.     if (rcount == 0)
  215.       break;
  216.  
  217.     rtotal += rcount;
  218.     if (rtotal == toread)
  219.       break;
  220.     if (toread < 0)
  221.       {
  222.         bufsize *= 2;
  223.  
  224.         if (_PyString_Resize (&retvalue, bufsize) < 0)
  225.           {
  226.         Py_BLOCK_THREADS
  227.         return NULL;
  228.           }
  229.       }
  230.       }
  231.   Py_END_ALLOW_THREADS
  232.  
  233.   if (rtotal != bufsize)
  234.     _PyString_Resize (&retvalue, rtotal);
  235.     
  236.   return retvalue;
  237. }
  238.  
  239. /* XXX A better solution would be implementing/using -readLine: and
  240.    -writeLine: on Streams. Since this approach would use optimized
  241.    access to the stream structure (for example, memorystreams already
  242.    cache the data in memory, so there is no need to reread the
  243.    content...). NB: GNU Stream's -writeLine: does append a newline to
  244.    its output. */
  245.    
  246. /* Internal routine to get a line.
  247.    Size argument interpretation:
  248.    > 0: max length;
  249.    = 0: read arbitrary line;
  250.    < 0: strip trailing '\n', raise EOFError if EOF reached immediately. */
  251.  
  252. static PyObject *
  253. _ObjCStream_readline (ObjCStream *self, int toread)
  254. {
  255.   int rtotal, bufsize;
  256.   char *buf, *bufend;
  257.   char *p;
  258.   PyObject *retvalue;
  259.     
  260.   if ([self->stream isClosed])
  261.     {
  262.       PyErr_SetString (ObjCStreams_Error, "Inappropriate operation on closed stream.");
  263.       return NULL;
  264.     }
  265.  
  266.   bufsize = toread > 0 ? toread : 100;
  267.   retvalue = PyString_FromStringAndSize ((char *)NULL, bufsize);
  268.   if (retvalue == NULL)
  269.     return NULL;
  270.  
  271.   p = buf = PyString_AS_STRING ((PyStringObject *) retvalue);
  272.   bufend = buf + bufsize;
  273.   
  274.   rtotal = 0;
  275.   Py_BEGIN_ALLOW_THREADS
  276.     for (;;)
  277.       {
  278.     int status;
  279.     
  280.     STREAM_DURING
  281.       status = [self->stream readByte:p];
  282.     STREAM_ENDDURING_BLOCK_THREADS
  283.  
  284.     if (status == EOF)
  285.       {
  286.         if (toread < 0 && p == buf)
  287.           {
  288.         Py_BLOCK_THREADS
  289.  
  290.         Py_DECREF (retvalue);
  291.         PyErr_SetString (PyExc_EOFError, "EOF when reading a line");
  292.         return NULL;
  293.           }
  294.         break;
  295.       }
  296.  
  297.     if (*p++ == '\n')
  298.       {
  299.         if (toread < 0)    // skip trailing newline
  300.           p--;
  301.         break;
  302.       }
  303.  
  304.     if (p == bufend)
  305.       {
  306.         if (toread > 0)
  307.           break;
  308.  
  309.         rtotal = bufsize;
  310.         bufsize *= 2;
  311.  
  312.         if (_PyString_Resize (&retvalue, bufsize) < 0)
  313.           {
  314.         Py_BLOCK_THREADS
  315.         return NULL;
  316.           }
  317.  
  318.         buf = PyString_AS_STRING ((PyStringObject *) retvalue);
  319.         p = buf + rtotal;
  320.         bufend = buf + bufsize;
  321.       }
  322.       }
  323.   Py_END_ALLOW_THREADS
  324.  
  325.   rtotal = p - buf;
  326.   if (rtotal != bufsize)
  327.     _PyString_Resize (&retvalue, rtotal);
  328.     
  329.   return retvalue;
  330. }
  331.  
  332. static PyObject *
  333. ObjCStream_readline (ObjCStream *self, PyObject *args)
  334. {
  335.   int toread = -1;
  336.   
  337.   if (PyArg_ParseTuple (args, "|i;optional number of bytes", &toread))
  338.     {
  339.       if (toread == 0)
  340.     return PyString_FromString ("");
  341.       else
  342.     return _ObjCStream_readline (self, (toread < 0 ? 0 : toread));
  343.     }
  344.  
  345.   return NULL;
  346. }
  347.  
  348. static PyObject *
  349. ObjCStream_readlines (ObjCStream *self, PyObject *args)
  350. {
  351.   if (PyArg_ParseTuple (args, ""))
  352.     {
  353.       PyObject *list = PyList_New (0);
  354.       int rtotal;
  355.       int bufsize;
  356.       char *buffer, *bufend;
  357.       register char *startl;
  358.       
  359.       if (!list)
  360.     return NULL;
  361.  
  362. #if 1
  363.       
  364.       buffer = malloc (bufsize = BUFSIZ);
  365.       if (!buffer)
  366.     {
  367.       PyErr_NoMemory();
  368.       return NULL;
  369.     }
  370.  
  371.       rtotal = 0;
  372.       Py_BEGIN_ALLOW_THREADS
  373.     for (;;)
  374.       {
  375.         int rcount;
  376.         PyObject *retvalue = NULL;
  377.         
  378.         STREAM_DURING
  379.           rcount = [self->stream readBytes:buffer+rtotal length:bufsize-rtotal];
  380.         STREAM_ENDDURING_BLOCK_THREADS
  381.       
  382.         if (rcount == 0)
  383.           break;
  384.         else if (rcount == bufsize-rtotal)
  385.           {
  386.         bufsize *= 2;
  387.  
  388.         buffer = realloc (buffer, bufsize);
  389.         if (! buffer)
  390.           {
  391.             Py_BLOCK_THREADS
  392.             PyErr_NoMemory();
  393.             return NULL;
  394.           }
  395.           }
  396.         
  397.         rtotal += rcount;
  398.       }
  399.       Py_END_ALLOW_THREADS
  400.  
  401.       startl = buffer;
  402.       bufend = startl+rtotal;
  403.       
  404.       while (startl < bufend)
  405.     {
  406.       char *endl = memchr (startl, '\n', bufend - startl);
  407.       int size;
  408.       PyObject *line;
  409.       
  410.       if (endl)
  411.         size = endl - startl + 1;
  412.       else
  413.         size = bufend - startl;
  414.       
  415.       line = PyString_FromStringAndSize (startl, size);
  416.       if (!line || PyList_Append (list, line))
  417.         {
  418.           Py_XDECREF (line);
  419.           Py_DECREF (list);
  420.           free (buffer);
  421.           return NULL;
  422.         }
  423.       else
  424.         Py_DECREF (line);
  425.  
  426.       startl += size;
  427.     }
  428.  
  429.       free (buffer);
  430.       
  431. #else  // this is slower
  432.  
  433.       for (;;)
  434.     {
  435.       PyObject *line = _ObjCStream_readline (self, 0);
  436.  
  437.       if (line && PyString_Size (line) == 0)
  438.         {
  439.           Py_DECREF (line);
  440.           break;
  441.         }
  442.       else if (!line || PyList_Append (list, line))
  443.         {
  444.           Py_XDECREF (line);
  445.           Py_DECREF (list);
  446.           return NULL;
  447.         }
  448.       else
  449.         Py_DECREF (line);
  450.     }
  451.       
  452. #endif
  453.       
  454.       return list;
  455.     }
  456.  
  457.   return NULL;
  458. }
  459.  
  460. static PyObject *
  461. ObjCStream_seek (ObjCStream *self, PyObject *args)
  462. {
  463.   long offset;
  464.   int whence = OCS_FROMSTART;
  465.   PyObject *retvalue = NULL;
  466.   
  467.   if (!PyArg_ParseTuple (args, "l|i;offset and optionally one of FROMSTART (default),FROMEND,FROMCURRENT", &offset, &whence))
  468.     return NULL;
  469.   
  470.   STREAM_DURING
  471.     [self->stream setStreamPosition:offset seekMode:whence];
  472.   STREAM_ENDDURING
  473.     
  474.   Py_INCREF(Py_None);
  475.   return Py_None;
  476. }
  477.  
  478. static PyObject *
  479. ObjCStream_tell (ObjCStream *self, PyObject *args)
  480. {
  481.   if (PyArg_ParseTuple (args, ""))
  482.     {
  483.       PyObject *retvalue = NULL;
  484.       long offset;
  485.  
  486.       STREAM_DURING
  487.     offset = [self->stream streamPosition];
  488.       STREAM_ENDDURING
  489.  
  490.       retvalue = PyInt_FromLong (offset);
  491.       return retvalue;
  492.     }
  493.  
  494.   return NULL;
  495. }
  496.  
  497. static PyObject *
  498. ObjCStream_write (ObjCStream *self, PyObject *args)
  499. {
  500.   char *s;
  501.   int l;
  502.  
  503.   if (PyArg_ParseTuple (args, "s#;string", &s, &l))
  504.     {
  505.       PyObject *retvalue = NULL;
  506.  
  507.       Py_BEGIN_ALLOW_THREADS
  508.       STREAM_DURING
  509.     errno = 0;
  510.     if ([self->stream writeBytes:s length:l] != l)
  511.       {
  512.         Py_BLOCK_THREADS
  513.         PyErr_SetFromErrno (PyExc_IOError);    // XXX does stream set errno?
  514.         return NULL;
  515.       }
  516.       STREAM_ENDDURING_BLOCK_THREADS
  517.       Py_END_ALLOW_THREADS
  518.  
  519.       Py_INCREF (Py_None);
  520.       return Py_None;
  521.     }
  522.  
  523.   return NULL;
  524. }
  525.  
  526. static PyObject *
  527. ObjCStream_writelines (ObjCStream *self, PyObject *args)
  528. {
  529.   PyObject *list;
  530.  
  531.   if (PyArg_ParseTuple (args, "O!;list of strings", &PyList_Type, &list))
  532.     {
  533.       int nlines = PyList_Size (list);
  534.       int i;
  535.       PyObject *retvalue = NULL;
  536.  
  537.       Py_BEGIN_ALLOW_THREADS
  538.     errno = 0;
  539.     for (i=0; i<nlines; i++)
  540.       {
  541.         PyObject *line = PyList_GET_ITEM ((PyListObject *) list, i);
  542.  
  543.         if (!PyString_Check (line))
  544.           {
  545.         Py_BLOCK_THREADS
  546.         PyErr_SetString (PyExc_TypeError, "writelines() requires list of strings");
  547.         return NULL;
  548.           }
  549.         else
  550.           {
  551.         int len = PyString_Size (line);
  552.  
  553.         STREAM_DURING
  554.           if ([self->stream writeBytes:PyString_AS_STRING ((PyStringObject *) line)
  555.                length:len] != len)
  556.             {
  557.               Py_BLOCK_THREADS
  558.               PyErr_SetFromErrno (PyExc_IOError); // XXX does stream set errno?
  559.               return NULL;
  560.             }
  561.         STREAM_ENDDURING_BLOCK_THREADS
  562.           }
  563.       }
  564.       Py_END_ALLOW_THREADS
  565.  
  566.       Py_INCREF (Py_None);
  567.       return Py_None;
  568.     }
  569.  
  570.   return NULL;
  571. }
  572.  
  573. static char ObjCStream_savetofile_doc[] =
  574. FUNDOC("Save the content of the stream to a file.",
  575.        ".savetofile (NAME)",
  576.        "NAME\t: name of the file",
  577.        "None");
  578. static PyObject *
  579. ObjCStream_savetofile (ObjCStream *self, PyObject *args)
  580. {
  581.   char *name;
  582.  
  583.   if (PyArg_ParseTuple (args, "s;filename", &name))
  584.     {
  585.       PyObject *retvalue = NULL;
  586.       
  587.       Py_BEGIN_ALLOW_THREADS
  588.       STREAM_DURING
  589.     errno = 0;
  590.     if (![(id) self->stream saveToFilename:name])
  591.       {
  592.         Py_BLOCK_THREADS
  593.         PyErr_SetFromErrno (PyExc_IOError);    // XXX does stream set errno?
  594.         return NULL;
  595.       }
  596.       STREAM_ENDDURING
  597.       Py_END_ALLOW_THREADS
  598.  
  599.       Py_INCREF (Py_None);
  600.       return Py_None;      
  601.     }
  602.  
  603.   return NULL;
  604. }
  605.  
  606. static PyMethodDef ObjCStream_methods[] =
  607. {
  608.   { "close",    (PyCFunction) ObjCStream_close,        METH_VARARGS, NULL },
  609.   { "flush",    (PyCFunction) ObjCStream_flush,        METH_VARARGS, NULL },  
  610.   { "read",    (PyCFunction) ObjCStream_read,        METH_VARARGS, NULL },
  611.   { "readline",    (PyCFunction) ObjCStream_readline,    METH_VARARGS, NULL },
  612.   { "readlines",(PyCFunction) ObjCStream_readlines,    METH_VARARGS, NULL },
  613.   { "seek",    (PyCFunction) ObjCStream_seek,        METH_VARARGS, NULL },
  614.   { "tell",    (PyCFunction) ObjCStream_tell,        METH_VARARGS, NULL },
  615.   { "write",    (PyCFunction) ObjCStream_write,        METH_VARARGS, NULL },
  616.   { "writelines",(PyCFunction) ObjCStream_writelines,    METH_VARARGS, NULL },
  617.  
  618.   { "savetofile",(PyCFunction) ObjCStream_savetofile,    METH_VARARGS, ObjCStream_savetofile_doc },
  619.   { 0, 0, 0, 0 }
  620. };
  621.  
  622. static PyObject *
  623. ObjCStream_getattr (ObjCPointer *self, char *name)
  624. {
  625.   PyObject *method;
  626.  
  627.   method = Py_FindMethod (ObjCStream_methods, (PyObject *) self, name);
  628.  
  629.   return method;
  630. }
  631.  
  632. PyTypeObject ObjCStream_Type =
  633. {
  634.   PyObject_HEAD_INIT(&PyType_Type)
  635.   0,                          /*ob_size*/
  636.   "ObjCStream",                      /*tp_name*/
  637.   sizeof (ObjCStream),                  /*tp_basicsize*/
  638.   0,                          /*tp_itemsize*/
  639.   
  640.   /* methods */
  641.   (destructor) ObjCStream_dealloc,          /*tp_dealloc*/
  642.   (printfunc) 0,                  /*tp_print*/
  643.   (getattrfunc) ObjCStream_getattr,          /*tp_getattr*/
  644.   (setattrfunc) 0,                  /*tp_setattr*/
  645.   (cmpfunc) 0,                      /*tp_compare*/
  646.   (reprfunc) 0,                      /*tp_repr*/
  647.   0,                          /*tp_as_number*/
  648.   0,                          /*tp_as_sequence*/
  649.   0,                          /*tp_as_mapping*/
  650.   (hashfunc) 0,                      /*tp_hash*/
  651.   (ternaryfunc) 0,                  /*tp_call*/
  652.   (reprfunc) 0,                      /*tp_str*/
  653.   (getattrofunc) 0,                        /*tp_getattro*/
  654.   (setattrofunc) 0,                  /*tp_setattro*/
  655.  
  656.   /* Space for future expansion */
  657.   0L,0L,
  658.   
  659.   "Wrapper around a Objective-C Stream"          /* Documentation string */
  660. };
  661.  
  662. ObjCStream *
  663. ObjCStream_new_from_file_and_mode (const char *name, int mode)
  664. {
  665.   ObjCStream *retvalue = PyObject_NEW (ObjCStream, &ObjCStream_Type);
  666.   
  667.   if (!retvalue)
  668.     return NULL;
  669.  
  670.   retvalue->from = NULL;
  671.  
  672.   STREAM_DURING
  673.     retvalue->stream = [OC_Stream newFromFilename:name withMode:mode];
  674.   STREAM_ENDDURING
  675.  
  676.   if (retvalue->stream == nil)
  677.     {
  678.       Py_DECREF (retvalue);
  679.       return NULL;
  680.     }
  681.   else
  682.     {
  683.       retvalue->from = PyString_FromString ((char *) name);
  684.     }
  685.   
  686. #ifdef WITH_FOUNDATION
  687.   [retvalue->stream retain];
  688. #endif
  689.   
  690.   return retvalue;
  691. }
  692.  
  693. ObjCStream *
  694. ObjCStream_new_from_file (const char *name)
  695. {
  696.   ObjCStream *retvalue = PyObject_NEW (ObjCStream, &ObjCStream_Type);
  697.   
  698.   if (!retvalue)
  699.     return NULL;
  700.  
  701.   retvalue->from = NULL;
  702.  
  703.   STREAM_DURING
  704.     retvalue->stream = [OC_Stream newFromFilename:name];
  705.   STREAM_ENDDURING
  706.  
  707.   if (retvalue->stream == nil)
  708.     {
  709.       Py_DECREF (retvalue);
  710.       return NULL;
  711.     }
  712.   else
  713.     {
  714.       retvalue->from = PyString_FromString ((char *) name);
  715.     }
  716.   
  717. #ifdef WITH_FOUNDATION
  718.   [retvalue->stream retain];
  719. #endif
  720.  
  721.   
  722.   return retvalue;
  723. }
  724.  
  725. ObjCStream *
  726. ObjCStream_new (OC_Stream *stream)
  727. {
  728.   ObjCStream *retvalue = PyObject_NEW (ObjCStream, &ObjCStream_Type);
  729.   
  730.   if (!retvalue)
  731.     return NULL;
  732.  
  733.   retvalue->stream = stream;
  734. #ifdef WITH_FOUNDATION
  735.   [retvalue->stream retain];
  736. #endif
  737.   retvalue->from = NULL;
  738.   
  739.   return retvalue;
  740. }
  741.  
  742. #ifndef WITH_FOUNDATION
  743. NXStream *
  744. ObjCStream_stream (ObjCStream *self)
  745. {
  746.   return self->stream ? [(id) self->stream stream] : NULL;
  747. }
  748.  
  749. ObjCStream *
  750. ObjCStream_new_from_stream (NXStream *stream)
  751. {
  752.   return ObjCStream_new ([OC_Stream newFromStream:stream]);
  753. }
  754.  
  755. #endif /* WITH_FOUNDATION */
  756.  
  757. ObjCStream *
  758. ObjCStream_new_from_memory_with_mode (void *p, int len, int mode)
  759. {
  760.   ObjCStream *retvalue = PyObject_NEW (ObjCStream, &ObjCStream_Type);
  761.   
  762.   if (!retvalue)
  763.     return NULL;
  764.  
  765.   retvalue->from = NULL;
  766.  
  767.   STREAM_DURING
  768.     retvalue->stream = [OC_Stream newFromMemory:p length:len withMode:mode];
  769.   STREAM_ENDDURING
  770.  
  771.   if (retvalue->stream == nil)
  772.     {
  773.       Py_DECREF (retvalue);
  774.       return NULL;
  775.     }
  776.  
  777. #ifdef WITH_FOUNDATION
  778.   [retvalue->stream retain];
  779. #endif
  780.   
  781.   return retvalue;
  782. }
  783.   
  784. static char ObjCStreams_openfile_doc[] =
  785. FUNDOC("Open a file with the underlying Streams facility",
  786.        ".openfile (NAME, MODE)",
  787.        "NAME\t: the name of the file\n\
  788. \t\tMODE\t: optional mode, defaults to READONLY; may be READONLY, READWRITE, WRITEONLY",
  789.        "An ObjCStream instance");
  790. static PyObject *
  791. ObjCStreams_openfile (PyObject *self, PyObject *args)
  792. {
  793.   char *filename;
  794.   int mode = OCS_READONLY;
  795.  
  796.   if (PyArg_ParseTuple (args, "s|i;filename and an optional mode from READONLY (default),READWRITE,WRITEONLY", &filename, &mode))
  797.     {
  798.       return (PyObject *) ObjCStream_new_from_file_and_mode (filename, mode);
  799.     }
  800.  
  801.   return NULL;
  802. }
  803.  
  804. static char ObjCStreams_openmemory_doc[] =
  805. FUNDOC("Open a chunk of memory with the underlying Streams facility",
  806.        ".openmemory (MEM, MODE)",
  807.        "MEM\t: a string to be read as a stream, or None (not in READONLY mode)\n\
  808. \t\tMODE\t: optional mode, defaults to READONLY; may be READONLY, READWRITE, WRITEONLY",
  809.        "An ObjCStream instance");
  810. static PyObject *
  811. ObjCStreams_openmemory (PyObject *self, PyObject *args)
  812. {
  813.   PyObject *memory;
  814.   int mode = OCS_READONLY;
  815.  
  816.   if (PyArg_ParseTuple (args, "O|i;a string or None and an optional mode from READONLY (default),READWRITE,WRITEONLY", &memory, &mode))
  817.     {
  818.       char *m;
  819.       int len;
  820.       ObjCStream *retvalue;
  821.       
  822.       if (mode != OCS_READONLY)
  823.     {
  824.       if (memory != Py_None)
  825.         {
  826.           PyErr_SetString (ObjCStreams_Error, "Writeable memory stream requires None as first parameter");
  827.           return NULL;
  828.         }
  829.  
  830.       m = NULL;
  831.       len = 0;
  832.     }
  833.       else
  834.     {
  835.       if (PyString_Check (memory))
  836.         {
  837.           m = PyString_AsString (memory);
  838.           len = PyString_Size (memory);
  839.         }
  840.       else
  841.         {
  842.           PyErr_SetString (ObjCStreams_Error, "Expected a string object");
  843.           return NULL;
  844.         }
  845.     }
  846.       
  847.       retvalue = ObjCStream_new_from_memory_with_mode (m, len, mode);
  848.       if (mode == OCS_READONLY)
  849.     {
  850.       retvalue->from = memory;
  851.       Py_INCREF (retvalue->from);
  852.     }
  853.  
  854.       return (PyObject *) retvalue;
  855.     }
  856.  
  857.   return NULL;
  858. }
  859.  
  860. #if defined(NeXT) && !defined(GNU_RUNTIME)
  861. static char ObjCStreams_openport_doc[] =
  862. FUNDOC("Open a Mach port with the underlying Streams facility",
  863.        ".openport (PORT, MODE)",
  864.        "PORT\t: the Mach port number\n\
  865. \t\tMODE\t: optional mode, defaults to READONLY; may be READONLY, READWRITE, WRITEONLY",
  866.        "An ObjCStream instance");
  867. static PyObject *
  868. ObjCStreams_openport (PyObject *self, PyObject *args)
  869. {
  870.   port_t port;
  871.   int mode = OCS_READONLY;
  872.  
  873.   if (PyArg_ParseTuple (args, "i|i;port number and an optional mode from READONLY (default),READWRITE,WRITEONLY", &port, &mode))
  874.     {
  875.       PyObject *retvalue = NULL;
  876.       NXStream *s;
  877.  
  878.       STREAM_DURING
  879.     s = NXOpenPort (port, mode);
  880.       STREAM_ENDDURING
  881.  
  882.       if (! s)
  883.     {
  884.       PyErr_SetString (ObjCStreams_Error, "Cannot open MACH port.");
  885.       return NULL;
  886.     }
  887.       
  888.       retvalue = (PyObject *) ObjCStream_new_from_stream (s);
  889.       return retvalue;
  890.     }
  891.  
  892.   return NULL;
  893. }
  894. #endif
  895.  
  896. static PyMethodDef ObjCStreams_methods[] =
  897. {
  898.   { "openfile",        (PyCFunction) ObjCStreams_openfile,    METH_VARARGS,    ObjCStreams_openfile_doc },
  899.   { "openmemory",    (PyCFunction) ObjCStreams_openmemory,    METH_VARARGS,    ObjCStreams_openmemory_doc },
  900. #if defined(NeXT) && !defined(GNU_RUNTIME)
  901.   { "openport",        (PyCFunction) ObjCStreams_openport,    METH_VARARGS,    ObjCStreams_openport_doc },
  902. #endif
  903.   { 0, 0, 0, 0 }
  904. };
  905.  
  906. PyObject *ObjCStreams_Error;
  907.  
  908. void
  909. initObjCStreams (void)
  910. {
  911.   PyObject *m, *d;
  912.  
  913.   m = Py_InitModule4 ("ObjCStreams", ObjCStreams_methods, NULL, NULL, PYTHON_API_VERSION);
  914.   d = PyModule_GetDict (m);
  915.  
  916.   ObjCStreams_Error = PyString_FromString ("ObjCStreams.error");
  917.   PyDict_SetItemString (d, "error", ObjCStreams_Error);
  918.  
  919. #define DEFCONST(name,val) do {                        \
  920.                              PyObject *pval = PyInt_FromLong (val);    \
  921.                  PyDict_SetItemString (d, name, pval);    \
  922.                  Py_DECREF (pval);                \
  923.                            } while (0)
  924.  
  925.   DEFCONST("READONLY", OCS_READONLY);
  926.   DEFCONST("WRITEONLY", OCS_WRITEONLY);
  927.   DEFCONST("READWRITE", OCS_READWRITE);
  928.   DEFCONST("APPEND", OCS_APPEND);
  929.  
  930.   DEFCONST("FROMSTART", OCS_FROMSTART);
  931.   DEFCONST("FROMCURRENT", OCS_FROMCURRENT);
  932.   DEFCONST("FROMEND", OCS_FROMEND);
  933.  
  934.   if (PyErr_Occurred())
  935.     Py_FatalError ("can't initialize module ObjCStreams");
  936. }
  937.  
  938. /*
  939. ** Local Variables:
  940. ** change-log-default-name:"../ChangeLog.PyObjC"
  941. ** End:
  942. */
  943.