ファイル名の数値優先ソート C 言語版を書いてみた。
というより、手元に溜まっている古い覚書ファイルを整理している。
昔書いたのって posix と glib が混在で自分がゲンナリするもので。
とにかく今の知識で限界まで整理して Web に書き出す。
Python の覚書でディレクトリ内容列挙とソートを別々に書いているけど
どうせ同時に使うのだからまとめたほうがよさそう。
ということでこんなコードになった。
#include <glib.h>
#include <gio/gio.h>
/*
* Numeric sort in GLib (like a Nautilus)
* gcc nautilus_sort.c `pkg-config --cflags --libs gio-2.0`
**/
gint
compare_main_func(gchar** a, gchar** b) {
gint n;
gchar* aaa = g_utf8_collate_key_for_filename (*a, -1);
gchar* bbb = g_utf8_collate_key_for_filename (*b, -1);
n = g_strcmp0(aaa, bbb);
g_free(aaa);
g_free(bbb);
return n;
}
gint
compare_data_func(gconstpointer a, gconstpointer b) {
return compare_main_func((gchar**)a, (gchar**)b);
}
void
print_data(gpointer data, gpointer user_data) {
g_printf("%s\n", data);
}
int
main (int argc, char *argv[]) {
gchar* dir;
GFile* file;
GFileEnumerator* file_enum;
GFileInfo* info;
GPtrArray* array;
dir = g_get_current_dir();
file = g_file_new_for_path(dir);
g_free(dir);
/* Get the directory contents */
array = g_ptr_array_new();
file_enum = g_file_enumerate_children(file,
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
G_FILE_QUERY_INFO_NONE,
NULL,
NULL);
for (;;) {
info = g_file_enumerator_next_file(file_enum, NULL, NULL);
if (info == NULL) break;
g_ptr_array_add(array, g_strdup(g_file_info_get_display_name(info)));
g_object_unref(info);
}
g_object_unref(file_enum);
/* Sort */
g_ptr_array_sort(array, compare_data_func);
/* print */
g_ptr_array_foreach(array, print_data, NULL);
/* free */
g_ptr_array_free(array, TRUE);
return 0;
}

pkg-config は gio ですのでお間違いなく。
Python では使わないので気が付かなかったけど
GCompareFunc の引数が gconstpointer になっている。
実際には const gchar** だ、コレにはまいった。
gchar* aaa = g_utf8_collate_key_for_filename (*((gchar**)a), -1);
とやれば一応関数に分離せずにビルドできる。
けど見た目が酷過ぎるので分離した、ドンだけキャストすればいいのよ。
ポインタが今一。。。な初心者がこんなの見たらブン投げるわ。
しかし GLib はループ用の int をまったく使わないで書けるんだな。
筆者はもう慣れたけどローカル変数も malloc も使わないって違和感スゲェ。
C より Python の経験があるほうが覚えるの早そう、破棄が必要なだけだし。
ついでに、今日電源を入れたら。

GNOME はこんなに親切だったのか、初めて見た。
いやマウスの LED がチカチカするから解るんですけど。