Click here to Skip to main content
15,894,646 members
Articles / Programming Languages / C#

Small LINQ to JSON Library

Rate me:
Please Sign up or sign in to vote.
4.96/5 (28 votes)
6 Dec 2011CPOL13 min read 81.6K   2K   79  
A small LinqToJSON library in C#, and how it works
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Article Source</title>
<link rel="stylesheet" type="text/css" href="Linq.Json_fichiers/CodeProject.css">
<!-- base href="http://www.codeproject.com/KB/linq/" -->
</head>
<body>
<!--
HTML for article "Small LINQ to JSON library" by Guillaume Ranslant
URL: http://www.codeproject.com/KB/linq/LinqToJSON.aspx
Copyright 2011 by Guillaume Ranslant
All formatting, additions and alterations Copyright © CodeProject, 1999-2011
-->



<p><b>Please choose 'View Source' in your browser to view the HTML, or File | Save to save this 
file to your hard drive for editing.</b></p>

<hr class="Divider subdue">
<div>




<!-- Start Article -->
<span id="ArticleContent">
<ul class="Download">
<li><a href="http://www.codeproject.com/KB/linq/LinqToJSON/LinqToJSON-src.zip">Download LinqToJSON-src - 35.29 KB</a></li>

<li><a href="http://www.codeproject.com/KB/linq/LinqToJSON/LinqToJSON-doc.zip">Download LinqToJSON-doc - 18.09 KB</a></li>

<li><a href="http://www.codeproject.com/KB/linq/LinqToJSON/LinqToJSON-assembly.zip">Download LinqToJSON-assembly - 6.23 KB</a></li>

<li><a href="http://www.codeproject.com/KB/linq/LinqToJSON/LinqToJSON-all.zip">Download LinqToJSON-all - 54.54 KB</a></li>
</ul>

<h2>Introduction</h2>

<p>Here you will find a .NET assembly, written in C# that allows reading and writing data formatted according to the <a href="http://www.json.org/">JSON standard</a> with features that mimic those of LinqToXML .</p>

<h2>Background</h2>

<p>I am very impressed by how easy it is to read and to write XML data 
with LinqToXml in .NET Framework 4.0, and I wanted something very 
similar for JSON. I search around a bit but could find nothing to my 
liking.</p>

<p>What I found was mostly JSON serializer/deserializer assemblies, 
which is not what I was interested in, and the few LinqToJSON helpers 
that I found have issues in my humble opinion:</p>

<ul>
<li>they rely on an underlying serializer</li>

<li>they do not seem to respect the specifications of JSON (this is mostly a consequence of using the serializer)</li>

<li>they do not offer writing JSON data the way LinqToXml offers writing XML data</li>
</ul>

<p>When I write “do not seem to respect the specifications of JSON” I 
mean that the serializer writes data that is not conforming to Json, as 
it is described in <a href="http://www.json.org/">www.json.org</a>. For instance, in the examples for the JSON libraries I have often seen something similar to:</p>

<pre>"Expiry" = new Date(1234567890)</pre>

<p>In my understanding of JSON, this is wrong, because the value <code>new Date(1234567890)</code> is neither</p>

<ul>
<li>a JSON string - it would be: <code>"<code>new Date(1234567890)</code>"</code></li>

<li><code></code>a JSON number, a JSON boolean value or JSON null – this is clear</li>

<li>a JSON array element – it would need the delimiters <code>[</code> and <code>]</code> and it would need to be a valid array element, which it is not</li>

<li>a JSON object - it would need the delimiters <code>{</code> and <code>}</code> and it would need to be a valid object member, which it is not</li>
</ul>

<p>A date can be written using the proper JSON formatting. Either as a 
string: “01/01/2011” or as an array [1, 1, 2011], or just as a number 
(the usual amount of seconds since ...), and choose a descriptive name. 
For instance:</p>

<pre>"ExpiryDate" : "01/01/2011" </pre>

<p>or</p>

<pre>"TestDates" : [[01,01,2011], [01,01,2012], [01,01,2013]]</pre>

<p>Of course, you have to convert the string or array or whatever 
afterwards to the actual 'Date' object, but this should not be an issue,
 especially as the .NET Framework already provides the necessary 
mechanisms to achieve that.</p>

<p>One more piece of advice: when you have decided over the 
representation of a non-trivial item (whether it's a 'Date' or binary 
data, or whatever), <strong>stick to it! </strong>Please.</p>

<p>Anyway, only one thing to do then: write my own library.</p>

<h2>Disclaimer</h2>

<p>I do not pretend that this LinqToJson library is the fastest, the 
leanest, the smallest or the best, I just pretend that it does exactly 
what I planned it to do, and that it does it well enough for me. And 
that in "only" 14KB. :)</p>

<p>Besides, please note that I am not dismissing using JSON serializers.
 My point is that I did not want/need a serializer. In other words, JSON
 serializers are not better or worse that my LinqToJSON library, they 
are just serving a different purpose, which wasn't fitting my needs. So,
 if you need a serializer, use one.</p>

<h2>Specifications (what I want)</h2>

<h3>Public objects</h3>

<p>Similar to <code>XDocument</code>, <code>XElement </code>and <code>XAttribute </code>from LinqToXml, I want to have:</p>

<ul>
<li><code>JDocument</code>, as the root object. Derived class of <code>JObject</code>, to allow directly using the properties and methods of <code>JObject</code>.</li>

<li>Generic containers</li>

<ul>
<li><code>JObject </code>and <code>JArray </code>hold values. They implement the interface <code>IJValue </code>and provide accessors to the JSON content.</li>
</ul>

<li>Specific containers</li>

<ul>
<li><code>JString </code>– I do not want to use the built-in type <code>System.String</code> directly, because conceptually a JSON string and a C# string are two different items. <code>JString</code> implements the interface <code>IJValue </code>and checks the validity of the given C# string, according to the JSON specifications.</li>

<li><code>JNumber </code>– Same story here as to why I do not use the type <code>Double </code>directly. This class implements the interface <code>IJValue </code>and checks the validity of the given C# string, regarding the JSON specifications for numbers.</li>

<li><code>JTrue</code>, <code>JFalse </code>and <code>JNull </code>- They also implement the interface <code>IJValue</code>. Again, I did not want to use the types <code>bool</code> and <code>object</code> directly. </li>
</ul>
</ul>

<h3>Reading JSON</h3>

<ol>
<li>Provide a static method <code>JDocument.Load()</code></li>

<li><code></code>Accessors will return</li>

<ol>
<li><code>IEnumerable&lt;IJvalue&gt;</code> when the calling object is a <code>JObject </code>or <code>Jarray</code>, to allow for Linq-style querying</li>

<li>a value of the appropriate type and content for the containers: 'bool' for <code>JTrue </code>and <code>JFalse</code>, 'double' for <code>JNumber</code>, 'string' for <code>JString </code>and 'object' for <code>JNull</code>.</li>
</ol>

<li>The generic type is <code>IJValue</code>. Filtering the values returned can be done over the type, using the keyword <em>is:</em></li>
</ol>

<pre lang="cs">if(value is JNumber).</pre>

<p>See the classes' description below and the code of the demo application for more details.</p>

<h4>code snippet</h4>

<pre lang="cs">// first, load a file
JDocument jDoc = JDocument.Load(filename);

// then, you can use LINQ to parse the document
var members = from member in jDoc.GetMembers() select member;
foreach (var member in members)
{
	// you can filter the values using their type
	if (member.Value is JString || member.Value is JNumber)
		// do something ...

	// you can filter the values using their type 
	if (member.Value is JObject)
	{
		JObject obj = member.Value as JObject;

		var names = from name in obj.GetNames() select name;
		foreach (var name in names)
		{
			// you can get an object with its name
			IJValue value = obj[name];

			if (value is JFalse || value is JTrue || value is JNull)
				// do something ...
		}

		var members = from member in obj.GetMembers() select member;
		foreach (var member in members)
		{
			Console.WriteLine("\t{0} : {1}", member.Name, member.Value.WriteAsJSON(0));
		}
	}
}</pre>

<h3>Writing JSON</h3>

<ol>
<li>Create a new <code>JDocument </code>instance</li>

<li>Add content in several ways.</li>

<ol>
<li>either in the constructors of the JSON values directly</li>

<li>or with the family of methods <code>Add()</code></li>
</ol>

<li><code></code>Each class implementing the interface <code>IJValue </code>provides
 a method returning a string that contains the correct representation. 
For most object I do not use ToString() because I want to keep the JSON 
string representation of this object independent of C#.</li>

<li>Provide a <code>JDocument </code>instance method <code>Save()</code></li>
</ol>

<p><code></code>See the classes' description below and the code of the demo application for more details.</p>

<h4>code snippet #1</h4>

<pre lang="cs">// example of JDocument written only through the constructor:
new JDocument(
	new JObjectMember("D'oh",
		new JObject(
			new JObjectMember("First Name", new JString("Homer")),
			new JObjectMember("Family Name", new JString("Simpson")),
			new JObjectMember("Is yellow?", new JTrue()),
			new JObjectMember("Children", 
				new JArray(
					new JString("Bart"),
					new JString("Lisa"),
					new JString("Maggie"))
			)
		)
	),
	new JObjectMember("never gets older",
		new JObject(
			new JObjectMember("First Name", new JString("Bart")),
			new JObjectMember("Family Name", new JString("Simpson"))
		)
	)
).Save("simpsons.json");</pre>

<p>There are several interesting aspects in the example above: </p>

<ul>
<li>except the final call to Save() all the data is created through constructors</li>

<li>the code can be presented in a very visual way, that mimics the structure of the JSON data</li>

<li>This JSON data can most likely not be deserialized, mostly because 
of the non-alphanumerical characters in the names of the object members</li>
</ul>

<h4>code snippet #2</h4>

<pre lang="cs">// you can create an empty object and add values
JObject obj = new JObject();
obj.Add("_number", new JNumber(-3.14));
obj.Add("_true", new JTrue()); // notice the use of JTrue 
obj.Add("_null", new JNull()); // notice the use of JNull

// you can create an empty array and add values
JArray arr = new JArray();
// ... either only one value
arr.Add(new JNumber("-15.64"));
// ... or more than one at once
// Notice that prefixing your strings with @ will help keeping them as valid JSON strings
arr.Add(new JString(@"Unicode: \u12A0"),
	new JString(@"\n\\test\""me:{}"));

JDocument doc = new JDocument(
	new JObjectMember("_false", new JFalse()),
	new JObjectMember("_false2", new JFalse())
); // the same name cannot be used twice!

// Add() has two forms:
// 1. with JObjectMember, you can give one or more
doc.Add(
	new JObjectMember("_array", arr),
	new JObjectMember("_string1", new JString("string1")),
);
// 2. directly give the name and the value
doc.Add("_obj", obj);

doc.Save(filename);</pre>

<h2>Interfaces and classes</h2>

<h3>Interfaces</h3>

<p><code>IJValue </code>– generic type representing all the different items a JSON value can be.</p>

<h3>Public classes</h3>

<p>Only the important, <strong>public</strong> methods and properties are listed here (the keyword <code>public </code>is voluntarily ommitted)</p>

<pre lang="cs">class JDocument : JObject
{
	JDocument()

	// Creates a new JDocument instance and copies the members from jObject
	JDocument(JObject jObject)

	// Creates a new JDocument instance and fills it with the jObjectMembers
	JDocument(params JObjectMember[] jObjectMembers)

	// Loads JSON data from a file. An exception is thrown if something goes wrong. The file has to contain nothing but JSON data.
	static JDocument Load(string uri)

	// Loads JSON data from a stream. An exception is thrown if something goes wrong. The stream has to contain nothing but JSON data from its current position to its end.
	static JDocument Load(StreamReader stream)

	// Parses the given text. Only JSON data is expected. An exception is thrown if something goes wrong, for instance if the JSON data is not properly formatted
	static JDocument Parse(string text)

	// Write the JDocument as JObject to the stream. The stream is not closed. An exception is thrown if something goes wrong.
	void Save(StreamWriter stream)

	// Saves the JSON data to a file.
	void Save(string uri)
}</pre>

<pre lang="cs">class JObject : IJValue
{
	// Creates an empty JSON object. Use one of the Add() functions to fill it.
	JObject()

	// Creates a JSON object pre-filled with the jObjectMembers. Further members can still be added using one of the Add() functions
	JObject(params JobjectMember[] jObjectMembers)

	// Returns the amount of members in the object
	int Count

	// Returns the object member value that is associated to 'name'
	IJValue this[string name]

	// Returns the object member value that is associated to 'name'
	IJValue GetValue(string name)

	// Returns a list of all the names stored in the object, without their values
	Ienumerable&lt;string&gt; GetNames()

	// Returns a list of all the values stored in the object, without their names
	IEnumerable&lt;IJValue&gt; GetValues()

	// Returns a list of all members stored in the object
	IEnumerable&lt;JObjectMember&gt; GetMembers()

	// Adds JSON object members (the values and their associated name are stored in a JObjectMember object) to the JSON object
	void Add(params JobjectMember[] jObjectMembers)

	// Adds one JSON object member to the object. A name cannot be added twice, it has to be unique in the object
	void Add(string name, IJValue jValue)
}
</pre>

<pre lang="cs">// data container class, used solely with JObject
class JObjectMember
{
	string Name // only the getter is public
	IJValue Value // only the getter is public
	JObjectMember(string name, IJValue value)
}
</pre>

<pre lang="cs">class JArray : IJValue
{
	// Creates an empty JSON array. Use one of the Add() functions to fill it.
	JArray()

	// Allows to set the initial capacity of the private value container. Use one of the Add() functions to fill it.
	JArray(int capacity)

	// Creates a JSON array pre-filled with the jValues. Use one of the Add() functions to fill it further.
	JArray(params IJValue[] jValues)

	// Returns the amount of elements in the array
	int Count

	// Returns the value stored at a specific index in the JArray
	IJValue this[int index]

	// Adds JSON values to the JSON array
	void Add(params IJValue[] jValues)

	// Returns a list of all elements stored in the JSON array
	IEnumerable&lt;IJValue&gt; GetValues()
}
</pre>

<pre lang="cs">class JNumber : IJValue
{
	double Content
	JNumber(double number)

	// 'text' is checked for validity according to the format description on &lt;a href="http://www.json.org/"&gt;www.json.org&lt;/a&gt;, an exception is thrown if an issue is found.
	JNumber(string text)
}
</pre>

<pre lang="cs">class JString:IJValue
{
	string Content

	// 'content' is checked for validity according to the format description on &lt;a href="http://www.json.org/"&gt;www.json.org&lt;/a&gt;, an exception is thrown if an issue is found.
	JString(string content)
}
</pre>

<pre lang="cs">class JNull : IJValue
{
	object Content // returns 'null'
}
</pre>

<pre lang="cs">class JFalse : IJValue
{
	bool Content // returns 'false'
}
</pre>

<pre lang="cs">class JTrue : IJValue
{
	bool Content // returns 'true'
}</pre>

<h3>Error handling</h3>

<p>Errors are notified solely through Exceptions, no error codes are returned.</p>

<h2>Demo Console Application</h2>

<p>The demo application is a bit of code thrown together to show several
 ways how to read and how to write JSON data using the assembly <strong>Ranslant.Linq.Json</strong>.</p>

<p>It also shows what would trigger errors when parsing or saving.</p>

<h2>Points of Interest</h2>

<h3>Source code</h3>

<p>I have tried to write code that is easy to understand yet efficient 
enough. I have avoided complex constructs and design patterns, because 
reading/writing JSON data is, in itself, not a complex task and 
therefore <strong>should not require complex code</strong>.<br>A few things are worth mentioning for the beginners in C#:</p>

<ul>
<li>Use of <strong>regular expressions</strong> (in <code>JNumber </code>for instance)</li>

<li><strong>Lazy creation</strong> of the data structures in <code>JObject </code>and <code>JArray </code>(<code>Add()</code>).The private data containers are initialized only once they are actually needed.</li>

<li>Use of an <strong>extension method</strong> (<code>ConsumeToken()</code> )</li>

<li>Use of an <strong>interface</strong> as generic base type (<code>IJValue</code>) , in combination with a simple <strong>factory pattern</strong> (<code>JParser.ParseValue()</code>)</li>

<li>Methods with <strong>variable number of arguments</strong> (e.g. Add<code>(params JObjectMember[] jObjectMembers</code><code>)</code>)</li>

<li>Use of <code><strong>IEnumerable&lt;T&gt;</strong></code> to benefit from <strong>Linq's</strong> querying power</li>
</ul>

<h3>About the parser</h3>

<p>There are hundreds of ways to write a text parser. It is my opinion 
that all of them are right as long as the text is properly parsed and 
you get the specified (and hopefully expected) result. Which means: my 
parser is good because it works. This is all I expect from it. </p>

<p>What I do here is simple. I parse the text looking for tokens. Those 
tokens represent delimiters for specific JSON value types. In other 
words a token or a set of tokens give away the expected value type. The 
text between those tokens is then checked for validity, which means I 
check if what I have actually represents the value type that I expect 
from the delimiters.</p>

<p>For instance, the delimiter '{' means I get a JSON object, and 
therefore everything between this delimiter and the corresponding 
closing delimiter ('}') should represent a JSON object and should 
therefore be written according to the grammatical rules (taken from <a href="http://www.json.org/">www.json.org</a>):</p>

<ul>
<li>a JSON <code>object </code>is <code>{}</code> or <code>{members}</code></li>

<li><code></code><code>members </code>are <code>pair </code>or <code>pair,members</code></li>

<li><code></code><code>pair </code>is <code>string<code><code></code>: value</code></code></li>

<li><code><code></code></code><code>string </code>is <code>""</code> or <code>"text"</code>, where <code>text </code>is …</li>

<li><code>value </code>is <code>object </code>or <code>array </code>or <code>string </code>or <code>number</code>, etc.</li>

<li>etc.</li>
</ul>

<p>What the parser does is follow these grammatical rules and report an error (by throwing an exception) when a rule is violated.</p>

<p>The way the string is technically parsed is by eating it up, so to 
speak, until it is empty. In other words, what is checked (whether 
tokens or content) is removed from the string to be parsed. Picture 
Pac-Man eating the pills in the maze, one pill at a time. Well, same 
thing here. :)</p>

<p>To achieve this I have chosen the following code structure:</p>

<ol>
<li>A class field containing the string that will be consumed. This 
field is not static since I want to stay thread safe. Each parsing step 
will modify this string, by removing the current token or content.</li>

<li>A set of parsing function, each one devoted to recognizing and/or 
filling one and only one type of value. Which one is called depends on 
the token found.</li>
</ol>

<p>I also considered the following alternative, where no string would be
 stored in the class, but rather passed from parse function to parse 
function:</p>

<pre lang="cs">ParseSomething(string textIn, out string textOut)</pre>

<p>With <code>textIn </code>being the string fed to the specific parse function and <code>textOut </code>being
 the string left after successful parsing. But I left this solution out,
 out of concerns for performance. Indeed, the recursive nature of JSON 
would have created situations where many string instances are necessary,
 requiring a lot of memory.</p>

<h3>Converting a base class to one of its derived classes</h3>

<p>The only specific difficulty of the parser was getting <code>ParseDocument(string)</code> to return a <code>JDocument </code>instance although it was actually parsing a <code>JObject</code>. <br>First I had the following code:</p>

<pre lang="cs">Document jDoc = (JDocument)ParseObject();</pre>

<p>It compiled, but threw an <code>InvalidCastException </code>(see <a href="http://msdn.microsoft.com/en-us/library/ms173105.aspx">http://msdn.microsoft.com/en-us/library/ms173105.aspx</a> and search for <strong>'Giraffe'</strong>).
 Indeed there is no equivalent to the C++ dynamic_cast in C#, and 
therefore you cannot convert a base class into one of its derived 
classes.</p>

<p>There are a few solutions for this issue:</p>

<ol>
<li><strong>SELECTED SOLUTION</strong>&nbsp;- Copy the members of the object returned by <code>ParseObject()</code> into the base of the <code>JDocument </code>object (using the constructor <code>JDocument(JObject jObject)</code>).
 This works well and requires on-ly very little code. Besides, this 
solution allows to generally create a JDocument out of any JObject, 
which can also be useful.</li>

<li>Encapsulate a JObject instance in JDocument. I found this to be not as nice, in terms of usability, as the first solution.</li>

<li>use the <code>CopyTo() </code>method of <code>JObject</code>. This uses reflection (and can therefore bring per-formance issues) and is not guaranteed to work according to <a href="http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/f7362ba9-48cd-49eb-9c65-d91355a3daee">http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/f7362ba9-48cd-49eb-9c65-d91355a3daee</a> </li>

<li>derive <code>JDocument </code>from <code>IJValue</code>. But then I loose inheriting the <code>JObject </code>methods and I would have needed to duplicate them in <code>JDocument</code>. This is definitely not clean.</li>
</ol>

<p>I found the <strong>solution #1</strong> to be the only clean and elegant solution, but it works only because in <code>JObject </code>the
 fields and properties (there's actually only one field) are accessed 
for writing only through public accessor functions (the <code>Add() </code>functions) that can be used freely in <code>JDocument </code>thanks to the inheritance.<br>This means that this pattern cannot be used generically.</p>

<p>Read the source code and the comments there for more information.</p>

<h2>Possible improvements</h2>

<h3>Source code cleanness and efficiency</h3>

<p>Obviously <strong>YOU</strong> would have written everything not just completely differently, but better. :D</p>

<p>More seriously, if you have suggestions concerning code cleanness (I 
am referring to clean code development) and efficiency of data and 
classes structures, then you are welcome, I always want to learn.</p>

<h3>Bug fixes</h3>

<p>I have not included the unit tests in the package, but I have tested 
the code thoroughly. Some issues may still have slipped me though, so if
 you find a bug, then you're welcome to report it (please be descriptive
 enough).<br>If you have a JSON file that cannot be read with this code:<br>1. Make sure the JSON text is properly formatted<br>2. Send me the file if possible and I will check</p>

<h3>Direct conversion</h3>

<p>It may turn out to be simpler to use <code>bool </code>for <code>JTrue </code>and <code>JFalse</code>, <code>double </code>for <code>JNumber</code>, <code>string </code>for <code>JString </code>and <code>object </code>for <code>JNull </code>more directly. I would still keep those classes because I still want to use the interface <code>IJValue</code>, but I could add converters so that the following could be written:</p>

<pre lang="cs">var myQuery = from value in jDocument.GetValues() select value;
foreach(IJValue value in myQuery)
{
if(value is JTrue || value is JFalse)
{
if(value)
{
// do something...
}
}
}</pre>

<p>Currently you have to write: <strong>if(value.Content)</strong>, which is not too much to ask for, but <strong>if(value) </strong>is more comfortable, and LINQ is all about comfort, isn't it?</p>

<p>Would it help?</p>

<h3>JSON to XML converter</h3>

<p>Not too sure about this one. The user could perhaps provide a schema,
 to provide the desired structure because I definitely do not want to 
impose an XML schema to the user. I'm not convince this is needed here 
though.</p>

<h3>Parser</h3>

<ul>
<li>Use more regular expressions? For instance, to chack the validity of a string content </li>

<li>Improve parsing speed? How? Why?</li>

<li>Support comments (delimiter: @"//") even though this is not defined in the JSON standard?</li>
</ul>

<h3>Generic</h3>

<ul>
<li>Improve memory footprint?</li>

<li>Have the classes that implement <code>IJValue </code>also implement <code>IDisposable</code>? Why?</li>
</ul>

<h2>History</h2>

<p>v 1.0 - 2011/11/23</p>

</span>
<!-- End Article -->




</div> 


<div style="padding: 0pt ! important; margin: 0pt ! important; float: none ! important; border: 0px solid rgb(255, 0, 0) ! important; background: none repeat scroll center center transparent ! important; width: auto ! important; height: auto ! important; display: block ! important; overflow: visible ! important; position: static ! important; text-indent: 0px ! important; z-index: auto ! important; max-width: none ! important; min-width: 0pt ! important; max-height: none ! important; min-height: 0pt ! important; left: auto ! important; top: auto ! important; bottom: auto ! important; right: auto ! important; line-height: 16px ! important; white-space: nowrap ! important;" class="linkscent-iconblock"></div><iframe src="javascript: void(0);" class="clueframe" style="padding: 0pt ! important; margin: 0pt ! important; float: none ! important; border: 0px solid rgb(255, 0, 0) ! important; background: none repeat scroll center center transparent ! important; width: 400px; height: 200px; display: none; overflow: visible ! important; position: fixed; text-indent: 0px ! important; z-index: 2147483637 ! important; max-width: none ! important; min-width: 0pt ! important; max-height: none ! important; min-height: 0pt ! important; left: -2000px; top: -2000px; bottom: auto ! important; right: auto ! important; line-height: 16px ! important; white-space: nowrap ! important;" name="ClueFrame" id="ClueFrame" frameborder="0" scrolling="no"></iframe></body></html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer IPG
Germany Germany
since 2010: C# with WPF
since 2002: C++ (MFC / QT)
since 1995: C, Java, Pascal


"if a drummer can do it, anobody can" - Bruce Dickinson

Comments and Discussions