TaylanUB / scheme-bytestructures

Structured access to bytevector contents.
GNU General Public License v3.0
36 stars 6 forks source link

extend bs:pointer to allow indexing with integers #39

Closed mwette closed 3 years ago

mwette commented 4 years ago

Consider extending the bs:pointer descriptor to allow integer indexes.
In C pointers are deferenced using array syntax as if they were arrays:

int *a;   => (define a (bytestructure (bs:pointer int) ...)
int x = a[3];  => (define x (bytestructure-ref a 3))

candidate patch to guile/pointer.scm:

--- bs-pointer.scm  2020-03-02 15:19:13.046101687 -0800
+++ fh-pointer.scm  2020-03-02 15:38:35.242496103 -0800
@@ -57,6 +57,13 @@
         (error "Tried to dereference null-pointer.")
         (ffi:pointer->bytevector (ffi:make-pointer address) content-size))))

+(define (pointer-idx-ref bytevector offset index content-size)
+  (let* ((base-address (bytevector-address-ref bytevector offset))
+    (address (+ base-address (* index content-size))))
+    (if (zero? base-address)
+   (error "Tried to dereference null-pointer.")
+   (ffi:pointer->bytevector (ffi:make-pointer address) content-size))))
+
 (define (pointer-set! bytevector offset value)
   (cond
    ((exact-integer? value)
@@ -88,17 +95,24 @@
       (when (eq? 'void descriptor)
         (error "Tried to follow void pointer."))
       (let* ((size (bytestructure-descriptor-size descriptor))
-             (bytevector* (if syntax?
-                              #`(pointer-ref #,bytevector #,offset #,size)
-                              (pointer-ref bytevector offset size)))
-             (index-datum (if syntax? (syntax->datum index) index)))
-        (if (eq? '* index-datum)
-            (values bytevector* 0 descriptor)
-            (if syntax?
-                (bytestructure-unwrap/syntax
-                 bytevector* 0 descriptor (syntax-list index index))
-                (bytestructure-unwrap*
-                 bytevector* 0 descriptor index))))))
+        (index-datum (if syntax? (syntax->datum index) index)))
+   (cond
+    ((eq? '* index-datum)
+     (if syntax?
+         (values #`(pointer-ref #,bytevector #,offset #,size) 0 descriptor)
+         (values (pointer-ref bytevector offset size) 0 descriptor)))
+    ((integer? index-datum)
+     (if syntax?
+         (values #`(pointer-idx-ref #,bytevector #,offset ,index #,size))
+         (values (pointer-idx-ref bytevector offset index-datum size))))
+    (else
+     (if syntax?
+         (let ((bytevector* #`(pointer-ref #,bytevector #,offset #,size)))
+       (bytestructure-unwrap/syntax
+        bytevector* 0 descriptor (syntax-list index index)))
+         (let ((bytevector* (pointer-ref bytevector offset size)))
+       (bytestructure-unwrap*
+        bytevector* 0 descriptor index))))))))
   (define (getter syntax? bytevector offset)
     (if syntax?
         #`(bytevector-address-ref #,bytevector #,offset)
TaylanUB commented 3 years ago

Thanks for the patch, I applied a modified version of it.

I decided to deprecate implicit dereferencing of pointers, so if you used to make use of that, you will now have to make sure that you always dereference pointers explicitly.

The reason is twofold:

I think I've tested the change thoroughly enough so I'm closing this; please reopen if you face any issues.

mwette commented 3 years ago

got it -- I will be working on this next weekend