cStringIO.c revision 7e47402264cf87b9bbb61fc9ff610af08add7c7b
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_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