Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: fc50de3907d9070eb3319e3658d49e7982b12422 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*******************************************************************************
 * Copyright (c) 2010, 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 ******************************************************************************/
package org.eclipse.equinox.bidi;

import java.lang.ref.SoftReference;
import org.eclipse.equinox.bidi.custom.STextStringProcessor;

/**
 *  This class records strings which are structured text. Several static
 *  methods in this class allow to record such strings in a pool, and to find if
 *  a given string is member of the pool.
 *  <p>
 *  Instances of this class are the records which are members of the pool.
 *  <p>
 *  The pool is managed as a cyclic list. When the pool is full,
 *  each new element overrides the oldest element in the list.
 */
public class STextStringRecord {
	/**
	 * Number of entries in the pool of recorded strings
	 */
	public static final int POOLSIZE = 100;

	// maximum index allowed
	private static final int MAXINDEX = POOLSIZE - 1;

	// index of the last entered record
	private static int last = MAXINDEX;

	// the pool
	private static STextStringRecord[] records = new STextStringRecord[POOLSIZE];

	// structured text types
	private static final String[] types = STextStringProcessor.getKnownTypes();

	// maximum type index allowed
	private static int MAXTYPE = types.length - 1;

	// reference to the recorded string
	private SoftReference strRef;

	// hash code of the recorded string
	private int hash;

	// reference to the triplets of the recorded string
	private SoftReference triRef;

	/**
	 *  Constructor.
	 *
	 *  @param  string the string to record
	 *
	 *  @param  triplets
	 *          array of short integers, the number of elements in the array
	 *          must be a multiple of 3, so that the array is made of one or
	 *          more triplets of short integers.
	 *          <p>
	 *          The first element in each triplet is the beginning offset of a
	 *          susbstring of <code>string</code> which is a structured text.
	 *          <p>
	 *          The second element in each triplet is the ending offset of a
	 *          susbstring of <code>string</code> which is a structured text.
	 *          This offset points to one position beyond the last
	 *          character of the substring.
	 *          <p>
	 *          The third element in each triplet is the numeric type of the
	 *          structured text.<br>
	 *          The type of a structured text must be one of the string
	 *          values listed in {@link ISTextTypes}.<br>
	 *          The corresponding numeric type must be obtained using the
	 *          method {@link #typeStringToShort typeStringToShort}.
	 */
	public STextStringRecord(String string, short[] triplets) {
		if (string == null || triplets == null)
			throw new IllegalArgumentException("The string and triplets argument must not be null!"); //$NON-NLS-1$
		if ((triplets.length % 3) != 0)
			throw new IllegalArgumentException("The number of elements in triplets must be a multiple of 3!"); //$NON-NLS-1$
		for (int i = 2; i < triplets.length; i += 3)
			if (triplets[i] < 0 || triplets[i] > MAXTYPE)
				throw new IllegalArgumentException("Illegal type value in element" + i); //$NON-NLS-1$
		strRef = new SoftReference(string);
		triRef = new SoftReference(triplets);
		hash = string.hashCode();
	}

	/**
	 *  Get the numeric type of a structured text given its string type.
	 *
	 *  @param  type type of structured text as string. It must be one
	 *          of the strings listed in {@link ISTextTypes}.
	 *
	 *  @return a value which is the corresponding numeric type. If
	 *          <code>type</code> is invalid, the method returns <code>-1</code>.
	 */
	public static short typeStringToShort(String type) {
		for (int i = 0; i < types.length; i++)
			if (types[i].equals(type))
				return (short) i;
		return -1;
	}

	/**
	 *  Get the string type of a structured text given its numeric type.
	 *
	 *  @param shType
	 *         the numeric type of a structured text. It should be a value
	 *         obtained using {@link #typeStringToShort typeStringToShort}.
	 *
	 *  @return the corresponding string type. If <code>shType</code> is invalid,
	 *          the method returns <code>null</code>.
	 */
	public static String typeShortToString(short shType) {
		if (shType < 0 || shType > MAXTYPE)
			return null;
		return types[shType];
	}

	/**
	 *  Add a record to the pool.
	 *
	 *  @param record a STextStringRecord instance
	 */
	public static synchronized void add(STextStringRecord record) {
		if (last < MAXINDEX)
			last++;
		else
			last = 0;
		records[last] = record;
	}

	/**
	 *  Check if a string is recorded and retrieve its triplets.
	 *
	 *  @param  string the string to check
	 *
	 *  @return <code>null</code> if the string is not recorded in the pool;
	 *          otherwise, return the triplets associated with this string.
	 */
	public static short[] getTriplets(String string) {
		if (records[0] == null) // no records at all
			return null;
		if (string == null || string.length() < 1)
			return null;
		STextStringRecord rec;
		String str;
		short[] tri;
		int myLast = last;
		int hash = string.hashCode();
		for (int i = myLast; i >= 0; i--) {
			rec = records[i];
			if (hash == rec.hash && (tri = (short[]) rec.triRef.get()) != null && (str = (String) rec.strRef.get()) != null && string.equals(str)) {
				return tri;
			}
		}
		if (records[MAXINDEX] == null) // never recorded past myLast
			return null;
		for (int i = MAXINDEX; i > myLast; i--) {
			rec = records[i];
			if (hash == rec.hash && (tri = (short[]) rec.triRef.get()) != null && (str = (String) rec.strRef.get()) != null && string.equals(str)) {
				return tri;
			}
		}
		return null;
	}

	/**
	 *  Clear the pool. All elements of the pool are erased and any associated
	 *  memory is freed.
	 *
	 */
	public static synchronized void clear() {
		for (int i = 0; i <= MAXINDEX; i++) {
			STextStringRecord sr = records[i];
			if (sr == null)
				break;
			sr.hash = 0;
			sr.strRef.clear();
			sr.triRef.clear();
			records[i] = null;
		}
		last = MAXINDEX;
	}

}

Back to the top