Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Objects/clinic/bytearrayobject.c.h
12 views
1
/*[clinic input]
2
preserve
3
[clinic start generated code]*/
4
5
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
6
# include "pycore_gc.h" // PyGC_Head
7
# include "pycore_runtime.h" // _Py_ID()
8
#endif
9
10
11
static int
12
bytearray___init___impl(PyByteArrayObject *self, PyObject *arg,
13
const char *encoding, const char *errors);
14
15
static int
16
bytearray___init__(PyObject *self, PyObject *args, PyObject *kwargs)
17
{
18
int return_value = -1;
19
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
20
21
#define NUM_KEYWORDS 3
22
static struct {
23
PyGC_Head _this_is_not_used;
24
PyObject_VAR_HEAD
25
PyObject *ob_item[NUM_KEYWORDS];
26
} _kwtuple = {
27
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
28
.ob_item = { &_Py_ID(source), &_Py_ID(encoding), &_Py_ID(errors), },
29
};
30
#undef NUM_KEYWORDS
31
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
32
33
#else // !Py_BUILD_CORE
34
# define KWTUPLE NULL
35
#endif // !Py_BUILD_CORE
36
37
static const char * const _keywords[] = {"source", "encoding", "errors", NULL};
38
static _PyArg_Parser _parser = {
39
.keywords = _keywords,
40
.fname = "bytearray",
41
.kwtuple = KWTUPLE,
42
};
43
#undef KWTUPLE
44
PyObject *argsbuf[3];
45
PyObject * const *fastargs;
46
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
47
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0;
48
PyObject *arg = NULL;
49
const char *encoding = NULL;
50
const char *errors = NULL;
51
52
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 3, 0, argsbuf);
53
if (!fastargs) {
54
goto exit;
55
}
56
if (!noptargs) {
57
goto skip_optional_pos;
58
}
59
if (fastargs[0]) {
60
arg = fastargs[0];
61
if (!--noptargs) {
62
goto skip_optional_pos;
63
}
64
}
65
if (fastargs[1]) {
66
if (!PyUnicode_Check(fastargs[1])) {
67
_PyArg_BadArgument("bytearray", "argument 'encoding'", "str", fastargs[1]);
68
goto exit;
69
}
70
Py_ssize_t encoding_length;
71
encoding = PyUnicode_AsUTF8AndSize(fastargs[1], &encoding_length);
72
if (encoding == NULL) {
73
goto exit;
74
}
75
if (strlen(encoding) != (size_t)encoding_length) {
76
PyErr_SetString(PyExc_ValueError, "embedded null character");
77
goto exit;
78
}
79
if (!--noptargs) {
80
goto skip_optional_pos;
81
}
82
}
83
if (!PyUnicode_Check(fastargs[2])) {
84
_PyArg_BadArgument("bytearray", "argument 'errors'", "str", fastargs[2]);
85
goto exit;
86
}
87
Py_ssize_t errors_length;
88
errors = PyUnicode_AsUTF8AndSize(fastargs[2], &errors_length);
89
if (errors == NULL) {
90
goto exit;
91
}
92
if (strlen(errors) != (size_t)errors_length) {
93
PyErr_SetString(PyExc_ValueError, "embedded null character");
94
goto exit;
95
}
96
skip_optional_pos:
97
return_value = bytearray___init___impl((PyByteArrayObject *)self, arg, encoding, errors);
98
99
exit:
100
return return_value;
101
}
102
103
PyDoc_STRVAR(bytearray_clear__doc__,
104
"clear($self, /)\n"
105
"--\n"
106
"\n"
107
"Remove all items from the bytearray.");
108
109
#define BYTEARRAY_CLEAR_METHODDEF \
110
{"clear", (PyCFunction)bytearray_clear, METH_NOARGS, bytearray_clear__doc__},
111
112
static PyObject *
113
bytearray_clear_impl(PyByteArrayObject *self);
114
115
static PyObject *
116
bytearray_clear(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
117
{
118
return bytearray_clear_impl(self);
119
}
120
121
PyDoc_STRVAR(bytearray_copy__doc__,
122
"copy($self, /)\n"
123
"--\n"
124
"\n"
125
"Return a copy of B.");
126
127
#define BYTEARRAY_COPY_METHODDEF \
128
{"copy", (PyCFunction)bytearray_copy, METH_NOARGS, bytearray_copy__doc__},
129
130
static PyObject *
131
bytearray_copy_impl(PyByteArrayObject *self);
132
133
static PyObject *
134
bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
135
{
136
return bytearray_copy_impl(self);
137
}
138
139
PyDoc_STRVAR(bytearray_removeprefix__doc__,
140
"removeprefix($self, prefix, /)\n"
141
"--\n"
142
"\n"
143
"Return a bytearray with the given prefix string removed if present.\n"
144
"\n"
145
"If the bytearray starts with the prefix string, return\n"
146
"bytearray[len(prefix):]. Otherwise, return a copy of the original\n"
147
"bytearray.");
148
149
#define BYTEARRAY_REMOVEPREFIX_METHODDEF \
150
{"removeprefix", (PyCFunction)bytearray_removeprefix, METH_O, bytearray_removeprefix__doc__},
151
152
static PyObject *
153
bytearray_removeprefix_impl(PyByteArrayObject *self, Py_buffer *prefix);
154
155
static PyObject *
156
bytearray_removeprefix(PyByteArrayObject *self, PyObject *arg)
157
{
158
PyObject *return_value = NULL;
159
Py_buffer prefix = {NULL, NULL};
160
161
if (PyObject_GetBuffer(arg, &prefix, PyBUF_SIMPLE) != 0) {
162
goto exit;
163
}
164
if (!PyBuffer_IsContiguous(&prefix, 'C')) {
165
_PyArg_BadArgument("removeprefix", "argument", "contiguous buffer", arg);
166
goto exit;
167
}
168
return_value = bytearray_removeprefix_impl(self, &prefix);
169
170
exit:
171
/* Cleanup for prefix */
172
if (prefix.obj) {
173
PyBuffer_Release(&prefix);
174
}
175
176
return return_value;
177
}
178
179
PyDoc_STRVAR(bytearray_removesuffix__doc__,
180
"removesuffix($self, suffix, /)\n"
181
"--\n"
182
"\n"
183
"Return a bytearray with the given suffix string removed if present.\n"
184
"\n"
185
"If the bytearray ends with the suffix string and that suffix is not\n"
186
"empty, return bytearray[:-len(suffix)]. Otherwise, return a copy of\n"
187
"the original bytearray.");
188
189
#define BYTEARRAY_REMOVESUFFIX_METHODDEF \
190
{"removesuffix", (PyCFunction)bytearray_removesuffix, METH_O, bytearray_removesuffix__doc__},
191
192
static PyObject *
193
bytearray_removesuffix_impl(PyByteArrayObject *self, Py_buffer *suffix);
194
195
static PyObject *
196
bytearray_removesuffix(PyByteArrayObject *self, PyObject *arg)
197
{
198
PyObject *return_value = NULL;
199
Py_buffer suffix = {NULL, NULL};
200
201
if (PyObject_GetBuffer(arg, &suffix, PyBUF_SIMPLE) != 0) {
202
goto exit;
203
}
204
if (!PyBuffer_IsContiguous(&suffix, 'C')) {
205
_PyArg_BadArgument("removesuffix", "argument", "contiguous buffer", arg);
206
goto exit;
207
}
208
return_value = bytearray_removesuffix_impl(self, &suffix);
209
210
exit:
211
/* Cleanup for suffix */
212
if (suffix.obj) {
213
PyBuffer_Release(&suffix);
214
}
215
216
return return_value;
217
}
218
219
PyDoc_STRVAR(bytearray_translate__doc__,
220
"translate($self, table, /, delete=b\'\')\n"
221
"--\n"
222
"\n"
223
"Return a copy with each character mapped by the given translation table.\n"
224
"\n"
225
" table\n"
226
" Translation table, which must be a bytes object of length 256.\n"
227
"\n"
228
"All characters occurring in the optional argument delete are removed.\n"
229
"The remaining characters are mapped through the given translation table.");
230
231
#define BYTEARRAY_TRANSLATE_METHODDEF \
232
{"translate", _PyCFunction_CAST(bytearray_translate), METH_FASTCALL|METH_KEYWORDS, bytearray_translate__doc__},
233
234
static PyObject *
235
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
236
PyObject *deletechars);
237
238
static PyObject *
239
bytearray_translate(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
240
{
241
PyObject *return_value = NULL;
242
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
243
244
#define NUM_KEYWORDS 1
245
static struct {
246
PyGC_Head _this_is_not_used;
247
PyObject_VAR_HEAD
248
PyObject *ob_item[NUM_KEYWORDS];
249
} _kwtuple = {
250
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
251
.ob_item = { &_Py_ID(delete), },
252
};
253
#undef NUM_KEYWORDS
254
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
255
256
#else // !Py_BUILD_CORE
257
# define KWTUPLE NULL
258
#endif // !Py_BUILD_CORE
259
260
static const char * const _keywords[] = {"", "delete", NULL};
261
static _PyArg_Parser _parser = {
262
.keywords = _keywords,
263
.fname = "translate",
264
.kwtuple = KWTUPLE,
265
};
266
#undef KWTUPLE
267
PyObject *argsbuf[2];
268
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
269
PyObject *table;
270
PyObject *deletechars = NULL;
271
272
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
273
if (!args) {
274
goto exit;
275
}
276
table = args[0];
277
if (!noptargs) {
278
goto skip_optional_pos;
279
}
280
deletechars = args[1];
281
skip_optional_pos:
282
return_value = bytearray_translate_impl(self, table, deletechars);
283
284
exit:
285
return return_value;
286
}
287
288
PyDoc_STRVAR(bytearray_maketrans__doc__,
289
"maketrans(frm, to, /)\n"
290
"--\n"
291
"\n"
292
"Return a translation table usable for the bytes or bytearray translate method.\n"
293
"\n"
294
"The returned table will be one where each byte in frm is mapped to the byte at\n"
295
"the same position in to.\n"
296
"\n"
297
"The bytes objects frm and to must be of the same length.");
298
299
#define BYTEARRAY_MAKETRANS_METHODDEF \
300
{"maketrans", _PyCFunction_CAST(bytearray_maketrans), METH_FASTCALL|METH_STATIC, bytearray_maketrans__doc__},
301
302
static PyObject *
303
bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to);
304
305
static PyObject *
306
bytearray_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs)
307
{
308
PyObject *return_value = NULL;
309
Py_buffer frm = {NULL, NULL};
310
Py_buffer to = {NULL, NULL};
311
312
if (!_PyArg_CheckPositional("maketrans", nargs, 2, 2)) {
313
goto exit;
314
}
315
if (PyObject_GetBuffer(args[0], &frm, PyBUF_SIMPLE) != 0) {
316
goto exit;
317
}
318
if (!PyBuffer_IsContiguous(&frm, 'C')) {
319
_PyArg_BadArgument("maketrans", "argument 1", "contiguous buffer", args[0]);
320
goto exit;
321
}
322
if (PyObject_GetBuffer(args[1], &to, PyBUF_SIMPLE) != 0) {
323
goto exit;
324
}
325
if (!PyBuffer_IsContiguous(&to, 'C')) {
326
_PyArg_BadArgument("maketrans", "argument 2", "contiguous buffer", args[1]);
327
goto exit;
328
}
329
return_value = bytearray_maketrans_impl(&frm, &to);
330
331
exit:
332
/* Cleanup for frm */
333
if (frm.obj) {
334
PyBuffer_Release(&frm);
335
}
336
/* Cleanup for to */
337
if (to.obj) {
338
PyBuffer_Release(&to);
339
}
340
341
return return_value;
342
}
343
344
PyDoc_STRVAR(bytearray_replace__doc__,
345
"replace($self, old, new, count=-1, /)\n"
346
"--\n"
347
"\n"
348
"Return a copy with all occurrences of substring old replaced by new.\n"
349
"\n"
350
" count\n"
351
" Maximum number of occurrences to replace.\n"
352
" -1 (the default value) means replace all occurrences.\n"
353
"\n"
354
"If the optional argument count is given, only the first count occurrences are\n"
355
"replaced.");
356
357
#define BYTEARRAY_REPLACE_METHODDEF \
358
{"replace", _PyCFunction_CAST(bytearray_replace), METH_FASTCALL, bytearray_replace__doc__},
359
360
static PyObject *
361
bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old,
362
Py_buffer *new, Py_ssize_t count);
363
364
static PyObject *
365
bytearray_replace(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs)
366
{
367
PyObject *return_value = NULL;
368
Py_buffer old = {NULL, NULL};
369
Py_buffer new = {NULL, NULL};
370
Py_ssize_t count = -1;
371
372
if (!_PyArg_CheckPositional("replace", nargs, 2, 3)) {
373
goto exit;
374
}
375
if (PyObject_GetBuffer(args[0], &old, PyBUF_SIMPLE) != 0) {
376
goto exit;
377
}
378
if (!PyBuffer_IsContiguous(&old, 'C')) {
379
_PyArg_BadArgument("replace", "argument 1", "contiguous buffer", args[0]);
380
goto exit;
381
}
382
if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) {
383
goto exit;
384
}
385
if (!PyBuffer_IsContiguous(&new, 'C')) {
386
_PyArg_BadArgument("replace", "argument 2", "contiguous buffer", args[1]);
387
goto exit;
388
}
389
if (nargs < 3) {
390
goto skip_optional;
391
}
392
{
393
Py_ssize_t ival = -1;
394
PyObject *iobj = _PyNumber_Index(args[2]);
395
if (iobj != NULL) {
396
ival = PyLong_AsSsize_t(iobj);
397
Py_DECREF(iobj);
398
}
399
if (ival == -1 && PyErr_Occurred()) {
400
goto exit;
401
}
402
count = ival;
403
}
404
skip_optional:
405
return_value = bytearray_replace_impl(self, &old, &new, count);
406
407
exit:
408
/* Cleanup for old */
409
if (old.obj) {
410
PyBuffer_Release(&old);
411
}
412
/* Cleanup for new */
413
if (new.obj) {
414
PyBuffer_Release(&new);
415
}
416
417
return return_value;
418
}
419
420
PyDoc_STRVAR(bytearray_split__doc__,
421
"split($self, /, sep=None, maxsplit=-1)\n"
422
"--\n"
423
"\n"
424
"Return a list of the sections in the bytearray, using sep as the delimiter.\n"
425
"\n"
426
" sep\n"
427
" The delimiter according which to split the bytearray.\n"
428
" None (the default value) means split on ASCII whitespace characters\n"
429
" (space, tab, return, newline, formfeed, vertical tab).\n"
430
" maxsplit\n"
431
" Maximum number of splits to do.\n"
432
" -1 (the default value) means no limit.");
433
434
#define BYTEARRAY_SPLIT_METHODDEF \
435
{"split", _PyCFunction_CAST(bytearray_split), METH_FASTCALL|METH_KEYWORDS, bytearray_split__doc__},
436
437
static PyObject *
438
bytearray_split_impl(PyByteArrayObject *self, PyObject *sep,
439
Py_ssize_t maxsplit);
440
441
static PyObject *
442
bytearray_split(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
443
{
444
PyObject *return_value = NULL;
445
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
446
447
#define NUM_KEYWORDS 2
448
static struct {
449
PyGC_Head _this_is_not_used;
450
PyObject_VAR_HEAD
451
PyObject *ob_item[NUM_KEYWORDS];
452
} _kwtuple = {
453
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
454
.ob_item = { &_Py_ID(sep), &_Py_ID(maxsplit), },
455
};
456
#undef NUM_KEYWORDS
457
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
458
459
#else // !Py_BUILD_CORE
460
# define KWTUPLE NULL
461
#endif // !Py_BUILD_CORE
462
463
static const char * const _keywords[] = {"sep", "maxsplit", NULL};
464
static _PyArg_Parser _parser = {
465
.keywords = _keywords,
466
.fname = "split",
467
.kwtuple = KWTUPLE,
468
};
469
#undef KWTUPLE
470
PyObject *argsbuf[2];
471
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
472
PyObject *sep = Py_None;
473
Py_ssize_t maxsplit = -1;
474
475
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf);
476
if (!args) {
477
goto exit;
478
}
479
if (!noptargs) {
480
goto skip_optional_pos;
481
}
482
if (args[0]) {
483
sep = args[0];
484
if (!--noptargs) {
485
goto skip_optional_pos;
486
}
487
}
488
{
489
Py_ssize_t ival = -1;
490
PyObject *iobj = _PyNumber_Index(args[1]);
491
if (iobj != NULL) {
492
ival = PyLong_AsSsize_t(iobj);
493
Py_DECREF(iobj);
494
}
495
if (ival == -1 && PyErr_Occurred()) {
496
goto exit;
497
}
498
maxsplit = ival;
499
}
500
skip_optional_pos:
501
return_value = bytearray_split_impl(self, sep, maxsplit);
502
503
exit:
504
return return_value;
505
}
506
507
PyDoc_STRVAR(bytearray_partition__doc__,
508
"partition($self, sep, /)\n"
509
"--\n"
510
"\n"
511
"Partition the bytearray into three parts using the given separator.\n"
512
"\n"
513
"This will search for the separator sep in the bytearray. If the separator is\n"
514
"found, returns a 3-tuple containing the part before the separator, the\n"
515
"separator itself, and the part after it as new bytearray objects.\n"
516
"\n"
517
"If the separator is not found, returns a 3-tuple containing the copy of the\n"
518
"original bytearray object and two empty bytearray objects.");
519
520
#define BYTEARRAY_PARTITION_METHODDEF \
521
{"partition", (PyCFunction)bytearray_partition, METH_O, bytearray_partition__doc__},
522
523
PyDoc_STRVAR(bytearray_rpartition__doc__,
524
"rpartition($self, sep, /)\n"
525
"--\n"
526
"\n"
527
"Partition the bytearray into three parts using the given separator.\n"
528
"\n"
529
"This will search for the separator sep in the bytearray, starting at the end.\n"
530
"If the separator is found, returns a 3-tuple containing the part before the\n"
531
"separator, the separator itself, and the part after it as new bytearray\n"
532
"objects.\n"
533
"\n"
534
"If the separator is not found, returns a 3-tuple containing two empty bytearray\n"
535
"objects and the copy of the original bytearray object.");
536
537
#define BYTEARRAY_RPARTITION_METHODDEF \
538
{"rpartition", (PyCFunction)bytearray_rpartition, METH_O, bytearray_rpartition__doc__},
539
540
PyDoc_STRVAR(bytearray_rsplit__doc__,
541
"rsplit($self, /, sep=None, maxsplit=-1)\n"
542
"--\n"
543
"\n"
544
"Return a list of the sections in the bytearray, using sep as the delimiter.\n"
545
"\n"
546
" sep\n"
547
" The delimiter according which to split the bytearray.\n"
548
" None (the default value) means split on ASCII whitespace characters\n"
549
" (space, tab, return, newline, formfeed, vertical tab).\n"
550
" maxsplit\n"
551
" Maximum number of splits to do.\n"
552
" -1 (the default value) means no limit.\n"
553
"\n"
554
"Splitting is done starting at the end of the bytearray and working to the front.");
555
556
#define BYTEARRAY_RSPLIT_METHODDEF \
557
{"rsplit", _PyCFunction_CAST(bytearray_rsplit), METH_FASTCALL|METH_KEYWORDS, bytearray_rsplit__doc__},
558
559
static PyObject *
560
bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep,
561
Py_ssize_t maxsplit);
562
563
static PyObject *
564
bytearray_rsplit(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
565
{
566
PyObject *return_value = NULL;
567
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
568
569
#define NUM_KEYWORDS 2
570
static struct {
571
PyGC_Head _this_is_not_used;
572
PyObject_VAR_HEAD
573
PyObject *ob_item[NUM_KEYWORDS];
574
} _kwtuple = {
575
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
576
.ob_item = { &_Py_ID(sep), &_Py_ID(maxsplit), },
577
};
578
#undef NUM_KEYWORDS
579
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
580
581
#else // !Py_BUILD_CORE
582
# define KWTUPLE NULL
583
#endif // !Py_BUILD_CORE
584
585
static const char * const _keywords[] = {"sep", "maxsplit", NULL};
586
static _PyArg_Parser _parser = {
587
.keywords = _keywords,
588
.fname = "rsplit",
589
.kwtuple = KWTUPLE,
590
};
591
#undef KWTUPLE
592
PyObject *argsbuf[2];
593
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
594
PyObject *sep = Py_None;
595
Py_ssize_t maxsplit = -1;
596
597
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf);
598
if (!args) {
599
goto exit;
600
}
601
if (!noptargs) {
602
goto skip_optional_pos;
603
}
604
if (args[0]) {
605
sep = args[0];
606
if (!--noptargs) {
607
goto skip_optional_pos;
608
}
609
}
610
{
611
Py_ssize_t ival = -1;
612
PyObject *iobj = _PyNumber_Index(args[1]);
613
if (iobj != NULL) {
614
ival = PyLong_AsSsize_t(iobj);
615
Py_DECREF(iobj);
616
}
617
if (ival == -1 && PyErr_Occurred()) {
618
goto exit;
619
}
620
maxsplit = ival;
621
}
622
skip_optional_pos:
623
return_value = bytearray_rsplit_impl(self, sep, maxsplit);
624
625
exit:
626
return return_value;
627
}
628
629
PyDoc_STRVAR(bytearray_reverse__doc__,
630
"reverse($self, /)\n"
631
"--\n"
632
"\n"
633
"Reverse the order of the values in B in place.");
634
635
#define BYTEARRAY_REVERSE_METHODDEF \
636
{"reverse", (PyCFunction)bytearray_reverse, METH_NOARGS, bytearray_reverse__doc__},
637
638
static PyObject *
639
bytearray_reverse_impl(PyByteArrayObject *self);
640
641
static PyObject *
642
bytearray_reverse(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
643
{
644
return bytearray_reverse_impl(self);
645
}
646
647
PyDoc_STRVAR(bytearray_insert__doc__,
648
"insert($self, index, item, /)\n"
649
"--\n"
650
"\n"
651
"Insert a single item into the bytearray before the given index.\n"
652
"\n"
653
" index\n"
654
" The index where the value is to be inserted.\n"
655
" item\n"
656
" The item to be inserted.");
657
658
#define BYTEARRAY_INSERT_METHODDEF \
659
{"insert", _PyCFunction_CAST(bytearray_insert), METH_FASTCALL, bytearray_insert__doc__},
660
661
static PyObject *
662
bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item);
663
664
static PyObject *
665
bytearray_insert(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs)
666
{
667
PyObject *return_value = NULL;
668
Py_ssize_t index;
669
int item;
670
671
if (!_PyArg_CheckPositional("insert", nargs, 2, 2)) {
672
goto exit;
673
}
674
{
675
Py_ssize_t ival = -1;
676
PyObject *iobj = _PyNumber_Index(args[0]);
677
if (iobj != NULL) {
678
ival = PyLong_AsSsize_t(iobj);
679
Py_DECREF(iobj);
680
}
681
if (ival == -1 && PyErr_Occurred()) {
682
goto exit;
683
}
684
index = ival;
685
}
686
if (!_getbytevalue(args[1], &item)) {
687
goto exit;
688
}
689
return_value = bytearray_insert_impl(self, index, item);
690
691
exit:
692
return return_value;
693
}
694
695
PyDoc_STRVAR(bytearray_append__doc__,
696
"append($self, item, /)\n"
697
"--\n"
698
"\n"
699
"Append a single item to the end of the bytearray.\n"
700
"\n"
701
" item\n"
702
" The item to be appended.");
703
704
#define BYTEARRAY_APPEND_METHODDEF \
705
{"append", (PyCFunction)bytearray_append, METH_O, bytearray_append__doc__},
706
707
static PyObject *
708
bytearray_append_impl(PyByteArrayObject *self, int item);
709
710
static PyObject *
711
bytearray_append(PyByteArrayObject *self, PyObject *arg)
712
{
713
PyObject *return_value = NULL;
714
int item;
715
716
if (!_getbytevalue(arg, &item)) {
717
goto exit;
718
}
719
return_value = bytearray_append_impl(self, item);
720
721
exit:
722
return return_value;
723
}
724
725
PyDoc_STRVAR(bytearray_extend__doc__,
726
"extend($self, iterable_of_ints, /)\n"
727
"--\n"
728
"\n"
729
"Append all the items from the iterator or sequence to the end of the bytearray.\n"
730
"\n"
731
" iterable_of_ints\n"
732
" The iterable of items to append.");
733
734
#define BYTEARRAY_EXTEND_METHODDEF \
735
{"extend", (PyCFunction)bytearray_extend, METH_O, bytearray_extend__doc__},
736
737
PyDoc_STRVAR(bytearray_pop__doc__,
738
"pop($self, index=-1, /)\n"
739
"--\n"
740
"\n"
741
"Remove and return a single item from B.\n"
742
"\n"
743
" index\n"
744
" The index from where to remove the item.\n"
745
" -1 (the default value) means remove the last item.\n"
746
"\n"
747
"If no index argument is given, will pop the last item.");
748
749
#define BYTEARRAY_POP_METHODDEF \
750
{"pop", _PyCFunction_CAST(bytearray_pop), METH_FASTCALL, bytearray_pop__doc__},
751
752
static PyObject *
753
bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index);
754
755
static PyObject *
756
bytearray_pop(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs)
757
{
758
PyObject *return_value = NULL;
759
Py_ssize_t index = -1;
760
761
if (!_PyArg_CheckPositional("pop", nargs, 0, 1)) {
762
goto exit;
763
}
764
if (nargs < 1) {
765
goto skip_optional;
766
}
767
{
768
Py_ssize_t ival = -1;
769
PyObject *iobj = _PyNumber_Index(args[0]);
770
if (iobj != NULL) {
771
ival = PyLong_AsSsize_t(iobj);
772
Py_DECREF(iobj);
773
}
774
if (ival == -1 && PyErr_Occurred()) {
775
goto exit;
776
}
777
index = ival;
778
}
779
skip_optional:
780
return_value = bytearray_pop_impl(self, index);
781
782
exit:
783
return return_value;
784
}
785
786
PyDoc_STRVAR(bytearray_remove__doc__,
787
"remove($self, value, /)\n"
788
"--\n"
789
"\n"
790
"Remove the first occurrence of a value in the bytearray.\n"
791
"\n"
792
" value\n"
793
" The value to remove.");
794
795
#define BYTEARRAY_REMOVE_METHODDEF \
796
{"remove", (PyCFunction)bytearray_remove, METH_O, bytearray_remove__doc__},
797
798
static PyObject *
799
bytearray_remove_impl(PyByteArrayObject *self, int value);
800
801
static PyObject *
802
bytearray_remove(PyByteArrayObject *self, PyObject *arg)
803
{
804
PyObject *return_value = NULL;
805
int value;
806
807
if (!_getbytevalue(arg, &value)) {
808
goto exit;
809
}
810
return_value = bytearray_remove_impl(self, value);
811
812
exit:
813
return return_value;
814
}
815
816
PyDoc_STRVAR(bytearray_strip__doc__,
817
"strip($self, bytes=None, /)\n"
818
"--\n"
819
"\n"
820
"Strip leading and trailing bytes contained in the argument.\n"
821
"\n"
822
"If the argument is omitted or None, strip leading and trailing ASCII whitespace.");
823
824
#define BYTEARRAY_STRIP_METHODDEF \
825
{"strip", _PyCFunction_CAST(bytearray_strip), METH_FASTCALL, bytearray_strip__doc__},
826
827
static PyObject *
828
bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes);
829
830
static PyObject *
831
bytearray_strip(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs)
832
{
833
PyObject *return_value = NULL;
834
PyObject *bytes = Py_None;
835
836
if (!_PyArg_CheckPositional("strip", nargs, 0, 1)) {
837
goto exit;
838
}
839
if (nargs < 1) {
840
goto skip_optional;
841
}
842
bytes = args[0];
843
skip_optional:
844
return_value = bytearray_strip_impl(self, bytes);
845
846
exit:
847
return return_value;
848
}
849
850
PyDoc_STRVAR(bytearray_lstrip__doc__,
851
"lstrip($self, bytes=None, /)\n"
852
"--\n"
853
"\n"
854
"Strip leading bytes contained in the argument.\n"
855
"\n"
856
"If the argument is omitted or None, strip leading ASCII whitespace.");
857
858
#define BYTEARRAY_LSTRIP_METHODDEF \
859
{"lstrip", _PyCFunction_CAST(bytearray_lstrip), METH_FASTCALL, bytearray_lstrip__doc__},
860
861
static PyObject *
862
bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes);
863
864
static PyObject *
865
bytearray_lstrip(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs)
866
{
867
PyObject *return_value = NULL;
868
PyObject *bytes = Py_None;
869
870
if (!_PyArg_CheckPositional("lstrip", nargs, 0, 1)) {
871
goto exit;
872
}
873
if (nargs < 1) {
874
goto skip_optional;
875
}
876
bytes = args[0];
877
skip_optional:
878
return_value = bytearray_lstrip_impl(self, bytes);
879
880
exit:
881
return return_value;
882
}
883
884
PyDoc_STRVAR(bytearray_rstrip__doc__,
885
"rstrip($self, bytes=None, /)\n"
886
"--\n"
887
"\n"
888
"Strip trailing bytes contained in the argument.\n"
889
"\n"
890
"If the argument is omitted or None, strip trailing ASCII whitespace.");
891
892
#define BYTEARRAY_RSTRIP_METHODDEF \
893
{"rstrip", _PyCFunction_CAST(bytearray_rstrip), METH_FASTCALL, bytearray_rstrip__doc__},
894
895
static PyObject *
896
bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes);
897
898
static PyObject *
899
bytearray_rstrip(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs)
900
{
901
PyObject *return_value = NULL;
902
PyObject *bytes = Py_None;
903
904
if (!_PyArg_CheckPositional("rstrip", nargs, 0, 1)) {
905
goto exit;
906
}
907
if (nargs < 1) {
908
goto skip_optional;
909
}
910
bytes = args[0];
911
skip_optional:
912
return_value = bytearray_rstrip_impl(self, bytes);
913
914
exit:
915
return return_value;
916
}
917
918
PyDoc_STRVAR(bytearray_decode__doc__,
919
"decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n"
920
"--\n"
921
"\n"
922
"Decode the bytearray using the codec registered for encoding.\n"
923
"\n"
924
" encoding\n"
925
" The encoding with which to decode the bytearray.\n"
926
" errors\n"
927
" The error handling scheme to use for the handling of decoding errors.\n"
928
" The default is \'strict\' meaning that decoding errors raise a\n"
929
" UnicodeDecodeError. Other possible values are \'ignore\' and \'replace\'\n"
930
" as well as any other name registered with codecs.register_error that\n"
931
" can handle UnicodeDecodeErrors.");
932
933
#define BYTEARRAY_DECODE_METHODDEF \
934
{"decode", _PyCFunction_CAST(bytearray_decode), METH_FASTCALL|METH_KEYWORDS, bytearray_decode__doc__},
935
936
static PyObject *
937
bytearray_decode_impl(PyByteArrayObject *self, const char *encoding,
938
const char *errors);
939
940
static PyObject *
941
bytearray_decode(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
942
{
943
PyObject *return_value = NULL;
944
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
945
946
#define NUM_KEYWORDS 2
947
static struct {
948
PyGC_Head _this_is_not_used;
949
PyObject_VAR_HEAD
950
PyObject *ob_item[NUM_KEYWORDS];
951
} _kwtuple = {
952
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
953
.ob_item = { &_Py_ID(encoding), &_Py_ID(errors), },
954
};
955
#undef NUM_KEYWORDS
956
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
957
958
#else // !Py_BUILD_CORE
959
# define KWTUPLE NULL
960
#endif // !Py_BUILD_CORE
961
962
static const char * const _keywords[] = {"encoding", "errors", NULL};
963
static _PyArg_Parser _parser = {
964
.keywords = _keywords,
965
.fname = "decode",
966
.kwtuple = KWTUPLE,
967
};
968
#undef KWTUPLE
969
PyObject *argsbuf[2];
970
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
971
const char *encoding = NULL;
972
const char *errors = NULL;
973
974
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf);
975
if (!args) {
976
goto exit;
977
}
978
if (!noptargs) {
979
goto skip_optional_pos;
980
}
981
if (args[0]) {
982
if (!PyUnicode_Check(args[0])) {
983
_PyArg_BadArgument("decode", "argument 'encoding'", "str", args[0]);
984
goto exit;
985
}
986
Py_ssize_t encoding_length;
987
encoding = PyUnicode_AsUTF8AndSize(args[0], &encoding_length);
988
if (encoding == NULL) {
989
goto exit;
990
}
991
if (strlen(encoding) != (size_t)encoding_length) {
992
PyErr_SetString(PyExc_ValueError, "embedded null character");
993
goto exit;
994
}
995
if (!--noptargs) {
996
goto skip_optional_pos;
997
}
998
}
999
if (!PyUnicode_Check(args[1])) {
1000
_PyArg_BadArgument("decode", "argument 'errors'", "str", args[1]);
1001
goto exit;
1002
}
1003
Py_ssize_t errors_length;
1004
errors = PyUnicode_AsUTF8AndSize(args[1], &errors_length);
1005
if (errors == NULL) {
1006
goto exit;
1007
}
1008
if (strlen(errors) != (size_t)errors_length) {
1009
PyErr_SetString(PyExc_ValueError, "embedded null character");
1010
goto exit;
1011
}
1012
skip_optional_pos:
1013
return_value = bytearray_decode_impl(self, encoding, errors);
1014
1015
exit:
1016
return return_value;
1017
}
1018
1019
PyDoc_STRVAR(bytearray_join__doc__,
1020
"join($self, iterable_of_bytes, /)\n"
1021
"--\n"
1022
"\n"
1023
"Concatenate any number of bytes/bytearray objects.\n"
1024
"\n"
1025
"The bytearray whose method is called is inserted in between each pair.\n"
1026
"\n"
1027
"The result is returned as a new bytearray object.");
1028
1029
#define BYTEARRAY_JOIN_METHODDEF \
1030
{"join", (PyCFunction)bytearray_join, METH_O, bytearray_join__doc__},
1031
1032
PyDoc_STRVAR(bytearray_splitlines__doc__,
1033
"splitlines($self, /, keepends=False)\n"
1034
"--\n"
1035
"\n"
1036
"Return a list of the lines in the bytearray, breaking at line boundaries.\n"
1037
"\n"
1038
"Line breaks are not included in the resulting list unless keepends is given and\n"
1039
"true.");
1040
1041
#define BYTEARRAY_SPLITLINES_METHODDEF \
1042
{"splitlines", _PyCFunction_CAST(bytearray_splitlines), METH_FASTCALL|METH_KEYWORDS, bytearray_splitlines__doc__},
1043
1044
static PyObject *
1045
bytearray_splitlines_impl(PyByteArrayObject *self, int keepends);
1046
1047
static PyObject *
1048
bytearray_splitlines(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
1049
{
1050
PyObject *return_value = NULL;
1051
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
1052
1053
#define NUM_KEYWORDS 1
1054
static struct {
1055
PyGC_Head _this_is_not_used;
1056
PyObject_VAR_HEAD
1057
PyObject *ob_item[NUM_KEYWORDS];
1058
} _kwtuple = {
1059
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
1060
.ob_item = { &_Py_ID(keepends), },
1061
};
1062
#undef NUM_KEYWORDS
1063
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
1064
1065
#else // !Py_BUILD_CORE
1066
# define KWTUPLE NULL
1067
#endif // !Py_BUILD_CORE
1068
1069
static const char * const _keywords[] = {"keepends", NULL};
1070
static _PyArg_Parser _parser = {
1071
.keywords = _keywords,
1072
.fname = "splitlines",
1073
.kwtuple = KWTUPLE,
1074
};
1075
#undef KWTUPLE
1076
PyObject *argsbuf[1];
1077
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
1078
int keepends = 0;
1079
1080
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
1081
if (!args) {
1082
goto exit;
1083
}
1084
if (!noptargs) {
1085
goto skip_optional_pos;
1086
}
1087
keepends = PyObject_IsTrue(args[0]);
1088
if (keepends < 0) {
1089
goto exit;
1090
}
1091
skip_optional_pos:
1092
return_value = bytearray_splitlines_impl(self, keepends);
1093
1094
exit:
1095
return return_value;
1096
}
1097
1098
PyDoc_STRVAR(bytearray_fromhex__doc__,
1099
"fromhex($type, string, /)\n"
1100
"--\n"
1101
"\n"
1102
"Create a bytearray object from a string of hexadecimal numbers.\n"
1103
"\n"
1104
"Spaces between two numbers are accepted.\n"
1105
"Example: bytearray.fromhex(\'B9 01EF\') -> bytearray(b\'\\\\xb9\\\\x01\\\\xef\')");
1106
1107
#define BYTEARRAY_FROMHEX_METHODDEF \
1108
{"fromhex", (PyCFunction)bytearray_fromhex, METH_O|METH_CLASS, bytearray_fromhex__doc__},
1109
1110
static PyObject *
1111
bytearray_fromhex_impl(PyTypeObject *type, PyObject *string);
1112
1113
static PyObject *
1114
bytearray_fromhex(PyTypeObject *type, PyObject *arg)
1115
{
1116
PyObject *return_value = NULL;
1117
PyObject *string;
1118
1119
if (!PyUnicode_Check(arg)) {
1120
_PyArg_BadArgument("fromhex", "argument", "str", arg);
1121
goto exit;
1122
}
1123
string = arg;
1124
return_value = bytearray_fromhex_impl(type, string);
1125
1126
exit:
1127
return return_value;
1128
}
1129
1130
PyDoc_STRVAR(bytearray_hex__doc__,
1131
"hex($self, /, sep=<unrepresentable>, bytes_per_sep=1)\n"
1132
"--\n"
1133
"\n"
1134
"Create a string of hexadecimal numbers from a bytearray object.\n"
1135
"\n"
1136
" sep\n"
1137
" An optional single character or byte to separate hex bytes.\n"
1138
" bytes_per_sep\n"
1139
" How many bytes between separators. Positive values count from the\n"
1140
" right, negative values count from the left.\n"
1141
"\n"
1142
"Example:\n"
1143
">>> value = bytearray([0xb9, 0x01, 0xef])\n"
1144
">>> value.hex()\n"
1145
"\'b901ef\'\n"
1146
">>> value.hex(\':\')\n"
1147
"\'b9:01:ef\'\n"
1148
">>> value.hex(\':\', 2)\n"
1149
"\'b9:01ef\'\n"
1150
">>> value.hex(\':\', -2)\n"
1151
"\'b901:ef\'");
1152
1153
#define BYTEARRAY_HEX_METHODDEF \
1154
{"hex", _PyCFunction_CAST(bytearray_hex), METH_FASTCALL|METH_KEYWORDS, bytearray_hex__doc__},
1155
1156
static PyObject *
1157
bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep);
1158
1159
static PyObject *
1160
bytearray_hex(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
1161
{
1162
PyObject *return_value = NULL;
1163
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
1164
1165
#define NUM_KEYWORDS 2
1166
static struct {
1167
PyGC_Head _this_is_not_used;
1168
PyObject_VAR_HEAD
1169
PyObject *ob_item[NUM_KEYWORDS];
1170
} _kwtuple = {
1171
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
1172
.ob_item = { &_Py_ID(sep), &_Py_ID(bytes_per_sep), },
1173
};
1174
#undef NUM_KEYWORDS
1175
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
1176
1177
#else // !Py_BUILD_CORE
1178
# define KWTUPLE NULL
1179
#endif // !Py_BUILD_CORE
1180
1181
static const char * const _keywords[] = {"sep", "bytes_per_sep", NULL};
1182
static _PyArg_Parser _parser = {
1183
.keywords = _keywords,
1184
.fname = "hex",
1185
.kwtuple = KWTUPLE,
1186
};
1187
#undef KWTUPLE
1188
PyObject *argsbuf[2];
1189
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
1190
PyObject *sep = NULL;
1191
int bytes_per_sep = 1;
1192
1193
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf);
1194
if (!args) {
1195
goto exit;
1196
}
1197
if (!noptargs) {
1198
goto skip_optional_pos;
1199
}
1200
if (args[0]) {
1201
sep = args[0];
1202
if (!--noptargs) {
1203
goto skip_optional_pos;
1204
}
1205
}
1206
bytes_per_sep = _PyLong_AsInt(args[1]);
1207
if (bytes_per_sep == -1 && PyErr_Occurred()) {
1208
goto exit;
1209
}
1210
skip_optional_pos:
1211
return_value = bytearray_hex_impl(self, sep, bytes_per_sep);
1212
1213
exit:
1214
return return_value;
1215
}
1216
1217
PyDoc_STRVAR(bytearray_reduce__doc__,
1218
"__reduce__($self, /)\n"
1219
"--\n"
1220
"\n"
1221
"Return state information for pickling.");
1222
1223
#define BYTEARRAY_REDUCE_METHODDEF \
1224
{"__reduce__", (PyCFunction)bytearray_reduce, METH_NOARGS, bytearray_reduce__doc__},
1225
1226
static PyObject *
1227
bytearray_reduce_impl(PyByteArrayObject *self);
1228
1229
static PyObject *
1230
bytearray_reduce(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
1231
{
1232
return bytearray_reduce_impl(self);
1233
}
1234
1235
PyDoc_STRVAR(bytearray_reduce_ex__doc__,
1236
"__reduce_ex__($self, proto=0, /)\n"
1237
"--\n"
1238
"\n"
1239
"Return state information for pickling.");
1240
1241
#define BYTEARRAY_REDUCE_EX_METHODDEF \
1242
{"__reduce_ex__", _PyCFunction_CAST(bytearray_reduce_ex), METH_FASTCALL, bytearray_reduce_ex__doc__},
1243
1244
static PyObject *
1245
bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto);
1246
1247
static PyObject *
1248
bytearray_reduce_ex(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs)
1249
{
1250
PyObject *return_value = NULL;
1251
int proto = 0;
1252
1253
if (!_PyArg_CheckPositional("__reduce_ex__", nargs, 0, 1)) {
1254
goto exit;
1255
}
1256
if (nargs < 1) {
1257
goto skip_optional;
1258
}
1259
proto = _PyLong_AsInt(args[0]);
1260
if (proto == -1 && PyErr_Occurred()) {
1261
goto exit;
1262
}
1263
skip_optional:
1264
return_value = bytearray_reduce_ex_impl(self, proto);
1265
1266
exit:
1267
return return_value;
1268
}
1269
1270
PyDoc_STRVAR(bytearray_sizeof__doc__,
1271
"__sizeof__($self, /)\n"
1272
"--\n"
1273
"\n"
1274
"Returns the size of the bytearray object in memory, in bytes.");
1275
1276
#define BYTEARRAY_SIZEOF_METHODDEF \
1277
{"__sizeof__", (PyCFunction)bytearray_sizeof, METH_NOARGS, bytearray_sizeof__doc__},
1278
1279
static PyObject *
1280
bytearray_sizeof_impl(PyByteArrayObject *self);
1281
1282
static PyObject *
1283
bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
1284
{
1285
return bytearray_sizeof_impl(self);
1286
}
1287
/*[clinic end generated code: output=0817195f176cd8e3 input=a9049054013a1b77]*/
1288
1289