// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com) // All rights reserved. // Hash functions for the Five runtime library. // Harbour: hb_Hash, hb_HGet, hb_HSet, hb_HDel, hb_HHasKey, etc. package hbrtl import "five/hbrt" // HbHash creates a hash from key-value pairs. // Harbour: hb_Hash(key1, val1, key2, val2, ...) → hHash func HbHash(t *hbrt.Thread) { nParams := t.ParamCount() t.Frame(nParams, 0) defer t.EndProc() h := hbrt.MakeHash() hh := h.AsHash() for i := 1; i <= nParams-1; i += 2 { hh.Keys = append(hh.Keys, t.Local(i)) hh.Values = append(hh.Values, t.Local(i+1)) } t.PushValue(h) t.RetValue() } // HbHGet gets a value from a hash by key. // Harbour: hb_HGet(hHash, xKey) → xValue func HbHGet(t *hbrt.Thread) { t.Frame(2, 0) defer t.EndProc() hVal := t.Local(1) key := t.Local(2) hh := hVal.AsHash() if hh != nil { for i, k := range hh.Keys { if valuesEqual(k, key) { t.PushValue(hh.Values[i]) t.RetValue() return } } } t.PushNil() t.RetValue() } // HbHSet sets a value in hash by key. // Harbour: hb_HSet(hHash, xKey, xValue) → hHash func HbHSet(t *hbrt.Thread) { t.Frame(3, 0) defer t.EndProc() hVal := t.Local(1) key := t.Local(2) val := t.Local(3) hh := hVal.AsHash() if hh != nil { for i, k := range hh.Keys { if valuesEqual(k, key) { hh.Values[i] = val t.PushValue(hVal) t.RetValue() return } } hh.Keys = append(hh.Keys, key) hh.Values = append(hh.Values, val) } t.PushValue(hVal) t.RetValue() } // HbHDel deletes a key from hash. // Harbour: hb_HDel(hHash, xKey) → hHash func HbHDel(t *hbrt.Thread) { t.Frame(2, 0) defer t.EndProc() hVal := t.Local(1) key := t.Local(2) hh := hVal.AsHash() if hh != nil { for i, k := range hh.Keys { if valuesEqual(k, key) { hh.Keys = append(hh.Keys[:i], hh.Keys[i+1:]...) hh.Values = append(hh.Values[:i], hh.Values[i+1:]...) break } } } t.PushValue(hVal) t.RetValue() } // HbHHasKey checks if hash contains a key. // Harbour: hb_HHasKey(hHash, xKey) → lExists func HbHHasKey(t *hbrt.Thread) { t.Frame(2, 0) defer t.EndProc() hVal := t.Local(1) key := t.Local(2) hh := hVal.AsHash() if hh != nil { for _, k := range hh.Keys { if valuesEqual(k, key) { t.PushBool(true) t.RetValue() return } } } t.PushBool(false) t.RetValue() } // HbHKeys returns an array of hash keys. // Harbour: hb_HKeys(hHash) → aKeys func HbHKeys(t *hbrt.Thread) { t.Frame(1, 0) defer t.EndProc() hh := t.Local(1).AsHash() if hh != nil { t.PushValue(hbrt.MakeArrayFrom(hh.Keys)) } else { t.PushValue(hbrt.MakeArray(0)) } t.RetValue() } // HbHValues returns an array of hash values. // Harbour: hb_HValues(hHash) → aValues func HbHValues(t *hbrt.Thread) { t.Frame(1, 0) defer t.EndProc() hh := t.Local(1).AsHash() if hh != nil { t.PushValue(hbrt.MakeArrayFrom(hh.Values)) } else { t.PushValue(hbrt.MakeArray(0)) } t.RetValue() }