| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| 1 /* Author: Daniel Stutzbach */ | 1 /* Author: Daniel Stutzbach */ |
| 2 | 2 |
| 3 #define PY_SSIZE_T_CLEAN | 3 #define PY_SSIZE_T_CLEAN |
| 4 #include "Python.h" | 4 #include "Python.h" |
| 5 #include "structmember.h" | 5 #include "structmember.h" |
| 6 #ifdef HAVE_SYS_TYPES_H | 6 #ifdef HAVE_SYS_TYPES_H |
| 7 #include <sys/types.h> | 7 #include <sys/types.h> |
| 8 #endif | 8 #endif |
| 9 #ifdef HAVE_SYS_STAT_H | 9 #ifdef HAVE_SYS_STAT_H |
| 10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 | 45 |
| 46 #if SIZEOF_INT < 4 | 46 #if SIZEOF_INT < 4 |
| 47 #define BIGCHUNK (512 * 32) | 47 #define BIGCHUNK (512 * 32) |
| 48 #else | 48 #else |
| 49 #define BIGCHUNK (512 * 1024) | 49 #define BIGCHUNK (512 * 1024) |
| 50 #endif | 50 #endif |
| 51 | 51 |
| 52 typedef struct { | 52 typedef struct { |
| 53 PyObject_HEAD | 53 PyObject_HEAD |
| 54 int fd; | 54 int fd; |
| 55 unsigned int created : 1; | |
| 55 unsigned int readable : 1; | 56 unsigned int readable : 1; |
| 56 unsigned int writable : 1; | 57 unsigned int writable : 1; |
| 57 signed int seekable : 2; /* -1 means unknown */ | 58 signed int seekable : 2; /* -1 means unknown */ |
| 58 unsigned int closefd : 1; | 59 unsigned int closefd : 1; |
| 59 unsigned int deallocating: 1; | 60 unsigned int deallocating: 1; |
| 60 PyObject *weakreflist; | 61 PyObject *weakreflist; |
| 61 PyObject *dict; | 62 PyObject *dict; |
| 62 } fileio; | 63 } fileio; |
| 63 | 64 |
| 64 PyTypeObject PyFileIO_Type; | 65 PyTypeObject PyFileIO_Type; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 static PyObject * | 151 static PyObject * |
| 151 fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | 152 fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
| 152 { | 153 { |
| 153 fileio *self; | 154 fileio *self; |
| 154 | 155 |
| 155 assert(type != NULL && type->tp_alloc != NULL); | 156 assert(type != NULL && type->tp_alloc != NULL); |
| 156 | 157 |
| 157 self = (fileio *) type->tp_alloc(type, 0); | 158 self = (fileio *) type->tp_alloc(type, 0); |
| 158 if (self != NULL) { | 159 if (self != NULL) { |
| 159 self->fd = -1; | 160 self->fd = -1; |
| 161 self->created = 0; | |
| 160 self->readable = 0; | 162 self->readable = 0; |
| 161 self->writable = 0; | 163 self->writable = 0; |
| 162 self->seekable = -1; | 164 self->seekable = -1; |
| 163 self->closefd = 1; | 165 self->closefd = 1; |
| 164 self->weakreflist = NULL; | 166 self->weakreflist = NULL; |
| 165 } | 167 } |
| 166 | 168 |
| 167 return (PyObject *) self; | 169 return (PyObject *) self; |
| 168 } | 170 } |
| 169 | 171 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 "encoder failed to return bytes"); | 287 "encoder failed to return bytes"); |
| 286 goto error; | 288 goto error; |
| 287 } | 289 } |
| 288 name = PyBytes_AS_STRING(stringobj); | 290 name = PyBytes_AS_STRING(stringobj); |
| 289 } | 291 } |
| 290 } | 292 } |
| 291 | 293 |
| 292 s = mode; | 294 s = mode; |
| 293 while (*s) { | 295 while (*s) { |
| 294 switch (*s++) { | 296 switch (*s++) { |
| 295 case 'r': | 297 case 'x': |
| 296 if (rwa) { | 298 if (rwa) { |
| 297 bad_mode: | 299 bad_mode: |
| 298 PyErr_SetString(PyExc_ValueError, | 300 PyErr_SetString(PyExc_ValueError, |
| 299 "Must have exactly one of read/write/append " | 301 "Must have exactly one of create/read/write/appe nd " |
| 300 "mode and at most one plus"); | 302 "mode and at most one plus"); |
| 301 goto error; | 303 goto error; |
| 302 } | 304 } |
| 303 rwa = 1; | 305 rwa = 1; |
| 306 self->created = 1; | |
| 307 self->writable = 1; | |
| 308 flags |= O_EXCL | O_CREAT; | |
|
Benjamin Peterson
2012/01/08 16:16:10
Strange indentation again.
| |
| 309 break; | |
| 310 case 'r': | |
| 311 if (rwa) | |
| 312 goto bad_mode; | |
| 313 rwa = 1; | |
| 304 self->readable = 1; | 314 self->readable = 1; |
| 305 break; | 315 break; |
| 306 case 'w': | 316 case 'w': |
| 307 if (rwa) | 317 if (rwa) |
| 308 goto bad_mode; | 318 goto bad_mode; |
| 309 rwa = 1; | 319 rwa = 1; |
| 310 self->writable = 1; | 320 self->writable = 1; |
| 311 flags |= O_CREAT | O_TRUNC; | 321 flags |= O_CREAT | O_TRUNC; |
| 312 break; | 322 break; |
| 313 case 'a': | 323 case 'a': |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 "File not open for %s", action); | 474 "File not open for %s", action); |
| 465 return NULL; | 475 return NULL; |
| 466 } | 476 } |
| 467 | 477 |
| 468 static PyObject * | 478 static PyObject * |
| 469 fileio_fileno(fileio *self) | 479 fileio_fileno(fileio *self) |
| 470 { | 480 { |
| 471 if (self->fd < 0) | 481 if (self->fd < 0) |
| 472 return err_closed(); | 482 return err_closed(); |
| 473 return PyLong_FromLong((long) self->fd); | 483 return PyLong_FromLong((long) self->fd); |
| 484 } | |
| 485 | |
| 486 static PyObject * | |
| 487 fileio_created(fileio *self) | |
| 488 { | |
| 489 if (self->fd < 0) | |
| 490 return err_closed(); | |
| 491 return PyBool_FromLong((long) self->created); | |
| 474 } | 492 } |
| 475 | 493 |
| 476 static PyObject * | 494 static PyObject * |
| 477 fileio_readable(fileio *self) | 495 fileio_readable(fileio *self) |
| 478 { | 496 { |
| 479 if (self->fd < 0) | 497 if (self->fd < 0) |
| 480 return err_closed(); | 498 return err_closed(); |
| 481 return PyBool_FromLong((long) self->readable); | 499 return PyBool_FromLong((long) self->readable); |
| 482 } | 500 } |
| 483 | 501 |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 956 return NULL; | 974 return NULL; |
| 957 } | 975 } |
| 958 | 976 |
| 959 return posobj; | 977 return posobj; |
| 960 } | 978 } |
| 961 #endif /* HAVE_FTRUNCATE */ | 979 #endif /* HAVE_FTRUNCATE */ |
| 962 | 980 |
| 963 static char * | 981 static char * |
| 964 mode_string(fileio *self) | 982 mode_string(fileio *self) |
| 965 { | 983 { |
| 984 if (self->created) { | |
|
Charles-François Natali
2011/12/30 12:49:33
Indentation.
| |
| 985 if (self->readable) | |
| 986 return "xb+"; | |
| 987 else | |
| 988 return "xb"; | |
| 989 } | |
| 966 if (self->readable) { | 990 if (self->readable) { |
| 967 if (self->writable) | 991 if (self->writable) |
| 968 return "rb+"; | 992 return "rb+"; |
| 969 else | 993 else |
| 970 return "rb"; | 994 return "rb"; |
| 971 } | 995 } |
| 972 else | 996 else |
| 973 return "wb"; | 997 return "wb"; |
| 974 } | 998 } |
| 975 | 999 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1016 { | 1040 { |
| 1017 PyErr_Format(PyExc_TypeError, | 1041 PyErr_Format(PyExc_TypeError, |
| 1018 "cannot serialize '%s' object", Py_TYPE(self)->tp_name); | 1042 "cannot serialize '%s' object", Py_TYPE(self)->tp_name); |
| 1019 return NULL; | 1043 return NULL; |
| 1020 } | 1044 } |
| 1021 | 1045 |
| 1022 | 1046 |
| 1023 PyDoc_STRVAR(fileio_doc, | 1047 PyDoc_STRVAR(fileio_doc, |
| 1024 "file(name: str[, mode: str]) -> file IO object\n" | 1048 "file(name: str[, mode: str]) -> file IO object\n" |
| 1025 "\n" | 1049 "\n" |
| 1026 "Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n" | 1050 "Open a file. The mode can be 'x', 'r', 'w' or 'a' for creating,\n" |
| 1027 "writing or appending. The file will be created if it doesn't exist\n" | 1051 "reading (default), writing or appending. The file will be created\n" |
| 1028 "when opened for writing or appending; it will be truncated when\n" | 1052 "if it doesn't exist when opened for writing or appending; it will be\n" |
| 1029 "opened for writing. Add a '+' to the mode to allow simultaneous\n" | 1053 "truncated when opened for writing. An IOError will be raise if it\n" |
|
Benjamin Peterson
2012/01/08 16:16:10
OSError.
| |
| 1030 "reading and writing."); | 1054 "already exists when opened for creating. Opening a file for creating\n" |
| 1055 "implies writing, so this mode behaves in a similar way to 'w'. Add a\n" | |
| 1056 "'+' to the mode to allow simultaneous reading and writing."); | |
| 1031 | 1057 |
| 1032 PyDoc_STRVAR(read_doc, | 1058 PyDoc_STRVAR(read_doc, |
| 1033 "read(size: int) -> bytes. read at most size bytes, returned as bytes.\n" | 1059 "read(size: int) -> bytes. read at most size bytes, returned as bytes.\n" |
| 1034 "\n" | 1060 "\n" |
| 1035 "Only makes one system call, so less data may be returned than requested\n" | 1061 "Only makes one system call, so less data may be returned than requested\n" |
| 1036 "In non-blocking mode, returns None if no data is available.\n" | 1062 "In non-blocking mode, returns None if no data is available.\n" |
| 1037 "On end-of-file, returns ''."); | 1063 "On end-of-file, returns ''."); |
| 1038 | 1064 |
| 1039 PyDoc_STRVAR(readall_doc, | 1065 PyDoc_STRVAR(readall_doc, |
| 1040 "readall() -> bytes. read all data from the file, returned as bytes.\n" | 1066 "readall() -> bytes. read all data from the file, returned as bytes.\n" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1082 "close() -> None. Close the file.\n" | 1108 "close() -> None. Close the file.\n" |
| 1083 "\n" | 1109 "\n" |
| 1084 "A closed file cannot be used for further I/O operations. close() may be\n" | 1110 "A closed file cannot be used for further I/O operations. close() may be\n" |
| 1085 "called more than once without error. Changes the fileno to -1."); | 1111 "called more than once without error. Changes the fileno to -1."); |
| 1086 | 1112 |
| 1087 PyDoc_STRVAR(isatty_doc, | 1113 PyDoc_STRVAR(isatty_doc, |
| 1088 "isatty() -> bool. True if the file is connected to a tty device."); | 1114 "isatty() -> bool. True if the file is connected to a tty device."); |
| 1089 | 1115 |
| 1090 PyDoc_STRVAR(seekable_doc, | 1116 PyDoc_STRVAR(seekable_doc, |
| 1091 "seekable() -> bool. True if file supports random-access."); | 1117 "seekable() -> bool. True if file supports random-access."); |
| 1118 | |
| 1119 PyDoc_STRVAR(created_doc, | |
| 1120 "created() -> bool. True if file was newly created when opened with 'x' mode"); | |
|
Charles-François Natali
2011/12/30 12:49:33
Nit: missing space.
| |
| 1092 | 1121 |
| 1093 PyDoc_STRVAR(readable_doc, | 1122 PyDoc_STRVAR(readable_doc, |
| 1094 "readable() -> bool. True if file was opened in a read mode."); | 1123 "readable() -> bool. True if file was opened in a read mode."); |
| 1095 | 1124 |
| 1096 PyDoc_STRVAR(writable_doc, | 1125 PyDoc_STRVAR(writable_doc, |
| 1097 "writable() -> bool. True if file was opened in a write mode."); | 1126 "writable() -> bool. True if file was opened in a write mode."); |
| 1098 | 1127 |
| 1099 static PyMethodDef fileio_methods[] = { | 1128 static PyMethodDef fileio_methods[] = { |
| 1100 {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc}, | 1129 {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc}, |
| 1101 {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc}, | 1130 {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc}, |
| 1102 {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc}, | 1131 {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc}, |
| 1103 {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc}, | 1132 {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc}, |
| 1104 {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc}, | 1133 {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc}, |
| 1105 {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc}, | 1134 {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc}, |
| 1106 #ifdef HAVE_FTRUNCATE | 1135 #ifdef HAVE_FTRUNCATE |
| 1107 {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc}, | 1136 {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc}, |
| 1108 #endif | 1137 #endif |
| 1109 {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc}, | 1138 {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc}, |
| 1110 {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc}, | 1139 {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc}, |
| 1140 {"created", (PyCFunction)fileio_created, METH_NOARGS, created_doc}, | |
| 1111 {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc}, | 1141 {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc}, |
| 1112 {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc}, | 1142 {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc}, |
| 1113 {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc}, | 1143 {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc}, |
| 1114 {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc}, | 1144 {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc}, |
| 1115 {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, | 1145 {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, |
| 1116 {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL}, | 1146 {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL}, |
| 1117 {NULL, NULL} /* sentinel */ | 1147 {NULL, NULL} /* sentinel */ |
| 1118 }; | 1148 }; |
| 1119 | 1149 |
| 1120 /* 'closed' and 'mode' are attributes for backwards compatibility reasons. */ | 1150 /* 'closed' and 'mode' are attributes for backwards compatibility reasons. */ |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1180 0, /* tp_base */ | 1210 0, /* tp_base */ |
| 1181 0, /* tp_dict */ | 1211 0, /* tp_dict */ |
| 1182 0, /* tp_descr_get */ | 1212 0, /* tp_descr_get */ |
| 1183 0, /* tp_descr_set */ | 1213 0, /* tp_descr_set */ |
| 1184 offsetof(fileio, dict), /* tp_dictoffset */ | 1214 offsetof(fileio, dict), /* tp_dictoffset */ |
| 1185 fileio_init, /* tp_init */ | 1215 fileio_init, /* tp_init */ |
| 1186 PyType_GenericAlloc, /* tp_alloc */ | 1216 PyType_GenericAlloc, /* tp_alloc */ |
| 1187 fileio_new, /* tp_new */ | 1217 fileio_new, /* tp_new */ |
| 1188 PyObject_GC_Del, /* tp_free */ | 1218 PyObject_GC_Del, /* tp_free */ |
| 1189 }; | 1219 }; |
| OLD | NEW |