/*
Copyright 2007,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.documents;
using it.stefanochizzolini.clown.files;
using System;
using System.Collections;
using System.Collections.Generic;
// using System.IO;
// using System.Text;
namespace it.stefanochizzolini.clown.objects{
/**
<summary>Name tree [PDF:1.6:3.8.5].</summary>
*/
public abstract class NameTree<T>
: PdfObjectWrapper<PdfDictionary>,
IDictionary<string,T>
where T : PdfObjectWrapper
{
/*
TODO:IMPL A B-tree algorithm should be implemented to optimize the inner layout
of the name tree (better insertion/deletion performance). In this case, it would
be necessary to keep track of the modified tree nodes for incremental update.
*/
#region dynamic
#region constructors
public NameTree(
Document context
) : base(
context.File,
new PdfDictionary(
new PdfName[]
{ PdfName.Names },
new PdfDirectObject[]
{ new PdfArray() }
)
)
{}
public NameTree(
PdfDirectObject baseObject,
PdfIndirectObject container
) : base(
baseObject,
container
)
{}
#endregion
#region interface
#region public
public override object Clone(
Document context
)
{throw new NotImplementedException();}
#region IDictionary
public void Add(
string key,
T value
)
{throw new NotImplementedException();}
public bool ContainsKey(
string key
)
{throw new NotImplementedException();}
public ICollection<string> Keys
{get{throw new NotImplementedException();}}
public bool Remove(
string key
)
{throw new NotImplementedException();}
public T this[
string key
]
{
get
{
PdfDirectObject containerObject = BaseObject;
PdfDictionary parent = BaseDataObject;
while(true)
{
PdfDirectObject namesObject = parent[PdfName.Names];
if(namesObject == null) // Intermediate node.
{
PdfArray kids = (PdfArray)File.Resolve(parent[PdfName.Kids]);
int low = 0, high = kids.Count - 1;
while(true)
{
if(low > high)
return null;
int mid = (low + high) / 2;
PdfDirectObject kidObject = kids[mid];
PdfDictionary kid = (PdfDictionary)File.Resolve(kidObject);
PdfArray limits = (PdfArray)File.Resolve(kid[PdfName.Limits]);
// Compare to the lower limit!
int comparison = key.CompareTo(
((PdfString)limits[0]).Value
);
if(comparison < 0)
{high = mid - 1;}
else
{
// Compare to the upper limit!
comparison = key.CompareTo(
((PdfString)limits[1]).Value
);
if(comparison > 0)
{low = mid + 1;}
else
{
// Go down one level!
containerObject = kidObject; // NOTE: Node children MUST be indirectly referenced.
parent = kid;
break;
}
}
}
}
else // Leaf node.
{
if(namesObject is PdfReference)
{containerObject = namesObject;}
PdfArray names = (PdfArray)File.Resolve(namesObject);
int low = 0, high = names.Count;
while(true)
{
if(low > high)
return null;
int mid = (mid = ((low + high) / 2)) - (mid % 2);
int comparison = key.CompareTo(
((PdfString)names[mid]).Value
);
if(comparison < 0)
{high = mid - 2;}
else if(comparison > 0)
{low = mid + 2;}
else
{
// We got it!
return Wrap(
names[mid + 1],
((PdfReference)containerObject).IndirectObject
);
}
}
}
}
}
set
{throw new NotImplementedException();}
}
public bool TryGetValue(
string key,
out T value
)
{throw new NotImplementedException();}
public ICollection<T> Values
{get{throw new NotImplementedException();}}
#region ICollection
void ICollection<KeyValuePair<string,T>>.Add(
KeyValuePair<string,T> keyValuePair
)
{throw new NotImplementedException();}
public void Clear(
)
{throw new NotImplementedException();}
bool ICollection<KeyValuePair<string,T>>.Contains(
KeyValuePair<string,T> keyValuePair
)
{throw new NotImplementedException();}
public void CopyTo(
KeyValuePair<string,T>[] keyValuePairs,
int index
)
{throw new NotImplementedException();}
public int Count
{get{throw new NotImplementedException();}}
public bool IsReadOnly
{get{throw new NotImplementedException();}}
public bool Remove(
KeyValuePair<string,T> keyValuePair
)
{throw new NotImplementedException();}
#region IEnumerable<KeyValuePair<string,T>>
IEnumerator<KeyValuePair<string,T>> IEnumerable<KeyValuePair<string,T>>.GetEnumerator(
)
{throw new NotImplementedException();}
#region IEnumerable
IEnumerator IEnumerable.GetEnumerator(
)
{throw new NotImplementedException();}
#endregion
#endregion
#endregion
#endregion
#endregion
#region protected
/**
<summary>Wraps a base object within its corresponding high-level representation.</summary>
*/
protected abstract T Wrap(
PdfDirectObject baseObject,
PdfIndirectObject container
);
#endregion
#endregion
#endregion
}
}
|