using System;
using System.Collections;
using System.Collections.Generic;
namespace OSHttpServer
{
///
/// represents a HTTP input item. Each item can have multiple sub items, a sub item
/// is made in a HTML form by using square brackets
///
///
/// // becomes:
/// Console.WriteLine("Value: {0}", form["user"]["FirstName"].Value);
///
///
/// All names in a form SHOULD be in lowercase.
///
public class HttpInputItem : IHttpInput
{
/// Representation of a non-initialized .
public static readonly HttpInputItem Empty = new(string.Empty, true);
private readonly IDictionary _items = new Dictionary();
private readonly List _values = new();
private string _name;
private readonly bool _ignoreChanges;
///
/// Initializes an input item setting its name/identifier and value
///
/// Parameter name/id
/// Parameter value
public HttpInputItem(string name, string value)
{
Name = name;
Add(value);
}
private HttpInputItem(string name, bool ignore)
{
Name = name;
_ignoreChanges = ignore;
}
/// Creates a deep copy of the item specified
/// The item to copy
/// The function makes a deep copy of quite a lot which can be slow
public HttpInputItem(HttpInputItem item)
{
foreach (KeyValuePair pair in item._items)
_items.Add(pair.Key, pair.Value);
foreach (string value in item._values)
_values.Add(value);
_ignoreChanges = item._ignoreChanges;
_name = item.Name;
}
///
/// Number of values
///
public int Count
{
get { return _values.Count; }
}
///
/// Get a sub item
///
/// name in lower case.
/// if no item was found.
public HttpInputItem this[string name]
{
get
{
return _items.TryGetValue(name, out HttpInputItem hii) ? hii : Empty;
}
}
///
/// Name of item (in lower case).
///
public string Name
{
get { return _name; }
set { _name = value; }
}
///
/// Returns the first value, or null if no value exist.
///
public string Value
{
get {
return _values.Count == 0 ? null : _values[0];
}
set
{
if (_values.Count == 0)
_values.Add(value);
else
_values[0] = value;
}
}
///
/// Returns the last value, or null if no value exist.
///
public string LastValue
{
get
{
return _values.Count == 0 ? null : _values[^1];
}
}
///
/// Returns the list with values.
///
public IList Values
{
get { return _values.AsReadOnly(); }
}
///
/// Add another value to this item
///
/// Value to add.
/// Cannot add stuff to .
public void Add(string value)
{
if (value is null)
return;
if (_ignoreChanges)
throw new InvalidOperationException("Cannot add stuff to HttpInput.Empty.");
_values.Add(value);
}
///
/// checks if a sub-item exists (and has a value).
///
/// name in lower case
/// true if the sub-item exists and has a value; otherwise false.
public bool Contains(string name)
{
return _items.TryGetValue(name, out HttpInputItem hii) && hii.Value != null;
}
/// Returns a formatted representation of the instance with the values of all contained parameters
public override string ToString()
{
return ToString(string.Empty);
}
///
/// Outputs the string in a formatted manner
///
/// A prefix to append, used internally
/// produce a query string
public string ToString(string prefix, bool asQuerySting)
{
string name;
if (string.IsNullOrEmpty(prefix))
name = Name;
else
name = prefix + "[" + Name + "]";
if (asQuerySting)
{
string temp;
if (_values.Count == 0 && _items.Count > 0)
temp = string.Empty;
else
temp = name;
if (_values.Count > 0)
{
temp += '=';
foreach (string value in _values)
temp += value + ',';
temp = temp.Remove(temp.Length - 1, 1);
}
foreach (KeyValuePair item in _items)
temp += item.Value.ToString(name, true) + '&';
return _items.Count > 0 ? temp[..^1] : temp;
}
else
{
string temp = name;
if (_values.Count > 0)
{
temp += " = ";
foreach (string value in _values)
temp += value + ", ";
temp = temp.Remove(temp.Length - 2, 2);
}
temp += Environment.NewLine;
foreach (KeyValuePair item in _items)
temp += item.Value.ToString(name, false);
return temp;
}
}
#region IHttpInput Members
///
///
///
/// name in lower case
///
HttpInputItem IHttpInput.this[string name]
{
get
{
return _items.TryGetValue(name, out HttpInputItem hii) ? hii : Empty;
}
}
///
/// Add a sub item.
///
/// Can contain array formatting, the item is then parsed and added in multiple levels
/// Value to add.
/// Argument is null.
/// Cannot add stuff to .
public void Add(string name, string value)
{
if (name == null && value != null)
throw new ArgumentNullException("name");
if (name == null)
return;
if (_ignoreChanges)
throw new InvalidOperationException("Cannot add stuff to HttpInput.Empty.");
int pos = name.IndexOf('[');
if (pos != -1)
{
string name1 = name[..pos];
string name2 = HttpInput.ExtractOne(name);
if (!_items.TryGetValue(name1, out HttpInputItem it))
{
it = new HttpInputItem(name1, null);
_items.Add(name1, it);
}
it.Add(name2, value);
/*
HttpInputItem item = HttpInput.ParseItem(name, value);
// Add the value to an existing sub item
if (_items.ContainsKey(item.Name))
_items[item.Name].Add(item.Value);
else
_items.Add(item.Name, item);
*/
}
else
{
if (_items.TryGetValue(name, out HttpInputItem it2))
it2.Add(value);
else
_items.Add(name, new HttpInputItem(name, value));
}
}
#endregion
///
///Returns an enumerator that iterates through the collection.
///
///
///
///A that can be used to iterate through the collection.
///
///1
IEnumerator IEnumerable.GetEnumerator()
{
return _items.Values.GetEnumerator();
}
#region IEnumerable Members
///
///Returns an enumerator that iterates through a collection.
///
///
///
///An object that can be used to iterate through the collection.
///
///2
public IEnumerator GetEnumerator()
{
return _items.Values.GetEnumerator();
}
#endregion
///
/// Outputs the string in a formatted manner
///
/// A prefix to append, used internally
///
public string ToString(string prefix)
{
return ToString(prefix, false);
}
}
}