Skip to content

Instantly share code, notes, and snippets.

@cho45
Created February 3, 2009 17:05
Show Gist options
  • Save cho45/57621 to your computer and use it in GitHub Desktop.
Save cho45/57621 to your computer and use it in GitHub Desktop.
//#!gcc -g -O0 -Wall
// to use strndup
#define _GNU_SOURCE 1
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
// class Entry {
typedef struct entry {
char* path;
char* title;
char* body;
struct stat* stat;
struct entry* next;
} Entry;
Entry* Entry_new (const char* path) {
Entry* self = malloc(sizeof(Entry));
self->path = strdup(path);
self->stat = malloc(sizeof(struct stat));
stat(self->path, self->stat);
FILE* f = fopen(self->path, "r");
if (f != NULL) {
// 一括読みこみ
char* data = calloc(self->stat->st_size + 1, sizeof(char));
fread(data, sizeof(char), self->stat->st_size, f);
fclose(f);
char* body = strchr(data, 0x0a);
if (body) {
int title_length = ((int)body - (int)data) / sizeof(char);
// data から 0x0a まで抜きだして title に
self->title = strndup(data, title_length);
self->body = strdup(body);
} else {
self->title = strdup(body);
self->body = NULL;
}
free(data);
}
if (!self->title) self->title = calloc(1, sizeof(char));
if (!self->body) self->body = calloc(1, sizeof(char));
self->next = NULL;
return self;
}
void Entry_destroy (Entry*const self) {
free(self->path);
free(self->title);
free(self->body);
free(self->stat);
free(self);
}
// } end of Entry class
// class Entries {
typedef Entry Entries;
Entry* Entries_collect_recursive (const char* parent, Entry* current) {
DIR* dir;
// printf("downto %s\n", parent);
dir = opendir(parent);
if (dir == NULL) return NULL;
struct dirent* ent;
char* path;
while ((ent = readdir(dir)) != NULL) {
path = calloc(strlen(parent) + strlen(ent->d_name) + 2, sizeof(char));
sprintf(path, "%s/%s", parent, ent->d_name);
if (strcmp(ent->d_name, ".") == 0) continue;
if (strcmp(ent->d_name, "..") == 0) continue;
struct stat s;
stat(path, &s);
// printf("%s %s\n", path, S_ISDIR(s.st_mode) ? "(dir)" : "");
if (S_ISDIR(s.st_mode)) {
current = Entries_collect_recursive(path, current);
} else {
// .txt でおわるものだけ
char* ext = ent->d_name + (strlen(ent->d_name) - 4);
if (strcmp(ext, ".txt") == 0) {
current->next = Entry_new(path);
current = current->next;
}
}
free(path);
}
closedir(dir);
return current;
}
Entries* Entries_new (const char* root) {
Entries* self = malloc(sizeof(Entries));
Entries_collect_recursive(root, self);
return self;
}
void Entries_destroy (Entries*const self) {
// free self and all Entry
Entry* entry = self->next;
Entry* temp;
while (entry) {
// printf("destroy: %s\n", entry->path);
temp = entry->next;
Entry_destroy(entry);
entry = temp;
}
free(self);
}
Entries* Entries_sort (Entries* self);
Entry* Entries_merge_sort (Entry* list);
Entry* Entries_merge_sort_merge (Entry* a, Entry* b);
Entries* Entries_sort (Entries* self) {
self->next = Entries_merge_sort(self->next);
return self;
}
Entry* Entries_merge_sort (Entry* list) {
// printf("0x%08x, 0x%08x\n", (int)list, (int)list->next);
if (!list || !list->next) return list;
Entry* mid = list;
Entry* itr = list->next;
if (itr) itr = itr->next;
while (itr) {
mid = mid->next;
itr = itr->next;
if (itr) itr = itr->next;
}
Entry* a = list;
Entry* b = mid->next;
mid->next = NULL;
return Entries_merge_sort_merge(
Entries_merge_sort(a),
Entries_merge_sort(b)
);
}
Entry* Entries_merge_sort_merge (Entry* a, Entry* b) {
Entry ret;
Entry* tmp;
tmp = &ret;
while (a && b) {
if (a->stat->st_mtime > b->stat->st_mtime) {
tmp->next = a;
tmp = a;
a = a->next;
} else {
tmp->next = b;
tmp = b;
b = b->next;
}
}
while (a) {
tmp->next = a;
tmp = a;
a = a->next;
}
while (b) {
tmp->next = b;
tmp = b;
b = b->next;
}
return ret.next;
}
// } end of Entries class
int main (int argc, char* argv[]) {
// Entry* entry = Entry_new("/home/cho45/blosxom-test-data/intro.txt");
// printf("%s\n", entry->path);
// printf("%s\n\n", entry->title);
// printf("%s\n", entry->body);
//
// Entry_destroy(entry);
Entries* entries = Entries_new("/home/cho45/blosxom-test-data");
Entries_sort(entries);
Entry* entry = entries;
while ( (entry = entry->next) ) {
char buf[256];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&entry->stat->st_mtime));
printf("%s\n", entry->path);
printf("%d, %s\n", (int)entry->stat->st_mtime, buf);
printf("%s\n", entry->title);
}
Entries_destroy(entries);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment