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