if(c == '#')
{
try
{c = (getHex(stream.readUnsignedByte()) << 4) + getHex(stream.readUnsignedByte());}
catch(EOFException e)
{throw new FileFormatException("Unexpected EOF (malformed hexadecimal code in name object).",e,stream.getPosition());}
}
buffer.append((char)c);
}
}
catch(EOFException e)
{throw new FileFormatException("Unexpected EOF (malformed name object).",e,stream.getPosition());}
stream.skip(-1); // Recover the first byte after the current token.
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '-':
case '+': // Number [PDF:1.6:3.2.2] | Indirect reference.
switch(c)
{
case '.': // Decimal point.
tokenType = TokenTypeEnum.Real;
break;
default: // Digit or signum.
tokenType = TokenTypeEnum.Integer; // By default (it may be real).
break;
}
// Building the number...
buffer = new StringBuilder();
try
{
do
{
buffer.append((char)c);
c = stream.readUnsignedByte();
if(c == '.')
tokenType = TokenTypeEnum.Real;
else if(c < '0' || c > '9')
break;
} while(true);
}
catch(EOFException e)
{throw new FileFormatException("Unexpected EOF (malformed number object).",e,stream.getPosition());}
stream.skip(-1); // Recover the first byte after the current token.
break;
case '[': // Array (begin).
tokenType = TokenTypeEnum.ArrayBegin;
break;
case ']': // Array (end).
tokenType = TokenTypeEnum.ArrayEnd;
break;
case '<': // Dictionary (begin) | Hexadecimal string.
try
{c = stream.readUnsignedByte();}
catch(EOFException e)
{throw new FileFormatException("Unexpected EOF (isolated opening angle-bracket character).",e,stream.getPosition());}
// Is it a dictionary (2nd angle bracket [PDF:1.6:3.2.6])?
if(c == '<')
{
tokenType = TokenTypeEnum.DictionaryBegin;
break;
}
// Hexadecimal string (single angle bracket [PDF:1.6:3.2.3]).
tokenType = TokenTypeEnum.Hex;
// [FIX:0.0.4:4] It skipped after the first hexadecimal character, missing it.
buffer = new StringBuilder();
try
{
while(c != '>') // NOT string end.
{
buffer.append((char)c);
c = stream.readUnsignedByte();
}
}
catch(EOFException e)
{throw new FileFormatException("Unexpected EOF (malformed hex string).",e,stream.getPosition());}
break;
case '>': // Dictionary (end).
try
{c = stream.readUnsignedByte();}
catch(EOFException e)
{throw new FileFormatException("Unexpected EOF (malformed dictionary).",e,stream.getPosition());}
if(c != '>')
throw new FileFormatException("Malformed dictionary.",stream.getPosition());
tokenType = TokenTypeEnum.DictionaryEnd;
break;
case '%': // Comment.
tokenType = TokenTypeEnum.Comment;
// Skipping comment content...
try
{
do
{c = stream.readUnsignedByte();}
while(!isEOL(c));
}
catch(EOFException e)
{/* Let it go. */}
break;
case '(': // Literal string.
tokenType = TokenTypeEnum.Literal;
buffer = new StringBuilder();
int level = 0;
try
{
while(true)
{
c = stream.readUnsignedByte();
if(c == '(')
level++;
else if(c == ')')
level--;
else if(c == '\\')
{
boolean lineBreak = false;
c = stream.readUnsignedByte();
switch(c)
{
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case 't':
c = '\t';
break;
case 'b':
c = '\b';
break;
case 'f':
c = '\f';
break;
case '(':
case ')':
case '\\':
break;
case '\r':
lineBreak = true;
c = stream.readUnsignedByte();
if(c != '\n')
stream.skip(-1);
break;
case '\n':
lineBreak = true;
break;
default:
{
// Is it outside the octal encoding?
if(c < '0' || c > '7')
break;
// Octal [PDF:1.6:3.2.3].
int octal = c - '0';
c = stream.readUnsignedByte();
// Octal end?
if(c < '0' || c > '7')
{c = octal; stream.skip(-1); break;}
octal = (octal << 3) + c - '0';
c = stream.readUnsignedByte();
// Octal end?
if(c < '0' || c > '7')
{c = octal; stream.skip(-1); break;}
octal = (octal << 3) + c - '0';
c = octal & 0xff;
break;
}
}
if(lineBreak)
continue;
}
else if(c == '\r')
{
c = stream.readUnsignedByte();
if(c != '\n')
{c = '\n'; stream.skip(-1);}
}
if(level == -1)
break;
buffer.append((char)c);
}
}
catch(EOFException e)
{throw new FileFormatException("Unexpected EOF (malformed literal string).",e,stream.getPosition());}
break;
default: // Keyword.
tokenType = TokenTypeEnum.Keyword;
buffer = new StringBuilder();