+
+// Enumerator
+
+LOC_EXPORT int loc_database_enumerator_new(struct loc_database_enumerator** enumerator, struct loc_database* db) {
+ struct loc_database_enumerator* e = calloc(1, sizeof(*e));
+ if (!e)
+ return -ENOMEM;
+
+ // Reference context
+ e->ctx = loc_ref(db->ctx);
+ e->db = loc_database_ref(db);
+ e->refcount = 1;
+
+ DEBUG(e->ctx, "Database enumerator object allocated at %p\n", e);
+
+ *enumerator = e;
+ return 0;
+}
+
+LOC_EXPORT struct loc_database_enumerator* loc_database_enumerator_ref(struct loc_database_enumerator* enumerator) {
+ enumerator->refcount++;
+
+ return enumerator;
+}
+
+static void loc_database_enumerator_free(struct loc_database_enumerator* enumerator) {
+ DEBUG(enumerator->ctx, "Releasing database enumerator %p\n", enumerator);
+
+ // Release all references
+ loc_database_unref(enumerator->db);
+ loc_unref(enumerator->ctx);
+
+ if (enumerator->string)
+ free(enumerator->string);
+
+ free(enumerator);
+}
+
+LOC_EXPORT struct loc_database_enumerator* loc_database_enumerator_unref(struct loc_database_enumerator* enumerator) {
+ if (!enumerator)
+ return NULL;
+
+ if (--enumerator->refcount > 0)
+ return enumerator;
+
+ loc_database_enumerator_free(enumerator);
+ return NULL;
+}
+
+LOC_EXPORT int loc_database_enumerator_set_string(struct loc_database_enumerator* enumerator, const char* string) {
+ enumerator->string = strdup(string);
+
+ // Make the string lowercase
+ for (char *p = enumerator->string; *p; p++)
+ *p = tolower(*p);
+
+ return 0;
+}
+
+LOC_EXPORT struct loc_as* loc_database_enumerator_next_as(struct loc_database_enumerator* enumerator) {
+ struct loc_database* db = enumerator->db;
+ struct loc_as* as;
+
+ while (enumerator->as_index < db->as_count) {
+ // Fetch the next AS
+ int r = loc_database_fetch_as(db, &as, enumerator->as_index++);
+ if (r)
+ return NULL;
+
+ r = loc_as_match_string(as, enumerator->string);
+ if (r == 1) {
+ DEBUG(enumerator->ctx, "AS%d (%s) matches %s\n",
+ loc_as_get_number(as), loc_as_get_name(as), enumerator->string);
+
+ return as;
+ }
+
+ // No match
+ loc_as_unref(as);
+ }
+
+ // Reset the index
+ enumerator->as_index = 0;
+
+ // We have searched through all of them
+ return NULL;
+}