Fun 0.41.5
The programming language that makes you have fun!
Loading...
Searching...
No Matches
map.c
Go to the documentation of this file.
1/*
2 * This file is part of the Fun programming language.
3 * https://fun-lang.xyz/
4 *
5 * Copyright 2025 Johannes Findeisen <you@hanez.org>
6 * Licensed under the terms of the Apache-2.0 license.
7 * https://opensource.org/license/apache-2-0
8 */
9
10/**
11 * @file map.c
12 * @brief Simple string-keyed map implementation backing VAL_MAP Values.
13 */
14
15#include "value.h"
16#include <stdlib.h>
17#include <string.h>
18
19/* Internal Map definition; Value holds struct Map* */
20typedef struct Map {
22 int count;
23 int cap;
24 char **keys; /* each key owned here */
25 Value *vals; /* each value owned here */
27
28/**
29 * @brief Construct a new empty map Value.
30 *
31 * Allocates an internal Map structure with refcount=1 and zero capacity.
32 *
33 * @return A Value of type VAL_MAP on success, or VAL_NIL on allocation failure.
34 */
36 Map *m = (Map *)malloc(sizeof(Map));
37 if (!m) return make_nil();
38 m->refcount = 1;
39 m->count = 0;
40 m->cap = 0;
41 m->keys = NULL;
42 m->vals = NULL;
43 Value v;
44 v.type = VAL_MAP;
45 v.map = (struct Map *)m;
46 return v;
47}
48
49/**
50 * @brief Ensure the map has capacity for at least need elements.
51 * @param m Internal map pointer (must not be NULL).
52 * @param need Required capacity.
53 * @return 1 on success, 0 on allocation failure.
54 */
55static int map_ensure_cap(Map *m, int need) {
56 if (m->cap >= need) return 1;
57 int ncap = m->cap == 0 ? 4 : m->cap * 2;
58 while (ncap < need)
59 ncap *= 2;
60 char **nkeys = (char **)realloc(m->keys, sizeof(char *) * ncap);
61 Value *nvals = (Value *)realloc(m->vals, sizeof(Value) * ncap);
62 if (!nkeys || !nvals) return 0;
63 m->keys = nkeys;
64 m->vals = nvals;
65 m->cap = ncap;
66 return 1;
67}
68
69/**
70 * @brief Insert or replace a key in the map.
71 *
72 * On success, ownership of v transfers into the map. On failure, v is freed.
73 *
74 * @param vm Target Value of type VAL_MAP.
75 * @param key NUL-terminated key string (copied into the map).
76 * @param v Value to store; consumed on success.
77 * @return 1 on success, 0 on error (type mismatch, OOM, or NULL params).
78 */
79int map_set(Value *vm, const char *key, Value v) {
80 if (!vm || vm->type != VAL_MAP || !vm->map || !key) {
82 return 0;
83 }
84 Map *m = (Map *)vm->map;
85 for (int i = 0; i < m->count; ++i) {
86 if (strcmp(m->keys[i], key) == 0) {
87 free_value(m->vals[i]);
88 m->vals[i] = v;
89 return 1;
90 }
91 }
92 if (!map_ensure_cap(m, m->count + 1)) {
94 return 0;
95 }
96 m->keys[m->count] = strdup(key);
97 m->vals[m->count] = v;
98 m->count++;
99 return 1;
100}
101
102/**
103 * @brief Look up a key and copy the stored value into out.
104 *
105 * The returned value is a deep copy; caller owns it and must free it.
106 *
107 * @param vm Source map Value (VAL_MAP).
108 * @param key Key to search for.
109 * @param out Output pointer to receive a copy; may be NULL to only test presence.
110 * @return 1 if found (and out filled if non-NULL), 0 otherwise.
111 */
112int map_get_copy(const Value *vm, const char *key, Value *out) {
113 if (!vm || vm->type != VAL_MAP || !vm->map || !key) return 0;
114 Map *m = (Map *)vm->map;
115 for (int i = 0; i < m->count; ++i) {
116 if (strcmp(m->keys[i], key) == 0) {
117 if (out) *out = copy_value(&m->vals[i]);
118 return 1;
119 }
120 }
121 return 0;
122}
123
124/**
125 * @brief Check whether the map contains the specified key.
126 * @param vm Map Value (VAL_MAP).
127 * @param key Key to search for.
128 * @return 1 if present, 0 if absent or on invalid input.
129 */
130int map_has(const Value *vm, const char *key) {
131 if (!vm || vm->type != VAL_MAP || !vm->map || !key) return 0;
132 Map *m = (Map *)vm->map;
133 for (int i = 0; i < m->count; ++i) {
134 if (strcmp(m->keys[i], key) == 0) return 1;
135 }
136 return 0;
137}
138
139/**
140 * @brief Return all map keys as an array of strings.
141 *
142 * Ownership: Caller must free the returned Value with free_value().
143 *
144 * @param vm Map Value (VAL_MAP).
145 * @return Array Value of keys; empty array if vm is not a map or is empty.
146 */
148 if (!vm || vm->type != VAL_MAP || !vm->map) return make_array_from_values(NULL, 0);
149 Map *m = (Map *)vm->map;
150 if (m->count <= 0) return make_array_from_values(NULL, 0);
151 Value *tmp = (Value *)malloc(sizeof(Value) * m->count);
152 if (!tmp) return make_array_from_values(NULL, 0);
153 for (int i = 0; i < m->count; ++i) {
154 tmp[i] = make_string(m->keys[i]);
155 }
156 Value arr = make_array_from_values(tmp, m->count);
157 for (int i = 0; i < m->count; ++i)
158 free_value(tmp[i]);
159 free(tmp);
160 return arr;
161}
162
163/**
164 * @brief Return all map values as an array (deep-copied).
165 *
166 * Ownership: Caller must free the returned Value with free_value().
167 *
168 * @param vm Map Value (VAL_MAP).
169 * @return Array Value of values; empty array if vm is not a map or is empty.
170 */
172 if (!vm || vm->type != VAL_MAP || !vm->map) return make_array_from_values(NULL, 0);
173 Map *m = (Map *)vm->map;
174 if (m->count <= 0) return make_array_from_values(NULL, 0);
175 Value *tmp = (Value *)malloc(sizeof(Value) * m->count);
176 if (!tmp) return make_array_from_values(NULL, 0);
177 for (int i = 0; i < m->count; ++i) {
178 tmp[i] = copy_value(&m->vals[i]);
179 }
180 Value arr = make_array_from_values(tmp, m->count);
181 for (int i = 0; i < m->count; ++i)
182 free_value(tmp[i]);
183 free(tmp);
184 return arr;
185}
Value out
Definition apop.c:38
Value v
Definition cast.c:22
array_clear & arr
Definition clear.c:38
const char * key
Definition get_bool.c:40
Value m
Definition has_key.c:27
free(vals)
int map_set(Value *vm, const char *key, Value v)
Insert or replace a key in the map.
Definition map.c:79
Value map_values_array(const Value *vm)
Return all map values as an array (deep-copied).
Definition map.c:171
Value make_map_empty(void)
Construct a new empty map Value.
Definition map.c:35
int map_get_copy(const Value *vm, const char *key, Value *out)
Look up a key and copy the stored value into out.
Definition map.c:112
Value map_keys_array(const Value *vm)
Return all map keys as an array of strings.
Definition map.c:147
int map_has(const Value *vm, const char *key)
Check whether the map contains the specified key.
Definition map.c:130
static int map_ensure_cap(Map *m, int need)
Ensure the map has capacity for at least need elements.
Definition map.c:55
Definition map.c:20
int refcount
Definition map.c:21
char ** keys
Definition map.c:24
int cap
Definition map.c:23
int count
Definition map.c:22
Value * vals
Definition map.c:25
Tagged union representing a Fun value.
Definition value.h:68
struct Map * map
Definition value.h:76
ValueType type
Definition value.h:69
Value make_nil(void)
Construct a nil Value.
Definition value.c:126
Value make_string(const char *s)
Construct a string Value by duplicating the given C string.
Definition value.c:95
void free_value(Value v)
Free dynamic storage owned by a Value.
Definition value.c:517
Value make_array_from_values(const Value *vals, int count)
Create an array Value by copying items from an input span.
Definition value.c:142
Value copy_value(const Value *v)
Shallow copy a Value.
Definition value.c:415
Defines the Value type and associated functions for the Fun VM.
@ VAL_MAP
Definition value.h:56