]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/util/URIUtil.java
(refs #7307) Added features field to SCL module header
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / util / URIUtil.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.util;
13
14 import java.io.UnsupportedEncodingException;
15 import java.nio.charset.Charset;
16
17 /**
18  * <a href="http://www.simantics.org/wiki/index.php/URI">Simantics URI and identifier escape specification.
19  * 
20  * @author Hannu Niemist&ouml;
21  */
22 public final class URIUtil {
23
24     static final Charset UTF8        = Charset.forName("UTF-8");
25
26     static final byte[]  encodeTable = new byte[128];
27     static final byte[]  encodeTable2 = new byte[128]; // for non-bijection filenames
28
29     static {
30         for (int i = 0; i < 128; ++i) {
31             char c = (char) i;
32             if (c == ' ')
33                 encodeTable[i] = '_';
34             
35             else if (Character.isJavaIdentifierPart(c) && c != '_' && c != '$') {
36                 encodeTable[i] = (byte) i;
37             } else
38                 encodeTable[i] = -1;
39         }
40         
41         for (int i = 0; i < 128; ++i) {
42             char c = (char) i;
43             if (c == ' ' || c == '_' || c == '(' || c== ')')
44                 encodeTable2[i] = (byte) i;
45             else if (c == '/')
46                 encodeTable2[i] = (byte) '-';
47             else if (c == ' ')
48                 encodeTable2[i] = (byte) '_';
49             else if (c == '-' || c == '.')
50                 encodeTable2[i] = (byte) i;
51             else if (Character.isJavaIdentifierPart(c) && c != '_' && c != '$') {
52                 encodeTable2[i] = (byte) i;
53             } else
54                 encodeTable2[i] = -1;
55         }
56         
57     }
58
59     public static byte[] encode(String str, byte escapeChar, boolean identifier) throws UnsupportedEncodingException {
60         byte[] bytes = str.getBytes(UTF8);
61
62         boolean prefixWithUnderscore = identifier && bytes.length > 0 && (bytes[0] == '_' || Character.isDigit(bytes[0]));
63
64         // First calculate the length
65         int length = bytes.length;
66         for (byte b : bytes) {
67             if (b < 0 || encodeTable[b] == -1)
68                 length += 2;
69         }
70         if (prefixWithUnderscore)
71             length += 1;
72
73         // Then encode
74         if (length == bytes.length) {
75             for (int i = 0; i < length; ++i)
76                 bytes[i] = encodeTable[bytes[i]];
77             return bytes;
78         } else {
79             byte[] result = new byte[length];
80             int pos = 0;
81             if (prefixWithUnderscore) {
82                 result[pos++] = '_';
83             }
84             for (byte b : bytes) {
85                 int ib = (int) b;
86                 if (ib >= 0) {
87                     byte eb = encodeTable[ib];
88                     if (eb >= 0) {
89                         result[pos++] = eb;
90                         continue;
91                     }
92                 } else
93                     ib += 256;
94
95                 result[pos++] = escapeChar;
96                 result[pos++] = (byte) Character.forDigit(ib >> 4, 16);
97                 result[pos++] = (byte) Character.forDigit(ib & 15, 16);
98             }
99             return result;
100         }
101     }
102     
103     public static byte[] encodeFilename(String str, byte escapeChar, boolean identifier) throws UnsupportedEncodingException {
104         byte[] bytes = str.getBytes(UTF8);
105
106         boolean prefixWithUnderscore = identifier && bytes.length > 0 && (bytes[0] == '_' || Character.isDigit(bytes[0]));
107
108         // First calculate the length
109         int length = bytes.length;
110         for (byte b : bytes) {
111             if (b < 0 || encodeTable2[b] == -1)
112                 length += 2;
113         }
114         if (prefixWithUnderscore)
115             length += 1;
116
117         // Then encode
118         if (length == bytes.length) {
119             for (int i = 0; i < length; ++i)
120                 bytes[i] = encodeTable2[bytes[i]];
121             return bytes;
122         } else {
123             byte[] result = new byte[length];
124             int pos = 0;
125             if (prefixWithUnderscore) {
126                 result[pos++] = '_';
127             }
128             for (byte b : bytes) {
129                 int ib = (int) b;
130                 if (ib >= 0) {
131                     byte eb = encodeTable2[ib];
132                     if (eb >= 0) {
133                         result[pos++] = eb;
134                         continue;
135                     }
136                 } else
137                     ib += 256;
138
139                 result[pos++] = escapeChar;
140                 result[pos++] = (byte) Character.forDigit(ib >> 4, 16);
141                 result[pos++] = (byte) Character.forDigit(ib & 15, 16);
142             }
143             return result;
144         }
145     }
146     
147     public static String encodeFilename(String str) {
148         try {
149             byte[] result = encodeFilename(str, (byte) '%', false);
150             return new String(result, 0, result.length);
151         } catch (UnsupportedEncodingException e) {
152             // Should never happen when using UTF-8
153             throw new Error(e);
154         }
155
156     }
157
158     public static String encodeURI(String str) {
159         try {
160             byte[] result = encode(str, (byte) '%', false);
161             return new String(result, 0, result.length);
162         } catch (UnsupportedEncodingException e) {
163             // Should never happen when using UTF-8
164             throw new Error(e);
165         }
166
167     }
168
169     public static String encodeIdentifier(String str) {
170         try {
171             byte[] result = encode(str, (byte) '$', true);
172             return new String(result, 0, result.length);
173         } catch (UnsupportedEncodingException e) {
174             // Should never happen when using UTF-8
175             throw new Error(e);
176         }
177
178     }
179
180     public static String decode(byte[] bytes, byte escapeChar, boolean identifier) {
181         int length = 0;
182         int startPos = 0;
183         {
184             int i = 0;
185             // Skip '_' prefix if necessary
186             if (identifier && bytes.length > 0 && bytes[0] == '_') {
187                 startPos = 1;
188                 i = 1;
189             }
190             for (; i < bytes.length; ++i) {
191                 byte b = bytes[i];
192                 if (b == escapeChar)
193                     i += 2;
194                 ++length;
195             }
196         }
197         int pos = 0;
198         byte[] result = new byte[length];
199         for (int i = startPos; i < bytes.length; ++i) {
200             byte b = bytes[i];
201             if (b == escapeChar) {
202                 int c = Character.digit((char) bytes[++i], 16);
203                 c *= 16;
204                 c += Character.digit((char) bytes[++i], 16);
205                 result[pos] = (byte) c;
206             } else {
207                 if (b == '_')
208                     result[pos] = ' ';
209                 else
210                     result[pos] = b;
211             }
212             ++pos;
213         }
214         return new String(result, UTF8);
215     }
216
217     public static String decodeURI(String str) {
218         return decode(str.getBytes(), (byte) '%', false);
219     }
220
221     public static String decodeIdentifier(String str) {
222         return decode(str.getBytes(), (byte) '$', true);
223     }
224     
225 }