https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9bdeaca56e8e01473d9858a1b7ea4bbdbbc836cf

commit 9bdeaca56e8e01473d9858a1b7ea4bbdbbc836cf
Author:     Mark Jansen <[email protected]>
AuthorDate: Thu Sep 30 20:19:21 2021 +0200
Commit:     Mark Jansen <[email protected]>
CommitDate: Sun Oct 3 20:26:25 2021 +0200

    [RAPPS] Speed up app loading by caching the INI sections
---
 base/applications/rapps/appview.cpp            |   6 +
 base/applications/rapps/configparser.cpp       | 182 ++++++++++++++++---------
 base/applications/rapps/include/appview.h      |  13 +-
 base/applications/rapps/include/configparser.h |  13 +-
 base/applications/rapps/include/gui.h          |   7 -
 base/applications/rapps/misc.cpp               |  35 +++--
 6 files changed, 157 insertions(+), 99 deletions(-)

diff --git a/base/applications/rapps/appview.cpp 
b/base/applications/rapps/appview.cpp
index c15c3ab1172..631eecbad9c 100644
--- a/base/applications/rapps/appview.cpp
+++ b/base/applications/rapps/appview.cpp
@@ -1705,6 +1705,12 @@ BOOL CApplicationView::CreateAppInfoDisplay()
     return m_AppsInfo->Create(m_hWnd) != NULL;
 }
 
+void CApplicationView::SetRedraw(BOOL bRedraw)
+{
+    CWindow::SetRedraw(bRedraw);
+    m_ListView->SetRedraw(bRedraw);
+}
+
 VOID CApplicationView::OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     if (wParam == SIZE_MINIMIZED)
diff --git a/base/applications/rapps/configparser.cpp 
b/base/applications/rapps/configparser.cpp
index 5e191da800b..d5c65991daa 100644
--- a/base/applications/rapps/configparser.cpp
+++ b/base/applications/rapps/configparser.cpp
@@ -2,18 +2,31 @@
  * PROJECT:     ReactOS Applications Manager
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     Config parser
- * COPYRIGHT:   Copyright 2009 Dmitry Chapyshev           ([email protected])
+ * COPYRIGHT:   Copyright 2009 Dmitry Chapyshev ([email protected])
  *              Copyright 2015 Ismael Ferreras Morezuelas 
([email protected])
- *              Copyright 2017 Alexander Shaposhnikov     
([email protected])
+ *              Copyright 2017 Alexander Shaposhnikov ([email protected])
+ *              Copyright 2021 Mark Jansen <[email protected]>
  */
 #include "rapps.h"
+#include <debug.h>
 
-CConfigParser::CConfigParser(const ATL::CStringW& FileName) : 
szConfigPath(GetINIFullPath(FileName))
+struct CLocaleSections
 {
-    CacheINILocale();
-}
+    CStringW Locale;
+    CStringW LocaleNeutral;
+    CStringW Section;
+};
 
-ATL::CStringW CConfigParser::GetINIFullPath(const ATL::CStringW& FileName)
+struct CSectionNames
+{
+    CLocaleSections ArchSpecific;
+    CLocaleSections ArchNeutral;
+};
+static CSectionNames g_Names;
+
+
+static
+ATL::CStringW GetINIFullPath(const ATL::CStringW& FileName)
 {
     ATL::CStringW szDir;
     ATL::CStringW szBuffer;
@@ -24,79 +37,124 @@ ATL::CStringW CConfigParser::GetINIFullPath(const 
ATL::CStringW& FileName)
     return szBuffer;
 }
 
-VOID CConfigParser::CacheINILocale()
+CConfigParser::CConfigParser(const ATL::CStringW& FileName)
+    : szConfigPath(GetINIFullPath(FileName))
 {
-    // TODO: Set default locale if call fails
-    // find out what is the current system lang code (e.g. "0a") and append it 
to SectionLocale
-    GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE,
-                    m_szLocaleID.GetBuffer(m_cchLocaleSize), m_cchLocaleSize);
-
-    m_szLocaleID.ReleaseBuffer();
-    m_szCachedINISectionLocale = L"Section." + m_szLocaleID;
-
-    // turn "Section.0c0a" into "Section.0a", keeping just the neutral lang 
part
-    if (m_szLocaleID.GetLength() >= 2)
-        m_szCachedINISectionLocaleNeutral = L"Section." + 
m_szLocaleID.Right(2);
-    else
-        m_szCachedINISectionLocaleNeutral = m_szCachedINISectionLocale;
+    CacheINI();
 }
 
-BOOL CConfigParser::GetStringWorker(const ATL::CStringW& KeyName, PCWSTR 
Suffix, ATL::CStringW& ResultString)
+void CConfigParser::ReadSection(ATL::CStringW& Buffer, const ATL::CStringW& 
Section, BOOL isArch)
 {
-    DWORD dwResult;
-
-    LPWSTR ResultStringBuffer = ResultString.GetBuffer(MAX_PATH);
-    // 1st - find localized strings (e.g. "Section.0c0a")
-    dwResult = GetPrivateProfileStringW((m_szCachedINISectionLocale + 
Suffix).GetString(),
-                                        KeyName.GetString(),
-                                        NULL,
-                                        ResultStringBuffer,
-                                        MAX_PATH,
-                                        szConfigPath.GetString());
-
-    if (!dwResult)
+    DWORD len = 512;
+    DWORD result;
+
+    do
     {
-        // 2nd - if they weren't present check for neutral sub-langs/ generic 
translations (e.g. "Section.0a")
-        dwResult = GetPrivateProfileStringW((m_szCachedINISectionLocaleNeutral 
+ Suffix).GetString(),
-                                            KeyName.GetString(),
-                                            NULL,
-                                            ResultStringBuffer,
-                                            MAX_PATH,
-                                            szConfigPath.GetString());
-        if (!dwResult)
+        len *= 2;
+
+        result = GetPrivateProfileSectionW(Section, Buffer.GetBuffer(len), 
len, szConfigPath);
+        Buffer.ReleaseBuffer(result);
+    } while (result == len - 2);
+
+    len = 0;
+    while (len < result)
+    {
+        // Explicitly use the null terminator!
+        CString tmp = Buffer.GetBuffer() + len;
+        if (tmp.GetLength() > 0)
+        {
+            len += tmp.GetLength() + 1;
+
+            int idx = tmp.Find('=');
+            if (idx >= 0)
+            {
+                CString key = tmp.Left(idx);
+
+#ifndef _M_IX86
+                // On non-x86 architecture we need the architecture specific 
URL
+                if (!isArch && key == "URLDownload")
+                {
+                    continue;
+                }
+#endif
+
+                // Is this key already present from a more specific 
translation?
+                if (m_Keys.FindKey(key) >= 0)
+                {
+                    continue;
+                }
+
+                CString value = tmp.Mid(idx+1);
+                m_Keys.Add(key, value);
+            }
+            else
+            {
+                DPRINT1("ERROR: invalid key/value pair: '%S'\n", 
tmp.GetString());
+            }
+        }
+        else
         {
-            // 3rd - if they weren't present fallback to standard english 
strings (just "Section")
-            dwResult = GetPrivateProfileStringW((ATL::CStringW(L"Section") + 
Suffix).GetString(),
-                                                KeyName.GetString(),
-                                                NULL,
-                                                ResultStringBuffer,
-                                                MAX_PATH,
-                                                szConfigPath.GetString());
+            break;
         }
     }
-
-    ResultString.ReleaseBuffer();
-    return (dwResult != 0 ? TRUE : FALSE);
 }
 
-BOOL CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& 
ResultString)
+VOID CConfigParser::CacheINI()
 {
-    /* First try */
-    if (GetStringWorker(KeyName, L"." CurrentArchitecture, ResultString))
+    // Cache section names
+    if (g_Names.ArchSpecific.Locale.IsEmpty())
     {
-        return TRUE;
+        CString szLocaleID;
+        const INT cchLocaleSize = 5;
+
+        GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE, 
szLocaleID.GetBuffer(cchLocaleSize), cchLocaleSize);
+        szLocaleID.ReleaseBuffer();
+        CString INISectionLocale = L"Section." + szLocaleID;
+
+        g_Names.ArchSpecific.Locale = INISectionLocale + L"." 
CurrentArchitecture;
+        g_Names.ArchNeutral.Locale = INISectionLocale;
+
+        // turn "Section.0c0a" into "Section.0a", keeping just the neutral 
lang part
+        if (szLocaleID.GetLength() >= 2)
+        {
+            g_Names.ArchSpecific.LocaleNeutral = L"Section." + 
szLocaleID.Right(2) + L"." CurrentArchitecture;
+            g_Names.ArchNeutral.LocaleNeutral = L"Section." + 
szLocaleID.Right(2);
+        }
+
+        g_Names.ArchSpecific.Section = L"Section." CurrentArchitecture;
+        g_Names.ArchNeutral.Section = L"Section";
     }
 
-#ifndef _M_IX86
-    /* On non-x86 architecture we need the architecture specific URL */
-    if (KeyName == L"URLDownload")
+    // Use a shared buffer so that we don't have to re-allocate it every time
+    CStringW Buffer;
+
+    ReadSection(Buffer, g_Names.ArchSpecific.Locale, TRUE);
+    if (!g_Names.ArchSpecific.LocaleNeutral.IsEmpty())
     {
-        return FALSE;
+        ReadSection(Buffer, g_Names.ArchSpecific.LocaleNeutral, TRUE);
+    }
+    ReadSection(Buffer, g_Names.ArchSpecific.Section, TRUE);
+
+
+    ReadSection(Buffer, g_Names.ArchNeutral.Locale, FALSE);
+    if (!g_Names.ArchNeutral.LocaleNeutral.IsEmpty())
+    {
+        ReadSection(Buffer, g_Names.ArchNeutral.LocaleNeutral, FALSE);
+    }
+    ReadSection(Buffer, g_Names.ArchNeutral.Section, FALSE);
+}
+
+BOOL CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& 
ResultString)
+{
+    int nIndex = m_Keys.FindKey(KeyName);
+    if (nIndex >= 0)
+    {
+        ResultString = m_Keys.GetValueAt(nIndex);
+        return TRUE;
     }
-#endif
 
-    /* Fall back to default */
-    return GetStringWorker(KeyName, L"", ResultString);
+    ResultString.Empty();
+    return FALSE;
 }
 
 BOOL CConfigParser::GetInt(const ATL::CStringW& KeyName, INT& iResult)
diff --git a/base/applications/rapps/include/appview.h 
b/base/applications/rapps/include/appview.h
index 192a59c7489..b625d5ed296 100644
--- a/base/applications/rapps/include/appview.h
+++ b/base/applications/rapps/include/appview.h
@@ -351,42 +351,31 @@ private:
     BOOL ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM 
lParam, LRESULT &theResult, DWORD dwMapId);
 
     BOOL CreateToolbar();
-
     BOOL CreateSearchBar();
-
     BOOL CreateComboBox();
-
     BOOL CreateHSplitter();
-
     BOOL CreateListView();
-
     BOOL CreateAppInfoDisplay();
 
     VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam);
-
     VOID OnCommand(WPARAM wParam, LPARAM lParam);
 public:
 
     CApplicationView(CMainWindow *MainWindow);
-
     ~CApplicationView();
 
     static ATL::CWndClassInfo &GetWndClassInfo();
 
     HWND Create(HWND hwndParent);
-
+    void SetRedraw(BOOL bRedraw);
     BOOL SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
 
     BOOL AddInstalledApplication(CInstalledApplicationInfo *InstAppInfo, 
LPVOID param);
-
     BOOL AddAvailableApplication(CAvailableApplicationInfo *AvlbAppInfo, BOOL 
InitCheckState, LPVOID param);
 
     void CheckAll();
-
     PVOID GetFocusedItemData();
-
     int GetItemCount();
-
     VOID AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> 
&TabOrderList);
 
     // this function is called when a item of listview get focus.
diff --git a/base/applications/rapps/include/configparser.h 
b/base/applications/rapps/include/configparser.h
index 5df9150269c..7ccfa115bd4 100644
--- a/base/applications/rapps/include/configparser.h
+++ b/base/applications/rapps/include/configparser.h
@@ -5,18 +5,11 @@
 
 class CConfigParser
 {
-    // Locale names cache
-    const static INT m_cchLocaleSize = 5;
-
-    ATL::CStringW m_szLocaleID;
-    ATL::CStringW m_szCachedINISectionLocale;
-    ATL::CStringW m_szCachedINISectionLocaleNeutral;
-
     const ATL::CStringW szConfigPath;
+    CSimpleMap<CStringW, CStringW> m_Keys;
 
-    ATL::CStringW GetINIFullPath(const ATL::CStringW& FileName);
-    VOID CacheINILocale();
-    BOOL GetStringWorker(const ATL::CStringW& KeyName, PCWSTR Suffix, 
ATL::CStringW& ResultString);
+    void CacheINI();
+    void ReadSection(ATL::CStringW& Buffer, const ATL::CStringW& Section, BOOL 
isArch);
 
 public:
     CConfigParser(const ATL::CStringW& FileName);
diff --git a/base/applications/rapps/include/gui.h 
b/base/applications/rapps/include/gui.h
index 1d8b6141ece..738379d7a1e 100644
--- a/base/applications/rapps/include/gui.h
+++ b/base/applications/rapps/include/gui.h
@@ -71,13 +71,9 @@ private:
     VOID InitCategoriesList();
 
     BOOL CreateStatusBar();
-
     BOOL CreateTreeView();
-
     BOOL CreateApplicationView();
-
     BOOL CreateVSplitter();
-
     BOOL CreateLayout();
 
     VOID LayoutCleanup();
@@ -99,11 +95,8 @@ private:
     VOID OnCommand(WPARAM wParam, LPARAM lParam);
 
     BOOL CALLBACK EnumInstalledAppProc(CInstalledApplicationInfo *Info);
-
     BOOL CALLBACK EnumAvailableAppProc(CAvailableApplicationInfo *Info, BOOL 
bInitialCheckState);
-
     static BOOL CALLBACK s_EnumInstalledAppProc(CInstalledApplicationInfo 
*Info, PVOID param);
-
     static BOOL CALLBACK s_EnumAvailableAppProc(CAvailableApplicationInfo 
*Info, BOOL bInitialCheckState, PVOID param);
 
     static BOOL CALLBACK 
s_EnumSelectedAppForDownloadProc(CAvailableApplicationInfo *Info, BOOL 
bInitialCheckState, PVOID param);
diff --git a/base/applications/rapps/misc.cpp b/base/applications/rapps/misc.cpp
index 742d4d67bb4..b5d142828ff 100644
--- a/base/applications/rapps/misc.cpp
+++ b/base/applications/rapps/misc.cpp
@@ -140,17 +140,36 @@ BOOL StartProcess(const ATL::CStringW& Path, BOOL Wait)
 
 BOOL GetStorageDirectory(ATL::CStringW& Directory)
 {
-    LPWSTR DirectoryStr = Directory.GetBuffer(MAX_PATH);
-    if (!SHGetSpecialFolderPathW(NULL, DirectoryStr, CSIDL_LOCAL_APPDATA, 
TRUE))
+    static CStringW CachedDirectory;
+    static BOOL CachedDirectoryInitialized = FALSE;
+
+    if (!CachedDirectoryInitialized)
     {
-        Directory.ReleaseBuffer();
-        return FALSE;
-    }
+        LPWSTR DirectoryStr = CachedDirectory.GetBuffer(MAX_PATH);
+        BOOL bHasPath = SHGetSpecialFolderPathW(NULL, DirectoryStr, 
CSIDL_LOCAL_APPDATA, TRUE);
+        if (bHasPath)
+        {
+            PathAppendW(DirectoryStr, L"rapps");
+        }
+        CachedDirectory.ReleaseBuffer();
+
+        if (bHasPath)
+        {
+            if (!CreateDirectoryW(CachedDirectory, NULL) && GetLastError() != 
ERROR_ALREADY_EXISTS)
+            {
+                CachedDirectory.Empty();
+            }
+        }
+        else
+        {
+            CachedDirectory.Empty();
+        }
 
-    PathAppendW(DirectoryStr, L"rapps");
-    Directory.ReleaseBuffer();
+        CachedDirectoryInitialized = TRUE;
+    }
 
-    return (CreateDirectoryW(Directory.GetString(), NULL) || GetLastError() == 
ERROR_ALREADY_EXISTS);
+    Directory = CachedDirectory;
+    return !Directory.IsEmpty();
 }
 
 VOID InitLogs()

Reply via email to