@@ -95,6 +95,30 @@ R_xlen_t hash_lookup(const hashtab * h, SEXP key, R_xlen_t ifnotfound) {
9595 return ifnotfound ; // # nocov
9696}
9797
98+ R_xlen_t hash_lookup_or_insert (hashtab * h , SEXP key , R_xlen_t value ) {
99+ struct hash_pair * cell = h -> tb + hash_index (key , h -> multiplier ) % h -> size , * end = h -> tb + h -> size - 1 ;
100+ for (size_t i = 0 ; i < h -> size ; ++ i , cell = (cell == end ? h -> tb : cell + 1 )) {
101+ if (cell -> key == key ) {
102+ cell -> value = value ;
103+ return cell -> value ;
104+ } else if (!cell -> key ) {
105+ if (!h -> free ) internal_error (
106+ __func__ , "no free slots left (full size=%zu)" , h -> size
107+ );
108+ -- h -> free ;
109+ * cell = (struct hash_pair ){.key = key , .value = value };
110+ return value ; // insert here
111+ }
112+ }
113+
114+ internal_error ( // # nocov
115+ __func__ , "did not find a free slot for key %p; size=%zu, free=%zu" ,
116+ (void * )key , h -> size , h -> free
117+ );
118+ // Should be impossible, but just in case:
119+ return value ;
120+ }
121+
98122typedef struct dhashtab_ {
99123 dhashtab public ; // must be at offset 0
100124 size_t size , used , limit ;
0 commit comments