Ctrl K
ComunidadGuías…

std/map.zc

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot

import "./core.zc"
import "./hash.zc"
import "./option.zc"
import "./mem.zc"

// Pure Zen-C string hash using FNV-1a algorithm
fn _map_hash_str(str: const char*) -> usize {
    let hash = hash_get_seed();
    let i: usize = 0;
    
    while (str[i] != 0) {
        // Cast char to u8 for unsigned byte value
        let b: u8 = (u8)str[i];
        hash = hash_combine(hash, (usize)b);
        i = i + 1;
    }
    
    return hash;
}

struct Map<V> {
    keys: char**;
    vals: V*;
    occupied: bool*;  
    deleted: bool*;
    len: usize;
    cap: usize;
}

struct MapEntry<V> {
    key: char*;
    val: V;
}

struct MapIter<V> {
    keys: char**;
    vals: V*;
    occupied: bool*;
    deleted: bool*;
    cap: usize;
    idx: usize;
}

struct MapIterResult<V> {
    entry: MapEntry<V>;
    has_val: bool;
}

impl MapIterResult<V> {
    fn is_none(self) -> bool {
        return !self.has_val;
    }
    
    fn unwrap(self) -> MapEntry<V> {
        if (!self.has_val) {
             !"Panic: Map iterator unwrap on None";
             exit(1);
        }
        return self.entry;
    }
}

impl MapIter<V> {
    /// Yields the next entry.
    fn next(self) -> MapIterResult<V> {
        while self.idx < self.cap {
            let i = self.idx;
            self.idx = self.idx + 1;
            
            if (self.occupied[i] && !self.deleted[i]) {
                let entry = MapEntry<V> {
                    key: self.keys[i],
                    val: self.vals[i]
                };
                return MapIterResult<V> {
                    entry: entry,
                    has_val: true
                };
            }
        }
        // Empty entry for None (zero-initialized to avoid reading uninitialized data)
        let empty: MapEntry<V>;
        memset(&empty, 0, sizeof(MapEntry<V>));
        return MapIterResult<V> { entry: empty, has_val: false };
    }
}

impl Map<V> {
    /// Creates a new, empty Map.
    fn new() -> Map<V> {
        return Map<V> { keys: 0, vals: 0, occupied: 0, deleted: 0, len: 0, cap: 0 };
    }

    fn _resize(self, new_cap: usize) {
        let old_keys = self.keys;
        let old_vals = self.vals;
        let old_occupied = self.occupied;
        let old_deleted = self.deleted;
        let old_cap = self.cap;

        self.cap = new_cap;
        self.keys = alloc_n<char*>(new_cap);
        self.vals = alloc_n<V>(new_cap);
        self.occupied = alloc_n<bool>(new_cap);
        self.deleted = alloc_n<bool>(new_cap);
        // Manual zeroing as alloc_n doesn't zero in non-misra mode
        memset(self.keys, 0, new_cap * sizeof(char*));
        memset(self.vals, 0, new_cap * sizeof(V));
        memset(self.occupied, 0, new_cap * sizeof(bool));
        memset(self.deleted, 0, new_cap * sizeof(bool));
        self.len = 0;

        for (let i: usize = 0; i < old_cap; i = i + 1) {
            if (old_occupied[i] && !old_deleted[i]) {
                self.put(old_keys[i], old_vals[i]);
            }
        }
        
        // Free old arrays (use explicit braces to avoid parser bug)
        if (old_keys != NULL) { dealloc<char*>(old_keys); }
        if (old_vals != NULL) { dealloc<V>(old_vals); }
        if (old_occupied != NULL) { dealloc<bool>(old_occupied); }
        if (old_deleted != NULL) { dealloc<bool>(old_deleted); }
    }

    /// Inserts or overwrites the value for `key`.
    fn put(self, key: char*, val: V) {
        if (self.len >= self.cap * 0.75) {
            let new_cap = self.cap * 2;
            if (new_cap < 8) {
                new_cap = 8;
            }
            self._resize(new_cap);
        }

        let hash = _map_hash_str(key);
        let idx = hash % self.cap;

        while (true) {
            if (!self.occupied[idx] || (self.occupied[idx] && !self.deleted[idx] && strcmp(self.keys[idx], key) == 0)) {
                if (!self.occupied[idx]) {
                    self.len = self.len + 1;
                }
                
                if (!self.occupied[idx] || self.deleted[idx]) {
                    self.keys[idx] = strdup(key);
                }
                
                self.vals[idx] = val;
                self.occupied[idx] = true;
                self.deleted[idx] = false;
                return;
            }
            
            idx = (idx + 1) % self.cap;
        }
    }

    /// Returns the value for `key`, or `None`.
    fn get(self, key: char*) -> Option<V> {
        if (self.cap == 0) {
            return Option<V>::None();
        }

        let hash = _map_hash_str(key);
        let idx = hash % self.cap;
        let start_idx = idx;

        while (true) {
            if (!self.occupied[idx]) {
                return Option<V>::None();
            }
            
            if (!self.deleted[idx] && strcmp(self.keys[idx], key) == 0) {
                return Option<V>::Some(self.vals[idx]);
            }

            idx = (idx + 1) % self.cap;
            if (idx == start_idx) {
                return Option<V>::None();
            }
        }
        return Option<V>::None();
    }
    
    /// Returns whether `key` exists.
    fn contains(self, key: char*) -> bool {
        let opt: Option<V> = self.get(key);
        return opt.is_some();
    }
    
    /// Removes `key`; returns whether it was present.
    fn remove(self, key: char*) {
        if (self.cap == 0) {
            return;
        }
        
        let hash = _map_hash_str(key);
        let idx = hash % self.cap;
        
        while (true) {
            if (!self.occupied[idx]) {
                return;
            }
            
            if (!self.deleted[idx] && strcmp(self.keys[idx], key) == 0) {
                 self.deleted[idx] = true;
                 self.len = self.len - 1;
                 dealloc<char>(self.keys[idx]);
                 return;
            }
            
            idx = (idx + 1) % self.cap;
        }
    }
    
    /// Returns the number of entries.
    fn length(self) -> usize {
        return self.len;
    }
    
    /// Returns whether the Map is empty.
    fn is_empty(self) -> bool {
        return self.len == 0;
    }
    
    /// Frees all entries and the backing storage.
    fn free(self) {
        if (self.keys) {
            for (let i: usize = 0; i < self.cap; i = i + 1) {
                if (self.occupied[i] && !self.deleted[i]) {
                    dealloc<char>(self.keys[i]);
                }
            }
            dealloc<char*>(self.keys);
            dealloc<V>(self.vals);
            dealloc<bool>(self.occupied);
            dealloc<bool>(self.deleted);
        }
        self.keys = 0;
        self.vals = 0;
        self.occupied = 0;
        self.deleted = 0;
        self.len = 0;
        self.cap = 0;
    }
    
    /// Returns the current table capacity.
    fn capacity(self) -> usize {
        return self.cap;
    }
    
    /// Returns whether slot `idx` holds an entry.
    fn is_slot_occupied(self, idx: usize) -> bool {
        if (idx >= self.cap) {
            return false;
        }
        return self.occupied[idx] && !self.deleted[idx];
    }
    
    /// Returns the key at slot `idx`.
    fn key_at(self, idx: usize) -> char* {
        if (idx >= self.cap || !self.occupied[idx] || self.deleted[idx]) {
            return NULL;
        }
        return self.keys[idx];
    }
    
    /// Returns the value at slot `idx`.
    fn val_at(self, idx: usize) -> V {
        return self.vals[idx];
    }

    /// Returns an iterator over the entries.
    fn iterator(self) -> MapIter<V> {
        return MapIter<V> {
            keys: self.keys,
            vals: self.vals,
            occupied: self.occupied,
            deleted: self.deleted,
            cap: self.cap,
            idx: 0
        };
    }
}

impl Drop for Map {
    fn drop(self) {
        self.free();
    }
}