| OLD | NEW |
|---|---|
| 1 #include "Python.h" | 1 #include "Python.h" |
| 2 #include "structmember.h" | 2 #include "structmember.h" |
| 3 #include "cPickle.h" | 3 #include "cPickle.h" |
| 4 | 4 |
| 5 PyDoc_STRVAR(cPickle_module_documentation, | 5 PyDoc_STRVAR(cPickle_module_documentation, |
| 6 "C implementation and optimization of the Python pickle module."); | 6 "C implementation and optimization of the Python pickle module."); |
| 7 | 7 |
| 8 #ifndef Py_eval_input | 8 #ifndef Py_eval_input |
| 9 #include <graminit.h> | 9 #include <graminit.h> |
| 10 #define Py_eval_input eval_input | 10 #define Py_eval_input eval_input |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 344 return NULL; | 344 return NULL; |
| 345 } | 345 } |
| 346 memset(memo->mt_table, 0, MT_MINSIZE * sizeof(PyMemoEntry)); | 346 memset(memo->mt_table, 0, MT_MINSIZE * sizeof(PyMemoEntry)); |
| 347 | 347 |
| 348 return memo; | 348 return memo; |
| 349 } | 349 } |
| 350 | 350 |
| 351 STATIC_MEMOTABLE PyMemoTable * | 351 STATIC_MEMOTABLE PyMemoTable * |
| 352 PyMemoTable_Copy(PyMemoTable *self) | 352 PyMemoTable_Copy(PyMemoTable *self) |
| 353 { | 353 { |
| 354 Py_ssize_t i; | |
| 354 PyMemoTable *new = PyMemoTable_New(); | 355 PyMemoTable *new = PyMemoTable_New(); |
| 355 if (new == NULL) | 356 if (new == NULL) |
| 356 return NULL; | 357 return NULL; |
| 357 | 358 |
| 358 new->mt_used = self->mt_used; | 359 new->mt_used = self->mt_used; |
| 359 new->mt_allocated = self->mt_allocated; | 360 new->mt_allocated = self->mt_allocated; |
| 360 new->mt_mask = self->mt_mask; | 361 new->mt_mask = self->mt_mask; |
| 361 /* The table we get from _New() is probably smaller than we wanted. | 362 /* The table we get from _New() is probably smaller than we wanted. |
| 362 Free it and allocate one that's the right size. */ | 363 Free it and allocate one that's the right size. */ |
| 363 PyMem_FREE(new->mt_table); | 364 PyMem_FREE(new->mt_table); |
| 364 new->mt_table = PyMem_NEW(PyMemoEntry, self->mt_allocated); | 365 new->mt_table = PyMem_NEW(PyMemoEntry, self->mt_allocated); |
| 365 if (new->mt_table == NULL) { | 366 if (new->mt_table == NULL) { |
| 366 PyMem_FREE(new); | 367 PyMem_FREE(new); |
| 367 return NULL; | 368 return NULL; |
| 369 } | |
| 370 for (i = 0; i < self->mt_allocated; i++) { | |
| 371 Py_XINCREF(self->mt_table[i].me_key); | |
| 368 } | 372 } |
| 369 memcpy(new->mt_table, self->mt_table, | 373 memcpy(new->mt_table, self->mt_table, |
| 370 sizeof(PyMemoEntry) * self->mt_allocated); | 374 sizeof(PyMemoEntry) * self->mt_allocated); |
| 371 | 375 |
| 372 return new; | 376 return new; |
| 373 } | 377 } |
| 374 | 378 |
| 375 STATIC_MEMOTABLE void | 379 STATIC_MEMOTABLE void |
| 376 PyMemoTable_Del(PyMemoTable *self) | 380 PyMemoTable_Del(PyMemoTable *self) |
| 377 { | 381 { |
| 382 Py_ssize_t i; | |
|
Jeffrey Yasskin
2009/07/03 01:32:59
Just call PyMemoTable_Clear()? The extra memset sh
| |
| 383 for (i = 0; i < self->mt_allocated; i++) { | |
| 384 Py_XDECREF(self->mt_table[i].me_key); | |
| 385 } | |
| 386 | |
| 378 PyMem_FREE(self->mt_table); | 387 PyMem_FREE(self->mt_table); |
| 379 PyMem_FREE(self); | 388 PyMem_FREE(self); |
| 380 } | 389 } |
| 381 | 390 |
| 382 STATIC_MEMOTABLE Py_ssize_t | 391 STATIC_MEMOTABLE Py_ssize_t |
| 383 PyMemoTable_Size(PyMemoTable *self) | 392 PyMemoTable_Size(PyMemoTable *self) |
| 384 { | 393 { |
| 385 return self->mt_used; | 394 return self->mt_used; |
| 386 } | 395 } |
| 387 | 396 |
| 388 STATIC_MEMOTABLE int | 397 STATIC_MEMOTABLE int |
| 389 PyMemoTable_Clear(PyMemoTable *self) | 398 PyMemoTable_Clear(PyMemoTable *self) |
| 390 { | 399 { |
| 400 Py_ssize_t i; | |
| 401 for (i = 0; i < self->mt_allocated; i++) { | |
| 402 Py_XDECREF(self->mt_table[i].me_key); | |
| 403 } | |
| 404 | |
| 391 self->mt_used = 0; | 405 self->mt_used = 0; |
| 392 memset(self->mt_table, 0, self->mt_allocated * sizeof(PyMemoEntry)); | 406 memset(self->mt_table, 0, self->mt_allocated * sizeof(PyMemoEntry)); |
| 393 return 0; | 407 return 0; |
| 394 } | 408 } |
| 395 | 409 |
| 396 /* Since entries cannot be deleted from this hashtable, _PyMemoTable_Lookup() | 410 /* Since entries cannot be deleted from this hashtable, _PyMemoTable_Lookup() |
| 397 can be considerably simpler than dictobject.c's lookdict(). */ | 411 can be considerably simpler than dictobject.c's lookdict(). */ |
| 398 static PyMemoEntry * | 412 static PyMemoEntry * |
| 399 _PyMemoTable_Lookup(PyMemoTable *self, void *key) | 413 _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key) |
| 400 { | 414 { |
| 401 size_t i; | 415 size_t i; |
| 402 size_t perturb; | 416 size_t perturb; |
| 403 size_t mask = (size_t)self->mt_mask; | 417 size_t mask = (size_t)self->mt_mask; |
| 404 PyMemoEntry *table = self->mt_table; | 418 PyMemoEntry *table = self->mt_table; |
| 405 PyMemoEntry *entry; | 419 PyMemoEntry *entry; |
| 406 long hash = (long)key >> 3; | 420 long hash = (long)key >> 3; |
| 407 | 421 |
| 408 i = hash & mask; | 422 i = hash & mask; |
| 409 entry = &table[i]; | 423 entry = &table[i]; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 } | 484 } |
| 471 } | 485 } |
| 472 | 486 |
| 473 /* Deallocate the old table. */ | 487 /* Deallocate the old table. */ |
| 474 PyMem_FREE(oldtable); | 488 PyMem_FREE(oldtable); |
| 475 return 0; | 489 return 0; |
| 476 } | 490 } |
| 477 | 491 |
| 478 /* Returns NULL on failure, a pointer to the value otherwise. */ | 492 /* Returns NULL on failure, a pointer to the value otherwise. */ |
| 479 STATIC_MEMOTABLE long * | 493 STATIC_MEMOTABLE long * |
| 480 PyMemoTable_Get(PyMemoTable *self, void *key) | 494 PyMemoTable_Get(PyMemoTable *self, PyObject *key) |
| 481 { | 495 { |
| 482 PyMemoEntry *entry = _PyMemoTable_Lookup(self, key); | 496 PyMemoEntry *entry = _PyMemoTable_Lookup(self, key); |
| 483 if (entry->me_key == NULL) | 497 if (entry->me_key == NULL) |
| 484 return NULL; | 498 return NULL; |
| 485 return &entry->me_value; | 499 return &entry->me_value; |
| 486 } | 500 } |
| 487 | 501 |
| 488 /* Returns -1 on failure, 0 on success. */ | 502 /* Returns -1 on failure, 0 on success. */ |
| 489 STATIC_MEMOTABLE int | 503 STATIC_MEMOTABLE int |
| 490 PyMemoTable_Set(PyMemoTable *self, void *key, long value) | 504 PyMemoTable_Set(PyMemoTable *self, PyObject *key, long value) |
| 491 { | 505 { |
| 492 PyMemoEntry *entry; | 506 PyMemoEntry *entry; |
| 493 | 507 |
| 494 assert(key != NULL); | 508 assert(key != NULL); |
| 495 | 509 |
| 496 entry = _PyMemoTable_Lookup(self, key); | 510 entry = _PyMemoTable_Lookup(self, key); |
| 497 if (entry->me_key != NULL) { | 511 if (entry->me_key != NULL) { |
| 498 entry->me_value = value; | 512 entry->me_value = value; |
| 499 return 0; | 513 return 0; |
| 500 } | 514 } |
| 515 Py_INCREF(key); | |
| 501 entry->me_key = key; | 516 entry->me_key = key; |
| 502 entry->me_value = value; | 517 entry->me_value = value; |
| 503 self->mt_used++; | 518 self->mt_used++; |
| 504 | 519 |
| 505 /* If we added a key, we can safely resize. Otherwise just return! | 520 /* If we added a key, we can safely resize. Otherwise just return! |
| 506 * If used >= 2/3 size, adjust size. Normally, this quaduples the size. | 521 * If used >= 2/3 size, adjust size. Normally, this quaduples the size. |
| 507 * | 522 * |
| 508 * Quadrupling the size improves average table sparseness | 523 * Quadrupling the size improves average table sparseness |
| 509 * (reducing collisions) at the cost of some memory. It also halves | 524 * (reducing collisions) at the cost of some memory. It also halves |
| 510 * the number of expensive resize operations in a growing memo table. | 525 * the number of expensive resize operations in a growing memo table. |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1059 char *r = PyMem_NEW(char, n+1); | 1074 char *r = PyMem_NEW(char, n+1); |
| 1060 if (r == NULL) | 1075 if (r == NULL) |
| 1061 return (char*)PyErr_NoMemory(); | 1076 return (char*)PyErr_NoMemory(); |
| 1062 memcpy(r, s, n); | 1077 memcpy(r, s, n); |
| 1063 r[n] = 0; | 1078 r[n] = 0; |
| 1064 return r; | 1079 return r; |
| 1065 } | 1080 } |
| 1066 | 1081 |
| 1067 | 1082 |
| 1068 static int | 1083 static int |
| 1069 get(Picklerobject *self, void *id) | 1084 get(Picklerobject *self, PyObject *id) |
| 1070 { | 1085 { |
| 1071 long *value; | 1086 long *value; |
| 1072 char s[30]; | 1087 char s[30]; |
| 1073 size_t len; | 1088 size_t len; |
| 1074 | 1089 |
| 1075 value = PyMemoTable_Get(self->memo, id); | 1090 value = PyMemoTable_Get(self->memo, id); |
| 1076 if (value == NULL) { | 1091 if (value == NULL) { |
| 1077 » » PyErr_SetObject(PyExc_KeyError, PyLong_FromVoidPtr(id)); | 1092 » » PyErr_SetObject(PyExc_KeyError, PyLong_FromVoidPtr((void *)id)); |
| 1078 return -1; | 1093 return -1; |
| 1079 } | 1094 } |
| 1080 | 1095 |
| 1081 self->uses_gets = 1; | 1096 self->uses_gets = 1; |
| 1082 if (!self->bin) { | 1097 if (!self->bin) { |
| 1083 s[0] = GET; | 1098 s[0] = GET; |
| 1084 PyOS_snprintf(s + 1, sizeof(s) - 1, "%ld\n", *value); | 1099 PyOS_snprintf(s + 1, sizeof(s) - 1, "%ld\n", *value); |
| 1085 len = strlen(s); | 1100 len = strlen(s); |
| 1086 } | 1101 } |
| 1087 else { | 1102 else { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1122 { | 1137 { |
| 1123 char c_str[30]; | 1138 char c_str[30]; |
| 1124 int p; | 1139 int p; |
| 1125 size_t len; | 1140 size_t len; |
| 1126 | 1141 |
| 1127 if (self->fast) | 1142 if (self->fast) |
| 1128 return 0; | 1143 return 0; |
| 1129 | 1144 |
| 1130 /* PyMemoTable_{Get,Set} doesn't accept null pointers as keys. */ | 1145 /* PyMemoTable_{Get,Set} doesn't accept null pointers as keys. */ |
| 1131 p = PyMemoTable_Size(self->memo) + 1; | 1146 p = PyMemoTable_Size(self->memo) + 1; |
| 1132 » if (PyMemoTable_Set(self->memo, (void *)ob, p) < 0) | 1147 » if (PyMemoTable_Set(self->memo, ob, p) < 0) |
| 1133 return -1; | 1148 return -1; |
| 1134 | 1149 |
| 1135 if (!self->bin) { | 1150 if (!self->bin) { |
| 1136 c_str[0] = PUT; | 1151 c_str[0] = PUT; |
| 1137 PyOS_snprintf(c_str + 1, sizeof(c_str) - 1, "%d\n", p); | 1152 PyOS_snprintf(c_str + 1, sizeof(c_str) - 1, "%d\n", p); |
| 1138 len = strlen(c_str); | 1153 len = strlen(c_str); |
| 1139 } | 1154 } |
| 1140 else { | 1155 else { |
| 1141 if (p >= 256) { | 1156 if (p >= 256) { |
| 1142 c_str[0] = LONG_BINPUT; | 1157 c_str[0] = LONG_BINPUT; |
| (...skipping 2344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3487 } | 3502 } |
| 3488 else if (PyDict_Check(pymemo)) { | 3503 else if (PyDict_Check(pymemo)) { |
| 3489 PyObject *pykey, *pyval; | 3504 PyObject *pykey, *pyval; |
| 3490 Py_ssize_t i = 0; | 3505 Py_ssize_t i = 0; |
| 3491 | 3506 |
| 3492 if (p->memo != NULL) | 3507 if (p->memo != NULL) |
| 3493 PyMemoTable_Del(p->memo); | 3508 PyMemoTable_Del(p->memo); |
| 3494 p->memo = PyMemoTable_New(); | 3509 p->memo = PyMemoTable_New(); |
| 3495 | 3510 |
| 3496 while (PyDict_Next(pymemo, &i, &pykey, &pyval)) { | 3511 while (PyDict_Next(pymemo, &i, &pykey, &pyval)) { |
| 3497 » » » long val; | 3512 » » » long val = PyLong_AsLong(pyval); |
| 3498 » » » void *key = (void *)PyLong_AsLong(pykey); | 3513 » » » if (PyMemoTable_Set(p->memo, pykey, val) < 0) |
| 3499 » » » val = PyLong_AsLong(pyval); | |
| 3500 » » » if (PyMemoTable_Set(p->memo, key, val) < 0) | |
| 3501 return -1; | 3514 return -1; |
| 3502 } | 3515 } |
| 3503 | 3516 |
| 3504 return 0; | 3517 return 0; |
| 3505 } | 3518 } |
| 3506 else { | 3519 else { |
| 3507 PyErr_Format(PyExc_TypeError, | 3520 PyErr_Format(PyExc_TypeError, |
| 3508 "'memo' attribute must be a PicklerMemoProxy " | 3521 "'memo' attribute must be a PicklerMemoProxy " |
| 3509 "object or dict, not %.200s", | 3522 "object or dict, not %.200s", |
| 3510 Py_TYPE(pymemo)->tp_name); | 3523 Py_TYPE(pymemo)->tp_name); |
| (...skipping 3032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6543 "1.0", /* Original protocol 0 */ | 6556 "1.0", /* Original protocol 0 */ |
| 6544 "1.1", /* Protocol 0 + INST */ | 6557 "1.1", /* Protocol 0 + INST */ |
| 6545 "1.2", /* Original protocol 1 */ | 6558 "1.2", /* Original protocol 1 */ |
| 6546 "1.3", /* Protocol 1 + BINFLOAT */ | 6559 "1.3", /* Protocol 1 + BINFLOAT */ |
| 6547 "2.0"); /* Original protocol 2 */ | 6560 "2.0"); /* Original protocol 2 */ |
| 6548 PyDict_SetItemString(d, "format_version", format_version); | 6561 PyDict_SetItemString(d, "format_version", format_version); |
| 6549 PyDict_SetItemString(d, "compatible_formats", compatible_formats); | 6562 PyDict_SetItemString(d, "compatible_formats", compatible_formats); |
| 6550 Py_XDECREF(format_version); | 6563 Py_XDECREF(format_version); |
| 6551 Py_XDECREF(compatible_formats); | 6564 Py_XDECREF(compatible_formats); |
| 6552 } | 6565 } |
| OLD | NEW |