AMemFile

(0)

(1) ver.1.00 [2024.09.02] (133行)

#include "acl1Tiny.c"
AClass(AMemFile) {
    int bufSiz, flags;
    char *p0, *p, *p1;
};

#define AMemFile_Err		1
#define AMemFile_Text		2

AStatic AMemFile *AMemFile_newSiz(int flags, int siz)
{
    AMemFile *mp = malloc(sizeof (AMemFile));
    if (mp == 0) {
outOfMemory:
        if ((flags & AMemFile_Err) == 0) { aErrExit("AMemFile_new: out of memory"); }
        return 0;
    }
    mp->p0 = malloc(siz);
    if (mp->p0 == 0) { free(mp); goto outOfMemory; }
    mp->bufSiz = siz;
    mp->flags = flags;
    mp->p = mp->p0;
    mp->p1 = mp->p0 + siz;
    return mp;
}

AStatic AMemFile *AMemFile_new(int flags) { return AMemFile_newSiz(flags, 64 * 1024); }

AStatic void AMemFile_close(AMemFile *mp)
{
    if (mp != 0) {
        free(mp->p0);
        free(mp);
    }
}

AStatic int AMemFile_write(AMemFile *mp, const char *s, int n)
{
retry:
    if (n <= 0) { return 0; }
    if (mp->p + n <= mp->p1) {
        memcpy(mp->p, s, n);
        mp->p += n;
        return 0;
    }
    char *p = realloc(mp->p0, mp->bufSiz * 2);
    if (p == 0) {
        if ((mp->flags & AMemFile_Err) == 0) { aErrExit("AMemFile_write: out of memory"); }
        return 1;
    }
    int i = mp->p - mp->p0;
    mp->bufSiz *= 2;
    mp->p0 = p;
    mp->p = p + i;
    mp->p1 = mp->p0 + mp->bufSiz;
    goto retry;
}

AStatic int AMemFile_toReadMode(AMemFile *mp)
{
    static char s[16];
    int i = AMemFile_write(mp, s, 16);
    if (i != 0) return i;
    i = mp->p - mp->p0;
    mp->p0 = realloc(mp->p0, i);
    mp->p = mp->p0 + (i - 16);
    mp->p1 = mp->p0 + i;
    mp->bufSiz = i;
    return 0;
}

AStatic int AMemFile_load(AMemFile *mp, const char *path)
// 1GBを超えるようなファイルサイズは想定していない.
{
    int siz = 1024 * 1024, i;
    char *t = malloc(siz);
    FILE *fp= fopen(path, "rb");
    if (fp == 0) {
        if ((mp->flags & AMemFile_Err) == 0) { aErrExit("AMemFile_load: fopen error: %s", path); }
        return 1;
    }
    do {
        i = fread(t, 1, siz, fp);
        AMemFile_write(mp, t, i);
    } while (i >= siz); // 実際には i > siz になることはない.
    fclose(fp);
    free(t);
    return 0;
}

AStatic int AMemFile_save(AMemFile *mp, const char *path)
{
    const char *mod = "wb";
    if ((mp->flags & AMemFile_Text) != 0) { mod = "wt"; }
    FILE *fp = fopen(path, mod);
    if (fp == 0) {
        if ((mp->flags & AMemFile_Err) == 0) { aErrExit("AMemFile_save: fopen error: %s", path); }
        return 1;
    }
    int i = fwrite(mp->p0, 1, mp->p - mp->p0, fp);
    fclose(fp);
    if (i < mp->p - mp->p0) {
        if ((mp->flags & AMemFile_Err) == 0) { aErrExit("AMemFile_save: fwrite error: %s", path); }
        return 1;
    }
    return 0;
}

AStatic void AMemFile_eraseCr(AMemFile *mp)
{
    char *p = mp->p0, *q = p, *p1 = mp->p;
    for (; p < p1; p++) {
        if (*p != '\r') { *q++ = *p; }
    }
    mp->p = q;
}

AStatic AMemFile *AMemFile_open(int flags, const char *path)
{
    AMemFile *mp = AMemFile_new(flags);
    if (mp == 0) return 0;
    if (AMemFile_load(mp, path) != 0) { AMemFile_close(mp); return 0; }
    if ((flags & AMemFile_Text) != 0) { AMemFile_eraseCr(mp); }
    AMemFile_toReadMode(mp);
    return mp;
}

AStatic int AMemFile_saveClose(AMemFile *mp, const char *path)
{
    int i = AMemFile_save(mp, path);
    if (i != 0) { return i; }
    AMemFile_close(mp);
    return 0;
}

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS