[Mono-devel-list] [PATCH] GetFolderPath improvements

Todd Berman tberman at sevenl.net
Tue Jun 15 20:14:32 EDT 2004


So we are moving a chunk of code from corlib to the runtime to prevent a 
  switch in a method that is not used more than once or twice if even at 
all in an average program's lifecycle?

--Todd

Ben Maurer wrote:
> I should have explained this part, thank you for reminding me.
> 
> As I mentioned on IRC, this is so that we can use #ifdef to do specific
> testing for platforms. IMHO, this is something that is cleaner if we can
> use the autoconf information.
> 
> -- Ben
> 
> On Tue, 2004-06-15 at 19:56, Todd Berman wrote:
> 
>>Why is this becoming an icall?
>>
>>--Todd
>>
>>Ben Maurer wrote:
>>
>>>Hey guys,
>>>
>>>GetFolderPath was returning paths that are not really consistent with
>>>the Linux background. The attached path will make us do the following
>>>mappings:
>>>
>>>Desktop
>>>DesktopDirectory
>>>        ~/Desktop -- Luis says that this is the default on all GNOME and
>>>        KDE systems. That should pretty much cover us for Linux.
>>>Personal
>>>        ~ -- as before
>>>ApplicationData
>>>        The config directory as per fd.o's XDG spec. This defaults to
>>>        ~/.config
>>>LocalApplicationData
>>>        The data folder per XDG. Defaults to ~/.local/share
>>>CommonApplicationData
>>>        /etc. Should this be /usr/share.
>>>System
>>>        /etc. Maybe /bin is more correct?
>>>Program Files
>>>	/usr/bin
>>>CommonApplicationData
>>>	/usr/share
>>>
>>>All other folders return "". Per the MSDN docs, if a folder has not been
>>>created on the computer, the method should return String.Empty. Before
>>>we would return a semi-related folder for things.
>>>
>>>Another open issue is if we should probe for the existence of the folder
>>>before returning it. In the windows code, it looks like we even try to
>>>create the file before giving up. I would appreciate comments on this.
>>>
>>>-- Ben
>>>
>>>
>>>
>>>------------------------------------------------------------------------
>>>
>>>Index: Environment.cs
>>>===================================================================
>>>RCS file: /cvs/public/mcs/class/corlib/System/Environment.cs,v
>>>retrieving revision 1.76
>>>diff -u -r1.76 Environment.cs
>>>--- Environment.cs	11 Jun 2004 01:59:23 -0000	1.76
>>>+++ Environment.cs	15 Jun 2004 22:41:06 -0000
>>>@@ -90,6 +90,8 @@
>>> 			MyPictures = 0x27,
>>> 			CommonProgramFiles = 0x2b,
>>> 		}
>>>+		
>>>+		const SpecialFolder MAX_SPECIAL_FOLDER = SpecialFolder.CommonProgramFiles;
>>> 
>>> 		// TODO: Make sure the security attributes do what I expect
>>> 			
>>>@@ -367,96 +369,24 @@
>>> 
>>> 
>>> 		[MethodImplAttribute (MethodImplOptions.InternalCall)]
>>>-		private extern static string GetWindowsFolderPath (int folder);
>>>+		private extern static string GetFolderPathInternal (int folder);
>>> 
>>>+		static string [] get_folder_path_cache;
>>> 		/// <summary>
>>> 		/// Returns the fully qualified path of the
>>> 		/// folder specified by the "folder" parameter
>>> 		/// </summary>
>>> 		public static string GetFolderPath (SpecialFolder folder)
>>> 		{
>>>-			if ((int) Platform != 128)
>>>-				return GetWindowsFolderPath ((int) folder);
>>>-
>>>-			// we can do this in managed code for non-Windows environments
>>>-			string path = String.Empty;
>>>-
>>>-			string home = GetEnvironmentVariable ("HOME");
>>>-
>>>-			// http://freedesktop.org/Standards/basedir-spec/basedir-spec-0.6.html
>>>-			string data = GetEnvironmentVariable ("XDG_DATA_HOME");
>>>-			if ((data == null) || (data == String.Empty)) {
>>>-				data = Path.Combine (home, ".local");
>>>-				data = Path.Combine (data, "share");
>>>-			}
>>>-
>>>-			string config = GetEnvironmentVariable ("XDG_CONFIG_HOME");
>>>-			if ((config == null) || (config == String.Empty)) {
>>>-				config = Path.Combine (home, ".config");
>>>-			}
>>>-
>>>-			string cache = GetEnvironmentVariable ("XDG_CACHE_HOME");
>>>-			if ((cache == null) || (cache == String.Empty)) {
>>>-				cache = Path.Combine (home, ".cache");
>>>+			if (get_folder_path_cache != null) {
>>>+				string s = get_folder_path_cache [(int) folder];
>>>+				if (s != null)
>>>+					return s;
>>>+			} else {
>>>+				get_folder_path_cache = new string [(int)MAX_SPECIAL_FOLDER + 1];
>>> 			}
>>>-
>>>-			switch (folder) {
>>>-#if NET_1_1
>>>-			case SpecialFolder.MyComputer: // MyComputer is a virtual directory
>>>-				path = "";
>>>-				break;
>>>-#endif				      
>>>-
>>>-			case SpecialFolder.Personal:
>>>-				path = home;
>>>-				break;
>>>-
>>>-			// data related
>>>-			case SpecialFolder.ApplicationData:
>>>-			case SpecialFolder.LocalApplicationData:
>>>-			case SpecialFolder.MyMusic:
>>>-			case SpecialFolder.MyPictures:
>>>-			case SpecialFolder.Templates:
>>>-				path = data;
>>>-				break;
>>>-
>>>-			// configuration related
>>>-#if NET_1_1
>>>-			case SpecialFolder.Desktop:
>>>-#endif
>>>-			case SpecialFolder.DesktopDirectory:
>>>-			case SpecialFolder.Favorites:
>>>-			case SpecialFolder.Programs:
>>>-			case SpecialFolder.SendTo:
>>>-			case SpecialFolder.StartMenu:
>>>-			case SpecialFolder.Startup:
>>>-				path = config;
>>>-				break;
>>>-
>>>-			// cache related (could disappear)
>>>-			case SpecialFolder.Cookies:
>>>-			case SpecialFolder.History:
>>>-			case SpecialFolder.InternetCache:
>>>-			case SpecialFolder.Recent:
>>>-				path = cache;
>>>-				break;
>>>-
>>>-			// programs
>>>-			case SpecialFolder.CommonProgramFiles:
>>>-			case SpecialFolder.ProgramFiles:
>>>-			case SpecialFolder.System:
>>>-				break;
>>>-
>>>-			// Directories shared by all users
>>>-			case SpecialFolder.CommonApplicationData:
>>>-				path = Path.GetDirectoryName (GetMachineConfigPath ());
>>>-				break;
>>>-
>>>-			default:
>>>-				throw new ArgumentException ("Invalid SpecialFolder");
>>>-                        }
>>>-
>>>-			return path;
>>>+			
>>>+			return get_folder_path_cache [(int) folder] = GetFolderPathInternal ((int) folder);
>>>                 }
>>> 
>>> 		public static string[] GetLogicalDrives ()
>>>
>>>
>>>------------------------------------------------------------------------
>>>
>>>? t
>>>Index: icall.c
>>>===================================================================
>>>RCS file: /cvs/public/mono/mono/metadata/icall.c,v
>>>retrieving revision 1.498
>>>diff -u -r1.498 icall.c
>>>--- icall.c	12 Jun 2004 11:32:35 -0000	1.498
>>>+++ icall.c	15 Jun 2004 22:39:30 -0000
>>>@@ -4443,13 +4443,38 @@
>>> 	return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
>>> }
>>> 
>>>+typedef enum {
>>>+	MONO_FOLDER_PATH_DESKTOP = 0x00,
>>>+	MONO_FOLDER_PATH_MYCOMPUTER = 0x11,
>>>+	MONO_FOLDER_PATH_PROGRAMS = 0x02,
>>>+	MONO_FOLDER_PATH_PERSONAL = 0x05,
>>>+	MONO_FOLDER_PATH_FAVORITES = 0x06,
>>>+	MONO_FOLDER_PATH_STARTUP = 0x07,
>>>+	MONO_FOLDER_PATH_RECENT = 0x08,
>>>+	MONO_FOLDER_PATH_SENDTO = 0x09,
>>>+	MONO_FOLDER_PATH_STARTMENU = 0x0b,
>>>+	MONO_FOLDER_PATH_MYMUSIC = 0x0d,
>>>+	MONO_FOLDER_PATH_DESKTOPDIRECTORY = 0x10,
>>>+	MONO_FOLDER_PATH_TEMPLATES = 0x15,
>>>+	MONO_FOLDER_PATH_APPLICATIONDATA	= 0x1a,
>>>+	MONO_FOLDER_PATH_LOCALAPPLICATIONDATA = 0x1c,
>>>+	MONO_FOLDER_PATH_INTERNETCACHE = 0x20,
>>>+	MONO_FOLDER_PATH_COOKIES = 0x21,
>>>+	MONO_FOLDER_PATH_HISTORY = 0x22,
>>>+	MONO_FOLDER_PATH_COMMONAPPLICATIONDATA	= 0x23,
>>>+	MONO_FOLDER_PATH_SYSTEM = 0x25,
>>>+	MONO_FOLDER_PATH_PROGRAMFILES = 0x26,
>>>+	MONO_FOLDER_PATH_MYPICTURES = 0x27,
>>>+	MONO_FOLDER_PATH_COMMONPROGRAMFILES = 0x2b
>>>+} MonoFolderPathEnum;
>>>+
>>> static MonoString*
>>>-ves_icall_System_Environment_GetWindowsFolderPath (int folder)
>>>+ves_icall_System_Environment_GetFolderPathInternal (int folder)
>>> {
>>>-#if defined (PLATFORM_WIN32)
>>>-	#ifndef CSIDL_FLAG_CREATE
>>>-		#define CSIDL_FLAG_CREATE	0x8000
>>>-	#endif
>>>+#ifdef PLATFORM_WIN32
>>>+#	ifndef CSIDL_FLAG_CREATE
>>>+#		define CSIDL_FLAG_CREATE	0x8000
>>>+#	endif
>>> 
>>> 	WCHAR path [MAX_PATH];
>>> 	/* Create directory if no existing */
>>>@@ -4460,7 +4485,81 @@
>>> 		return mono_string_new_utf16 (mono_domain_get (), path, len);
>>> 	}
>>> #else
>>>-	g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
>>>+	char* path;
>>>+	MonoString* ret;
>>>+	switch (folder) {
>>>+	case MONO_FOLDER_PATH_DESKTOP:
>>>+	case MONO_FOLDER_PATH_DESKTOPDIRECTORY:
>>>+		path = g_strconcat (g_get_home_dir (), "/Desktop", NULL);
>>>+		ret = mono_string_new (mono_domain_get (), path);
>>>+		g_free (path);
>>>+		break;
>>>+	case MONO_FOLDER_PATH_MYCOMPUTER:
>>>+		/* this is a virtual folder, we return "" as does MS */
>>>+		ret = NULL;
>>>+		break;
>>>+	case MONO_FOLDER_PATH_PERSONAL:
>>>+		ret = mono_string_new (mono_domain_get (), g_get_home_dir ());
>>>+		break;
>>>+	case MONO_FOLDER_PATH_PROGRAMS:
>>>+	case MONO_FOLDER_PATH_FAVORITES:
>>>+	case MONO_FOLDER_PATH_STARTUP:
>>>+	case MONO_FOLDER_PATH_RECENT:
>>>+	case MONO_FOLDER_PATH_SENDTO:
>>>+	case MONO_FOLDER_PATH_STARTMENU:
>>>+	case MONO_FOLDER_PATH_MYMUSIC:
>>>+	case MONO_FOLDER_PATH_INTERNETCACHE:
>>>+	case MONO_FOLDER_PATH_COOKIES:
>>>+	case MONO_FOLDER_PATH_HISTORY:
>>>+	case MONO_FOLDER_PATH_TEMPLATES:
>>>+	case MONO_FOLDER_PATH_MYPICTURES:
>>>+		/* all of these either a) dont exist on linux, or b) are not
>>>+		 * standard enough to be worth giving here
>>>+		 */
>>>+		ret = NULL;
>>>+		break;
>>>+	
>>>+	case MONO_FOLDER_PATH_APPLICATIONDATA:
>>>+		/* use FDO's CONFIG_HOME. This data will be synced across a
>>>+		 * network like the windows counterpart.
>>>+		 */
>>>+		 
>>>+		path = g_getenv ("XDG_CONFIG_HOME");
>>>+		if (!path)
>>>+			path = g_strconcat (g_get_home_dir (), "/.config", NULL);
>>>+		
>>>+		ret = mono_string_new (mono_domain_get (), path);
>>>+		g_free (path);
>>>+		break;
>>>+	case MONO_FOLDER_PATH_LOCALAPPLICATIONDATA:
>>>+		/* use FDO's DATA_HOME. This is *NOT* synced. */
>>>+		 
>>>+		path = g_getenv ("XDG_DATA_HOME");
>>>+		if (!path)
>>>+			path = g_strconcat (g_get_home_dir (), "/.local/share", NULL);
>>>+		
>>>+		ret = mono_string_new (mono_domain_get (), path);
>>>+		g_free (path);
>>>+		break;
>>>+	case MONO_FOLDER_PATH_COMMONAPPLICATIONDATA:
>>>+		ret = mono_string_new (mono_domain_get (), "/etc");
>>>+		break;
>>>+	case MONO_FOLDER_PATH_SYSTEM:
>>>+		ret = mono_string_new (mono_domain_get (), "/etc");
>>>+		break;
>>>+	case MONO_FOLDER_PATH_PROGRAMFILES:
>>>+		ret = mono_string_new (mono_domain_get (), "/usr/bin");
>>>+		break;
>>>+	case MONO_FOLDER_PATH_COMMONPROGRAMFILES:
>>>+		ret = mono_string_new (mono_domain_get (), "/usr/share");
>>>+		break;
>>>+	default:
>>>+		g_assert_not_reached ();
>>>+	}
>>>+	
>>>+	/* should we test that the file exists? */
>>>+	if (ret)
>>>+		return ret;
>>> #endif
>>> 	return mono_string_new (mono_domain_get (), "");
>>> }
>>>@@ -5128,10 +5227,10 @@
>>> 	{"GetCommandLineArgs", mono_runtime_get_main_args},
>>> 	{"GetEnvironmentVariable", ves_icall_System_Environment_GetEnvironmentVariable},
>>> 	{"GetEnvironmentVariableNames", ves_icall_System_Environment_GetEnvironmentVariableNames},
>>>+	{"GetFolderPathInternal", ves_icall_System_Environment_GetFolderPathInternal},
>>> 	{"GetLogicalDrivesInternal", ves_icall_System_Environment_GetLogicalDrives },
>>>  	{"GetMachineConfigPath", ves_icall_System_Configuration_DefaultConfig_get_machine_config_path},
>>>  	{"GetOSVersionString", ves_icall_System_Environment_GetOSVersionString},
>>>-	{"GetWindowsFolderPath", ves_icall_System_Environment_GetWindowsFolderPath},
>>> 	{"get_ExitCode", mono_environment_exitcode_get},
>>> 	{"get_HasShutdownStarted", ves_icall_System_Environment_get_HasShutdownStarted},
>>> 	{"get_MachineName", ves_icall_System_Environment_get_MachineName},
>>
> 
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list
> 




More information about the Mono-devel-list mailing list