11/*
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.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
3131 */
3232package sun .util .locale ;
3333
34+ import java .text .ParsePosition ;
3435import java .util .ArrayList ;
3536import java .util .Collections ;
3637import java .util .HashMap ;
@@ -180,14 +181,10 @@ private LanguageTag() {
180181 * privateuse = "x" 1*("-" (1*8alphanum))
181182 *
182183 */
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 ) {
190186 StringTokenIterator itr ;
187+ var errorMsg = new StringBuilder ();
191188
192189 // Check if the tag is a legacy language tag
193190 String [] gfmap = LEGACY .get (LocaleUtils .toLowerString (languageTag ));
@@ -201,32 +198,38 @@ public static LanguageTag parse(String languageTag, ParseStatus sts) {
201198 LanguageTag tag = new LanguageTag ();
202199
203200 // 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 ) {
213211 String s = itr .current ();
214- sts . errorIndex = itr .currentStart ();
212+ pp . setErrorIndex ( itr .currentStart () );
215213 if (s .isEmpty ()) {
216- sts . errorMsg = "Empty subtag" ;
214+ errorMsg . append ( "Empty subtag" ) ;
217215 } else {
218- sts . errorMsg = "Invalid subtag: " + s ;
216+ errorMsg . append ( "Invalid subtag: " ). append ( s ) ;
219217 }
220218 }
219+
220+ if (!lenient && pp .getErrorIndex () != -1 ) {
221+ throw new IllformedLocaleException (errorMsg .toString (), pp .getErrorIndex ());
222+ }
223+
221224 return tag ;
222225 }
223226
224227 //
225228 // Language subtag parsers
226229 //
227230
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 ) {
230233 return false ;
231234 }
232235
@@ -236,15 +239,15 @@ private boolean parseLanguage(StringTokenIterator itr, ParseStatus sts) {
236239 if (isLanguage (s )) {
237240 found = true ;
238241 language = s ;
239- sts . parseLength = itr .currentEnd ();
242+ pp . setIndex ( itr .currentEnd () );
240243 itr .next ();
241244 }
242245
243246 return found ;
244247 }
245248
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 ) {
248251 return false ;
249252 }
250253
@@ -260,7 +263,7 @@ private boolean parseExtlangs(StringTokenIterator itr, ParseStatus sts) {
260263 extlangs = new ArrayList <>(3 );
261264 }
262265 extlangs .add (s );
263- sts . parseLength = itr .currentEnd ();
266+ pp . setIndex ( itr .currentEnd () );
264267 itr .next ();
265268
266269 if (extlangs .size () == 3 ) {
@@ -272,8 +275,8 @@ private boolean parseExtlangs(StringTokenIterator itr, ParseStatus sts) {
272275 return found ;
273276 }
274277
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 ) {
277280 return false ;
278281 }
279282
@@ -283,15 +286,15 @@ private boolean parseScript(StringTokenIterator itr, ParseStatus sts) {
283286 if (isScript (s )) {
284287 found = true ;
285288 script = s ;
286- sts . parseLength = itr .currentEnd ();
289+ pp . setIndex ( itr .currentEnd () );
287290 itr .next ();
288291 }
289292
290293 return found ;
291294 }
292295
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 ) {
295298 return false ;
296299 }
297300
@@ -301,15 +304,15 @@ private boolean parseRegion(StringTokenIterator itr, ParseStatus sts) {
301304 if (isRegion (s )) {
302305 found = true ;
303306 region = s ;
304- sts . parseLength = itr .currentEnd ();
307+ pp . setIndex ( itr .currentEnd () );
305308 itr .next ();
306309 }
307310
308311 return found ;
309312 }
310313
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 ) {
313316 return false ;
314317 }
315318
@@ -325,15 +328,16 @@ private boolean parseVariants(StringTokenIterator itr, ParseStatus sts) {
325328 variants = new ArrayList <>(3 );
326329 }
327330 variants .add (s );
328- sts . parseLength = itr .currentEnd ();
331+ pp . setIndex ( itr .currentEnd () );
329332 itr .next ();
330333 }
331334
332335 return found ;
333336 }
334337
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 ) {
337341 return false ;
338342 }
339343
@@ -351,16 +355,16 @@ private boolean parseExtensions(StringTokenIterator itr, ParseStatus sts) {
351355 s = itr .current ();
352356 if (isExtensionSubtag (s )) {
353357 sb .append (SEP ).append (s );
354- sts . parseLength = itr .currentEnd ();
358+ pp . setIndex ( itr .currentEnd () );
355359 } else {
356360 break ;
357361 }
358362 itr .next ();
359363 }
360364
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 ( "'" ) ;
364368 break ;
365369 }
366370
@@ -376,8 +380,9 @@ private boolean parseExtensions(StringTokenIterator itr, ParseStatus sts) {
376380 return found ;
377381 }
378382
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 ) {
381386 return false ;
382387 }
383388
@@ -395,15 +400,15 @@ private boolean parsePrivateuse(StringTokenIterator itr, ParseStatus sts) {
395400 break ;
396401 }
397402 sb .append (SEP ).append (s );
398- sts . parseLength = itr .currentEnd ();
403+ pp . setIndex ( itr .currentEnd () );
399404
400405 itr .next ();
401406 }
402407
403- if (sts . parseLength <= start ) {
408+ if (pp . getIndex () <= start ) {
404409 // need at least 1 private subtag
405- sts . errorIndex = start ;
406- sts . errorMsg = "Incomplete privateuse" ;
410+ pp . setErrorIndex ( start ) ;
411+ err . append ( "Incomplete privateuse" ) ;
407412 } else {
408413 privateuse = sb .toString ();
409414 found = true ;
@@ -414,13 +419,8 @@ private boolean parsePrivateuse(StringTokenIterator itr, ParseStatus sts) {
414419 }
415420
416421 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+
424424 // Legacy tags
425425 String potentialLegacy = tag .toLowerCase (Locale .ROOT );
426426 if (LEGACY .containsKey (potentialLegacy )) {
0 commit comments