create changelog entry
[debian/openrocket] / android / src / net / sf / openrocket / android / thrustcurve / Base64Decoder.java
1 package net.sf.openrocket.android.thrustcurve;\r
2 \r
3 import java.io.IOException;\r
4 import java.io.Reader;\r
5 import java.io.StringReader;\r
6 import java.io.StringWriter;\r
7 \r
8 public abstract class Base64Decoder {\r
9 \r
10         private static final String BASE64_CHARS =\r
11                 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\r
12         private static final char PAD_CHAR = '=';\r
13 \r
14         private final static short[]  _charToBits = new short[128];\r
15 \r
16         static {\r
17 \r
18                 for (int i = 0; i < _charToBits.length; i++)\r
19                         _charToBits[i] = -1;\r
20 \r
21                 for (int i = 0; i < BASE64_CHARS.length(); i++)\r
22                         _charToBits[BASE64_CHARS.charAt(i)] = (byte) i;\r
23                 _charToBits[PAD_CHAR] = 0;\r
24 \r
25         }\r
26         \r
27         /**\r
28          * Decode the specified Base64 string and write binary data\r
29          * to the given stream.\r
30          * @param str Base64 encoded string\r
31          * @param w output stream\r
32          */\r
33         public static String decodeData(String str) throws IOException\r
34         {\r
35                 StringReader  r;\r
36                 int           c1;\r
37 \r
38                 if (str == null || str.length() < 1)\r
39                         return null;\r
40 \r
41                 r = new StringReader(str);\r
42                 \r
43                 StringWriter w = new StringWriter();\r
44 \r
45                 // spin through the input string\r
46                 c1 = readToNonSpace(r);\r
47                 while (c1 > 0)\r
48                 {\r
49                         int  c2, c3, c4;\r
50                         int  p1, p2, p3, p4;\r
51                         int  pad, n;\r
52 \r
53                         pad = 0;\r
54 \r
55                         c2 = readToNonSpace(r);\r
56                         c3 = readToNonSpace(r);\r
57                         c4 = readToNonSpace(r);\r
58                         if (c4 < 0)\r
59                                 throw new IllegalArgumentException("Encoded string ends prematurely.");\r
60 \r
61                         p1 = charToBits(c1);\r
62                         p2 = charToBits(c2);\r
63 \r
64                         if (c3 == PAD_CHAR)\r
65                         {\r
66                                 p3 = 0;\r
67                                 pad++;\r
68                         }\r
69                         else\r
70                                 p3 = charToBits(c3);\r
71 \r
72                         if (c4 == PAD_CHAR)\r
73                         {\r
74                                 p4 = 0;\r
75                                 pad++;\r
76                         }\r
77                         else\r
78                                 p4 = charToBits(c4);\r
79 \r
80                         if (p1 < 0 || p2 < 0 || p3 < 0 || p4 < 0)\r
81                                 throw new IllegalArgumentException("Encoded string contains invalid characters.");\r
82 \r
83                         n = (p1 << 18) | (p2 << 12) | (p3 << 6) | p4;\r
84 \r
85                         w.write((byte) ((n & 0xFF0000) >> 16));\r
86                         if (pad < 2)\r
87                                 w.write((byte) ((n & 0x00FF00) >> 8));\r
88                         if (pad < 1)\r
89                                 w.write((byte) (n & 0x0000FF));\r
90 \r
91                         c1 = readToNonSpace(r);\r
92                         if (c1 > 0 && pad > 0)\r
93                                 throw new IllegalArgumentException("Extra characters found after padding.");\r
94                 }\r
95                 \r
96                 return w.toString();\r
97         }\r
98 \r
99 \r
100         private static int readToNonSpace(Reader r)\r
101         throws IOException\r
102         {\r
103                 int  c;\r
104 \r
105                 c = r.read();\r
106                 while (c >= 0 && Character.isWhitespace(c))\r
107                         c = r.read();\r
108 \r
109                 return c;\r
110         }\r
111 \r
112         private static int charToBits(int c)\r
113         {\r
114                 // use it to look up the value\r
115                 if (c < 0 || c >= _charToBits.length)\r
116                         return -1;\r
117                 else\r
118                         return _charToBits[c];\r
119         }\r
120 \r
121 \r
122 }\r