diff --git a/.gitignore b/.gitignore
index 28aa2d1..19398a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,4 +39,4 @@ src/packages/**
*.ncrunch*
*.ndproj
*.nupkg
-**/project.lock.json
\ No newline at end of file
+src/ByteSize/pack
diff --git a/.travis.yml b/.travis.yml
index cef5031..dbdaaf9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,4 +4,4 @@ services:
- docker
script:
- - make build-in-docker
+ - make test-in-docker
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..a8a939e
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,27 @@
+# Adapted from https://github.com/andrewlock/docker-dotnet-mono/blob/master/Dockerfile
+FROM mcr.microsoft.com/dotnet/core/sdk:2.1.700 AS builder
+
+# Install mono
+ENV MONO_VERSION 5.18.0.225
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends gnupg dirmngr \
+ && rm -rf /var/lib/apt/lists/* \
+ && export GNUPGHOME="$(mktemp -d)" \
+ && gpg --batch --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF \
+ && gpg --batch --export --armor 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF > /etc/apt/trusted.gpg.d/mono.gpg.asc \
+ && gpgconf --kill all \
+ && rm -rf "$GNUPGHOME" \
+ && apt-key list | grep Xamarin \
+ && apt-get purge -y --auto-remove gnupg dirmngr
+
+RUN echo "deb http://download.mono-project.com/repo/debian stable-stretch/snapshots/$MONO_VERSION main" > /etc/apt/sources.list.d/mono-official-stable.list \
+ && apt-get update \
+ && apt-get install -y mono-runtime \
+ && rm -rf /var/lib/apt/lists/* /tmp/*
+
+RUN apt-get update \
+ && apt-get install -y binutils curl mono-devel ca-certificates-mono fsharp mono-vbnc nuget referenceassemblies-pcl \
+ && rm -rf /var/lib/apt/lists/* /tmp/*
+
+WORKDIR /sln
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index d458b58..9884ab8 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2013-2017 Omar Khudeira (http://omar.io)
+Copyright (c) 2013-2019 Omar Khudeira (http://omar.io)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Makefile b/Makefile
index d1294eb..34cd919 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,13 @@
+.PHONY: build test pack
+
+# Check to see if Mono exists. If it does, use that path to build against .NET 4.5
+ifneq ("$(wildcard /usr/local/lib/mono/)","")
+ # MONO_REFERENCE_ASSEMBLIES is automatically pulled in ByteSizeLib.csproj
+ # to allow building against .NET Framework on a Mac where I do most of my
+ # development.
+ export MONO_REFERENCE_ASSEMBLIES=/usr/local/lib/mono
+endif
+
build:
dotnet build src
@@ -7,8 +17,12 @@ test:
pack:
dotnet pack src/ByteSizeLib -c Release -o pack
-build-in-docker:
- # Use an image with both Mono and .NET Core SDK installed
- docker run -td --name bytesize -v $(CURDIR):/bytesize andrewlock/dotnet-mono
+test-in-docker:
+ # Stop and delete conatiner if already exists
+ docker stop bytesize || true && docker rm bytesize || true
+ # Use an image with both Mono and .NET Core SDK installed so we can build
+ # against .NET Framework 4.5
+ docker build -t bytesize-build .
+ docker run -td --name bytesize -v $(CURDIR):/bytesize bytesize-build
docker exec bytesize bash -c "cd /bytesize/src && msbuild -t:restore ByteSizeLib.sln"
docker exec bytesize bash -c "cd /bytesize/src && dotnet test ByteSizeLib.Tests"
diff --git a/README.md b/README.md
index 8867f86..956f0c8 100644
--- a/README.md
+++ b/README.md
@@ -1,46 +1,78 @@
# ByteSize
-`ByteSize` is a utility class that makes byte size representation in code easier by removing ambiguity of the value being represented.
+`ByteSize` is a utility class that makes byte size representation in code easier
+by removing ambiguity of the value being represented.
`ByteSize` is to bytes what `System.TimeSpan` is to time.
[![](https://travis-ci.org/omar/ByteSize.svg?branch=master)](https://travis-ci.org/omar/ByteSize)
[![Stable nuget](https://img.shields.io/nuget/v/ByteSize.svg)](https://www.nuget.org/packages/ByteSize/)
-#### Building
+#### Development
-* Windows: use Visual Studio
-* Mac OS X
- * Install [Mono](http://www.mono-project.com/download/).
- * NOTE: using `brew install mono` will not install the PCL libraries required to build the PCL compatible DLLs. The PCL libraries can be installed by running the installer downloaded from http://www.mono-project.com/download/.
- * Run `make build` in terminal.
-* Linux
- * Install [Mono](http://www.mono-project.com/docs/getting-started/install/linux/) and the reference assemblies (`sudo apt-get referenceassemblies-pcl`).
- * Run `make build` in terminal.
+- Install [.NET Core SDK](https://dotnet.microsoft.com/download)
+- Build: `make build`
+- Test: `make test`
-## Usage
+## v2 Breaking Changes
-`ByteSize` assumes `1 kilobyte` = `1024 bytes`. See [why here](http://omar.io/2017/01/16/when-technically-right-is-wrong-kilobytes.html).
+### Ratio Changes (HUGE BREAKING CHANGE)
+
+By default `ByteSize` now assumes `1 KB == 1000 B` and `1 KiB == 1024 B` to
+adhere to the IEC and NIST standards (https://en.wikipedia.org/wiki/Binary_prefix).
+In version 1 `ByteSize` assumed `1 KB == 1024 B`, that means if you're upgrading
+from v1, you'll see differences in values.
+
+When you upgrade an existing application to v2 your existing code will be using
+the decimal representation of bytes (i.e. `1 KB == 1000 B`). If the difference
+in calculation is not material to your application, you don't need to change anything.
+
+However, if you want to use `1 KiB == 1024 B`, then you'll need to change all
+`ByteSize` calls to the respective method. For example, calls to
+`ByteSize.FromKiloByte` need to be changed to `ByteSize.FromKibiByte`.
+
+Lastly, `ByteSize` no longer supports the ratio of `1 KB == 1024 B`. Note this
+is ***kilo***_bytes_ to _bytes_. The only ratio of `1 == 1024` is ***kibi***_bytes_
+to _bytes_.
+
+### Other Breaking Changes
+
+- Renamed property `LargestWholeNumberSymbol` and `LargestWholeNumberValue` to `LargestWholeNumberDecimalSymbol` and `LargestWholeNumberDecimalValue` respectively.
+- Drop support for all platforms _except_ `netstandard1.0` and `net45`.
+
+## Usage
+
+`ByteSize` adheres to the IEC standard, see this [Wikipedia article](https://en.wikipedia.org/wiki/Kilobyte#Definitions_and_usage).
+That means `ByteSize` assumes:
+
+- `1 kilobyte` = `1000 bytes` with 2 letter abbrevations `b`, `B`,`KB`, `MB`, `GB`, `TB`, `PB`.
+- `1 kibibyte` = `1024 bytes` with 3 letter abbrevations `b`, `B`,`KiB`, `MiB`, `GiB`, `TiB`, `PiB`.
+
+`ByteSize` manages conversion of the values internally and provides methods to create and retrieve the values as needed. See the examples below.
+
+### Example
Without `ByteSize`:
```c#
-static double MaxFileSizeMBs = 1.5;
+double maxFileSizeMBs = 1.5;
-// I need it in KBs!
-var kilobytes = MaxFileSizeMBs * 1024; // 1536
+// I need it in KBs and KiBs!
+var kilobytes = maxFileSizeMBs * 1000; // 1500
+var kibibytes = maxFileSizeMBs * 1024; // 1536
```
With `ByteSize`:
```c#
-static MaxFileSize = ByteSize.FromMegaBytes(1.5);
+var maxFileSize = ByteSize.FromMegaBytes(1.5);
-// I have it in KBs!
-MaxFileSize.KiloBytes; // 1536
+// I have it in KBs and KiBs!!
+maxFileSize.KiloBytes; // 1500
+maxFileSize.KibiBytes; // 1464.84376
```
-`ByteSize` behaves like any other struct backed by a numerical value.
+`ByteSize` behaves like any other struct backed by a numerical value allowing arithmetic operations between two objects.
```c#
// Add
@@ -62,43 +94,68 @@ delta = delta.AddMegaBytes(-100);
You can create a `ByteSize` object from `bits`, `bytes`, `kilobytes`, `megabytes`, `gigabytes`, and `terabytes`.
```c#
-new ByteSize(1.5); // Constructor takes in bytes
+new ByteSize(15); // Constructor takes in bits (long)
+new ByteSize(1.5); // ... or bytes (double)
// Static Constructors
-ByteSize.FromBits(10); // Bits are whole numbers only
+ByteSize.FromBits(10); // Same as constructor
ByteSize.FromBytes(1.5); // Same as constructor
+
+// Decimal: 1 KB = 1000 B
ByteSize.FromKiloBytes(1.5);
ByteSize.FromMegaBytes(1.5);
ByteSize.FromGigaBytes(1.5);
ByteSize.FromTeraBytes(1.5);
+
+// Binary: 1 KiB = 1024 B
+ByteSize.FromKibiBytes(1.5);
+ByteSize.FromMebiBytes(1.5);
+ByteSize.FromGibiBytes(1.5);
+ByteSize.FromTebiBytes(1.5);
```
### Properties
-A `ByteSize` object contains representations in `bits`, `bytes`, `kilobytes`, `megabytes`, `gigabytes`, and `terabytes`.
+A `ByteSize` object contains representations in:
+
+- `bits`, `bytes`
+- `kilobytes`, `megabytes`, `gigabytes`, and `terabytes`
+- `kibibytes`, `mebibytes`, `gibibytes`, and `tebibytes`
```c#
var maxFileSize = ByteSize.FromKiloBytes(10);
-maxFileSize.Bits; // 81920
-maxFileSize.Bytes; // 10240
+maxFileSize.Bits; // 80000
+maxFileSize.Bytes; // 10000
+
+// Decimal
maxFileSize.KiloBytes; // 10
-maxFileSize.MegaBytes; // 0.009765625
-maxFileSize.GigaBytes; // 9.53674316e-6
-maxFileSize.TeraBytes; // 9.31322575e-9
+maxFileSize.MegaBytes; // 0.01
+maxFileSize.GigaBytes; // 1E-05
+maxFileSize.TeraBytes; // 1E-08
+
+// Binary
+maxFileSize.KibiBytes; // 9.765625
+maxFileSize.MebiBytes; // 0.0095367431640625
+maxFileSize.GibiBytes; // 9.31322574615479E-06
+maxFileSize.TebiBytes; // 9.09494701772928E-09
```
-A `ByteSize` object also contains two properties that represent the largest metric prefix symbol and value.
+A `ByteSize` object also contains four properties that represent the largest whole number symbol and value.
```c#
var maxFileSize = ByteSize.FromKiloBytes(10);
-maxFileSize.LargestWholeNumberSymbol; // "KB"
-maxFileSize.LargestWholeNumberValue; // 10
+maxFileSize.LargestWholeNumberDecimalSymbol; // "KB"
+maxFileSize.LargestWholeNumberDecimalValue; // 10
+maxFileSize.LargestWholeNumberBinarySymbol; // "KiB"
+maxFileSize.LargestWholeNumberBinaryValue; // 9.765625
```
### String Representation
+By default a `ByteSize` object uses the decimal value for string representation.
+
All string operations are localized to use the number decimal separator of the culture set in `Thread.CurrentThread.CurrentCulture`.
#### ToString
@@ -106,20 +163,32 @@ All string operations are localized to use the number decimal separator of the c
`ByteSize` comes with a handy `ToString` method that uses the largest metric prefix whose value is greater than or equal to 1.
```c#
+// By default the decimal values are used
ByteSize.FromBits(7).ToString(); // 7 b
ByteSize.FromBits(8).ToString(); // 1 B
-ByteSize.FromKiloBytes(.5).ToString(); // 512 B
-ByteSize.FromKiloBytes(1000).ToString(); // 1000 KB
-ByteSize.FromKiloBytes(1024).ToString(); // 1 MB
-ByteSize.FromGigabytes(.5).ToString(); // 512 MB
-ByteSize.FromGigabytes(1024).ToString(); // 1 TB
+ByteSize.FromKiloBytes(.5).ToString(); // 500 B
+ByteSize.FromKiloBytes(999).ToString(); // 999 KB
+ByteSize.FromKiloBytes(1000).ToString(); // 1 MB
+ByteSize.FromGigabytes(.5).ToString(); // 500 MB
+ByteSize.FromGigabytes(1000).ToString(); // 1 TB
+
+// Binary
+ByteSize.Parse("1.55 kb").ToString("kib"); // 1.51 kib
```
#### Formatting
-The `ToString` method accepts a single `string` parameter to format the output. The formatter can contain the symbol of the value to display: `b`, `B`, `KB`, `MB`, `GB`, `TB`. The formatter uses the built in [`double.ToString` method](http://msdn.microsoft.com/en-us/library/kfsatb94\(v=vs.110\).aspx).
+The `ToString` method accepts a single `string` parameter to format the output.
+The formatter can contain the symbol of the value to display.
+
+- Base: `b`, `B`
+- Decimal: `KB`, `MB`, `GB`, `TB`
+- Binary: `KiB`, `MiB`, `GiB`, `TiB`
-The default number format is `0.##` which rounds the number to two decimal places and outputs only `0` if the value is `0`.
+The formatter uses the built in [`double.ToString` method](http://msdn.microsoft.com/en-us/library/kfsatb94\(v=vs.110\).aspx).
+
+The default number format is `0.##` which rounds the number to two decimal
+places and outputs only `0` if the value is `0`.
You can include symbol and number formats.
@@ -154,11 +223,14 @@ zeroBytes.ToString("0.## mb"); // 0 mb
`ByteSize` has a `Parse` and `TryParse` method similar to other base classes.
-Like other `TryParse` methods, `ByteSize.TryParse` returns `boolean` value indicating whether or not the parsing was successful. If the value is parsed it is output to the `out` parameter supplied.
+Like other `TryParse` methods, `ByteSize.TryParse` returns `boolean`
+value indicating whether or not the parsing was successful. If the value is
+parsed it is output to the `out` parameter supplied.
```c#
ByteSize output;
ByteSize.TryParse("1.5mb", out output);
+ByteSize.TryParse("1.5mib", out output);
// Invalid
ByteSize.Parse("1.5 b"); // Can't have partial bits
@@ -174,18 +246,17 @@ ByteSize.Parse("1.55 mB");
ByteSize.Parse("1.55 mb");
ByteSize.Parse("1.55 GB");
ByteSize.Parse("1.55 gB");
-ByteSize.Parse("1.55 gb");
-ByteSize.Parse("1.55 TB");
-ByteSize.Parse("1.55 tB");
-ByteSize.Parse("1.55 tb");
-ByteSize.Parse("1,55 kb"); // de-DE culture
+ByteSize.Parse("1.55 gib");
+ByteSize.Parse("1.55 TiB");
+ByteSize.Parse("1.55 tiB");
+ByteSize.Parse("1.55 tib");
+ByteSize.Parse("1,55 kib"); // de-DE culture
```
#### Author and License
Omar Khudeira ([http://omar.io](http://omar.io))
-Copyright (c) 2013-2016 Omar Khudeira. All rights reserved.
+Copyright (c) 2013-2019 Omar Khudeira. All rights reserved.
Released under MIT License (see LICENSE file).
-
diff --git a/docs/binary-byte.md b/docs/binary-byte.md
new file mode 100644
index 0000000..95378f1
--- /dev/null
+++ b/docs/binary-byte.md
@@ -0,0 +1,68 @@
+# Binary Byte
+
+ByteSize started off with:
+
+- 1 kilobyte = 1024 bytes
+- 2 letter abbreviation (KB, GB etc.)
+
+See why [here](https://omar.io/2017/01/16/when-technically-right-is-wrong-kilobytes.html).
+
+Since then, there have been a few requests to support the [IEC binary prefix](https://en.wikipedia.org/wiki/Binary_prefix#kibi),
+see [issue#1](https://github.com/omar/ByteSize/issues/1) and [Humanizr/Humanizer/issues/592](https://github.com/Humanizr/Humanizer/issues/592).
+This document will include the rational for the design of implementing the IEC standard.
+
+## Research
+
+| Vendor | Abbreviation | Ratio | [IEC Standard] | Source
+| --- | --- | --- | --- | ---
+| ByteSize | KB, GB, etc. | 1 = 1024 | No |
+| GCP | KB, GB, etc. | 1 = 1024 | No | https://cloud.google.com/storage/pricing
+| AWS | KB, GB, etc. | 1 = 1024 | No | https://aws.amazon.com/ebs/features/
+| AWS Glossary | KB, GB, etc. | 1 = 1000 | Yes | https://docs.aws.amazon.com/general/latest/gr/glos-chap.html
+| AWS Glossary | KiB, GiB, etc. | 1 = 1024 | Yes | https://docs.aws.amazon.com/general/latest/gr/glos-chap.html
+| Azure (RAM) | KiB, GiB, etc. | 1 = 1024 | Yes | https://azure.microsoft.com/en-gb/blog/largest-vm-in-the-cloud/
+| Azure (Disk) | KB, GB, etc. | 1 = 1000 | Yes | https://azure.microsoft.com/en-gb/blog/largest-vm-in-the-cloud/
+| Mac OS X Leopard + | KB, GB, etc. | 1 = 1000 | Yes | https://support.apple.com/en-us/HT201402
+| iOS 11 + | KB, GB, etc. | 1 = 1000 | Yes | https://support.apple.com/en-us/HT201402
+
+In summary, developers are _attempting_ to adhere to the IEC standard by either:
+
+- Changing the abbreviation and ratio to match the IEC binary standard, or;
+- Changing the ratio they've used in the past to match the decimal values
+
+[IEC Standard]: https://en.wikipedia.org/wiki/Binary_prefix#kibi
+
+## Implementation Considerations
+
+1. Two structs that represents the decimal (`DecimalByteSize`) and binary
+ values (`BinaryByteSize`).
+ - Pros
+ - Clear separation of what's being represented by the object.
+ - Solve the namespace collision that forced the `ByteSize` namespace.
+ - Cons
+ - Swapping between binary and decimal representation requires two
+ objects. Maybe can provide a simple way to go from one to the other:
+ `BinaryByteSize.FromDecimalByteSize` and
+ `DecimalByteSize.FromBinaryByteSize`. No idea how valuable or needed
+ this would be though.
+ - Breaking change since `BinaryByteSize` has the same ratio as the
+ original `ByteSize` class, but not the text representation.
+ (See "Backwards Compatibility Note" below).
+ - Backwards Compatibility Note
+ - v1.x of ByteSize could ship with two additional structs
+ `DecimalByteSize` and `BinaryByteSize` but keep `ByteSize` with it's
+ current implementation.
+ - v2.0 of ByteSize could break compatiblity and remove the `ByteSize`
+ struct in favor of `DecimalByteSize` and `BinaryByteSize`.
+
+2. Single struct
+ - Flat properties (e.g. `value.KiloByte` and `value.KibiByte`).
+ - Pros
+ - Single object that allows use of both standards.
+ - Cons
+ - Autocomplete lists will have twice as many methods and properties
+ - Nested properties (e.g. `value.Decimal.KiloByte` and `value.Binary.KibiByte`).
+ - Pros
+ - Single object that allows use of both standards.
+ - Cons
+ - Autocomplete lists will have twice as many methods and properties
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..c6c08c9
--- /dev/null
+++ b/global.json
@@ -0,0 +1,8 @@
+{
+ "projects": [
+ "src"
+ ],
+ "sdk": {
+ "version": "2.1.700"
+ }
+}
diff --git a/src/ByteSizeLib.Tests/ArithmeticMethods.cs b/src/ByteSizeLib.Tests/ArithmeticMethods.cs
index 1e0802f..1a1bca7 100644
--- a/src/ByteSizeLib.Tests/ArithmeticMethods.cs
+++ b/src/ByteSizeLib.Tests/ArithmeticMethods.cs
@@ -32,66 +32,6 @@ public void AddBytesMethod()
Assert.Equal(16, size.Bits);
}
- [Fact]
- public void AddKiloBytesMethod()
- {
- var size = ByteSize.FromKiloBytes(2).AddKiloBytes(2);
-
- Assert.Equal(4 * 1024 * 8, size.Bits);
- Assert.Equal(4 * 1024, size.Bytes);
- Assert.Equal(4, size.KiloBytes);
- }
-
- [Fact]
- public void AddMegaBytesMethod()
- {
- var size = ByteSize.FromMegaBytes(2).AddMegaBytes(2);
-
- Assert.Equal(4 * 1024 * 1024 * 8, size.Bits);
- Assert.Equal(4 * 1024 * 1024, size.Bytes);
- Assert.Equal(4 * 1024, size.KiloBytes);
- Assert.Equal(4, size.MegaBytes);
- }
-
- [Fact]
- public void AddGigaBytesMethod()
- {
- var size = ByteSize.FromGigaBytes(2).AddGigaBytes(2);
-
- Assert.Equal(4d * 1024 * 1024 * 1024 * 8, size.Bits);
- Assert.Equal(4d * 1024 * 1024 * 1024, size.Bytes);
- Assert.Equal(4d * 1024 * 1024, size.KiloBytes);
- Assert.Equal(4d * 1024, size.MegaBytes);
- Assert.Equal(4d, size.GigaBytes);
- }
-
- [Fact]
- public void AddTeraBytesMethod()
- {
- var size = ByteSize.FromTeraBytes(2).AddTeraBytes(2);
-
- Assert.Equal(4d * 1024 * 1024 * 1024 * 1024 * 8, size.Bits);
- Assert.Equal(4d * 1024 * 1024 * 1024 * 1024, size.Bytes);
- Assert.Equal(4d * 1024 * 1024 * 1024, size.KiloBytes);
- Assert.Equal(4d * 1024 * 1024, size.MegaBytes);
- Assert.Equal(4d * 1024, size.GigaBytes);
- Assert.Equal(4d, size.TeraBytes);
- }
-
- [Fact]
- public void AddPetaBytesMethod()
- {
- var size = ByteSize.FromPetaBytes(2).AddPetaBytes(2);
-
- Assert.Equal(4d * 1024 * 1024 * 1024 * 1024 * 1024 * 8, size.Bits);
- Assert.Equal(4d * 1024 * 1024 * 1024 * 1024 * 1024, size.Bytes);
- Assert.Equal(4d * 1024 * 1024 * 1024 * 1024, size.KiloBytes);
- Assert.Equal(4d * 1024 * 1024 * 1024, size.MegaBytes);
- Assert.Equal(4d * 1024 * 1024, size.GigaBytes);
- Assert.Equal(4d * 1024, size.TeraBytes);
- Assert.Equal(4d, size.PetaBytes);
- }
-
[Fact]
public void SubtractMethod()
{
@@ -141,5 +81,13 @@ public void DecrementOperator()
Assert.Equal(8, size.Bits);
Assert.Equal(1, size.Bytes);
}
+
+ [Fact]
+ public void MaxValueBits()
+ {
+ var size = ByteSize.FromBits(long.MaxValue);
+
+ Assert.Equal(long.MaxValue, size.Bits);
+ }
}
}
diff --git a/src/ByteSizeLib.Tests/Binary/ArithmeticMethods.cs b/src/ByteSizeLib.Tests/Binary/ArithmeticMethods.cs
new file mode 100644
index 0000000..dff3ac0
--- /dev/null
+++ b/src/ByteSizeLib.Tests/Binary/ArithmeticMethods.cs
@@ -0,0 +1,67 @@
+using Xunit;
+
+namespace ByteSizeLib.Tests.Binary
+{
+ public class ArithmeticMethods
+ {
+ [Fact]
+ public void AddKibiBytesMethod()
+ {
+ var size = ByteSize.FromKibiBytes(2).AddKibiBytes(2);
+
+ Assert.Equal(4 * 1024 * 8, size.Bits);
+ Assert.Equal(4 * 1024, size.Bytes);
+ Assert.Equal(4, size.KibiBytes);
+ }
+
+ [Fact]
+ public void AddMebiBytesMethod()
+ {
+ var size = ByteSize.FromMebiBytes(2).AddMebiBytes(2);
+
+ Assert.Equal(4 * 1024 * 1024 * 8, size.Bits);
+ Assert.Equal(4 * 1024 * 1024, size.Bytes);
+ Assert.Equal(4 * 1024, size.KibiBytes);
+ Assert.Equal(4, size.MebiBytes);
+ }
+
+ [Fact]
+ public void AddGibiBytesMethod()
+ {
+ var size = ByteSize.FromGibiBytes(2).AddGibiBytes(2);
+
+ Assert.Equal(4d * 1024 * 1024 * 1024 * 8, size.Bits);
+ Assert.Equal(4d * 1024 * 1024 * 1024, size.Bytes);
+ Assert.Equal(4d * 1024 * 1024, size.KibiBytes);
+ Assert.Equal(4d * 1024, size.MebiBytes);
+ Assert.Equal(4d, size.GibiBytes);
+ }
+
+ [Fact]
+ public void AddTebiBytesMethod()
+ {
+ var size = ByteSize.FromTebiBytes(2).AddTebiBytes(2);
+
+ Assert.Equal(4d * 1024 * 1024 * 1024 * 1024 * 8, size.Bits);
+ Assert.Equal(4d * 1024 * 1024 * 1024 * 1024, size.Bytes);
+ Assert.Equal(4d * 1024 * 1024 * 1024, size.KibiBytes);
+ Assert.Equal(4d * 1024 * 1024, size.MebiBytes);
+ Assert.Equal(4d * 1024, size.GibiBytes);
+ Assert.Equal(4d, size.TebiBytes);
+ }
+
+ [Fact]
+ public void AddPebiBytesMethod()
+ {
+ var size = ByteSize.FromPebiBytes(2).AddPebiBytes(2);
+
+ Assert.Equal(4d * 1024 * 1024 * 1024 * 1024 * 1024 * 8, size.Bits);
+ Assert.Equal(4d * 1024 * 1024 * 1024 * 1024 * 1024, size.Bytes);
+ Assert.Equal(4d * 1024 * 1024 * 1024 * 1024, size.KibiBytes);
+ Assert.Equal(4d * 1024 * 1024 * 1024, size.MebiBytes);
+ Assert.Equal(4d * 1024 * 1024, size.GibiBytes);
+ Assert.Equal(4d * 1024, size.TebiBytes);
+ Assert.Equal(4d, size.PebiBytes);
+ }
+ }
+}
diff --git a/src/ByteSizeLib.Tests/Binary/CreatingMethods.cs b/src/ByteSizeLib.Tests/Binary/CreatingMethods.cs
new file mode 100644
index 0000000..e8bd74b
--- /dev/null
+++ b/src/ByteSizeLib.Tests/Binary/CreatingMethods.cs
@@ -0,0 +1,96 @@
+using Xunit;
+
+namespace ByteSizeLib.Tests.BinaryByteSizeTests
+{
+ public class CreatingMethods
+ {
+ [Fact]
+ public void Constructor()
+ {
+ // Arrange
+ double bytes = 1125899906842624;
+
+ // Act
+ var result = new ByteSize(bytes);
+
+ // Assert
+ Assert.Equal(bytes * 8, result.Bits);
+ Assert.Equal(bytes, result.Bytes);
+ Assert.Equal(bytes / 1024, result.KibiBytes);
+ Assert.Equal(bytes / 1024 / 1024, result.MebiBytes);
+ Assert.Equal(bytes / 1024 / 1024 / 1024, result.GibiBytes);
+ Assert.Equal(bytes / 1024 / 1024 / 1024 / 1024, result.TebiBytes);
+ Assert.Equal(1, result.PebiBytes);
+ }
+
+ [Fact]
+ public void FromKibiBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromKibiBytes(value);
+
+ // Assert
+ Assert.Equal(1536, result.Bytes);
+ Assert.Equal(1.5, result.KibiBytes);
+ }
+
+ [Fact]
+ public void FromMebiBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromMebiBytes(value);
+
+ // Assert
+ Assert.Equal(1572864, result.Bytes);
+ Assert.Equal(1.5, result.MebiBytes);
+ }
+
+ [Fact]
+ public void FromGibiBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromGibiBytes(value);
+
+ // Assert
+ Assert.Equal(1610612736, result.Bytes);
+ Assert.Equal(1.5, result.GibiBytes);
+ }
+
+ [Fact]
+ public void FromTebiBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromTebiBytes(value);
+
+ // Assert
+ Assert.Equal(1649267441664, result.Bytes);
+ Assert.Equal(1.5, result.TebiBytes);
+ }
+
+ [Fact]
+ public void FromPebiBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromPebiBytes(value);
+
+ // Assert
+ Assert.Equal(1688849860263936, result.Bytes);
+ Assert.Equal(1.5, result.PebiBytes);
+ }
+ }
+}
diff --git a/src/ByteSizeLib.Tests/Binary/ParsingMethods.cs b/src/ByteSizeLib.Tests/Binary/ParsingMethods.cs
new file mode 100644
index 0000000..4dfb442
--- /dev/null
+++ b/src/ByteSizeLib.Tests/Binary/ParsingMethods.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Globalization;
+using System.Threading;
+using Xunit;
+
+namespace ByteSizeLib.Tests.BinaryByteSizeTests
+{
+ public class ParsingMethods
+ {
+ [Fact]
+ public void ParseKiB()
+ {
+ string val = "1020KiB";
+ var expected = ByteSize.FromKibiBytes(1020);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ParseMiB()
+ {
+ string val = "1000MiB";
+ var expected = ByteSize.FromMebiBytes(1000);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ParseGiB()
+ {
+ string val = "805GiB";
+ var expected = ByteSize.FromGibiBytes(805);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ParseTiB()
+ {
+ string val = "100TiB";
+ var expected = ByteSize.FromTebiBytes(100);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ParsePiB()
+ {
+ string val = "100PiB";
+ var expected = ByteSize.FromPebiBytes(100);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+ }
+}
diff --git a/src/ByteSizeLib.Tests/Binary/ToBinaryStringMethod.cs b/src/ByteSizeLib.Tests/Binary/ToBinaryStringMethod.cs
new file mode 100644
index 0000000..3fc2cbe
--- /dev/null
+++ b/src/ByteSizeLib.Tests/Binary/ToBinaryStringMethod.cs
@@ -0,0 +1,21 @@
+using Xunit;
+
+namespace ByteSizeLib.Tests.BinaryByteSizeTests
+{
+ public class ToBinaryStringMethod
+ {
+
+ [Fact]
+ public void ReturnsDefaultRepresenation()
+ {
+ // Arrange
+ var b = ByteSize.FromKiloBytes(10);
+
+ // Act
+ var result = b.ToBinaryString();
+
+ // Assert
+ Assert.Equal("9.77 KiB", result);
+ }
+ }
+}
diff --git a/src/ByteSizeLib.Tests/Binary/ToStringMethod.cs b/src/ByteSizeLib.Tests/Binary/ToStringMethod.cs
new file mode 100644
index 0000000..15c4dd3
--- /dev/null
+++ b/src/ByteSizeLib.Tests/Binary/ToStringMethod.cs
@@ -0,0 +1,87 @@
+using System.Globalization;
+using System.Threading;
+using Xunit;
+
+namespace ByteSizeLib.Tests.BinaryByteSizeTests
+{
+ public class ToStringMethod
+ {
+ [Fact]
+ public void ReturnsKibiBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromKibiBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### KiB");
+
+ // Assert
+ Assert.Equal("10 KiB", result);
+ }
+
+ [Fact]
+ public void ReturnsMebiBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromMebiBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### MiB");
+
+ // Assert
+ Assert.Equal("10 MiB", result);
+ }
+
+ [Fact]
+ public void ReturnsGibiBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromGibiBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### GiB");
+
+ // Assert
+ Assert.Equal("10 GiB", result);
+ }
+
+ [Fact]
+ public void ReturnsTebiBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromTebiBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### TiB");
+
+ // Assert
+ Assert.Equal("10 TiB", result);
+ }
+
+ [Fact]
+ public void ReturnsPebiBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromPebiBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### PiB");
+
+ // Assert
+ Assert.Equal("10 PiB", result);
+ }
+
+ [Fact]
+ public void ReturnsSelectedFormat()
+ {
+ // Arrange
+ var b = ByteSize.FromTebiBytes(10);
+
+ // Act
+ var result = b.ToString("0.0 TiB");
+
+ // Assert
+ Assert.Equal(10.ToString("0.0 TiB"), result);
+ }
+ }
+}
diff --git a/src/ByteSizeLib.Tests/ByteSizeLib.Tests.csproj b/src/ByteSizeLib.Tests/ByteSizeLib.Tests.csproj
old mode 100644
new mode 100755
index b7b089d..e5a5676
--- a/src/ByteSizeLib.Tests/ByteSizeLib.Tests.csproj
+++ b/src/ByteSizeLib.Tests/ByteSizeLib.Tests.csproj
@@ -1,18 +1,20 @@
-
+
netcoreapp2.1
- true
+
+ false
-
-
-
+
-
+
+
+
+
-
\ No newline at end of file
+
diff --git a/src/ByteSizeLib.Tests/CreatingMethods.cs b/src/ByteSizeLib.Tests/CreatingMethods.cs
index 066ebd2..2749f35 100644
--- a/src/ByteSizeLib.Tests/CreatingMethods.cs
+++ b/src/ByteSizeLib.Tests/CreatingMethods.cs
@@ -4,25 +4,6 @@ namespace ByteSizeLib.Tests
{
public class CreatingMethods
{
- [Fact]
- public void Constructor()
- {
- // Arrange
- double byteSize = 1125899906842624;
-
- // Act
- var result = new ByteSize(byteSize);
-
- // Assert
- Assert.Equal(byteSize * 8, result.Bits);
- Assert.Equal(byteSize, result.Bytes);
- Assert.Equal(byteSize / 1024, result.KiloBytes);
- Assert.Equal(byteSize / 1024 / 1024, result.MegaBytes);
- Assert.Equal(byteSize / 1024 / 1024 / 1024, result.GigaBytes);
- Assert.Equal(byteSize / 1024 / 1024 / 1024 / 1024, result.TeraBytes);
- Assert.Equal(1, result.PetaBytes);
- }
-
[Fact]
public void FromBitsMethod()
{
@@ -50,75 +31,5 @@ public void FromBytesMethod()
Assert.Equal(12, result.Bits);
Assert.Equal(1.5, result.Bytes);
}
-
- [Fact]
- public void FromKiloBytesMethod()
- {
- // Arrange
- double value = 1.5;
-
- // Act
- var result = ByteSize.FromKiloBytes(value);
-
- // Assert
- Assert.Equal(1536, result.Bytes);
- Assert.Equal(1.5, result.KiloBytes);
- }
-
- [Fact]
- public void FromMegaBytesMethod()
- {
- // Arrange
- double value = 1.5;
-
- // Act
- var result = ByteSize.FromMegaBytes(value);
-
- // Assert
- Assert.Equal(1572864, result.Bytes);
- Assert.Equal(1.5, result.MegaBytes);
- }
-
- [Fact]
- public void FromGigaBytesMethod()
- {
- // Arrange
- double value = 1.5;
-
- // Act
- var result = ByteSize.FromGigaBytes(value);
-
- // Assert
- Assert.Equal(1610612736, result.Bytes);
- Assert.Equal(1.5, result.GigaBytes);
- }
-
- [Fact]
- public void FromTeraBytesMethod()
- {
- // Arrange
- double value = 1.5;
-
- // Act
- var result = ByteSize.FromTeraBytes(value);
-
- // Assert
- Assert.Equal(1649267441664, result.Bytes);
- Assert.Equal(1.5, result.TeraBytes);
- }
-
- [Fact]
- public void FromPetaBytesMethod()
- {
- // Arrange
- double value = 1.5;
-
- // Act
- var result = ByteSize.FromPetaBytes(value);
-
- // Assert
- Assert.Equal(1688849860263936, result.Bytes);
- Assert.Equal(1.5, result.PetaBytes);
- }
}
}
diff --git a/src/ByteSizeLib.Tests/Decimal/ArithmeticMethods.cs b/src/ByteSizeLib.Tests/Decimal/ArithmeticMethods.cs
new file mode 100644
index 0000000..7d00c2e
--- /dev/null
+++ b/src/ByteSizeLib.Tests/Decimal/ArithmeticMethods.cs
@@ -0,0 +1,67 @@
+using Xunit;
+
+namespace ByteSizeLib.Tests.Decimal
+{
+ public class ArithmeticMethods
+ {
+ [Fact]
+ public void AddKiloBytesMethod()
+ {
+ var size = ByteSize.FromKiloBytes(2).AddKiloBytes(2);
+
+ Assert.Equal(4 * 1000 * 8, size.Bits);
+ Assert.Equal(4 * 1000, size.Bytes);
+ Assert.Equal(4, size.KiloBytes);
+ }
+
+ [Fact]
+ public void AddMegaBytesMethod()
+ {
+ var size = ByteSize.FromMegaBytes(2).AddMegaBytes(2);
+
+ Assert.Equal(4 * 1000 * 1000 * 8, size.Bits);
+ Assert.Equal(4 * 1000 * 1000, size.Bytes);
+ Assert.Equal(4 * 1000, size.KiloBytes);
+ Assert.Equal(4, size.MegaBytes);
+ }
+
+ [Fact]
+ public void AddGigaBytesMethod()
+ {
+ var size = ByteSize.FromGigaBytes(2).AddGigaBytes(2);
+
+ Assert.Equal(4d * 1000 * 1000 * 1000 * 8, size.Bits);
+ Assert.Equal(4d * 1000 * 1000 * 1000, size.Bytes);
+ Assert.Equal(4d * 1000 * 1000, size.KiloBytes);
+ Assert.Equal(4d * 1000, size.MegaBytes);
+ Assert.Equal(4d, size.GigaBytes);
+ }
+
+ [Fact]
+ public void AddTeraBytesMethod()
+ {
+ var size = ByteSize.FromTeraBytes(2).AddTeraBytes(2);
+
+ Assert.Equal(4d * 1000 * 1000 * 1000 * 1000 * 8, size.Bits);
+ Assert.Equal(4d * 1000 * 1000 * 1000 * 1000, size.Bytes);
+ Assert.Equal(4d * 1000 * 1000 * 1000, size.KiloBytes);
+ Assert.Equal(4d * 1000 * 1000, size.MegaBytes);
+ Assert.Equal(4d * 1000, size.GigaBytes);
+ Assert.Equal(4d, size.TeraBytes);
+ }
+
+ [Fact]
+ public void AddPetaBytesMethod()
+ {
+ var size = ByteSize.FromPetaBytes(2).AddPetaBytes(2);
+
+ Assert.Equal(4d * 1000 * 1000 * 1000 * 1000 * 1000 * 8, size.Bits);
+ Assert.Equal(4d * 1000 * 1000 * 1000 * 1000 * 1000, size.Bytes);
+ Assert.Equal(4d * 1000 * 1000 * 1000 * 1000, size.KiloBytes);
+ Assert.Equal(4d * 1000 * 1000 * 1000, size.MegaBytes);
+ Assert.Equal(4d * 1000 * 1000, size.GigaBytes);
+ Assert.Equal(4d * 1000, size.TeraBytes);
+ Assert.Equal(4d, size.PetaBytes);
+ }
+ }
+}
diff --git a/src/ByteSizeLib.Tests/Decimal/CreatingMethods.cs b/src/ByteSizeLib.Tests/Decimal/CreatingMethods.cs
new file mode 100644
index 0000000..199c4df
--- /dev/null
+++ b/src/ByteSizeLib.Tests/Decimal/CreatingMethods.cs
@@ -0,0 +1,96 @@
+using Xunit;
+
+namespace ByteSizeLib.Tests.Decimal
+{
+ public class CreatingMethods
+ {
+ [Fact]
+ public void Constructor()
+ {
+ // Arrange
+ double bytes = 1000000000000000;
+
+ // Act
+ var result = new ByteSize(bytes);
+
+ // Assert
+ Assert.Equal(bytes * 8, result.Bits);
+ Assert.Equal(bytes, result.Bytes);
+ Assert.Equal(bytes / 1000, result.KiloBytes);
+ Assert.Equal(bytes / 1000 / 1000, result.MegaBytes);
+ Assert.Equal(bytes / 1000 / 1000 / 1000, result.GigaBytes);
+ Assert.Equal(bytes / 1000 / 1000 / 1000 / 1000, result.TeraBytes);
+ Assert.Equal(1, result.PetaBytes);
+ }
+
+ [Fact]
+ public void FromKiloBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromKiloBytes(value);
+
+ // Assert
+ Assert.Equal(1500, result.Bytes);
+ Assert.Equal(1.5, result.KiloBytes);
+ }
+
+ [Fact]
+ public void FromMegaBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromMegaBytes(value);
+
+ // Assert
+ Assert.Equal(1500000, result.Bytes);
+ Assert.Equal(1.5, result.MegaBytes);
+ }
+
+ [Fact]
+ public void FromGigaBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromGigaBytes(value);
+
+ // Assert
+ Assert.Equal(1500000000, result.Bytes);
+ Assert.Equal(1.5, result.GigaBytes);
+ }
+
+ [Fact]
+ public void FromTeraBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromTeraBytes(value);
+
+ // Assert
+ Assert.Equal(1500000000000, result.Bytes);
+ Assert.Equal(1.5, result.TeraBytes);
+ }
+
+ [Fact]
+ public void FromPetaBytesMethod()
+ {
+ // Arrange
+ double value = 1.5;
+
+ // Act
+ var result = ByteSize.FromPetaBytes(value);
+
+ // Assert
+ Assert.Equal(1500000000000000, result.Bytes);
+ Assert.Equal(1.5, result.PetaBytes);
+ }
+ }
+}
diff --git a/src/ByteSizeLib.Tests/Decimal/ParsingMethods.cs b/src/ByteSizeLib.Tests/Decimal/ParsingMethods.cs
new file mode 100644
index 0000000..f8f86ac
--- /dev/null
+++ b/src/ByteSizeLib.Tests/Decimal/ParsingMethods.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Globalization;
+using System.Threading;
+using Xunit;
+
+namespace ByteSizeLib.Tests.Decimal
+{
+ public class ParsingMethods
+ {
+ [Fact]
+ public void ParseKB()
+ {
+ string val = "1020KB";
+ var expected = ByteSize.FromKiloBytes(1020);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ParseMB()
+ {
+ string val = "1000MB";
+ var expected = ByteSize.FromMegaBytes(1000);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ParseGB()
+ {
+ string val = "805GB";
+ var expected = ByteSize.FromGigaBytes(805);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ParseTB()
+ {
+ string val = "100TB";
+ var expected = ByteSize.FromTeraBytes(100);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ParsePB()
+ {
+ string val = "100PB";
+ var expected = ByteSize.FromPetaBytes(100);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ParseCultureNumberSeparator()
+ {
+ CultureInfo.CurrentCulture = new CultureInfo("de-DE");
+ string val = "1.500,5 MB";
+ var expected = ByteSize.FromMegaBytes(1500.5);
+
+ var result = ByteSize.Parse(val);
+
+ Assert.Equal(expected, result);
+
+ CultureInfo.CurrentCulture = new CultureInfo("en-US");
+ }
+ }
+}
diff --git a/src/ByteSizeLib.Tests/Decimal/ToStringMethod.cs b/src/ByteSizeLib.Tests/Decimal/ToStringMethod.cs
new file mode 100644
index 0000000..7bdf060
--- /dev/null
+++ b/src/ByteSizeLib.Tests/Decimal/ToStringMethod.cs
@@ -0,0 +1,236 @@
+using System.Globalization;
+using System.Threading;
+using Xunit;
+
+namespace ByteSizeLib.Tests.Decimal
+{
+ public class ToStringMethod
+ {
+ [Fact]
+ public void ReturnsLargestSuffix()
+ {
+ // Arrange
+ var b = ByteSize.FromKiloBytes(10.5);
+
+ // Act
+ var result = b.ToString();
+
+ // Assert
+ Assert.Equal(10.5.ToString("0.0 KB"), result);
+ }
+
+ [Fact]
+ public void ReturnsDefaultNumberFormat()
+ {
+ // Arrange
+ var b = ByteSize.FromKiloBytes(10.5);
+
+ // Act
+ var result = b.ToString("KB");
+
+ // Assert
+ Assert.Equal(10.5.ToString("0.0 KB"), result);
+ }
+
+ [Fact]
+ public void ReturnsProvidedNumberFormat()
+ {
+ // Arrange
+ var b = ByteSize.FromKiloBytes(10.1234);
+
+ // Act
+ var result = b.ToString("#.#### KB");
+
+ // Assert
+ Assert.Equal(10.1234.ToString("0.0000 KB"), result);
+ }
+
+ [Fact]
+ public void ReturnsBits()
+ {
+ // Arrange
+ var b = ByteSize.FromBits(10);
+
+ // Act
+ var result = b.ToString("##.#### b");
+
+ // Assert
+ Assert.Equal("10 b", result);
+ }
+
+ [Fact]
+ public void ReturnsBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### B");
+
+ // Assert
+ Assert.Equal("10 B", result);
+ }
+
+ [Fact]
+ public void ReturnsKiloBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromKiloBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### KB");
+
+ // Assert
+ Assert.Equal("10 KB", result);
+ }
+
+ [Fact]
+ public void ReturnsMegaBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromMegaBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### MB");
+
+ // Assert
+ Assert.Equal("10 MB", result);
+ }
+
+ [Fact]
+ public void ReturnsGigaBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromGigaBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### GB");
+
+ // Assert
+ Assert.Equal("10 GB", result);
+ }
+
+ [Fact]
+ public void ReturnsTeraBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromTeraBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### TB");
+
+ // Assert
+ Assert.Equal("10 TB", result);
+ }
+
+ [Fact]
+ public void ReturnsPetaBytes()
+ {
+ // Arrange
+ var b = ByteSize.FromPetaBytes(10);
+
+ // Act
+ var result = b.ToString("##.#### PB");
+
+ // Assert
+ Assert.Equal("10 PB", result);
+ }
+
+ [Fact]
+ public void ReturnsSelectedFormat()
+ {
+ // Arrange
+ var b = ByteSize.FromTeraBytes(10);
+
+ // Act
+ var result = b.ToString("0.0 TB");
+
+ // Assert
+ Assert.Equal(10.ToString("0.0 TB"), result);
+ }
+
+ [Fact]
+ public void ReturnsLargestPrefixLargerThanZero()
+ {
+ // Arrange
+ var b = ByteSize.FromMegaBytes(.5);
+
+ // Act
+ var result = b.ToString("#.#");
+
+ // Assert
+ Assert.Equal("500 KB", result);
+ }
+
+ [Fact]
+ public void ReturnsLargestPrefixLargerThanZeroForNegativeValues()
+ {
+ // Arrange
+ var b = ByteSize.FromMegaBytes(-.5);
+
+ // Act
+ var result = b.ToString("#.#");
+
+ // Assert
+ Assert.Equal("-500 KB", result);
+ }
+
+ [Fact]
+ public void ReturnsLargestSuffixUsingCurrentCulture()
+ {
+ var originalCulture = CultureInfo.CurrentCulture;
+ CultureInfo.CurrentCulture = new CultureInfo("fr-FR");
+
+ // Arrange
+ var b = ByteSize.FromKiloBytes(9770);
+
+ // Act
+ var result = b.ToString();
+
+ // Assert
+ Assert.Equal("9,77 MB", result);
+
+ CultureInfo.CurrentCulture = originalCulture;
+ }
+
+ [Fact]
+ public void ReturnsLargestSuffixUsingSpecifiedCulture()
+ {
+ // Arrange
+ var b = ByteSize.FromKiloBytes(9800);
+
+ // Act
+ var result = b.ToString("#.#", new CultureInfo("fr-FR"));
+
+ // Assert
+ Assert.Equal("9,8 MB", result);
+ }
+
+ [Fact]
+ public void ReturnsCultureSpecificFormat()
+ {
+ // Arrange
+ var b = ByteSize.FromKiloBytes(10.5);
+
+ // Act
+ var deCulture = new CultureInfo("de-DE");
+ var result = b.ToString("0.0 KB", deCulture);
+
+ // Assert
+ Assert.Equal(10.5.ToString("0.0 KB", deCulture), result);
+ }
+
+ [Fact]
+ public void ReturnsZeroBits()
+ {
+ // Arrange
+ var b = ByteSize.FromBits(0);
+
+ // Act
+ var result = b.ToString();
+
+ // Assert
+ Assert.Equal("0 b", result);
+ }
+ }
+}
diff --git a/src/ByteSizeLib.Tests/ParsingMethods.cs b/src/ByteSizeLib.Tests/ParsingMethods.cs
index 9cbe04a..a8d4e50 100644
--- a/src/ByteSizeLib.Tests/ParsingMethods.cs
+++ b/src/ByteSizeLib.Tests/ParsingMethods.cs
@@ -11,8 +11,8 @@ public class ParsingMethods
[Fact]
public void Parse()
{
- string val = "1020KB";
- var expected = ByteSize.FromKiloBytes(1020);
+ string val = "1020KiB";
+ var expected = ByteSize.FromKibiBytes(1020);
var result = ByteSize.Parse(val);
@@ -22,14 +22,14 @@ public void Parse()
[Fact]
public void TryParse()
{
- string val = "1020KB";
- var expected = ByteSize.FromKiloBytes(1020);
+ string val = "1020KiB";
+ var expected = ByteSize.FromKibiBytes(1020);
- ByteSize resultByteSize;
- var resultBool = ByteSize.TryParse(val, out resultByteSize);
+ ByteSize resultBinaryByteSize;
+ var resultBool = ByteSize.TryParse(val, out resultBinaryByteSize);
Assert.True(resultBool);
- Assert.Equal(expected, resultByteSize);
+ Assert.Equal(expected, resultBinaryByteSize);
}
[Fact]
@@ -49,11 +49,11 @@ public void TryParseReturnsFalseOnBadValue()
{
string val = "Unexpected Value";
- ByteSize resultByteSize;
- var resultBool = ByteSize.TryParse(val, out resultByteSize);
+ ByteSize resultBinaryByteSize;
+ var resultBool = ByteSize.TryParse(val, out resultBinaryByteSize);
Assert.False(resultBool);
- Assert.Equal(new ByteSize(), resultByteSize);
+ Assert.Equal(new ByteSize(), resultBinaryByteSize);
}
[Fact]
@@ -61,30 +61,30 @@ public void TryParseReturnsFalseOnMissingMagnitude()
{
string val = "1000";
- ByteSize resultByteSize;
- var resultBool = ByteSize.TryParse(val, out resultByteSize);
+ ByteSize resultBinaryByteSize;
+ var resultBool = ByteSize.TryParse(val, out resultBinaryByteSize);
Assert.False(resultBool);
- Assert.Equal(new ByteSize(), resultByteSize);
+ Assert.Equal(new ByteSize(), resultBinaryByteSize);
}
[Fact]
public void TryParseReturnsFalseOnMissingValue()
{
- string val = "KB";
+ string val = "KiB";
- ByteSize resultByteSize;
- var resultBool = ByteSize.TryParse(val, out resultByteSize);
+ ByteSize resultBinaryByteSize;
+ var resultBool = ByteSize.TryParse(val, out resultBinaryByteSize);
Assert.False(resultBool);
- Assert.Equal(new ByteSize(), resultByteSize);
+ Assert.Equal(new ByteSize(), resultBinaryByteSize);
}
[Fact]
public void TryParseWorksWithLotsOfSpaces()
{
- string val = " 100 KB ";
- var expected = ByteSize.FromKiloBytes(100);
+ string val = " 100 KiB ";
+ var expected = ByteSize.FromKibiBytes(100);
var result = ByteSize.Parse(val);
@@ -102,7 +102,6 @@ public void ParsePartialBits()
});
}
-
// Parse method throws exceptions
[Fact]
public void ParseThrowsOnInvalid()
@@ -148,67 +147,12 @@ public void ParseBytes()
Assert.Equal(expected, result);
}
- [Fact]
- public void ParseKB()
- {
- string val = "1020KB";
- var expected = ByteSize.FromKiloBytes(1020);
-
- var result = ByteSize.Parse(val);
-
- Assert.Equal(expected, result);
- }
-
- [Fact]
- public void ParseMB()
- {
- string val = "1000MB";
- var expected = ByteSize.FromMegaBytes(1000);
-
- var result = ByteSize.Parse(val);
-
- Assert.Equal(expected, result);
- }
-
- [Fact]
- public void ParseGB()
- {
- string val = "805GB";
- var expected = ByteSize.FromGigaBytes(805);
-
- var result = ByteSize.Parse(val);
-
- Assert.Equal(expected, result);
- }
-
- [Fact]
- public void ParseTB()
- {
- string val = "100TB";
- var expected = ByteSize.FromTeraBytes(100);
-
- var result = ByteSize.Parse(val);
-
- Assert.Equal(expected, result);
- }
-
- [Fact]
- public void ParsePB()
- {
- string val = "100PB";
- var expected = ByteSize.FromPetaBytes(100);
-
- var result = ByteSize.Parse(val);
-
- Assert.Equal(expected, result);
- }
-
[Fact]
public void ParseCultureNumberSeparator()
{
CultureInfo.CurrentCulture = new CultureInfo("de-DE");
- string val = "1.500,5 MB";
- var expected = ByteSize.FromMegaBytes(1500.5);
+ string val = "1.500,5 MiB";
+ var expected = ByteSize.FromMebiBytes(1500.5);
var result = ByteSize.Parse(val);
diff --git a/src/ByteSizeLib.Tests/ToStringMethod.cs b/src/ByteSizeLib.Tests/ToStringMethod.cs
index b309618..ce4b890 100644
--- a/src/ByteSizeLib.Tests/ToStringMethod.cs
+++ b/src/ByteSizeLib.Tests/ToStringMethod.cs
@@ -7,7 +7,7 @@ namespace ByteSizeLib.Tests
public class ToStringMethod
{
[Fact]
- public void ReturnsLargestMetricSuffix()
+ public void ReturnsLargestSuffix()
{
// Arrange
var b = ByteSize.FromKiloBytes(10.5);
@@ -71,71 +71,6 @@ public void ReturnsBytes()
Assert.Equal("10 B", result);
}
- [Fact]
- public void ReturnsKiloBytes()
- {
- // Arrange
- var b = ByteSize.FromKiloBytes(10);
-
- // Act
- var result = b.ToString("##.#### KB");
-
- // Assert
- Assert.Equal("10 KB", result);
- }
-
- [Fact]
- public void ReturnsMegaBytes()
- {
- // Arrange
- var b = ByteSize.FromMegaBytes(10);
-
- // Act
- var result = b.ToString("##.#### MB");
-
- // Assert
- Assert.Equal("10 MB", result);
- }
-
- [Fact]
- public void ReturnsGigaBytes()
- {
- // Arrange
- var b = ByteSize.FromGigaBytes(10);
-
- // Act
- var result = b.ToString("##.#### GB");
-
- // Assert
- Assert.Equal("10 GB", result);
- }
-
- [Fact]
- public void ReturnsTeraBytes()
- {
- // Arrange
- var b = ByteSize.FromTeraBytes(10);
-
- // Act
- var result = b.ToString("##.#### TB");
-
- // Assert
- Assert.Equal("10 TB", result);
- }
-
- [Fact]
- public void ReturnsPetaBytes()
- {
- // Arrange
- var b = ByteSize.FromPetaBytes(10);
-
- // Act
- var result = b.ToString("##.#### PB");
-
- // Assert
- Assert.Equal("10 PB", result);
- }
-
[Fact]
public void ReturnsSelectedFormat()
{
@@ -150,7 +85,7 @@ public void ReturnsSelectedFormat()
}
[Fact]
- public void ReturnsLargestMetricPrefixLargerThanZero()
+ public void ReturnsLargestPrefixLargerThanZero()
{
// Arrange
var b = ByteSize.FromMegaBytes(.5);
@@ -159,11 +94,11 @@ public void ReturnsLargestMetricPrefixLargerThanZero()
var result = b.ToString("#.#");
// Assert
- Assert.Equal("512 KB", result);
+ Assert.Equal("500 KB", result);
}
[Fact]
- public void ReturnsLargestMetricPrefixLargerThanZeroForNegativeValues()
+ public void ReturnsLargestPrefixLargerThanZeroForNegativeValues()
{
// Arrange
var b = ByteSize.FromMegaBytes(-.5);
@@ -172,17 +107,17 @@ public void ReturnsLargestMetricPrefixLargerThanZeroForNegativeValues()
var result = b.ToString("#.#");
// Assert
- Assert.Equal("-512 KB", result);
+ Assert.Equal("-500 KB", result);
}
[Fact]
- public void ReturnsLargestMetricSuffixUsingCurrentCulture()
+ public void ReturnsLargestSuffixUsingCurrentCulture()
{
var originalCulture = CultureInfo.CurrentCulture;
CultureInfo.CurrentCulture = new CultureInfo("fr-FR");
// Arrange
- var b = ByteSize.FromKiloBytes(10000);
+ var b = ByteSize.FromKiloBytes(9770);
// Act
var result = b.ToString();
@@ -194,10 +129,10 @@ public void ReturnsLargestMetricSuffixUsingCurrentCulture()
}
[Fact]
- public void ReturnsLargestMetricSuffixUsingSpecifiedCulture()
+ public void ReturnsLargestSuffixUsingSpecifiedCulture()
{
// Arrange
- var b = ByteSize.FromKiloBytes(10000);
+ var b = ByteSize.FromKiloBytes(9800);
// Act
var result = b.ToString("#.#", new CultureInfo("fr-FR"));
diff --git a/src/ByteSizeLib/BinaryByteSize.cs b/src/ByteSizeLib/BinaryByteSize.cs
new file mode 100644
index 0000000..dd13efa
--- /dev/null
+++ b/src/ByteSizeLib/BinaryByteSize.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Globalization;
+
+namespace ByteSizeLib
+{
+ public partial struct ByteSize
+ {
+ public const long BytesInKibiByte = 1_024;
+ public const long BytesInMebiByte = 1_048_576;
+ public const long BytesInGibiByte = 1_073_741_824;
+ public const long BytesInTebiByte = 1_099_511_627_776;
+ public const long BytesInPebiByte = 1_125_899_906_842_624;
+
+ public const string KibiByteSymbol = "KiB";
+ public const string MebiByteSymbol = "MiB";
+ public const string GibiByteSymbol = "GiB";
+ public const string TebiByteSymbol = "TiB";
+ public const string PebiByteSymbol = "PiB";
+
+ public double KibiBytes => Bytes / BytesInKibiByte;
+ public double MebiBytes => Bytes / BytesInMebiByte;
+ public double GibiBytes => Bytes / BytesInGibiByte;
+ public double TebiBytes => Bytes / BytesInTebiByte;
+ public double PebiBytes => Bytes / BytesInPebiByte;
+
+ public static ByteSize FromKibiBytes(double value)
+ {
+ return new ByteSize(value * BytesInKibiByte);
+ }
+
+ public static ByteSize FromMebiBytes(double value)
+ {
+ return new ByteSize(value * BytesInMebiByte);
+ }
+
+ public static ByteSize FromGibiBytes(double value)
+ {
+ return new ByteSize(value * BytesInGibiByte);
+ }
+
+ public static ByteSize FromTebiBytes(double value)
+ {
+ return new ByteSize(value * BytesInTebiByte);
+ }
+
+ public static ByteSize FromPebiBytes(double value)
+ {
+ return new ByteSize(value * BytesInPebiByte);
+ }
+
+ public ByteSize AddKibiBytes(double value)
+ {
+ return this + ByteSize.FromKibiBytes(value);
+ }
+
+ public ByteSize AddMebiBytes(double value)
+ {
+ return this + ByteSize.FromMebiBytes(value);
+ }
+
+ public ByteSize AddGibiBytes(double value)
+ {
+ return this + ByteSize.FromGibiBytes(value);
+ }
+
+ public ByteSize AddTebiBytes(double value)
+ {
+ return this + ByteSize.FromTebiBytes(value);
+ }
+
+ public ByteSize AddPebiBytes(double value)
+ {
+ return this + ByteSize.FromPebiBytes(value);
+ }
+
+ public string ToBinaryString()
+ {
+ return this.ToString("0.##", CultureInfo.CurrentCulture, useBinaryByte: true);
+ }
+ }
+}
diff --git a/src/ByteSizeLib/ByteSize.cs b/src/ByteSizeLib/ByteSize.cs
index ab0729f..c199a6e 100644
--- a/src/ByteSizeLib/ByteSize.cs
+++ b/src/ByteSizeLib/ByteSize.cs
@@ -4,64 +4,101 @@
namespace ByteSizeLib
{
///
- /// Represents a byte size value.
+ /// Represents a byte size value with support for decimal (KiloByte) and
+ /// binary values (KibiByte).
///
- public struct ByteSize : IComparable, IEquatable
- {
- public static readonly ByteSize MinValue = ByteSize.FromBits(0);
+ public partial struct ByteSize : IComparable, IEquatable
+ {
+ public static readonly ByteSize MinValue = ByteSize.FromBits(long.MinValue);
public static readonly ByteSize MaxValue = ByteSize.FromBits(long.MaxValue);
-
public const long BitsInByte = 8;
- public const long BytesInKiloByte = 1024;
- public const long BytesInMegaByte = 1048576;
- public const long BytesInGigaByte = 1073741824;
- public const long BytesInTeraByte = 1099511627776;
- public const long BytesInPetaByte = 1125899906842624;
-
public const string BitSymbol = "b";
public const string ByteSymbol = "B";
- public const string KiloByteSymbol = "KB";
- public const string MegaByteSymbol = "MB";
- public const string GigaByteSymbol = "GB";
- public const string TeraByteSymbol = "TB";
- public const string PetaByteSymbol = "PB";
-
public long Bits { get; private set; }
public double Bytes { get; private set; }
- public double KiloBytes => Bytes / BytesInKiloByte;
- public double MegaBytes => Bytes / BytesInMegaByte;
- public double GigaBytes => Bytes / BytesInGigaByte;
- public double TeraBytes => Bytes / BytesInTeraByte;
- public double PetaBytes => Bytes / BytesInPetaByte;
- public string LargestWholeNumberSymbol
+ public string LargestWholeNumberBinarySymbol
+ {
+ get
+ {
+ // Absolute value is used to deal with negative values
+ if (Math.Abs(this.PebiBytes) >= 1)
+ return PebiByteSymbol;
+
+ if (Math.Abs(this.TebiBytes) >= 1)
+ return TebiByteSymbol;
+
+ if (Math.Abs(this.GibiBytes) >= 1)
+ return GibiByteSymbol;
+
+ if (Math.Abs(this.MebiBytes) >= 1)
+ return MebiByteSymbol;
+
+ if (Math.Abs(this.KibiBytes) >= 1)
+ return KibiByteSymbol;
+
+ if (Math.Abs(this.Bytes) >= 1)
+ return ByteSymbol;
+
+ return BitSymbol;
+ }
+ }
+
+ public string LargestWholeNumberDecimalSymbol
{
get
{
// Absolute value is used to deal with negative values
if (Math.Abs(this.PetaBytes) >= 1)
- return ByteSize.PetaByteSymbol;
+ return PetaByteSymbol;
if (Math.Abs(this.TeraBytes) >= 1)
- return ByteSize.TeraByteSymbol;
+ return TeraByteSymbol;
if (Math.Abs(this.GigaBytes) >= 1)
- return ByteSize.GigaByteSymbol;
+ return GigaByteSymbol;
if (Math.Abs(this.MegaBytes) >= 1)
- return ByteSize.MegaByteSymbol;
+ return MegaByteSymbol;
if (Math.Abs(this.KiloBytes) >= 1)
- return ByteSize.KiloByteSymbol;
+ return KiloByteSymbol;
+
+ if (Math.Abs(this.Bytes) >= 1)
+ return ByteSymbol;
+
+ return BitSymbol;
+ }
+ }
+
+ public double LargestWholeNumberBinaryValue
+ {
+ get
+ {
+ // Absolute value is used to deal with negative values
+ if (Math.Abs(this.PebiBytes) >= 1)
+ return this.PebiBytes;
+
+ if (Math.Abs(this.TebiBytes) >= 1)
+ return this.TebiBytes;
+
+ if (Math.Abs(this.GibiBytes) >= 1)
+ return this.GibiBytes;
+
+ if (Math.Abs(this.MebiBytes) >= 1)
+ return this.MebiBytes;
+
+ if (Math.Abs(this.KibiBytes) >= 1)
+ return this.KibiBytes;
if (Math.Abs(this.Bytes) >= 1)
- return ByteSize.ByteSymbol;
+ return this.Bytes;
- return ByteSize.BitSymbol;
+ return this.Bits;
}
}
- public double LargestWholeNumberValue
+ public double LargestWholeNumberDecimalValue
{
get
{
@@ -88,55 +125,38 @@ public double LargestWholeNumberValue
}
}
- public ByteSize(double byteSize)
+ public ByteSize(long bits)
: this()
{
- // Get ceiling because bits are whole units
- Bits = (long)Math.Ceiling(byteSize * BitsInByte);
+ Bits = bits;
- Bytes = byteSize;
- }
-
- public static ByteSize FromBits(long value)
- {
- return new ByteSize(value / (double)BitsInByte);
+ Bytes = bits / BitsInByte;
}
- public static ByteSize FromBytes(double value)
- {
- return new ByteSize(value);
- }
-
- public static ByteSize FromKiloBytes(double value)
- {
- return new ByteSize(value * BytesInKiloByte);
- }
-
- public static ByteSize FromMegaBytes(double value)
+ public ByteSize(double bytes)
+ : this()
{
- return new ByteSize(value * BytesInMegaByte);
- }
+ // Get ceiling because bits are whole units
+ Bits = (long)Math.Ceiling(bytes * BitsInByte);
- public static ByteSize FromGigaBytes(double value)
- {
- return new ByteSize(value * BytesInGigaByte);
+ Bytes = bytes;
}
- public static ByteSize FromTeraBytes(double value)
+ public static ByteSize FromBits(long value)
{
- return new ByteSize(value * BytesInTeraByte);
+ return new ByteSize(value);
}
- public static ByteSize FromPetaBytes(double value)
+ public static ByteSize FromBytes(double value)
{
- return new ByteSize(value * BytesInPetaByte);
+ return new ByteSize(value);
}
///
- /// Converts the value of the current ByteSize object to a string.
- /// The metric prefix symbol (bit, byte, kilo, mega, giga, tera) used is
- /// the largest metric prefix such that the corresponding value is greater
- // than or equal to one.
+ /// Converts the value of the current object to a string.
+ /// The prefix symbol (bit, byte, kilo, mebi, gibi, tebi) used is the
+ /// largest prefix such that the corresponding value is greater than or
+ /// equal to one.
///
public override string ToString()
{
@@ -148,7 +168,7 @@ public string ToString(string format)
return this.ToString(format, CultureInfo.CurrentCulture);
}
- public string ToString(string format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider, bool useBinaryByte = false)
{
if (!format.Contains("#") && !format.Contains("0"))
format = "0.## " + format;
@@ -158,6 +178,19 @@ public string ToString(string format, IFormatProvider provider)
Func has = s => format.IndexOf(s, StringComparison.CurrentCultureIgnoreCase) != -1;
Func output = n => n.ToString(format, provider);
+ // Binary
+ if (has("PiB"))
+ return output(this.PebiBytes);
+ if (has("TiB"))
+ return output(this.TebiBytes);
+ if (has("GiB"))
+ return output(this.GibiBytes);
+ if (has("MiB"))
+ return output(this.MebiBytes);
+ if (has("KiB"))
+ return output(this.KibiBytes);
+
+ // Decimal
if (has("PB"))
return output(this.PetaBytes);
if (has("TB"))
@@ -175,8 +208,15 @@ public string ToString(string format, IFormatProvider provider)
if (format.IndexOf(ByteSize.BitSymbol) != -1)
return output(this.Bits);
-
- return string.Format("{0} {1}", this.LargestWholeNumberValue.ToString(format, provider), this.LargestWholeNumberSymbol);
+
+ if (useBinaryByte)
+ {
+ return string.Format("{0} {1}", this.LargestWholeNumberBinaryValue.ToString(format, provider), this.LargestWholeNumberBinarySymbol);
+ }
+ else
+ {
+ return string.Format("{0} {1}", this.LargestWholeNumberDecimalValue.ToString(format, provider), this.LargestWholeNumberDecimalSymbol);
+ }
}
public override bool Equals(object value)
@@ -223,31 +263,6 @@ public ByteSize AddBytes(double value)
return this + ByteSize.FromBytes(value);
}
- public ByteSize AddKiloBytes(double value)
- {
- return this + ByteSize.FromKiloBytes(value);
- }
-
- public ByteSize AddMegaBytes(double value)
- {
- return this + ByteSize.FromMegaBytes(value);
- }
-
- public ByteSize AddGigaBytes(double value)
- {
- return this + ByteSize.FromGigaBytes(value);
- }
-
- public ByteSize AddTeraBytes(double value)
- {
- return this + ByteSize.FromTeraBytes(value);
- }
-
- public ByteSize AddPetaBytes(double value)
- {
- return this + ByteSize.FromPetaBytes(value);
- }
-
public ByteSize Subtract(ByteSize bs)
{
return new ByteSize(this.Bytes - bs.Bytes);
@@ -321,13 +336,8 @@ public static ByteSize Parse(string s, NumberStyles numberStyles, IFormatProvide
{
// Arg checking
-#if NET35
- if (string.IsNullOrEmpty(s) || s.Trim() == "")
- throw new ArgumentNullException("s", "String is null or whitespace");
-#else
if (string.IsNullOrWhiteSpace(s))
throw new ArgumentNullException("s", "String is null or whitespace");
-#endif
// Get the index of the first non-digit character
s = s.TrimStart(); // Protect against leading spaces
@@ -372,29 +382,39 @@ public static ByteSize Parse(string s, NumberStyles numberStyles, IFormatProvide
case "B":
return FromBytes(number);
+ }
+
+ switch (sizePart.ToLowerInvariant())
+ {
+ // Binary
+ case "kib":
+ return FromKibiBytes(number);
+
+ case "mib":
+ return FromMebiBytes(number);
+
+ case "gib":
+ return FromGibiBytes(number);
+
+ case "tib":
+ return FromTebiBytes(number);
+
+ case "pib":
+ return FromPebiBytes(number);
- case "KB":
- case "kB":
+ // Decimal
case "kb":
return FromKiloBytes(number);
- case "MB":
- case "mB":
case "mb":
return FromMegaBytes(number);
- case "GB":
- case "gB":
case "gb":
return FromGigaBytes(number);
- case "TB":
- case "tB":
case "tb":
return FromTeraBytes(number);
- case "PB":
- case "pB":
case "pb":
return FromPetaBytes(number);
diff --git a/src/ByteSizeLib/ByteSizeLib.csproj b/src/ByteSizeLib/ByteSizeLib.csproj
old mode 100644
new mode 100755
index f23a86e..bbfc70a
--- a/src/ByteSizeLib/ByteSizeLib.csproj
+++ b/src/ByteSizeLib/ByteSizeLib.csproj
@@ -1,17 +1,37 @@
-
+
ByteSize
ByteSize is a utility class that makes byte size representation in code easier by removing ambiguity of the value being represented. ByteSize is to bytes what System.TimeSpan is to time.
- Copyright © Omar Khudeira 2013-2018
+ Copyright © Omar Khudeira 2013-2019
ByteSize
- 1.3.0
- 1.3.0
+ 2.0.0-beta1
+ 2.0.0
Omar Khudeira
- net45;netstandard2.0
+ netstandard1.0;net45
true
portable
+ ByteSize
+ ByteSize
bytes
+
+**HUGE BREAKING CHANGE**:
+
+By default `ByteSize` now assumes `1 KB == 1000 B` and `1 KiB == 1024 B` to
+adhere to the IEC and NIST standards (https://en.wikipedia.org/wiki/Binary_prefix).
+In the past `ByteSize` assumed `1 KB == 1024 B`, that means if you're upgrading
+from v1, you'll see differences in values.
+
+Other Breaking Changes:
+- Renamed property `LargestWholeNumberSymbol` and `LargestWholeNumberValue` to `LargestWholeNumberDecimalSymbol` and `LargestWholeNumberDecimalValue` respectively.
+- Drop support for all platforms _except_ `netstandard1.0` and `net45`.
+
+New Features:
+
+- Support for binary and decimal values (e.g. `ByteSize.FromKibiByte` and `ByteSize.FromKiloByte`).
+- New constructor that takes a `long` value as the number of bits.
+
+View all release notes at https://github.com/omar/ByteSize/releases.
https://github.com/omar/ByteSize
https://raw.githubusercontent.com/omar/ByteSize/master/LICENSE
git
@@ -19,4 +39,8 @@
en
-
\ No newline at end of file
+
+ $(MONO_REFERENCE_ASSEMBLIES)/4.5-api
+
+
+
diff --git a/src/ByteSizeLib/DecimalByteSize.cs b/src/ByteSizeLib/DecimalByteSize.cs
new file mode 100644
index 0000000..6a43471
--- /dev/null
+++ b/src/ByteSizeLib/DecimalByteSize.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Globalization;
+
+namespace ByteSizeLib
+{
+ public partial struct ByteSize
+ {
+ public const long BytesInKiloByte = 1_000;
+ public const long BytesInMegaByte = 1_000_000;
+ public const long BytesInGigaByte = 1_000_000_000;
+ public const long BytesInTeraByte = 1_000_000_000_000;
+ public const long BytesInPetaByte = 1_000_000_000_000_000;
+
+ public const string KiloByteSymbol = "KB";
+ public const string MegaByteSymbol = "MB";
+ public const string GigaByteSymbol = "GB";
+ public const string TeraByteSymbol = "TB";
+ public const string PetaByteSymbol = "PB";
+
+ public double KiloBytes => Bytes / BytesInKiloByte;
+ public double MegaBytes => Bytes / BytesInMegaByte;
+ public double GigaBytes => Bytes / BytesInGigaByte;
+ public double TeraBytes => Bytes / BytesInTeraByte;
+ public double PetaBytes => Bytes / BytesInPetaByte;
+
+ public static ByteSize FromKiloBytes(double value)
+ {
+ return new ByteSize(value * BytesInKiloByte);
+ }
+
+ public static ByteSize FromMegaBytes(double value)
+ {
+ return new ByteSize(value * BytesInMegaByte);
+ }
+
+ public static ByteSize FromGigaBytes(double value)
+ {
+ return new ByteSize(value * BytesInGigaByte);
+ }
+
+ public static ByteSize FromTeraBytes(double value)
+ {
+ return new ByteSize(value * BytesInTeraByte);
+ }
+
+ public static ByteSize FromPetaBytes(double value)
+ {
+ return new ByteSize(value * BytesInPetaByte);
+ }
+
+ public ByteSize AddKiloBytes(double value)
+ {
+ return this + ByteSize.FromKiloBytes(value);
+ }
+
+ public ByteSize AddMegaBytes(double value)
+ {
+ return this + ByteSize.FromMegaBytes(value);
+ }
+
+ public ByteSize AddGigaBytes(double value)
+ {
+ return this + ByteSize.FromGigaBytes(value);
+ }
+
+ public ByteSize AddTeraBytes(double value)
+ {
+ return this + ByteSize.FromTeraBytes(value);
+ }
+
+ public ByteSize AddPetaBytes(double value)
+ {
+ return this + ByteSize.FromPetaBytes(value);
+ }
+ }
+}