1;;; Encoding and decoding byte representations of strings 2 3;; Copyright (C) 2013, 2021 Free Software Foundation, Inc. 4 5;;;; This library is free software; you can redistribute it and/or 6;;;; modify it under the terms of the GNU Lesser General Public 7;;;; License as published by the Free Software Foundation; either 8;;;; version 3 of the License, or (at your option) any later version. 9;;;; 10;;;; This library is distributed in the hope that it will be useful, 11;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of 12;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13;;;; Lesser General Public License for more details. 14;;;; 15;;;; You should have received a copy of the GNU Lesser General Public 16;;;; License along with this library; if not, write to the Free Software 17;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 19;;; Code: 20 21(define-module (ice-9 iconv) 22 #:use-module (rnrs bytevectors) 23 #:use-module (ice-9 binary-ports) 24 #:use-module ((ice-9 rdelim) #:select (read-string)) 25 #:export (string->bytevector 26 bytevector->string 27 call-with-encoded-output-string)) 28 29(define* (call-with-encoded-output-string encoding proc 30 #:optional 31 (conversion-strategy 'error)) 32 "Call PROC on a fresh port. Encode the resulting string as a 33bytevector according to ENCODING, and return the bytevector." 34 (if (and (string-ci=? encoding "utf-8") 35 (eq? conversion-strategy 'error)) 36 ;; I don't know why, but this appears to be faster; at least for 37 ;; serving examples/debug-sxml.scm (1464 reqs/s versus 850 38 ;; reqs/s). 39 (string->utf8 (call-with-output-string proc)) 40 (call-with-output-bytevector 41 (lambda (port) 42 (set-port-encoding! port encoding) 43 (if conversion-strategy 44 (set-port-conversion-strategy! port conversion-strategy)) 45 (proc port))))) 46 47;; TODO: Provide C implementations that call scm_from_stringn and 48;; friends? 49 50(define* (string->bytevector str encoding 51 #:optional (conversion-strategy 'error)) 52 "Encode STRING according to ENCODING, which should be a string naming 53a character encoding, like \"utf-8\"." 54 (if (and (string-ci=? encoding "utf-8") 55 (eq? conversion-strategy 'error)) 56 (string->utf8 str) 57 (call-with-encoded-output-string 58 encoding 59 (lambda (port) 60 (display str port)) 61 conversion-strategy))) 62 63(define* (bytevector->string bv encoding 64 #:optional (conversion-strategy 'error)) 65 "Decode the string represented by BV. The bytes in the bytevector 66will be interpreted according to ENCODING, which should be a string 67naming a character encoding, like \"utf-8\"." 68 (if (and (string-ci=? encoding "utf-8") 69 (eq? conversion-strategy 'error)) 70 (utf8->string bv) 71 (let ((p (open-bytevector-input-port bv))) 72 (set-port-encoding! p encoding) 73 (if conversion-strategy 74 (set-port-conversion-strategy! p conversion-strategy)) 75 (let ((res (read-string p))) 76 (close-port p) 77 (if (eof-object? res) 78 "" 79 res))))) 80