public HoleList( IntervalInt32 range ) { range_ = range; filledArea_ = new SortedList <Int32, Int32>(); }
public PayloadPair( IntervalInt32 offsetInterval , byte[] payload ) { OffsetInterval = offsetInterval; Payload = payload; }
/// <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); }
/// <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; }
/// <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; }
/// <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; }
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); }