A DottedDecimal Object
Ok, so there are a lot of objects that are represented in dotted decimal notation. The most common are versions and IP addresses.
Version 3.1.9.27
IP Address: 192.168.0.1
I have to wonder why I have never found in the Standard C++ Library, or in the C# libraries an object for these? Are they there and I just don’t know how to find them. It seems they are always just treated as Strings and this makes no sense to me. Also these seem common enough that they should be standard objects in all languages.
Which IP Address is greater?
192.168.0.2
192.168.0.100
Well, since these are usually treated as strings, then .2 is greater than .100. Unfortunately that is not correct. We all know that .100 is greater.
So I created some objects that overload the >,>=,<=,<,==,!= functions. Maybe these are completely finished, but hey, they are a start. I created C# and C++ versions. The C# is first, scroll down if you are looking for C++ versions. This is really great for versions that can be different. However, I think that for an IP address object, that because it is limited to three characters and each section is one byte and only can be seen as 0-255, that a very efficient object could be created, but for now, a more generic DottedDecimal object is fine, though if you had a large list of IP addresses, you may want that efficiency. Also, this is only tested with digits 0-9, not hex, so there is plenty more work to do, but usually version are just 0-9, though sometimes people throw in an "a" or "b" build such as 1.0.0.1a. That is not handled yet. So again, much more work to do. But for my needs these are more than enough for now. If there are already objects like this that are awesome, efficient, tested, and free, let me know.
C# DottedDecimal object for IP address and Versions
For C#, I implement a lot of interfaces too as you can see in the object.
DottedDecimal.cs
using System; using System.Collections.Generic; using System.Text; namespace DottedDecimalProject { public class DottedDecimal : IComparable, IComparable<dottedDecimal>, IComparable<string>, ICloneable, IEquatable<string>, IEquatable<dottedDecimal> { #region Member Variables List<long> _DecimalValues; CompareDirection _CompareDirection = CompareDirection.LeftToRight; #endregion #region Constructors /* * The default constuctor. * The default compare direction is left to right * No values are added by default. */ public DottedDecimal() { } /* * This constructor takes a string in this regex format * [0-9]+(\.[0-9])* */ public DottedDecimal(String inDottedDecimalString) { _DecimalValues = null; _DecimalValues = StringToDottedDecimalList(inDottedDecimalString); } /* * This constructor takes two parameters. * Parameter 1 is a string in this regex format: [0-9]+(\.[0-9])* * Parameter 2 sets the compare direction. See this.Direction. */ public DottedDecimal(String inDottedDecimalString, CompareDirection inCompareDirection) { _CompareDirection = inCompareDirection; _DecimalValues = null; _DecimalValues = StringToDottedDecimalList(inDottedDecimalString); } #endregion #region Properties /* * Returns the dotted decimal object in string format. */ public String DottedDecimalString { get { return DottedDecimalListToString(); } set { _DecimalValues = StringToDottedDecimalList(value); } } /* * The decimal values are stored in order. If LeftToRight, the left * most value is first. If RightToLeft, the right most value is first. */ public List<long> DecimalValues { get { return _DecimalValues; } set { _DecimalValues = value; } } /* * Determines whether to compare left to right or right to left. * * LeftToRight - 1.0.0.1 is greater than 1.0.0.0 * 1.0.10 is greater than 1.0.0.27 * * RightToLeft - 1.0.0.1 is less than 1.0.0.0 * - 1.0.10 is less than 1.0.0.27 */ public CompareDirection Direction { get { return _CompareDirection; } set { if (!(this.Direction == value)) { this._DecimalValues.Reverse(); } _CompareDirection = value; } } #endregion #region Functions /* * Verifies that the CompareDirection values match between two DottedDecimal objects. */ private static bool CompareDirectionsMatch(DottedDecimal left, DottedDecimal right) { if (left.Direction == right.Direction) return true; else return false; } /* * Overloads the greater than operator (>) to allow for a syntax as follows: * * bool b = dd1 > dd2; */ public static bool operator >(DottedDecimal left, DottedDecimal right) { int count = (left.DecimalValues.Count > right.DecimalValues.Count) ? right.DecimalValues.Count : left.DecimalValues.Count; for (int i = 0; i < count; i++) { // If left side is greater then true; if (left.DecimalValues[i] > right.DecimalValues[i]) { return true; } // If right side is greater then false; if (left.DecimalValues[i] < right.DecimalValues[i]) { return false; } // If it is equal, check the next decimal values over if (left.DecimalValues[i] == right.DecimalValues[i]) { continue; } } if (left.DecimalValues.Count > right.DecimalValues.Count) { // If the left side has the same values as the right, // but then has more values, true. return true; } if (left.DecimalValues.Count < right.DecimalValues.Count) { // If the left side has the same values as the right, // but then the right side has more values, false. return false; } // If we get here both sides are equals, so false return false; } /* * Overloads the less than operator (<) to allow for a syntax as follows: * * bool b = dd1 < dd2; */ public static bool operator <(DottedDecimal left, DottedDecimal right) { int count = (left.DecimalValues.Count > right.DecimalValues.Count) ? right.DecimalValues.Count : left.DecimalValues.Count; for (int i = 0; i < count; i++) { // If right side is greater then true; if (left.DecimalValues[i] < right.DecimalValues[i]) { return true; } // If the left is greater then false; if (left.DecimalValues[i] > right.DecimalValues[i]) { return false; } // If it is equal, check the next decimal values over if (left.DecimalValues[i] == right.DecimalValues[i]) { continue; } } if (left.DecimalValues.Count > right.DecimalValues.Count) { // If the left side has the same values as the right, // but then has more values, false. return false; } if (left.DecimalValues.Count < right.DecimalValues.Count) { // If the left side has the same values as the right, // but then the right side has more values, true. return true; } // If we get here both sides are equals, so false return false; } /* * Overloads the equals operator (==) to allow for a syntax as follows: * * bool b = dd1 == dd2; */ public static bool operator ==(DottedDecimal left, DottedDecimal right) { // If there are more values in either side, they aren't equal if (!(left.DecimalValues.Count == right.DecimalValues.Count)) { return false; } for (int i = 0; i < left.DecimalValues.Count; i++) { // If any one value is not equal, then false if (left.DecimalValues[i] != right.DecimalValues[i]) { return false; } } // If you get here they are all equal so true return true; } /* * Overloads the not equals operator (!=) to allow for a syntax as follows: * * bool b = dd1 != dd2; */ public static bool operator !=(DottedDecimal left, DottedDecimal right) { // If there are more values in either side, they aren't equal if (!(left.DecimalValues.Count == right.DecimalValues.Count)) { return true; } for (int i = 0; i < left.DecimalValues.Count; i++) { // If any one value is not equal, then true if (left.DecimalValues[i] != right.DecimalValues[i]) { return true; } } // If you get here they are all equal so false return false; } public override bool Equals(object obj) { return base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode(); } public override string ToString() { return DottedDecimalString; } /* * Appends a new string value to the left side of a DottedDecimal object. Adding "12" to * 1.0.0 makes it 1.0.0.12. Because it is a string, you can also add multiple values at * a time so adding the string "12.24" makes 1.0.0.12.24. */ void AddToLeftSide(String inVal) { foreach (string decimalString in inVal.Split('.')) { _DecimalValues.Insert(0, Convert.ToInt64(inVal)); } } /* * Appends a new value to the left side of a DottedDecimal object. Adding 12 to * 1.0.0 makes it 1.0.0.12 */ public void AddToLeftSide(long inVal) { _DecimalValues.Insert(0, inVal); } /* * Appends a new string value to the right side of a DottedDecimal object. Adding "12" to * 1.0.0 makes it 12.1.0.0. Because it is a string, you can also add multiple values at * a time so adding the string "12.24" makes 12.24.1.0.0. */ public void AddToRightSide(String inVal) { foreach (string decimalString in inVal.Split('.')) { _DecimalValues.Add(Convert.ToInt64(decimalString)); } } /* * Appends a new value to the right side of a DottedDecimal object. Adding 12 to * 1.0.0 makes it 12.1.0.0 */ public void AddToRightSide(long inVal) { _DecimalValues.Add(inVal); } private string DottedDecimalListToString() { string retVal = ""; if (this.Direction == CompareDirection.LeftToRight) { foreach (long l in _DecimalValues) { if (!retVal.Equals("")) { retVal += "."; } retVal += l; } } else { for (int i = _DecimalValues.Count - 1; i >= 0; i--) { if (!retVal.Equals("")) { retVal += "."; } retVal += _DecimalValues[i]; } } return retVal; } private List<long> StringToDottedDecimalList(String inString) { List<long> retList = new List<long>(); foreach (string decimalString in inString.Split('.')) { retList.Add(Convert.ToInt64(decimalString)); } if (this.Direction == CompareDirection.RightToLeft) { retList.Reverse(); } return retList; } #endregion #region Interface Functions #region IComparable Members public int CompareTo(object inOjbect) { DottedDecimal dd = (DottedDecimal)inOjbect; return CompareTo(dd); } #endregion #region IComparable<dottedDecimal> Members public int CompareTo(DottedDecimal inDottedDecimal) { if (this < inDottedDecimal) return -1; if (this == inDottedDecimal) return 0; if (this > inDottedDecimal) return 1; return -2; // Should never get here. } #endregion #region IComparable<string> Members public int CompareTo(string inString) { DottedDecimal dd = new DottedDecimal(inString); return CompareTo(dd); } #endregion #region ICloneable Members public object Clone() { return new DottedDecimal(this.DottedDecimalString, this.Direction); } #endregion #region IEquatable<string> Members public bool Equals(string inString) { DottedDecimal dd = new DottedDecimal(inString); return this == dd; } #endregion #region IEquatable<dottedDecimal> Members public bool Equals(DottedDecimal inDottedDecimal) { return this == inDottedDecimal; } #endregion #endregion #region Enums public enum CompareDirection { LeftToRight, RightToLeft } #endregion } }
C++ DottedDecimal object for IP address and Versions
I tried to overload the common operators, if there is one you would like overloaded, let me know.
DottedDecimal.h
#pragma once #include <vector> #include <iostream> #include "windows.h" using namespace std; class DottedDecimal { public: // Constructors DottedDecimal(); // Default constructor DottedDecimal(DottedDecimal & inDottedDecimal); // Copy constructor DottedDecimal(string inString); DottedDecimal(char * inString); DottedDecimal(LPTSTR inString); // Destructors ~DottedDecimal(); // Public functions string GetDottedDecimal(); template <class T> void SetDottedDecimal(const T& t); vector<long> GetDecimals(); // Functions Overloading Operators friend ostream &operator<<(ostream & dataStream, DottedDecimal & dd); friend bool operator==(DottedDecimal & left, DottedDecimal & right); friend bool operator!=(DottedDecimal & left, DottedDecimal & right); friend bool operator>(DottedDecimal & left, DottedDecimal & right); friend bool operator>=(DottedDecimal & left, DottedDecimal & right); friend bool operator<(DottedDecimal & left, DottedDecimal & right); friend bool operator<=(DottedDecimal & left, DottedDecimal & right); private: // Member Variables vector<long> _decimals; // Private Functions void StringSplit(string inString, string inDelim, vector<string> * outResults); template <class T> string AnyTypeToString(const T& t); template <class T> void StringToAnyType(T& t, std::string inString); };
DottedDecimal.cpp
#include "StdAfx.h" #include "DottedDecimal.h" #include <iostream> #include <sstream> using namespace std; DottedDecimal::DottedDecimal() { } DottedDecimal::DottedDecimal(DottedDecimal & inDottedDecimal) { SetDottedDecimal(inDottedDecimal.GetDottedDecimal()); } DottedDecimal::DottedDecimal(string inString) { SetDottedDecimal(inString); } DottedDecimal::DottedDecimal(LPTSTR inString) { wstring ws = wstring(inString); string s; s.assign(ws.begin(), ws.end()); SetDottedDecimal(s); } DottedDecimal::DottedDecimal(char * inString) { SetDottedDecimal(inString); } DottedDecimal::~DottedDecimal() { } string DottedDecimal::GetDottedDecimal() { string retVal = ""; for (unsigned short i = 0; i < _decimals.size(); i++) { if (retVal.compare("") != 0) { retVal += "."; } retVal += AnyTypeToString(_decimals.at(i)); } return retVal; } template <class T> void DottedDecimal::SetDottedDecimal(const T& t) { _decimals.clear(); string valueString = AnyTypeToString(t); vector<string> * values = new vector<string>(); StringSplit(valueString, ".", values); for (unsigned short i = 0; i < values->size(); i++) { long l; StringToAnyType(l, values->at(i)); _decimals.push_back(l); } delete values; } vector<long> DottedDecimal::GetDecimals() { return _decimals; } ostream &operator<<(ostream & dataStream, DottedDecimal & dd) { dataStream << dd.GetDottedDecimal(); return dataStream; } bool operator==(DottedDecimal & left, DottedDecimal & right) { // If the value count isn't the same, then false if (left.GetDecimals().size() != right.GetDecimals().size()) return false; for (unsigned short i = 0; i < left.GetDecimals().size(); i++) { // If at any time values don't match, return false if (left.GetDecimals().at(i) != right.GetDecimals().at(i)) return false; } // If you get here they are the same. return true; } bool operator!=(DottedDecimal & left, DottedDecimal & right) { // If the value count isn't the same, then true if (left.GetDecimals().size() != right.GetDecimals().size()) return true; for (unsigned short i = 0; i < left.GetDecimals().size(); i++) { // If at any time values don't match, return true if (left.GetDecimals().at(i) != right.GetDecimals().at(i)) return true; } // If you get here they are the same. return false; } bool operator>(DottedDecimal & left, DottedDecimal & right) { // If one has three values and the other has four, only check three short count = (left.GetDecimals().size() <= right.GetDecimals().size() ? left.GetDecimals().size() : right.GetDecimals().size()); for (unsigned short i = 0; i < count; i++) { if (left.GetDecimals().at(i) > right.GetDecimals().at(i)) return true; } // If you get here, then the checked values were the same. // Return true if the left side has more values than the right side. if (left.GetDecimals().size() > right.GetDecimals().size() ) return true; else return false; } bool operator>=(DottedDecimal & left, DottedDecimal & right) { // If one has three values and the other has four, only check three short count = (left.GetDecimals().size() <= right.GetDecimals().size() ? left.GetDecimals().size() : right.GetDecimals().size()); for (unsigned short i = 0; i < count; i++) { // If any compared value is greater, return true; if (left.GetDecimals().at(i) > right.GetDecimals().at(i)) return true; } // If you get here, then the checked values were the same. // Return true if the left side has more values than or the same values as the right side. return left.GetDecimals().size() >= right.GetDecimals().size(); } bool operator<(DottedDecimal & left, DottedDecimal & right) { // If one has three values and the other has four, only check three short count = (left.GetDecimals().size() <= right.GetDecimals().size() ? left.GetDecimals().size() : right.GetDecimals().size()); for (unsigned short i = 0; i < count; i++) { // If any compared value is less, return true; if (left.GetDecimals().at(i) < right.GetDecimals().at(i)) return true; } // If you get here, then the checked values were the same. // Return true if the left side has less values than the right side. return left.GetDecimals().size() < right.GetDecimals().size(); } bool operator<=(DottedDecimal & left, DottedDecimal & right) { // If one has three values and the other has four, only check three short count = (left.GetDecimals().size() <= right.GetDecimals().size() ? left.GetDecimals().size() : right.GetDecimals().size()); for (unsigned short i = 0; i < count; i++) { // If any compared value is greater, return true; if (left.GetDecimals().at(i) > right.GetDecimals().at(i)) return true; } // If you get here, then the checked values were the same. // Return true if the left side has less values than or the same values as the right side. return left.GetDecimals().size() <= right.GetDecimals().size(); } // Private template <class T> string DottedDecimal::AnyTypeToString(const T& t) { std::stringstream ss; ss << t; return ss.str(); } template <class T> void DottedDecimal::StringToAnyType(T& t, std::string inString) { std::stringstream ss(inString); ss >> t; } void DottedDecimal::StringSplit(string inString, string inDelim, vector<string> * outResults) { int cutAt; while( (cutAt = inString.find_first_of(inDelim)) != inString.npos ) { if(cutAt > 0) { outResults->push_back(inString.substr(0,cutAt)); } inString = inString.substr(cutAt+1); } if(inString.length() > 0) { outResults->push_back(inString); } }
Copyright ® Rhyous.com – Linking to this article is allowed without permission and as many as ten lines of this article can be used along with this link. Any other use of this article is allowed only by permission of Rhyous.com.