The Labs \ Source Viewer \ SSCLI \ System \ IPv4AddressHelper

  1. //------------------------------------------------------------------------------
  2. // <copyright file="_IPv4Address.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System
  16. {
  17.    
  18.     // The class designed as to keep minimal the working set of Uri class.
  19.     // The idea is to stay with static helper methods and strings
  20.     internal class IPv4AddressHelper
  21.     {
  22.        
  23.         // fields
  24.         private IPv4AddressHelper()
  25.         {
  26.         }
  27.        
  28.         private const int NumberOfLabels = 4;
  29.        
  30.         // methods
  31.        
  32.         static internal string ParseCanonicalName(string str, int start, int end, ref bool isLoopback)
  33.         {
  34.             unsafe {
  35.                 byte* numbers = stackalloc byte[NumberOfLabels];
  36.                 isLoopback = Parse(str, numbers, start, end);
  37.                 return numbers[0] + "." + numbers[1] + "." + numbers[2] + "." + numbers[3];
  38.             }
  39.         }
  40.        
  41.         static internal int ParseHostNumber(string str, int start, int end)
  42.         {
  43.             unsafe {
  44.                 byte* numbers = stackalloc byte[NumberOfLabels];
  45.                 Parse(str, numbers, start, end);
  46.                 return (numbers[0] << 24) + (numbers[1] << 16) + (numbers[2] << 8) + numbers[3];
  47.             }
  48.         }
  49.        
  50.         //
  51.         // IsValid
  52.         //
  53.         // Performs IsValid on a substring. Updates the index to where we
  54.         // believe the IPv4 address ends
  55.         //
  56.         // Inputs:
  57.         // <argument> name
  58.         // string containing possible IPv4 address
  59.         //
  60.         // <argument> start
  61.         // offset in <name> to start checking for IPv4 address
  62.         //
  63.         // <argument> end
  64.         // offset in <name> of the last character we can touch in the check
  65.         //
  66.         // Outputs:
  67.         // <argument> end
  68.         // index of last character in <name> we checked
  69.         //
  70.         // Assumes:
  71.         // The address string is terminated by either
  72.         // end of the string, characters ':' '/' '\' '?'
  73.         //
  74.         //
  75.         // Returns:
  76.         // bool
  77.         //
  78.         // Throws:
  79.         // Nothing
  80.         //
  81.        
  82.         //internal unsafe static bool IsValid(char* name, int start, ref int end) {
  83.         // return IsValid(name, start, ref end, false);
  84.         //}
  85.        
  86.         //Remark: MUST NOT be used unless all input indexes are are verified and trusted.
  87.         unsafe static internal bool IsValid(char* name, int start, ref int end, bool allowIPv6, bool notImplicitFile)
  88.         {
  89.            
  90.             int dots = 0;
  91.             int number = 0;
  92.             bool haveNumber = false;
  93.            
  94.             while (start < end) {
  95.                 char ch = name[start];
  96.                 if (allowIPv6) {
  97.                     // for ipv4 inside ipv6 the terminator is either ScopeId, prefix or ipv6 terminator
  98.                     if (ch == ']' || ch == '/' || ch == '%')
  99.                         break;
  100.                 }
  101.                 else if (ch == '/' || ch == '\\' || (notImplicitFile && (ch == ':' || ch == '?' || ch == '#'))) {
  102.                     break;
  103.                 }
  104.                
  105.                 if (ch <= '9' && ch >= '0') {
  106.                     haveNumber = true;
  107.                     number = number * 10 + (name[start] - '0');
  108.                     if (number > 255) {
  109.                         return false;
  110.                     }
  111.                 }
  112.                 else if (ch == '.') {
  113.                     if (!haveNumber) {
  114.                         return false;
  115.                     }
  116.                     ++dots;
  117.                     haveNumber = false;
  118.                     number = 0;
  119.                 }
  120.                 else {
  121.                     return false;
  122.                 }
  123.                 ++start;
  124.             }
  125.             bool res = (dots == 3) && haveNumber;
  126.             if (res) {
  127.                 end = start;
  128.             }
  129.             return res;
  130.         }
  131.        
  132.         //
  133.         // Parse
  134.         //
  135.         // Convert this IPv4 address into a sequence of 4 8-bit numbers
  136.         //
  137.         // Assumes:
  138.         // <Name> has been validated and contains only decimal digits in groups
  139.         // of 8-bit numbers and the characters '.'
  140.         // Address may terminate with ':' or with the end of the string
  141.         //
  142.         unsafe private static bool Parse(string name, byte* numbers, int start, int end)
  143.         {
  144.             for (int i = 0; i < NumberOfLabels; ++i) {
  145.                
  146.                 byte b = 0;
  147.                 char ch;
  148.                 for (; (start < end) && (ch = name[start]) != '.' && ch != ':'; ++start) {
  149.                     b = (byte)(b * 10 + (byte)(ch - '0'));
  150.                 }
  151.                 numbers[i] = b;
  152.                 ++start;
  153.             }
  154.             return numbers[0] == 127;
  155.         }
  156.     }
  157. }

Developer Fusion