/* bytes object implementation */ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() #include "pycore_bytes_methods.h" // _Py_bytes_startswith() #include "pycore_bytesobject.h" // _PyBytes_Find(), _PyBytes_Repeat() #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_GetBuiltin() #include "pycore_format.h" // F_LJUST #include "pycore_global_objects.h"// _Py_GET_GLOBAL_OBJECT() #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_long.h" // _PyLong_DigitValue #include "pycore_object.h" // _PyObject_GC_TRACK #include "pycore_pymem.h" // PYMEM_CLEANBYTE #include "pycore_strhex.h" // _Py_strhex_with_sep() #include <stddef.h> /*[clinic input] class bytes "PyBytesObject *" "&PyBytes_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=7a238f965d64892b]*/ #include "clinic/bytesobject.c.h" /* PyBytesObject_SIZE gives the basic size of a bytes object; any memory allocation for a bytes object of length n should request PyBytesObject_SIZE + n bytes. Using PyBytesObject_SIZE instead of sizeof(PyBytesObject) saves 3 or 7 bytes per bytes object allocation on a typical system. */ #define PyBytesObject_SIZE … /* Forward declaration */ Py_LOCAL_INLINE(Py_ssize_t) _PyBytesWriter_GetSize(_PyBytesWriter *writer, char *str); #define CHARACTERS … #define CHARACTER(ch) … #define EMPTY … // Return a reference to the immortal empty bytes string singleton. static inline PyObject* bytes_get_empty(void) { … } /* For PyBytes_FromString(), the parameter 'str' points to a null-terminated string containing exactly 'size' bytes. For PyBytes_FromStringAndSize(), the parameter 'str' is either NULL or else points to a string containing at least 'size' bytes. For PyBytes_FromStringAndSize(), the string in the 'str' parameter does not have to be null-terminated. (Therefore it is safe to construct a substring by calling 'PyBytes_FromStringAndSize(origstring, substrlen)'.) If 'str' is NULL then PyBytes_FromStringAndSize() will allocate 'size+1' bytes (setting the last byte to the null terminating character) and you can fill in the data yourself. If 'str' is non-NULL then the resulting PyBytes object must be treated as immutable and you must not fill in nor alter the data yourself, since the strings may be shared. The PyObject member 'op->ob_size', which denotes the number of "extra items" in a variable-size object, will contain the number of bytes allocated for string data, not counting the null terminating character. It is therefore equal to the 'size' parameter (for PyBytes_FromStringAndSize()) or the length of the string in the 'str' parameter (for PyBytes_FromString()). */ static PyObject * _PyBytes_FromSize(Py_ssize_t size, int use_calloc) { … } PyObject * PyBytes_FromStringAndSize(const char *str, Py_ssize_t size) { … } PyObject * PyBytes_FromString(const char *str) { … } PyObject * PyBytes_FromFormatV(const char *format, va_list vargs) { … } PyObject * PyBytes_FromFormat(const char *format, ...) { … } /* Helpers for formatstring */ Py_LOCAL_INLINE(PyObject *) getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx) { … } /* Returns a new reference to a PyBytes object, or NULL on failure. */ static char* formatfloat(PyObject *v, int flags, int prec, int type, PyObject **p_result, _PyBytesWriter *writer, char *str) { … } static PyObject * formatlong(PyObject *v, int flags, int prec, int type) { … } static int byte_converter(PyObject *arg, char *p) { … } static PyObject *_PyBytes_FromBuffer(PyObject *x); static PyObject * format_obj(PyObject *v, const char **pbuf, Py_ssize_t *plen) { … } /* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */ PyObject * _PyBytes_FormatEx(const char *format, Py_ssize_t format_len, PyObject *args, int use_bytearray) { … } /* Unescape a backslash-escaped string. */ PyObject *_PyBytes_DecodeEscape(const char *s, Py_ssize_t len, const char *errors, const char **first_invalid_escape) { … } PyObject *PyBytes_DecodeEscape(const char *s, Py_ssize_t len, const char *errors, Py_ssize_t Py_UNUSED(unicode), const char *Py_UNUSED(recode_encoding)) { … } /* -------------------------------------------------------------------- */ /* object api */ Py_ssize_t PyBytes_Size(PyObject *op) { … } char * PyBytes_AsString(PyObject *op) { … } int PyBytes_AsStringAndSize(PyObject *obj, char **s, Py_ssize_t *len) { … } /* -------------------------------------------------------------------- */ /* Methods */ #define STRINGLIB_GET_EMPTY … #include "stringlib/stringdefs.h" #define STRINGLIB_MUTABLE … #include "stringlib/fastsearch.h" #include "stringlib/count.h" #include "stringlib/find.h" #include "stringlib/join.h" #include "stringlib/partition.h" #include "stringlib/split.h" #include "stringlib/ctype.h" #include "stringlib/transmogrify.h" #undef STRINGLIB_GET_EMPTY Py_ssize_t _PyBytes_Find(const char *haystack, Py_ssize_t len_haystack, const char *needle, Py_ssize_t len_needle, Py_ssize_t offset) { … } Py_ssize_t _PyBytes_ReverseFind(const char *haystack, Py_ssize_t len_haystack, const char *needle, Py_ssize_t len_needle, Py_ssize_t offset) { … } PyObject * PyBytes_Repr(PyObject *obj, int smartquotes) { … } static PyObject * bytes_repr(PyObject *op) { … } static PyObject * bytes_str(PyObject *op) { … } static Py_ssize_t bytes_length(PyObject *self) { … } /* This is also used by PyBytes_Concat() */ static PyObject * bytes_concat(PyObject *a, PyObject *b) { … } static PyObject * bytes_repeat(PyObject *self, Py_ssize_t n) { … } static int bytes_contains(PyObject *self, PyObject *arg) { … } static PyObject * bytes_item(PyObject *self, Py_ssize_t i) { … } static int bytes_compare_eq(PyBytesObject *a, PyBytesObject *b) { … } static PyObject* bytes_richcompare(PyObject *aa, PyObject *bb, int op) { … } static Py_hash_t bytes_hash(PyObject *self) { … } static PyObject* bytes_subscript(PyObject *op, PyObject* item) { … } static int bytes_buffer_getbuffer(PyObject *op, Py_buffer *view, int flags) { … } static PySequenceMethods bytes_as_sequence = …; static PyMappingMethods bytes_as_mapping = …; static PyBufferProcs bytes_as_buffer = …; /*[clinic input] bytes.__bytes__ Convert this value to exact type bytes. [clinic start generated code]*/ static PyObject * bytes___bytes___impl(PyBytesObject *self) /*[clinic end generated code: output=63a306a9bc0caac5 input=34ec5ddba98bd6bb]*/ { … } #define LEFTSTRIP … #define RIGHTSTRIP … #define BOTHSTRIP … /*[clinic input] bytes.split sep: object = None The delimiter according which to split the bytes. None (the default value) means split on ASCII whitespace characters (space, tab, return, newline, formfeed, vertical tab). maxsplit: Py_ssize_t = -1 Maximum number of splits to do. -1 (the default value) means no limit. Return a list of the sections in the bytes, using sep as the delimiter. [clinic start generated code]*/ static PyObject * bytes_split_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit) /*[clinic end generated code: output=52126b5844c1d8ef input=8b809b39074abbfa]*/ { … } /*[clinic input] bytes.partition sep: Py_buffer / Partition the bytes into three parts using the given separator. This will search for the separator sep in the bytes. If the separator is found, returns a 3-tuple containing the part before the separator, the separator itself, and the part after it. If the separator is not found, returns a 3-tuple containing the original bytes object and two empty bytes objects. [clinic start generated code]*/ static PyObject * bytes_partition_impl(PyBytesObject *self, Py_buffer *sep) /*[clinic end generated code: output=f532b392a17ff695 input=61cca95519406099]*/ { … } /*[clinic input] bytes.rpartition sep: Py_buffer / Partition the bytes into three parts using the given separator. This will search for the separator sep in the bytes, starting at the end. If the separator is found, returns a 3-tuple containing the part before the separator, the separator itself, and the part after it. If the separator is not found, returns a 3-tuple containing two empty bytes objects and the original bytes object. [clinic start generated code]*/ static PyObject * bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep) /*[clinic end generated code: output=191b114cbb028e50 input=d78db010c8cfdbe1]*/ { … } /*[clinic input] bytes.rsplit = bytes.split Return a list of the sections in the bytes, using sep as the delimiter. Splitting is done starting at the end of the bytes and working to the front. [clinic start generated code]*/ static PyObject * bytes_rsplit_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit) /*[clinic end generated code: output=ba698d9ea01e1c8f input=0f86c9f28f7d7b7b]*/ { … } /*[clinic input] bytes.join iterable_of_bytes: object / Concatenate any number of bytes objects. The bytes whose method is called is inserted in between each pair. The result is returned as a new bytes object. Example: b'.'.join([b'ab', b'pq', b'rs']) -> b'ab.pq.rs'. [clinic start generated code]*/ static PyObject * bytes_join(PyBytesObject *self, PyObject *iterable_of_bytes) /*[clinic end generated code: output=a046f379f626f6f8 input=7fe377b95bd549d2]*/ { … } PyObject * PyBytes_Join(PyObject *sep, PyObject *iterable) { … } /*[clinic input] @text_signature "($self, sub[, start[, end]], /)" bytes.find sub: object start: slice_index(accept={int, NoneType}, c_default='0') = None Optional start position. Default: start of the bytes. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None Optional stop position. Default: end of the bytes. / Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. Return -1 on failure. [clinic start generated code]*/ static PyObject * bytes_find_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) /*[clinic end generated code: output=d5961a1c77b472a1 input=3171e62a8ae7f240]*/ { … } /*[clinic input] bytes.index = bytes.find Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. Raise ValueError if the subsection is not found. [clinic start generated code]*/ static PyObject * bytes_index_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) /*[clinic end generated code: output=0da25cc74683ba42 input=aa34ad71ba0bafe3]*/ { … } /*[clinic input] bytes.rfind = bytes.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. Return -1 on failure. [clinic start generated code]*/ static PyObject * bytes_rfind_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) /*[clinic end generated code: output=51b60fa4ad011c09 input=864c3e7f3010b33c]*/ { … } /*[clinic input] bytes.rindex = bytes.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. Raise ValueError if the subsection is not found. [clinic start generated code]*/ static PyObject * bytes_rindex_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) /*[clinic end generated code: output=42bf674e0a0aabf6 input=21051fc5cfeacf2c]*/ { … } Py_LOCAL_INLINE(PyObject *) do_xstrip(PyBytesObject *self, int striptype, PyObject *sepobj) { … } Py_LOCAL_INLINE(PyObject *) do_strip(PyBytesObject *self, int striptype) { … } Py_LOCAL_INLINE(PyObject *) do_argstrip(PyBytesObject *self, int striptype, PyObject *bytes) { … } /*[clinic input] bytes.strip bytes: object = None / Strip leading and trailing bytes contained in the argument. If the argument is omitted or None, strip leading and trailing ASCII whitespace. [clinic start generated code]*/ static PyObject * bytes_strip_impl(PyBytesObject *self, PyObject *bytes) /*[clinic end generated code: output=c7c228d3bd104a1b input=8a354640e4e0b3ef]*/ { … } /*[clinic input] bytes.lstrip bytes: object = None / Strip leading bytes contained in the argument. If the argument is omitted or None, strip leading ASCII whitespace. [clinic start generated code]*/ static PyObject * bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes) /*[clinic end generated code: output=28602e586f524e82 input=9baff4398c3f6857]*/ { … } /*[clinic input] bytes.rstrip bytes: object = None / Strip trailing bytes contained in the argument. If the argument is omitted or None, strip trailing ASCII whitespace. [clinic start generated code]*/ static PyObject * bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes) /*[clinic end generated code: output=547e3815c95447da input=b78af445c727e32b]*/ { … } /*[clinic input] bytes.count = bytes.find Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end]. [clinic start generated code]*/ static PyObject * bytes_count_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) /*[clinic end generated code: output=9848140b9be17d0f input=b6e4a5ed515e1e59]*/ { … } /*[clinic input] bytes.translate table: object Translation table, which must be a bytes object of length 256. / delete as deletechars: object(c_default="NULL") = b'' Return a copy with each character mapped by the given translation table. All characters occurring in the optional argument delete are removed. The remaining characters are mapped through the given translation table. [clinic start generated code]*/ static PyObject * bytes_translate_impl(PyBytesObject *self, PyObject *table, PyObject *deletechars) /*[clinic end generated code: output=43be3437f1956211 input=0ecdf159f654233c]*/ { … } /*[clinic input] @staticmethod bytes.maketrans frm: Py_buffer to: Py_buffer / Return a translation table usable for the bytes or bytearray translate method. The returned table will be one where each byte in frm is mapped to the byte at the same position in to. The bytes objects frm and to must be of the same length. [clinic start generated code]*/ static PyObject * bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to) /*[clinic end generated code: output=a36f6399d4b77f6f input=a3bd00d430a0979f]*/ { … } /*[clinic input] bytes.replace old: Py_buffer new: Py_buffer count: Py_ssize_t = -1 Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences. / Return a copy with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced. [clinic start generated code]*/ static PyObject * bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) /*[clinic end generated code: output=994fa588b6b9c104 input=b2fbbf0bf04de8e5]*/ { … } /** End DALKE **/ /*[clinic input] bytes.removeprefix as bytes_removeprefix prefix: Py_buffer / Return a bytes object with the given prefix string removed if present. If the bytes starts with the prefix string, return bytes[len(prefix):]. Otherwise, return a copy of the original bytes. [clinic start generated code]*/ static PyObject * bytes_removeprefix_impl(PyBytesObject *self, Py_buffer *prefix) /*[clinic end generated code: output=f006865331a06ab6 input=0c93bac817a8502c]*/ { … } /*[clinic input] bytes.removesuffix as bytes_removesuffix suffix: Py_buffer / Return a bytes object with the given suffix string removed if present. If the bytes ends with the suffix string and that suffix is not empty, return bytes[:-len(prefix)]. Otherwise, return a copy of the original bytes. [clinic start generated code]*/ static PyObject * bytes_removesuffix_impl(PyBytesObject *self, Py_buffer *suffix) /*[clinic end generated code: output=d887d308e3242eeb input=9f4e1da8c637bbf1]*/ { … } /*[clinic input] @text_signature "($self, prefix[, start[, end]], /)" bytes.startswith prefix as subobj: object A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None Optional start position. Default: start of the bytes. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None Optional stop position. Default: end of the bytes. / Return True if the bytes starts with the specified prefix, False otherwise. [clinic start generated code]*/ static PyObject * bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) /*[clinic end generated code: output=b1e8da1cbd528e8c input=8a4165df8adfa6c9]*/ { … } /*[clinic input] @text_signature "($self, suffix[, start[, end]], /)" bytes.endswith suffix as subobj: object A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None Optional start position. Default: start of the bytes. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None Optional stop position. Default: end of the bytes. / Return True if the bytes ends with the specified suffix, False otherwise. [clinic start generated code]*/ static PyObject * bytes_endswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) /*[clinic end generated code: output=038b633111f3629d input=b5c3407a2a5c9aac]*/ { … } /*[clinic input] bytes.decode encoding: str(c_default="NULL") = 'utf-8' The encoding with which to decode the bytes. errors: str(c_default="NULL") = 'strict' The error handling scheme to use for the handling of decoding errors. The default is 'strict' meaning that decoding errors raise a UnicodeDecodeError. Other possible values are 'ignore' and 'replace' as well as any other name registered with codecs.register_error that can handle UnicodeDecodeErrors. Decode the bytes using the codec registered for encoding. [clinic start generated code]*/ static PyObject * bytes_decode_impl(PyBytesObject *self, const char *encoding, const char *errors) /*[clinic end generated code: output=5649a53dde27b314 input=958174769d2a40ca]*/ { … } /*[clinic input] bytes.splitlines keepends: bool = False Return a list of the lines in the bytes, breaking at line boundaries. Line breaks are not included in the resulting list unless keepends is given and true. [clinic start generated code]*/ static PyObject * bytes_splitlines_impl(PyBytesObject *self, int keepends) /*[clinic end generated code: output=3484149a5d880ffb input=5d7b898af2fe55c0]*/ { … } /*[clinic input] @classmethod bytes.fromhex string: unicode / Create a bytes object from a string of hexadecimal numbers. Spaces between two numbers are accepted. Example: bytes.fromhex('B9 01EF') -> b'\\xb9\\x01\\xef'. [clinic start generated code]*/ static PyObject * bytes_fromhex_impl(PyTypeObject *type, PyObject *string) /*[clinic end generated code: output=0973acc63661bb2e input=bf4d1c361670acd3]*/ { … } PyObject* _PyBytes_FromHex(PyObject *string, int use_bytearray) { … } /*[clinic input] bytes.hex sep: object = NULL An optional single character or byte to separate hex bytes. bytes_per_sep: int = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. Create a string of hexadecimal numbers from a bytes object. Example: >>> value = b'\xb9\x01\xef' >>> value.hex() 'b901ef' >>> value.hex(':') 'b9:01:ef' >>> value.hex(':', 2) 'b9:01ef' >>> value.hex(':', -2) 'b901:ef' [clinic start generated code]*/ static PyObject * bytes_hex_impl(PyBytesObject *self, PyObject *sep, int bytes_per_sep) /*[clinic end generated code: output=1f134da504064139 input=1a21282b1f1ae595]*/ { … } static PyObject * bytes_getnewargs(PyBytesObject *v, PyObject *Py_UNUSED(ignored)) { … } static PyMethodDef bytes_methods[] = …; static PyObject * bytes_mod(PyObject *self, PyObject *arg) { … } static PyNumberMethods bytes_as_number = …; static PyObject * bytes_subtype_new(PyTypeObject *, PyObject *); /*[clinic input] @classmethod bytes.__new__ as bytes_new source as x: object = NULL encoding: str = NULL errors: str = NULL [clinic start generated code]*/ static PyObject * bytes_new_impl(PyTypeObject *type, PyObject *x, const char *encoding, const char *errors) /*[clinic end generated code: output=1e0c471be311a425 input=f0a966d19b7262b4]*/ { … } static PyObject* _PyBytes_FromBuffer(PyObject *x) { … } static PyObject* _PyBytes_FromList(PyObject *x) { … } static PyObject* _PyBytes_FromTuple(PyObject *x) { … } static PyObject * _PyBytes_FromIterator(PyObject *it, PyObject *x) { … } PyObject * PyBytes_FromObject(PyObject *x) { … } /* This allocator is needed for subclasses don't want to use __new__. * See https://github.com/python/cpython/issues/91020#issuecomment-1096793239 * * This allocator will be removed when ob_shash is removed. */ static PyObject * bytes_alloc(PyTypeObject *self, Py_ssize_t nitems) { … } static PyObject * bytes_subtype_new(PyTypeObject *type, PyObject *tmp) { … } PyDoc_STRVAR(bytes_doc, "bytes(iterable_of_ints) -> bytes\n\ bytes(string, encoding[, errors]) -> bytes\n\ bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer\n\ bytes(int) -> bytes object of size given by the parameter initialized with null bytes\n\ bytes() -> empty bytes object\n\ \n\ Construct an immutable array of bytes from:\n\ - an iterable yielding integers in range(256)\n\ - a text string encoded using the specified encoding\n\ - any object implementing the buffer API.\n\ - an integer"); static PyObject *bytes_iter(PyObject *seq); PyTypeObject PyBytes_Type = …; void PyBytes_Concat(PyObject **pv, PyObject *w) { … } void PyBytes_ConcatAndDel(PyObject **pv, PyObject *w) { … } /* The following function breaks the notion that bytes are immutable: it changes the size of a bytes object. You can think of it as creating a new bytes object and destroying the old one, only more efficiently. Note that if there's not enough memory to resize the bytes object, the original bytes object at *pv is deallocated, *pv is set to NULL, an "out of memory" exception is set, and -1 is returned. Else (on success) 0 is returned, and the value in *pv may or may not be the same as on input. As always, an extra byte is allocated for a trailing \0 byte (newsize does *not* include that), and a trailing \0 byte is stored. */ int _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) { … } /*********************** Bytes Iterator ****************************/ striterobject; static void striter_dealloc(striterobject *it) { … } static int striter_traverse(striterobject *it, visitproc visit, void *arg) { … } static PyObject * striter_next(striterobject *it) { … } static PyObject * striter_len(striterobject *it, PyObject *Py_UNUSED(ignored)) { … } PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyObject * striter_reduce(striterobject *it, PyObject *Py_UNUSED(ignored)) { … } PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); static PyObject * striter_setstate(striterobject *it, PyObject *state) { … } PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); static PyMethodDef striter_methods[] = …; PyTypeObject PyBytesIter_Type = …; static PyObject * bytes_iter(PyObject *seq) { … } /* _PyBytesWriter API */ #ifdef MS_WINDOWS /* On Windows, overallocate by 50% is the best factor */ #define OVERALLOCATE_FACTOR … #else /* On Linux, overallocate by 25% is the best factor */ #define OVERALLOCATE_FACTOR … #endif void _PyBytesWriter_Init(_PyBytesWriter *writer) { … } void _PyBytesWriter_Dealloc(_PyBytesWriter *writer) { … } Py_LOCAL_INLINE(char*) _PyBytesWriter_AsString(_PyBytesWriter *writer) { … } Py_LOCAL_INLINE(Py_ssize_t) _PyBytesWriter_GetSize(_PyBytesWriter *writer, char *str) { … } #ifndef NDEBUG Py_LOCAL_INLINE(int) _PyBytesWriter_CheckConsistency(_PyBytesWriter *writer, char *str) { const char *start, *end; if (writer->use_small_buffer) { assert(writer->buffer == NULL); } else { assert(writer->buffer != NULL); if (writer->use_bytearray) assert(PyByteArray_CheckExact(writer->buffer)); else assert(PyBytes_CheckExact(writer->buffer)); assert(Py_REFCNT(writer->buffer) == 1); } if (writer->use_bytearray) { /* bytearray has its own overallocation algorithm, writer overallocation must be disabled */ assert(!writer->overallocate); } assert(0 <= writer->allocated); assert(0 <= writer->min_size && writer->min_size <= writer->allocated); /* the last byte must always be null */ start = _PyBytesWriter_AsString(writer); assert(start[writer->allocated] == 0); end = start + writer->allocated; assert(str != NULL); assert(start <= str && str <= end); return 1; } #endif void* _PyBytesWriter_Resize(_PyBytesWriter *writer, void *str, Py_ssize_t size) { … } void* _PyBytesWriter_Prepare(_PyBytesWriter *writer, void *str, Py_ssize_t size) { … } /* Allocate the buffer to write size bytes. Return the pointer to the beginning of buffer data. Raise an exception and return NULL on error. */ void* _PyBytesWriter_Alloc(_PyBytesWriter *writer, Py_ssize_t size) { … } PyObject * _PyBytesWriter_Finish(_PyBytesWriter *writer, void *str) { … } void* _PyBytesWriter_WriteBytes(_PyBytesWriter *writer, void *ptr, const void *bytes, Py_ssize_t size) { … } void _PyBytes_Repeat(char* dest, Py_ssize_t len_dest, const char* src, Py_ssize_t len_src) { … }