/*
Copyright 2008 Stefano Chizzolini. http://clown.stefanochizzolini.it
Contributors:
* Stefano Chizzolini (original code developer, http://www.stefanochizzolini.it)
This file should be part of the source code distribution of "PDF Clown library"
(the Program): see the accompanying README files for more info.
This Program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later version.
This Program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY, either expressed or implied; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more details.
You should have received a copy of the GNU General Public License along with this
Program (see README files); if not, go to the GNU website (http://www.gnu.org/).
Redistribution and use, with or without modification, are permitted provided that such
redistributions retain the above copyright notice, license and disclaimer, along with
this list of conditions.
*/
using it.stefanochizzolini.clown.bytes;
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace it.stefanochizzolini.clown.objects{
/**
<summary>
PDF string object [PDF:1.6:3.2.3].
<para>A string object consists of a series of bytes.</para>
<para>String objects can be serialized in two ways:</para>
<ul>
<li>as a sequence of literal characters (plain form)</li>
<li>as a sequence of hexadecimal digits (hexadecimal form)</li>
</ul>
</summary>
*/
public class PdfString
: PdfAtomicObject<byte[]>
{
/*
NOTE: String objects are internally represented as unescaped sequences of bytes.
Escaping is applied on serialization only.
*/
#region types
/**
<summary>String serialization mode.</summary>
*/
public enum SerializationModeEnum
{
/**
Plain form.
*/
Literal,
/**
Hexadecimal form.
*/
Hex
};
#endregion
#region static
#region fields
private const byte BackspaceCode = 8;
private const byte CarriageReturnCode = 13;
private const byte FormFeedCode = 12;
private const byte HorizontalTabCode = 9;
private const byte LineFeedCode = 10;
private const byte HexLeftDelimiterCode = 60;
private const byte HexRightDelimiterCode = 62;
private const byte LiteralEscapeCode = 92;
private const byte LiteralLeftDelimiterCode = 40;
private const byte LiteralRightDelimiterCode = 41;
private static readonly Encoding Encoding = Encoding.GetEncoding("ISO-8859-1");
#endregion
#endregion
#region dynamic
#region fields
private SerializationModeEnum serializationMode = SerializationModeEnum.Literal;
#endregion
#region constructors
public PdfString(
)
{}
public PdfString(
byte[] value
)
{RawValue = value;}
public PdfString(
string value
)
{Value = value;}
public PdfString(
byte[] value,
SerializationModeEnum serializationMode
)
{
RawValue = value;
SerializationMode = serializationMode;
}
public PdfString(
string value,
SerializationModeEnum serializationMode
)
{
Value = value;
SerializationMode = serializationMode;
}
#endregion
#region interface
#region public
public override object Clone(
files.File context
)
{
// Shallow copy.
return this.MemberwiseClone();
}
/**
<summary>Gets/Sets the serialization mode.</summary>
*/
public SerializationModeEnum SerializationMode
{
get{return serializationMode;}
set{serializationMode = value;}
}
public override object Value
{
get
{return Encoding.GetString(RawValue);}
set
{RawValue = Encoding.GetBytes((string)value);}
}
#endregion
#region internal
internal override void WriteTo(
IOutputStream stream
)
{
stream.Write(
ToPdf(
RawValue,
serializationMode
)
);
}
#endregion
#region private
private byte[] ToPdf(
byte[] value,
SerializationModeEnum serializationMode
)
{
MemoryStream buffer = new MemoryStream();
switch(serializationMode)
{
case SerializationModeEnum.Literal:
buffer.WriteByte(LiteralLeftDelimiterCode);
/*
NOTE: Literal lexical conventions prescribe that the following reserved characters
are to be escaped when placed inside string character sequences:
- \n Line feed (LF)
- \r Carriage return (CR)
- \t Horizontal tab (HT)
- \b Backspace (BS)
- \f Form feed (FF)
- \( Left parenthesis
- \) Right parenthesis
- \\ Backslash
*/
for(
int index = 0;
index < value.Length;
index++
)
{
byte valueByte = value[index];
switch(valueByte)
{
case LineFeedCode:
buffer.WriteByte(LiteralEscapeCode); valueByte = 110; break;
case CarriageReturnCode:
buffer.WriteByte(LiteralEscapeCode); valueByte = 114; break;
case HorizontalTabCode:
buffer.WriteByte(LiteralEscapeCode); valueByte = 116; break;
case BackspaceCode:
buffer.WriteByte(LiteralEscapeCode); valueByte = 98; break;
case FormFeedCode:
buffer.WriteByte(LiteralEscapeCode); valueByte = 102; break;
case LiteralLeftDelimiterCode:
case LiteralRightDelimiterCode:
case LiteralEscapeCode:
buffer.WriteByte(LiteralEscapeCode); break;
}
buffer.WriteByte(valueByte);
}
buffer.WriteByte(LiteralRightDelimiterCode);
break;
case SerializationModeEnum.Hex:
buffer.WriteByte(HexLeftDelimiterCode);
for(
int index = 0;
index < value.Length;
index++
)
{buffer.Write(Encoding.GetBytes(value[index].ToString("X2")),0,2);}
buffer.WriteByte(HexRightDelimiterCode);
break;
default:
throw new NotImplementedException();
}
return buffer.ToArray();
}
#endregion
#endregion
#endregion
}
}
|