forked from mia/Aegisub
Store the lines in LuaAssFile in a vector
This makes the implementation better match the exposed interface and simplifies some of the code.
This commit is contained in:
parent
10f0f5fc7b
commit
59eae9ab85
2 changed files with 50 additions and 75 deletions
|
@ -55,7 +55,7 @@ namespace Automation4 {
|
|||
struct PendingCommit {
|
||||
wxString mesage;
|
||||
int modification_type;
|
||||
std::list<AssEntry*> lines;
|
||||
std::vector<AssEntry*> lines;
|
||||
};
|
||||
|
||||
/// Pointer to file being modified
|
||||
|
@ -70,6 +70,8 @@ namespace Automation4 {
|
|||
bool can_set_undo;
|
||||
/// throws an error if modification is disallowed
|
||||
void CheckAllowModify();
|
||||
/// throws an error if the line index is out of bounds
|
||||
void CheckBounds(int idx);
|
||||
|
||||
/// How ass file been modified by the script since the last commit
|
||||
int modification_type;
|
||||
|
@ -79,19 +81,12 @@ namespace Automation4 {
|
|||
int references;
|
||||
|
||||
/// Set of subtitle lines being modified; initially a shallow copy of ass->Line
|
||||
std::list<AssEntry*> lines;
|
||||
std::vector<AssEntry*> lines;
|
||||
/// Commits to apply once processing completes successfully
|
||||
std::deque<PendingCommit> pending_commits;
|
||||
/// Lines to delete once processing complete successfully
|
||||
std::deque<AssEntry*> lines_to_delete;
|
||||
|
||||
/// Cursor for last access into file
|
||||
std::list<AssEntry*>::iterator last_entry_ptr;
|
||||
/// Index for last access into file
|
||||
int last_entry_id;
|
||||
/// Move last_entry_ptr to 1-based index n
|
||||
void SeekCursorTo(int n);
|
||||
|
||||
int ObjectIndexRead(lua_State *L);
|
||||
void ObjectIndexWrite(lua_State *L);
|
||||
int ObjectGetLen(lua_State *L);
|
||||
|
|
|
@ -183,6 +183,12 @@ namespace Automation4 {
|
|||
luaL_error(L, "Attempt to modify subtitles in read-only feature context.");
|
||||
}
|
||||
|
||||
void LuaAssFile::CheckBounds(int idx)
|
||||
{
|
||||
if (idx <= 0 || idx > (int)lines.size())
|
||||
luaL_error(L, "Requested out-of-range line from subtitle file: %d", idx);
|
||||
}
|
||||
|
||||
void LuaAssFile::AssEntryToLua(lua_State *L, AssEntry *e)
|
||||
{
|
||||
lua_newtable(L);
|
||||
|
@ -371,35 +377,17 @@ namespace Automation4 {
|
|||
}
|
||||
}
|
||||
|
||||
void LuaAssFile::SeekCursorTo(int n)
|
||||
{
|
||||
if (n <= 0 || n > (int)lines.size())
|
||||
luaL_error(L, "Requested out-of-range line from subtitle file: %d", n);
|
||||
|
||||
if (n < last_entry_id - n) {
|
||||
// fastest to search from start
|
||||
last_entry_ptr = lines.begin();
|
||||
last_entry_id = 1;
|
||||
}
|
||||
else if ((int)lines.size() - last_entry_id < abs(last_entry_id - n)) {
|
||||
// fastest to search from end
|
||||
last_entry_ptr = lines.end();
|
||||
last_entry_id = lines.size() + 1;
|
||||
}
|
||||
// otherwise fastest to search from cursor
|
||||
|
||||
advance(last_entry_ptr, n - last_entry_id);
|
||||
last_entry_id = n;
|
||||
}
|
||||
|
||||
int LuaAssFile::ObjectIndexRead(lua_State *L)
|
||||
{
|
||||
switch (lua_type(L, 2)) {
|
||||
case LUA_TNUMBER:
|
||||
{
|
||||
// read an indexed AssEntry
|
||||
SeekCursorTo(lua_tointeger(L, 2));
|
||||
AssEntryToLua(L, *last_entry_ptr);
|
||||
int idx = lua_tointeger(L, 2);
|
||||
CheckBounds(idx);
|
||||
AssEntryToLua(L, lines[idx - 1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case LUA_TSTRING:
|
||||
{
|
||||
|
@ -466,9 +454,9 @@ namespace Automation4 {
|
|||
// insert
|
||||
AssEntry *e = LuaToAssEntry(L);
|
||||
modification_type |= modification_mask(e);
|
||||
SeekCursorTo(n);
|
||||
lines_to_delete.push_back(*last_entry_ptr);
|
||||
*last_entry_ptr = e;
|
||||
CheckBounds(n);
|
||||
lines_to_delete.push_back(lines[n - 1]);
|
||||
lines[n - 1] = e;
|
||||
}
|
||||
else {
|
||||
// delete
|
||||
|
@ -497,40 +485,43 @@ namespace Automation4 {
|
|||
while (itemcount > 0) {
|
||||
int n = luaL_checkint(L, itemcount);
|
||||
luaL_argcheck(L, n > 0 && n <= (int)lines.size(), itemcount, "Out of range line index");
|
||||
ids.push_back(n);
|
||||
ids.push_back(n - 1);
|
||||
--itemcount;
|
||||
}
|
||||
|
||||
// sort the item id's so we can delete from last to first to preserve original numbering
|
||||
sort(ids.begin(), ids.end());
|
||||
|
||||
// now delete the id's backwards
|
||||
SeekCursorTo(ids.back());
|
||||
for (size_t i = ids.size(); i > 0; --i) {
|
||||
while (last_entry_id > ids[i - 1]) {
|
||||
--last_entry_ptr;
|
||||
--last_entry_id;
|
||||
size_t id_idx = 0, out = 0;
|
||||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
if (id_idx < ids.size() && ids[id_idx] == i) {
|
||||
modification_type |= modification_mask(lines[i]);
|
||||
lines_to_delete.push_back(lines[i]);
|
||||
++id_idx;
|
||||
}
|
||||
else {
|
||||
lines[out++] = lines[i];
|
||||
}
|
||||
modification_type |= modification_mask(*last_entry_ptr);
|
||||
lines_to_delete.push_back(*last_entry_ptr);
|
||||
lines.erase(last_entry_ptr++);
|
||||
}
|
||||
|
||||
lines.erase(lines.begin() + out, lines.end());
|
||||
}
|
||||
|
||||
void LuaAssFile::ObjectDeleteRange(lua_State *L)
|
||||
{
|
||||
CheckAllowModify();
|
||||
|
||||
int a = std::max<int>(luaL_checkinteger(L, 1), 1);
|
||||
int b = std::min<int>(luaL_checkinteger(L, 2), lines.size());
|
||||
size_t a = std::max<size_t>(luaL_checkinteger(L, 1), 1) - 1;
|
||||
size_t b = std::min<size_t>(luaL_checkinteger(L, 2), lines.size());
|
||||
|
||||
SeekCursorTo(a);
|
||||
if (a >= b) return;
|
||||
|
||||
while (a++ <= b) {
|
||||
modification_type |= modification_mask(*last_entry_ptr);
|
||||
lines_to_delete.push_back(*last_entry_ptr);
|
||||
lines.erase(last_entry_ptr++);
|
||||
for (; b < lines.size(); ++a, ++b) {
|
||||
modification_type |= modification_mask(lines[a]);
|
||||
lines_to_delete.push_back(lines[a]);
|
||||
lines[a] = lines[b];
|
||||
}
|
||||
|
||||
lines.erase(lines.begin() + a, lines.end());
|
||||
}
|
||||
|
||||
void LuaAssFile::ObjectAppend(lua_State *L)
|
||||
|
@ -539,18 +530,13 @@ namespace Automation4 {
|
|||
|
||||
int n = lua_gettop(L);
|
||||
|
||||
if (last_entry_ptr != lines.begin()) {
|
||||
--last_entry_ptr;
|
||||
--last_entry_id;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_pushvalue(L, i);
|
||||
AssEntry *e = LuaToAssEntry(L);
|
||||
modification_type |= modification_mask(e);
|
||||
|
||||
// Find the appropriate place to put it
|
||||
std::list<AssEntry*>::iterator it = lines.end();
|
||||
std::vector<AssEntry*>::iterator it = lines.end();
|
||||
if (!lines.empty()) {
|
||||
do {
|
||||
--it;
|
||||
|
@ -574,11 +560,6 @@ namespace Automation4 {
|
|||
lines.insert(it, e);
|
||||
}
|
||||
}
|
||||
|
||||
// If last_entry_ptr is end, the file was empty but no longer is, so
|
||||
// last_entry_id is wrong
|
||||
if (last_entry_ptr == lines.end())
|
||||
last_entry_id = lines.size() + 1;
|
||||
}
|
||||
|
||||
void LuaAssFile::ObjectInsert(lua_State *L)
|
||||
|
@ -597,18 +578,16 @@ namespace Automation4 {
|
|||
return;
|
||||
}
|
||||
|
||||
SeekCursorTo(before);
|
||||
|
||||
int n = lua_gettop(L);
|
||||
std::vector<AssEntry *> new_entries(n - 1, (AssEntry *)0);
|
||||
for (int i = 2; i <= n; i++) {
|
||||
lua_pushvalue(L, i);
|
||||
AssEntry *e = LuaToAssEntry(L);
|
||||
modification_type |= modification_mask(e);
|
||||
lines.insert(last_entry_ptr, e);
|
||||
new_entries[i - 2] = e;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
last_entry_id += n - 1;
|
||||
lines.insert(lines.begin() + before - 1, new_entries.begin(), new_entries.end());
|
||||
}
|
||||
|
||||
void LuaAssFile::ObjectGarbageCollect(lua_State *L)
|
||||
|
@ -680,13 +659,16 @@ namespace Automation4 {
|
|||
{
|
||||
// Apply any pending commits
|
||||
for (std::deque<PendingCommit>::iterator it = pending_commits.begin(); it != pending_commits.end(); ++it) {
|
||||
swap(ass->Line, it->lines);
|
||||
ass->Line.clear();
|
||||
ass->Line.insert(ass->Line.end(), it->lines.begin(), it->lines.end());
|
||||
ass->Commit(it->mesage, it->modification_type);
|
||||
}
|
||||
|
||||
// Commit any changes after the last undo point was set
|
||||
if (modification_type)
|
||||
swap(ass->Line, lines);
|
||||
if (modification_type) {
|
||||
ass->Line.clear();
|
||||
ass->Line.insert(ass->Line.end(), lines.begin(), lines.end());
|
||||
}
|
||||
if (modification_type && can_set_undo && !undo_description.empty())
|
||||
ass->Commit(undo_description, modification_type);
|
||||
|
||||
|
@ -709,9 +691,7 @@ namespace Automation4 {
|
|||
, can_set_undo(can_set_undo)
|
||||
, modification_type(0)
|
||||
, references(2)
|
||||
, lines(ass->Line)
|
||||
, last_entry_ptr(lines.begin())
|
||||
, last_entry_id(1)
|
||||
, lines(ass->Line.begin(), ass->Line.end())
|
||||
{
|
||||
// prepare userdata object
|
||||
*static_cast<LuaAssFile**>(lua_newuserdata(L, sizeof(LuaAssFile*))) = this;
|
||||
|
|
Loading…
Reference in a new issue