📄 textfile.cc
字号:
int instate = e->instate; while (count--) { e = new ht_ltextfile_line(); e->is_in_memory = true; e->instate = instate; e->on_disk.ofs = 0xffffffff; e->on_disk.len = 0; e->in_memory.data = ht_malloc(1); e->in_memory.len = 0; e->nofs = 0; if (line_ends && line_end_lens) { e->lineendlen = *line_end_lens++; memcpy(e->lineend, *line_ends++, e->lineendlen); } else { e->lineendlen = 1; e->lineend[0] = '\n'; } lines->insertBefore(before, e); } dirty_parse(before); dirty_nofs(before); dirty = true;}void ht_ltextfile::insert_chars(uint line, uint ofs, void *chars, uint len){ ht_ltextfile_line *e=fetch_line(line); if (e) { uint olen=e->is_in_memory ? e->in_memory.len : e->on_disk.len; if (ofs<=olen) { e=fetch_line_into_memory(line); char *ostr=e->in_memory.data; char *nstr; uint nlen=olen; uint clen=len; if (ofs>nlen) nlen=ofs; nlen+=clen; nstr = ht_malloc(nlen); memcpy(nstr, ostr, ofs); memcpy(nstr+ofs, chars, clen); memcpy(nstr+ofs+clen, ostr+ofs, olen-ofs); e->in_memory.data=nstr; e->in_memory.len=nlen; dirty_parse(line+1); dirty_nofs(line+1); dirty=true; free(ostr); } }}bool ht_ltextfile::has_line(uint line){ return (fetch_line(line)!=NULL);}bool ht_ltextfile::is_dirty_nofs(uint line) const{ return (line >= first_nofs_dirty_line);}bool ht_ltextfile::is_dirty_parse(uint line) const{ return (line >= first_parse_dirty_line);}uint ht_ltextfile::linecount() const{ return lines->count();}byte *ht_ltextfile::match_lineend_forwd(byte *buf, uint buflen, int *le_len){ byte *result=NULL; byte *n=(byte*)memchr(buf, '\n', buflen); if (n) { if ((n>buf) && (n[-1] == '\r')) { *le_len=2; result=n-1; } else { *le_len=1; result=n; } } return result;}lexer_state ht_ltextfile::next_instate(uint line){ byte buf[TEXTFILE_MAX_LINELEN+1]; lexer_state state = 0; uint buflen; if (!getline(line, 0, buf, TEXTFILE_MAX_LINELEN, &buflen, &state)) return state; buf[buflen] = 0; if (lexer) { text_pos p; char *bufp = (char*)buf; uint toklen; bool start_of_line = true; p.line = line; p.pofs = 0; int bufplen = buflen; int prev_bufplen = -1; while ((lexer->gettoken(bufp, bufplen, p, start_of_line, &state, &toklen))) { bufp += toklen; p.pofs += toklen; bufplen -= toklen; start_of_line = false; if (!bufplen && !prev_bufplen) break; prev_bufplen = bufplen; } } return state;}FileOfs ht_ltextfile::next_nofs(ht_ltextfile_line *l) const{ if (l) { if (l->is_in_memory) return l->nofs+l->in_memory.len+l->lineendlen; else return l->nofs+l->on_disk.len+l->lineendlen; } return 0;}void ht_ltextfile::pstat(pstat_t &s) const{ mFile->pstat(s); s.size = getSize();}uint ht_ltextfile::read(void *buf, uint size){ FileOfs o=tell(); uint line; uint pofs; uint c=0; byte *b=(byte*)buf; if (convert_ofs2line(o, &line, &pofs)) while (size) { ht_ltextfile_line *l=fetch_line(line); if (!l) break; uint q; if (l->is_in_memory) { q=l->in_memory.len; uint s=q; if (s>pofs) { s-=pofs; s=MIN(size, s); memcpy(b+c, l->in_memory.data+pofs, s); size-=s; c+=s; pofs+=s; } } else { q=l->on_disk.len; uint r; uint s=q; if (s>pofs) { s-=pofs; s=MIN(size, s); mFile->seek(l->on_disk.ofs+pofs); r = mFile->read(b+c, s); if (r!=s) break; size-=s; c+=s; pofs+=s; } } uint s=l->lineendlen; if ((q+s>pofs) && (pofs >= q)) { s-=pofs-q; s=MIN(size, s); memcpy(b+c, l->lineend+(pofs-q), s); size-=s; c+=s; } line++; pofs=0; } ofs += c; return c;}void ht_ltextfile::reread(){ lines->delAll(); orig_lines->delAll(); dirty = false; FileOfs ofs=0; int ll, pll=-1, ln=0; bool firstline = true; byte buf[TEXTFILE_MAX_LINELEN+1]; lexer_state state=0; ht_ltextfile_line *e, *ce; if (lexer) state=lexer->getinitstate(); uint l=0; while ((l=find_linelen_forwd(buf, sizeof buf, ofs, &ll))) { mFile->seek(ofs); uint x = mFile->read(buf, l-ll); buf[x]=0; e=new ht_ltextfile_line(); e->is_in_memory=false; e->instate=state; e->on_disk.ofs=ofs; e->on_disk.len=l-ll; e->nofs=ofs; e->lineendlen=ll; assert( (uint)ll <= sizeof e->lineend); mFile->read(e->lineend, ll); lines->insert(e); ce=new ht_ltextfile_line(); *ce = *e; orig_lines->insert(ce); if (lexer) { text_pos p; char *bufp=(char*)buf; uint toklen; bool start_of_line=true; p.line=ln; p.pofs=0; while (lexer->gettoken(bufp, l-ll-(bufp-(char*)buf), p, start_of_line, &state, &toklen)) { bufp+=toklen; p.pofs+=toklen; start_of_line=false; } } ofs+=l; pll=ll; firstline=false; ln++; } if (pll || firstline) { ll=0; e=new ht_ltextfile_line(); e->is_in_memory=false; e->instate=state; e->on_disk.ofs=ofs; e->on_disk.len=l-ll; e->nofs=ofs; e->lineendlen=ll; lines->insert(e); ce=new ht_ltextfile_line(); *ce = *e; orig_lines->insert(ce); }}void ht_ltextfile::split_line(uint a, uint pos, void *line_end, int line_end_len){ if (pos == 0) { insert_lines(a, 1, &line_end, &line_end_len); } else { uint l=getlinelength(a); if (pos > l) pos = l; char *aline = ht_malloc(pos+1); uint alinelen; getline(a, 0, aline, pos+1, &alinelen, NULL); insert_lines(a, 1, &line_end, &line_end_len); insert_chars(a, 0, aline, alinelen); delete_chars(a+1, 0, pos); free(aline); }}void ht_ltextfile::seek(FileOfs offset){ ofs = offset;}void ht_ltextfile::setLayered(File *streamfile, bool ownNewLayered){ FileLayer::setLayered(streamfile, ownNewLayered); reread();}void ht_ltextfile::set_layered_assume(File *streamfile, bool ownNewLayered, bool changes_applied){ if (changes_applied) { orig_lines->delAll(); uint c = lines->count(); for (uint i=0; i<c; i++) { ht_ltextfile_line *l = fetch_line_nofs_ok(i); ht_ltextfile_line *m = new ht_ltextfile_line(); l->on_disk.ofs = l->nofs; if (l->is_in_memory) { l->on_disk.len = l->in_memory.len; free(l->in_memory.data); l->is_in_memory = false; } *m = *l; orig_lines->insert(m); } cache_invd(); } FileLayer::setLayered(streamfile, ownNewLayered);}void ht_ltextfile::set_lexer(ht_syntax_lexer *l){ if (lexer != l) { lexer = l; dirty_parse(0); }}FileOfs ht_ltextfile::tell() const{ return ofs;}void ht_ltextfile::truncate(FileOfs newsize){ /* FIXME: nyi */ throw IOException(ENOSYS);}void ht_ltextfile::update_parse(uint target){ ht_ltextfile_line *e; uint line = first_parse_dirty_line; lexer_state instate=0; if (line) { instate = next_instate(line-1);// FIXME: function help works with this already.../* e = fetch_line(line); instate = e->instate;*/ } else { if (lexer) instate = lexer->getinitstate(); } while (line<=target) { e = fetch_line(line); if (!e) break;// if (e->instate==instate) break; /* FIXME: valid simplification ?!... */ e->instate = instate; first_parse_dirty_line = line+1; instate = next_instate(line); line++; } e = fetch_line(line); if (e) e->instate = instate;}void ht_ltextfile::update_nofs(uint target) const{ ht_ltextfile_line *e; uint line=first_nofs_dirty_line; FileOfs nofs; if (line) { e=fetch_line(line-1); nofs=next_nofs(e); } else { nofs=0; } while (line<=target) { e=fetch_line(line); if (!e) break; e->nofs=nofs; first_nofs_dirty_line=line+1; nofs=next_nofs(e); line++; }}int ht_ltextfile::vcntl(uint cmd, va_list vargs){ switch (cmd) { case FCNTL_MODS_INVD: cache_invd(); return 0; case FCNTL_MODS_FLUSH: cache_flush(); return 0; case FCNTL_MODS_IS_DIRTY: { FileOfs o = va_arg(vargs, FileOfs); FileOfs s = va_arg(vargs, FileOfs); bool *b = va_arg(vargs, bool*); *b = dirty; o = 0; // gcc warns otherwise s = 0; // gcc warns otherwise return 0; } case FCNTL_MODS_CLEAR_DIRTY_RANGE: { FileOfs o = va_arg(vargs, FileOfs); FileOfs s = va_arg(vargs, FileOfs); dirty = false; o = s = 0; return 0; } } return ht_textfile::vcntl(cmd, vargs);}uint ht_ltextfile::write(const void *buf, uint size){ FileOfs o = tell(); uint line; uint pofs; byte *b = (byte*)buf; uint r = 0; if (convert_ofs2line(o, &line, &pofs)) { r = size; while (size) { int lelen; uint s; byte *c = match_lineend_forwd(b, size, &lelen); if (c) { s = c-b; split_line(line, pofs, c, lelen); } else { s = size; lelen = 0; } insert_chars(line, pofs, b, s); s += lelen; b += s; size -= s; line++; pofs = 0; } } ofs += r; return r;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -