用于生成 Office 文件的 .NET 组件。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
8.9 KiB

8 years ago
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for Additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
namespace Npoi.Core.DDF
8 years ago
{
8 years ago
using Npoi.Core.Util;
8 years ago
using System;
using System.Collections;
using System.Collections.Generic;
8 years ago
using System.Text;
8 years ago
/// <summary>
/// This record is used whenever a escher record is encountered that
/// we do not explicitly support.
/// @author Glen Stampoultzis (glens at apache.org)
/// </summary>
public class UnknownEscherRecord : EscherRecord
{
private static byte[] NO_BYTES = new byte[0];
/** The data for this record not including the the 8 byte header */
private byte[] _thedata = NO_BYTES;
private List<EscherRecord> _childRecords = new List<EscherRecord>();
8 years ago
public UnknownEscherRecord() {
8 years ago
}
/// <summary>
/// This method deSerializes the record from a byte array.
/// </summary>
/// <param name="data"> The byte array containing the escher record information</param>
/// <param name="offset">The starting offset into data </param>
/// <param name="recordFactory">May be null since this is not a container record.</param>
/// <returns>The number of bytes Read from the byte array.</returns>
8 years ago
public override int FillFields(byte[] data, int offset, IEscherRecordFactory recordFactory) {
8 years ago
int bytesRemaining = ReadHeader(data, offset);
/*
* Modified by Zhang Zhang
8 years ago
* Have a check between avaliable bytes and bytesRemaining,
8 years ago
* take the avaliable length if the bytesRemaining out of range.
* July 09, 2010
*/
int avaliable = data.Length - (offset + 8);
8 years ago
if (bytesRemaining > avaliable) {
8 years ago
bytesRemaining = avaliable;
}
8 years ago
if (IsContainerRecord) {
8 years ago
int bytesWritten = 0;
_thedata = new byte[0];
offset += 8;
bytesWritten += 8;
8 years ago
while (bytesRemaining > 0) {
8 years ago
EscherRecord child = recordFactory.CreateRecord(data, offset);
int childBytesWritten = child.FillFields(data, offset, recordFactory);
bytesWritten += childBytesWritten;
offset += childBytesWritten;
bytesRemaining -= childBytesWritten;
ChildRecords.Add(child);
}
return bytesWritten;
}
8 years ago
else {
8 years ago
_thedata = new byte[bytesRemaining];
Array.Copy(data, offset + 8, _thedata, 0, bytesRemaining);
return bytesRemaining + 8;
}
}
/// <summary>
/// Writes this record and any contained records to the supplied byte
/// array.
/// </summary>
/// <param name="offset"></param>
/// <param name="data"></param>
/// <param name="listener">a listener for begin and end serialization events.</param>
/// <returns>the number of bytes written.</returns>
8 years ago
public override int Serialize(int offset, byte[] data, EscherSerializationListener listener) {
8 years ago
listener.BeforeRecordSerialize(offset, RecordId, this);
LittleEndian.PutShort(data, offset, Options);
LittleEndian.PutShort(data, offset + 2, RecordId);
int remainingBytes = _thedata.Length;
8 years ago
for (IEnumerator iterator = ChildRecords.GetEnumerator(); iterator.MoveNext();) {
8 years ago
EscherRecord r = (EscherRecord)iterator.Current;
remainingBytes += r.RecordSize;
}
LittleEndian.PutInt(data, offset + 4, remainingBytes);
Array.Copy(_thedata, 0, data, offset + 8, _thedata.Length);
int pos = offset + 8 + _thedata.Length;
8 years ago
for (IEnumerator iterator = ChildRecords.GetEnumerator(); iterator.MoveNext();) {
8 years ago
EscherRecord r = (EscherRecord)iterator.Current;
pos += r.Serialize(pos, data);
}
listener.AfterRecordSerialize(pos, RecordId, pos - offset, this);
return pos - offset;
}
/// <summary>
/// Gets the data.
/// </summary>
/// <value>The data.</value>
8 years ago
public byte[] Data {
8 years ago
get { return _thedata; }
}
/// <summary>
/// Returns the number of bytes that are required to Serialize this record.
/// </summary>
/// <value>Number of bytes</value>
8 years ago
public override int RecordSize {
8 years ago
get { return 8 + _thedata.Length; }
}
/// <summary>
/// Returns the children of this record. By default this will
/// be an empty list. EscherCotainerRecord is the only record
/// that may contain children.
/// </summary>
/// <value></value>
8 years ago
public override List<EscherRecord> ChildRecords {
8 years ago
get { return _childRecords; }
set { this._childRecords = value; }
}
/// <summary>
/// The short name for this record
/// </summary>
/// <value></value>
8 years ago
public override String RecordName {
8 years ago
get { return "Unknown 0x" + HexDump.ToHex(RecordId); }
}
/// <summary>
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
/// </summary>
/// <returns>
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
/// </returns>
8 years ago
public override String ToString() {
8 years ago
String nl = Environment.NewLine;
StringBuilder children = new StringBuilder();
8 years ago
if (ChildRecords.Count > 0) {
8 years ago
children.Append(" children: " + nl);
8 years ago
for (IEnumerator iterator = ChildRecords.GetEnumerator(); iterator.MoveNext();) {
8 years ago
EscherRecord record = (EscherRecord)iterator.Current;
children.Append(record.ToString());
children.Append(nl);
}
}
String theDumpHex = "";
8 years ago
try {
if (_thedata.Length != 0) {
8 years ago
theDumpHex = " Extra Data(" + _thedata.Length + "):" + nl;
theDumpHex += HexDump.Dump(_thedata, 0, 0);
}
}
8 years ago
catch (Exception) {
8 years ago
theDumpHex = "Error!!";
}
return this.GetType().Name + ":" + nl +
" isContainer: " + IsContainerRecord + nl +
" version: 0x" + HexDump.ToHex(Version) + nl +
" instance: 0x" + HexDump.ToHex(Instance) + nl +
" recordId: 0x" + HexDump.ToHex(RecordId) + nl +
" numchildren: " + ChildRecords.Count + nl +
theDumpHex +
children.ToString();
}
8 years ago
public override String ToXml(string tab) {
8 years ago
String theDumpHex = HexDump.ToHex(_thedata, 32);
StringBuilder builder = new StringBuilder();
builder.Append(tab).Append(FormatXmlRecordHeader(GetType().Name, HexDump.ToHex(RecordId), HexDump.ToHex(Version), HexDump.ToHex(Instance)))
.Append(tab).Append("\t").Append("<IsContainer>").Append(IsContainerRecord).Append("</IsContainer>\n")
.Append(tab).Append("\t").Append("<Numchildren>").Append(HexDump.ToHex(_childRecords.Count)).Append("</Numchildren>\n");
8 years ago
for (IEnumerator<EscherRecord> iterator = _childRecords.GetEnumerator(); iterator.MoveNext();) {
8 years ago
EscherRecord record = iterator.Current;
builder.Append(record.ToXml(tab + "\t"));
}
builder.Append(theDumpHex).Append("\n");
builder.Append(tab).Append("</").Append(GetType().Name).Append(">\n");
return builder.ToString();
}
8 years ago
8 years ago
/// <summary>
/// Adds the child record.
/// </summary>
/// <param name="childRecord">The child record.</param>
8 years ago
public void AddChildRecord(EscherRecord childRecord) {
8 years ago
ChildRecords.Add(childRecord);
}
}
}