123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977 |
- #include "filemanager.h"
- #include "scintillaeditview.h"
- #include "scintillahexeditview.h"
- #include "CmpareMode.h"
- #include "ccnotepad.h"
- #include <QMessageBox>
- #include <QFile>
- #include <QtGlobal>
- #include <qscilexer.h>
- FileManager::~FileManager()
- {
- }
- ScintillaEditView* FileManager::newEmptyDocument()
- {
- ScintillaEditView* pEdit = new ScintillaEditView(nullptr);
- return pEdit;
- }
- ScintillaHexEditView* FileManager::newEmptyHexDocument()
- {
- ScintillaHexEditView* pEdit = new ScintillaHexEditView(nullptr);
- return pEdit;
- }
- //从尾部找前面的换行符号。返回的是需要回溯的个数
- int findLineEndPos(const char* buf, int size)
- {
- int ret = 0;
- bool isfound = false;
- for (int i = size - 1; i >= 0; --i)
- {
- if (buf[i] == '\n')
- {
- isfound = true;
- break;
- }
- ++ret;
- }
- //如果没有找到,怀疑是mac格式,按照\r结尾解析
- if (!isfound)
- {
- for (int i = size - 1; i >= 0; --i)
- {
- if (buf[i] == '\r')
- {
- isfound = true;
- break;
- }
- ++ret;
- }
- }
- if (isfound)
- {
- return ret;
- }
- //说明是一个巨长的行,这种情况不是很好。直接读取了,不管是否进行了行截断
- return 0;
- }
- //从行首找后面的换行符号。返回的是需要前进的个数,即把前面掐掉一节,让返回在一行的行首位置
- int findLineStartPos(const char* buf, int size)
- {
- int ret = 0;
- bool isfound = false;
- for (int i = 0; i < size; ++i)
- {
- ++ret;
- if (buf[i] == '\n')
- {
- isfound = true;
- break;
- }
- }
- //如果没有找到,怀疑是mac格式,按照\r结尾解析
- if (!isfound)
- {
- for (int i = size - 1; i >= 0; --i)
- {
- ++ret;
- if (buf[i] == '\r')
- {
- isfound = true;
- break;
- }
- }
- }
- if (isfound)
- {
- return ret;
- }
- //说明是一个巨长的行,这种情况不是很好。直接读取了,不管是否进行了行截断
- return 0;
- }
- //返回第一个空闲的id,m_newFileIdList必须有序,从小到大,从0开始
- //序号也从0开始,notepad++是从1开始
- int FileManager::getNextNewFileId()
- {
- if (m_newFileIdList.isEmpty())
- {
- return 0;
- }
- int index = 0;
- bool isFind = false;
- for (int i = 0; i < m_newFileIdList.size(); ++i)
- {
- if (m_newFileIdList.at(i).index > i)
- {
- index = i;
- isFind = true;
- break;
- }
- }
- if (!isFind)
- {
- index = m_newFileIdList.size();
- }
- return index;
- }
- //务必要保证不能重复id,所以newnode后,必须接着调用insertNewFileNode,避免重复了
- void FileManager::insertNewFileNode(NewFileIdMgr node)
- {
- m_newFileIdList.append(node);
- std::sort(m_newFileIdList.begin(), m_newFileIdList.end(), [](NewFileIdMgr& a, NewFileIdMgr& b) {
- return a.index < b.index;
- });
- }
- //删除newfile id的节点
- void FileManager::delNewFileNode(int fileIndex)
- {
- for (int i = 0; i < m_newFileIdList.size(); ++i)
- {
- if (m_newFileIdList.at(i).index == fileIndex)
- {
- m_newFileIdList.removeAt(i);
- break;
- }
- }
- }
- //这里是以文本方式加载文件。但是可能遇到的是二进制文件,里面会做判断
- //二进制时hexAsk是否询问,当用户指定打开格式时,不需要询问
- int FileManager::loadFileDataInText(ScintillaEditView* editView, QString filePath, CODE_ID& fileTextCode, RC_LINE_FORM& lineEnd,CCNotePad * callbackObj, bool hexAsk)
- {
- QFile file(filePath);
- //如果文件不存在,直接返回
- if (!file.exists())
- {
- return -1;
- }
- QFlags<QFileDevice::Permission> power = QFile::permissions(filePath);
- #if 0
- if (!power.testFlag(QFile::ReadOwner))
- {
- //文件不能读
- QMessageBox::warning(nullptr, tr("Error"), tr("Open File %1 failed Can not read auth").arg(filePath));
-
- return 1;
- }
- #endif
- //直接以只读的方式打开,至于能不能保存,是保存时需要考虑的问题。
- //只需要在保存的时候获取admin权限即可
- QIODevice::OpenMode mode;
-
- mode = QIODevice::ExistingOnly | QIODevice::ReadOnly;
- #if 0
- if (!power.testFlag(QFile::WriteUser))
- {
- //文件不能写
- mode = QIODevice::ExistingOnly | QIODevice::ReadOnly;
- }
- else
- {
- mode = QIODevice::ExistingOnly | QIODevice::ReadWrite;
- }
- #endif
- if (!file.open(mode))
- {
- qDebug() << file.error();
- #ifdef Q_OS_WIN
- //打开失败,这里一般是权限问题导致。如果是windows,在外面申请权限后继续处理
- if (QFileDevice::OpenError == file.error())
- {
- if (callbackObj != nullptr)
- {
- return callbackObj->runAsAdmin(filePath);
- }
- return 1;
- }
- #endif
- #ifdef Q_OS_UNIX
- QMessageBox::warning(nullptr, tr("Error"), tr("Open File %1 failed").arg(filePath));
- #endif
- return 2;
- }
- qint64 fileSize = file.size();
- qint64 bufferSizeRequested = fileSize + qMin((qint64)(1 << 20), (qint64)(fileSize / 6));
- // As a 32bit application, we cannot allocate 2 buffer of more than INT_MAX size (it takes the whole address space)
- if (bufferSizeRequested > INT_MAX)
- {
- QMessageBox::warning(nullptr, tr("Error"), tr("File is too big to be opened by Notepad--"));
- file.close();
- return 3;
- }
- QList<LineFileInfo> outputLineInfoVec;
- int maxLineSize = 0;
- int charsNums = 0;
- bool isHexFile = false;
- fileTextCode = CmpareMode::scanFileOutPut(fileTextCode,filePath, outputLineInfoVec, maxLineSize, charsNums, isHexFile);
- if (isHexFile && hexAsk)
- {
- //检测到文件很可能是二进制文件,询问用户,是否以二进制加载
- int ret = QMessageBox::question(nullptr, tr("Open with Text or Hex?"), tr("The file %1 is likely to be binary. Do you want to open it in binary?").arg(filePath), tr("Hex Open"), tr("Text Open"), tr("Cancel"));
-
- if (ret == 0)
- {
- //16进制打开
- file.close();
- return 4;
- }
- else if (ret == 1)
- {
- //继续以文本打开
- }
- else
- {
- //取消,不打开
- file.close();
- return 2;
- }
- }
- if (maxLineSize > 0)
- {
- //int textWidth = editView->execute(SCI_TEXTWIDTH, STYLE_DEFAULT, reinterpret_cast<sptr_t>("P"));
- editView->execute(SCI_SETSCROLLWIDTH, maxLineSize*10);
- }
- //以第一行的换行为文本的换行符
- lineEnd = UNKNOWN_LINE;
- if (!outputLineInfoVec.isEmpty())
- {
- lineEnd = static_cast<RC_LINE_FORM>(outputLineInfoVec.at(0).lineEndFormat);
- }
- if (lineEnd == UNKNOWN_LINE)
- {
- #ifdef _WIN32
- lineEnd = DOS_LINE;
- #else
- lineEnd = UNIX_LINE;
- #endif
- }
- QString text;
- text.reserve(charsNums + 1);
- for (QList<LineFileInfo>::iterator it = outputLineInfoVec.begin(); it != outputLineInfoVec.end(); ++it)
- {
- text.append(it->unicodeStr);
- }
- file.close();
- //优先根据文件后缀来确定其语法风格
- LexerInfo lxdata = CCNotePad::getLangLexerIdByFileExt(filePath);
- if (lxdata.lexerId != L_TXT)
- {
- QsciLexer* lexer = editView->createLexer(lxdata.lexerId, lxdata.tagName);
- editView->setLexer(lexer);
- }
- else
- {
- //利用前面5行,进行一个编程语言的判断
- QString headContens;
- for (int i = 0; (i < outputLineInfoVec.size() && i < 5); ++i)
- {
- headContens.append(outputLineInfoVec.at(i).unicodeStr);
- }
- std::string headstr = headContens.toStdString();
- LangType _language = detectLanguageFromTextBegining((const unsigned char *)headstr.data(), headstr.length());
- if (_language >= 0 && _language < L_EXTERNAL)
- {
- QsciLexer* lexer = editView->createLexer(_language);
- editView->setLexer(lexer);
- }
- }
-
- //如果检测到时16进制文件,但是强行以二进制打开,则有限走setUtf8Text。
- if (!isHexFile)
- {
- editView->setText(text);
- }
- else
- {
- //这种情况,为了不编辑二进制模式,是可能只读的。
- if (1 == editView->setUtf8Text(text))
- {
- return 5;//只读模式
- }
- }
-
- return 0;
- }
- //加载文件,只为查找使用
- int FileManager::loadFileForSearch(ScintillaEditView* editView, QString filePath)
- {
- QFile file(filePath);
- QFlags<QFileDevice::Permission> power = QFile::permissions(filePath);
- if (!power.testFlag(QFile::ReadOwner))
- {
- //文件不能读
- return 1;
- }
- QIODevice::OpenMode mode;
- if (!power.testFlag(QFile::WriteOwner))
- {
- //文件不能写
- mode = QIODevice::ExistingOnly | QIODevice::ReadOnly;
- }
- else
- {
- mode = QIODevice::ExistingOnly | QIODevice::ReadWrite;
- }
- if (!file.open(mode))
- {
- qDebug() << file.error();
- return 2;
- }
- qint64 fileSize = file.size();
- qint64 bufferSizeRequested = fileSize + qMin((qint64)(1 << 20), (qint64)(fileSize / 6));
- // As a 32bit application, we cannot allocate 2 buffer of more than INT_MAX size (it takes the whole address space)
- if (bufferSizeRequested > INT_MAX)
- {
- file.close();
- return 3;
- }
- QList<LineFileInfo> outputLineInfoVec;
- int maxLineSize = 0;
- int charsNums = 0;
- bool isHexFile = false;
- CODE_ID fileTextCode = CODE_ID::UNKOWN;
- CmpareMode::scanFileOutPut(fileTextCode, filePath, outputLineInfoVec, maxLineSize, charsNums, isHexFile);
- if (isHexFile)
- {
- qDebug() << filePath;
- file.close();
- return 4;
- }
- if (maxLineSize > 0)
- {
- editView->execute(SCI_SETSCROLLWIDTH, maxLineSize * 10);
- }
- QString text;
- text.reserve(charsNums + 1);
- for (QList<LineFileInfo>::iterator it = outputLineInfoVec.begin(); it != outputLineInfoVec.end(); ++it)
- {
- text.append(it->unicodeStr);
- }
- file.close();
- editView->setText(text);
- return 0;
- }
- const int ONE_PAGE_BYTES = 4096;
- //加载下一页或者上一页。(二进制模式)
- int FileManager::loadFilePreNextPage(int dir, QString& filePath, HexFileMgr* & hexFileOut)
- {
- if (m_hexFileMgr.contains(filePath))
- {
- hexFileOut = m_hexFileMgr.value(filePath);
- qint64 pos = hexFileOut->fileOffset;
- if (dir == 1 && (pos >= 0))
- {
- //上一页
- pos = pos - hexFileOut->contentRealSize - ONE_PAGE_BYTES;
- if (pos < 0)
- {
- pos = 0;
- }
- }
- else if(dir == 2 && (pos < hexFileOut->fileSize))
- {
-
- }
- else
- {
- return 1;
- }
- char* buf = new char[ONE_PAGE_BYTES+1];
- hexFileOut->file->seek(pos);
- qint64 ret = hexFileOut->file->read(buf, ONE_PAGE_BYTES);
- if (ret <= 0)
- {
- return -1;
- }
- else
- {
- //读取成功
- hexFileOut->fileOffset = hexFileOut->file->pos();
- if (hexFileOut->contentBuf != nullptr)
- {
- delete[]hexFileOut->contentBuf;
- }
- hexFileOut->contentBuf = buf;
- hexFileOut->contentRealSize = ret;
- }
- return 0;
- }
- return -1;
- }
- const int ONE_PAGE_TEXT_SIZE = 200 * 1024;
- //加载下一页或者上一页。(文本模式)
- int FileManager::loadFilePreNextPage(int dir, QString& filePath, TextFileMgr* & textFileOut)
- {
- if (m_bigTxtFileMgr.contains(filePath))
- {
- textFileOut = m_bigTxtFileMgr.value(filePath);
- qint64 pos = textFileOut->fileOffset;
- int canReadSize = 0;
- if (dir == 1 && (pos >= 0))
- {
- //读取上一页
- pos = pos - textFileOut->contentRealSize - ONE_PAGE_TEXT_SIZE;
- if (pos < 0)
- {
- //前面的内容不足以ONE_PAGE_TEXT_SIZE字节
- canReadSize = textFileOut->fileOffset - textFileOut->contentRealSize;
- if (canReadSize <= 0)
- {
- return 1;
- }
- pos = 0;
- }
- else
- {
- canReadSize = ONE_PAGE_TEXT_SIZE;
- }
- }
- else if (dir == 2 && (pos < textFileOut->fileSize))
- {
- canReadSize = ONE_PAGE_TEXT_SIZE;
- }
- else
- {
- return 1;
- }
- char* buf = new char[canReadSize + 1];
- buf[canReadSize] = '\0';
- textFileOut->file->seek(pos);
- qint64 ret = textFileOut->file->read(buf, canReadSize);
- if (ret <= 0)
- {
- return -1;
- }
- else
- {
- //读取成功
- //如果是往后读取
- if (dir == 2)
- {
- //读取了1M的内容,从内容尾部往前查找,找到第一个换行符号。如果没有怎么办?说明是一个巨长的行,不妙
- buf[ret] = '\0';
- int preLineEndPos = 0;
-
- if (textFileOut->file->pos() < textFileOut->fileSize)//反之已经到尾部了,不需要往前找行首了
- {
- preLineEndPos = findLineEndPos(buf, ret);
- if (preLineEndPos > 0)
- {
- //给后面的字符填\0,让字符串正常结尾\0
- buf[ret - preLineEndPos] = '\0';
- }
- }
- textFileOut->fileOffset = textFileOut->file->pos() -preLineEndPos;
- if (preLineEndPos > 0)
- {
- //文件seek到下一行的首位置。
- textFileOut->file->seek(textFileOut->fileOffset);
- }
- if (textFileOut->contentBuf != nullptr)
- {
- delete[]textFileOut->contentBuf;
- }
- textFileOut->contentBuf = buf;
- textFileOut->contentRealSize = ret - preLineEndPos;
- }
- else if (dir == 1)
- {
- //如果是往前读取
- //读取了1M的内容,往内容前面往后查找,找到第一个换行符号。如果没有怎么办?说明是一个巨长的行,不妙
- buf[ret] = '\0';
- int preLineStartPos = 0;
- if (textFileOut->file->pos() > canReadSize)//==canReadSize说明已经在文件最前面了。不在最前面,需要
- {
- preLineStartPos = findLineStartPos(buf, ret);
- if (preLineStartPos > 0)
- {
- //把\n前面的内容去掉,通过内存move的方式。
- memmove(buf, buf+preLineStartPos,ret - preLineStartPos);
- buf[ret - preLineStartPos] = '\0';
- }
- }
- textFileOut->fileOffset = textFileOut->file->pos();
- if (textFileOut->contentBuf != nullptr)
- {
- delete[]textFileOut->contentBuf;
- }
- textFileOut->contentBuf = buf;
- textFileOut->contentRealSize = ret - preLineStartPos;
- }
- }
- return 0;
- }
- return -1;
- }
- //从指定地址开始加载文件
- int FileManager::loadFileFromAddr(QString filePath, qint64 addr, HexFileMgr* & hexFileOut)
- {
- if (m_hexFileMgr.contains(filePath))
- {
- hexFileOut = m_hexFileMgr.value(filePath);
- //超过文件大小
- if (addr < 0 || addr >= hexFileOut->fileSize)
- {
- return -2;
- }
- //4K对齐
- addr &= 0xfffffffffff0;
- char* buf = new char[ONE_PAGE_BYTES + 1];
- hexFileOut->file->seek(addr);
- qint64 ret = hexFileOut->file->read(buf, ONE_PAGE_BYTES);
- if (ret <= 0)
- {
- return -1;
- }
- else
- {
- //读取成功
- hexFileOut->fileOffset = hexFileOut->file->pos();
- if (hexFileOut->contentBuf != nullptr)
- {
- delete[]hexFileOut->contentBuf;
- }
- hexFileOut->contentBuf = buf;
- hexFileOut->contentRealSize = ret;
- }
- return 0;
- }
- return -1;
- }
- //从指定地址开始加载文本文件
- int FileManager::loadFileFromAddr(QString filePath, qint64 addr, TextFileMgr* & textFileOut)
- {
- if (m_bigTxtFileMgr.contains(filePath))
- {
- textFileOut = m_bigTxtFileMgr.value(filePath);
- //超过文件大小
- if (addr < 0 || addr >= textFileOut->fileSize)
- {
- return -2;
- }
- char* buf = new char[ONE_PAGE_TEXT_SIZE + 1];
- buf[ONE_PAGE_TEXT_SIZE] = '\0';
- textFileOut->file->seek(addr);
- qint64 ret = textFileOut->file->read(buf, ONE_PAGE_TEXT_SIZE);
- if (ret <= 0)//-1是出错。0也是没有读到
- {
- return -1;
- }
- else
- {
-
- int preLineEndPos = 0;
- buf[ret] = '\0';
- if (textFileOut->file->pos() < textFileOut->fileSize)//反之已经到尾部了,不需要往前找行了
- {
- preLineEndPos = findLineEndPos(buf, ret);
- if (preLineEndPos > 0)
- {
- //给后面的字符填\0,让字符串正常结尾\0
- buf[ret - preLineEndPos] = '\0';
- }
- }
- int preLineStartPos = findLineStartPos(buf, ret);
- if (preLineStartPos > 0 && preLineStartPos < ret) //preLineStartPos如果大于ret,则全部都被跳过了,不会显示,是个特例
- {
- memmove(buf, buf + preLineStartPos, ret - preLineStartPos);
- buf[ret - preLineStartPos] = '\0';
- }
- else
- {
- //如果没做调整,则后续不需要偏移,这里必须preLineStartPos赋0值
- preLineStartPos = 0;
- }
-
- //只需要文件调到上一行的行位即可。
- textFileOut->fileOffset = textFileOut->file->pos() - preLineEndPos;
- if (preLineEndPos > 0)
- {
- //文件seek到下一行的首位置。
- textFileOut->file->seek(textFileOut->fileOffset);
- }
- if (textFileOut->contentBuf != nullptr)
- {
- delete[]textFileOut->contentBuf;
- }
- textFileOut->contentBuf = buf;
- textFileOut->contentRealSize = ret - preLineEndPos - preLineStartPos;
- }
- return 0;
- }
- return -1;
- }
- //加载二进制文件。从curPos开始,每行16个byte,每次读取64行,一共1024个byte
- bool FileManager::loadFileData(QString filePath, HexFileMgr* & hexFileOut)
- {
- QFile *file = new QFile(filePath);
- if (!file->open(QIODevice::ReadOnly | QIODevice::ExistingOnly))
- {
- return false;
- }
- //小于10k的文件一次性全部读取完毕
- const int LITTLE_FILE_MAX = 10240;
- int readBytes = 0;
- if (file->size() <= LITTLE_FILE_MAX)
- {
- readBytes = LITTLE_FILE_MAX;
- }
- else
- {
- //对于大于10K的文件,每次只读4K
- readBytes = ONE_PAGE_BYTES;
- }
- char* buf = new char[readBytes];
- qint64 ret = file->read(buf, readBytes);
- if (ret == -1)
- {
- //错误
- file->close();
- delete file;
- return false;
- }
- else
- {
- HexFileMgr* hexFile = nullptr;
- if (!m_hexFileMgr.contains(filePath))
- {
- hexFile = new HexFileMgr();
- hexFile->filePath = filePath;
- hexFile->file = file;
- hexFile->fileOffset = file->pos();
- hexFile->fileSize = file->size();
- hexFile->contentBuf = buf;
- hexFile->contentRealSize = ret;
- m_hexFileMgr.insert(filePath, hexFile);
- }
- else
- {
- //理论上这里永远不走
- hexFile = m_hexFileMgr.value(filePath);
- hexFile->fileOffset = file->pos();
- hexFile->contentBuf = buf;
- hexFile->contentRealSize = ret;
- }
- hexFileOut = hexFile;
- return true;
- }
- return false;
- }
- //加载大文本文件。从0开始读取ONE_PAGE_TEXT_SIZE 500K的内容
- bool FileManager::loadFileData(QString filePath, TextFileMgr* & textFileOut)
- {
- QFile *file = new QFile(filePath);
- if (!file->open(QIODevice::ReadOnly | QIODevice::ExistingOnly))
- {
- return false;
- }
- int readBytes = ONE_PAGE_TEXT_SIZE;
- char* buf = new char[ONE_PAGE_TEXT_SIZE+1];
- buf[ONE_PAGE_TEXT_SIZE] = '\0';
- qint64 ret = file->read(buf, readBytes);
- if (ret <= 0)
- {
- //错误
- file->close();
- delete file;
- return false;
- }
- else
- {
- //读取了1M的内容,从尾部往找,找到第一个换行符号。如果没有怎么办?说明是一个巨长的行,不妙
- buf[ret] = '\0';
- int preLineEndPos = findLineEndPos(buf,ret);
- if (preLineEndPos > 0)
- {
- //给后面的字符填\0,让字符串正常结尾\0
- buf[ret - preLineEndPos] = '\0';
- }
- TextFileMgr* txtFile = nullptr;
- if (!m_bigTxtFileMgr.contains(filePath))
- {
- txtFile = new TextFileMgr();
- txtFile->filePath = filePath;
- txtFile->file = file;
- txtFile->fileOffset = file->pos() - preLineEndPos;
- if (preLineEndPos > 0)
- {
- //文件seek到下一行的首位置。下次读的时候,头部肯定是一行的行首啦
- file->seek(txtFile->fileOffset);
- }
- txtFile->fileSize = file->size();
- txtFile->contentBuf = buf;
- txtFile->contentRealSize = ret - preLineEndPos;
- m_bigTxtFileMgr.insert(filePath, txtFile);
- }
- else
- {
- //理论上这里永远不走
- assert(false);
- txtFile = m_bigTxtFileMgr.value(filePath);
- txtFile->fileOffset = file->pos();
- txtFile->contentBuf = buf;
- txtFile->contentRealSize = ret;
- }
- textFileOut = txtFile;
- return true;
- }
- return false;
- }
- HexFileMgr * FileManager::getHexFileHand(QString filepath)
- {
- if (m_hexFileMgr.contains(filepath))
- {
- return m_hexFileMgr.value(filepath);
- }
- return nullptr;
- }
- void FileManager::closeHexFileHand(QString filepath)
- {
- if (m_hexFileMgr.contains(filepath))
- {
- HexFileMgr* v = m_hexFileMgr.value(filepath);
- v->destory();
- delete v;
- m_hexFileMgr.remove(filepath);
- }
- }
- void FileManager::closeBigTextFileHand(QString filepath)
- {
- if (m_bigTxtFileMgr.contains(filepath))
- {
- TextFileMgr* v = m_bigTxtFileMgr.value(filepath);
- v->destory();
- delete v;
- m_bigTxtFileMgr.remove(filepath);
- }
- }
- //检查文件的编程语言
- LangType FileManager::detectLanguageFromTextBegining(const unsigned char *data, size_t dataLen)
- {
- struct FirstLineLanguages
- {
- std::string pattern;
- LangType lang;
- };
- // Is the buffer at least the size of a BOM?
- if (dataLen <= 3)
- return L_TXT;
- // Eliminate BOM if present
- size_t i = 0;
- if ((data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) || // UTF8 BOM
- (data[0] == 0xFE && data[1] == 0xFF && data[2] == 0x00) || // UTF16 BE BOM
- (data[0] == 0xFF && data[1] == 0xFE && data[2] == 0x00)) // UTF16 LE BOM
- i += 3;
- // Skip any space-like char
- for (; i < dataLen; ++i)
- {
- if (data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r')
- break;
- }
- // Create the buffer to need to test
- const size_t longestLength = 40; // shebangs can be large
- std::string buf2Test = std::string((const char *)data + i, longestLength);
- // Is there a \r or \n in the buffer? If so, truncate it
- auto cr = buf2Test.find("\r");
- auto nl = buf2Test.find("\n");
- auto crnl = qMin(cr, nl);
- if (crnl != std::string::npos && crnl < longestLength)
- buf2Test = std::string((const char *)data + i, crnl);
- // First test for a Unix-like Shebang
- // See https://en.wikipedia.org/wiki/Shebang_%28Unix%29 for more details about Shebang
- std::string shebang = "#!";
- size_t foundPos = buf2Test.find(shebang);
- if (foundPos == 0)
- {
- // Make a list of the most commonly used languages
- const size_t NB_SHEBANG_LANGUAGES = 7;
- FirstLineLanguages ShebangLangs[NB_SHEBANG_LANGUAGES] = {
- { "sh", L_BASH },
- { "python", L_PYTHON },
- { "perl", L_PERL },
- { "php", L_PHP },
- { "ruby", L_RUBY },
- { "node", L_JAVASCRIPT },
- { "Makefile", L_MAKEFILE}
- };
- // Go through the list of languages
- for (i = 0; i < NB_SHEBANG_LANGUAGES; ++i)
- {
- if (buf2Test.find(ShebangLangs[i].pattern) != std::string::npos)
- {
- return ShebangLangs[i].lang;
- }
- }
- // Unrecognized shebang (there is always room for improvement ;-)
- return L_TXT;
- }
- // Are there any other patterns we know off?
- const size_t NB_FIRST_LINE_LANGUAGES = 5;
- FirstLineLanguages languages[NB_FIRST_LINE_LANGUAGES] = {
- { "<?xml", L_XML },
- { "<?php", L_PHP },
- { "<html", L_HTML },
- { "<!DOCTYPE html", L_HTML },
- { "<?", L_PHP } // MUST be after "<?php" and "<?xml" to get the result as accurate as possible
- };
- for (i = 0; i < NB_FIRST_LINE_LANGUAGES; ++i)
- {
- foundPos = buf2Test.find(languages[i].pattern);
- if (foundPos == 0)
- {
- return languages[i].lang;
- }
- }
- // Unrecognized first line, we assume it is a text file for now
- return L_UNKNOWN;
- }
|