Skip to content

Instantly share code, notes, and snippets.

@shirosaki
Created February 4, 2012 03:11
Show Gist options
  • Select an option

  • Save shirosaki/1734867 to your computer and use it in GitHub Desktop.

Select an option

Save shirosaki/1734867 to your computer and use it in GitHub Desktop.
Long name conversion benchmark
Long name conversion of the following path.
V:\LONG_P~1\build\samples\LONG_N~1.EXE
GetLongFileName is a GetLongPathName implementation using FindFirstFile.
File exist:
GetLongPathName() time: 177.076
FindFirstFile() time: 44.9106
GetLongFileName() time: 198.462
SHGetFileInfo() time: 13801.7
GetFileAttributes() time: 28.2295
File not exist:
GetLongPathName() time: 17.1088
FindFirstFile() time: 50.0432
GetLongFileName() time: 37.6394
SHGetFileInfo() time: 605.224
GetFileAttributes() time: 16.6811
diff --git a/samples/long_name.cpp b/samples/long_name.cpp
new file mode 100644
index 0000000..9e24bdc
--- /dev/null
+++ b/samples/long_name.cpp
@@ -0,0 +1,187 @@
+#include <ios>
+#include <iostream>
+#include <ostream>
+#include <iomanip>
+#include <stdexcept>
+
+#define BUFSIZE MAX_PATH
+#if defined (_WIN32)
+// define _WIN32_WINNT to use GetLongPathName()
+# undef _WIN32_WINNT
+# define _WIN32_WINNT 0x0500
+# include <windows.h>
+# include <io.h>
+# include <fcntl.h>
+# define shortname "LONG_N~1.EXE"
+# include <sys/stat.h>
+#endif
+
+#include "hrtimer.h"
+
+LPSTR StrRChrDBCS(LPSTR pSrc,char ch)
+{
+ LPSTR pHit = NULL; // Set search error
+
+ for ( ; *pSrc; pSrc++) {
+ if (IsDBCSLeadByte(*pSrc)) {
+ pSrc++;
+ continue;
+ }
+ if (*pSrc == ch) {
+ pHit = pSrc;
+ }
+ }
+ return pHit;
+}
+
+BOOL GetLongFileName(LPCTSTR lpszShortFileName, LPTSTR lpszBuffer, DWORD dwBufferSize)
+{
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind;
+ char szTmpShortFile[MAX_PATH];
+ char szLongFile[MAX_PATH];
+ char szTmp[MAX_PATH];
+ LPTSTR lpSeparator;
+ int nPos;
+
+ szLongFile[0] = '\0';
+ lstrcpy(szTmpShortFile, lpszShortFileName);
+
+ hFind = FindFirstFile(szTmpShortFile, &wfd);
+ if (hFind == INVALID_HANDLE_VALUE) {
+ return FALSE;
+ }
+ FindClose(hFind);
+
+ do {
+ lpSeparator = StrRChrDBCS(szTmpShortFile, '\\');
+ if(lpSeparator != NULL) {
+ nPos = lpSeparator - szTmpShortFile;
+ if(lstrlen(szLongFile) == 0) {
+ lstrcpy(szLongFile, wfd.cFileName);
+ } else {
+ wsprintf(szTmp, "%s\\%s", wfd.cFileName, szLongFile);
+ lstrcpy(szLongFile, szTmp);
+ }
+ szTmpShortFile[nPos] = '\0';
+ hFind = FindFirstFile(szTmpShortFile ,&wfd);
+ if (hFind == INVALID_HANDLE_VALUE) {
+ wsprintf(szTmp, "%s\\%s", szTmpShortFile, szLongFile);
+ lstrcpy(szLongFile, szTmp);
+ break;
+ }
+ FindClose(hFind);
+ } else {
+ wsprintf(szTmp, "%s\\%s", szTmpShortFile, szLongFile);
+ lstrcpy(szLongFile, szTmp);
+ }
+ } while(lpSeparator != NULL);
+
+ if ((DWORD)lstrlen(szLongFile) >= dwBufferSize)
+ return FALSE;
+
+ lstrcpy(lpszBuffer, szLongFile);
+ return TRUE;
+}
+
+
+int main(int argc, char* argv[])
+{
+ using namespace std;
+
+ double rv = 0.0;
+
+ // hires timer returning usecond times
+ HiRes::Timer<HiRes::us> t_us;
+
+ string headers[] = {"File exist:", "File not exist:"};
+ string file_path[] = {shortname, "dummy"};
+ for (int i = 0; i < 2; i++) {
+ const char *file = file_path[i].c_str();
+ char fullpath[BUFSIZE];
+#if defined(_WIN32)
+ GetFullPathName(file, BUFSIZE, fullpath, NULL);
+ GetShortPathName(fullpath, fullpath, BUFSIZE);
+ cout << endl << fullpath << endl;
+ cout << endl << headers[i] << endl;
+
+ char buffer[BUFSIZE];
+
+ t_us.start();
+ DWORD retval = GetLongPathName(fullpath,
+ buffer,
+ BUFSIZE);
+ rv = t_us.stop();
+ cout << left
+ << setw(30)
+ << "GetLongPathName() time: "
+ << rv << endl;
+
+ if (retval != 0) {
+ cout << buffer << endl;
+ }
+
+ WIN32_FIND_DATA FindFileData;
+ HANDLE hFind;
+
+ t_us.start();
+ hFind = FindFirstFile(fullpath, &FindFileData);
+ if (hFind != INVALID_HANDLE_VALUE)
+ FindClose(hFind);
+ rv = t_us.stop();
+ cout << left
+ << setw(30)
+ << "FindFirstFile() time: "
+ << rv << endl;
+
+ if (hFind != INVALID_HANDLE_VALUE) {
+ cout << FindFileData.cFileName << endl;
+ }
+
+
+ t_us.start();
+ BOOL ret = GetLongFileName(fullpath,
+ buffer,
+ BUFSIZE);
+ rv = t_us.stop();
+ cout << left
+ << setw(30)
+ << "GetLongFileName() time: "
+ << rv << endl;
+
+ if (ret) {
+ cout << buffer << endl;
+ }
+
+
+ SHFILEINFO sfi = {0};
+
+ t_us.start();
+ DWORD_PTR hr = SHGetFileInfo(fullpath,
+ 0,
+ &sfi,
+ sizeof(sfi),
+ SHGFI_DISPLAYNAME);
+ rv = t_us.stop();
+ cout << left
+ << setw(30)
+ << "SHGetFileInfo() time: "
+ << rv << endl;
+
+ if (SUCCEEDED(hr)) {
+ // The display name is now held in sfi.szDisplayName.
+ cout << sfi.szDisplayName << endl;
+ }
+
+ t_us.start();
+ GetFileAttributes(fullpath);
+ rv = t_us.stop();
+ cout << left
+ << setw(30)
+ << "GetFileAttributes() time: "
+ << rv << endl;
+ #endif
+ }
+
+ return 0;
+}
diff --git a/samples/wscript b/samples/wscript
index ee626ef..71daa42 100644
--- a/samples/wscript
+++ b/samples/wscript
@@ -54,4 +54,13 @@ def build(bld):
linkflags = my_linkflags,
)
+ bld.program(
+ source = [ 'long_name.cpp' ],
+ includes = [ '../include' ],
+ target = 'long_name',
+ cxxflags = my_cxxflags,
+ linkflags = my_linkflags,
+ )
+
+
# vim: ft=python ai ts=4 sw=4 sts=4 et
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment