internal.scm 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. ;;; guile-gcrypt --- crypto tooling for guile
  2. ;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
  3. ;;;
  4. ;;; This file is part of guile-gcrypt.
  5. ;;;
  6. ;;; guile-gcrypt is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or
  9. ;;; (at your option) any later version.
  10. ;;;
  11. ;;; guile-gcrypt is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;;; General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with guile-gcrypt. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (gcrypt internal)
  19. #:use-module (gcrypt package-config)
  20. #:use-module (system foreign)
  21. #:export (libgcrypt->pointer
  22. libgcrypt->procedure
  23. define-enumerate-type
  24. define-lookup-procedure))
  25. ;;; Code:
  26. ;;;
  27. ;;; This module provides tools for internal use. The API of this module may
  28. ;;; change anytime; you should not rely on it.
  29. ;;;
  30. ;;; Comment:
  31. (define (libgcrypt->pointer name)
  32. "Return a pointer to symbol FUNC in libgcrypt."
  33. (catch #t
  34. (lambda ()
  35. (dynamic-func name (dynamic-link %libgcrypt)))
  36. (lambda args
  37. (lambda _
  38. (throw 'system-error name "~A" (list (strerror ENOSYS))
  39. (list ENOSYS))))))
  40. (define (libgcrypt->procedure return name params)
  41. "Return a pointer to symbol FUNC in libgcrypt."
  42. (catch #t
  43. (lambda ()
  44. (let ((ptr (dynamic-func name (dynamic-link %libgcrypt))))
  45. ;; The #:return-errno? facility was introduced in Guile 2.0.12.
  46. (pointer->procedure return ptr params
  47. #:return-errno? #t)))
  48. (lambda args
  49. (lambda _
  50. (throw 'system-error name "~A" (list (strerror ENOSYS))
  51. (list ENOSYS))))))
  52. (define-syntax-rule (define-enumerate-type name->integer symbol->integer
  53. (name id) ...)
  54. (begin
  55. (define-syntax name->integer
  56. (syntax-rules (name ...)
  57. "Return hash algorithm NAME."
  58. ((_ name) id) ...))
  59. (define symbol->integer
  60. (let ((alist '((name . id) ...)))
  61. (lambda (symbol)
  62. "Look up SYMBOL and return the corresponding integer or #f if it
  63. could not be found."
  64. (assq-ref alist symbol))))))
  65. (define-syntax define-lookup-procedure
  66. (lambda (s)
  67. "Define LOOKUP as a procedure that maps an integer to its corresponding
  68. value in O(1)."
  69. (syntax-case s ()
  70. ((_ lookup docstring (index value) ...)
  71. (let* ((values (syntax->datum #'((index . value) ...)))
  72. (min (apply min (syntax->datum #'(index ...))))
  73. (max (apply max (syntax->datum #'(index ...))))
  74. (array (let loop ((i max)
  75. (result '()))
  76. (if (< i min)
  77. result
  78. (loop (- i 1)
  79. (cons (or (assv-ref values i) -1)
  80. result))))))
  81. #`(define lookup
  82. ;; Allocate a big sparse vector.
  83. (let ((values '#(#,@array)))
  84. (lambda (integer)
  85. docstring
  86. (and (<= integer #,max) (>= integer #,min)
  87. (let ((result (vector-ref values (- integer #,min))))
  88. (and (> result 0) result)))))))))))