//database functions void dbsave() { dprintf("Saving database..."); DWORD ticks = GetTickCount(); JSON root = json_object(); CommentCacheSave(root); LabelCacheSave(root); BookmarkCacheSave(root); FunctionCacheSave(root); LoopCacheSave(root); BpCacheSave(root); WString wdbpath = StringUtils::Utf8ToUtf16(dbpath); if(json_object_size(root)) { Handle hFile = CreateFileW(wdbpath.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); if(!hFile) { dputs("\nFailed to open database for writing!"); json_decref(root); //free root return; } SetEndOfFile(hFile); char* jsonText = json_dumps(root, JSON_INDENT(4)); DWORD written = 0; if(!WriteFile(hFile, jsonText, (DWORD)strlen(jsonText), &written, 0)) { json_free(jsonText); dputs("\nFailed to write database file!"); json_decref(root); //free root return; } hFile.Close(); json_free(jsonText); if(!settingboolget("Engine", "DisableDatabaseCompression")) LZ4_compress_fileW(wdbpath.c_str(), wdbpath.c_str()); } else //remove database when nothing is in there DeleteFileW(wdbpath.c_str()); dprintf("%ums\n", GetTickCount() - ticks); json_decref(root); //free root }
static bool scriptcreatelinemap(const char* filename) { Handle hFile = CreateFileW(StringUtils::Utf8ToUtf16(filename).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if(hFile == INVALID_HANDLE_VALUE) { GuiScriptError(0, "CreateFile failed..."); return false; } unsigned int filesize = GetFileSize(hFile, 0); if(!filesize) { GuiScriptError(0, "Empty script..."); return false; } Memory<char*> filedata(filesize + 1, "createlinemap:filedata"); DWORD read = 0; if(!ReadFile(hFile, filedata(), filesize, &read, 0)) { GuiScriptError(0, "ReadFile failed..."); return false; } hFile.Close(); int len = (int)strlen(filedata()); char temp[256] = ""; LINEMAPENTRY entry; memset(&entry, 0, sizeof(entry)); std::vector<LINEMAPENTRY>().swap(linemap); for(int i = 0, j = 0; i < len; i++) //make raw line map { if(filedata()[i] == '\r' && filedata()[i + 1] == '\n') //windows file { memset(&entry, 0, sizeof(entry)); int add = 0; while(temp[add] == ' ') add++; strcpy_s(entry.raw, temp + add); *temp = 0; j = 0; i++; linemap.push_back(entry); } else if(filedata()[i] == '\n') //other file { memset(&entry, 0, sizeof(entry)); int add = 0; while(temp[add] == ' ') add++; strcpy_s(entry.raw, temp + add); *temp = 0; j = 0; linemap.push_back(entry); } else if(j >= 254) { memset(&entry, 0, sizeof(entry)); int add = 0; while(temp[add] == ' ') add++; strcpy_s(entry.raw, temp + add); *temp = 0; j = 0; linemap.push_back(entry); } else j += sprintf(temp + j, "%c", filedata()[i]); } if(*temp) { memset(&entry, 0, sizeof(entry)); strcpy_s(entry.raw, temp); linemap.push_back(entry); } int linemapsize = (int)linemap.size(); while(!*linemap.at(linemapsize - 1).raw) //remove empty lines from the end { linemapsize--; linemap.pop_back(); } for(int i = 0; i < linemapsize; i++) { LINEMAPENTRY cur = linemap.at(i); //temp. remove comments from the raw line char line_comment[256] = ""; char* comment = strstr(&cur.raw[0], "//"); if(comment && comment != cur.raw) //only when the line doesnt start with a comment { if(*(comment - 1) == ' ') //space before comment { strcpy_s(line_comment, comment); *(comment - 1) = '\0'; } else //no space before comment { strcpy_s(line_comment, comment); *comment = 0; } } int rawlen = (int)strlen(cur.raw); if(!rawlen) //empty { cur.type = lineempty; } else if(!strncmp(cur.raw, "//", 2)) //comment { cur.type = linecomment; strcpy_s(cur.u.comment, cur.raw); } else if(cur.raw[rawlen - 1] == ':') //label { cur.type = linelabel; sprintf(cur.u.label, "l %.*s", rawlen - 1, cur.raw); //create a fake command for formatting strcpy_s(cur.u.label, StringUtils::Trim(cur.u.label).c_str()); char temp[256] = ""; strcpy_s(temp, cur.u.label + 2); strcpy_s(cur.u.label, temp); //remove fake command if(!*cur.u.label || !strcmp(cur.u.label, "\"\"")) //no label text { char message[256] = ""; sprintf(message, "Empty label detected on line %d!", i + 1); GuiScriptError(0, message); std::vector<LINEMAPENTRY>().swap(linemap); return false; } int foundlabel = scriptlabelfind(cur.u.label); if(foundlabel) //label defined twice { char message[256] = ""; sprintf(message, "Duplicate label \"%s\" detected on lines %d and %d!", cur.u.label, foundlabel, i + 1); GuiScriptError(0, message); std::vector<LINEMAPENTRY>().swap(linemap); return false; } } else if(scriptgetbranchtype(cur.raw) != scriptnobranch) //branch { cur.type = linebranch; cur.u.branch.type = scriptgetbranchtype(cur.raw); char newraw[MAX_SCRIPT_LINE_SIZE] = ""; strcpy_s(newraw, StringUtils::Trim(cur.raw).c_str()); int len = (int)strlen(newraw); for(int i = 0; i < len; i++) if(newraw[i] == ' ') { strcpy_s(cur.u.branch.branchlabel, newraw + i + 1); break; } } else { cur.type = linecommand; strcpy_s(cur.u.command, cur.raw); } //append the comment to the raw line again if(*line_comment) sprintf(cur.raw + rawlen, " %s", line_comment); linemap.at(i) = cur; } linemapsize = (int)linemap.size(); for(int i = 0; i < linemapsize; i++) { auto & currentLine = linemap.at(i); if(currentLine.type == linebranch) //invalid branch label { int labelline = scriptlabelfind(currentLine.u.branch.branchlabel); if(!labelline) //invalid branch label { char message[256] = ""; sprintf(message, "Invalid branch label \"%s\" detected on line %d!", currentLine.u.branch.branchlabel, i + 1); GuiScriptError(0, message); std::vector<LINEMAPENTRY>().swap(linemap); return false; } else //set the branch destination line currentLine.u.branch.dest = scriptinternalstep(labelline); } } if(linemap.at(linemapsize - 1).type == linecomment || linemap.at(linemapsize - 1).type == linelabel) //label/comment on the end { memset(&entry, 0, sizeof(entry)); entry.type = linecommand; strcpy_s(entry.raw, "ret"); strcpy_s(entry.u.command, "ret"); linemap.push_back(entry); } return true; }
void dbload() { // If the file doesn't exist, there is no DB to load if(!FileExists(dbpath)) return; dprintf("Loading database..."); DWORD ticks = GetTickCount(); // Multi-byte (UTF8) file path converted to UTF16 WString databasePathW = StringUtils::Utf8ToUtf16(dbpath); // Decompress the file if compression was enabled bool useCompression = !settingboolget("Engine", "DisableDatabaseCompression"); LZ4_STATUS lzmaStatus = LZ4_INVALID_ARCHIVE; { lzmaStatus = LZ4_decompress_fileW(databasePathW.c_str(), databasePathW.c_str()); // Check return code if(useCompression && lzmaStatus != LZ4_SUCCESS && lzmaStatus != LZ4_INVALID_ARCHIVE) { dputs("\nInvalid database file!"); return; } } // Read the database file Handle hFile = CreateFileW(databasePathW.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if(!hFile) { dputs("\nFailed to open database file!"); return; } unsigned int jsonFileSize = GetFileSize(hFile, 0); if(!jsonFileSize) { dputs("\nEmpty database file!"); return; } Memory<char*> jsonText(jsonFileSize + 1); DWORD read = 0; if(!ReadFile(hFile, jsonText(), jsonFileSize, &read, 0)) { dputs("\nFailed to read database file!"); return; } hFile.Close(); // Deserialize JSON JSON root = json_loads(jsonText(), 0, 0); if(lzmaStatus != LZ4_INVALID_ARCHIVE && useCompression) LZ4_compress_fileW(databasePathW.c_str(), databasePathW.c_str()); // Validate JSON load status if(!root) { dputs("\nInvalid database file (JSON)!"); return; } // Finally load all structures CommentCacheLoad(root); LabelCacheLoad(root); BookmarkCacheLoad(root); FunctionCacheLoad(root); LoopCacheLoad(root); BpCacheLoad(root); // Free root json_decref(root); dprintf("%ums\n", GetTickCount() - ticks); }