utils.lisp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. (in-package :hurd-common)
  2. (defun largest-representable-number (bits)
  3. "Largest representable number having 'bits' bits available"
  4. (1- (expt 2 bits)))
  5. (defun num-bits (bytes)
  6. "Tells how many bits there are in a number of bytes"
  7. (* 8 bytes))
  8. (defmacro unless-return (call &body body)
  9. "Evaluates 'call' and returns its value if true, else evaluates and returns 'body'."
  10. ;; XXX this does not actually correspond to the description,
  11. ;; as this does ot discard the second, third, ... value.
  12. #`(or #,call #,body))
  13. (defun translate-foreign-list (value ls &optional (order :from))
  14. "In a list with key/values finds a value using first/second as key, returning second/first from the item found."
  15. (let ((item (find value ls :key (if (eq order :from)
  16. #'first
  17. #'second))))
  18. (when item
  19. (if (eq order :from)
  20. (second item)
  21. (first item)))))
  22. (defmacro select-error (error-code &optional (result #'#t))
  23. "If error-code is success returns result, else returns multiple values 'nil' and 'error-code'."
  24. #`(cond
  25. ((eq #,error-code #t)
  26. #,result)
  27. (#t
  28. (values nil #,error-code))))
  29. (defmacro with-cleanup (cleanup &body body)
  30. "Unwind-protect with multiple expressions."
  31. #`(unwind-protect (progn #,@body)
  32. #,cleanup))
  33. (defmacro chained-bit-op (op &body ls)
  34. "Makes possible to have multiple arguments, instead of only two, in a boole operation."
  35. (syntax-case ls ()
  36. (() #'0)
  37. ((first . tail)
  38. #`(boole #,op
  39. first
  40. (chained-bit-op #,op . tail)))))
  41. ;; XXX verify these two defuns.
  42. ;; I don't understand the loop code.
  43. (defun %find-different (str len chr pos)
  44. "Finds the position of a char different than chr from 'pos' in 'str'"
  45. (or (string-skip str chr pos len) len))
  46. (defun split-path (str)
  47. "Splits a path into a list with each component. Examples:
  48. a/b/c -> ('a' 'b' 'c')
  49. /a/b -> ('a' 'b') ;;; <-- XXX what?
  50. a///b -> ('a' 'b') ;; <--- ditto? symlinks?
  51. a/b/c/ -> ('a', 'b', 'c', '') pay attention to the last component!"
  52. ;; XXX what if str = "/"?
  53. (let* ((l (string-split #\/ str))
  54. (last-empty? (if (null? l)
  55. #f
  56. (string=? "" (last l))))
  57. (lf (filter! (negate string-null?) l)))
  58. (if last-empty?
  59. lf
  60. (append! lf (list "")))))
  61. (defun join-path (ls)
  62. "Joins a path previously split by split-path."
  63. (string-left-trim "/" (reduce (lambda (all x)
  64. (concatenate 'string all "/" x))
  65. ls
  66. :initial-value "")))
  67. (defun %convert-list (item)
  68. (if (symbolp item)
  69. (list item)
  70. item))
  71. (defun flag-is? (flags flag)
  72. "Checks if flags has the flag or flag's list 'flag' enabled."
  73. (let ((new-list (%convert-list flag)))
  74. (equal new-list
  75. (intersection flags new-list))))
  76. (defun enable-flags (flags new-flags)
  77. "Enable all flags in new-flags."
  78. (union flags (%convert-list new-flags)))
  79. (defun disable-flags (flags old-flags)
  80. "Disable all flags in old-flags."
  81. (set-difference flags (%convert-list old-flags)))
  82. (defun only-flags (flags new-flags)
  83. "Only enable flags in new-flags."
  84. (intersection flags (%convert-list new-flags)))
  85. (defun free-memory-list (ls)
  86. "Frees a list with pointers."
  87. (loop for item in ls
  88. do (when (and (pointerp item)
  89. (not (null-pointer-p item)))
  90. (foreign-free item))))
  91. (defun foreign-string-zero-separated-to-list (ptr ptr-len)
  92. "Converts a foreign string sequence separated by '\0' into a list of lisp strings."
  93. (let ((total-len 0))
  94. (loop until (eq total-len ptr-len)
  95. collect (let* ((str (foreign-string-to-lisp ptr))
  96. (len (1+ (length str))))
  97. (incf-pointer ptr len)
  98. (incf total-len len)
  99. str))))
  100. (defmacro concatenate-string (&body rest)
  101. "Use concatenate to concat strings."
  102. #`(concatenate 'string #,@rest))
  103. (define-syntax with-stream
  104. (syntax-rules ()
  105. "Open stream with name 'stream-name' and initialization 'init' and the close it."
  106. ((_ (stream-name init) . body)
  107. (let ((stream-name init))
  108. (with-cleanup (close stream-name)
  109. . body)))))
  110. (defun string-list-len (ls)
  111. "Given a list of strings, return a list of string lengths plus one."
  112. (mapcar 1+ (mapcar length ls)))
  113. (defun sum-list (ls)
  114. "Return sum of an number list."
  115. (apply + ls))
  116. (defun list-to-foreign-string-zero-separated (ls ptr &optional ls-len)
  117. "Write a list of strings into a foreign array. Strings are '\0'-separated.
  118. If you have the list with the length for each string pass it in ls-len."
  119. (unless ls-len
  120. (setf ls-len (string-list-len ls)))
  121. (loop* ((item #:in ls)
  122. (item-len #:in ls-len))
  123. #:do (progn
  124. (lisp-string-to-foreign item
  125. ptr
  126. item-len)
  127. (incf-pointer ptr item-len))))
  128. (defmacro remove-declare (body)
  129. "Removes a potencial declare directive from body and returns it."
  130. `(when (and (>= (length ,body) 1)
  131. (eq (first (first ,body)) 'declare))
  132. (let ((ret (first ,body)))
  133. (setf ,body (rest ,body))
  134. ret)))
  135. (defun microsecs->nanosecs (microsecs)
  136. "Convert microseconds to nanoseconds."
  137. (* microsecs 1000))
  138. (defun nanosecs->microsecs (nanosecs)
  139. "Convert nanoseconds to microseconds."
  140. (/ nanosecs 1000))