AMemFile

(0)

(1) ver.1.20 [2024.09.20] (143行)

AClass(AMemFile) {
    AInt bufSiz, flags;
    char *p0, *p, *p1;
    AM *m;
};

AStatic AMap11 *AMemFile_dbgNam = 0;
AInlineStatic void AMemFile_dbgSetNam(AM *w, const char *n) { aDbgSetNam(&AMemFile_dbgNam, w, n); }
AStatic void AMemFile_err(AMemFile *w, const char *fnc, const char *f,...) { va_list ap; va_start(ap, f); aClassErr(&AMemFile_dbgNam, w, fnc, f, ap); va_end(ap); }

#define AMemFile_Text    8

AStatic void AMemFile_dst(AMemFile *mp)
{
    if (mp != 0) {
        AM_fre(mp->m, mp->p0, mp->bufSiz);
        AM_fre(mp->m, mp, sizeof (AMemFile));
    }
}

AStatic AMemFile *AMemFile_newSiz(int flags, AM *m, AInt siz)
{
    AMemFile *mp = AM_alc(m, 4, sizeof (AMemFile));
    if (mp == 0) {
outOfMemory:
        if ((flags & 4) == 0) aErrExit("AMemFile_new: out of memory");
        return 0;
    }
    mp->p0 = AM_alc(m, 4, siz);
    if (mp->p0 == 0) { AM_fre(m, mp, sizeof (AMemFile)); goto outOfMemory; }
    mp->bufSiz = siz;
    mp->flags = flags;
    mp->p = mp->p0;
    mp->p1 = mp->p0 + siz;
    mp->m = m;
    if ((flags & 1) != 0) AM_arp(m, AMemFile_dst, mp, 0, 0);
    return mp;
}

AInlineStatic AMemFile *AMemFile_new(int flags, AM *m) { return AMemFile_newSiz(flags, m, 64 * 1024); }

AStatic int AMemFile_write(AMemFile *mp, int flags, const char *s, AInt n)
{
retry:
    if (n <= 0) return 0;
    if (mp->p + n <= mp->p1) {
        memcpy(mp->p, s, n);
        mp->p += n;
        return 0;
    }
    if (mp->bufSiz * 2 <= mp->bufSiz) AMemFile_err(mp, "AMemFile_write", "error: siz=%d", (int) mp->bufSiz);
    char *p = AM_rlc(mp->m, flags & 6, mp->p0, mp->bufSiz, mp->bufSiz * 2);
    if (p == 0) return 1;
    AInt 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, int flags)
{
    static char s[16];
    AInt i = AMemFile_write(mp, flags, s, 16);
    if (i != 0) return 1;
    i = mp->p - mp->p0;
    char *p0 = AM_rlc(mp->m, flags & 4, mp->p0, mp->bufSiz, i);
    if (p0 == 0) return 1;
    mp->p0 = p0;
    mp->p = mp->p0 + (i - 16);
    mp->p1 = mp->p0 + i;
    mp->bufSiz = i;
    return 0;
}

AStatic int AMemFile_load(AMemFile *mp, int flags, AM *m, FILE *fp)
{
    AInt siz = 1024 * 1024, i;
    char *t = AM_alc(m, flags & 4, siz);
    if (t == 0) return 1;
    do {
        i = fread(t, 1, siz, fp);
        if (AMemFile_write(mp, flags, t, i) != 0) {
            AM_fre(m, t, siz);
            return 1;
        }
    } while (i >= siz); // 実際には i > siz になることはない.
    AM_fre(m, t, siz);
    return 0;
}

AStatic int AMemFile_save(AMemFile *mp, int flags, const char *path)
{
    const char *mod = "wb";
    if ((mp->flags & AMemFile_Text) != 0) { mod = "wt"; }
    FILE *fp = fopen(path, mod);
    if (fp == 0) {
        if ((flags & 4) == 0) AMemFile_err(mp, "AMemFile_save", "fopen error: %s", path);
        return 1;
    }
    AInt i = fwrite(mp->p0, 1, mp->p - mp->p0, fp);
    fclose(fp);
    if (i < mp->p - mp->p0) {
        if ((flags & 4) == 0) AMemFile_err(mp, "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, AM *m, const char *path)
{
    AMemFile *mp = AMemFile_new(flags, m);
    if (mp == 0) return 0;
    FILE *fp = fopen(path, "rb");
    if (fp == 0) {
        if ((flags & 1) == 0) AMemFile_dst(mp);
        if ((flags & 4) == 0) AMemFile_err(mp, "AMemFile_open", "fopen error: %s", path);
        return 0;
    }
    if (AMemFile_load(mp, flags, m, fp) != 0) { fclose(fp); if ((flags & 1) == 0) AMemFile_dst(mp); return 0; }
    fclose(fp);
    if ((flags & AMemFile_Text) != 0) { AMemFile_eraseCr(mp); }
    if (AMemFile_toReadMode(mp, flags) != 0) { if ((flags & 1) == 0) AMemFile_dst(mp); return 0; }
    return mp;
}

AStatic int AMemFile_saveDst(AMemFile *mp, int flags, const char *path)
{
    int i = AMemFile_save(mp, flags, path);
    if (i != 0) { return i; }
    if ((flags & 1) == 0) AMemFile_dst(mp);
    return 0;
}

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