1
1
/*
2
- * Copyright (c) 2010, 2023 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2010, 2025 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
31
31
*/
32
32
package sun .util .locale ;
33
33
34
+ import java .text .ParsePosition ;
34
35
import java .util .ArrayList ;
35
36
import java .util .Collections ;
36
37
import java .util .HashMap ;
@@ -180,14 +181,10 @@ private LanguageTag() {
180
181
* privateuse = "x" 1*("-" (1*8alphanum))
181
182
*
182
183
*/
183
- public static LanguageTag parse (String languageTag , ParseStatus sts ) {
184
- if (sts == null ) {
185
- sts = new ParseStatus ();
186
- } else {
187
- sts .reset ();
188
- }
189
-
184
+ public static LanguageTag parse (String languageTag , ParsePosition pp ,
185
+ boolean lenient ) {
190
186
StringTokenIterator itr ;
187
+ var errorMsg = new StringBuilder ();
191
188
192
189
// Check if the tag is a legacy language tag
193
190
String [] gfmap = LEGACY .get (LocaleUtils .toLowerString (languageTag ));
@@ -201,32 +198,38 @@ public static LanguageTag parse(String languageTag, ParseStatus sts) {
201
198
LanguageTag tag = new LanguageTag ();
202
199
203
200
// langtag must start with either language or privateuse
204
- if (tag .parseLanguage (itr , sts )) {
205
- tag .parseExtlangs (itr , sts );
206
- tag .parseScript (itr , sts );
207
- tag .parseRegion (itr , sts );
208
- tag .parseVariants (itr , sts );
209
- tag .parseExtensions (itr , sts );
210
- }
211
- tag .parsePrivateuse (itr , sts );
212
- if (!itr .isDone () && !sts .isError ()) {
201
+ if (tag .parseLanguage (itr , pp )) {
202
+ tag .parseExtlangs (itr , pp );
203
+ tag .parseScript (itr , pp );
204
+ tag .parseRegion (itr , pp );
205
+ tag .parseVariants (itr , pp );
206
+ tag .parseExtensions (itr , pp , errorMsg );
207
+ }
208
+ tag .parsePrivateuse (itr , pp , errorMsg );
209
+
210
+ if (!itr .isDone () && pp .getErrorIndex () == -1 ) {
213
211
String s = itr .current ();
214
- sts . errorIndex = itr .currentStart ();
212
+ pp . setErrorIndex ( itr .currentStart () );
215
213
if (s .isEmpty ()) {
216
- sts . errorMsg = "Empty subtag" ;
214
+ errorMsg . append ( "Empty subtag" ) ;
217
215
} else {
218
- sts . errorMsg = "Invalid subtag: " + s ;
216
+ errorMsg . append ( "Invalid subtag: " ). append ( s ) ;
219
217
}
220
218
}
219
+
220
+ if (!lenient && pp .getErrorIndex () != -1 ) {
221
+ throw new IllformedLocaleException (errorMsg .toString (), pp .getErrorIndex ());
222
+ }
223
+
221
224
return tag ;
222
225
}
223
226
224
227
//
225
228
// Language subtag parsers
226
229
//
227
230
228
- private boolean parseLanguage (StringTokenIterator itr , ParseStatus sts ) {
229
- if (itr .isDone () || sts . isError () ) {
231
+ private boolean parseLanguage (StringTokenIterator itr , ParsePosition pp ) {
232
+ if (itr .isDone () || pp . getErrorIndex () != - 1 ) {
230
233
return false ;
231
234
}
232
235
@@ -236,15 +239,15 @@ private boolean parseLanguage(StringTokenIterator itr, ParseStatus sts) {
236
239
if (isLanguage (s )) {
237
240
found = true ;
238
241
language = s ;
239
- sts . parseLength = itr .currentEnd ();
242
+ pp . setIndex ( itr .currentEnd () );
240
243
itr .next ();
241
244
}
242
245
243
246
return found ;
244
247
}
245
248
246
- private boolean parseExtlangs (StringTokenIterator itr , ParseStatus sts ) {
247
- if (itr .isDone () || sts . isError () ) {
249
+ private boolean parseExtlangs (StringTokenIterator itr , ParsePosition pp ) {
250
+ if (itr .isDone () || pp . getErrorIndex () != - 1 ) {
248
251
return false ;
249
252
}
250
253
@@ -260,7 +263,7 @@ private boolean parseExtlangs(StringTokenIterator itr, ParseStatus sts) {
260
263
extlangs = new ArrayList <>(3 );
261
264
}
262
265
extlangs .add (s );
263
- sts . parseLength = itr .currentEnd ();
266
+ pp . setIndex ( itr .currentEnd () );
264
267
itr .next ();
265
268
266
269
if (extlangs .size () == 3 ) {
@@ -272,8 +275,8 @@ private boolean parseExtlangs(StringTokenIterator itr, ParseStatus sts) {
272
275
return found ;
273
276
}
274
277
275
- private boolean parseScript (StringTokenIterator itr , ParseStatus sts ) {
276
- if (itr .isDone () || sts . isError () ) {
278
+ private boolean parseScript (StringTokenIterator itr , ParsePosition pp ) {
279
+ if (itr .isDone () || pp . getErrorIndex () != - 1 ) {
277
280
return false ;
278
281
}
279
282
@@ -283,15 +286,15 @@ private boolean parseScript(StringTokenIterator itr, ParseStatus sts) {
283
286
if (isScript (s )) {
284
287
found = true ;
285
288
script = s ;
286
- sts . parseLength = itr .currentEnd ();
289
+ pp . setIndex ( itr .currentEnd () );
287
290
itr .next ();
288
291
}
289
292
290
293
return found ;
291
294
}
292
295
293
- private boolean parseRegion (StringTokenIterator itr , ParseStatus sts ) {
294
- if (itr .isDone () || sts . isError () ) {
296
+ private boolean parseRegion (StringTokenIterator itr , ParsePosition pp ) {
297
+ if (itr .isDone () || pp . getErrorIndex () != - 1 ) {
295
298
return false ;
296
299
}
297
300
@@ -301,15 +304,15 @@ private boolean parseRegion(StringTokenIterator itr, ParseStatus sts) {
301
304
if (isRegion (s )) {
302
305
found = true ;
303
306
region = s ;
304
- sts . parseLength = itr .currentEnd ();
307
+ pp . setIndex ( itr .currentEnd () );
305
308
itr .next ();
306
309
}
307
310
308
311
return found ;
309
312
}
310
313
311
- private boolean parseVariants (StringTokenIterator itr , ParseStatus sts ) {
312
- if (itr .isDone () || sts . isError () ) {
314
+ private boolean parseVariants (StringTokenIterator itr , ParsePosition pp ) {
315
+ if (itr .isDone () || pp . getErrorIndex () != - 1 ) {
313
316
return false ;
314
317
}
315
318
@@ -325,15 +328,16 @@ private boolean parseVariants(StringTokenIterator itr, ParseStatus sts) {
325
328
variants = new ArrayList <>(3 );
326
329
}
327
330
variants .add (s );
328
- sts . parseLength = itr .currentEnd ();
331
+ pp . setIndex ( itr .currentEnd () );
329
332
itr .next ();
330
333
}
331
334
332
335
return found ;
333
336
}
334
337
335
- private boolean parseExtensions (StringTokenIterator itr , ParseStatus sts ) {
336
- if (itr .isDone () || sts .isError ()) {
338
+ private boolean parseExtensions (StringTokenIterator itr , ParsePosition pp ,
339
+ StringBuilder err ) {
340
+ if (itr .isDone () || pp .getErrorIndex () != -1 ) {
337
341
return false ;
338
342
}
339
343
@@ -351,16 +355,16 @@ private boolean parseExtensions(StringTokenIterator itr, ParseStatus sts) {
351
355
s = itr .current ();
352
356
if (isExtensionSubtag (s )) {
353
357
sb .append (SEP ).append (s );
354
- sts . parseLength = itr .currentEnd ();
358
+ pp . setIndex ( itr .currentEnd () );
355
359
} else {
356
360
break ;
357
361
}
358
362
itr .next ();
359
363
}
360
364
361
- if (sts . parseLength <= start ) {
362
- sts . errorIndex = start ;
363
- sts . errorMsg = "Incomplete extension '" + singleton + "'" ;
365
+ if (pp . getIndex () <= start ) {
366
+ pp . setErrorIndex ( start ) ;
367
+ err . append ( "Incomplete extension '" ). append ( singleton ). append ( "'" ) ;
364
368
break ;
365
369
}
366
370
@@ -376,8 +380,9 @@ private boolean parseExtensions(StringTokenIterator itr, ParseStatus sts) {
376
380
return found ;
377
381
}
378
382
379
- private boolean parsePrivateuse (StringTokenIterator itr , ParseStatus sts ) {
380
- if (itr .isDone () || sts .isError ()) {
383
+ private boolean parsePrivateuse (StringTokenIterator itr , ParsePosition pp ,
384
+ StringBuilder err ) {
385
+ if (itr .isDone () || pp .getErrorIndex () != -1 ) {
381
386
return false ;
382
387
}
383
388
@@ -395,15 +400,15 @@ private boolean parsePrivateuse(StringTokenIterator itr, ParseStatus sts) {
395
400
break ;
396
401
}
397
402
sb .append (SEP ).append (s );
398
- sts . parseLength = itr .currentEnd ();
403
+ pp . setIndex ( itr .currentEnd () );
399
404
400
405
itr .next ();
401
406
}
402
407
403
- if (sts . parseLength <= start ) {
408
+ if (pp . getIndex () <= start ) {
404
409
// need at least 1 private subtag
405
- sts . errorIndex = start ;
406
- sts . errorMsg = "Incomplete privateuse" ;
410
+ pp . setErrorIndex ( start ) ;
411
+ err . append ( "Incomplete privateuse" ) ;
407
412
} else {
408
413
privateuse = sb .toString ();
409
414
found = true ;
@@ -414,13 +419,8 @@ private boolean parsePrivateuse(StringTokenIterator itr, ParseStatus sts) {
414
419
}
415
420
416
421
public static String caseFoldTag (String tag ) {
417
- ParseStatus sts = new ParseStatus ();
418
- parse (tag , sts );
419
- // Illegal tags
420
- if (sts .errorMsg != null ) {
421
- throw new IllformedLocaleException (String .format ("Ill formed tag:" +
422
- " %s" , sts .errorMsg ));
423
- }
422
+ parse (tag , new ParsePosition (0 ), false );
423
+
424
424
// Legacy tags
425
425
String potentialLegacy = tag .toLowerCase (Locale .ROOT );
426
426
if (LEGACY .containsKey (potentialLegacy )) {
0 commit comments