public HoleList(
     IntervalInt32 range
     )
 {
     range_      = range;
     filledArea_ = new SortedList <Int32, Int32>();
 }
 public PayloadPair(
     IntervalInt32 offsetInterval
     , byte[] payload
     )
 {
     OffsetInterval = offsetInterval;
     Payload        = payload;
 }
Exemplo n.º 3
0
		/// <summary>
		/// 
		/// </summary>
		/// <param name="nonTerminal"></param>
		/// <param name="input">The input string.</param>
		/// <param name="substring">The substring interval.</param>
		/// <returns></returns>
		private bool ApplyAny(INonTerminal nonTerminal, string input, IntervalInt32 substring)
		{
			#region Contract
			Contract.Requires<ArgumentNullException>(nonTerminal != null);
			Contract.Requires<ArgumentNullException>(input != null);
			#endregion
			var productionRules = GetProductionRules(nonTerminal);
			foreach(var rule in productionRules)
			{
				bool success = Apply(rule, input, substring);
				if (success) return true;
			}
			return false;
		}
            private static int CompareIntervalsForSort(
                IntervalInt32 lhs
                , IntervalInt32 rhs
                )
            {
                var diff = lhs.Minimum - rhs.Minimum;

                if (diff != 0)
                {
                    return(diff);
                }

                return(lhs.Maximum - rhs.Maximum);
            }
Exemplo n.º 5
0
		/// <summary>
		/// Applies the specified rule to the specified part of the input.
		/// </summary>
		/// <param name="rule">The rule to apply.</param>
		/// <param name="input">The input string.</param>
		/// <param name="substring">The substring interval.</param>
		/// <returns><see langword="true"/> when the rule could be applied;
		/// otherwise, <see langword="false"/>.</returns>
		private bool Apply(IProductionRule rule, string input, IntervalInt32 substring)
		{
			#region Contract
			Contract.Requires<ArgumentNullException>(rule != null);
			Contract.Requires<ArgumentNullException>(input != null);
			// TODO: The rule must be context-free. That is: must have exactly one symbol, a non-terminal, on the left-hand side.
			#endregion

			foreach(IntervalInt32[] partition in GetPartitions(substring, rule.Right.Count))
			{
				// First try all terminals.
				bool terminalsMatch = true;
				for (int i = 0; i < rule.Right.Count; i++)
				{
					if (!(rule.Right[i] is ITerminal))
						continue;
					ITerminal terminal = (ITerminal)rule.Right[i];
					if (!terminal.Match(input, partition[i].Start, (int)partition[i].Length))
					{
						terminalsMatch = false;
						break;
					}
				}
				if (!terminalsMatch)
					continue;

				// Then recursively try all non-terminals.
				bool nonTerminalsMatch = true;
				for (int i = 0; i < rule.Right.Count; i++)
				{
					if (!(rule.Right[i] is INonTerminal))
						continue;
					INonTerminal nonTerminal = (INonTerminal)rule.Right[i];
					if (!ApplyAny(nonTerminal, input, partition[i]))
					{
						nonTerminalsMatch = false;
						break;
					}
						
				}
				if (!nonTerminalsMatch)
					continue;

				return true;
			}

			return false;
		}
Exemplo n.º 6
0
		/// <summary>
		/// Generates the next partition.
		/// </summary>
		/// <param name="input">The input substring interval.</param>
		/// <param name="parts">The array of parts.</param>
		/// <returns><see langword="true"/> when the next partition was successfully generated;
		/// otherwise, <see langword="false"/> when there are no more partitions.</returns>
		private bool GenerateNextPartition(IntervalInt32 input, IntervalInt32[] parts)
		{
			if (parts.Length == 0)
				return false;

			// 0, 0, 3
			// 0, 1, 2
			// 0, 2, 1
			// 0, 3, 0
			// 1, 0, 2
			// 1, 1, 1
			// 1, 2, 0
			// 2, 0, 1
			// 2, 1, 0
			// 3, 0, 0

			// 0, 0, 0, 2
			// 0, 0, 1, 1
			// 0, 0, 2, 0
			// 0, 1, 0, 1
			// 0, 1, 1, 0
			// 0, 2, 0, 0
			// 1, 0, 0, 1
			// 1, 0, 1, 0
			// 1, 1, 0, 0
			// 2, 0, 0, 0

			// Find the last index that has a non-zero value.
			// By definition, the last non-zero index cannot be incremented any further.
			int lastIndex = parts.Length - 1;
			while (parts[lastIndex].Length == 0)
				lastIndex--;

			// The last non-zero index contains the number of remaining characters in the input.
			long remainder = parts[lastIndex].Length;

			if (lastIndex == 0 || remainder == 0)
				// We've reached the end.
				return false;

			// Increment the index before the last non-zero value,
			// and decrement the remainder.
			lastIndex -= 1;
			parts[lastIndex] = IntervalInt32.WithLength(parts[lastIndex].Start, parts[lastIndex].Length + 1);
			remainder -= 1;

			// Set all following substrings to zero, except the last.
			for (int i = lastIndex + 1; i < parts.Length - 1; i++)
			{
				parts[i] = IntervalInt32.Empty;
			}
			// The last part is set to the number of remaining characters.
			parts[parts.Length - 1] = IntervalInt32.WithLength((int)(input.Length - remainder), remainder);

			return true;
		}
Exemplo n.º 7
0
		/// <summary>
		/// Generates the first partition.
		/// </summary>
		/// <param name="input">The input substring interval.</param>
		/// <param name="partsCount">The number of parts.</param>
		/// <returns>An array of parts.</returns>
		private IntervalInt32[] GenerateFirstPartition(IntervalInt32 input, int partsCount)
		{
			#region Contract
			Contract.Requires<ArgumentNullException>(partsCount >= 0);
			#endregion

			IntervalInt32[] output = new IntervalInt32[partsCount];
			// NOTE: All partitions are set to empty by default.
			
			// The last substring is set to the remaining string (the whole string).
			output[output.Length - 1] = input;

			return output;
		}
Exemplo n.º 8
0
		private IEnumerable<IntervalInt32[]> GetPartitions(IntervalInt32 input, int partsCount)
		{
			IntervalInt32[] parts = GenerateFirstPartition(input, partsCount);
			do
			{
				yield return parts;
			} while (GenerateNextPartition(input, parts));
		}
            public void Fill(
                IntervalInt32 interval
                )
            {
                if (!range_.Contains(interval))
                {
                    throw new ArgumentOutOfRangeException("");
                }

                var shouldAddNewInterval = true;

                IntervalInt32 ltInterval = default(IntervalInt32);
                Int32         ltIntervalMin;
                var           isLtIntervalMinFound = filledArea_.FindKeyLessThenOrEqualTo(interval.Minimum, out ltIntervalMin);

                if (isLtIntervalMinFound)
                {
                    var ltIntervalMax = filledArea_[ltIntervalMin];
                    ltInterval = new IntervalInt32(ltIntervalMin, ltIntervalMax);
                    if (ltInterval.IntersectsWith(interval))
                    {
                        //Error! Discard all information of the original packet.
                        throw new ArgumentOutOfRangeException("");
                    }

                    if (interval.Minimum - ltInterval.Maximum == 1)
                    {
                        filledArea_[ltInterval.Minimum] = interval.Maximum;
                        interval = new IntervalInt32(ltInterval.Minimum, interval.Maximum);

                        shouldAddNewInterval = false;
                    }
                }

                IntervalInt32 gtInterval = default(IntervalInt32);
                Int32         gtIntervalMin;
                var           isGtIntervalMinFound = filledArea_.FindKeyGreaterThenOrEqualTo(interval.Maximum, out gtIntervalMin);

                if (isGtIntervalMinFound)
                {
                    var gtIntervalMax = filledArea_[gtIntervalMin];
                    gtInterval = new IntervalInt32(gtIntervalMin, gtIntervalMax);
                    if (gtInterval.IntersectsWith(interval))
                    {
                        //Error! Discard all information of the original packet.
                        throw new ArgumentOutOfRangeException("");
                    }

                    if (gtInterval.Minimum - interval.Maximum == 1)
                    {
                        filledArea_.Remove(interval.Minimum);
                        filledArea_.Remove(gtInterval.Minimum);
                        filledArea_.Add(interval.Minimum, gtInterval.Maximum);

                        shouldAddNewInterval = false;
                    }
                }

                if (shouldAddNewInterval)
                {
                    filledArea_.Add(interval.Minimum, interval.Maximum);
                }
            }
            public IpV4Packet Consume(
                IpV4Packet packet
                )
            {
                IpV4Packet mergedPacket = null;

                if (packet == null)
                {
                    throw new ArgumentNullException("packet");
                }

                var header = packet.Header;

                var isNotFragmented = false;

                var offsetInterval = default(IntervalInt32);

                switch (header.FragmentFlags)
                {
                case 0x00:
                    if (header.FragmentOffset > 0)
                    {
                        if (lastFragmentHeader_ != null)
                        {
                            throw new Exception("Duplicated last fragment!");
                        }
                        lastFragmentHeader_ = packet.Header;

                        offsetInterval = new IntervalInt32(header.FragmentOffset, holeList_.Range.Maximum);
                    }
                    else
                    {
                        isNotFragmented = true;
                    }
                    break;

                case 0x01:
                    if (header.FragmentOffset == 0)
                    {
                        if (firstFragmentHeader_ != null)
                        {
                            throw new Exception("Duplicated first fragment!");
                        }
                        else
                        {
                            firstFragmentHeader_ = packet.Header;
                        }
                    }

                    if ((header.PayloadLength & ((1 << 3) - 1)) != 0)
                    {
                        throw new FormatException("The length of non-final fragments must be multiple of 8.");
                    }

                    offsetInterval = new IntervalInt32(header.FragmentOffset, (header.PayloadLength > 0 ? header.PayloadLength - 1 : 0));
                    break;

                case 0x02:
                    isNotFragmented = true;
                    break;

                default:
                    throw new FormatException("The fragment flag has an invalid value.");
                }

                if (isNotFragmented)
                {
                    mergedPacket = packet;
                    Reset();
                }
                else
                {
                    try {
                        holeList_.Fill(offsetInterval);
                        payloadMap_.Add(header.FragmentOffset, packet.Payload);

                        if (holeList_.HasNoMoreHoles)
                        {
                            if (lastFragmentHeader_ == null || firstFragmentHeader_ == null)
                            {
                                throw new FormatException("");
                            }

                            var mergedPayloadLength = lastFragmentHeader_.FragmentOffset + lastFragmentHeader_.PayloadLength;
                            var mergedPayloadBuffer = new ByteBuffer(lastFragmentHeader_.FragmentOffset + lastFragmentHeader_.PayloadLength);
                            foreach (var pair in payloadMap_)
                            {
                                mergedPayloadBuffer.Enqueue(pair.Value);
                            }
                            if (mergedPayloadBuffer.Count != mergedPayloadLength)
                            {
                                throw new FormatException("");
                            }

                            mergedPacket = new IpV4Packet(header, mergedPayloadBuffer.Dequeue());

                            Reset();
                        }
                    }
                    catch (Exception e) {
                        Reset();

                        throw e;
                    }
                }

                return(mergedPacket);
            }