/** * This will parse the stream and create a cmap object. * * @param input The CMAP stream to parse. * @return The parsed stream as a java object. * * @throws IOException If there is an error parsing the stream. */ public CMap Parse( Stream input ) { PushbackStream cmapStream = new PushbackStream( input ); CMap result = new CMap(); Object previousToken = null; Object token = null; while ( (token = ParseNextToken( cmapStream )) != null ) { if ( token is Operator ) { Operator op = (Operator)token; if ( op.op.Equals( BEGIN_CODESPACE_RANGE ) ) { IConvertible cosCount = (IConvertible)previousToken; for ( int j=0; j<cosCount.ToInt32(CultureInfo.InvariantCulture); j++ ) { byte[] startRange = (byte[])ParseNextToken( cmapStream ); byte[] endRange = (byte[])ParseNextToken( cmapStream ); CodespaceRange range = new CodespaceRange(); range.SetStart( startRange ); range.SetEnd( endRange ); result.AddCodespaceRange( range ); } } else if ( op.op.Equals( BEGIN_BASE_FONT_CHAR ) ) { IConvertible cosCount = (IConvertible)previousToken; for ( int j=0; j<cosCount.ToInt32(CultureInfo.InvariantCulture); j++ ) { byte[] inputCode = (byte[])ParseNextToken( cmapStream ); Object nextToken = ParseNextToken( cmapStream ); if ( nextToken is byte[] ) { byte[] bytes = (byte[])nextToken; String value = CreateStringFromBytes( bytes ); result.AddMapping( inputCode, value ); } else if ( nextToken is LiteralName ) { result.AddMapping( inputCode, ((LiteralName)nextToken).name ); } else { throw new IOException(MessageLocalization.GetComposedMessage("error.parsing.cmap.beginbfchar.expected.cosstring.or.cosname.and.not.1", nextToken)); } } } else if ( op.op.Equals( BEGIN_BASE_FONT_RANGE ) ) { IConvertible cosCount = (IConvertible)previousToken; for ( int j=0; j<cosCount.ToInt32(CultureInfo.InvariantCulture); j++ ) { byte[] startCode = (byte[])ParseNextToken( cmapStream ); byte[] endCode = (byte[])ParseNextToken( cmapStream ); Object nextToken = ParseNextToken( cmapStream ); IList<byte[]> array = null; byte[] tokenBytes = null; if ( nextToken is IList<byte[]> ) { array = (IList<byte[]>)nextToken; tokenBytes = array[0]; } else { tokenBytes = (byte[])nextToken; } String value = null; int arrayIndex = 0; bool done = false; while ( !done ) { if ( Compare( startCode, endCode ) >= 0 ) { done = true; } value = CreateStringFromBytes( tokenBytes ); result.AddMapping( startCode, value ); Increment( startCode ); if ( array == null ) { Increment( tokenBytes ); } else { arrayIndex++; if ( arrayIndex < array.Count ) { tokenBytes = array[arrayIndex]; } } } } } } previousToken = token; } return result; }
private Object ParseNextToken( PushbackStream pis ) { Object retval = null; int nextByte = pis.ReadByte(); //skip whitespace while ( nextByte == 0x09 || nextByte == 0x20 || nextByte == 0x0D || nextByte == 0x0A ) { nextByte = pis.ReadByte(); } switch ( nextByte ) { case '%': { //header operations, for now return the entire line //may need to smarter in the future StringBuilder buffer = new StringBuilder(); buffer.Append( (char)nextByte ); ReadUntilEndOfLine( pis, buffer ); retval = buffer.ToString(); break; } case '(': { StringBuilder buffer = new StringBuilder(); int stringByte = pis.ReadByte(); while ( stringByte != -1 && stringByte != ')' ) { buffer.Append( (char)stringByte ); stringByte = pis.ReadByte(); } retval = buffer.ToString(); break; } case '>': { int secondCloseBrace = pis.ReadByte(); if ( secondCloseBrace == '>' ) { retval = MARK_END_OF_DICTIONARY; } else { throw new IOException(MessageLocalization.GetComposedMessage("error.expected.the.end.of.a.dictionary")); } break; } case ']': { retval = MARK_END_OF_ARRAY; break; } case '[': { IList<Object> list = new List<Object>(); Object nextToken = ParseNextToken( pis ); while (!MARK_END_OF_ARRAY.Equals(nextToken) ) { list.Add( nextToken ); nextToken = ParseNextToken( pis ); } retval = list; break; } case '<': { int theNextByte = pis.ReadByte(); if ( theNextByte == '<' ) { IDictionary<String, Object> result = new Dictionary<String, Object>(); //we are reading a dictionary Object key = ParseNextToken( pis ); while ( key is LiteralName && !MARK_END_OF_DICTIONARY.Equals(key) ) { Object value = ParseNextToken( pis ); result[((LiteralName)key).name] = value; key = ParseNextToken( pis ); } retval = result; } else { //won't read more than 512 bytes int multiplyer = 16; int bufferIndex = -1; while ( theNextByte != -1 && theNextByte != '>' ) { int intValue = 0; if ( theNextByte >= '0' && theNextByte <= '9' ) { intValue = theNextByte - '0'; } else if ( theNextByte >= 'A' && theNextByte <= 'F' ) { intValue = 10 + theNextByte - 'A'; } else if ( theNextByte >= 'a' && theNextByte <= 'f' ) { intValue = 10 + theNextByte - 'a'; } else { throw new IOException(MessageLocalization.GetComposedMessage("error.expected.hex.character.and.not.char.thenextbyte.1", theNextByte)); } intValue *= multiplyer; if ( multiplyer == 16 ) { bufferIndex++; tokenParserByteBuffer[bufferIndex] = 0; multiplyer = 1; } else { multiplyer = 16; } tokenParserByteBuffer[bufferIndex]+= (byte)intValue; theNextByte = pis.ReadByte(); } byte[] finalResult = new byte[bufferIndex+1]; System.Array.Copy(tokenParserByteBuffer,0,finalResult, 0, bufferIndex+1); retval = finalResult; } break; } case '/': { StringBuilder buffer = new StringBuilder(); int stringByte = pis.ReadByte(); while ( !IsWhitespaceOrEOF( stringByte ) ) { buffer.Append( (char)stringByte ); stringByte = pis.ReadByte(); } retval = new LiteralName( buffer.ToString() ); break; } case -1: { //EOF return null; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { StringBuilder buffer = new StringBuilder(); buffer.Append( (char)nextByte ); nextByte = pis.ReadByte(); while ( !IsWhitespaceOrEOF( nextByte ) && (Char.IsDigit( (char)nextByte )|| nextByte == '.' ) ) { buffer.Append( (char)nextByte ); nextByte = pis.ReadByte(); } pis.Unread( nextByte ); String value = buffer.ToString(); if ( value.IndexOf( '.' ) >=0 ) { retval = double.Parse(value, CultureInfo.InvariantCulture); } else { retval = int.Parse(value, CultureInfo.InvariantCulture); } break; } default: { StringBuilder buffer = new StringBuilder(); buffer.Append( (char)nextByte ); nextByte = pis.ReadByte(); while ( !IsWhitespaceOrEOF( nextByte ) ) { buffer.Append( (char)nextByte ); nextByte = pis.ReadByte(); } retval = new Operator( buffer.ToString() ); break; } } return retval; }