New test.
[mono.git] / mcs / class / I18N / CJK / CodeTable.cs
1 /*
2  * CodeTable.cs - Implementation of the "System.Text.CodeTable" class.
3  *
4  * Copyright (c) 2002  Southern Storm Software, Pty Ltd
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 namespace I18N.CJK
26 {
27
28 using System;
29 using System.IO;
30 using System.Reflection;
31 using System.Runtime.CompilerServices;
32 using I18N.Common;
33
34 // This class assists encoding classes for the large CJK character
35 // sets by providing pointer access to table data in the resource
36 // section of the current assembly.
37 //
38 // Code tables are named by their resource (e.g. "jis.table") and
39 // contain one or more sections.  Each section has an 8-byte header,
40 // consisting of a 32-bit section number and a 32-bit section length.
41 // The alignment of the data in the table is not guaranteed.
42
43 internal unsafe sealed class CodeTable : IDisposable
44 {
45         // Internal state.
46         private Stream stream;
47
48         // Load a code table from the resource section of this assembly.
49         public CodeTable(String name)
50                         {
51                                 stream = (Assembly.GetExecutingAssembly()
52                                                          .GetManifestResourceStream(name));
53                                 if(stream == null)
54                                 {
55                                         throw new NotSupportedException
56                                                 (String.Format
57                                                         (Strings.GetString("NotSupp_MissingCodeTable"),
58                                                          name));
59                                 }
60                         }
61
62         // Implement the IDisposable interface.
63         public void Dispose()
64                         {
65                                 if(stream != null)
66                                 {
67                                         stream.Close();
68                                         stream = null;
69                                 }
70                         }
71
72         // Get the starting address for a particular section within
73         // the code table.  This address is guaranteed to persist
74         // after "Dispose" is called.
75 #if __PNET__
76         public byte *GetSection(int num)
77 #else
78         public byte[] GetSection(int num)
79 #endif
80                         {
81                                 // If the table has been disposed, then bail out.
82                                 if(stream == null)
83                                 {
84                                         return null;
85                                 }
86
87                                 // Scan through the stream looking for the section.
88                                 long posn = 0;
89                                 long length = stream.Length;
90                                 byte[] header = new byte [8];
91                                 int sectNum, sectLen;
92                                 while((posn + 8) <= length)
93                                 {
94                                         // Read the next header block.
95                                         stream.Position = posn;
96                                         if(stream.Read(header, 0, 8) != 8)
97                                         {
98                                                 break;
99                                         }
100
101                                         // Decode the fields in the header block.
102                                         sectNum = ((int)(header[0])) |
103                                                           (((int)(header[1])) << 8) |
104                                                           (((int)(header[2])) << 16) |
105                                                           (((int)(header[3])) << 24);
106                                         sectLen = ((int)(header[4])) |
107                                                           (((int)(header[5])) << 8) |
108                                                           (((int)(header[6])) << 16) |
109                                                           (((int)(header[7])) << 24);
110
111                                         // Is this the section we are looking for?
112                                         if(sectNum == num)
113                                         {
114 #if __PNET__
115                                                 return GetAddress(stream, posn + 8);
116 #else
117                                                 byte[] buf = new byte [sectLen];
118                                                 if(stream.Read(buf, 0, sectLen) != sectLen)
119                                                 {
120                                                         break;
121                                                 }
122                                                 return buf;
123 #endif
124                                         }
125
126                                         // Advance to the next section.
127                                         posn += 8 + sectLen;
128                                 }
129
130                                 // We were unable to find the requested section.
131                                 return null;
132                         }
133
134 #if __PNET__
135         // Back door access into the engine to get the address of
136         // an offset within a manifest resource stream.
137         [MethodImpl(MethodImplOptions.InternalCall)]
138         extern private static byte *GetAddress(Stream stream, long position);
139 #endif
140
141 }; // class CodeTable
142
143 }; // namespace I18N.CJK