pg_base32_crockford.sql (2045B)
1 -- 2 -- This file is part of TALER 3 -- Copyright (C) 2026 Taler Systems SA 4 -- 5 -- TALER is free software; you can redistribute it and/or modify it under the 6 -- terms of the GNU General Public License as published by the Free Software 7 -- Foundation; either version 3, or (at your option) any later version. 8 -- 9 -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 -- 13 -- You should have received a copy of the GNU General Public License along with 14 -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 -- 16 17 DROP FUNCTION IF EXISTS base32_crockford; 18 CREATE FUNCTION base32_crockford(data BYTEA) 19 RETURNS TEXT 20 LANGUAGE plpgsql 21 IMMUTABLE 22 STRICT 23 PARALLEL SAFE 24 AS $$ 25 DECLARE 26 alphabet TEXT := '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; 27 chars TEXT[] := '{}'; 28 bit_buf BIGINT := 0; -- sliding window of accumulated bits 29 bit_count INT := 0; -- how many valid bits are in bit_buf 30 b INT; 31 i INT; 32 BEGIN 33 IF length(data) = 0 THEN 34 RETURN ''; 35 END IF; 36 37 -- Process each byte, emitting 5-bit groups as we go 38 FOR i IN 0 .. length(data) - 1 39 LOOP 40 b := get_byte(data, i); 41 bit_buf := (bit_buf << 8) | b; 42 bit_count := bit_count + 8; 43 44 WHILE bit_count >= 5 45 LOOP 46 bit_count := bit_count - 5; 47 chars := array_append( 48 chars, 49 substr(alphabet, ((bit_buf >> bit_count) & 31)::INT + 1, 1) 50 ); 51 END LOOP; 52 END LOOP; 53 54 -- Flush any remaining bits (zero-padded to 5) 55 IF bit_count > 0 56 THEN 57 chars := array_append( 58 chars, 59 substr(alphabet, ((bit_buf << (5 - bit_count)) & 31)::INT + 1, 1) 60 ); 61 END IF; 62 RETURN array_to_string(chars, ''); 63 END; 64 $$; 65 COMMENT ON FUNCTION base32_crockford(BYTEA) 66 IS 'Encodes binary data using Crockford Base32';