~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Objects/fileobject.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* File object implementation (what's left of it -- see io.py) */
 
2
 
 
3
#define PY_SSIZE_T_CLEAN
 
4
#include "Python.h"
 
5
 
 
6
#ifdef HAVE_GETC_UNLOCKED
 
7
#define GETC(f) getc_unlocked(f)
 
8
#define FLOCKFILE(f) flockfile(f)
 
9
#define FUNLOCKFILE(f) funlockfile(f)
 
10
#else
 
11
#define GETC(f) getc(f)
 
12
#define FLOCKFILE(f)
 
13
#define FUNLOCKFILE(f)
 
14
#endif
 
15
 
 
16
/* Newline flags */
 
17
#define NEWLINE_UNKNOWN 0       /* No newline seen, yet */
 
18
#define NEWLINE_CR 1            /* \r newline seen */
 
19
#define NEWLINE_LF 2            /* \n newline seen */
 
20
#define NEWLINE_CRLF 4          /* \r\n newline seen */
 
21
 
 
22
#ifdef __cplusplus
 
23
extern "C" {
 
24
#endif
 
25
 
 
26
/* External C interface */
 
27
 
 
28
PyObject *
 
29
PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding,
 
30
              char *errors, char *newline, int closefd)
 
31
{
 
32
        PyObject *io, *stream, *nameobj = NULL;
 
33
 
 
34
        io = PyImport_ImportModule("io");
 
35
        if (io == NULL)
 
36
                return NULL;
 
37
        stream = PyObject_CallMethod(io, "open", "isisssi", fd, mode,
 
38
                                     buffering, encoding, errors,
 
39
                                     newline, closefd);
 
40
        Py_DECREF(io);
 
41
        if (stream == NULL)
 
42
                return NULL;
 
43
        if (name != NULL) {
 
44
                nameobj = PyUnicode_FromString(name);
 
45
                if (nameobj == NULL)
 
46
                        PyErr_Clear();
 
47
                else {
 
48
                        if (PyObject_SetAttrString(stream, "name", nameobj) < 0)
 
49
                                PyErr_Clear();
 
50
                        Py_DECREF(nameobj);
 
51
                }
 
52
        }
 
53
        return stream;
 
54
}
 
55
 
 
56
PyObject *
 
57
PyFile_GetLine(PyObject *f, int n)
 
58
{
 
59
        PyObject *result;
 
60
 
 
61
        if (f == NULL) {
 
62
                PyErr_BadInternalCall();
 
63
                return NULL;
 
64
        }
 
65
 
 
66
        {
 
67
                PyObject *reader;
 
68
                PyObject *args;
 
69
 
 
70
                reader = PyObject_GetAttrString(f, "readline");
 
71
                if (reader == NULL)
 
72
                        return NULL;
 
73
                if (n <= 0)
 
74
                        args = PyTuple_New(0);
 
75
                else
 
76
                        args = Py_BuildValue("(i)", n);
 
77
                if (args == NULL) {
 
78
                        Py_DECREF(reader);
 
79
                        return NULL;
 
80
                }
 
81
                result = PyEval_CallObject(reader, args);
 
82
                Py_DECREF(reader);
 
83
                Py_DECREF(args);
 
84
                if (result != NULL && !PyBytes_Check(result) &&
 
85
                    !PyUnicode_Check(result)) {
 
86
                        Py_DECREF(result);
 
87
                        result = NULL;
 
88
                        PyErr_SetString(PyExc_TypeError,
 
89
                                   "object.readline() returned non-string");
 
90
                }
 
91
        }
 
92
 
 
93
        if (n < 0 && result != NULL && PyBytes_Check(result)) {
 
94
                char *s = PyBytes_AS_STRING(result);
 
95
                Py_ssize_t len = PyBytes_GET_SIZE(result);
 
96
                if (len == 0) {
 
97
                        Py_DECREF(result);
 
98
                        result = NULL;
 
99
                        PyErr_SetString(PyExc_EOFError,
 
100
                                        "EOF when reading a line");
 
101
                }
 
102
                else if (s[len-1] == '\n') {
 
103
                        if (result->ob_refcnt == 1)
 
104
                                _PyBytes_Resize(&result, len-1);
 
105
                        else {
 
106
                                PyObject *v;
 
107
                                v = PyBytes_FromStringAndSize(s, len-1);
 
108
                                Py_DECREF(result);
 
109
                                result = v;
 
110
                        }
 
111
                }
 
112
        }
 
113
        if (n < 0 && result != NULL && PyUnicode_Check(result)) {
 
114
                Py_UNICODE *s = PyUnicode_AS_UNICODE(result);
 
115
                Py_ssize_t len = PyUnicode_GET_SIZE(result);
 
116
                if (len == 0) {
 
117
                        Py_DECREF(result);
 
118
                        result = NULL;
 
119
                        PyErr_SetString(PyExc_EOFError,
 
120
                                        "EOF when reading a line");
 
121
                }
 
122
                else if (s[len-1] == '\n') {
 
123
                        if (result->ob_refcnt == 1)
 
124
                                PyUnicode_Resize(&result, len-1);
 
125
                        else {
 
126
                                PyObject *v;
 
127
                                v = PyUnicode_FromUnicode(s, len-1);
 
128
                                Py_DECREF(result);
 
129
                                result = v;
 
130
                        }
 
131
                }
 
132
        }
 
133
        return result;
 
134
}
 
135
 
 
136
/* Interfaces to write objects/strings to file-like objects */
 
137
 
 
138
int
 
139
PyFile_WriteObject(PyObject *v, PyObject *f, int flags)
 
140
{
 
141
        PyObject *writer, *value, *args, *result;
 
142
        if (f == NULL) {
 
143
                PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");
 
144
                return -1;
 
145
        }
 
146
        writer = PyObject_GetAttrString(f, "write");
 
147
        if (writer == NULL)
 
148
                return -1;
 
149
        if (flags & Py_PRINT_RAW) {
 
150
                value = PyObject_Str(v);
 
151
        }
 
152
        else
 
153
                value = PyObject_Repr(v);
 
154
        if (value == NULL) {
 
155
                Py_DECREF(writer);
 
156
                return -1;
 
157
        }
 
158
        args = PyTuple_Pack(1, value);
 
159
        if (args == NULL) {
 
160
                Py_DECREF(value);
 
161
                Py_DECREF(writer);
 
162
                return -1;
 
163
        }
 
164
        result = PyEval_CallObject(writer, args);
 
165
        Py_DECREF(args);
 
166
        Py_DECREF(value);
 
167
        Py_DECREF(writer);
 
168
        if (result == NULL)
 
169
                return -1;
 
170
        Py_DECREF(result);
 
171
        return 0;
 
172
}
 
173
 
 
174
int
 
175
PyFile_WriteString(const char *s, PyObject *f)
 
176
{
 
177
        if (f == NULL) {
 
178
                /* Should be caused by a pre-existing error */
 
179
                if (!PyErr_Occurred())
 
180
                        PyErr_SetString(PyExc_SystemError,
 
181
                                        "null file for PyFile_WriteString");
 
182
                return -1;
 
183
        }
 
184
        else if (!PyErr_Occurred()) {
 
185
                PyObject *v = PyUnicode_FromString(s);
 
186
                int err;
 
187
                if (v == NULL)
 
188
                        return -1;
 
189
                err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
 
190
                Py_DECREF(v);
 
191
                return err;
 
192
        }
 
193
        else
 
194
                return -1;
 
195
}
 
196
 
 
197
/* Try to get a file-descriptor from a Python object.  If the object
 
198
   is an integer or long integer, its value is returned.  If not, the
 
199
   object's fileno() method is called if it exists; the method must return
 
200
   an integer or long integer, which is returned as the file descriptor value.
 
201
   -1 is returned on failure.
 
202
*/
 
203
 
 
204
int
 
205
PyObject_AsFileDescriptor(PyObject *o)
 
206
{
 
207
        int fd;
 
208
        PyObject *meth;
 
209
 
 
210
        if (PyLong_Check(o)) {
 
211
                fd = PyLong_AsLong(o);
 
212
        }
 
213
        else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)
 
214
        {
 
215
                PyObject *fno = PyEval_CallObject(meth, NULL);
 
216
                Py_DECREF(meth);
 
217
                if (fno == NULL)
 
218
                        return -1;
 
219
 
 
220
                if (PyLong_Check(fno)) {
 
221
                        fd = PyLong_AsLong(fno);
 
222
                        Py_DECREF(fno);
 
223
                }
 
224
                else {
 
225
                        PyErr_SetString(PyExc_TypeError,
 
226
                                        "fileno() returned a non-integer");
 
227
                        Py_DECREF(fno);
 
228
                        return -1;
 
229
                }
 
230
        }
 
231
        else {
 
232
                PyErr_SetString(PyExc_TypeError,
 
233
                                "argument must be an int, or have a fileno() method.");
 
234
                return -1;
 
235
        }
 
236
 
 
237
        if (fd == -1 && PyErr_Occurred())
 
238
                return -1;
 
239
        if (fd < 0) {
 
240
                PyErr_Format(PyExc_ValueError,
 
241
                             "file descriptor cannot be a negative integer (%i)",
 
242
                             fd);
 
243
                return -1;
 
244
        }
 
245
        return fd;
 
246
}
 
247
 
 
248
/*
 
249
** Py_UniversalNewlineFgets is an fgets variation that understands
 
250
** all of \r, \n and \r\n conventions.
 
251
** The stream should be opened in binary mode.
 
252
** If fobj is NULL the routine always does newline conversion, and
 
253
** it may peek one char ahead to gobble the second char in \r\n.
 
254
** If fobj is non-NULL it must be a PyFileObject. In this case there
 
255
** is no readahead but in stead a flag is used to skip a following
 
256
** \n on the next read. Also, if the file is open in binary mode
 
257
** the whole conversion is skipped. Finally, the routine keeps track of
 
258
** the different types of newlines seen.
 
259
** Note that we need no error handling: fgets() treats error and eof
 
260
** identically.
 
261
*/
 
262
char *
 
263
Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
 
264
{
 
265
        char *p = buf;
 
266
        int c;
 
267
        int newlinetypes = 0;
 
268
        int skipnextlf = 0;
 
269
 
 
270
        if (fobj) {
 
271
                errno = ENXIO;  /* What can you do... */
 
272
                return NULL;
 
273
        }
 
274
        FLOCKFILE(stream);
 
275
        c = 'x'; /* Shut up gcc warning */
 
276
        while (--n > 0 && (c = GETC(stream)) != EOF ) {
 
277
                if (skipnextlf ) {
 
278
                        skipnextlf = 0;
 
279
                        if (c == '\n') {
 
280
                                /* Seeing a \n here with skipnextlf true
 
281
                                ** means we saw a \r before.
 
282
                                */
 
283
                                newlinetypes |= NEWLINE_CRLF;
 
284
                                c = GETC(stream);
 
285
                                if (c == EOF) break;
 
286
                        } else {
 
287
                                /*
 
288
                                ** Note that c == EOF also brings us here,
 
289
                                ** so we're okay if the last char in the file
 
290
                                ** is a CR.
 
291
                                */
 
292
                                newlinetypes |= NEWLINE_CR;
 
293
                        }
 
294
                }
 
295
                if (c == '\r') {
 
296
                        /* A \r is translated into a \n, and we skip
 
297
                        ** an adjacent \n, if any. We don't set the
 
298
                        ** newlinetypes flag until we've seen the next char.
 
299
                        */
 
300
                        skipnextlf = 1;
 
301
                        c = '\n';
 
302
                } else if ( c == '\n') {
 
303
                        newlinetypes |= NEWLINE_LF;
 
304
                }
 
305
                *p++ = c;
 
306
                if (c == '\n') break;
 
307
        }
 
308
        if ( c == EOF && skipnextlf )
 
309
                newlinetypes |= NEWLINE_CR;
 
310
        FUNLOCKFILE(stream);
 
311
        *p = '\0';
 
312
        if ( skipnextlf ) {
 
313
                /* If we have no file object we cannot save the
 
314
                ** skipnextlf flag. We have to readahead, which
 
315
                ** will cause a pause if we're reading from an
 
316
                ** interactive stream, but that is very unlikely
 
317
                ** unless we're doing something silly like
 
318
                ** exec(open("/dev/tty").read()).
 
319
                */
 
320
                c = GETC(stream);
 
321
                if ( c != '\n' )
 
322
                        ungetc(c, stream);
 
323
        }
 
324
        if (p == buf)
 
325
                return NULL;
 
326
        return buf;
 
327
}
 
328
 
 
329
/* **************************** std printer ****************************
 
330
 * The stdprinter is used during the boot strapping phase as a preliminary
 
331
 * file like object for sys.stderr.
 
332
 */
 
333
 
 
334
typedef struct {
 
335
        PyObject_HEAD
 
336
        int fd;
 
337
} PyStdPrinter_Object;
 
338
 
 
339
static PyObject *
 
340
stdprinter_new(PyTypeObject *type, PyObject *args, PyObject *kews)
 
341
{
 
342
        PyStdPrinter_Object *self;
 
343
 
 
344
        assert(type != NULL && type->tp_alloc != NULL);
 
345
 
 
346
        self = (PyStdPrinter_Object *) type->tp_alloc(type, 0);
 
347
        if (self != NULL) {
 
348
                self->fd = -1;
 
349
        }
 
350
 
 
351
        return (PyObject *) self;
 
352
}
 
353
 
 
354
static int
 
355
fileio_init(PyObject *self, PyObject *args, PyObject *kwds)
 
356
{
 
357
        PyErr_SetString(PyExc_TypeError,
 
358
                        "cannot create 'stderrprinter' instances");
 
359
        return -1;
 
360
}
 
361
 
 
362
PyObject *
 
363
PyFile_NewStdPrinter(int fd)
 
364
{
 
365
        PyStdPrinter_Object *self;
 
366
 
 
367
        if (fd != fileno(stdout) && fd != fileno(stderr)) {
 
368
                /* not enough infrastructure for PyErr_BadInternalCall() */
 
369
                return NULL;
 
370
        }
 
371
 
 
372
        self = PyObject_New(PyStdPrinter_Object,
 
373
                            &PyStdPrinter_Type);
 
374
        if (self != NULL) {
 
375
                self->fd = fd;
 
376
        }
 
377
        return (PyObject*)self;
 
378
}
 
379
 
 
380
static PyObject *
 
381
stdprinter_write(PyStdPrinter_Object *self, PyObject *args)
 
382
{
 
383
        char *c;
 
384
        Py_ssize_t n;
 
385
 
 
386
        if (self->fd < 0) {
 
387
                /* fd might be invalid on Windows
 
388
                 * I can't raise an exception here. It may lead to an
 
389
                 * unlimited recursion in the case stderr is invalid.
 
390
                 */
 
391
                Py_RETURN_NONE;
 
392
        }
 
393
 
 
394
        if (!PyArg_ParseTuple(args, "s", &c)) {
 
395
                return NULL;
 
396
        }
 
397
        n = strlen(c);
 
398
 
 
399
        Py_BEGIN_ALLOW_THREADS
 
400
        errno = 0;
 
401
        n = write(self->fd, c, n);
 
402
        Py_END_ALLOW_THREADS
 
403
 
 
404
        if (n < 0) {
 
405
                if (errno == EAGAIN)
 
406
                        Py_RETURN_NONE;
 
407
                PyErr_SetFromErrno(PyExc_IOError);
 
408
                return NULL;
 
409
        }
 
410
 
 
411
        return PyLong_FromSsize_t(n);
 
412
}
 
413
 
 
414
static PyObject *
 
415
stdprinter_fileno(PyStdPrinter_Object *self)
 
416
{
 
417
        return PyLong_FromLong((long) self->fd);
 
418
}
 
419
 
 
420
static PyObject *
 
421
stdprinter_repr(PyStdPrinter_Object *self)
 
422
{
 
423
        return PyUnicode_FromFormat("<stdprinter(fd=%d) object at 0x%x>",
 
424
                                    self->fd, self);
 
425
}
 
426
 
 
427
static PyObject *
 
428
stdprinter_noop(PyStdPrinter_Object *self)
 
429
{
 
430
        Py_RETURN_NONE;
 
431
}
 
432
 
 
433
static PyObject *
 
434
stdprinter_isatty(PyStdPrinter_Object *self)
 
435
{
 
436
        long res;
 
437
        if (self->fd < 0) {
 
438
                Py_RETURN_FALSE;
 
439
        }
 
440
 
 
441
        Py_BEGIN_ALLOW_THREADS
 
442
        res = isatty(self->fd);
 
443
        Py_END_ALLOW_THREADS
 
444
 
 
445
        return PyBool_FromLong(res);
 
446
}
 
447
 
 
448
static PyMethodDef stdprinter_methods[] = {
 
449
        {"close",       (PyCFunction)stdprinter_noop, METH_NOARGS, ""},
 
450
        {"flush",       (PyCFunction)stdprinter_noop, METH_NOARGS, ""},
 
451
        {"fileno",      (PyCFunction)stdprinter_fileno, METH_NOARGS, ""},
 
452
        {"isatty",      (PyCFunction)stdprinter_isatty, METH_NOARGS, ""},
 
453
        {"write",       (PyCFunction)stdprinter_write, METH_VARARGS, ""},
 
454
        {NULL,          NULL}  /*sentinel */
 
455
};
 
456
 
 
457
static PyObject *
 
458
get_closed(PyStdPrinter_Object *self, void *closure)
 
459
{
 
460
        Py_INCREF(Py_False);
 
461
        return Py_False;
 
462
}
 
463
 
 
464
static PyObject *
 
465
get_mode(PyStdPrinter_Object *self, void *closure)
 
466
{
 
467
        return PyUnicode_FromString("w");
 
468
}
 
469
 
 
470
static PyObject *
 
471
get_encoding(PyStdPrinter_Object *self, void *closure)
 
472
{
 
473
        Py_RETURN_NONE;
 
474
}
 
475
 
 
476
static PyGetSetDef stdprinter_getsetlist[] = {
 
477
        {"closed", (getter)get_closed, NULL, "True if the file is closed"},
 
478
        {"encoding", (getter)get_encoding, NULL, "Encoding of the file"},
 
479
        {"mode", (getter)get_mode, NULL, "String giving the file mode"},
 
480
        {0},
 
481
};
 
482
 
 
483
PyTypeObject PyStdPrinter_Type = {
 
484
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
 
485
        "stderrprinter",                        /* tp_name */
 
486
        sizeof(PyStdPrinter_Object),            /* tp_basicsize */
 
487
        0,                                      /* tp_itemsize */
 
488
        /* methods */
 
489
        0,                                      /* tp_dealloc */
 
490
        0,                                      /* tp_print */
 
491
        0,                                      /* tp_getattr */
 
492
        0,                                      /* tp_setattr */
 
493
        0,                                      /* tp_reserved */
 
494
        (reprfunc)stdprinter_repr,              /* tp_repr */
 
495
        0,                                      /* tp_as_number */
 
496
        0,                                      /* tp_as_sequence */
 
497
        0,                                      /* tp_as_mapping */
 
498
        0,                                      /* tp_hash */
 
499
        0,                                      /* tp_call */
 
500
        0,                                      /* tp_str */
 
501
        PyObject_GenericGetAttr,                /* tp_getattro */
 
502
        0,                                      /* tp_setattro */
 
503
        0,                                      /* tp_as_buffer */
 
504
        Py_TPFLAGS_DEFAULT,                     /* tp_flags */
 
505
        0,                                      /* tp_doc */
 
506
        0,                                      /* tp_traverse */
 
507
        0,                                      /* tp_clear */
 
508
        0,                                      /* tp_richcompare */
 
509
        0,                                      /* tp_weaklistoffset */
 
510
        0,                                      /* tp_iter */
 
511
        0,                                      /* tp_iternext */
 
512
        stdprinter_methods,                     /* tp_methods */
 
513
        0,                                      /* tp_members */
 
514
        stdprinter_getsetlist,                  /* tp_getset */
 
515
        0,                                      /* tp_base */
 
516
        0,                                      /* tp_dict */
 
517
        0,                                      /* tp_descr_get */
 
518
        0,                                      /* tp_descr_set */
 
519
        0,                                      /* tp_dictoffset */
 
520
        fileio_init,                            /* tp_init */
 
521
        PyType_GenericAlloc,                    /* tp_alloc */
 
522
        stdprinter_new,                         /* tp_new */
 
523
        PyObject_Del,                           /* tp_free */
 
524
};
 
525
 
 
526
 
 
527
#ifdef __cplusplus
 
528
}
 
529
#endif