cStringIO.c revision 03657cfdb056dbd36db12cc3db12a6b58a962e20
1/*
2 * cStringIO.c,v 1.29 1999/06/15 14:10:27 jim Exp
3 *
4 * Copyright (c) 1996-1998, Digital Creations, Fredericksburg, VA, USA.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 *   o Redistributions of source code must retain the above copyright
12 *     notice, this list of conditions, and the disclaimer that follows.
13 *
14 *   o Redistributions in binary form must reproduce the above copyright
15 *     notice, this list of conditions, and the following disclaimer in
16 *     the documentation and/or other materials provided with the
17 *     distribution.
18 *
19 *   o All advertising materials mentioning features or use of this
20 *     software must display the following acknowledgement:
21 *
22 *       This product includes software developed by Digital Creations
23 *       and its contributors.
24 *
25 *   o Neither the name of Digital Creations nor the names of its
26 *     contributors may be used to endorse or promote products derived
27 *     from this software without specific prior written permission.
28 *
29 *
30 * THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
31 * IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
32 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
33 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL
34 * CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
37 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
40 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
41 * DAMAGE.
42 *
43 #
44 # If you have questions regarding this software, contact:
45 #
46 #   Digital Creations, L.C.
47 #   910 Princess Ann Street
48 #   Fredericksburge, Virginia  22401
49 #
50 #   info@digicool.com
51 #
52 #   (540) 371-6909
53 */
54static char cStringIO_module_documentation[] =
55"A simple fast partial StringIO replacement.\n"
56"\n"
57"This module provides a simple useful replacement for\n"
58"the StringIO module that is written in C.  It does not provide the\n"
59"full generality of StringIO, but it provides enough for most\n"
60"applications and is especially useful in conjuction with the\n"
61"pickle module.\n"
62"\n"
63"Usage:\n"
64"\n"
65"  from cStringIO import StringIO\n"
66"\n"
67"  an_output_stream=StringIO()\n"
68"  an_output_stream.write(some_stuff)\n"
69"  ...\n"
70"  value=an_output_stream.getvalue() # str(an_output_stream) works too!\n"
71"\n"
72"  an_input_stream=StringIO(a_string)\n"
73"  spam=an_input_stream.readline()\n"
74"  spam=an_input_stream.read(5)\n"
75"  an_input_stream.seek(0)           # OK, start over\n"
76"  spam=an_input_stream.read()       # and read it all\n"
77"  \n"
78"If someone else wants to provide a more complete implementation,\n"
79"go for it. :-)  \n"
80"\n"
81"cStringIO.c,v 1.29 1999/06/15 14:10:27 jim Exp\n"
82;
83
84#include "Python.h"
85#include "import.h"
86#include "cStringIO.h"
87
88#define UNLESS(E) if(!(E))
89
90/* Declarations for objects of type StringO */
91
92typedef struct {
93  PyObject_HEAD
94  char *buf;
95  int pos, string_size, buf_size, softspace;
96} Oobject;
97
98/* Declarations for objects of type StringI */
99
100typedef struct {
101  PyObject_HEAD
102  char *buf;
103  int pos, string_size;
104  PyObject *pbuf;
105} Iobject;
106
107static char O_reset__doc__[] =
108"reset() -- Reset the file position to the beginning"
109;
110
111static PyObject *
112O_reset(Oobject *self, PyObject *args) {
113  self->pos = 0;
114
115  Py_INCREF(Py_None);
116  return Py_None;
117}
118
119
120static char O_tell__doc__[] =
121"tell() -- get the current position.";
122
123static PyObject *
124O_tell(Oobject *self, PyObject *args) {
125  return PyInt_FromLong(self->pos);
126}
127
128
129static char O_seek__doc__[] =
130"seek(position)       -- set the current position\n"
131"seek(position, mode) -- mode 0: absolute; 1: relative; 2: relative to EOF";
132
133static PyObject *
134O_seek(Oobject *self, PyObject *args) {
135  int position, mode = 0;
136
137  UNLESS(PyArg_ParseTuple(args, "i|i:seek", &position, &mode)) {
138    return NULL;
139  }
140
141  if (mode == 2) {
142    position += self->string_size;
143  }
144  else if (mode == 1) {
145    position += self->pos;
146  }
147
148  if (position > self->buf_size) {
149      self->buf_size*=2;
150      if(self->buf_size <= position) self->buf_size=position+1;
151      UNLESS(self->buf=(char*)realloc(self->buf,self->buf_size*sizeof(char))) {
152	  self->buf_size=self->pos=0;
153	  return PyErr_NoMemory();
154	}
155    }
156  else if(position < 0) position=0;
157
158  self->pos=position;
159
160  while(--position >= self->string_size) self->buf[position]=0;
161
162  Py_INCREF(Py_None);
163  return Py_None;
164}
165
166static char O_read__doc__[] =
167"read([s]) -- Read s characters, or the rest of the string"
168;
169
170static int
171O_cread(PyObject *self, char **output, int  n) {
172  int l;
173
174  l = ((Oobject*)self)->string_size - ((Oobject*)self)->pos;
175  if (n < 0 || n > l) {
176    n = l;
177    if (n < 0) n=0;
178  }
179
180  *output=((Oobject*)self)->buf + ((Oobject*)self)->pos;
181  ((Oobject*)self)->pos += n;
182  return n;
183}
184
185static PyObject *
186O_read(Oobject *self, PyObject *args) {
187  int n = -1;
188  char *output;
189
190  UNLESS(PyArg_ParseTuple(args, "|i:read", &n)) return NULL;
191
192  n=O_cread((PyObject*)self,&output,n);
193
194  return PyString_FromStringAndSize(output, n);
195}
196
197
198static char O_readline__doc__[] =
199"readline() -- Read one line"
200;
201
202static int
203O_creadline(PyObject *self, char **output) {
204  char *n, *s;
205  int l;
206
207  for (n = ((Oobject*)self)->buf + ((Oobject*)self)->pos,
208	 s = ((Oobject*)self)->buf + ((Oobject*)self)->string_size;
209       n < s && *n != '\n'; n++);
210  if (n < s) n++;
211
212  *output=((Oobject*)self)->buf + ((Oobject*)self)->pos;
213  l = n - ((Oobject*)self)->buf - ((Oobject*)self)->pos;
214  ((Oobject*)self)->pos += l;
215  return l;
216}
217
218static PyObject *
219O_readline(Oobject *self, PyObject *args) {
220  int n;
221  char *output;
222
223  n=O_creadline((PyObject*)self,&output);
224  return PyString_FromStringAndSize(output, n);
225}
226
227static char O_write__doc__[] =
228"write(s) -- Write a string to the file"
229"\n\nNote (hack:) writing None resets the buffer"
230;
231
232
233static int
234O_cwrite(PyObject *self, char *c, int  l) {
235  int newl;
236
237  newl=((Oobject*)self)->pos+l;
238  if(newl >= ((Oobject*)self)->buf_size) {
239      ((Oobject*)self)->buf_size*=2;
240      if(((Oobject*)self)->buf_size <= newl) ((Oobject*)self)->buf_size=newl+1;
241      UNLESS(((Oobject*)self)->buf=
242	     (char*)realloc(((Oobject*)self)->buf,
243			    (((Oobject*)self)->buf_size) *sizeof(char))) {
244	  PyErr_SetString(PyExc_MemoryError,"out of memory");
245	  ((Oobject*)self)->buf_size=((Oobject*)self)->pos=0;
246	  return -1;
247	}
248    }
249
250  memcpy(((Oobject*)((Oobject*)self))->buf+((Oobject*)self)->pos,c,l);
251
252  ((Oobject*)self)->pos += l;
253
254  if (((Oobject*)self)->string_size < ((Oobject*)self)->pos) {
255      ((Oobject*)self)->string_size = ((Oobject*)self)->pos;
256    }
257
258  return l;
259}
260
261static PyObject *
262O_write(Oobject *self, PyObject *args) {
263  PyObject *s;
264  char *c;
265  int l;
266
267  UNLESS(PyArg_ParseTuple(args, "O:write", &s)) return NULL;
268  UNLESS(-1 != (l=PyString_Size(s))) return NULL;
269  UNLESS(c=PyString_AsString(s)) return NULL;
270  UNLESS(-1 != O_cwrite((PyObject*)self,c,l)) return NULL;
271
272  Py_INCREF(Py_None);
273  return Py_None;
274}
275
276static char O_getval__doc__[] =
277   "getvalue([use_pos]) -- Get the string value."
278   "\n"
279   "If use_pos is specified and is a true value, then the string returned\n"
280   "will include only the text up to the current file position.\n"
281;
282
283static PyObject *
284O_getval(Oobject *self, PyObject *args) {
285  PyObject *use_pos=Py_None;
286  int s;
287
288  use_pos=Py_None;
289  UNLESS(PyArg_ParseTuple(args,"|O:getval",&use_pos)) return NULL;
290  if(PyObject_IsTrue(use_pos)) {
291      s=self->pos;
292      if (s > self->string_size) s=self->string_size;
293  }
294  else
295      s=self->string_size;
296  return PyString_FromStringAndSize(self->buf, s);
297}
298
299static PyObject *
300O_cgetval(PyObject *self) {
301  return PyString_FromStringAndSize(((Oobject*)self)->buf,
302				    ((Oobject*)self)->pos);
303}
304
305static char O_truncate__doc__[] =
306"truncate(): truncate the file at the current position.";
307
308static PyObject *
309O_truncate(Oobject *self, PyObject *args) {
310  if (self->string_size > self->pos)
311      self->string_size = self->pos;
312  Py_INCREF(Py_None);
313  return Py_None;
314}
315
316static char O_isatty__doc__[] = "isatty(): always returns 0";
317
318static PyObject *
319O_isatty(Oobject *self, PyObject *args) {
320  return PyInt_FromLong(0);
321}
322
323static char O_close__doc__[] = "close(): explicitly release resources held.";
324
325static PyObject *
326O_close(Oobject *self, PyObject *args) {
327  if (self->buf != NULL)
328    free(self->buf);
329  self->buf = NULL;
330
331  self->pos = self->string_size = self->buf_size = 0;
332
333  Py_INCREF(Py_None);
334  return Py_None;
335}
336
337static char O_flush__doc__[] = "flush(): does nothing.";
338
339static PyObject *
340O_flush(Oobject *self, PyObject *args) {
341  Py_INCREF(Py_None);
342  return Py_None;
343}
344
345
346static char O_writelines__doc__[] =
347"writelines(sequence_of_strings): write each string";
348static PyObject *
349O_writelines(Oobject *self, PyObject *args) {
350  PyObject *string_module = 0;
351  static PyObject *string_joinfields = 0;
352
353  UNLESS(PyArg_ParseTuple(args, "O:writelines", &args)) {
354    return NULL;
355  }
356
357  if (!string_joinfields) {
358    UNLESS(string_module = PyImport_ImportModule("string")) {
359      return NULL;
360    }
361
362    UNLESS(string_joinfields=
363        PyObject_GetAttrString(string_module, "joinfields")) {
364      return NULL;
365    }
366
367    Py_DECREF(string_module);
368  }
369
370  if (PyObject_Size(args) == -1) {
371    return NULL;
372  }
373
374  {
375	  PyObject *x = PyObject_CallFunction(string_joinfields,
376					      "Os", args, "");
377	  if (x == NULL)
378		  return NULL;
379	  args = Py_BuildValue("(O)", x);
380	  Py_DECREF(x);
381	  if (args == NULL)
382		  return NULL;
383	  x = O_write(self, args);
384	  Py_DECREF(args);
385	  return x;
386  }
387}
388
389static struct PyMethodDef O_methods[] = {
390  {"write",	 (PyCFunction)O_write,      METH_VARARGS, O_write__doc__},
391  {"read",       (PyCFunction)O_read,       METH_VARARGS, O_read__doc__},
392  {"readline",   (PyCFunction)O_readline,   METH_VARARGS, O_readline__doc__},
393  {"reset",      (PyCFunction)O_reset,      METH_VARARGS, O_reset__doc__},
394  {"seek",       (PyCFunction)O_seek,       METH_VARARGS, O_seek__doc__},
395  {"tell",       (PyCFunction)O_tell,       METH_VARARGS, O_tell__doc__},
396  {"getvalue",   (PyCFunction)O_getval,     METH_VARARGS, O_getval__doc__},
397  {"truncate",   (PyCFunction)O_truncate,   METH_VARARGS, O_truncate__doc__},
398  {"isatty",     (PyCFunction)O_isatty,     METH_VARARGS, O_isatty__doc__},
399  {"close",      (PyCFunction)O_close,      METH_VARARGS, O_close__doc__},
400  {"flush",      (PyCFunction)O_flush,      METH_VARARGS, O_flush__doc__},
401  {"writelines", (PyCFunction)O_writelines, METH_VARARGS, O_writelines__doc__},
402  {NULL,	 NULL}		/* sentinel */
403};
404
405
406static void
407O_dealloc(Oobject *self) {
408  if (self->buf != NULL)
409    free(self->buf);
410  PyObject_Del(self);
411}
412
413static PyObject *
414O_getattr(Oobject *self, char *name) {
415  if (strcmp(name, "softspace") == 0) {
416	  return PyInt_FromLong(self->softspace);
417  }
418  return Py_FindMethod(O_methods, (PyObject *)self, name);
419}
420
421static int
422O_setattr(Oobject *self, char *name, PyObject *value) {
423	long x;
424	if (strcmp(name, "softspace") != 0) {
425		PyErr_SetString(PyExc_AttributeError, name);
426		return -1;
427	}
428	x = PyInt_AsLong(value);
429	if (x == -1 && PyErr_Occurred())
430		return -1;
431	self->softspace = x;
432	return 0;
433}
434
435static char Otype__doc__[] =
436"Simple type for output to strings."
437;
438
439static PyTypeObject Otype = {
440  PyObject_HEAD_INIT(NULL)
441  0,	       		/*ob_size*/
442  "StringO",     		/*tp_name*/
443  sizeof(Oobject),       	/*tp_basicsize*/
444  0,	       		/*tp_itemsize*/
445  /* methods */
446  (destructor)O_dealloc,	/*tp_dealloc*/
447  (printfunc)0,		/*tp_print*/
448  (getattrfunc)O_getattr,	/*tp_getattr*/
449  (setattrfunc)O_setattr,	/*tp_setattr*/
450  (cmpfunc)0,		/*tp_compare*/
451  (reprfunc)0,		/*tp_repr*/
452  0,			/*tp_as_number*/
453  0,			/*tp_as_sequence*/
454  0,			/*tp_as_mapping*/
455  (hashfunc)0,		/*tp_hash*/
456  (ternaryfunc)0,		/*tp_call*/
457  (reprfunc)0,		/*tp_str*/
458
459  /* Space for future expansion */
460  0L,0L,0L,0L,
461  Otype__doc__ 		/* Documentation string */
462};
463
464static PyObject *
465newOobject(int  size) {
466  Oobject *self;
467
468  self = PyObject_New(Oobject, &Otype);
469  if (self == NULL)
470    return NULL;
471  self->pos=0;
472  self->string_size = 0;
473  self->softspace = 0;
474
475  UNLESS(self->buf=malloc(size*sizeof(char))) {
476      PyErr_SetString(PyExc_MemoryError,"out of memory");
477      self->buf_size = 0;
478      return NULL;
479    }
480
481  self->buf_size=size;
482  return (PyObject*)self;
483}
484
485/* End of code for StringO objects */
486/* -------------------------------------------------------- */
487
488static PyObject *
489I_close(Iobject *self, PyObject *args) {
490  Py_XDECREF(self->pbuf);
491  self->pbuf = NULL;
492
493  self->pos = self->string_size = 0;
494
495  Py_INCREF(Py_None);
496  return Py_None;
497}
498
499static PyObject *
500I_seek(Oobject *self, PyObject *args) {
501  int position, mode = 0;
502
503  UNLESS(PyArg_ParseTuple(args, "i|i:seek", &position, &mode)) {
504    return NULL;
505  }
506
507  if (mode == 2) {
508    position += self->string_size;
509  }
510  else if (mode == 1) {
511    position += self->pos;
512  }
513
514  if(position < 0) position=0;
515
516  self->pos=position;
517
518  Py_INCREF(Py_None);
519  return Py_None;
520}
521
522static struct PyMethodDef I_methods[] = {
523  {"read",	(PyCFunction)O_read,     METH_VARARGS, O_read__doc__},
524  {"readline",	(PyCFunction)O_readline, METH_VARARGS, O_readline__doc__},
525  {"reset",	(PyCFunction)O_reset,	 METH_VARARGS, O_reset__doc__},
526  {"seek",      (PyCFunction)I_seek,     METH_VARARGS, O_seek__doc__},
527  {"tell",      (PyCFunction)O_tell,     METH_VARARGS, O_tell__doc__},
528  {"getvalue",  (PyCFunction)O_getval,   METH_VARARGS, O_getval__doc__},
529  {"truncate",  (PyCFunction)O_truncate, METH_VARARGS, O_truncate__doc__},
530  {"isatty",    (PyCFunction)O_isatty,   METH_VARARGS, O_isatty__doc__},
531  {"close",     (PyCFunction)I_close,    METH_VARARGS, O_close__doc__},
532  {"flush",     (PyCFunction)O_flush,    METH_VARARGS, O_flush__doc__},
533  {NULL,	NULL}
534};
535
536static void
537I_dealloc(Iobject *self) {
538  Py_XDECREF(self->pbuf);
539  PyObject_Del(self);
540}
541
542static PyObject *
543I_getattr(Iobject *self, char *name) {
544  return Py_FindMethod(I_methods, (PyObject *)self, name);
545}
546
547static char Itype__doc__[] =
548"Simple type for treating strings as input file streams"
549;
550
551static PyTypeObject Itype = {
552  PyObject_HEAD_INIT(NULL)
553  0,		       	/*ob_size*/
554  "StringI",	       	/*tp_name*/
555  sizeof(Iobject),       	/*tp_basicsize*/
556  0,		       	/*tp_itemsize*/
557  /* methods */
558  (destructor)I_dealloc,	/*tp_dealloc*/
559  (printfunc)0,		/*tp_print*/
560  (getattrfunc)I_getattr,	/*tp_getattr*/
561  (setattrfunc)0,		/*tp_setattr*/
562  (cmpfunc)0,		/*tp_compare*/
563  (reprfunc)0,		/*tp_repr*/
564  0,			/*tp_as_number*/
565  0,			/*tp_as_sequence*/
566  0,			/*tp_as_mapping*/
567  (hashfunc)0,		/*tp_hash*/
568  (ternaryfunc)0,		/*tp_call*/
569  (reprfunc)0,		/*tp_str*/
570
571  /* Space for future expansion */
572  0L,0L,0L,0L,
573  Itype__doc__ 		/* Documentation string */
574};
575
576static PyObject *
577newIobject(PyObject *s) {
578  Iobject *self;
579  char *buf;
580  int size;
581
582  if (!PyString_Check(s)) {
583      PyErr_Format(PyExc_TypeError, "expected string, %.200s found",
584		   s->ob_type->tp_name);
585      return NULL;
586  }
587  buf = PyString_AS_STRING(s);
588  size = PyString_GET_SIZE(s);
589  UNLESS(self = PyObject_New(Iobject, &Itype)) return NULL;
590  Py_INCREF(s);
591  self->buf=buf;
592  self->string_size=size;
593  self->pbuf=s;
594  self->pos=0;
595
596  return (PyObject*)self;
597}
598
599/* End of code for StringI objects */
600/* -------------------------------------------------------- */
601
602
603static char IO_StringIO__doc__[] =
604"StringIO([s]) -- Return a StringIO-like stream for reading or writing"
605;
606
607static PyObject *
608IO_StringIO(PyObject *self, PyObject *args) {
609  PyObject *s=0;
610
611  if (!PyArg_ParseTuple(args, "|O:StringIO", &s))
612      return NULL;
613  if(s) return newIobject(s);
614  return newOobject(128);
615}
616
617/* List of methods defined in the module */
618
619static struct PyMethodDef IO_methods[] = {
620  {"StringIO",	(PyCFunction)IO_StringIO,	1,	IO_StringIO__doc__},
621  {NULL,		NULL}		/* sentinel */
622};
623
624
625/* Initialization function for the module (*must* be called initcStringIO) */
626
627static struct PycStringIO_CAPI CAPI = {
628  O_cread,
629  O_creadline,
630  O_cwrite,
631  O_cgetval,
632  newOobject,
633  newIobject,
634  &Itype,
635  &Otype,
636};
637
638#ifndef DL_EXPORT	/* declarations for DLL import/export */
639#define DL_EXPORT(RTYPE) RTYPE
640#endif
641DL_EXPORT(void)
642initcStringIO() {
643  PyObject *m, *d, *v;
644
645
646  /* Create the module and add the functions */
647  m = Py_InitModule4("cStringIO", IO_methods,
648		     cStringIO_module_documentation,
649		     (PyObject*)NULL,PYTHON_API_VERSION);
650
651  /* Add some symbolic constants to the module */
652  d = PyModule_GetDict(m);
653
654  /* Export C API */
655  Itype.ob_type=&PyType_Type;
656  Otype.ob_type=&PyType_Type;
657  PyDict_SetItemString(d,"cStringIO_CAPI",
658		       v = PyCObject_FromVoidPtr(&CAPI,NULL));
659  Py_XDECREF(v);
660
661  /* Export Types */
662  PyDict_SetItemString(d,"InputType",  (PyObject*)&Itype);
663  PyDict_SetItemString(d,"OutputType", (PyObject*)&Otype);
664
665  /* Maybe make certain warnings go away */
666  if(0) PycString_IMPORT;
667}
668