PostgreSQL Source Code: src/backend/utils/adt/encode.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

15

16#include <ctype.h>

17

23

24

25

26

27

28

29

30

31

32

33

35{

40};

41

43

44

45

46

47

50{

54 char *namebuf;

55 char *dataptr;

56 size_t datalen;

60

62

64 if (enc == NULL)

66 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

67 errmsg("unrecognized encoding: \"%s\"", namebuf),

68 errhint("Valid encodings are \"%s\", \"%s\", \"%s\", and \"%s\".",

69 "base64", "base64url", "escape", "hex")));

70

73

75

76

77

78

79

82 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),

83 errmsg("result of encoding conversion is too large")));

84

86

88

89

90 if (res > resultlen)

91 elog(FATAL, "overflow - encode estimate too small");

92

94

96}

97

100{

104 char *namebuf;

105 char *dataptr;

106 size_t datalen;

110

112

114 if (enc == NULL)

116 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

117 errmsg("unrecognized encoding: \"%s\"", namebuf),

118 errhint("Valid encodings are \"%s\", \"%s\", \"%s\", and \"%s\".",

119 "base64", "base64url", "escape", "hex")));

120

123

125

126

127

128

129

132 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),

133 errmsg("result of decoding conversion is too large")));

134

136

138

139

140 if (res > resultlen)

141 elog(FATAL, "overflow - decode estimate too small");

142

144

146}

147

148

149

150

151

152

153

154

155

157"000102030405060708090a0b0c0d0e0f"

158"101112131415161718191a1b1c1d1e1f"

159"202122232425262728292a2b2c2d2e2f"

160"303132333435363738393a3b3c3d3e3f"

161"404142434445464748494a4b4c4d4e4f"

162"505152535455565758595a5b5c5d5e5f"

163"606162636465666768696a6b6c6d6e6f"

164"707172737475767778797a7b7c7d7e7f"

165"808182838485868788898a8b8c8d8e8f"

166"909192939495969798999a9b9c9d9e9f"

167"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"

168"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"

169"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"

170"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"

171"e0e1e2e3e4e5e6e7e8e9eaebecedeeef"

172"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";

173

175 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

176 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

177 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

178 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,

179 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,

180 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

181 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,

182 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

183};

184

187{

188 const char *end = src + len;

189

190 while (src < end)

191 {

192 unsigned char usrc = *((const unsigned char *) src);

193

194 memcpy(dst, &hextbl[2 * usrc], 2);

195 src++;

196 dst += 2;

197 }

199}

200

203{

204#ifdef USE_NO_SIMD

206#else

209

210

211

212

213

214

215

216 for (i = 0; i < tail_idx; i += sizeof(Vector8))

217 {

222

224

229 lo = vector8_add(lo, mask);

230

232 hi = vector8_shift_right(hi, 4);

236 hi = vector8_add(hi, mask);

237

238 vector8_store((uint8 *) &dst[i * 2],

239 vector8_interleave_low(hi, lo));

240 vector8_store((uint8 *) &dst[i * 2 + sizeof(Vector8)],

241 vector8_interleave_high(hi, lo));

242 }

243

245

247#endif

248}

249

250static inline bool

252{

253 unsigned char c = (unsigned char) *cp;

254 int res = -1;

255

256 if (c < 127)

258

259 *out = (char) res;

260

261 return (res >= 0);

262}

263

266{

268}

269

272{

273 const char *s,

274 *srcend;

275 char v1,

276 v2,

277 *p;

278

279 srcend = src + len;

280 s = src;

281 p = dst;

282 while (s < srcend)

283 {

284 if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')

285 {

286 s++;

287 continue;

288 }

291 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

292 errmsg("invalid hexadecimal digit: \"%.*s\"",

294 s++;

295 if (s >= srcend)

297 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

298 errmsg("invalid hexadecimal data: odd number of digits")));

301 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

302 errmsg("invalid hexadecimal digit: \"%.*s\"",

304 s++;

305 *p++ = (v1 << 4) | v2;

306 }

307

308 return p - dst;

309}

310

311

312

313

314

315

316

317#ifndef USE_NO_SIMD

318static inline bool

319hex_decode_simd_helper(const Vector8 src, Vector8 *dst)

320{

325 bool ret;

326

329

332 sub = vector8_add(sub, tmp);

333

336 sub = vector8_add(sub, tmp);

337

338 *dst = vector8_issub(src, sub);

339 ret = !vector8_has_ge(*dst, 0x10);

340

341 tmp = vector8_and(*dst, mask_hi);

342 tmp = vector8_shift_right(tmp, 8);

343 *dst = vector8_and(*dst, mask_lo);

344 *dst = vector8_shift_left(*dst, 4);

346 return ret;

347}

348#endif

349

352{

353#ifdef USE_NO_SIMD

355#else

359

360

361

362

363

364 for (i = 0; i < tail_idx; i += sizeof(Vector8) * 2)

365 {

369

371 success &= hex_decode_simd_helper(srcv, &dstv1);

372

374 success &= hex_decode_simd_helper(srcv, &dstv2);

375

376 vector8_store((uint8 *) &dst[i / 2], vector8_pack_16(dstv1, dstv2));

377 }

378

379

380

381

382

384 i = 0;

385

387#endif

388}

389

392{

393 return (uint64) srclen << 1;

394}

395

398{

399 return (uint64) srclen >> 1;

400}

401

402

403

404

405

407"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

408

410"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

411

413 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

414 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

415 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,

416 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,

417 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,

418 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,

419 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,

420 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,

421};

422

423

424

425

426

427

428

429

432{

433 char *p,

434 *lend = dst + 76;

435 const char *s,

436 *end = src + len;

437 int pos = 2;

440

441 s = src;

442 p = dst;

443

444 while (s < end)

445 {

446 buf |= (unsigned char) *s << (pos << 3);

447 pos--;

448 s++;

449

450

451 if (pos < 0)

452 {

453 *p++ = alphabet[(buf >> 18) & 0x3f];

454 *p++ = alphabet[(buf >> 12) & 0x3f];

455 *p++ = alphabet[(buf >> 6) & 0x3f];

456 *p++ = alphabet[buf & 0x3f];

457

458 pos = 2;

460

461 if (!url && p >= lend)

462 {

463 *p++ = '\n';

464 lend = p + 76;

465 }

466 }

467 }

468

469

470 if (pos != 2)

471 {

472 *p++ = alphabet[(buf >> 18) & 0x3f];

473 *p++ = alphabet[(buf >> 12) & 0x3f];

474

475 if (pos == 0)

476 {

477 *p++ = alphabet[(buf >> 6) & 0x3f];

478 if (!url)

479 *p++ = '=';

480 }

481 else if (!url)

482 {

483 *p++ = '=';

484 *p++ = '=';

485 }

486 }

487

488 return p - dst;

489}

490

493{

495}

496

499{

501}

502

503

504

505

506

507

508

511{

512 const char *srcend = src + len,

513 *s = src;

514 char *p = dst;

515 char c;

516 int b = 0;

518 int pos = 0,

519 end = 0;

520

521 while (s < srcend)

522 {

523 c = *s++;

524

525 if (c == ' ' || c == '\t' || c == '\n' || c == '\r')

526 continue;

527

528

529 if (url)

530 {

531 if (c == '-')

532 c = '+';

533 else if (c == '_')

534 c = '/';

535 }

536

537 if (c == '=')

538 {

539

540 if (!end)

541 {

542 if (pos == 2)

543 end = 1;

544 else if (pos == 3)

545 end = 2;

546 else

547 {

548

550 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

551 errmsg("unexpected \"=\" while decoding %s sequence", url ? "base64url" : "base64")));

552 }

553 }

554 b = 0;

555 }

556 else

557 {

558 b = -1;

559 if (c > 0 && c < 127)

561 if (b < 0)

562 {

563

565 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

566 errmsg("invalid symbol \"%.*s\" found while decoding %s sequence",

568 url ? "base64url" : "base64")));

569 }

570 }

571

573 pos++;

574 if (pos == 4)

575 {

576 *p++ = (buf >> 16) & 255;

577 if (end == 0 || end > 1)

578 *p++ = (buf >> 8) & 255;

579 if (end == 0 || end > 2)

580 *p++ = buf & 255;

582 pos = 0;

583 }

584 }

585

586 if (pos == 2)

587 {

588 buf <<= 12;

589 *p++ = (buf >> 16) & 0xFF;

590 }

591 else if (pos == 3)

592 {

593 buf <<= 6;

594 *p++ = (buf >> 16) & 0xFF;

595 *p++ = (buf >> 8) & 0xFF;

596 }

597 else if (pos != 0)

598 {

599

601 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

602 errmsg("invalid %s end sequence", url ? "base64url" : "base64"),

603 errhint("Input data is missing padding, is truncated, or is otherwise corrupted.")));

604 }

605

606 return p - dst;

607}

608

611{

613}

614

617{

619}

620

623{

624

625 return ((uint64) srclen + 2) / 3 * 4 + (uint64) srclen / (76 * 3 / 4);

626}

627

630{

631 return ((uint64) srclen * 3) >> 2;

632}

633

636{

637

638

639

640

641 return (srclen + 2) / 3 * 4;

642}

643

646{

647

648

649

650

651

652 size_t adjusted_len = srclen;

653

654 if (srclen % 4 != 0)

655 adjusted_len += 4 - (srclen % 4);

656

657 return (adjusted_len * 3) / 4;

658}

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674#define VAL(CH) ((CH) - '0')

675#define DIG(VAL) ((VAL) + '0')

676

678esc_encode(const char *src, size_t srclen, char *dst)

679{

680 const char *end = src + srclen;

681 char *rp = dst;

683

684 while (src < end)

685 {

686 unsigned char c = (unsigned char) *src;

687

689 {

690 rp[0] = '\\';

691 rp[1] = DIG(c >> 6);

692 rp[2] = DIG((c >> 3) & 7);

693 rp[3] = DIG(c & 7);

694 rp += 4;

695 len += 4;

696 }

697 else if (c == '\\')

698 {

699 rp[0] = '\\';

700 rp[1] = '\\';

701 rp += 2;

702 len += 2;

703 }

704 else

705 {

706 *rp++ = c;

708 }

709

710 src++;

711 }

712

713 return len;

714}

715

717esc_decode(const char *src, size_t srclen, char *dst)

718{

719 const char *end = src + srclen;

720 char *rp = dst;

722

723 while (src < end)

724 {

725 if (src[0] != '\\')

726 *rp++ = *src++;

727 else if (src + 3 < end &&

728 (src[1] >= '0' && src[1] <= '3') &&

729 (src[2] >= '0' && src[2] <= '7') &&

730 (src[3] >= '0' && src[3] <= '7'))

731 {

733

735 val <<= 3;

737 val <<= 3;

738 *rp++ = val + VAL(src[3]);

739 src += 4;

740 }

741 else if (src + 1 < end &&

742 (src[1] == '\\'))

743 {

744 *rp++ = '\\';

745 src += 2;

746 }

747 else

748 {

749

750

751

752

754 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),

755 errmsg("invalid input syntax for type %s", "bytea")));

756 }

757

759 }

760

761 return len;

762}

763

766{

767 const char *end = src + srclen;

769

770 while (src < end)

771 {

773 len += 4;

774 else if (*src == '\\')

775 len += 2;

776 else

778

779 src++;

780 }

781

782 return len;

783}

784

787{

788 const char *end = src + srclen;

790

791 while (src < end)

792 {

793 if (src[0] != '\\')

794 src++;

795 else if (src + 3 < end &&

796 (src[1] >= '0' && src[1] <= '3') &&

797 (src[2] >= '0' && src[2] <= '7') &&

798 (src[3] >= '0' && src[3] <= '7'))

799 {

800

801

802

803 src += 4;

804 }

805 else if (src + 1 < end &&

806 (src[1] == '\\'))

807 {

808

809

810

811 src += 2;

812 }

813 else

814 {

815

816

817

819 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),

820 errmsg("invalid input syntax for type %s", "bytea")));

821 }

822

824 }

825 return len;

826}

827

828

829

830

831

832static const struct

833{

837

838{

839 {

840 "hex",

841 {

843 }

844 },

845 {

846 "base64",

847 {

849 }

850 },

851 {

852 "base64url",

853 {

855 }

856 },

857 {

858 "escape",

859 {

861 }

862 },

863 {

864 NULL,

865 {

866 NULL, NULL, NULL, NULL

867 }

868 }

870

873{

874 int i;

875

879

880 return NULL;

881}

#define TextDatumGetCString(d)

#define IS_HIGHBIT_SET(ch)

int errhint(const char *fmt,...)

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereturn(context, dummy_value,...)

#define ereport(elevel,...)

static uint64 pg_base64_decode(const char *src, size_t len, char *dst)

static uint64 pg_base64_decode_internal(const char *src, size_t len, char *dst, bool url)

static bool get_hex(const char *cp, char *out)

static uint64 hex_dec_len(const char *src, size_t srclen)

static const struct pg_encoding * pg_find_encoding(const char *name)

static uint64 pg_base64_encode(const char *src, size_t len, char *dst)

static uint64 esc_encode(const char *src, size_t srclen, char *dst)

static uint64 hex_enc_len(const char *src, size_t srclen)

Datum binary_decode(PG_FUNCTION_ARGS)

static const struct @24 enclist[]

static const char hextbl[512]

static uint64 pg_base64url_enc_len(const char *src, size_t srclen)

static uint64 pg_base64url_decode(const char *src, size_t len, char *dst)

static const char _base64url[]

uint64 hex_decode_safe(const char *src, size_t len, char *dst, Node *escontext)

static uint64 hex_decode_safe_scalar(const char *src, size_t len, char *dst, Node *escontext)

static uint64 hex_encode_scalar(const char *src, size_t len, char *dst)

uint64 hex_encode(const char *src, size_t len, char *dst)

static uint64 esc_enc_len(const char *src, size_t srclen)

static uint64 pg_base64url_encode(const char *src, size_t len, char *dst)

static uint64 pg_base64url_dec_len(const char *src, size_t srclen)

static uint64 pg_base64_enc_len(const char *src, size_t srclen)

static uint64 pg_base64_encode_internal(const char *src, size_t len, char *dst, bool url)

static const char _base64[]

static uint64 esc_decode(const char *src, size_t srclen, char *dst)

static uint64 esc_dec_len(const char *src, size_t srclen)

Datum binary_encode(PG_FUNCTION_ARGS)

uint64 hex_decode(const char *src, size_t len, char *dst)

static const int8 b64lookup[128]

static const int8 hexlookup[128]

static uint64 pg_base64_dec_len(const char *src, size_t srclen)

#define PG_GETARG_BYTEA_PP(n)

#define PG_GETARG_TEXT_PP(n)

#define PG_RETURN_BYTEA_P(x)

#define PG_GETARG_DATUM(n)

#define PG_RETURN_TEXT_P(x)

int pg_mblen(const char *mbstr)

static char buf[DEFAULT_XLOG_SEG_SIZE]

int pg_strcasecmp(const char *s1, const char *s2)

static Vector8 vector8_broadcast(const uint8 c)

static void vector8_load(Vector8 *v, const uint8 *s)

static Vector8 vector8_or(const Vector8 v1, const Vector8 v2)

uint64(* encode_len)(const char *data, size_t dlen)

uint64(* decode_len)(const char *data, size_t dlen)

uint64(* decode)(const char *data, size_t dlen, char *res)

uint64(* encode)(const char *data, size_t dlen, char *res)

static Size VARSIZE_ANY_EXHDR(const void *PTR)

static char * VARDATA(const void *PTR)

static char * VARDATA_ANY(const void *PTR)

static void SET_VARSIZE(void *PTR, Size len)