001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.directory.api.util;
021
022
023/**
024 * Various Character methods are kept here.
025 *
026 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
027 */
028public final class Chars
029{
030    /** &lt;alpha> ::= [0x41-0x5A] | [0x61-0x7A] */
031    public static final boolean[] ALPHA =
032        {
033            false, false, false, false, false, false, false, false,
034            false, false, false, false, false, false, false, false,
035            false, false, false, false, false, false, false, false,
036            false, false, false, false, false, false, false, false,
037            false, false, false, false, false, false, false, false,
038            false, false, false, false, false, false, false, false,
039            false, false, false, false, false, false, false, false,
040            false, false, false, false, false, false, false, false,
041            false, true, true, true, true, true, true, true,
042            true, true, true, true, true, true, true, true,
043            true, true, true, true, true, true, true, true,
044            true, true, true, false, false, false, false, false,
045            false, true, true, true, true, true, true, true,
046            true, true, true, true, true, true, true, true,
047            true, true, true, true, true, true, true, true,
048            true, true, true, false, false, false, false, false
049    };
050    /** &lt;alpha-lower-case> ::= [0x61-0x7A] */
051    public static final boolean[] ALPHA_LOWER_CASE =
052        {
053            false, false, false, false, false, false, false, false,
054            false, false, false, false, false, false, false, false,
055            false, false, false, false, false, false, false, false,
056            false, false, false, false, false, false, false, false,
057            false, false, false, false, false, false, false, false,
058            false, false, false, false, false, false, false, false,
059            false, false, false, false, false, false, false, false,
060            false, false, false, false, false, false, false, false,
061            false, false, false, false, false, false, false, false,
062            false, false, false, false, false, false, false, false,
063            false, false, false, false, false, false, false, false,
064            false, false, false, false, false, false, false, false,
065            false, true, true, true, true, true, true, true,
066            true, true, true, true, true, true, true, true,
067            true, true, true, true, true, true, true, true,
068            true, true, true, false, false, false, false, false
069    };
070    /** &lt;alpha-upper-case> ::= [0x41-0x5A] */
071    public static final boolean[] ALPHA_UPPER_CASE =
072        {
073            false, false, false, false, false, false, false, false,
074            false, false, false, false, false, false, false, false,
075            false, false, false, false, false, false, false, false,
076            false, false, false, false, false, false, false, false,
077            false, false, false, false, false, false, false, false,
078            false, false, false, false, false, false, false, false,
079            false, false, false, false, false, false, false, false,
080            false, false, false, false, false, false, false, false,
081            false, true, true, true, true, true, true, true,
082            true, true, true, true, true, true, true, true,
083            true, true, true, true, true, true, true, true,
084            true, true, true, false, false, false, false, false,
085            false, false, false, false, false, false, false, false,
086            false, false, false, false, false, false, false, false,
087            false, false, false, false, false, false, false, false,
088            false, false, false, false, false, false, false, false,
089    };
090    /** &lt;alpha-digit> | &lt;digit> */
091    public static final boolean[] ALPHA_DIGIT =
092        {
093            false, false, false, false, false, false, false, false,
094            false, false, false, false, false, false, false, false,
095            false, false, false, false, false, false, false, false,
096            false, false, false, false, false, false, false, false,
097            false, false, false, false, false, false, false, false,
098            false, false, false, false, false, false, false, false,
099            true, true, true, true, true, true, true, true,
100            true, true, false, false, false, false, false, false,
101            false, true, true, true, true, true, true, true,
102            true, true, true, true, true, true, true, true,
103            true, true, true, true, true, true, true, true,
104            true, true, true, false, false, false, false, false,
105            false, true, true, true, true, true, true, true,
106            true, true, true, true, true, true, true, true,
107            true, true, true, true, true, true, true, true,
108            true, true, true, false, false, false, false, false
109    };
110    /** &lt;alpha> | &lt;digit> | '-' */
111    public static final boolean[] CHAR =
112        {
113            false, false, false, false, false, false, false, false,
114            false, false, false, false, false, false, false, false,
115            false, false, false, false, false, false, false, false,
116            false, false, false, false, false, false, false, false,
117            false, false, false, false, false, false, false, false,
118            false, false, false, false, false, true,  false, false,
119            true,  true,  true,  true,  true,  true,  true,  true,
120            true,  true,  false, false, false, false, false, false,
121            false, true,  true,  true,  true,  true,  true,  true,
122            true,  true,  true,  true,  true,  true,  true,  true,
123            true,  true,  true,  true,  true,  true,  true,  true,
124            true,  true,  true,  false, false, false, false, false,
125            false, true,  true,  true,  true,  true,  true,  true,
126            true,  true,  true,  true,  true,  true,  true,  true,
127            true,  true,  true,  true,  true,  true,  true,  true,
128            true,  true,  true,  false, false, false, false, false
129    };
130    /** '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' */
131    public static final boolean[] DIGIT =
132        {
133            false, false, false, false, false, false, false, false,
134            false, false, false, false, false, false, false, false,
135            false, false, false, false, false, false, false, false,
136            false, false, false, false, false, false, false, false,
137            false, false, false, false, false, false, false, false,
138            false, false, false, false, false, false, false, false,
139            true, true, true, true, true, true, true, true,
140            true, true, false, false, false, false, false, false,
141            false, false, false, false, false, false, false, false,
142            false, false, false, false, false, false, false, false,
143            false, false, false, false, false, false, false, false,
144            false, false, false, false, false, false, false, false,
145            false, false, false, false, false, false, false, false,
146            false, false, false, false, false, false, false, false,
147            false, false, false, false, false, false, false, false,
148            false, false, false, false, false, false, false, false
149    };
150    /** &lt;hex> ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66] */
151    public static final boolean[] HEX =
152        {
153            false, false, false, false, false, false, false, false,
154            false, false, false, false, false, false, false, false,
155            false, false, false, false, false, false, false, false,
156            false, false, false, false, false, false, false, false,
157            false, false, false, false, false, false, false, false,
158            false, false, false, false, false, false, false, false,
159            true, true, true, true, true, true, true, true,
160            true, true, false, false, false, false, false, false,
161            false, true, true, true, true, true, true, false,
162            false, false, false, false, false, false, false, false,
163            false, false, false, false, false, false, false, false,
164            false, false, false, false, false, false, false, false,
165            false, true, true, true, true, true, true, false,
166            false, false, false, false, false, false, false, false,
167            false, false, false, false, false, false, false, false,
168            false, false, false, false, false, false, false, false };
169
170
171    /**
172    * Test if the current character is equal to a specific character.
173    *
174    * @param chars The buffer which contains the data
175    * @param index
176    *            Current position in the buffer
177    * @param car The character we want to compare with the current buffer position
178    * @return <code>true</code> if the current character equals the given character.
179    */
180    public static boolean isCharASCII( char[] chars, int index, char car )
181    {
182        if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) || ( index >= chars.length ) )
183        {
184            return false;
185        }
186        else
187        {
188            return ( ( chars[index] == car ) ? true : false );
189        }
190    }
191
192
193    /**
194     * Test if the current character is equal to a specific character.
195     *
196     * @param string The String which contains the data
197     * @param index Current position in the string
198     * @param car The character we want to compare with the current string
199     *            position
200     * @return <code>true</code> if the current character equals the given
201     *         character.
202     */
203    public static boolean isCharASCII( String string, int index, char car )
204    {
205        if ( string == null )
206        {
207            return false;
208        }
209
210        int length = string.length();
211
212        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
213        {
214            return false;
215        }
216        else
217        {
218            return string.charAt( index ) == car;
219        }
220    }
221
222
223    /**
224     * Test if the current character is equal to a specific character.
225     *
226     * @param string The String which contains the data
227     * @param index Current position in the string
228     * @param car The character we want to compare with the current string
229     *            position
230     * @return <code>true</code> if the current character equals the given
231     *         character.
232     */
233    public static boolean isICharASCII( String string, int index, char car )
234    {
235        if ( string == null )
236        {
237            return false;
238        }
239
240        int length = string.length();
241
242        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
243        {
244            return false;
245        }
246        else
247        {
248            return ( ( string.charAt( index ) | 0x20 ) & car ) == car;
249        }
250    }
251
252
253    /**
254     * Test if the current character is equal to a specific character.
255     *
256     * @param bytes The String which contains the data
257     * @param index Current position in the string
258     * @param car The character we want to compare with the current string
259     *            position
260     * @return <code>true</code> if the current character equals the given
261     *         character.
262     */
263    public static boolean isICharASCII( byte[] bytes, int index, char car )
264    {
265        if ( bytes == null )
266        {
267            return false;
268        }
269
270        int length = bytes.length;
271
272        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
273        {
274            return false;
275        }
276        else
277        {
278            return ( ( bytes[index] | 0x20 ) & car ) == car;
279        }
280    }
281
282
283    /**
284     * Test if the current byte is an Alpha character :
285     * &lt;alpha> ::= [0x41-0x5A] | [0x61-0x7A]
286     *
287     * @param c The byte to test
288     *
289     * @return <code>true</code> if the byte is an Alpha
290     *         character
291     */
292    public static boolean isAlpha( byte c )
293    {
294        return ( ( c > 0 ) && ( c <= 127 ) && ALPHA[c] );
295    }
296
297
298    /**
299     * Test if the current character is an Alpha character :
300     * &lt;alpha> ::= [0x41-0x5A] | [0x61-0x7A]
301     *
302     * @param c The char to test
303     *
304     * @return <code>true</code> if the character is an Alpha
305     *         character
306     */
307    public static boolean isAlpha( char c )
308    {
309        return ( ( c > 0 ) && ( c <= 127 ) && ALPHA[c] );
310    }
311
312
313    /**
314     * Test if the current character is an Alpha character : &lt;alpha> ::=
315     * [0x41-0x5A] | [0x61-0x7A]
316     *
317     * @param bytes The buffer which contains the data
318     * @param index Current position in the buffer
319     * @return <code>true</code> if the current character is an Alpha
320     *         character
321     */
322    public static boolean isAlphaASCII( byte[] bytes, int index )
323    {
324        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
325        {
326            return false;
327        }
328        else
329        {
330            byte c = bytes[index];
331
332            if ( ( ( c | 0x7F ) != 0x7F ) || !ALPHA[c] )
333            {
334                return false;
335            }
336            else
337            {
338                return true;
339            }
340        }
341    }
342
343
344    /**
345     * Test if the current character is an Alpha character : &lt;alpha> ::=
346     * [0x41-0x5A] | [0x61-0x7A]
347     *
348     * @param chars The buffer which contains the data
349     * @param index Current position in the buffer
350     * @return <code>true</code> if the current character is an Alpha
351     *         character
352     */
353    public static boolean isAlphaASCII( char[] chars, int index )
354    {
355        if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) || ( index >= chars.length ) )
356        {
357            return false;
358        }
359        else
360        {
361            char c = chars[index];
362
363            if ( ( c > 127 ) || !ALPHA[c] )
364            {
365                return false;
366            }
367            else
368            {
369                return true;
370            }
371        }
372    }
373
374
375    /**
376     * Test if the current character is an Alpha character : &lt;alpha> ::=
377     * [0x41-0x5A] | [0x61-0x7A]
378     *
379     * @param string The string which contains the data
380     * @param index Current position in the string
381     * @return <code>true</code> if the current character is an Alpha
382     *         character
383     */
384    public static boolean isAlphaASCII( String string, int index )
385    {
386        if ( string == null )
387        {
388            return false;
389        }
390
391        int length = string.length();
392
393        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
394        {
395            return false;
396        }
397        else
398        {
399            char c = string.charAt( index );
400
401            if ( ( c > 127 ) || !ALPHA[c] )
402            {
403                return false;
404            }
405            else
406            {
407                return true;
408            }
409        }
410    }
411
412
413    /**
414     * Test if the current character is a lowercased Alpha character : <br/>
415     * &lt;alpha> ::= [0x61-0x7A]
416     *
417     * @param string The string which contains the data
418     * @param index Current position in the string
419     * @return <code>true</code> if the current character is a lower Alpha
420     *         character
421     */
422    public static boolean isAlphaLowercaseASCII( String string, int index )
423    {
424        if ( string == null )
425        {
426            return false;
427        }
428
429        int length = string.length();
430
431        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
432        {
433            return false;
434        }
435        else
436        {
437            char c = string.charAt( index );
438
439            if ( ( c > 127 ) || !ALPHA_LOWER_CASE[c] )
440            {
441                return false;
442            }
443            else
444            {
445                return true;
446            }
447        }
448    }
449
450
451    /**
452     * Test if the current character is a uppercased Alpha character : <br/>
453     * &lt;alpha> ::= [0x61-0x7A]
454     *
455     * @param string The string which contains the data
456     * @param index Current position in the string
457     * @return <code>true</code> if the current character is a lower Alpha
458     *         character
459     */
460    public static boolean isAlphaUppercaseASCII( String string, int index )
461    {
462        if ( string == null )
463        {
464            return false;
465        }
466
467        int length = string.length();
468
469        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
470        {
471            return false;
472        }
473        else
474        {
475            char c = string.charAt( index );
476
477            if ( ( c > 127 ) || !ALPHA_UPPER_CASE[c] )
478            {
479                return false;
480            }
481            else
482            {
483                return true;
484            }
485        }
486    }
487
488
489    /**
490     * Check if the current character is an 7 bits ASCII CHAR (between 0 and
491     * 127).
492     * &lt;char> ::= &lt;alpha> | &lt;digit>
493     *
494     * @param string The string which contains the data
495     * @param index Current position in the string
496     * @return The position of the next character, if the current one is a CHAR.
497     */
498    public static boolean isAlphaDigit( String string, int index )
499    {
500        if ( string == null )
501        {
502            return false;
503        }
504
505        int length = string.length();
506
507        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
508        {
509            return false;
510        }
511        else
512        {
513            char c = string.charAt( index );
514
515            if ( ( c > 127 ) || !ALPHA_DIGIT[c] )
516            {
517                return false;
518            }
519            else
520            {
521                return true;
522            }
523        }
524    }
525
526
527    /**
528     * Check if the current character is an 7 bits ASCII CHAR (between 0 and
529     * 127). &lt;char> ::= &lt;alpha> | &lt;digit> | '-'
530     *
531     * @param bytes The buffer which contains the data
532     * @param index Current position in the buffer
533     * @return The position of the next character, if the current one is a CHAR.
534     */
535    public static boolean isAlphaDigitMinus( byte[] bytes, int index )
536    {
537        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
538        {
539            return false;
540        }
541        else
542        {
543            byte c = bytes[index];
544
545            if ( ( ( c | 0x7F ) != 0x7F ) || !CHAR[c] )
546            {
547                return false;
548            }
549            else
550            {
551                return true;
552            }
553        }
554    }
555
556
557    /**
558     * Check if the current character is an 7 bits ASCII CHAR (between 0 and
559     * 127). &lt;char> ::= &lt;alpha> | &lt;digit> | '-'
560     *
561     * @param chars The buffer which contains the data
562     * @param index Current position in the buffer
563     * @return The position of the next character, if the current one is a CHAR.
564     */
565    public static boolean isAlphaDigitMinus( char[] chars, int index )
566    {
567        if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) || ( index >= chars.length ) )
568        {
569            return false;
570        }
571        else
572        {
573            char c = chars[index];
574
575            if ( ( c > 127 ) || !CHAR[c] )
576            {
577                return false;
578            }
579            else
580            {
581                return true;
582            }
583        }
584    }
585
586
587    /**
588     * Check if the current character is an 7 bits ASCII CHAR (between 0 and
589     * 127). &lt;char> ::= &lt;alpha> | &lt;digit> | '-'
590     *
591     * @param string The string which contains the data
592     * @param index Current position in the string
593     * @return The position of the next character, if the current one is a CHAR.
594     */
595    public static boolean isAlphaDigitMinus( String string, int index )
596    {
597        if ( string == null )
598        {
599            return false;
600        }
601
602        int length = string.length();
603
604        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
605        {
606            return false;
607        }
608        else
609        {
610            char c = string.charAt( index );
611
612            if ( ( c > 127 ) || !CHAR[c] )
613            {
614                return false;
615            }
616            else
617            {
618                return true;
619            }
620        }
621    }
622
623
624    /**
625     * Check if the current character is an 7 bits ASCII CHAR (between 0 and
626     * 127). &lt;char> ::= &lt;alpha> | &lt;digit> | '-'
627     *
628     * @param c The char we want to check
629     * @return The position of the next character, if the current one is a CHAR.
630     */
631    public static boolean isAlphaDigitMinus( char c )
632    {
633        return ( ( c & 0x007F ) == c ) && CHAR[c];
634    }
635
636
637    /**
638     * Test if the current character is a bit, ie 0 or 1.
639     *
640     * @param string
641     *            The String which contains the data
642     * @param index
643     *            Current position in the string
644     * @return <code>true</code> if the current character is a bit (0 or 1)
645     */
646    public static boolean isBit( String string, int index )
647    {
648        if ( string == null )
649        {
650            return false;
651        }
652
653        int length = string.length();
654
655        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
656        {
657            return false;
658        }
659        else
660        {
661            char c = string.charAt( index );
662            return ( ( c == '0' ) || ( c == '1' ) );
663        }
664    }
665
666
667    /**
668     * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
669     * '3' | '4' | '5' | '6' | '7' | '8' | '9'
670     *
671     * @param bytes The buffer which contains the data
672     * @return <code>true</code> if the current character is a Digit
673     */
674    public static boolean isDigit( byte[] bytes )
675    {
676        if ( ( bytes == null ) || ( bytes.length == 0 ) )
677        {
678            return false;
679        }
680        else
681        {
682            return ( ( ( ( bytes[0] | 0x7F ) != 0x7F ) || !DIGIT[bytes[0]] ) ? false : true );
683        }
684    }
685
686
687    /**
688     * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
689     * '3' | '4' | '5' | '6' | '7' | '8' | '9'
690     *
691     * @param car the character to test
692     *
693     * @return <code>true</code> if the character is a Digit
694     */
695    public static boolean isDigit( char car )
696    {
697        return ( car >= '0' ) && ( car <= '9' );
698    }
699
700
701    /**
702     * Test if the current byte is a digit &lt;digit> ::= '0' | '1' | '2' |
703     * '3' | '4' | '5' | '6' | '7' | '8' | '9'
704     *
705     * @param car the byte to test
706     *
707     * @return <code>true</code> if the character is a Digit
708     */
709    public static boolean isDigit( byte car )
710    {
711        return ( car >= '0' ) && ( car <= '9' );
712    }
713
714
715    /**
716     * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
717     * '3' | '4' | '5' | '6' | '7' | '8' | '9'
718     *
719     * @param bytes The buffer which contains the data
720     * @param index Current position in the buffer
721     * @return <code>true</code> if the current character is a Digit
722     */
723    public static boolean isDigit( byte[] bytes, int index )
724    {
725        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
726        {
727            return false;
728        }
729        else
730        {
731            return ( ( ( ( bytes[index] | 0x7F ) != 0x7F ) || !DIGIT[bytes[index]] ) ? false : true );
732        }
733    }
734
735
736    /**
737     * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
738     * '3' | '4' | '5' | '6' | '7' | '8' | '9'
739     *
740     * @param chars The buffer which contains the data
741     * @param index Current position in the buffer
742     * @return <code>true</code> if the current character is a Digit
743     */
744    public static boolean isDigit( char[] chars, int index )
745    {
746        if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) || ( index >= chars.length ) )
747        {
748            return false;
749        }
750        else
751        {
752            return ( ( ( chars[index] > 127 ) || !DIGIT[chars[index]] ) ? false : true );
753        }
754    }
755
756
757    /**
758     * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
759     * '3' | '4' | '5' | '6' | '7' | '8' | '9'
760     *
761     * @param string The string which contains the data
762     * @param index Current position in the string
763     * @return <code>true</code> if the current character is a Digit
764     */
765    public static boolean isDigit( String string, int index )
766    {
767        if ( string == null )
768        {
769            return false;
770        }
771
772        int length = string.length();
773
774        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
775        {
776            return false;
777        }
778        else
779        {
780            char c = string.charAt( index );
781            return ( ( ( c > 127 ) || !DIGIT[c] ) ? false : true );
782        }
783    }
784
785
786    /**
787     * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
788     * '3' | '4' | '5' | '6' | '7' | '8' | '9'
789     *
790     * @param chars The buffer which contains the data
791     * @return <code>true</code> if the current character is a Digit
792     */
793    public static boolean isDigit( char[] chars )
794    {
795        if ( ( chars == null ) || ( chars.length == 0 ) )
796        {
797            return false;
798        }
799        else
800        {
801            return ( ( ( chars[0] > 127 ) || !DIGIT[chars[0]] ) ? false : true );
802        }
803    }
804
805
806    /**
807     * Check if the current char is an Hex Char
808     * &lt;hex> ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66]
809     *
810     * @param c The char we want to check
811     * @return <code>true</code> if the current char is a Hex char
812     */
813    public static boolean isHex( char c )
814    {
815        return ( ( c | 0x007F ) == 0x007F ) && HEX[c];
816    }
817
818
819    /**
820     * Check if the current byte is an Hex Char
821     * &lt;hex> ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66]
822     *
823     * @param b The byte we want to check
824     * @return <code>true</code> if the current byte is a Hex byte
825     */
826    public static boolean isHex( byte b )
827    {
828        return ( ( b | 0x7F ) == 0x7F ) && HEX[b];
829    }
830
831
832    /**
833     * Check if the current character is an Hex Char &lt;hex> ::= [0x30-0x39] |
834     * [0x41-0x46] | [0x61-0x66]
835     *
836     * @param bytes The buffer which contains the data
837     * @param index Current position in the buffer
838     * @return <code>true</code> if the current character is a Hex Char
839     */
840    public static boolean isHex( byte[] bytes, int index )
841    {
842        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
843        {
844            return false;
845        }
846        else
847        {
848            byte c = bytes[index];
849
850            return ( ( ( c | 0x7F ) == 0x7F ) && HEX[c] );
851        }
852    }
853
854
855    /**
856     * Check if the current character is an Hex Char &lt;hex> ::= [0x30-0x39] |
857     * [0x41-0x46] | [0x61-0x66]
858     *
859     * @param chars The buffer which contains the data
860     * @param index Current position in the buffer
861     * @return <code>true</code> if the current character is a Hex Char
862     */
863    public static boolean isHex( char[] chars, int index )
864    {
865        if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) || ( index >= chars.length ) )
866        {
867            return false;
868        }
869        else
870        {
871            char c = chars[index];
872
873            return ( ( ( c | 0x007F ) == 0x007F ) && HEX[c] );
874        }
875    }
876
877
878    /**
879     * Check if the current character is an Hex Char &lt;hex> ::= [0x30-0x39] |
880     * [0x41-0x46] | [0x61-0x66]
881     *
882     * @param string The string which contains the data
883     * @param index Current position in the string
884     * @return <code>true</code> if the current character is a Hex Char
885     */
886    public static boolean isHex( String string, int index )
887    {
888        if ( string == null )
889        {
890            return false;
891        }
892
893        int length = string.length();
894
895        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
896        {
897            return false;
898        }
899        else
900        {
901            char c = string.charAt( index );
902
903            return ( ( ( c | 0x007F ) == 0x007F ) && HEX[c] );
904        }
905    }
906    
907    
908    /**
909     * Check if the current character is the ASCII character underscore 0x5F.
910     *
911     * @param bytes The buffer which contains the data
912     * @param index Current position in the buffer
913     * @return <code>true</code> if the current character is a the underscore
914     */
915    public static boolean isUnderscore( byte[] bytes, int index )
916    {
917        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
918        {
919            return false;
920        }
921        else
922        {
923            byte c = bytes[index];
924
925            return c == 0x5F;
926        }
927    }
928
929}