blob: e9f8033e7e98d1b410f4394256b9c260a286fb9d [file] [log] [blame]
Guido van Rossum049cd901996-12-05 23:30:48 +00001/*
2
3 $Id$
4
5 A simple fast partial StringIO replacement.
6
7
8
9 Copyright
10
11 Copyright 1996 Digital Creations, L.C., 910 Princess Anne
12 Street, Suite 300, Fredericksburg, Virginia 22401 U.S.A. All
13 rights reserved. Copyright in this software is owned by DCLC,
14 unless otherwise indicated. Permission to use, copy and
15 distribute this software is hereby granted, provided that the
16 above copyright notice appear in all copies and that both that
17 copyright notice and this permission notice appear. Note that
18 any product, process or technology described in this software
19 may be the subject of other Intellectual Property rights
20 reserved by Digital Creations, L.C. and are not licensed
21 hereunder.
22
23 Trademarks
24
25 Digital Creations & DCLC, are trademarks of Digital Creations, L.C..
26 All other trademarks are owned by their respective companies.
27
28 No Warranty
29
30 The software is provided "as is" without warranty of any kind,
31 either express or implied, including, but not limited to, the
32 implied warranties of merchantability, fitness for a particular
33 purpose, or non-infringement. This software could include
34 technical inaccuracies or typographical errors. Changes are
35 periodically made to the software; these changes will be
36 incorporated in new editions of the software. DCLC may make
37 improvements and/or changes in this software at any time
38 without notice.
39
40 Limitation Of Liability
41
42 In no event will DCLC be liable for direct, indirect, special,
43 incidental, economic, cover, or consequential damages arising
44 out of the use of or inability to use this software even if
45 advised of the possibility of such damages. Some states do not
46 allow the exclusion or limitation of implied warranties or
47 limitation of liability for incidental or consequential
48 damages, so the above limitation or exclusion may not apply to
49 you.
50
51 If you have questions regarding this software,
52 contact:
53
54 Jim Fulton, jim@digicool.com
55 Digital Creations L.C.
56
57 (540) 371-6909
58
59
60 $Log$
61 Revision 2.1 1996/12/05 23:30:40 guido
62 Jim F's brainchild
63
64 Revision 1.6 1996/10/15 18:42:07 jim
65 Added lots of casts to make warnings go away.
66
67 Revision 1.5 1996/10/11 21:03:42 jim
68 *** empty log message ***
69
70 Revision 1.4 1996/10/11 21:02:15 jim
71 *** empty log message ***
72
73 Revision 1.3 1996/10/07 20:51:38 chris
74 *** empty log message ***
75
76 Revision 1.2 1996/07/18 13:08:34 jfulton
77 *** empty log message ***
78
79 Revision 1.1 1996/07/15 17:06:33 jfulton
80 Initial version.
81
82
83*/
84static char cStringIO_module_documentation[] =
85"A simple fast partial StringIO replacement.\n"
86"\n"
87"This module provides a simple useful replacement for\n"
88"the StringIO module that is written in C. It does not provide the\n"
89"full generality if StringIO, but it provides anough for most\n"
90"applications and is especially useful in conjuction with the\n"
91"pickle module.\n"
92"\n"
93"Usage:\n"
94"\n"
95" from cStringIO import StringIO\n"
96"\n"
97" an_output_stream=StringIO()\n"
98" an_output_stream.write(some_stuff)\n"
99" ...\n"
100" value=an_output_stream.getvalue() # str(an_output_stream) works too!\n"
101"\n"
102" an_input_stream=StringIO(a_string)\n"
103" spam=an_input_stream.readline()\n"
104" spam=an_input_stream.read(5)\n"
105" an_input_stream.reset() # OK, start over, note no seek yet\n"
106" spam=an_input_stream.read() # and read it all\n"
107" \n"
108"If someone else wants to provide a more complete implementation,\n"
109"go for it. :-) \n"
110;
111
112#include "Python.h"
113#include "import.h"
114
115static PyObject *ErrorObject;
116
117#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
118#define UNLESS(E) if(!(E))
119#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
120#define Py_ASSIGN(P,E) if(!PyObject_AssignExpression(&(P),(E))) return NULL
121
122/* ----------------------------------------------------- */
123
124/* Declarations for objects of type StringO */
125
126typedef struct {
127 PyObject_HEAD
128 char *buf;
129 int pos, string_size, buf_size, closed;
130} Oobject;
131
132staticforward PyTypeObject Otype;
133
134/* ---------------------------------------------------------------- */
135
136/* Declarations for objects of type StringI */
137
138typedef struct {
139 PyObject_HEAD
140 char *buf;
141 int pos, string_size, closed;
142 PyObject *pbuf;
143} Iobject;
144
145staticforward PyTypeObject Itype;
146
147
148
149/* ---------------------------------------------------------------- */
150
151static char O_reset__doc__[] =
152"reset() -- Reset the file position to the beginning"
153;
154
155static PyObject *
156O_reset(Oobject *self, PyObject *args)
157{
158 self->pos = 0;
159
160 Py_INCREF(Py_None);
161 return Py_None;
162}
163
164
165static char O_tell__doc__[] =
166"tell() -- get the current position.";
167
168static PyObject *
169O_tell(Oobject *self, PyObject *args)
170{
171 return PyInt_FromLong(self->pos);
172}
173
174
175static char O_seek__doc__[] =
176"seek(position) -- set the current position\n"
177"seek(position, mode) -- mode 0: absolute; 1: relative; 2: relative to EOF";
178
179static PyObject *
180O_seek(Oobject *self, PyObject *args)
181{
182 int position, mode = 0;
183
184 UNLESS(PyArg_ParseTuple(args, "i|i", &position, &mode))
185 {
186 return NULL;
187 }
188
189 if (mode == 2)
190 {
191 position += self->string_size;
192 }
193 else if (mode == 1)
194 {
195 position += self->pos;
196 }
197
198 self->pos = (position > self->string_size ? self->string_size :
199 (position < 0 ? 0 : position));
200
201 return PyInt_FromLong(self->pos);
202}
203
204static char O_read__doc__[] =
205"read([s]) -- Read s characters, or the rest of the string"
206;
207
208static int
209O_cread(Oobject *self, char **output, int n)
210{
211 int l;
212
213 l = self->string_size - self->pos;
214 if (n < 0 || n > l)
215 {
216 n = l;
217 }
218
219 *output=self->buf + self->pos;
220 self->pos += n;
221 return n;
222}
223
224static PyObject *
225O_read(Oobject *self, PyObject *args)
226{
227 int n = -1;
228 char *output;
229
230 UNLESS(PyArg_ParseTuple(args, "|i", &n)) return NULL;
231
232 n=O_cread(self,&output,n);
233
234 return PyString_FromStringAndSize(output, n);
235}
236
237
238static char O_readline__doc__[] =
239"readline() -- Read one line"
240;
241
242static int
243O_creadline(Oobject *self, char **output)
244{
245 char *n, *s;
246 int l;
247
248 for (n = self->buf + self->pos, s = self->buf + self->string_size;
249 n < s && *n != '\n'; n++);
250 if (n < s) n++;
251
252 *output=self->buf + self->pos;
253 l = n - self->buf - self->pos;
254 self->pos += l;
255 return l;
256}
257
258static PyObject *
259O_readline(Oobject *self, PyObject *args)
260{
261 int n;
262 char *output;
263
264 n=O_creadline(self,&output);
265 return PyString_FromStringAndSize(output, n);
266}
267
268static char O_write__doc__[] =
269"write(s) -- Write a string to the file"
270"\n\nNote (hack:) writing None resets the buffer"
271;
272
273
274static int
275O_cwrite(Oobject *self, char *c, int l)
276{
277 int newl;
278 newl=self->pos+l;
279 if(newl > self->buf_size)
280 {
281 self->buf_size*=2;
282 if(self->buf_size < newl) self->buf_size=newl;
283 UNLESS(self->buf=(char*)realloc(self->buf, self->buf_size*sizeof(char)))
284 {
285 PyErr_SetString(PyExc_MemoryError,"out of memory");
286 self->buf_size=self->pos=0;
287 return -1;
288 }
289 }
290
291 memcpy(self->buf+self->pos,c,l);
292
293 self->pos += l;
294
295 if (self->string_size < self->pos)
296 {
297 self->string_size = self->pos;
298 }
299
300 return l;
301}
302
303static PyObject *
304O_write(Oobject *self, PyObject *args)
305{
306 PyObject *s;
307 char *c;
308 int l;
309
310 UNLESS(PyArg_Parse(args, "O", &s)) return NULL;
311 if(s!=Py_None)
312 {
313 UNLESS(-1 != (l=PyString_Size(s))) return NULL;
314 UNLESS(c=PyString_AsString(s)) return NULL;
315 UNLESS(-1 != O_cwrite(self,c,l)) return NULL;
316 }
317 else
318 {
319 self->pos=0;
320 self->string_size = 0;
321 }
322
323 Py_INCREF(self);
324 return (PyObject *)self;
325}
326
327static PyObject *
328O_repr(self)
329 Oobject *self;
330{
331 return PyString_FromStringAndSize(self->buf,self->string_size);
332}
333
334static PyObject *
335O_getval(self,args)
336 Oobject *self;
337 PyObject *args;
338{
339 return PyString_FromStringAndSize(self->buf,self->pos);
340}
341
342static char O_truncate__doc__[] =
343"truncate(): truncate the file at the current position.";
344
345static PyObject *
346O_truncate(self, args)
347 Oobject *self;
348 PyObject *args;
349{
350 self->string_size = self->pos;
351 Py_INCREF(Py_None);
352 return Py_None;
353}
354
355static char O_isatty__doc__[] = "isatty(): always returns 0";
356
357static PyObject *
358O_isatty(self, args)
359 Oobject *self;
360 PyObject *args;
361{
362 return PyInt_FromLong(0);
363}
364
365static char O_close__doc__[] = "close(): explicitly release resources held.";
366
367static PyObject *
368O_close(self, args)
369 Oobject *self;
370 PyObject *args;
371{
372 free(self->buf);
373
374 self->pos = self->string_size = self->buf_size = 0;
375 self->closed = 1;
376
377 Py_INCREF(Py_None);
378 return Py_None;
379}
380
381static char O_flush__doc__[] = "flush(): does nothing.";
382
383static PyObject *
384O_flush(self, args)
385 Oobject *self;
386 PyObject *args;
387{
388 Py_INCREF(Py_None);
389 return Py_None;
390}
391
392
393static char O_writelines__doc__[] = "blah";
394static PyObject *
395O_writelines(self, args)
396 Oobject *self;
397 PyObject *args;
398{
399 PyObject *string_module = 0;
400 static PyObject *string_joinfields = 0;
401
402 UNLESS(PyArg_Parse(args, "O", args))
403 {
404 return NULL;
405 }
406
407 if (!string_joinfields)
408 {
409 UNLESS(string_module = PyImport_ImportModule("string"))
410 {
411 return NULL;
412 }
413
414 UNLESS(string_joinfields=
415 PyObject_GetAttrString(string_module, "joinfields"))
416 {
417 return NULL;
418 }
419
420 Py_DECREF(string_module);
421 }
422
423 if (PyObject_Length(args) == -1)
424 {
425 return NULL;
426 }
427
428 return O_write(self,
429 PyObject_CallFunction(string_joinfields, "Os", args, ""));
430}
431
432static struct PyMethodDef O_methods[] = {
433 {"read", (PyCFunction)O_read, 1, O_read__doc__},
434 {"readline", (PyCFunction)O_readline, 0, O_readline__doc__},
435 {"write", (PyCFunction)O_write, 0, O_write__doc__},
436 {"reset", (PyCFunction)O_reset, 0, O_reset__doc__},
437 {"seek", (PyCFunction)O_seek, 1, O_seek__doc__},
438 {"tell", (PyCFunction)O_tell, 0, O_tell__doc__},
439 {"getvalue", (PyCFunction)O_getval, 0, "getvalue() -- Get the string value"},
440 {"truncate", (PyCFunction)O_truncate, 0, O_truncate__doc__},
441 {"isatty", (PyCFunction)O_isatty, 0, O_isatty__doc__},
442 {"close", (PyCFunction)O_close, 0, O_close__doc__},
443 {"flush", (PyCFunction)O_flush, 0, O_flush__doc__},
444 {"writelines", (PyCFunction)O_writelines, 0, O_writelines__doc__},
445 {NULL, NULL} /* sentinel */
446};
447
448/* ---------- */
449
450
451static Oobject *
452newOobject(int size)
453{
454 Oobject *self;
455
456 self = PyObject_NEW(Oobject, &Otype);
457 if (self == NULL)
458 return NULL;
459 self->pos=0;
460 self->closed = 0;
461 self->string_size = 0;
462
463 UNLESS(self->buf=malloc(size*sizeof(char)))
464 {
465 PyErr_SetString(PyExc_MemoryError,"out of memory");
466 self->buf_size = 0;
467 return NULL;
468 }
469
470 self->buf_size=size;
471 return self;
472}
473
474
475static void
476O_dealloc(self)
477 Oobject *self;
478{
479 free(self->buf);
480 PyMem_DEL(self);
481}
482
483static PyObject *
484O_getattr(self, name)
485 Oobject *self;
486 char *name;
487{
488 return Py_FindMethod(O_methods, (PyObject *)self, name);
489}
490
491static char Otype__doc__[] =
492"Simple type for output to strings."
493;
494
495static PyTypeObject Otype = {
496 PyObject_HEAD_INIT(&PyType_Type)
497 0, /*ob_size*/
498 "StringO", /*tp_name*/
499 sizeof(Oobject), /*tp_basicsize*/
500 0, /*tp_itemsize*/
501 /* methods */
502 (destructor)O_dealloc, /*tp_dealloc*/
503 (printfunc)0, /*tp_print*/
504 (getattrfunc)O_getattr, /*tp_getattr*/
505 (setattrfunc)0, /*tp_setattr*/
506 (cmpfunc)0, /*tp_compare*/
507 (reprfunc)O_repr, /*tp_repr*/
508 0, /*tp_as_number*/
509 0, /*tp_as_sequence*/
510 0, /*tp_as_mapping*/
511 (hashfunc)0, /*tp_hash*/
512 (ternaryfunc)0, /*tp_call*/
513 (reprfunc)0, /*tp_str*/
514
515 /* Space for future expansion */
516 0L,0L,0L,0L,
517 Otype__doc__ /* Documentation string */
518};
519
520/* End of code for StringO objects */
521/* -------------------------------------------------------- */
522
523static PyObject *
524I_close(self, args)
525 Iobject *self;
526 PyObject *args;
527{
528 Py_DECREF(self->pbuf);
529
530 self->pos = self->string_size = 0;
531 self->closed = 1;
532
533 Py_INCREF(Py_None);
534 return Py_None;
535}
536
537static struct PyMethodDef I_methods[] = {
538 {"read", (PyCFunction)O_read, 1, O_read__doc__},
539 {"readline", (PyCFunction)O_readline, 0, O_readline__doc__},
540 {"reset", (PyCFunction)O_reset, 0, O_reset__doc__},
541 {"seek", (PyCFunction)O_seek, 1, O_seek__doc__},
542 {"tell", (PyCFunction)O_tell, 0, O_tell__doc__},
543 {"truncate", (PyCFunction)O_truncate, 0, O_truncate__doc__},
544 {"isatty", (PyCFunction)O_isatty, 0, O_isatty__doc__},
545 {"close", (PyCFunction)I_close, 0, O_close__doc__},
546 {"flush", (PyCFunction)O_flush, 0, O_flush__doc__},
547 {NULL, NULL} /* sentinel */
548};
549
550/* ---------- */
551
552
553static Iobject *
554newIobject(PyObject *s)
555{
556 Iobject *self;
557 char *buf;
558 int size;
559
560 UNLESS(buf=PyString_AsString(s)) return NULL;
561 UNLESS(-1 != (size=PyString_Size(s))) return NULL;
562 UNLESS(self = PyObject_NEW(Iobject, &Itype)) return NULL;
563 Py_INCREF(s);
564 self->buf=buf;
565 self->string_size=size;
566 self->pbuf=s;
567 self->pos=0;
568 self->closed = 0;
569
570 return self;
571}
572
573
574static void
575I_dealloc(self)
576 Iobject *self;
577{
578 Py_DECREF(self->pbuf);
579 PyMem_DEL(self);
580}
581
582static PyObject *
583I_getattr(self, name)
584 Iobject *self;
585 char *name;
586{
587 return Py_FindMethod(I_methods, (PyObject *)self, name);
588}
589
590static char Itype__doc__[] =
591"Simple type for treating strings as input file streams"
592;
593
594static PyTypeObject Itype = {
595 PyObject_HEAD_INIT(&PyType_Type)
596 0, /*ob_size*/
597 "StringI", /*tp_name*/
598 sizeof(Iobject), /*tp_basicsize*/
599 0, /*tp_itemsize*/
600 /* methods */
601 (destructor)I_dealloc, /*tp_dealloc*/
602 (printfunc)0, /*tp_print*/
603 (getattrfunc)I_getattr, /*tp_getattr*/
604 (setattrfunc)0, /*tp_setattr*/
605 (cmpfunc)0, /*tp_compare*/
606 (reprfunc)0, /*tp_repr*/
607 0, /*tp_as_number*/
608 0, /*tp_as_sequence*/
609 0, /*tp_as_mapping*/
610 (hashfunc)0, /*tp_hash*/
611 (ternaryfunc)0, /*tp_call*/
612 (reprfunc)0, /*tp_str*/
613
614 /* Space for future expansion */
615 0L,0L,0L,0L,
616 Itype__doc__ /* Documentation string */
617};
618
619/* End of code for StringI objects */
620/* -------------------------------------------------------- */
621
622
623static char IO_StringIO__doc__[] =
624"StringIO([s]) -- Return a StringIO-like stream for reading or writing"
625;
626
627static PyObject *
628IO_StringIO(self, args)
629 PyObject *self; /* Not used */
630 PyObject *args;
631{
632 PyObject *s=0;
633
634 UNLESS(PyArg_ParseTuple(args, "|O", &s)) return NULL;
635 if(s) return (PyObject *)newIobject(s);
636 return (PyObject *)newOobject(128);
637}
638
639/* List of methods defined in the module */
640
641static struct PyMethodDef IO_methods[] = {
642 {"StringIO", (PyCFunction)IO_StringIO, 1, IO_StringIO__doc__},
643 {NULL, NULL} /* sentinel */
644};
645
646
647/* Initialization function for the module (*must* be called initcStringIO) */
648
649void
650initcStringIO()
651{
652 PyObject *m, *d;
653
654 /* Create the module and add the functions */
655 m = Py_InitModule4("cStringIO", IO_methods,
656 cStringIO_module_documentation,
657 (PyObject*)NULL,PYTHON_API_VERSION);
658
659 /* Add some symbolic constants to the module */
660 d = PyModule_GetDict(m);
661 ErrorObject = PyString_FromString("cStringIO.error");
662 PyDict_SetItemString(d, "error", ErrorObject);
663
664 PyDict_SetItemString(d,"cread", PyCObject_FromVoidPtr(O_cread,NULL));
665 PyDict_SetItemString(d,"creadline", PyCObject_FromVoidPtr(O_creadline,NULL));
666 PyDict_SetItemString(d,"cwrite", PyCObject_FromVoidPtr(O_cwrite,NULL));
667 PyDict_SetItemString(d,"cgetvalue", PyCObject_FromVoidPtr(O_getval,NULL));
668 PyDict_SetItemString(d,"NewInput", PyCObject_FromVoidPtr(newIobject,NULL));
669 PyDict_SetItemString(d,"NewOutput", PyCObject_FromVoidPtr(newOobject,NULL));
670
671 PyDict_SetItemString(d,"InputType", (PyObject*)&Itype);
672 PyDict_SetItemString(d,"OutputType", (PyObject*)&Otype);
673
674
675 /* Check for errors */
676 if (PyErr_Occurred())
677 Py_FatalError("can't initialize module cStringIO");
678}