note description: "[ Objects representing a path, i.e. a way to identify a file or a directory for the current underlying platform. A path is made of two components: 1 - an optional root which can either be: a - a drive letter followed by colon on Windows, i.e. "C:" or "C:\" b - "/" for UNIX root directory. c - "\" for Windows root directory. d - "\\server\share" or "\\server\share\" for Microsoft UNC path. 2 - a sequence of zero or more names. A path is absolute if it has a root, and on windows if the root is a drive, then it should be followed by "\". Otherwise a path is relative. Validity ======== The current class will not check the validity of filenames. Check your file system for your operating system manual for the list of invalid characters. Windows consideration ===================== When the root of a Windows path is a drive, be aware of the following behavior: 1 - "C:filename.txt" refers to the file name "filename.txt" in the current directory on drive "C:". 2 - "C:sub\filename.txt" refers to the file name "filename.txt" in a subdirectory "sub" of the current directory on drive "C:". 3 - "C:\sub\filename.txt" refers to the file name "filename.txt" in a subdirectory "sub" located at the root of the drive "C:". Both forward and backslashes are accepted, but forward slashes are internally converted to backward slashes whenever they are used to construct a path. On Windows, there is a limit of 259 characters for a path. If you need to create a larger path, you can do so by using the following conventions which will let you have paths of about 32,767 characters: 1 - Use \\?\ for non-UNC path and let the rest unchanged. 2 - Use \\?\UNC\server\share for UNC path and let the rest unchanged. The above path cannot be used to specify a relative path. To know more about Windows paths, read the "Naming Files, Paths, and Namespaces" document located at: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx Unicode consideration ===================== The PATH class treats strings as sequence of Unicode characters, i.e. an instance of a READABLE_STRING_8 or descendant will be treated as if characters in the range 128 .. 255 were Unicode code points. This contrasts to the FILE/DIRECTORY classes where to preserve backward compatibility, those characters are treated as is. Mixed-encoding consideration ============================ Most operating systems have conventions for paths that are incompatible with Unicode. On UNIX, in a sequence of names, each name is just a null-terminated byte sequence, it does not follow any specific encoding. Usually the locale setting enables you to see the filename the way you expect. On Windows, the sequence of names is made of null-terminated UTF-16 code unit sequence. Windows does not guarantee that the sequence is actually a valid UTF-16 sequence. In other words, when there is an invalid UTF-8 encoding on UNIX, or an invalid UTF-16 encoding on Windows, the filename is not directly representable as a Unicode string. To make it possible to create and store paths in a textually representable form, the query name will create an encoded representation that can be then later used in make_from_string to create a PATH equivalent to the original path. The encoding is described in UTF_CONVERTER's note clause and is a fourth variant of the recommended practice for replacement characters in Unicode (see http://www.unicode.org/review/pr-121.html). Immutability ============ Instances of the current class are immutable. ]" library: "Free implementation of ELKS library" status: "See notice at end of class." date: "$Date: 2020-05-19 14:32:38 +0000 (Tue, 19 May 2020) $" revision: "$Revision: 104260 $" class interface PATH create {NATIVE_STRING_HANDLER} make_from_pointer create {PATH} make_from_storage, make_from_normalized_storage create make_empty, make_current, make_from_string, make_from_separate feature -- Status report is_current_symbol: BOOLEAN -- Is Current a representation of "."? is_parent_symbol: BOOLEAN -- Is Current Representation of ".."? has_root: BOOLEAN -- Does current have a root? ensure defintion: Result implies not is_empty is_empty: BOOLEAN -- Is current empty, i.e. no root and no sequence of names? is_relative: BOOLEAN -- Is current path relative? is_absolute: BOOLEAN -- Is current path absolute? is_simple: BOOLEAN -- Is current path made of only one name and no root? -- I.e. readme.txt, usr or the empty path. is_same_file_as (a_path: PATH): BOOLEAN -- Does Current and a_path points to the same file on disk? It is different from path equality -- as it will take into account symbolic links. -- If Current or/and a_path do not exists, it will yield false, otherwise it will compare -- the file at the file system level. require a_path_not_void: a_path /= Void has_extension (a_ext: READABLE_STRING_GENERAL): BOOLEAN -- Does Current has an extension a_ext compared in a case insensitive manner? require a_ext_not_void: a_ext /= Void a_ext_not_empty: not a_ext.is_empty a_ext_has_no_dot: not a_ext.has ('.'.to_character_32) feature -- Access root: detachable PATH -- Root if any of current path. ensure has_root_implies_not_void: has_root implies Result /= Void parent: PATH -- Parent directory if any, otherwise current working path. -- The parent of a path consists of root if any, and of each -- simple names in the current sequence except for the last. entry: detachable PATH -- Name of file or directory denoted by Current if any. -- This is the last name in the current sequence. ensure not_empty: Result /= Void implies not Result.is_empty extension: detachable IMMUTABLE_STRING_32 -- Extension if any of current entry. ensure not_empty: attached Result implies not Result.is_empty no_dot: attached Result implies not Result.has ('.'.to_character_32) components: ARRAYED_LIST [PATH] -- Sequence of simple paths making up Current, including root if any. absolute_path: PATH -- Absolute path of Current. -- If Current is already absolute, then return Current. -- If Current is empty, then return the current working directory. -- Otherwise resolve the path in a platform specific way: -- * On UNIX, resolve against the current working directory -- * On Windows: -- a) if current has a drive letter which is not followed by "\" -- resolve against the current working directory for that drive letter, -- otherwise resolve against the current working directory. -- b) if current path starts with "\", not a double "\\", then resolve -- against the root of the current working directory (i.e. a drive -- letter "C:\" or a UNC path "\\server\share\".) absolute_path_in (a_current_directory: PATH): PATH -- Absolute path of Current in the context of a_current_directory. -- If Current is already absolute, then return Current. -- If Current is empty, then return a_current_directory. -- Otherwise resolve the path in a platform specific way: -- * On UNIX, resolve against a_current_directory -- * On Windows: -- a) if current has a drive letter which is not followed by "\" -- resolve against a_current_directory for that drive letter, -- otherwise resolve against a_current_directory. -- b) if current path starts with "\", not a double "\\", then resolve -- against the root of `a_current_directory; (i.e. a drive -- letter "C:\" or a UNC path "\\server\share\".) require a_current_directory_not_void: a_current_directory /= Void a_current_directory_absolute: a_current_directory.is_absolute ensure has_root: Result.has_root canonical_path: PATH -- Canonical path of Current. -- Similar to absolute_path except that sequences containing "." or ".." are -- resolved. hash_code: INTEGER_32 -- Hash code value native_string: NATIVE_STRING -- Convert current into an instance of NATIVE_STRING ensure set: Result.raw_string.same_string (storage) Unix_separator: CHARACTER_8 = '/' Windows_separator: CHARACTER_8 = '\' -- Platform specific directory separator. directory_separator: CHARACTER_8 -- Default directory separator for the current platform. feature -- Status setting extended (a_name: READABLE_STRING_GENERAL): PATH -- New path instance of current extended with path a_name. -- If current is not empty, then a_name cannot have a root. -- A directory separator is added between two entries except -- 1 - a_name starts with a directory separator (i.e. it has a root) -- 2 - if current is empty or is just a root. -- Note that a_name can be an encoding of a mixed-encoding simple name and it will -- be decoded accordingly (see note clause for the class for more details.) require a_name_not_void: a_name /= Void a_name_not_empty: not a_name.is_empty a_name_has_no_root: not is_empty implies not (create {PATH}.make_from_string (a_name)).has_root ensure associated_path_of_name: attached (create {PATH}.make_from_string (a_name)) as l_path not_empty: not Result.is_empty extended_with_only_empty_or_root: (same_as (root) or is_empty) implies Result.name.same_string (name + l_path.name) extended_with_more_than_root_or_not_empty: (not same_as (root) and not is_empty) implies Result.name.same_string (name + Directory_separator_string + l_path.name) extended_path alias "+" (a_path: PATH): PATH -- New path instance of current extended with path a_path. -- If current is not empty, then a_path cannot have a root. -- A directory separator is added between two entries except -- 1 - a_path starts with a directory separator (i.e. it has a root) -- 2 - if current is empty or is just a root. require a_path_not_void: a_path /= Void a_path_not_empty: not a_path.is_empty a_path_has_no_root: not is_empty implies not a_path.has_root ensure not_empty: not Result.is_empty extended_with_only_empty_or_root: (same_as (root) or is_empty) implies Result.name.same_string (name + a_path.name) extended_with_more_than_root_or_not_empty: (not same_as (root) and not is_empty) implies Result.name.same_string (name + Directory_separator_string + a_path.name) appended (a_extra: READABLE_STRING_GENERAL): PATH -- New path instance of current where entry is appended with a_extra without -- adding a directory separator. -- For example if Current path is "C:" and a_path is "path\file.txt", it will yield -- "C:path\file.txt". -- Note that a_extra can be an encoding of a mixed-encoding simple name and it will -- be decoded accordingly (see note clause for the class for more details.) require a_extra_not_void: a_extra /= Void a_extra_not_empty: not a_extra.is_empty ensure not_empty: not Result.is_empty appended: Result.name.same_string (name + (create {PATH}.make_from_string (a_extra)).name) appended_with_extension (a_ext: READABLE_STRING_GENERAL): PATH -- New path instance of current where entry is extended with a dot followed by a_ext. -- If Current already has a dot, no dot is added. -- Note that a_ext can be an encoding of a mixed-encoding simple name and it will -- be decoded accordingly (see note clause for the class for more details.) require a_ext_not_void: a_ext /= Void a_ext_not_empty: not a_ext.is_empty a_ext_has_no_dot: not a_ext.has ('.'.to_character_32) a_ext_has_no_directory_separator: not a_ext.has (Windows_separator.to_character_32) and not a_ext.has (Unix_separator.to_character_32) has_entry: entry /= Void ensure not_empty: not Result.is_empty extension_set: attached Result.extension as l_ext and then l_ext.same_string_general (a_ext) components_stable: Result.components.count = components.count feature -- Comparison same_as (other: detachable PATH): BOOLEAN -- Is Current the same path as other? -- Note that no canonicalization is being performed to compare paths, -- paths are compared using the OS-specific convention for letter case. is_less alias "<" (other: like Current): BOOLEAN -- Is current object less than other? is_equal (other: like Current): BOOLEAN -- Is other attached to an object considered -- equal to current object? is_case_sensitive_equal (other: PATH): BOOLEAN -- Compare path and paying attention to case. require other_not_void: other /= Void is_case_insensitive_equal (other: PATH): BOOLEAN -- Compare path without paying attention to case. If the path is containing some mixed-encoding -- we might ignore many characters when doing the case comparison. require other_not_void: other /= Void feature -- Duplication copy (other: like Current) -- Update current object using fields of object attached -- to other, so as to yield equal objects. feature -- Output out: STRING_8 -- Unicode representation of the underlying filename if representable, -- otherwise a UTF-8 encoded version. -- Use utf_8_name to have a printable representation whose format is not going -- to be changed in the future. utf_8_name: STRING_8 -- UTF-8 representation of the underlying filename. name: IMMUTABLE_STRING_32 -- If current is representable in Unicode, the Unicode representation. -- Otherwise all non-valid sequences for the current platform in the path are escaped -- as mentioned in the note clause of the class. -- To ensure roundtrip, you cannot use name directly to create a FILE, you have to -- create a PATH instance using make_from_string before passing it to the creation -- procedure of FILE taking an instance of PATH. ensure roundtrip: same_as (create {PATH}.make_from_string (Result)) feature -- Output debug_output: READABLE_STRING_32 -- String that should be displayed in debugger to represent Current. invariant little_endian_windows: {PLATFORM}.is_windows implies Platform.Is_little_endian even_count_on_windows: {PLATFORM}.is_windows implies storage.count \\ unit_size = 0 no_forward_slash_on_windows: {PLATFORM}.is_windows implies not storage.has_substring ("/%U") note copyright: "Copyright (c) 1984-2020, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end -- class PATH
Generated by ISE EiffelStudio