metin2-factory 1010 Posted March 4, 2017 Share Posted March 4, 2017 Hey, I have made a small function that will enable you to use an unlimited amount of arguments in server source code. For example look at the function do_item in cmd_gm.cpp, it gets 2 arguments : arg1 and arg2. Using my function you will be able to have as many arguments easier and in more convenient way. That means you can have 5,7 or even 20 arguments. Let's begin: Open utils.cpp and look for #include "stdafx.h" add below the following: #include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of #include <boost/algorithm/string/split.hpp> look for const char *first_cmd add above: void split_argument(const char *argument, std::vector<std::string> & vecArgs) { std::string arg = argument; boost::split(vecArgs, arg, boost::is_any_of(" "), boost::token_compress_on); } open utils.h and look for const char * first_cmd add above: extern void split_argument(const char *argument, std::vector<std::string> & vecArgs); That's all. How to use? Let's look for example in ACMD(do_item) method: Instead of char arg1[256], arg2[256]; two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2)); you can replace with: std::vector<std::string> vecArgs; split_argument(argument,vecArgs); And now you can access any of the arguments starting from index of 1. so for example if you type ingame the command /item 6001 10 vecArgs[1] is 6001 vecArgs[2] is 10 if you need to convert it to number, you can use as example: int iCount = 0; str_to_number(iCount, vecArgs[2].c_str()); If you need any assistance, write here a reply and ill do my best in helping you. Enjoy 10 Link to comment Share on other sites More sharing options...
alondark 59 Posted March 4, 2017 Share Posted March 4, 2017 better than ymir, thanks xD 1 Link to comment Share on other sites More sharing options...
avertuss 48 Posted February 18, 2020 Share Posted February 18, 2020 Should i replace for example if (!*arg1) to if (!*vecArgs[1]) or not? Link to comment Share on other sites More sharing options...
UdvAtt108 100 Posted February 18, 2020 Share Posted February 18, 2020 (edited) 8 minutes ago, avertuss said: Should i replace for example if (!*arg1) to if (!*vecArgs[1]) or not? That is not correct. You can check the argument exists like the following exmaple: if(vecArgs.size() >= 1 && !vecArgs[0].empty()) //if it has to be with one argument if(vecArgs.size() >= 2 && !vecArgs[1].empty()) //if it has to be with two argument if(vecArgs.size() >= 3 && !vecArgs[2].empty()) //if it has to be with three argument etc...etc...etc... Be carefull, because when you would like to get the contained string from vector for example to a const char *, you have to convert the string to char*: vecArgs[0].c_str() Edited February 18, 2020 by UdvAtt108 All wolves are gray in the dark. Link to comment Share on other sites More sharing options...
Active Member hachiwari 138 Posted February 18, 2020 Active Member Share Posted February 18, 2020 Why did you use boost library? 1 Link to comment Share on other sites More sharing options...
Forum Moderator VegaS™ 10274 Posted February 18, 2020 Forum Moderator Share Posted February 18, 2020 (edited) On 2/18/2020 at 9:40 PM, hachiwari said: Why did you use boost library? This method is good for old compilers, but I would use regex right now, you've an example in a tool what i did some time ago. This is the hidden content, please Sign In or Sign Up Should look like: This is the hidden content, please Sign In or Sign Up Edited December 3, 2020 by VegaS™ 86 1 1 21 1 34 Check my GitHub Profile Click to find all the threads started by me [TOOL] Text file loader + JSON Link to comment Share on other sites More sharing options...
ARiniii 5 Posted March 29, 2022 Share Posted March 29, 2022 Hello! How to use here? my build error: 1>..\..\source\EterPack\EterPack.cpp(348): error C2660: 'CLZO::CompressEncryptedMemory' : function does not take 5 arguments 1>..\..\source\EterPack\EterPack.cpp(430): error C2660: 'CLZO::Decompress' : function does not take 4 arguments 1>..\..\source\EterPack\EterPack.cpp(575): error C2660: 'CLZO::Decompress' : function does not take 4 arguments 1>..\..\source\EterPack\EterPack.cpp(688): error C2660: 'CLZO::Decompress' : function does not take 4 arguments 1>..\..\source\EterPack\EterPack.cpp(802): error C2660: 'CLZO::Decompress' : function does not take 4 arguments 1>..\..\source\EterPack\EterPack.cpp(975): error C2660: 'CLZO::CompressEncryptedMemory' : function does not take 5 arguments eterpack.cpp Spoiler #include "StdAfx.h" #include <windows.h> #include <mmsystem.h> #include <io.h> #include <assert.h> #include "EterPack.h" #include "Inline.h" #include "EterPackPolicy_CSHybridCrypt.h" #pragma warning(push, 3) #include <cryptopp/cryptlib.h> #include <cryptopp/filters.h> #include <cryptopp/modes.h> #include <cryptopp/tiger.h> #include <cryptopp/sha.h> #include <cryptopp/ripemd.h> #include <cryptopp/whrlpool.h> #include <cryptopp/panama.h> #include <cryptopp/cryptoppLibLink.h> #pragma warning(pop) #include "../EterBase/utils.h" #include "../EterBase/Debug.h" #include "../EterBase/CRC32.h" #ifdef __THEMIDA__ #include <ThemidaSDK.h> #endif #include <iostream> #include <fstream> #define OUT_EXT ".rpm" #define TWOCC 0x5B0C #define OFFSET_KEY 0xd34dc0d3 void CMakePackLog::SetFileName(const char* c_szFileName) { m_stFileName = c_szFileName; m_stFileName += ".log"; m_stErrorFileName = c_szFileName; m_stErrorFileName += ".err"; } CMakePackLog& CMakePackLog::GetSingleton() { static CMakePackLog s_kMakePackLog; return s_kMakePackLog; } CMakePackLog::CMakePackLog() { m_fp = NULL; m_fp_err = NULL; } CMakePackLog::~CMakePackLog() { if (NULL != m_fp) { fclose(m_fp); m_fp = NULL; } if (NULL != m_fp_err) { fclose(m_fp_err); m_fp_err = NULL; } } bool CMakePackLog::__IsLogMode() { if (m_stFileName.empty()) return false; return true; } void CMakePackLog::Writef(const char* c_szFormat, ...) { if (!__IsLogMode()) return; va_list args; va_start(args, c_szFormat); char szBuf[1024]; int nBufLen = _vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args); szBuf[nBufLen++] = '\0'; __Write(szBuf, nBufLen); } void CMakePackLog::Writenf(const char* c_szFormat, ...) { if (!__IsLogMode()) return; va_list args; va_start(args, c_szFormat); char szBuf[1024 + 1]; int nBufLen = _vsnprintf(szBuf, sizeof(szBuf)-1, c_szFormat, args); if (nBufLen > 0) { szBuf[nBufLen++] = '\n'; szBuf[nBufLen++] = '\0'; } __Write(szBuf, nBufLen); } void CMakePackLog::Write(const char* c_szBuf) { if (!__IsLogMode()) return; __Write(c_szBuf, strlen(c_szBuf) + 1); } void CMakePackLog::__Write(const char* c_szBuf, int nBufLen) { if (!__IsLogMode()) return; if (NULL == m_fp) m_fp = fopen(m_stFileName.c_str(), "w"); fwrite(c_szBuf, nBufLen, 1, m_fp); printf("%s", c_szBuf); } void CMakePackLog::WriteErrorf(const char* c_szFormat, ...) { if (!__IsLogMode()) return; va_list args; va_start(args, c_szFormat); char szBuf[1024]; int nBufLen = _vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args); szBuf[nBufLen++] = '\0'; __WriteError(szBuf, nBufLen); } void CMakePackLog::WriteErrornf(const char* c_szFormat, ...) { if (!__IsLogMode()) return; va_list args; va_start(args, c_szFormat); char szBuf[1024 + 1]; int nBufLen = _vsnprintf(szBuf, sizeof(szBuf)-1, c_szFormat, args); if (nBufLen > 0) { szBuf[nBufLen++] = '\n'; szBuf[nBufLen++] = '\0'; } __WriteError(szBuf, nBufLen); } void CMakePackLog::WriteError(const char* c_szBuf) { if (!__IsLogMode()) return; __WriteError(c_szBuf, strlen(c_szBuf) + 1); } void CMakePackLog::__WriteError(const char* c_szBuf, int nBufLen) { if (!__IsLogMode()) return; if (NULL == m_fp_err) m_fp_err = fopen(m_stErrorFileName.c_str(), "w"); fwrite(c_szBuf, nBufLen, 1, m_fp_err); printf("Error: %s", c_szBuf); } void CMakePackLog::FlushError() { std::wifstream iFile(m_stErrorFileName.c_str()); std::istream_iterator <std::wstring, wchar_t> iit(iFile); std::istream_iterator <std::wstring, wchar_t> eos; std::vector <std::wstring> vText; std::copy(iit, eos, std::back_inserter(vText)); std::ostream_iterator <std::wstring, wchar_t, std::char_traits <wchar_t> > oit(std::wcout); std::sort(vText.begin(), vText.end()); std::copy(vText.begin(), vText.end(), oit); } #ifdef __MAKE_PACK__ FILE * CEterPack::ms_PackLogFile = NULL; #endif /////////////////////////////////////////////////////////////////////////////// CEterPack::CEterPack() : m_indexCount(0), m_indexData(NULL), m_FragmentSize(0), m_bEncrypted(false), m_bReadOnly(false), m_bDecrypedIV(false) { m_pCSHybridCryptPolicy = new EterPackPolicy_CSHybridCrypt; } CEterPack::~CEterPack() { Destroy(); delete m_pCSHybridCryptPolicy; m_pCSHybridCryptPolicy = NULL; } void CEterPack::Destroy() { m_bReadOnly = false; m_bEncrypted = false; m_indexCount = 0; m_DataPositionMap.clear(); for (int i = 0; i < FREE_INDEX_MAX_SIZE + 1; ++i) m_FreeIndexList[i].clear(); SAFE_DELETE_ARRAY(m_indexData); m_FragmentSize = 0; memset(m_dbName, 0, sizeof(m_dbName)); memset(m_indexFileName, 0, sizeof(m_indexFileName)); } const std::string& CEterPack::GetPathName() { return m_stPathName; } bool CEterPack::Create(CEterFileDict& rkFileDict, const char * dbname, const char* pathName, bool bReadOnly, const BYTE* iv) { if (iv) { m_stIV_Panama.assign((const char*)iv, 32); m_bDecrypedIV = false; } m_stPathName = pathName; strncpy(m_dbName, dbname, DBNAME_MAX_LEN); strncpy(m_indexFileName, dbname, MAX_PATH); strcat(m_indexFileName, OUT_EXT); m_stDataFileName = dbname; m_stDataFileName += OUT_EXT; m_bReadOnly = bReadOnly; // bReadOnly ¸ðµå°¡ ¾Æ´Ï°í µ¥ÀÌÅÍ º£À̽º°¡ ¿¸°´Ù¸é »ý¼º ½ÇÆÐ if (!CreateIndexFile()) return false; if (!CreateDataFile()) return false; bool bOverwrite = (iv != NULL); __BuildIndex(rkFileDict, bOverwrite); if (m_bReadOnly) { //m_bIsDataLoaded = true; //if (!m_file.Create(m_stDataFileName.c_str(), (const void**)&m_file_data, 0, 0)) // return false; } else { DecryptIndexFile(); } return true; } bool CEterPack::DecryptIV(DWORD dwPanamaKey) { if (m_stIV_Panama.length() != 32) return false; if (m_bDecrypedIV) // ÀÌ¹Ì ¾ÏȣȰ¡ Ç®·ÈÀ¸¸é ´Ù½Ã ó¸® ¾ÈÇÔ return true; DWORD* ivs = (DWORD*)&m_stIV_Panama[0]; for (int i = 0; i != m_stIV_Panama.length() / sizeof(DWORD); ++i) { ivs[i] ^= dwPanamaKey + i * 16777619; } m_bDecrypedIV = true; return true; } bool CEterPack::DecryptIndexFile() { if (!m_bEncrypted) return true; CFileBase file; if (!file.Create(m_indexFileName, CFileBase::FILEMODE_WRITE)) return false; file.Write(&eterpack::c_IndexCC, sizeof(DWORD)); file.Write(&eterpack::c_Version, sizeof(DWORD)); file.Write(&m_indexCount, sizeof(long)); file.Write(m_indexData, sizeof(TEterPackIndex)* m_indexCount); file.Close(); m_bEncrypted = false; return true; } static DWORD s_adwEterPackKey[] = { 0, 0, 0, 0 }; static DWORD s_adwEterPackSecurityKey[] = { 0, 0, 0, 0 }; bool CEterPack::EncryptIndexFile() { CMappedFile file; LPCVOID pvData; if (NULL == file.Create(m_indexFileName, &pvData, 0, 0)) { TraceError("EncryptIndex: Cannot open pack index file! %s", m_dbName); return false; } BYTE * pbData = new BYTE[file.Size()]; memcpy(pbData, pvData, file.Size()); CLZObject zObj; if (!CLZO::Instance().CompressEncryptedMemory(zObj, pbData, file.Size(), 1, s_adwEterPackKey)) { TraceError("EncryptIndex: Cannot encrypt! %s", m_dbName); SAFE_DELETE_ARRAY(pbData); return false; } file.Destroy(); while (!DeleteFile(m_indexFileName)); FILE * fp; fp = fopen(m_indexFileName, "wb"); if (!fp) { TraceError("EncryptIndex: Cannot open file for writing! %s", m_dbName); SAFE_DELETE_ARRAY(pbData); return false; } if (1 != fwrite(zObj.GetBuffer(), zObj.GetSize(), 1, fp)) { TraceError("Encryptindex: Cannot write to file! %s", m_indexFileName); SAFE_DELETE_ARRAY(pbData); fclose(fp); return false; } fclose(fp); m_bEncrypted = true; delete[] pbData; return true; } bool CEterPack::__BuildIndex(CEterFileDict& rkFileDict, bool bOverwrite) { //DWORD dwBeginTime = ELTimer_GetMSec(); CMappedFile file; LPCVOID pvData; CLZObject zObj; if (NULL == file.Create(m_indexFileName, &pvData, 0, 0)) { TraceError("Cannot open pack index file! %s", m_dbName); return false; } if (file.Size() < eterpack::c_HeaderSize) { TraceError("Pack index file header error! %s", m_dbName); return false; } //--------------------------- char* tData = (char*)pvData; DWORD twocc = *(WORD *)tData; if (twocc != TWOCC) { TraceError("Pack file header error! (TWOCC MISMATCH) %s", m_dbName); return false; } tData += sizeof(WORD); m_dataOff = ((*(DWORD*)tData) ^ OFFSET_KEY) + sizeof(WORD)+sizeof(DWORD); tData += sizeof(DWORD); pvData = (LPCVOID)tData; //--------------------------- DWORD fourcc = *(DWORD *)pvData; BYTE * pbData; UINT uiFileSize; if (fourcc == eterpack::c_IndexCC) { pbData = (BYTE *)pvData; uiFileSize = file.Size(); } else if (fourcc == CLZObject::ms_dwFourCC) { m_bEncrypted = true; if (!CLZO::Instance().Decompress(zObj, (const BYTE *)pvData, 1, s_adwEterPackKey)) return false; if (zObj.GetSize() < eterpack::c_HeaderSize) return false; pbData = zObj.GetBuffer(); uiFileSize = zObj.GetSize(); } else { TraceError("Pack index file fourcc error! %s", m_dbName); return false; } pbData += sizeof(DWORD); DWORD ver = *(DWORD *)pbData; pbData += sizeof(DWORD); if (ver != eterpack::c_Version) { TraceError("Pack index file version error! %s", m_dbName); return false; } m_indexCount = *(long *)pbData; pbData += sizeof(long); if (uiFileSize < eterpack::c_HeaderSize + sizeof(TEterPackIndex)* m_indexCount) { TraceError("Pack index file size error! %s, indexCount %d", m_dbName, m_indexCount); return false; } //Tracef("Loading Pack file %s elements: %d ... ", m_dbName, m_indexCount); m_indexData = new TEterPackIndex[m_indexCount]; memcpy(m_indexData, pbData, sizeof(TEterPackIndex)* m_indexCount); TEterPackIndex * index = m_indexData; for (int i = 0; i < m_indexCount; ++i, ++index) { if (!index->filename_crc) { PushFreeIndex(index); } else { if (index->real_data_size > index->data_size) m_FragmentSize += index->real_data_size - index->data_size; m_DataPositionMap.insert(TDataPositionMap::value_type(index->filename_crc, index)); if (bOverwrite) // ¼¹ö ¿¬µ¿ ÆÐÅ· ÆÄÀÏÀº ³ªÁß¿¡ µé¾î¿ÀÁö¸¸ ÃÖ»óÀ§·Î µî·ÏÇؾßÇÑ´Ù rkFileDict.UpdateItem(this, index); else rkFileDict.InsertItem(this, index); } } //Tracef("Done. (spent %dms)\n", ELTimer_GetMSec() - dwBeginTime); return true; } // //void CEterPack::UpdateLastAccessTime() //{ // m_tLastAccessTime = time(NULL); //} // //void CEterPack::ClearDataMemoryMap() //{ // // m_fileÀÌ data fileÀÌ´Ù... // m_file.Destroy(); // m_tLastAccessTime = 0; // m_bIsDataLoaded = false; //} bool CEterPack::Get(CMappedFile& out_file, const char * filename, LPCVOID * data) { TEterPackIndex * index = FindIndex(filename); if (!index) { return false; } //UpdateLastAccessTime(); //if (!m_bIsDataLoaded) //{ // if (!m_file.Create(m_stDataFileName.c_str(), (const void**)&m_file_data, 0, 0)) // return false; // // m_bIsDataLoaded = true; //} // ±âÁ¸¿¡´Â CEterPack¿¡¼ epk¸¦ memory map¿¡ ¿Ã·Á³õ°í, ¿äûÀÌ ¿À¸é ±× ºÎºÐÀ» ¸µÅ©Çؼ ³Ñ°Ü Áá¾ú´Âµ¥, // ÀÌÁ¦´Â ¿äûÀÌ ¿À¸é, ÇÊ¿äÇÑ ºÎºÐ¸¸ memory map¿¡ ¿Ã¸®°í, ¿äûÀÌ ³¡³ª¸é ÇØÁ¦ÇÏ°Ô ÇÔ. out_file.Create(m_stDataFileName.c_str(), data, index->data_position + m_dataOff, index->data_size); bool bIsSecurityCheckRequired = (index->compressed_type == COMPRESSED_TYPE_SECURITY || index->compressed_type == COMPRESSED_TYPE_PANAMA); if (bIsSecurityCheckRequired) { #ifdef CHECKSUM_CHECK_MD5 MD5_CTX context; GenerateMD5Hash((BYTE*)(*data), index->data_size, context); if (memcmp(index->MD5Digest, context.digest, 16) != 0) { return false; } #else #ifdef ENABLE_CRC32_CHECK DWORD dwCrc32 = GetCRC32((const char*)(*data), index->data_size); if (index->data_crc != dwCrc32) { return false; } #endif #endif } if (COMPRESSED_TYPE_COMPRESS == index->compressed_type) { CLZObject * zObj = new CLZObject; if (!CLZO::Instance().Decompress(*zObj, static_cast<const BYTE *>(*data), 0)) { TraceError("Failed to decompress : %s", filename); delete zObj; return false; } out_file.BindLZObject(zObj); *data = zObj->GetBuffer(); } else if (COMPRESSED_TYPE_SECURITY == index->compressed_type) { CLZObject * zObj = new CLZObject; if (!CLZO::Instance().Decompress(*zObj, static_cast<const BYTE *>(*data), 2, s_adwEterPackSecurityKey)) { TraceError("Failed to encrypt : %s", filename); delete zObj; return false; } out_file.BindLZObject(zObj); *data = zObj->GetBuffer(); } else if (COMPRESSED_TYPE_PANAMA == index->compressed_type) { CLZObject * zObj = new CLZObject; __Decrypt_Panama(filename, static_cast<const BYTE*>(*data), index->data_size, *zObj); out_file.BindLZObjectWithBufferedSize(zObj); *data = zObj->GetBuffer(); } else if (COMPRESSED_TYPE_HYBRIDCRYPT == index->compressed_type || COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type) { #ifdef __THEMIDA__ VM_START #endif CLZObject * zObj = new CLZObject; if (!m_pCSHybridCryptPolicy->DecryptMemory(string(filename), static_cast<const BYTE*>(*data), index->data_size, *zObj)) { return false; } out_file.BindLZObjectWithBufferedSize(zObj); if (COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type) { BYTE* pSDBData; int iSDBSize; if (!m_pCSHybridCryptPolicy->GetSupplementaryDataBlock(string(filename), pSDBData, iSDBSize)) { return false; } *data = out_file.AppendDataBlock(pSDBData, iSDBSize); } else { *data = zObj->GetBuffer(); } #ifdef __THEMIDA__ VM_END #endif } return true; } bool CEterPack::Get2(CMappedFile& out_file, const char * filename, TEterPackIndex * index, LPCVOID * data) { if (!index) { return false; } //UpdateLastAccessTime(); //if (!m_bIsDataLoaded) //{ // if (!m_file.Create(m_stDataFileName.c_str(), (const void**)&m_file_data, 0, 0)) // return false; // // m_bIsDataLoaded = true; //} out_file.Create(m_stDataFileName.c_str(), data, index->data_position + m_dataOff, index->data_size); bool bIsSecurityCheckRequired = (index->compressed_type == COMPRESSED_TYPE_SECURITY || index->compressed_type == COMPRESSED_TYPE_PANAMA); if (bIsSecurityCheckRequired) { #ifdef CHECKSUM_CHECK_MD5 MD5_CTX context; GenerateMD5Hash((BYTE*)(*data), index->data_size, context); if (memcmp(index->MD5Digest, context.digest, 16) != 0) { return false; } #else DWORD dwCrc32 = GetCRC32((const char*)(*data), index->data_size); if (index->data_crc != dwCrc32) { return false; } #endif } if (COMPRESSED_TYPE_COMPRESS == index->compressed_type) { CLZObject * zObj = new CLZObject; if (!CLZO::Instance().Decompress(*zObj, static_cast<const BYTE *>(*data), 0)) { TraceError("Failed to decompress : %s", filename); delete zObj; return false; } out_file.BindLZObject(zObj); *data = zObj->GetBuffer(); } else if (COMPRESSED_TYPE_SECURITY == index->compressed_type) { CLZObject * zObj = new CLZObject; if (!CLZO::Instance().Decompress(*zObj, static_cast<const BYTE *>(*data), 2, s_adwEterPackSecurityKey)) { TraceError("Failed to encrypt : %s", filename); delete zObj; return false; } out_file.BindLZObject(zObj); *data = zObj->GetBuffer(); } else if (COMPRESSED_TYPE_PANAMA == index->compressed_type) { CLZObject * zObj = new CLZObject; __Decrypt_Panama(filename, static_cast<const BYTE*>(*data), index->data_size, *zObj); out_file.BindLZObjectWithBufferedSize(zObj); *data = zObj->GetBuffer(); } else if (COMPRESSED_TYPE_HYBRIDCRYPT == index->compressed_type || COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type) { #ifdef __THEMIDA__ VM_START #endif CLZObject * zObj = new CLZObject; if (!m_pCSHybridCryptPolicy->DecryptMemory(string(filename), static_cast<const BYTE*>(*data), index->data_size, *zObj)) { return false; } out_file.BindLZObjectWithBufferedSize(zObj); if (COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type) { BYTE* pSDBData; int iSDBSize; if (!m_pCSHybridCryptPolicy->GetSupplementaryDataBlock(string(filename), pSDBData, iSDBSize)) { return false; } *data = out_file.AppendDataBlock(pSDBData, iSDBSize); } else { *data = zObj->GetBuffer(); } #ifdef __THEMIDA__ VM_END #endif } return true; } bool CEterPack::Delete(TEterPackIndex * pIndex) { CFileBase fileIndex; if (!fileIndex.Create(m_indexFileName, CFileBase::FILEMODE_WRITE)) return false; PushFreeIndex(pIndex); WriteIndex(fileIndex, pIndex); return true; } bool CEterPack::Delete(const char * filename) { TEterPackIndex * pIndex = FindIndex(filename); if (!pIndex) return false; return Delete(pIndex); } bool CEterPack::Extract() { CMappedFile dataMapFile; LPCVOID data; if (!dataMapFile.Create(m_stDataFileName.c_str(), &data, 0, 0)) return false; CLZObject zObj; for (TDataPositionMap::iterator i = m_DataPositionMap.begin(); i != m_DataPositionMap.end(); ++i) { TEterPackIndex* index = i->second; CFileBase writeFile; inlinePathCreate(index->filename); printf("%s\n", index->filename); writeFile.Create(index->filename, CFileBase::FILEMODE_WRITE); if (COMPRESSED_TYPE_COMPRESS == index->compressed_type) { if (!CLZO::Instance().Decompress(zObj, (const BYTE *)data + index->data_position, 0)) { printf("cannot decompress"); return false; } writeFile.Write(zObj.GetBuffer(), zObj.GetSize()); zObj.Clear(); } else if (COMPRESSED_TYPE_SECURITY == index->compressed_type) { if (!CLZO::Instance().Decompress(zObj, (const BYTE *)data + index->data_position, 2, s_adwEterPackSecurityKey)) { printf("cannot decompress"); return false; } writeFile.Write(zObj.GetBuffer(), zObj.GetSize()); zObj.Clear(); } else if (COMPRESSED_TYPE_PANAMA == index->compressed_type) { __Decrypt_Panama(index->filename, (const BYTE *)data + index->data_position, index->data_size, zObj); writeFile.Write(zObj.GetBuffer(), zObj.GetBufferSize()); zObj.Clear(); } else if (COMPRESSED_TYPE_HYBRIDCRYPT == index->compressed_type || COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type) { #ifdef __THEMIDA__ VM_START #endif if (!m_pCSHybridCryptPolicy->DecryptMemory(string(index->filename), (const BYTE *)data + index->data_position, index->data_size, zObj)) return false; if (COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB == index->compressed_type) { dataMapFile.BindLZObjectWithBufferedSize(&zObj); BYTE* pSDBData; int iSDBSize; if (!m_pCSHybridCryptPolicy->GetSupplementaryDataBlock(string(index->filename), pSDBData, iSDBSize)) return false; dataMapFile.AppendDataBlock(pSDBData, iSDBSize); writeFile.Write(dataMapFile.AppendDataBlock(pSDBData, iSDBSize), dataMapFile.Size()); } else { writeFile.Write(zObj.GetBuffer(), zObj.GetBufferSize()); } zObj.Clear(); #ifdef __THEMIDA__ VM_END #endif } else if (COMPRESSED_TYPE_NONE == index->compressed_type) writeFile.Write((const char *)data + index->data_position, index->data_size); writeFile.Destroy(); } return true; } bool CEterPack::GetNames(std::vector<std::string>* retNames) { CMappedFile dataMapFile; LPCVOID data; if (!dataMapFile.Create(m_stDataFileName.c_str(), &data, 0, 0)) return false; CLZObject zObj; for (TDataPositionMap::iterator i = m_DataPositionMap.begin(); i != m_DataPositionMap.end(); ++i) { TEterPackIndex* index = i->second; inlinePathCreate(index->filename); retNames->push_back(index->filename); } return true; } bool CEterPack::Put(const char * filename, const char * sourceFilename, BYTE packType, const std::string& strRelateMapName) { CMappedFile mapFile; LPCVOID data; if (sourceFilename) { if (!mapFile.Create(sourceFilename, &data, 0, 0)) { return false; } } else if (!mapFile.Create(filename, &data, 0, 0)) { return false; } BYTE* pMappedData = (BYTE*)data; int iMappedDataSize = mapFile.Size(); if (packType == COMPRESSED_TYPE_HYBRIDCRYPT || packType == COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB) { #ifdef __THEMIDA__ VM_START #endif m_pCSHybridCryptPolicy->GenerateCryptKey(string(filename)); if (packType == COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB) { if (!m_pCSHybridCryptPolicy->GenerateSupplementaryDataBlock(string(filename), strRelateMapName, (const BYTE*)data, mapFile.Size(), pMappedData, iMappedDataSize)) { return false; } } #ifdef __THEMIDA__ VM_END #endif } return Put(filename, pMappedData, iMappedDataSize, packType); } #ifdef CHECKSUM_CHECK_MD5 void CEterPack::GenerateMD5Hash(BYTE* pData, int nLength, IN OUT MD5_CTX& mdContext) { MD5Init(&mdContext); const int nBlockSize = 1024; int nLoopCnt = nLength / nBlockSize; int nRemainder = nLength % nBlockSize; int i; for (i = 0; i < nLoopCnt; ++i) { MD5Update(&mdContext, reinterpret_cast<BYTE*>(pData + i*nBlockSize), nBlockSize); } if (nRemainder > 0) MD5Update(&mdContext, reinterpret_cast<BYTE*>(pData + i*nBlockSize), nRemainder); MD5Final(&mdContext); } #endif bool CEterPack::Put(const char * filename, LPCVOID data, long len, BYTE packType) { if (m_bEncrypted) { TraceError("EterPack::Put : Cannot put to encrypted pack (filename: %s, DB: %s)", filename, m_dbName); return false; } CFileBase fileIndex; if (!fileIndex.Create(m_indexFileName, CFileBase::FILEMODE_WRITE)) { return false; } CFileBase fileData; if (!fileData.Create(m_stDataFileName.c_str(), CFileBase::FILEMODE_WRITE)) { return false; } TEterPackIndex * pIndex; pIndex = FindIndex(filename); CLZObject zObj; std::string encryptStr; if (packType == COMPRESSED_TYPE_SECURITY || packType == COMPRESSED_TYPE_COMPRESS) { if (packType == COMPRESSED_TYPE_SECURITY) { if (!CLZO::Instance().CompressEncryptedMemory(zObj, data, len, 2, s_adwEterPackSecurityKey)) { return false; } } else { if (!CLZO::Instance().CompressMemory(zObj, data, len)) { return false; } } data = zObj.GetBuffer(); len = zObj.GetSize(); } else if (packType == COMPRESSED_TYPE_PANAMA) { if (!__Encrypt_Panama(filename, (const BYTE *)data, len, zObj)) { return false; } data = zObj.GetBuffer(); len = zObj.GetBufferSize(); } else if (packType == COMPRESSED_TYPE_HYBRIDCRYPT || packType == COMPRESSED_TYPE_HYBRIDCRYPT_WITHSDB) { #ifdef __THEMIDA__ VM_START #endif if (!m_pCSHybridCryptPolicy->EncryptMemory(string(filename), (const BYTE *)data, len, zObj)) { return false; } data = zObj.GetBuffer(); len = zObj.GetBufferSize(); #ifdef __THEMIDA__ VM_END #endif } #ifdef CHECKSUM_CHECK_MD5 MD5_CTX context; GenerateMD5Hash((BYTE*)(data), len, context); #else DWORD data_crc; data_crc = GetCRC32((const char *)data, len); #endif // ±âÁ¸ µ¥ÀÌÅÍ°¡ ÀÖÀ¸¸é.. if (pIndex) { // ±âÁ¸ data Å©±â°¡ ³ÖÀ» µ¥ÀÌÅÍ Å©±â¸¦ ¼ö¿ëÇÒ ¼ö ÀÖ´Ù¸é if (pIndex->real_data_size >= len) { ++m_map_indexRefCount[pIndex->id]; // ±æÀÌ°¡ Ʋ¸®°Å³ª, checksumÀÌ Æ²¸± ¶§¸¸ ÀúÀå ÇÑ´Ù. if ((pIndex->data_size != len) || #ifdef CHECKSUM_CHECK_MD5 (memcmp(pIndex->MD5Digest, context.digest, 16) != 0)) #else (pIndex->data_crc != data_crc) ) #endif { #ifdef __MAKE_PACK__ if (ms_PackLogFile) fprintf(ms_PackLogFile, "Overwrite[%d/%d] %s\n", bCompress, bSecurity, pIndex->filename); printf("Overwrite[%d/%d] %s\n", bCompress, bSecurity, pIndex->filename); #endif pIndex->data_size = len; #ifdef CHECKSUM_CHECK_MD5 memcpy(pIndex->MD5Digest, context.digest, 16); #else pIndex->data_crc = data_crc; #endif pIndex->compressed_type = packType; CMakePackLog::GetSingleton().Writef("Overwrite[type:%u] %s\n", pIndex->compressed_type, pIndex->filename); WriteIndex(fileIndex, pIndex); WriteData(fileData, pIndex, data); } return true; } // ±âÁ¸ µ¥ÀÌÅÍ Å©±â°¡ »õ·Î µé¾î°¥ °Í º¸´Ù Àû´Ù¸é, »õ·Î À妽º¸¦ ÇÒ´çÇØ // ³Ö¾î¾ß ÇÑ´Ù. ¿ø·¡ ÀÖ´ø À妽º´Â ºñ¿ö µÐ´Ù. PushFreeIndex(pIndex); WriteIndex(fileIndex, pIndex); } // »õ µ¥ÀÌÅÍ pIndex = NewIndex(fileIndex, filename, len); pIndex->data_size = len; #ifdef CHECKSUM_CHECK_MD5 memcpy(pIndex->MD5Digest, context.digest, 16); #else pIndex->data_crc = data_crc; #endif pIndex->data_position = GetNewDataPosition(fileData); pIndex->compressed_type = packType; WriteIndex(fileIndex, pIndex); WriteNewData(fileData, pIndex, data); ++m_map_indexRefCount[pIndex->id]; #ifdef __MAKE_PACK__ if (ms_PackLogFile) fprintf(ms_PackLogFile, "Write[%d/%d] %s\n", bCompress, bSecurity, pIndex->filename); printf("Write[%d/%d] %s, position %ld realsize %ld size %ld\n", bCompress, bSecurity, pIndex->filename, pIndex->data_position, pIndex->real_data_size, pIndex->data_size); #endif CMakePackLog::GetSingleton().Writef("Write[type:%u] %s\n", pIndex->compressed_type, pIndex->filename); return true; } long CEterPack::GetFragmentSize() { return m_FragmentSize; } // Private methods bool CEterPack::CreateIndexFile() { FILE * fp; if (NULL != (fp = fopen(m_indexFileName, "rb"))) { fclose(fp); return true; } else if (m_bReadOnly) return false; // // ÆÄÀÏÀÌ ¾øÀ¸¹Ç·Î »õ·Î ¸¸µç´Ù. // fp = fopen(m_indexFileName, "wb"); if (!fp) return false; fwrite(&eterpack::c_IndexCC, sizeof(DWORD), 1, fp); fwrite(&eterpack::c_Version, sizeof(DWORD), 1, fp); fwrite(&m_indexCount, sizeof(long), 1, fp); fclose(fp); return true; } void CEterPack::WriteIndex(CFileBase & file, TEterPackIndex * index) { file.Seek(sizeof(DWORD)+sizeof(DWORD)); file.Write(&m_indexCount, sizeof(long)); file.Seek(eterpack::c_HeaderSize + (index->id * sizeof(TEterPackIndex))); if (!file.Write(index, sizeof(TEterPackIndex))) { assert(!"WriteIndex: fwrite failed"); return; } } /* * Free Block À̶õ µ¥ÀÌÅÍ¿¡¼ Áö¿öÁø ºÎºÐÀ» ¸»ÇÑ´Ù. * Free Block µéÀº °¢°¢ FREE_INDEX_BLOCK_SIZE (32768) ´ÜÀ§·Î ³ª´©¾îÁ® * ¸®½ºÆ®·Î °ü¸®µÈ´Ù. * * ¿¹¸¦ µé¾î 128k ÀÇ µ¥ÀÌÅÍ´Â * 128 * 1024 / FREE_INDEX_BLOCK_SIZE = 4 À̹ǷΠ* ÃÖÁ¾ ÀûÀ¸·Î´Â m_FreeIndexList[4] ¿¡ µé¾î°£´Ù. * * FREE_INDEX_BLOCK_SIZE ÀÇ ÃÖ´ë °ªÀº FREE_INDEX_MAX_SIZE(512) ÀÌ´Ù. * µû¶ó¼ 16MB ÀÌ»óÀÇ µ¥ÀÌÅÍ´Â ¹«Á¶°Ç ¹è¿ÀÇ 512 À§Ä¡¿¡ µé¾î°£´Ù. */ int CEterPack::GetFreeBlockIndex(long size) { return min(FREE_INDEX_MAX_SIZE, size / FREE_INDEX_BLOCK_SIZE); } void CEterPack::PushFreeIndex(TEterPackIndex* index) { if (index->filename_crc != 0) { TDataPositionMap::iterator i = m_DataPositionMap.find(index->filename_crc); if (i != m_DataPositionMap.end()) m_DataPositionMap.erase(i); index->filename_crc = 0; memset(index->filename, 0, sizeof(index->filename)); } int blockidx = GetFreeBlockIndex(index->real_data_size); m_FreeIndexList[blockidx].push_back(index); m_FragmentSize += index->real_data_size; //printf("FreeIndex: size %d: blockidx: %d\n", index->real_data_size, blockidx); } long CEterPack::GetNewIndexPosition(CFileBase & file) { long pos = (file.Size() - eterpack::c_HeaderSize) / sizeof(TEterPackIndex); ++m_indexCount; return (pos); } TEterPackIndex* CEterPack::NewIndex(CFileBase& file, const char* filename, long size) { TEterPackIndex* index = NULL; int block_size = size + (DATA_BLOCK_SIZE - (size % DATA_BLOCK_SIZE)); // if ((index = FindIndex(filename))) // ÀÌ¹Ì À妽º°¡ Á¸ÀçÇÏ´ÂÁö È®ÀÎ // return index; int blockidx = GetFreeBlockIndex(block_size); for (TFreeIndexList::iterator i = m_FreeIndexList[blockidx].begin(); i != m_FreeIndexList[blockidx].end(); ++i) { if ((*i)->real_data_size >= size) { index = *i; m_FreeIndexList[blockidx].erase(i); assert(index->filename_crc == 0); break; } } if (!index) { index = new TEterPackIndex; index->real_data_size = block_size; index->id = GetNewIndexPosition(file); } strncpy(index->filename, filename, FILENAME_MAX_LEN); index->filename[FILENAME_MAX_LEN] = '\0'; inlineConvertPackFilename(index->filename); index->filename_crc = GetCRC32(index->filename, strlen(index->filename)); m_DataPositionMap.insert(TDataPositionMap::value_type(index->filename_crc, index)); return index; } TEterPackIndex* CEterPack::FindIndex(const char * filename) { static char tmpFilename[MAX_PATH + 1]; strncpy(tmpFilename, filename, MAX_PATH); inlineConvertPackFilename(tmpFilename); DWORD filename_crc = GetCRC32(tmpFilename, strlen(tmpFilename)); TDataPositionMap::iterator i = m_DataPositionMap.find(filename_crc); if (i == m_DataPositionMap.end()) return NULL; return (i->second); } bool CEterPack::IsExist(const char * filename) { return FindIndex(filename) ? true : false; } bool CEterPack::CreateDataFile() { FILE * fp; if (NULL != (fp = fopen(m_stDataFileName.c_str(), "rb"))) { fclose(fp); return true; } else if (m_bReadOnly) return false; fp = fopen(m_stDataFileName.c_str(), "wb"); if (!fp) return false; fclose(fp); return true; } long CEterPack::GetNewDataPosition(CFileBase& file) { return file.Size(); } bool CEterPack::ReadData(CFileBase & file, TEterPackIndex* index, LPVOID data, long maxsize) { if (index->data_size > maxsize) return false; file.Seek(index->data_position); file.Read(data, index->data_size); return true; } bool CEterPack::WriteData(CFileBase & file, TEterPackIndex* index, LPCVOID data) { file.Seek(index->data_position); if (!file.Write(data, index->data_size)) { assert(!"WriteData: fwrite data failed"); return false; } return true; } bool CEterPack::WriteNewData(CFileBase& file, TEterPackIndex* index, LPCVOID data) { file.Seek(index->data_position); if (!file.Write(data, index->data_size)) { assert(!"WriteData: fwrite data failed"); return false; } int empty_size = index->real_data_size - index->data_size; if (empty_size < 0) { printf("SYSERR: WriteNewData(): CRITICAL ERROR: empty_size lower than 0!\n"); exit(1); } if (empty_size == 0) return true; char * empty_buf = (char *)calloc(empty_size, sizeof(char)); if (!file.Write(empty_buf, empty_size)) { assert(!"WriteData: fwrite empty data failed"); return false; } free(empty_buf); return true; } TDataPositionMap & CEterPack::GetIndexMap() { return m_DataPositionMap; } DWORD CEterPack::DeleteUnreferencedData() { TDataPositionMap::iterator i = m_DataPositionMap.begin(); DWORD dwCount = 0; while (i != m_DataPositionMap.end()) { TEterPackIndex * pIndex = (i++)->second; if (0 == m_map_indexRefCount[pIndex->id]) { printf("Unref File %s\n", pIndex->filename); Delete(pIndex); ++dwCount; } } return dwCount; } const char * CEterPack::GetDBName() { return m_dbName; } void CEterPack::__CreateFileNameKey_Panama(const char * filename, BYTE * key, unsigned int keySize) { // Å° ¾ÏÈ£È if (keySize != 32) return; std::string SrcStringForKey(filename); unsigned int idx = GetCRC32(SrcStringForKey.c_str(), SrcStringForKey.length()) & 3; CryptoPP::HashTransformation* hm1 = NULL; CryptoPP::HashTransformation* hm2 = NULL; static CryptoPP::Tiger tiger; static CryptoPP::SHA1 sha1; static CryptoPP::RIPEMD128 ripemd128; static CryptoPP::Whirlpool whirlpool; switch (idx & 3) { case 0: hm1 = &whirlpool; break; case 1: hm1 = &tiger; break; case 2: hm1 = &sha1; break; case 3: hm1 = &ripemd128; break; } CryptoPP::StringSource(SrcStringForKey, true, new CryptoPP::HashFilter(*hm1, //new CryptoPP::HexEncoder( new CryptoPP::ArraySink(key, 16) //) // HexEncoder ) // HashFilter ); // StringSource // ¸¸µé¾îÁø Å°ÀÇ Ã¹¹ø° 4¹ÙÀÌÆ®·Î ´ÙÀ½ 16¹ÙÀÌÆ® Å° »ý¼º ¾Ë°í¸®Áò ¼±Åà unsigned int idx2 = *(unsigned int*)key; switch (idx2 & 3) { case 0: hm2 = &sha1; break; case 1: hm2 = &ripemd128; break; case 2: hm2 = &whirlpool; break; case 3: hm2 = &tiger; break; } CryptoPP::StringSource(SrcStringForKey, true, new CryptoPP::HashFilter(*hm2, //new CryptoPP::HexEncoder( new CryptoPP::ArraySink(key + 16, 16) //) // HexEncoder ) // HashFilter ); // StringSource // Å° »ý¼º ¿Ï·á } bool CEterPack::__Encrypt_Panama(const char* filename, const BYTE* data, SIZE_T dataSize, CLZObject& zObj) { if (32 != m_stIV_Panama.length()) { // ÇØÄ¿°¡ ÀÌ ¸Þ¼¼Áö¸¦ º¸¸é ÈùÆ®¸¦ ¾òÀ»±îºÁ µð¹ö±×¿¡¼¸¸ Ãâ·Â #ifdef _DEBUG TraceError("IV not set (filename: %s)", filename); #endif return false; } CryptoPP::PanamaCipher<CryptoPP::LittleEndian>::Encryption Encryptor; if (dataSize < Encryptor.MandatoryBlockSize()) { #ifdef _DEBUG TraceError("Type 3 pack file must be bigger than %u bytes (filename: %s)", Encryptor.MandatoryBlockSize(), filename); #endif return false; } BYTE key[32]; __CreateFileNameKey_Panama(filename, key, sizeof(key)); Encryptor.SetKeyWithIV(key, sizeof(key), (const BYTE*)m_stIV_Panama.c_str(), 32); // MandatoryBlockSize¿¡ ³ª´©¾î ¶³¾îÁö°Ô ¸¸µé°í ÃÖ´ë 2048 ¹ÙÀÌÆ®¸¸ DWORD cryptSize = dataSize - (dataSize % Encryptor.MandatoryBlockSize()); cryptSize = cryptSize > 2048 ? 2048 : cryptSize; std::string tmp; tmp.reserve(cryptSize); CryptoPP::ArraySource(data, cryptSize, true, new CryptoPP::StreamTransformationFilter(Encryptor, new CryptoPP::StringSink(tmp) ) ); if (tmp.length() != cryptSize) { #ifdef _DEBUG TraceError("Type 3 pack crypt buffer size error (out %u should be %u)", tmp.length(), cryptSize); #endif return false; } zObj.AllocBuffer(dataSize); memcpy(zObj.GetBuffer(), tmp.c_str(), cryptSize); if (dataSize - cryptSize > 0) memcpy(zObj.GetBuffer() + cryptSize, data + cryptSize, dataSize - cryptSize); return true; } bool CEterPack::__Decrypt_Panama(const char* filename, const BYTE* data, SIZE_T dataSize, CLZObject& zObj) { if (32 != m_stIV_Panama.length()) { // ÇØÄ¿°¡ ÀÌ ¸Þ¼¼Áö¸¦ º¸¸é ÈùÆ®¸¦ ¾òÀ»±îºÁ µð¹ö±×¿¡¼¸¸ Ãâ·Â #ifdef _DEBUG TraceError("IV not set (filename: %s)", filename); #endif return false; } CryptoPP::PanamaCipher<CryptoPP::LittleEndian>::Decryption Decryptor; BYTE key[32]; __CreateFileNameKey_Panama(filename, key, sizeof(key)); Decryptor.SetKeyWithIV(key, sizeof(key), (const BYTE*)m_stIV_Panama.c_str(), 32); // MandatoryBlockSize¿¡ ³ª´©¾î ¶³¾îÁö°Ô ¸¸µé°í ÃÖ´ë 2048 ¹ÙÀÌÆ®¸¸ DWORD cryptSize = dataSize - (dataSize % Decryptor.MandatoryBlockSize()); cryptSize = cryptSize > 2048 ? 2048 : cryptSize; std::string tmp; tmp.reserve(cryptSize); CryptoPP::ArraySource(data, cryptSize, true, new CryptoPP::StreamTransformationFilter(Decryptor, new CryptoPP::StringSink(tmp) ) ); if (tmp.length() != cryptSize) { #ifdef _DEBUG TraceError("Type 3 pack crypt buffer size error (out %u should be %u)", tmp.length(), cryptSize); #endif return false; } zObj.AllocBuffer(dataSize); memcpy(zObj.GetBuffer(), tmp.c_str(), cryptSize); if (dataSize - cryptSize > 0) memcpy(zObj.GetBuffer() + cryptSize, data + cryptSize, dataSize - cryptSize); return true; } EterPackPolicy_CSHybridCrypt* CEterPack::GetPackPolicy_HybridCrypt() const { return m_pCSHybridCryptPolicy; } ///////////////////////// void CEterFileDict::InsertItem(CEterPack* pkPack, TEterPackIndex* pkInfo) { Item item; item.pkPack = pkPack; item.pkInfo = pkInfo; m_dict.insert(TDict::value_type(pkInfo->filename_crc, item)); } void CEterFileDict::UpdateItem(CEterPack* pkPack, TEterPackIndex* pkInfo) { Item item; item.pkPack = pkPack; item.pkInfo = pkInfo; TDict::iterator f = m_dict.find(pkInfo->filename_crc); if (f == m_dict.end()) m_dict.insert(TDict::value_type(pkInfo->filename_crc, item)); else { if (strcmp(f->second.pkInfo->filename, item.pkInfo->filename) == 0) { f->second = item; } else { TraceError("NAME_COLLISION: OLD: %s NEW: %s", f->second.pkInfo->filename, item.pkInfo->filename); } } } CEterFileDict::Item* CEterFileDict::GetItem(DWORD dwFileNameHash, const char * c_pszFileName) { std::pair<TDict::iterator, TDict::iterator> iter_pair = m_dict.equal_range(dwFileNameHash); TDict::iterator iter = iter_pair.first; while (iter != iter_pair.second) { Item& item = iter->second; if (0 == strcmp(c_pszFileName, item.pkInfo->filename)) return &item; ++iter; } return NULL; } Link to comment Share on other sites More sharing options...
Honorable Member martysama0134 7178 Posted January 8, 2023 Honorable Member Share Posted January 8, 2023 (edited) Someone asked about this function, and I recreated it, but I noticed there was one already public. I made some tests, and this is the result: https://godbolt.org/z/hd6oW4j7P Bench name: BoostTest, Elapsed time: 96ms Bench name: RegexTest, Elapsed time: 1009ms @ VegaS™ Bench name: mslTest, Elapsed time: 29ms from This is the hidden content, please Sign In or Sign Up Bench name: ymirTest, Elapsed time: 56ms (created right now) Bench name: ymir2Test, Elapsed time: 69ms (created right now for old compilers) This public function doesn't support commands like /m "Wild Dog", while the classic ymir does. In the godbolt link you find the whole test code. If you want to support the " tags, you'll need something like this: void split_argument(std::string_view stArg, std::vector<std::string> & vecArgs) // backward function for lazy people { vecArgs = split_arguments(stArg); } std::vector<std::string> split_arguments(std::string_view stArg) { std::vector<std::string> vecArgs; std::string_view argument = stArg; while (true) { char first_arg[256]{}; argument = one_argument(argument.data(), first_arg, sizeof(first_arg)); vecArgs.emplace_back(first_arg); if (argument.empty() || argument[0] == '\0') break; } return vecArgs; } meanwhile for old compilers: void split_argument(const std::string & stArg, std::vector<std::string> &vecArgs) { const char * argument = stArg.data(); while (true) { char first_arg[256]{}; argument = one_argument(argument, first_arg, sizeof(first_arg)); vecArgs.push_back(first_arg); if (!argument || argument[0] == '\0') break; } } ------------------------ Dynamic arg buffer: https://godbolt.org/z/5cWdoxbee std::vector<std::string> split_argument4(std::string_view stArg) { std::vector<std::string> vecArgs; std::string_view argument = stArg; std::string first_arg; first_arg.resize(stArg.size()+1); //+1 cuz one_argument assigns to first_arg[0] \0 if argument is empty while (true) { argument = one_argument(argument.data(), first_arg.data(), first_arg.size()); vecArgs.emplace_back(first_arg); if (argument.empty() || argument[0] == '\0') break; } return vecArgs; } Edited January 8, 2023 by martysama0134 Dynamic arg buffer 38 1 6 1 10 Check out my GitHub Link to comment Share on other sites More sharing options...
Recommended Posts