-
-
Save cho45/57621 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#!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