From 1d438c5645c63aa57babfa7da0e28d95049eb200 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 14 Nov 2025 12:27:55 +0100 Subject: [PATCH] feat(types): expose `IsPacked` to help dealing with hashmaps and lists in Go code --- docs/extensions.md | 1 + types.go | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/docs/extensions.md b/docs/extensions.md index dadaa6d12..98e4f8963 100644 --- a/docs/extensions.md +++ b/docs/extensions.md @@ -211,6 +211,7 @@ func process_data_packed(arr *C.zval) unsafe.Pointer { - `frankenphp.GoAssociativeArray(arr unsafe.Pointer, ordered bool) frankenphp.AssociativeArray` - Convert a PHP array to an ordered Go `AssociativeArray` (map with order) - `frankenphp.GoMap(arr unsafe.Pointer) map[string]any` - Convert a PHP array to an unordered Go map - `frankenphp.GoPackedArray(arr unsafe.Pointer) []any` - Convert a PHP array to a Go slice +- `frankenphp.IsPacked(zval unsafe.Pointer) bool` - Check if a PHP array is packed (indexed only) or associative (key-value pairs) ### Declaring a Native PHP Class diff --git a/types.go b/types.go index 4e4bbbbed..c2f86042c 100644 --- a/types.go +++ b/types.go @@ -401,6 +401,26 @@ func createNewArray(size uint32) *C.HashTable { return (*C.HashTable)(unsafe.Pointer(arr)) } +// IsPacked determines if the given zval pointer represents a packed array (list). +// Returns false if the zval is nil, not an array, or not packed. +func IsPacked(zval unsafe.Pointer) bool { + if zval == nil { + return false + } + + v, err := extractZvalValue((*C.zval)(zval), C.IS_ARRAY) + if err != nil { + return false + } + + ht := (*C.HashTable)(v) + if ht == nil { + return false + } + + return htIsPacked(ht) +} + // htIsPacked checks if a HashTable is a list (packed) or hashmap (not packed). func htIsPacked(ht *C.HashTable) bool { flags := *(*C.uint32_t)(unsafe.Pointer(&ht.u[0]))