]> git.lizzy.rs Git - nothing.git/commitdiff
Partially remove lt from LevelPicker branch
authorrexim <reximkut@gmail.com>
Tue, 10 Dec 2019 12:51:56 +0000 (19:51 +0700)
committerrexim <reximkut@gmail.com>
Tue, 10 Dec 2019 12:51:56 +0000 (19:51 +0700)
src/config.h
src/dynarray.c
src/dynarray.h
src/game/level/level_editor.c
src/game/level_folder.c
src/game/level_folder.h
src/game/level_metadata.c
src/game/level_metadata.h
src/game/level_picker.c
src/ui/list_selector.c
src/ui/list_selector.h

index b2e423f8741968b154393ff5bdb973ded4c5073e..4f2a845fea1712db137a289ce6675a8701f28daf 100644 (file)
 #define CAMERA_RATIO_X 16.0f
 #define CAMERA_RATIO_Y 9.0f
 
+#define METADATA_TITLE_MAX_SIZE 256
+#define METADATA_VERSION_MAX_SIZE 256
+#define METADATA_FILEPATH_MAX_SIZE 512
+
+#define VERSION "1"
+
 #endif  // CONFIG_H_
index 5b1a3fff8c528ae5b38c4e6cb301db1b907ce4c0..f6a7f8e51329fe657b933ae6f9c352c8315adc32 100644 (file)
@@ -9,7 +9,7 @@
 
 #define DYNARRAY_INIT_CAPACITY 8
 
-void *dynarray_pointer_at(Dynarray *dynarray, size_t index)
+void *dynarray_pointer_at(const Dynarray *dynarray, size_t index)
 {
     trace_assert(index < dynarray->count);
     return (uint8_t *)dynarray->data + index * dynarray->element_size;
index dcd1fd237c06d3d05f7d900bbdf8acc47b1623cb..b86345038ac526d12713570346eb3040addedd58 100644 (file)
@@ -24,7 +24,7 @@ Dynarray create_dynarray(size_t element_size)
     return result;
 }
 
-void *dynarray_pointer_at(Dynarray *dynarray, size_t index);
+void *dynarray_pointer_at(const Dynarray *dynarray, size_t index);
 void dynarray_replace_at(Dynarray *dynarray, size_t index, void *element);
 void dynarray_copy_to(Dynarray *dynarray, void *dest, size_t index);
 void dynarray_clear(Dynarray *dynarray);
index 28639ceecc3bf0fd6e2659cb0190488cc21a09e8..79e8f39df0b2b6c84f8770d265f13028d2781430 100644 (file)
@@ -196,7 +196,7 @@ LevelEditor *create_level_editor_from_file(const char *file_name, Cursor *cursor
         RETURN_LT(lt, NULL);
     }
 
-    if (metadata_load_from_line_stream(&level_editor->metadata, level_stream) < 0) {
+    if (metadata_load_from_line_stream(&level_editor->metadata, level_stream, level_editor->file_name) < 0) {
         RETURN_LT(lt, NULL);
     }
 
index 3255ab6e35eea2a266754d1c503d4e9cd31f325a..6e9b1204eaaf9b77207a90ad8ee6279c31f7fa37 100644 (file)
 
 #include "./level_folder.h"
 
-#define LEVEL_FOLDER_MAX_LENGTH 512
-
-struct LevelFolder
-{
-    Lt *lt;
-    Dynarray filenames;
-    Dynarray titles;
-};
-
-LevelFolder *create_level_folder(const char *dirpath)
+void level_folder_read(const char *dirpath, LevelFolder *folder)
 {
-    trace_assert(dirpath);
-
-    Lt *lt = create_lt();
-
-    LevelFolder *level_folder = PUSH_LT(
-        lt,
-        nth_calloc(1, sizeof(LevelFolder)),
-        free);
-    if (level_folder == NULL) {
-        RETURN_LT(lt, NULL);
+    DIR *level_dir = opendir(dirpath);
+    if (level_dir == NULL) {
+        log_fail("Can't open asset folder: %s\n", dirpath);
+        abort();
     }
-    level_folder->lt = lt;
-
-    level_folder->filenames = create_dynarray(sizeof(const char*));
-    level_folder->titles = create_dynarray(sizeof(const char*));
 
-    char path[LEVEL_FOLDER_MAX_LENGTH];
-    DIR *level_dir = PUSH_LT(lt, opendir(dirpath), closedir_lt);
+    dynarray_clear(&folder->metadatas);
 
-    LevelMetadata level_metadata;
+    char filepath[METADATA_FILEPATH_MAX_SIZE];
+    LevelMetadata metadata;
     for (struct dirent *d = readdir(level_dir);
          d != NULL;
          d = readdir(level_dir)) {
-        if (*d->d_name == '.') {
-            continue;
-        }
+        if (*d->d_name == '.') continue;
 
-        snprintf(path, LEVEL_FOLDER_MAX_LENGTH, "%s/%s", dirpath, d->d_name);
-        const char *filepath = PUSH_LT(lt, string_duplicate(trim_endline(path), NULL), free);
-        if (filepath == NULL) {
-            RETURN_LT(lt, NULL);
-        }
+        snprintf(filepath, METADATA_FILEPATH_MAX_SIZE,
+                 "%s/%s", dirpath, d->d_name);
 
-        if (metadata_load_from_file(&level_metadata, filepath) < 0) {
-            RETURN_LT(lt, NULL);
+        if (metadata_load_from_file(&metadata, filepath) < 0) {
+            log_warn("Can't read level: %s\n", filepath);
+            continue;
         }
 
-        const char *version = PUSH_LT(
-            lt,
-            string_duplicate(level_metadata.version, NULL),
-            free);
-        const char *title = PUSH_LT(
-            lt,
-            string_duplicate(level_metadata.title, NULL),
-            free);
-
-        if(strcmp(version, VERSION) == 0) {
-            dynarray_push(&level_folder->titles, &title);
-            dynarray_push(&level_folder->filenames, &filepath);
-        } else {
-            log_info(
+        if(strcmp(metadata.version, VERSION) != 0) {
+            log_warn(
                 "Unsupported version for level [%s]: Expected `%s`, got `%s`\n",
-                d->d_name,
-                VERSION,
-                version);
+                filepath, VERSION, metadata.version);
+            continue;
         }
-    }
 
-    closedir(RELEASE_LT(lt, level_dir));
-
-    return level_folder;
-}
-
-void destroy_level_folder(LevelFolder *level_folder)
-{
-    trace_assert(level_folder);
-    free(level_folder->filenames.data);
-    free(level_folder->titles.data);
-    RETURN_LT0(level_folder->lt);
-}
-
-const char **level_folder_filenames(const LevelFolder *level_folder)
-{
-    trace_assert(level_folder);
-    return (const char **)level_folder->filenames.data;
-}
-
-const char **level_folder_titles(const LevelFolder *level_folder)
-{
-    trace_assert(level_folder);
-    return (const char **)level_folder->titles.data;
-}
+        dynarray_push(&folder->metadatas, &metadata);
+    }
 
-size_t level_folder_count(const LevelFolder *level_folder)
-{
-    trace_assert(level_folder);
-    return level_folder->filenames.count;
+    closedir(level_dir);
 }
index 217cc233a4a136d52e60353f318d7fbef29af1c5..af134fc8ccfc6e51f693aca3f5b847d448ffecc6 100644 (file)
@@ -1,13 +1,25 @@
 #ifndef LEVEL_FOLDER_H_
 #define LEVEL_FOLDER_H_
 
-typedef struct LevelFolder LevelFolder;
+typedef struct {
+    Dynarray metadatas;
+} LevelFolder;
 
-LevelFolder *create_level_folder(const char *dirpath);
-void destroy_level_folder(LevelFolder *level_folder);
+static inline
+LevelFolder create_level_folder(void)
+{
+    LevelFolder result = {
+        .metadatas = create_dynarray(sizeof(LevelMetadata)),
+    };
+    return result;
+}
 
-const char **level_folder_filenames(const LevelFolder *level_folder);
-const char **level_folder_titles(const LevelFolder *level_folder);
-size_t level_folder_count(const LevelFolder *level_folder);
+static inline
+void destroy_level_folder(LevelFolder level_folder)
+{
+    free(level_folder.metadatas.data);
+}
+
+void level_folder_read(const char *dirpath, LevelFolder *folder);
 
 #endif  // LEVEL_FOLDER_H_
index 6c0fbac418cb2106c7868733d92e1829a5087110..512bebe209e041885ea860ef3953e62165af2d8b 100644 (file)
@@ -9,21 +9,16 @@
 #include "level_metadata.h"
 #include "math/extrema.h"
 
-struct LevelMetadata
-{
-    Lt *lt;
-    const char *version;
-    const char *title;
-};
-
 int metadata_load_from_line_stream(LevelMetadata *metadata,
-                                   LineStream *line_stream)
+                                   LineStream *line_stream,
+                                   const char *filepath)
 {
     trace_assert(metadata);
     trace_assert(line_stream);
 
     memset(metadata->version, 0, METADATA_VERSION_MAX_SIZE);
     memset(metadata->title, 0, METADATA_TITLE_MAX_SIZE);
+    memset(metadata->filepath, 0, METADATA_FILEPATH_MAX_SIZE);
 
     const char *line = line_stream_next(line_stream);
     if (line == NULL) return -1;
@@ -41,18 +36,23 @@ int metadata_load_from_line_stream(LevelMetadata *metadata,
            min_size_t(strlen(line), METADATA_VERSION_MAX_SIZE - 1));
     trim_endline(metadata->title);
 
+    memcpy(metadata->filepath,
+           filepath,
+           min_size_t(strlen(filepath), METADATA_FILEPATH_MAX_SIZE - 1));
+    trim_endline(metadata->filepath);
+
     return 0;
 }
 
-int metadata_load_from_file(LevelMetadata *metadata, const char *filename)
+int metadata_load_from_file(LevelMetadata *metadata, const char *filepath)
 {
     trace_assert(metadata);
-    trace_assert(filename);
+    trace_assert(filepath);
 
-    LineStream *line_stream = create_line_stream(filename, "r", 256);
+    LineStream *line_stream = create_line_stream(filepath, "r", 256);
     if (line_stream == NULL) return -1;
 
-    int err = metadata_load_from_line_stream(metadata, line_stream);
+    int err = metadata_load_from_line_stream(metadata, line_stream, filepath);
     destroy_line_stream(line_stream);
     return err;
 }
index 89b08f8e6f15d1b8c4700635f79d43be53638643..970bd59c8413c4231d947d10efdc076d1745d19d 100644 (file)
@@ -1,19 +1,17 @@
 #ifndef LEVEL_METADATA_H_
 #define LEVEL_METADATA_H_
 
-typedef struct LineStream LineStream;
-
-#define VERSION "1"
+#include "config.h"
 
-#define METADATA_TITLE_MAX_SIZE 256
-#define METADATA_VERSION_MAX_SIZE 256
+typedef struct LineStream LineStream;
 
 typedef struct {
+    char filepath[METADATA_FILEPATH_MAX_SIZE];
     char version[METADATA_VERSION_MAX_SIZE];
     char title[METADATA_TITLE_MAX_SIZE];
 } LevelMetadata;
 
-int metadata_load_from_file(LevelMetadata *metadata, const char *file);
-int metadata_load_from_line_stream(LevelMetadata *metadata, LineStream *line_stream);
+int metadata_load_from_file(LevelMetadata *metadata, const char *filepath);
+int metadata_load_from_line_stream(LevelMetadata *metadata, LineStream *line_stream, const char *filepath);
 
 #endif  // LEVEL_METADATA_H_
index 39102dd73904df20ab84d166c7dbb4da3951c671..b53b67ab38e35f53a0066593fd10c3cae3e0903e 100644 (file)
@@ -21,11 +21,18 @@ struct LevelPicker
     Lt *lt;
     Background background;
     Vec2f camera_position;
-    LevelFolder *level_folder;
+    LevelFolder level_folder;
     WigglyText wiggly_text;
-    ListSelector *list_selector;
+    ListSelector list_selector;
 };
 
+static inline
+const char *list_item_text(void *element)
+{
+    trace_assert(element);
+    return ((LevelMetadata *)element)->title;
+}
+
 LevelPicker *create_level_picker(const char *dirpath)
 {
     trace_assert(dirpath);
@@ -45,13 +52,8 @@ LevelPicker *create_level_picker(const char *dirpath)
 
     level_picker->camera_position = vec(0.0f, 0.0f);
 
-    level_picker->level_folder = PUSH_LT(
-        lt,
-        create_level_folder(dirpath),
-        destroy_level_folder);
-    if (level_picker->level_folder == NULL) {
-        RETURN_LT(lt, NULL);
-    }
+    level_picker->level_folder = create_level_folder();
+    level_folder_read("./assets/levels", &level_picker->level_folder);
 
     level_picker->wiggly_text = (WigglyText) {
         .text = "Select Level",
@@ -59,17 +61,10 @@ LevelPicker *create_level_picker(const char *dirpath)
         .color = COLOR_WHITE,
     };
 
-    level_picker->list_selector = PUSH_LT(
-        lt,
-        create_list_selector(
-            level_folder_titles(level_picker->level_folder),
-            level_folder_count(level_picker->level_folder),
-            vec(5.0f, 5.0f),
-            50.0f),
-        destroy_list_selector);
-    if (level_picker->list_selector == NULL) {
-        RETURN_LT(lt, NULL);
-    }
+    level_picker->list_selector.items = level_picker->level_folder.metadatas;
+    level_picker->list_selector.font_scale = vec(5.0f, 5.0f);
+    level_picker->list_selector.padding_bottom = 50.0f;
+    level_picker->list_selector.list_item_text = list_item_text;
 
     return level_picker;
 }
@@ -77,6 +72,7 @@ LevelPicker *create_level_picker(const char *dirpath)
 void destroy_level_picker(LevelPicker *level_picker)
 {
     trace_assert(level_picker);
+    destroy_level_folder(level_picker->level_folder);
     RETURN_LT0(level_picker->lt);
 }
 
@@ -98,9 +94,7 @@ int level_picker_render(const LevelPicker *level_picker,
         camera,
         vec(viewport.w * 0.5f - title_size.x * 0.5f, TITLE_MARGIN_TOP));
 
-    if (list_selector_render(camera, level_picker->list_selector) < 0) {
-        return -1;
-    }
+    list_selector_render(camera, &level_picker->list_selector);
 
     {
         /* CSS */
@@ -156,20 +150,19 @@ int level_picker_event(LevelPicker *level_picker,
             const Vec2f title_size = wiggly_text_size(&level_picker->wiggly_text);
 
             const Vec2f selector_size = list_selector_size(
-                level_picker->list_selector,
+                &level_picker->list_selector,
                 font_scale,
                 padding_bottom);
 
-            list_selector_move(
-                level_picker->list_selector,
+            level_picker->list_selector.position =
                 vec((float)width * 0.5f - selector_size.x * 0.5f,
-                    TITLE_MARGIN_TOP + title_size.y + TITLE_MARGIN_BOTTOM));
+                    TITLE_MARGIN_TOP + title_size.y + TITLE_MARGIN_BOTTOM);
         } break;
         }
     } break;
     }
 
-    return list_selector_event(level_picker->list_selector, event);
+    return list_selector_event(&level_picker->list_selector, event);
 }
 
 int level_picker_input(LevelPicker *level_picker,
@@ -186,20 +179,21 @@ const char *level_picker_selected_level(const LevelPicker *level_picker)
 {
     trace_assert(level_picker);
 
-    const int selected_index = list_selector_selected(level_picker->list_selector);
-    if (selected_index < 0) {
+    if (level_picker->list_selector.selected_item < 0) {
         return NULL;
     }
 
-    const char **filenames = level_folder_filenames(level_picker->level_folder);
+    LevelMetadata *metadata = dynarray_pointer_at(
+        &level_picker->level_folder.metadatas,
+        (size_t)level_picker->list_selector.selected_item);
 
-    return filenames[selected_index];
+    return metadata->filepath;
 }
 
 void level_picker_clean_selection(LevelPicker *level_picker)
 {
     trace_assert(level_picker);
-    list_selector_clean_selection(level_picker->list_selector);
+    level_picker->list_selector.selected_item = -1;
 }
 
 int level_picker_enter_camera_event(LevelPicker *level_picker,
index 32a2ad53f1a4c2bd8878eb468dd6a7e26559fa99..3b211fb60e5fd919ed7c41bf2470f677317d12c7 100644 (file)
 
 #include "./list_selector.h"
 
-struct ListSelector
-{
-    Lt *lt;
-    const char **items;
-    size_t count;
-    size_t cursor;
-    int selected_item;
-    Vec2f position;
-    Vec2f font_scale;
-    float padding_bottom;
-};
-
-ListSelector *create_list_selector(const char *items[],
-                                   size_t count,
-                                   Vec2f font_scale,
-                                   float padding_bottom)
-{
-    trace_assert(items);
-
-    Lt *lt = create_lt();
-
-    ListSelector *list_selector = PUSH_LT(lt, nth_calloc(1, sizeof(ListSelector)), free);
-    if (list_selector == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-    list_selector->lt = lt;
-
-    list_selector->items = items;
-    list_selector->count = count;
-    list_selector->cursor = 0;
-    list_selector->selected_item = -1;
-    list_selector->position = vec(0.0f, 0.0f);
-    list_selector->font_scale = font_scale;
-    list_selector->padding_bottom = padding_bottom;
-
-    return list_selector;
-}
-
-void destroy_list_selector(ListSelector *list_selector)
-{
-    trace_assert(list_selector);
-    RETURN_LT0(list_selector->lt);
-}
 
 int list_selector_render(const Camera *camera,
                          const ListSelector *list_selector)
@@ -63,25 +20,31 @@ int list_selector_render(const Camera *camera,
     trace_assert(camera);
     trace_assert(list_selector);
 
-    for (size_t i = 0; i < list_selector->count; ++i) {
+    for (size_t i = 0; i < list_selector->items.count; ++i) {
         const Vec2f current_position = vec_sum(
             list_selector->position,
             vec(0.0f, (float) i * ((float) FONT_CHAR_HEIGHT * list_selector->font_scale.y + list_selector->padding_bottom)));
 
+        const char *item_text =
+            list_selector->list_item_text(
+                dynarray_pointer_at(
+                    &list_selector->items,
+                    i));
+
         sprite_font_render_text(
             &camera->font,
             camera->renderer,
             current_position,
             list_selector->font_scale,
             rgba(1.0f, 1.0f, 1.0f, 1.0f),
-            list_selector->items[i]);
+            item_text);
 
         if (i == list_selector->cursor) {
             SDL_Rect boundary_box = rect_for_sdl(
                 sprite_font_boundary_box(
                     current_position,
                     list_selector->font_scale,
-                    strlen(list_selector->items[i])));
+                    strlen(item_text)));
             if (SDL_SetRenderDrawColor(camera->renderer, 255, 255, 255, 255) < 0) {
                 return -1;
             }
@@ -96,18 +59,24 @@ int list_selector_render(const Camera *camera,
 }
 
 Vec2f list_selector_size(const ListSelector *list_selector,
-                       Vec2f font_scale,
-                       float padding_bottom)
+                         Vec2f font_scale,
+                         float padding_bottom)
 {
     trace_assert(list_selector);
 
     Vec2f result = vec(0.0f, 0.0f);
 
-    for (size_t i = 0; i < list_selector->count; ++i) {
+    for (size_t i = 0; i < list_selector->items.count; ++i) {
+        const char *item_text =
+            list_selector->list_item_text(
+                    dynarray_pointer_at(
+                        &list_selector->items,
+                        i));
+
         Rect boundary_box = sprite_font_boundary_box(
             vec(0.0f, 0.0f),
             font_scale,
-            strlen(list_selector->items[i]));
+            strlen(item_text));
 
         result.x = fmaxf(result.x, boundary_box.w);
         result.y += boundary_box.y + padding_bottom;
@@ -116,14 +85,6 @@ Vec2f list_selector_size(const ListSelector *list_selector,
     return result;
 }
 
-int list_selector_update(ListSelector *list_selector, float delta_time)
-{
-    trace_assert(list_selector);
-    (void) delta_time;
-
-    return 0;
-}
-
 int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
 {
     trace_assert(list_selector);
@@ -138,7 +99,7 @@ int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
             }
             break;
         case SDLK_DOWN:
-            if (list_selector->cursor < list_selector->count - 1) {
+            if (list_selector->cursor < list_selector->items.count - 1) {
                 list_selector->cursor++;
             }
             break;
@@ -152,11 +113,17 @@ int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
         const Vec2f mouse_pos = vec((float) event->motion.x, (float) event->motion.y);
         Vec2f position = list_selector->position;
 
-        for (size_t i = 0; i < list_selector->count; ++i) {
+        for (size_t i = 0; i < list_selector->items.count; ++i) {
+            const char *item_text =
+                list_selector->list_item_text(
+                        dynarray_pointer_at(
+                            &list_selector->items,
+                            i));
+
             Rect boundary_box = sprite_font_boundary_box(
                 position,
                 list_selector->font_scale,
-                strlen(list_selector->items[i]));
+                strlen(item_text));
 
             if (rect_contains_point(boundary_box, mouse_pos)) {
                 list_selector->cursor = i;
@@ -172,23 +139,27 @@ int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
             // check if the click position was actually inside...
             // note: make sure there's actually stuff in the list! tsoding likes
             // to remove all levels and change title to "SMOL BREAK"...
-            if (list_selector->count == 0)
+            if (list_selector->items.count == 0)
                 break;
 
             // note: this assumes that all list items are the same height!
             // this is probably a valid assumption as long as we use a sprite font.
-            float single_item_height = sprite_font_boundary_box(
-                list_selector->position,
-                list_selector->font_scale,
-                strlen(list_selector->items[0])).h + list_selector->padding_bottom;
+            float single_item_height =
+                FONT_CHAR_HEIGHT * list_selector->font_scale.y + list_selector->padding_bottom;
 
             Vec2f position = list_selector->position;
             vec_add(&position, vec(0.0f, (float) list_selector->cursor * single_item_height));
 
+            const char *item_text =
+                list_selector->list_item_text(
+                    dynarray_pointer_at(
+                        &list_selector->items,
+                        list_selector->cursor));
+
             Rect boundary_box = sprite_font_boundary_box(
                 position,
                 list_selector->font_scale,
-                strlen(list_selector->items[list_selector->cursor]));
+                strlen(item_text));
 
             const Vec2f mouse_pos = vec((float) event->motion.x, (float) event->motion.y);
             if (rect_contains_point(boundary_box, mouse_pos)) {
@@ -201,20 +172,3 @@ int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
 
     return 0;
 }
-
-int list_selector_selected(const ListSelector *list_selector)
-{
-    trace_assert(list_selector);
-    return list_selector->selected_item;
-}
-
-void list_selector_clean_selection(ListSelector *list_selector)
-{
-    trace_assert(list_selector);
-    list_selector->selected_item = -1;
-}
-
-void list_selector_move(ListSelector *list_selector, Vec2f position)
-{
-    list_selector->position = position;
-}
index 124d854347a74df31685782f3d06dceb5f68824a..877092084b935870799ac168f80daad5314caada 100644 (file)
@@ -2,27 +2,32 @@
 #define LIST_SELECTOR_H_
 
 #include "game/camera.h"
+#include "dynarray.h"
 
-typedef struct ListSelector ListSelector;
+typedef const char *(*ListItemText)(void *element);
 
-ListSelector *create_list_selector(const char *items[],
-                                   size_t count,
-                                   Vec2f font_scale,
-                                   float padding_bottom);
-void destroy_list_selector(ListSelector *list_selector);
+typedef struct {
+    Dynarray items;
+    size_t cursor;
+    int selected_item;
+    Vec2f position;
+    Vec2f font_scale;
+    float padding_bottom;
+    ListItemText list_item_text;
+} ListSelector;
 
 int list_selector_render(const Camera *camera,
                          const ListSelector *list_selector);
 Vec2f list_selector_size(const ListSelector *list_selector,
                          Vec2f font_scale,
                          float padding_bottom);
-
-int list_selector_update(ListSelector *list_selector, float delta_time);
 int list_selector_event(ListSelector *list_selector, const SDL_Event *event);
 
-int list_selector_selected(const ListSelector *list_selector);
-void list_selector_clean_selection(ListSelector *list_selector);
-
-void list_selector_move(ListSelector *list_selector, Vec2f position);
+static inline
+void list_selector_clean_selection(ListSelector *list_selector)
+{
+    trace_assert(list_selector);
+    list_selector->selected_item = -1;
+}
 
 #endif  // LIST_SELECTOR_H_