4 // Copyright (C) 2004 Novell, Inc.
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 using System
.Collections
;
31 namespace Beagle
.Util
{
35 private UriFu () { }
// class is static
37 static public Uri
PathToFileUri (string path
)
39 string uriStr
= StringFu
.PathToQuotedFileUri (path
);
40 return new Uri (uriStr
, true);
43 static public Uri
UriStringToUri (string path
)
45 // Decode our pre-encoded 'odd' characters into their real values
47 while ((i
= path
.IndexOf ('%', pos
)) != -1) {
49 char unescaped
= UriFu
.HexUnescape (path
, ref pos
);
50 if (unescaped
< '!' || unescaped
> '~') {
51 path
= path
.Remove (i
, 3);
52 path
= path
.Insert (i
, new String(unescaped
, 1));
57 // Paths from the file:// indexer need (re)quoting. For example,
58 // valid characters such as @ need to be converted to their hex
60 if (path
.StartsWith ("file://")) {
61 // Remove the file:// prefix
62 path
= path
.Substring (7);
64 return PathToFileUri (path
);
67 // Currently, no other protocols need extra processing
68 return new Uri (path
, true);
71 static public String
UriToSerializableString (Uri uri
)
75 StringBuilder builder
= new StringBuilder ();
77 // The ToString() of a file:// URI is not always representative of
78 // what it was constructed from. For example, it will return a
79 // # (which was inputted as %23) as %23, whereas the more standard
80 // behaviour for other escaped-characters is to return them as
81 // their actual character. (e.g. %40 gets returned as @)
82 // On the other hand, the LocalPath of a file:// URI does seem to
83 // return the literal # so we use that instead.
85 ret
= Uri
.UriSchemeFile
+ Uri
.SchemeDelimiter
+ uri
.LocalPath
;
87 ret
= uri
.ToString ();
89 // XmlSerializer is happy to serialize 'odd' characters, but doesn't
90 // like to deserialize them. So we encode all 'odd' characters now.
91 for (i
= 0; i
< ret
.Length
; i
++)
92 if ((ret
[i
] < '!') || (ret
[i
] > '~' && ret
[i
] < 256))
93 builder
.Append (Uri
.HexEscape (ret
[i
]));
95 builder
.Append (ret
[i
]);
97 return builder
.ToString ();
100 // Stolen from Mono SVN 20050319
101 // Fixes bug where non-ASCII characters couldn't be decoded
102 // FIXME: Go back to using Uri.HexUnescape when new Mono 1.1.5+ is
103 // readily available.
104 public static char HexUnescape (string pattern
, ref int index
)
107 throw new ArgumentException ("pattern");
109 if (index
< 0 || index
>= pattern
.Length
)
110 throw new ArgumentOutOfRangeException ("index");
112 if (!Uri
.IsHexEncoding (pattern
, index
))
113 return pattern
[index
++];
121 int msb
= Uri
.FromHex (pattern
[index
++]);
122 int lsb
= Uri
.FromHex (pattern
[index
++]);
123 b
= (msb
<< 4) + lsb
;
124 if (!Uri
.IsHexEncoding (pattern
, index
)) {
126 c
+= (b
- 0x80) << ((stage
- 1) * 6);
130 } else if (stage
== 0) {
136 } else if (b
< 0xF0) {
139 } else if (b
< 0xF8) {
142 } else if (b
< 0xFB) {
145 } else if (b
< 0xFE) {
149 c
<<= (stage
- 1) * 6;
151 c
+= (b
- 0x80) << ((stage
- 1) * 6);
160 static public String
LocalPathFromUri (Uri uri
)
164 // FIXME: Can we assume "a directory", if it is not a file?
165 // If so, return the path of that directory.
167 return uri
.LocalPath
;
172 //////////////////////////////////
174 static public bool Equals (Uri uri1
, Uri uri2
)
176 return uri1
.ToString () == uri2
.ToString ();
179 static public int Compare (Uri uri1
, Uri uri2
)
181 return String
.Compare (uri1
.ToString (), uri2
.ToString ());
184 //////////////////////////////////
186 public class Comparer
: IComparer
188 public int Compare(object uri1
, object uri2
)
190 return String
.Compare(uri1
.ToString(), uri2
.ToString());
194 public class Hasher
: IHashCodeProvider
196 public int GetHashCode(object o
)
198 return o
.ToString().GetHashCode();
202 static Comparer the_comparer
= new Comparer ();
203 static Hasher the_hasher
= new Hasher ();
205 // Returns a hash table that does the right thing when
207 static public Hashtable
NewHashtable ()
209 return new Hashtable (the_hasher
, the_comparer
);
212 //////////////////////////////////
214 static public string UrisToString (ICollection list_of_uris
)
216 StringBuilder sb
= new StringBuilder ("!@#");
218 foreach (Uri uri
in list_of_uris
) {
220 sb
.Append (UriToSerializableString (uri
).Replace (" ", "%20"));
223 return sb
.ToString ();
226 static public ICollection
StringToUris (string list_of_uris_as_string
)
228 string [] parts
= list_of_uris_as_string
.Split (' ');
230 if (parts
.Length
== 0 || parts
[0] != "!@#")
233 ArrayList uri_array
= new ArrayList ();
234 for (int i
= 1; i
< parts
.Length
; ++i
) {
236 Uri uri
= UriStringToUri (parts
[i
]);
238 } catch (Exception ex
) {
239 Logger
.Log
.Debug ("Caught exception converting '{0}' to a Uri", parts
[i
]);