📄 xsfsstream.c
字号:
// XSFS Stream IO
#include <memory.h>
#include <knllib.h>
#include "xsfsunits.h"
#include "xsfsstream.h"
// convert byte-based posisition to unit and offset
static inline void cvt_pos(HXSSTREAM strm, _u64 pos, _u32 *unit, _u32 *off)
{
_u32 o;
o = strm->xsfs->desc.sector_size*strm->xsfs->desc.n_scale;
if(unit) *unit = (_u32)(pos/o);
if(off) *off = (_u32)(pos%o);
}
static inline int read_unit(HXSSTREAM strm, _u32 unit)
{
return fsioRead(strm->xsfs->handle, i_xsfs_start_sector(strm->xsfs)+unit*strm->xsfs->desc.n_scale,
strm->xsfs->buffer, strm->xsfs->desc.n_scale);
}
static inline int write_unit(HXSSTREAM strm, void *buffer, _u32 unit)
{
return fsioWrite(strm->xsfs->handle, i_xsfs_start_sector(strm->xsfs)+unit*strm->xsfs->desc.n_scale,
buffer, strm->xsfs->desc.n_scale);
}
static _u32 new_pri_unit(HXSSTREAM strm, _u32 unit)
{
_u32 nu;
if(xsfsAllocUnits(strm->xsfs, i_xsfs_sector_to_unit(strm->xsfs, strm->sector),
1, &nu, 0)==0) return 0;
strm->stream.pri_index[unit] = nu;
xsfsUpdateStreamDef(strm);
return nu;
}
static int update_unit(HXSSTREAM strm, _u32 unit, int index, _u32 link)
{
if(!read_unit(strm, unit)) return 0;
((_u32*)strm->xsfs->buffer)[index] = link;
if(!write_unit(strm, strm->xsfs->buffer, unit))
return 0;
return 1;
}
static _u32 new_sec_unit(HXSSTREAM strm, _u32 last, int start, int level, _u32 index[])
{
int i, cnt = level-start+1, n;
_u32 nus[MAX_SEC_INDEX+1];
if(xsfsAllocUnits(strm->xsfs, i_xsfs_sector_to_unit(strm->xsfs, strm->sector),
cnt, start==-1?nus:&nus[1], XSAM_CLEAN)!=cnt) return 0;
if(start>=0) nus[0] = last;
for(i=start==-1?0:start, n=0; i<=level; i++, n++)
if(!update_unit(strm, nus[n], index[i], nus[n+1]))
{
xsfsFreeUnits(strm->xsfs, start==-1?nus:&nus[1], cnt, 0);
return 0;
}
if(start == -1)
{
strm->stream.sec_index[level] = nus[0];
xsfsUpdateStreamDef(strm);
}
return nus[start==-1?cnt-1:cnt];
}
static inline int get_unit_level(_u32 sec_count, _u32 unit, _u32 index[])
{
unit -= MAX_PRI_INDEX;
if(unit<sec_count){ index[0] = unit; return 0; }
if(unit<sec_count+sec_count*sec_count)
{ index[0] = (unit-sec_count)/sec_count; index[1] = (unit-sec_count)%sec_count; return 1; }
index[0] = (unit-sec_count-sec_count*sec_count)/(sec_count*sec_count);
index[1] = ((unit-sec_count-sec_count*sec_count)%(sec_count*sec_count))/sec_count;
index[2] = ((unit-sec_count-sec_count*sec_count)%(sec_count*sec_count))%sec_count;
return 2;
}
static _u32 find_unit(HXSSTREAM strm, _u32 unit, int auto_grow)
{
_u32 sec_count, i, j;
_u32 index[MAX_SEC_INDEX];
int level, a;
// find pri_index
if(unit<MAX_PRI_INDEX)
{
i = strm->stream.pri_index[unit];
if(!i && auto_grow) new_pri_unit(strm, unit);
return strm->stream.pri_index[unit];
}
// find sec_index
sec_count = strm->xsfs->desc.n_scale*strm->xsfs->desc.sector_size/sizeof(_u32);
level = get_unit_level(sec_count, unit, index);
if((i=strm->stream.sec_index[level])==0)
return auto_grow ? new_sec_unit(strm, 0, -1, level, index) : 0;
for(a=0; a<=level; a++)
{
if(!read_unit(strm, i)) return 0;
j = i;
i = ((_u32*)strm->xsfs->buffer)[index[a]];
if(!i) return auto_grow ? new_sec_unit(strm, j, a, level, index) : 0;
}
return i;
}
static inline int read_unit_instream(HXSSTREAM strm, _u32 unit)
{
unit = find_unit(strm, unit, 0);
if(!unit) return 0;
return read_unit(strm, unit);
}
static inline int write_unit_instream(HXSSTREAM strm, void *buffer, _u32 unit)
{
unit = find_unit(strm, unit, 1);
if(!unit) return 0;
return write_unit(strm, buffer, unit);
}
int xsfsReadStream(HXSSTREAM strm, _u64 pos, void *buf, int len)
{
_u32 unit, off;
int cnt = 0, l;
char *p = (char*) buf;
cvt_pos(strm, pos, &unit, &off);
while(len)
{
if(!read_unit_instream(strm, unit)) break;
l = min((int)(i_xsfs_unit_size(strm->xsfs)-off), len);
memcpy(p, (char*)strm->xsfs->buffer + off, l);
p += l; len -= l; off = 0; unit ++; cnt += l;
}
return cnt;
}
int xsfsWriteStream(HXSSTREAM strm, _u64 pos, void *buf, int len)
{
_u32 unit, off;
int cnt = 0, l;
char *p = (char*) buf;
cvt_pos(strm, pos, &unit, &off);
while(len)
{
l = min((int)(i_xsfs_unit_size(strm->xsfs)-off), len);
if(off || l<(int)(i_xsfs_unit_size(strm->xsfs)-off))
{
_u32 u1 = find_unit(strm, unit, 1);
if(!read_unit(strm, u1)) break;
memcpy((char*)strm->xsfs->buffer + off, p, l);
if(!write_unit(strm, strm->xsfs->buffer, u1)) break;
}
else
{
if(!write_unit_instream(strm, p, unit)) break;
}
p += l; len -= l; off = 0; unit ++; cnt += l;
}
return cnt;
}
_u32 xsfsLocate(HXSSTREAM strm, _u64 pos, _u32 *off)
{
_u32 u, o;
cvt_pos(strm, pos, &u, &o);
u = find_unit(strm, u, 0);
if(u && off) *off = o;
return u;
}
void xsfsUpdateStreamDef(HXSSTREAM strm)
{
if(fsioRead(strm->xsfs->handle, strm->sector, strm->xsfs->buffer, 1)==0) return;
memcpy((char*)strm->xsfs->buffer + strm->offset, &strm->stream, sizeof(XSFSSTREAM));
fsioWrite(strm->xsfs->handle, strm->sector, strm->xsfs->buffer, 1);
}
int xsfsLoadSysStream(XSSTREAM *strm, int index)
{
int cnt = strm->xsfs->desc.sector_size/sizeof(XSFSSTREAM);
int n = index/cnt;
int i = index%cnt;
XSFSSTREAM *p;
if(!fsioRead(strm->xsfs->handle, strm->xsfs->desc.n_reserved+n, strm->xsfs->buffer, 1))
return 0;
p = (XSFSSTREAM*)strm->xsfs->buffer;
memcpy(&strm->stream, &p[i], sizeof(XSFSSTREAM));
strm->sector = strm->xsfs->desc.n_reserved+n;
strm->offset = i * sizeof(XSFSSTREAM);
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -