cStringIO.c revision c912a3a8fd353fab8d075f0d449703b9174ec2b1
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 conjunction 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_readlines__doc__[] =
228"readlines() -- Read all lines"
229;
230
231static PyObject *
232O_readlines(Oobject *self, PyObject *args) {
233	int n;
234	char *output;
235	PyObject *result, *line;
236        int hint = 0, length = 0;
237
238        UNLESS(PyArg_ParseTuple(args, "|i:write", &hint)) return NULL;
239	result = PyList_New(0);
240	if (!result)
241		return NULL;
242
243	while(1){
244		n = O_creadline((PyObject*)self,&output);
245		if (n == 0)
246			break;
247		line = PyString_FromStringAndSize (output, n);
248		if (!line){
249			Py_DECREF (result);
250			return NULL;
251		}
252		PyList_Append (result, line);
253		Py_DECREF (line);
254                length += n;
255                if (hint > 0 && length >= hint)
256			break;
257	}
258	return result;
259}
260
261static char O_write__doc__[] =
262"write(s) -- Write a string to the file"
263"\n\nNote (hack:) writing None resets the buffer"
264;
265
266
267static int
268O_cwrite(PyObject *self, char *c, int  l) {
269  int newl;
270
271  newl=((Oobject*)self)->pos+l;
272  if(newl >= ((Oobject*)self)->buf_size) {
273      ((Oobject*)self)->buf_size*=2;
274      if(((Oobject*)self)->buf_size <= newl) ((Oobject*)self)->buf_size=newl+1;
275      UNLESS(((Oobject*)self)->buf=
276	     (char*)realloc(((Oobject*)self)->buf,
277			    (((Oobject*)self)->buf_size) *sizeof(char))) {
278	  PyErr_SetString(PyExc_MemoryError,"out of memory");
279	  ((Oobject*)self)->buf_size=((Oobject*)self)->pos=0;
280	  return -1;
281	}
282    }
283
284  memcpy(((Oobject*)((Oobject*)self))->buf+((Oobject*)self)->pos,c,l);
285
286  ((Oobject*)self)->pos += l;
287
288  if (((Oobject*)self)->string_size < ((Oobject*)self)->pos) {
289      ((Oobject*)self)->string_size = ((Oobject*)self)->pos;
290    }
291
292  return l;
293}
294
295static PyObject *
296O_write(Oobject *self, PyObject *args) {
297  PyObject *s;
298  char *c;
299  int l;
300
301  UNLESS(PyArg_ParseTuple(args, "O:write", &s)) return NULL;
302  UNLESS(-1 != (l=PyString_Size(s))) return NULL;
303  UNLESS(c=PyString_AsString(s)) return NULL;
304  UNLESS(-1 != O_cwrite((PyObject*)self,c,l)) return NULL;
305
306  Py_INCREF(Py_None);
307  return Py_None;
308}
309
310static char O_getval__doc__[] =
311   "getvalue([use_pos]) -- Get the string value."
312   "\n"
313   "If use_pos is specified and is a true value, then the string returned\n"
314   "will include only the text up to the current file position.\n"
315;
316
317static PyObject *
318O_getval(Oobject *self, PyObject *args) {
319  PyObject *use_pos=Py_None;
320  int s;
321
322  use_pos=Py_None;
323  UNLESS(PyArg_ParseTuple(args,"|O:getval",&use_pos)) return NULL;
324  if(PyObject_IsTrue(use_pos)) {
325      s=self->pos;
326      if (s > self->string_size) s=self->string_size;
327  }
328  else
329      s=self->string_size;
330  return PyString_FromStringAndSize(self->buf, s);
331}
332
333static PyObject *
334O_cgetval(PyObject *self) {
335  return PyString_FromStringAndSize(((Oobject*)self)->buf,
336				    ((Oobject*)self)->pos);
337}
338
339static char O_truncate__doc__[] =
340"truncate(): truncate the file at the current position.";
341
342static PyObject *
343O_truncate(Oobject *self, PyObject *args) {
344  if (self->string_size > self->pos)
345      self->string_size = self->pos;
346  Py_INCREF(Py_None);
347  return Py_None;
348}
349
350static char O_isatty__doc__[] = "isatty(): always returns 0";
351
352static PyObject *
353O_isatty(Oobject *self, PyObject *args) {
354  return PyInt_FromLong(0);
355}
356
357static char O_close__doc__[] = "close(): explicitly release resources held.";
358
359static PyObject *
360O_close(Oobject *self, PyObject *args) {
361  if (self->buf != NULL)
362    free(self->buf);
363  self->buf = NULL;
364
365  self->pos = self->string_size = self->buf_size = 0;
366
367  Py_INCREF(Py_None);
368  return Py_None;
369}
370
371static char O_flush__doc__[] = "flush(): does nothing.";
372
373static PyObject *
374O_flush(Oobject *self, PyObject *args) {
375  Py_INCREF(Py_None);
376  return Py_None;
377}
378
379
380static char O_writelines__doc__[] =
381"writelines(sequence_of_strings): write each string";
382static PyObject *
383O_writelines(Oobject *self, PyObject *args) {
384  PyObject *string_module = 0;
385  static PyObject *string_joinfields = 0;
386
387  UNLESS(PyArg_ParseTuple(args, "O:writelines", &args)) {
388    return NULL;
389  }
390
391  if (!string_joinfields) {
392    UNLESS(string_module = PyImport_ImportModule("string")) {
393      return NULL;
394    }
395
396    UNLESS(string_joinfields=
397        PyObject_GetAttrString(string_module, "joinfields")) {
398      return NULL;
399    }
400
401    Py_DECREF(string_module);
402  }
403
404  if (PyObject_Size(args) == -1) {
405    return NULL;
406  }
407
408  {
409	  PyObject *x = PyObject_CallFunction(string_joinfields,
410					      "Os", args, "");
411	  if (x == NULL)
412		  return NULL;
413	  args = Py_BuildValue("(O)", x);
414	  Py_DECREF(x);
415	  if (args == NULL)
416		  return NULL;
417	  x = O_write(self, args);
418	  Py_DECREF(args);
419	  return x;
420  }
421}
422
423static struct PyMethodDef O_methods[] = {
424  {"write",	 (PyCFunction)O_write,      METH_VARARGS, O_write__doc__},
425  {"read",       (PyCFunction)O_read,       METH_VARARGS, O_read__doc__},
426  {"readline",   (PyCFunction)O_readline,   METH_VARARGS, O_readline__doc__},
427  {"readlines",  (PyCFunction)O_readlines,  METH_VARARGS, O_readlines__doc__},
428  {"reset",      (PyCFunction)O_reset,      METH_VARARGS, O_reset__doc__},
429  {"seek",       (PyCFunction)O_seek,       METH_VARARGS, O_seek__doc__},
430  {"tell",       (PyCFunction)O_tell,       METH_VARARGS, O_tell__doc__},
431  {"getvalue",   (PyCFunction)O_getval,     METH_VARARGS, O_getval__doc__},
432  {"truncate",   (PyCFunction)O_truncate,   METH_VARARGS, O_truncate__doc__},
433  {"isatty",     (PyCFunction)O_isatty,     METH_VARARGS, O_isatty__doc__},
434  {"close",      (PyCFunction)O_close,      METH_VARARGS, O_close__doc__},
435  {"flush",      (PyCFunction)O_flush,      METH_VARARGS, O_flush__doc__},
436  {"writelines", (PyCFunction)O_writelines, METH_VARARGS, O_writelines__doc__},
437  {NULL,	 NULL}		/* sentinel */
438};
439
440
441static void
442O_dealloc(Oobject *self) {
443  if (self->buf != NULL)
444    free(self->buf);
445  PyObject_Del(self);
446}
447
448static PyObject *
449O_getattr(Oobject *self, char *name) {
450  if (strcmp(name, "softspace") == 0) {
451	  return PyInt_FromLong(self->softspace);
452  }
453  return Py_FindMethod(O_methods, (PyObject *)self, name);
454}
455
456static int
457O_setattr(Oobject *self, char *name, PyObject *value) {
458	long x;
459	if (strcmp(name, "softspace") != 0) {
460		PyErr_SetString(PyExc_AttributeError, name);
461		return -1;
462	}
463	x = PyInt_AsLong(value);
464	if (x == -1 && PyErr_Occurred())
465		return -1;
466	self->softspace = x;
467	return 0;
468}
469
470static char Otype__doc__[] =
471"Simple type for output to strings."
472;
473
474static PyTypeObject Otype = {
475  PyObject_HEAD_INIT(NULL)
476  0,	       		/*ob_size*/
477  "StringO",     		/*tp_name*/
478  sizeof(Oobject),       	/*tp_basicsize*/
479  0,	       		/*tp_itemsize*/
480  /* methods */
481  (destructor)O_dealloc,	/*tp_dealloc*/
482  (printfunc)0,		/*tp_print*/
483  (getattrfunc)O_getattr,	/*tp_getattr*/
484  (setattrfunc)O_setattr,	/*tp_setattr*/
485  (cmpfunc)0,		/*tp_compare*/
486  (reprfunc)0,		/*tp_repr*/
487  0,			/*tp_as_number*/
488  0,			/*tp_as_sequence*/
489  0,			/*tp_as_mapping*/
490  (hashfunc)0,		/*tp_hash*/
491  (ternaryfunc)0,		/*tp_call*/
492  (reprfunc)0,		/*tp_str*/
493
494  /* Space for future expansion */
495  0L,0L,0L,0L,
496  Otype__doc__ 		/* Documentation string */
497};
498
499static PyObject *
500newOobject(int  size) {
501  Oobject *self;
502
503  self = PyObject_New(Oobject, &Otype);
504  if (self == NULL)
505    return NULL;
506  self->pos=0;
507  self->string_size = 0;
508  self->softspace = 0;
509
510  UNLESS(self->buf=malloc(size*sizeof(char))) {
511      PyErr_SetString(PyExc_MemoryError,"out of memory");
512      self->buf_size = 0;
513      return NULL;
514    }
515
516  self->buf_size=size;
517  return (PyObject*)self;
518}
519
520/* End of code for StringO objects */
521/* -------------------------------------------------------- */
522
523static PyObject *
524I_close(Iobject *self, PyObject *args) {
525  Py_XDECREF(self->pbuf);
526  self->pbuf = NULL;
527
528  self->pos = self->string_size = 0;
529
530  Py_INCREF(Py_None);
531  return Py_None;
532}
533
534static PyObject *
535I_seek(Oobject *self, PyObject *args) {
536  int position, mode = 0;
537
538  UNLESS(PyArg_ParseTuple(args, "i|i:seek", &position, &mode)) {
539    return NULL;
540  }
541
542  if (mode == 2) {
543    position += self->string_size;
544  }
545  else if (mode == 1) {
546    position += self->pos;
547  }
548
549  if(position < 0) position=0;
550
551  self->pos=position;
552
553  Py_INCREF(Py_None);
554  return Py_None;
555}
556
557static struct PyMethodDef I_methods[] = {
558  {"read",	(PyCFunction)O_read,     METH_VARARGS, O_read__doc__},
559  {"readline",	(PyCFunction)O_readline, METH_VARARGS, O_readline__doc__},
560  {"readlines",	(PyCFunction)O_readlines,METH_VARARGS, O_readlines__doc__},
561  {"reset",	(PyCFunction)O_reset,	 METH_VARARGS, O_reset__doc__},
562  {"seek",      (PyCFunction)I_seek,     METH_VARARGS, O_seek__doc__},
563  {"tell",      (PyCFunction)O_tell,     METH_VARARGS, O_tell__doc__},
564  {"getvalue",  (PyCFunction)O_getval,   METH_VARARGS, O_getval__doc__},
565  {"truncate",  (PyCFunction)O_truncate, METH_VARARGS, O_truncate__doc__},
566  {"isatty",    (PyCFunction)O_isatty,   METH_VARARGS, O_isatty__doc__},
567  {"close",     (PyCFunction)I_close,    METH_VARARGS, O_close__doc__},
568  {"flush",     (PyCFunction)O_flush,    METH_VARARGS, O_flush__doc__},
569  {NULL,	NULL}
570};
571
572static void
573I_dealloc(Iobject *self) {
574  Py_XDECREF(self->pbuf);
575  PyObject_Del(self);
576}
577
578static PyObject *
579I_getattr(Iobject *self, char *name) {
580  return Py_FindMethod(I_methods, (PyObject *)self, name);
581}
582
583static char Itype__doc__[] =
584"Simple type for treating strings as input file streams"
585;
586
587static PyTypeObject Itype = {
588  PyObject_HEAD_INIT(NULL)
589  0,		       	/*ob_size*/
590  "StringI",	       	/*tp_name*/
591  sizeof(Iobject),       	/*tp_basicsize*/
592  0,		       	/*tp_itemsize*/
593  /* methods */
594  (destructor)I_dealloc,	/*tp_dealloc*/
595  (printfunc)0,		/*tp_print*/
596  (getattrfunc)I_getattr,	/*tp_getattr*/
597  (setattrfunc)0,		/*tp_setattr*/
598  (cmpfunc)0,		/*tp_compare*/
599  (reprfunc)0,		/*tp_repr*/
600  0,			/*tp_as_number*/
601  0,			/*tp_as_sequence*/
602  0,			/*tp_as_mapping*/
603  (hashfunc)0,		/*tp_hash*/
604  (ternaryfunc)0,		/*tp_call*/
605  (reprfunc)0,		/*tp_str*/
606
607  /* Space for future expansion */
608  0L,0L,0L,0L,
609  Itype__doc__ 		/* Documentation string */
610};
611
612static PyObject *
613newIobject(PyObject *s) {
614  Iobject *self;
615  char *buf;
616  int size;
617
618  if (!PyString_Check(s)) {
619      PyErr_Format(PyExc_TypeError, "expected string, %.200s found",
620		   s->ob_type->tp_name);
621      return NULL;
622  }
623  buf = PyString_AS_STRING(s);
624  size = PyString_GET_SIZE(s);
625  UNLESS(self = PyObject_New(Iobject, &Itype)) return NULL;
626  Py_INCREF(s);
627  self->buf=buf;
628  self->string_size=size;
629  self->pbuf=s;
630  self->pos=0;
631
632  return (PyObject*)self;
633}
634
635/* End of code for StringI objects */
636/* -------------------------------------------------------- */
637
638
639static char IO_StringIO__doc__[] =
640"StringIO([s]) -- Return a StringIO-like stream for reading or writing"
641;
642
643static PyObject *
644IO_StringIO(PyObject *self, PyObject *args) {
645  PyObject *s=0;
646
647  if (!PyArg_ParseTuple(args, "|O:StringIO", &s))
648      return NULL;
649  if(s) return newIobject(s);
650  return newOobject(128);
651}
652
653/* List of methods defined in the module */
654
655static struct PyMethodDef IO_methods[] = {
656  {"StringIO",	(PyCFunction)IO_StringIO,
657   METH_VARARGS,	IO_StringIO__doc__},
658  {NULL,		NULL}		/* sentinel */
659};
660
661
662/* Initialization function for the module (*must* be called initcStringIO) */
663
664static struct PycStringIO_CAPI CAPI = {
665  O_cread,
666  O_creadline,
667  O_cwrite,
668  O_cgetval,
669  newOobject,
670  newIobject,
671  &Itype,
672  &Otype,
673};
674
675#ifndef DL_EXPORT	/* declarations for DLL import/export */
676#define DL_EXPORT(RTYPE) RTYPE
677#endif
678DL_EXPORT(void)
679initcStringIO(void) {
680  PyObject *m, *d, *v;
681
682
683  /* Create the module and add the functions */
684  m = Py_InitModule4("cStringIO", IO_methods,
685		     cStringIO_module_documentation,
686		     (PyObject*)NULL,PYTHON_API_VERSION);
687
688  /* Add some symbolic constants to the module */
689  d = PyModule_GetDict(m);
690
691  /* Export C API */
692  Itype.ob_type=&PyType_Type;
693  Otype.ob_type=&PyType_Type;
694  PyDict_SetItemString(d,"cStringIO_CAPI",
695		       v = PyCObject_FromVoidPtr(&CAPI,NULL));
696  Py_XDECREF(v);
697
698  /* Export Types */
699  PyDict_SetItemString(d,"InputType",  (PyObject*)&Itype);
700  PyDict_SetItemString(d,"OutputType", (PyObject*)&Otype);
701
702  /* Maybe make certain warnings go away */
703  if(0) PycString_IMPORT;
704}
705