/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2013-2014 Manuel Gaupp
*/
/**
* This class implements a parser for strings which are encoded using the
* Generic String Encoding Rules (GSER) defined in RFC 3641.
*
* @see <a href="http://tools.ietf.org/html/rfc3641">RFC 3641 -
* Generic String Encoding Rules (GSER) for ASN.1 Types
* </a>
*/
public class GSERParser
{
private int pos;
private int length;
/**
* Pattern to match an identifier defined in RFC 3641, section 3.4.
* <pre>
* An <identifier> conforms to the definition of an identifier in ASN.1
* notation (Clause 11.3 of X.680 [8]). It begins with a lowercase
* letter and is followed by zero or more letters, digits, and hyphens.
* A hyphen is not permitted to be the last character, nor is it to be
* followed by another hyphen. The case of letters in an identifier is
* always significant.
*
* identifier = lowercase *alphanumeric *(hyphen 1*alphanumeric)
* alphanumeric = uppercase / lowercase / decimal-digit
* uppercase = %x41-5A ; "A" to "Z"
* lowercase = %x61-7A ; "a" to "z"
* decimal-digit = %x30-39 ; "0" to "9"
* hyphen = "-"
* </pre>
*/
.compile("^([a-z]([A-Za-z0-9]|(-[A-Za-z0-9]))*)");
/**
* Pattern to match the identifier part (including the colon) of an
* IdentifiedChoiceValue defined in RFC 3641, section 3.12.
* <pre>
* IdentifiedChoiceValue = identifier ":" Value
* </pre>
*/
.compile("^([a-z]([A-Za-z0-9]|(-[A-Za-z0-9]))*:)");
/**
* Pattern to match "sp", containing zero, one or more space characters.
* <pre>
* sp = *%x20 ; zero, one or more space characters
* </pre>
*/
/**
* Pattern to match "msp", containing at least one space character.
* <pre>
* msp = 1*%x20 ; one or more space characters
* </pre>
*/
/**
* Pattern to match an Integer value.
*/
/**
* Pattern to match a GSER StringValue, defined in RFC 3641, section 3.2:
* <pre>
* Any embedded double quotes in the resulting UTF-8 character string
* are escaped by repeating the double quote characters.
*
* [...]
*
* StringValue = dquote *SafeUTF8Character dquote
* dquote = %x22 ; " (double quote)
* </pre>
*/
.compile("^(\"([^\"]|(\"\"))*\")");
/**
* Pattern to match the beginning of a GSER encoded Sequence.
* <pre>
* SequenceValue = ComponentList
* ComponentList = "{" [ sp NamedValue *( "," sp NamedValue) ] sp "}"
* </pre>
*/
/**
* Pattern to match the end of a GSER encoded Sequence.
* <pre>
* SequenceValue = ComponentList
* ComponentList = "{" [ sp NamedValue *( "," sp NamedValue) ] sp "}"
* </pre>
*/
/**
* Pattern to match the separator used in GSER encoded sequences.
*/
/**
* Creates a new GSER Parser.
*
* @param value the GSER encoded String value
*/
{
this.pos = 0;
}
/**
* Determines if the GSER String contains at least one character to be read.
*
* @return <code>true</code> if there is at least one remaining character or
* <code>false</code> otherwise.
*/
public boolean hasNext()
{
}
/**
* Determines if the remaining GSER String matches the provided pattern.
*
* @param pattern the pattern to search for
*
* @return <code>true</code> if the remaining string matches the pattern or
* <code>false</code> otherwise.
*/
{
if (!hasNext())
{
return false;
}
}
/**
* Returns the String matched by the first capturing group of the pattern.
* The parser advances past the input matched by the first capturing group.
*
* @param pattern the pattern to search for
*
* @return the String matched by the first capturing group of the pattern
*
* @throws GSERException
* If no match could be found
*/
{
{
}
else
{
throw new GSERException(msg);
}
}
/**
* Skips the input matched by the first capturing group.
*
* @param pattern the pattern to search for
*
* @throws GSERException
* If no match could be found
*/
{
{
}
else
{
throw new GSERException(msg);
}
}
/**
* Skips the input matching zero, one or more space characters.
*
* @return reference to this GSERParser
*
* @throws GSERException
* If no match could be found
*/
{
return this;
}
/**
* Skips the input matching one or more space characters.
*
* @return reference to this GSERParser
*
* @throws GSERException
* If no match could be found
*/
{
return this;
}
/**
* Skips the input matching the start of a sequence and subsequent space
* characters.
*
* @return reference to this GSERParser
*
* @throws GSERException
* If the input does not match the start of a sequence
*/
{
return this;
}
/**
* Skips the input matching the end of a sequence and preceding space
* characters.
*
* @return reference to this GSERParser
*
* @throws GSERException
* If the input does not match the end of a sequence
*/
{
return this;
}
/**
* Skips the input matching the separator pattern (",") and subsequenct space
* characters.
*
* @return reference to this GSERParser
*
* @throws GSERException
* If the input does not match the separator pattern.
*/
{
{
throw new GSERException(msg);
}
return this;
}
/**
* Returns the next element as a String.
*
* @return the input matching the String pattern
*
* @throws GSERException
* If the input does not match the string pattern.
*/
{
if (!hasNext(GSER_STRING))
{
throw new GSERException(msg);
}
// Strip leading and trailing dquotes; unescape double dquotes
}
/**
* Returns the next element as an Integer.
*
* @return the input matching the integer pattern
*
* @throws GSERException
* If the input does not match the integer pattern
*/
{
if (!hasNext(GSER_INTEGER))
{
throw new GSERException(msg);
}
}
/**
* Returns the next element as a BigInteger.
*
* @return the input matching the integer pattern
*
* @throws GSERException
* If the input does not match the integer pattern
*/
{
if (!hasNext(GSER_INTEGER))
{
throw new GSERException(msg);
}
}
/**
* Returns the identifier of the next NamedValue element.
*
* @return the identifier of the NamedValue element
*
* @throws GSERException
* If the input does not match the identifier pattern of a
* NamedValue
*/
{
if (!hasNext(GSER_IDENTIFIER))
{
throw new GSERException(msg);
}
{
throw new GSERException(msg);
}
skipMSP();
return identifier;
}
/**
* Return the identifier of the next IdentifiedChoiceValue element.
*
* @return the identifier of the IdentifiedChoiceValue element
*
* @throws GSERException
* If the input does not match the identifier pattern of an
* IdentifiedChoiceValue
*/
{
if (!hasNext(GSER_CHOICE_IDENTIFIER))
{
throw new GSERException(msg);
}
// Remove the colon at the end of the identifier
}
}