C# implementation of Google's 'Encoded Polyline Algorithm' - c#

Does anyone have a concise and robust implementation of Google's Encoded Polyline Algorithm in C#?
I essentially want the implementation of this signature:
public string Encode(IEnumerable<Point> points);

Here's the implementation I settled on:
public static string Encode(IEnumerable<GeoLocation> points)
{
var str = new StringBuilder();
var encodeDiff = (Action<int>)(diff => {
int shifted = diff << 1;
if (diff < 0)
shifted = ~shifted;
int rem = shifted;
while (rem >= 0x20)
{
str.Append((char)((0x20 | (rem & 0x1f)) + 63));
rem >>= 5;
}
str.Append((char)(rem + 63));
});
int lastLat = 0;
int lastLng = 0;
foreach (var point in points)
{
int lat = (int)Math.Round(point.Latitude * 1E5);
int lng = (int)Math.Round(point.Longitude * 1E5);
encodeDiff(lat - lastLat);
encodeDiff(lng - lastLng);
lastLat = lat;
lastLng = lng;
}
return str.ToString();
}
Hope that helps someone else out.

Maybe is late but I've just solved the same problem but to Encode list of locations and Decode polylines, I used http://json2csharp.com/ to generate corresponding classes in C# in order to deserialize the response with JsonConvert like:
var googleDirectionsResponse = JsonConvert.DeserializeObject<RootObject>(responseString);
This gave me this definition of Location (I'll clean it sooner or later):
public class Location
{
public double lat { get; set; }
public double lng { get; set; }
}
And I created a converter class to do the trick in both directions (IT's not original, it is just a refactor from this class: https://gist.github.com/shinyzhu/4617989 ):
/// <summary>
/// Google Polyline Converter (Encoder and Decoder)
/// </summary>
public static class GooglePolylineConverter
{
/// <summary>
/// Decodes the specified polyline string.
/// </summary>
/// <param name="polylineString">The polyline string.</param>
/// <returns>A list with Locations</returns>
public static IEnumerable<Location> Decode(string polylineString)
{
if (string.IsNullOrEmpty(polylineString))
throw new ArgumentNullException(nameof(polylineString));
var polylineChars = polylineString.ToCharArray();
var index = 0;
var currentLat = 0;
var currentLng = 0;
while (index < polylineChars.Length)
{
// Next lat
var sum = 0;
var shifter = 0;
int nextFiveBits;
do
{
nextFiveBits = polylineChars[index++] - 63;
sum |= (nextFiveBits & 31) << shifter;
shifter += 5;
} while (nextFiveBits >= 32 && index < polylineChars.Length);
if (index >= polylineChars.Length)
break;
currentLat += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
// Next lng
sum = 0;
shifter = 0;
do
{
nextFiveBits = polylineChars[index++] - 63;
sum |= (nextFiveBits & 31) << shifter;
shifter += 5;
} while (nextFiveBits >= 32 && index < polylineChars.Length);
if (index >= polylineChars.Length && nextFiveBits >= 32)
break;
currentLng += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
yield return new Location
{
lat = Convert.ToDouble(currentLat) / 1E5,
lng = Convert.ToDouble(currentLng) / 1E5
};
}
}
/// <summary>
/// Encodes the specified locations list.
/// </summary>
/// <param name="locations">The locations.</param>
/// <returns>The polyline string.</returns>
public static string Encode(IEnumerable<Location> locations)
{
var str = new StringBuilder();
var encodeDiff = (Action<int>)(diff =>
{
var shifted = diff << 1;
if (diff < 0)
shifted = ~shifted;
var rem = shifted;
while (rem >= 0x20)
{
str.Append((char)((0x20 | (rem & 0x1f)) + 63));
rem >>= 5;
}
str.Append((char)(rem + 63));
});
var lastLat = 0;
var lastLng = 0;
foreach (var point in locations)
{
var lat = (int)Math.Round(point.lat * 1E5);
var lng = (int)Math.Round(point.lng * 1E5);
encodeDiff(lat - lastLat);
encodeDiff(lng - lastLng);
lastLat = lat;
lastLng = lng;
}
return str.ToString();
}
}
I hope it helps.

Javascript implementation, in case anyone is interested:
var polyline_encoder = (function() {
var _ = {};
var invert_bits = function(str) {
var ret = "";
for(var i=0; i<str.length; i++) {
if(str.charAt(i) == "1")
ret += "0";
else
ret += "1";
}
return ret;
};
var get_binary = function(num) {
var binary = parseInt(num).toString(2);
var bit_difference = 32 - binary.length;
for(var i=0; i<bit_difference; i++)
binary = "0" + binary;
if(num < 0) {
binary = invert_bits(binary);
binary = parseInt(binary, 2);
binary++;
return parseInt(binary).toString(2);
}
return binary;
};
_.encode_polyline = function(points) {
var ret = "";
var last_point, val_1, val_2;
for(var i=0; i<points.length; i++) {
if(!last_point) {
val_1 = points[i][0];
val_2 = points[i][1];
} else {
val_1 = points[i][0] - last_point[0];
val_2 = points[i][1] - last_point[1];
}
last_point = points[i];
ret += _.encode_polyline_value(val_1) + _.encode_polyline_value(val_2);
}
return ret;
};
_.encode_polyline_value = function(value) {
var ret = "";
value = Math.round(value * 100000);
var shifted = value << 1;
if(shifted < 0)
shifted = ~shifted;
var rem = shifted;
while(rem >= 32) {
ret += get_ascii_value(((0x20 | (rem & 0x1f)) + 63));
rem >>= 5;
}
ret += get_ascii_value(rem + 63);
return ret;
};
var get_ascii_value = function(num) {
var ascii_table =
// 0 thru 9
"??????????" +
// 10 thru 19
"??????????" +
// 20 thru 29
"??????????" +
// 30 thru 39
"?? !\"#$%&'" +
// 40 thru 49
"()*+,-./01" +
// 50 thru 59
"23456789:;" +
// 60 thru 69
"<=>?#ABCDE" +
// 70 thru 79
"FGHIJKLMNO" +
// 80 thru 89
"PQRSTUVWXY" +
// 90 thru 99
"Z[\\]^_`abc" +
// 100 thru 109
"defghijklm" +
// 110 thru 119
"nopqrstuvw" +
// 120 thru 127
"xyz{|}~?";
var value = ascii_table.substr(num, 1);
if(value == "?")
value = "";
return value;
};
return _;
})();

Related

Cosine similarity calculation issue

I am having issues in calculation of cosine similarity between 2 strings.
I calculate the binary vector format of each string using a function. It gives out binary vectors which are in the form of, say, (1,1,1,1,1,0,0,0,0).
public static Tuple<int[],int[]> sentence_to_vector(String[] word_array1, String[] word_array2)
{
String[] unique_word_array1 = word_array1.Distinct().ToArray();
String[] unique_word_array2 = word_array2.Distinct().ToArray();
String[] list_all_words = unique_word_array1.Concat(unique_word_array2).ToArray();
String[] list_all_words_unique = list_all_words.Distinct().ToArray();
int count_all_unique_words = list_all_words_unique.Length;
int[] sentence1_vector = new int[count_all_unique_words];
int[] sentence2_vector = new int[count_all_unique_words];
for (int i = 0; i < count_all_unique_words; i++)
{
if (Array.IndexOf(unique_word_array1, list_all_words_unique[i]) >= 0)
{
sentence1_vector[i] = 1;
}
else
{
sentence1_vector[i] = 0;
}
}
for (int i = 0; i < count_all_unique_words; i++)
{
if (Array.IndexOf(word_array2, list_all_words_unique[i]) >= 0)
{
sentence2_vector[i] = 1;
}
else
{
sentence2_vector[i] = 0;
}
}
return Tuple.Create(sentence1_vector, sentence2_vector);;
}
After I calculate the vector representation, I go for cosine similarity calculation.
The code is attached herewith:
public static float get_cosine_similarity(int[] sentence1_vector, int[] sentence2_vector)
{
int vector_length = sentence1_vector.Length;
int i = 0;
float numerator = 0, denominator = 0;
int temp1 = 0, temp2 = 0;
double square_root1 = 0, square_root2 = 0;
for (i = 0; i < vector_length; i++)
{
numerator += sentence1_vector[i] * sentence2_vector[i];
temp1 += sentence1_vector[i] * sentence1_vector[i];
temp2 += sentence2_vector[i] * sentence2_vector[i];
}
//TextWriter tw = new StreamWriter("E://testpdf/date2.txt");
square_root1 = Math.Sqrt(temp1);
square_root2 = Math.Sqrt(temp2);
denominator = (float)(square_root1 * square_root2);
if (denominator != 0){
return (float)(numerator / denominator);
//return (float)(numerator);
}
else{
return 0;
}
}
I checked out a site where in I can specify 2 strings and find the cosine similarity between them. The site is attached herewith:
http://cs.uef.fi/~zhao/Link/Similarity_strings.html
function implementationCosin(){
var string1 = document.DPAform.str1.value;
var s1 = stringBlankCheck(string1);
var string2 = document.DPAform.str2.value;
var s2 = stringBlankCheck(string2);
if (s1.length < 1) {
alert("Please input the string1.");
return;
}
if (s2.length < 1) {
alert("Please input the string2.");
return;
}
document.DPAform.displayArea2.value = "";
var sDT = new Date();
// var begin = new Date().getTime();
var cosin_similarity_value = consinSimilarity(s1, s2);
document.DPAform.displayArea2.value += 'Cosin_Similarity(' + s1 + ',' + s2 + ')=' + cosin_similarity_value + '%\n';
var eDT = new Date();
var timediff = sDT.dateDiff("ms", eDT);
// var timediff = (new Date().getTime() - begin);
document.DPAform.displayArea2.value += "The total escaped time is: " + timediff + " (ms).\n";
}
Even if 2 sentences are 0% similar, my codes says that there is some amount of similarity between them.

Compare string using bitwise shift operation

So i am new to csharp and i cant seem to find a logical error here in this program.i am learning the bitwise shift operators as i am new to these operators. I need help tracing a fault in my code. the program encodes an input String and decodes the encoded String after.After that i compare the string to see if they are equal.They seem to be equal to me but i keep getting a false when i compare them. Here is my code:
class Program
{
static char[] transcode = new char[64];
private static void prep()
{
for (int i = 0; i < transcode.Length; i++)
{
transcode[i] = (char)((int)'A' + i);
if (i > 25 && i <= 51)
{
transcode[i] = (char)((int)transcode[i] + 6);
}
else if (i > 51)
{
transcode[i] = (char)((int)transcode[i] - 0x4b);
}
}
transcode[transcode.Length - 3] = '+';
transcode[transcode.Length - 2] = '/';
transcode[transcode.Length - 1] = '=';
}
static void Main(string[] args)
{
prep();
string test_string = "a";
if (Convert.ToBoolean(String.Compare(test_string, decode(encode(test_string)))))
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
}
private static string encode(string input)
{
int l = input.Length;
int cb = (l / 3 + (Convert.ToBoolean(l % 3) ? 1 : 0)) * 4;// (0 +(1))*4 =4
char[] output = new char[cb];
for (int i = 0; i < cb; i++)
{
output[i] = '=';
}
int c = 0;
int reflex = 0;
const int s = 0x3f;
for (int j = 0; j < l; j++)
{
reflex <<= 8;
reflex &= 0x00ffff00;
reflex += input[j];
int x = ((j % 3) + 1) * 2;
int mask = s << x;
while (mask >= s)
{
int pivot = (reflex & mask) >> x;
output[c++] = transcode[pivot];
char alpha = transcode[pivot];
int invert = ~mask;
reflex &= invert;
mask >>= 6;
x -= 6; //-4
}
}
switch (l % 3)
{
case 1:
reflex <<= 4; //16
output[c++] = transcode[reflex];
char at16 = transcode[16];
// Console.WriteLine("Character at 16 is: " + at16);
break;
case 2:
reflex <<= 2;
output[c++] = transcode[reflex];
break;
}
return new string(output);//final value is: YQ== (Encoded String.)
}
private static string decode(string input)//input is YQ== which has a length of 4
{
int l = input.Length;
int cb = (l / 4 + ((Convert.ToBoolean(l % 4)) ? 1 : 0)) * 3 + 1; // (1 + (0))*4
char[] output = new char[cb]; //4 in length
int c = 0;
int bits = 0;
int reflex = 0;
for (int j = 0; j < l; j++)
{
reflex <<= 6;
bits += 6;
bool fTerminate = ('=' == input[j]);
if (!fTerminate)
{
reflex += indexOf(input[j]);
while (bits >= 8)
{
int mask = 0x000000ff << (bits % 8);
output[c++] = (char)((reflex & mask) >> (bits % 8)); //convert issue cannot implicitly convert to proper data type.so will have to explicitly convert.
int invert = ~mask;
reflex &= invert;
bits -= 8;
}
}
else
{
break;
}
}
return new string(output);
}
private static int indexOf(char ch)
{
int index;
for (index = 0; index < transcode.Length; index++)
if (ch == transcode[index])
break;
return index;
}
}
Read the docs for String.Compare then read the docs for Convert.ToBoolean. Pay particular attention to the value returned by String.Compare when two strings are equal. Then compare with how that value gets converted to a boolean by ToBoolean
String.Compare is designed for sorting strings. It returns 0 when two strings are equal. ToBoolean will convert that 0 to false. So when you strings are equal, your if evaluates to false and not true.
A simple change would be:
if (String.Compare(test_string, decode(encode(test_string)))==0)
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
#Tom's comment about the trailing nulls also applies, but it seems that String.Compare just ignores them.

ITF Barcode Algorithm

I have this C# ITF/Interleaved 2 of 5 algorithm (from a VB Azalea Software algorithm):
public static string Interleaved25(string input)
{
if (input.Length <= 0) return "";
if (input.Length % 2 != 0)
{
input = "0" + input;
}
string result = "";
//Takes pairs of numbers and convert them to chars
for (int i = 0; i <= input.Length - 1; i += 2)
{
int pair = Int32.Parse(input.Substring(i, 2));
if (pair < 90)
pair = pair + 33;
else if (pair == 90)
pair = pair + 182;
else if (pair == 91)
pair = pair + 183;
else if (pair > 91)
pair = pair + 104;
result = result + Convert.ToChar(pair);
}
//Leading and trailing chars.
return (char)171 + result + (char)172;
}
The problem is that somehow chars with value > 89 all have empty boxes as result (using the ITF font).
I know this is an old question. But here is a solution with checksum:
using System;
public class Program
{
public static void Main()
{
var bcTxt = "0000420876801";//"29902110013"; //"0000420876801";
int prod1 = 0;
int prod2 = 0;
string Txt1 = "";
string Txt2 = "";
Txt1 = bcTxt;
// Berechnen der Prüfziffer, wenn ungerade Anzahl von Zeichen
if (Txt1.Length % 2 == 1)
{
for (int i = 0; i < Txt1.Length; i++)
{
prod1 += int.Parse(Txt1.Substring(i, 1)) * 3;
if (i < Txt1.Length -1)
{
prod1 += int.Parse(Txt1.Substring(i + 1, 1));
i += 1;
}
Console.WriteLine(prod1);
}
Console.WriteLine(prod1);
prod2 = prod1 % 10;
Console.WriteLine(prod2);
if (prod2 == 0)
{
prod2 = 10;
}
prod2 = 10 - prod2;
Txt1 += (char)(prod2 + 48);
Console.WriteLine(Txt1);
}
//Ascii Zeichen zuordnen
//beim Code 2/5 werden die Zeichen paarweise zugeordnet
Txt2 = ((char)34).ToString();
string Tmp = "";
for (int i = 0; i < Txt1.Length; i++)
{
Tmp += Txt1.Substring(i, 2);
i += 1;
if (int.Parse(Tmp) > 91)
{
Txt2 += ((char)(int.Parse(Tmp) + 70)).ToString();
}
else
{
Txt2 += ((char)(int.Parse(Tmp) + 36)).ToString();
}
Tmp = "";
}
Txt2 += ((char)35).ToString();
Console.WriteLine(Txt2);
}
}
While typing this question, I got the answer all by myself.
Here is the new code:
if (pair < 90)
pair = pair + 33;
else
{
pair = pair + 71;
}
Basically, all chars between 90 and 99 needs a + 71.
same code in vb6
Public Function DevolverI2of5(ByVal cString As String) as String
Dim i As Integer
If Len(cString) Mod 2 <> 0 Then
cString = "0" & cString
End If
Dim result As String
'Takes pairs of numbers and convert them to chars
For i = 1 To Len(cString) Step 2
Dim pair As Integer
pair = Val(Mid(cString, i, 2))
If pair < 90 Then
pair = pair + 33
Else
pair = pair + 71
End If
result = result & Chr(pair)
Next i
DevolverI2of5 = Chr(171) & result & Chr(172)

Get longest substring between two strings

I have two words,
britanicaeng and
britanicahin
I need to find out the longest common word between these i.e, britanica.
How can I do this in C# ?
Try this method:
public static string FindLongestCommonSubstring(string s1, string s2)
{
int[,] a = new int[s1.Length + 1, s2.Length + 1];
int row = 0; // s1 index
int col = 0; // s2 index
for (var i = 0; i < s1.Length; i++)
for (var j = 0; j < s2.Length; j++)
if (s1[i] == s2[j])
{
int len = a[i + 1, j + 1] = a[i, j] + 1;
if (len > a[row, col])
{
row = i + 1;
col = j + 1;
}
}
return s1.Substring(row - a[row, col], a[row, col]);
}
Usage example:
Console.WriteLine(FindLongestCommonSubstring("britanicaeng", "britanicahin"));
I refactored the C++ code from Ashutosh Singh at https://iq.opengenus.org/longest-common-substring-using-rolling-hash/ to create a rolling hash approach in C# - this will find the substring in O(N * log(N)^2) time and O(N) space
using System;
using System.Collections.Generic;
public class RollingHash
{
private class RollingHashPowers
{
// _mod = prime modulus of polynomial hashing
// any prime number over a billion should suffice
internal const int _mod = (int)1e9 + 123;
// _hashBase = base (point of hashing)
// this should be a prime number larger than the number of characters used
// in my use case I am only interested in ASCII (256) characters
// for strings in languages using non-latin characters, this should be much larger
internal const long _hashBase = 257;
// _pow1 = powers of base modulo mod
internal readonly List<int> _pow1 = new List<int> { 1 };
// _pow2 = powers of base modulo 2^64
internal readonly List<long> _pow2 = new List<long> { 1L };
internal void EnsureLength(int length)
{
if (_pow1.Capacity < length)
{
_pow1.Capacity = _pow2.Capacity = length;
}
for (int currentIndx = _pow1.Count - 1; currentIndx < length; ++currentIndx)
{
_pow1.Add((int)(_pow1[currentIndx] * _hashBase % _mod));
_pow2.Add(_pow2[currentIndx] * _hashBase);
}
}
}
private class RollingHashedString
{
readonly RollingHashPowers _pows;
readonly int[] _pref1; // Hash on prefix modulo mod
readonly long[] _pref2; // Hash on prefix modulo 2^64
// Constructor from string:
internal RollingHashedString(RollingHashPowers pows, string s, bool caseInsensitive = false)
{
_pows = pows;
_pref1 = new int[s.Length + 1];
_pref2 = new long[s.Length + 1];
const long capAVal = 'A';
const long capZVal = 'Z';
const long aADif = 'a' - 'A';
unsafe
{
fixed (char* c = s)
{
// Fill arrays with polynomial hashes on prefix
for (int i = 0; i < s.Length; ++i)
{
long v = c[i];
if (caseInsensitive && capAVal <= v && v <= capZVal)
{
v += aADif;
}
_pref1[i + 1] = (int)((_pref1[i] + v * _pows._pow1[i]) % RollingHashPowers._mod);
_pref2[i + 1] = _pref2[i] + v * _pows._pow2[i];
}
}
}
}
// Rollingnomial hash of subsequence [pos, pos+len)
// If mxPow != 0, value automatically multiply on base in needed power.
// Finally base ^ mxPow
internal Tuple<int, long> Apply(int pos, int len, int mxPow = 0)
{
int hash1 = _pref1[pos + len] - _pref1[pos];
long hash2 = _pref2[pos + len] - _pref2[pos];
if (hash1 < 0)
{
hash1 += RollingHashPowers._mod;
}
if (mxPow != 0)
{
hash1 = (int)((long)hash1 * _pows._pow1[mxPow - (pos + len - 1)] % RollingHashPowers._mod);
hash2 *= _pows._pow2[mxPow - (pos + len - 1)];
}
return Tuple.Create(hash1, hash2);
}
}
private readonly RollingHashPowers _rhp;
public RollingHash(int longestLength = 0)
{
_rhp = new RollingHashPowers();
if (longestLength > 0)
{
_rhp.EnsureLength(longestLength);
}
}
public string FindCommonSubstring(string a, string b, bool caseInsensitive = false)
{
// Calculate max neede power of base:
int mxPow = Math.Max(a.Length, b.Length);
_rhp.EnsureLength(mxPow);
// Create hashing objects from strings:
RollingHashedString hash_a = new RollingHashedString(_rhp, a, caseInsensitive);
RollingHashedString hash_b = new RollingHashedString(_rhp, b, caseInsensitive);
// Binary search by length of same subsequence:
int pos = -1;
int low = 0;
int minLen = Math.Min(a.Length, b.Length);
int high = minLen + 1;
var tupleCompare = Comparer<Tuple<int, long>>.Default;
while (high - low > 1)
{
int mid = (low + high) / 2;
List<Tuple<int, long>> hashes = new List<Tuple<int, long>>(a.Length - mid + 1);
for (int i = 0; i + mid <= a.Length; ++i)
{
hashes.Add(hash_a.Apply(i, mid, mxPow));
}
hashes.Sort(tupleCompare);
int p = -1;
for (int i = 0; i + mid <= b.Length; ++i)
{
if (hashes.BinarySearch(hash_b.Apply(i, mid, mxPow), tupleCompare) >= 0)
{
p = i;
break;
}
}
if (p >= 0)
{
low = mid;
pos = p;
}
else
{
high = mid;
}
}
// Output answer:
return pos >= 0
? b.Substring(pos, low)
: string.Empty;
}
}

Display entire IP Address range knowing Minimum and Maximum values? [duplicate]

How do I iterate through a range of IP addresses provided by the user?
I'm flexible on the format, provided it allows all ranges to be specified. Perhaps something like the nmap-style:
'192.0.2.1' # one IP address
'192.0.2.0-31' # one block with 32 IP addresses.
'192.0.2-3.1-254' # two blocks with 254 IP addresses.
'0-255.0-255.0-255.0-255' # the whole IPv4 address space
For example, if the user entered 192.0.2-3.1-254, I would like to know how to generate a list of all the valid IP addresses in this range so that I could iterate through them.
For example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
namespace IpRanges
{
public class IPRange
{
public IPRange(string ipRange)
{
if (ipRange == null)
throw new ArgumentNullException();
if (!TryParseCIDRNotation(ipRange) && !TryParseSimpleRange(ipRange))
throw new ArgumentException();
}
public IEnumerable<IPAddress> GetAllIP()
{
int capacity = 1;
for (int i = 0; i < 4; i++)
capacity *= endIP[i] - beginIP[i] + 1;
List<IPAddress> ips = new List<IPAddress>(capacity);
for (int i0 = beginIP[0]; i0 <= endIP[0]; i0++)
{
for (int i1 = beginIP[1]; i1 <= endIP[1]; i1++)
{
for (int i2 = beginIP[2]; i2 <= endIP[2]; i2++)
{
for (int i3 = beginIP[3]; i3 <= endIP[3]; i3++)
{
ips.Add(new IPAddress(new byte[] { (byte)i0, (byte)i1, (byte)i2, (byte)i3 }));
}
}
}
}
return ips;
}
/// <summary>
/// Parse IP-range string in CIDR notation.
/// For example "12.15.0.0/16".
/// </summary>
/// <param name="ipRange"></param>
/// <returns></returns>
private bool TryParseCIDRNotation(string ipRange)
{
string[] x = ipRange.Split('/');
if (x.Length != 2)
return false;
byte bits = byte.Parse(x[1]);
uint ip = 0;
String[] ipParts0 = x[0].Split('.');
for (int i = 0; i < 4; i++)
{
ip = ip << 8;
ip += uint.Parse(ipParts0[i]);
}
byte shiftBits = (byte)(32 - bits);
uint ip1 = (ip >> shiftBits) << shiftBits;
if (ip1 != ip) // Check correct subnet address
return false;
uint ip2 = ip1 >> shiftBits;
for (int k = 0; k < shiftBits; k++)
{
ip2 = (ip2 << 1) + 1;
}
beginIP = new byte[4];
endIP = new byte[4];
for (int i = 0; i < 4; i++)
{
beginIP[i] = (byte) ((ip1 >> (3 - i) * 8) & 255);
endIP[i] = (byte)((ip2 >> (3 - i) * 8) & 255);
}
return true;
}
/// <summary>
/// Parse IP-range string "12.15-16.1-30.10-255"
/// </summary>
/// <param name="ipRange"></param>
/// <returns></returns>
private bool TryParseSimpleRange(string ipRange)
{
String[] ipParts = ipRange.Split('.');
beginIP = new byte[4];
endIP = new byte[4];
for (int i = 0; i < 4; i++)
{
string[] rangeParts = ipParts[i].Split('-');
if (rangeParts.Length < 1 || rangeParts.Length > 2)
return false;
beginIP[i] = byte.Parse(rangeParts[0]);
endIP[i] = (rangeParts.Length == 1) ? beginIP[i] : byte.Parse(rangeParts[1]);
}
return true;
}
private byte [] beginIP;
private byte [] endIP;
}
}
Check out the snippet here. Keep the credits in place if you use this please.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
/* ====================================================================================
C# IP address range finder helper class (C) Nahum Bazes
* Free for private & commercial use - no restriction applied, please leave credits.
* DO NOT REMOVE THIS COMMENT
* ==================================================================================== */
namespace IPAddressTools
{
public class RangeFinder
{
public IEnumerable<string> GetIPRange(IPAddress startIP,
IPAddress endIP)
{
uint sIP = ipToUint(startIP.GetAddressBytes());
uint eIP = ipToUint(endIP.GetAddressBytes());
while (sIP <= eIP)
{
yield return new IPAddress(reverseBytesArray(sIP)).ToString();
sIP++;
}
}
/* reverse byte order in array */
protected uint reverseBytesArray(uint ip)
{
byte[] bytes = BitConverter.GetBytes(ip);
bytes = bytes.Reverse().ToArray();
return (uint)BitConverter.ToInt32(bytes, 0);
}
/* Convert bytes array to 32 bit long value */
protected uint ipToUint(byte[] ipBytes)
{
ByteConverter bConvert = new ByteConverter();
uint ipUint = 0;
int shift = 24; // indicates number of bits left for shifting
foreach (byte b in ipBytes)
{
if (ipUint == 0)
{
ipUint = (uint)bConvert.ConvertTo(b, typeof(uint)) << shift;
shift -= 8;
continue;
}
if (shift >= 8)
ipUint += (uint)bConvert.ConvertTo(b, typeof(uint)) << shift;
else
ipUint += (uint)bConvert.ConvertTo(b, typeof(uint));
shift -= 8;
}
return ipUint;
}
}
}
I'm late to the game, but your question was mentioned in duplicate, so I just add the answer here. Using the IPAddressRange library, you can enumerate your IPs like that:
var start = IPAddress.Parse("192.168.0.2");
var end = IPAddress.Parse("192.168.0.254");
var range = new IPAddressRange(start, end);
foreach (var ip in range)
{
Console.WriteLine(ip);
}
The library also supports CIDR notation and range strings
I think this should do it.
static void TestFunc()
{
byte[,] range = ParseRange("192.0.2-5.14-28");
foreach (IPAddress addr in Enumerate(range))
{
Console.WriteLine(addr);
}
}
static byte[,] ParseRange(string str)
{
if (string.IsNullOrEmpty(str)) throw new ArgumentException("str");
string[] partStr = str.Split('.');
if (partStr.Length != 4) throw new FormatException();
byte[,] range = new byte[4, 2];
for (int i = 0; i < 4; i++)
{
string[] rangeStr = partStr[i].Split('-');
if (rangeStr.Length > 2) throw new FormatException();
range[i, 0] = byte.Parse(rangeStr[0]);
range[i, 1] = byte.Parse(rangeStr[Math.Min(rangeStr.Length - 1, 1)]);
// Remove this to allow ranges to wrap around.
// For example: 254-4 = 254, 255, 0, 1, 2, 3, 4
if (range[i, 1] < range[i, 0]) throw new FormatException();
}
return range;
}
static IEnumerable<IPAddress> Enumerate(byte[,] range)
{
if (range.GetLength(0) != 4) throw new ArgumentException("range");
if (range.GetLength(1) != 2) throw new ArgumentException("range");
for (byte a = range[0, 0]; a != (byte)(range[0, 1] + 1); a++)
{
for (byte b = range[1, 0]; b != (byte)(range[1, 1] + 1); b++)
{
for (byte c = range[2, 0]; c != (byte)(range[2, 1] + 1); c++)
{
for (byte d = range[3, 0]; d != (byte)(range[3, 1] + 1); d++)
{
yield return new IPAddress(new byte[] { a, b, c, d });
}
}
}
}
}

Categories

Resources