├── ByteSizeLib.Tests ├── ByteSizeLib.Tests.dpr ├── ByteSizeLib.Tests.dproj └── src │ ├── ArithmeticMethodsTest.pas │ ├── CreatingMethodsTest.pas │ ├── ParsingMethodsTest.pas │ └── ToStringMethodTest.pas ├── ByteSizeLib.groupproj ├── ByteSizeLib ├── ByteSizeLibPascal.dpr ├── ByteSizeLibPascal.dproj └── src │ └── Main │ └── uByteSize.pas ├── LICENSE.md └── README.md /ByteSizeLib.Tests/ByteSizeLib.Tests.dpr: -------------------------------------------------------------------------------- 1 | program ByteSizeLib.Tests; 2 | 3 | {$IFNDEF TESTINSIGHT} 4 | {$APPTYPE CONSOLE} 5 | {$ENDIF}{$STRONGLINKTYPES ON} 6 | 7 | uses 8 | SysUtils, 9 | {$IFDEF TESTINSIGHT} 10 | TestInsight.DUnitX, 11 | {$ENDIF } 12 | DUnitX.Loggers.Console, 13 | DUnitX.Loggers.Xml.NUnit, 14 | DUnitX.TestFramework, 15 | ArithmeticMethodsTest in 'src\ArithmeticMethodsTest.pas', 16 | uByteSize in '..\ByteSizeLib\src\Main\uByteSize.pas', 17 | CreatingMethodsTest in 'src\CreatingMethodsTest.pas', 18 | ParsingMethodsTest in 'src\ParsingMethodsTest.pas', 19 | ToStringMethodTest in 'src\ToStringMethodTest.pas'; 20 | 21 | var 22 | runner: ITestRunner; 23 | results: IRunResults; 24 | logger: ITestLogger; 25 | nunitLogger: ITestLogger; 26 | 27 | begin 28 | {$IFDEF TESTINSIGHT} 29 | TestInsight.DUnitX.RunRegisteredTests; 30 | exit; 31 | {$ENDIF} 32 | try 33 | // Check command line options, will exit if invalid 34 | TDUnitX.CheckCommandLine; 35 | // Create the test runner 36 | runner := TDUnitX.CreateRunner; 37 | // Tell the runner to use RTTI to find Fixtures 38 | runner.UseRTTI := True; 39 | // tell the runner how we will log things 40 | // Log to the console window 41 | logger := TDUnitXConsoleLogger.Create(True); 42 | runner.AddLogger(logger); 43 | // Generate an NUnit compatible XML File 44 | nunitLogger := TDUnitXXMLNUnitFileLogger.Create 45 | (TDUnitX.Options.XMLOutputFile); 46 | runner.AddLogger(nunitLogger); 47 | runner.FailsOnNoAsserts := False; 48 | // When true, Assertions must be made during tests; 49 | 50 | // Run tests 51 | results := runner.Execute; 52 | if not results.AllPassed then 53 | System.ExitCode := EXIT_ERRORS; 54 | 55 | {$IFNDEF CI} 56 | // We don't want this happening when running under CI. 57 | if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then 58 | begin 59 | System.Write('Done.. press key to quit.'); 60 | System.Readln; 61 | end; 62 | {$ENDIF} 63 | except 64 | on E: Exception do 65 | System.Writeln(E.ClassName, ': ', E.Message); 66 | end; 67 | 68 | end. 69 | -------------------------------------------------------------------------------- /ByteSizeLib.Tests/ByteSizeLib.Tests.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {FD029E9D-19CE-4AB5-B1A6-B152E5D41F59} 4 | 18.1 5 | ByteSizeLib.Tests.dpr 6 | True 7 | Release 8 | Win32 9 | 1 10 | Console 11 | None 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Cfg_1 34 | true 35 | true 36 | 37 | 38 | true 39 | Base 40 | true 41 | 42 | 43 | $(BDS)\bin\delphi_PROJECTICNS.icns 44 | $(DUnitX);$(DCC_UnitSearchPath) 45 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 46 | TESTINSIGHT;$(DCC_Define) 47 | $(BDS)\bin\delphi_PROJECTICON.ico 48 | true 49 | ByteSizeLib_Tests 50 | .\$(Platform)\$(Config) 51 | .\$(Platform)\$(Config) 52 | false 53 | false 54 | false 55 | false 56 | false 57 | 58 | 59 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 60 | DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;emsclientfiredac;DataSnapFireDAC;svnui;tethering;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;skinpackd10Seattle;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FixInsight_10;DBXFirebirdDriver;DataSnapClient;inet;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;madExcept_;bsfd10Seattle;FireDACInfxDriver;vclimg;madBasic_;TeeDB;ibmonitor;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;madDisAsm_;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;DataSnapIndy10ServerTransport;dsnapxml;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage) 61 | 1033 62 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 63 | 64 | 65 | 1033 66 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 67 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 68 | DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;emsclientfiredac;DataSnapFireDAC;tethering;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;DBXFirebirdDriver;DataSnapClient;inet;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACInfxDriver;vclimg;TeeDB;ibmonitor;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;DataSnapIndy10ServerTransport;dsnapxml;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage) 69 | 70 | 71 | DEBUG;$(DCC_Define) 72 | true 73 | false 74 | true 75 | true 76 | true 77 | 78 | 79 | None 80 | 1033 81 | false 82 | 83 | 84 | false 85 | RELEASE;$(DCC_Define) 86 | 0 87 | 0 88 | 89 | 90 | 91 | MainSource 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Cfg_2 100 | Base 101 | 102 | 103 | Base 104 | 105 | 106 | Cfg_1 107 | Base 108 | 109 | 110 | 111 | Delphi.Personality.12 112 | Console 113 | 114 | 115 | 116 | ByteSizeLib.Tests.dpr 117 | 118 | 119 | FireDAC Data Explorer Integration 120 | Embarcadero FireDAC Components 121 | Embarcadero FMX FireDAC Components 122 | Embarcadero VCL FireDAC Components 123 | LiveBindings Expression Components DbExpress 124 | Embarcadero DBExpress DataSnap Provider Client Components 125 | Microsoft Office 2000 Sample Automation Server Wrapper Components 126 | Microsoft Office XP Sample Automation Server Wrapper Components 127 | 128 | 129 | 130 | 131 | 132 | true 133 | 134 | 135 | 136 | 137 | true 138 | 139 | 140 | 141 | 142 | true 143 | 144 | 145 | 146 | 147 | ByteSizeLib_Tests.exe 148 | true 149 | 150 | 151 | 152 | 153 | 154 | Contents\Resources 155 | 1 156 | 157 | 158 | 159 | 160 | classes 161 | 1 162 | 163 | 164 | 165 | 166 | Contents\MacOS 167 | 0 168 | 169 | 170 | 1 171 | 172 | 173 | 174 | 175 | 1 176 | 177 | 178 | 1 179 | 180 | 181 | 1 182 | 183 | 184 | 185 | 186 | res\drawable-xxhdpi 187 | 1 188 | 189 | 190 | 191 | 192 | library\lib\mips 193 | 1 194 | 195 | 196 | 197 | 198 | 0 199 | 200 | 201 | 1 202 | 203 | 204 | 1 205 | 206 | 207 | 1 208 | 209 | 210 | library\lib\armeabi-v7a 211 | 1 212 | 213 | 214 | 1 215 | 216 | 217 | 218 | 219 | 0 220 | 221 | 222 | 1 223 | .framework 224 | 225 | 226 | 227 | 228 | 1 229 | 230 | 231 | 1 232 | 233 | 234 | 1 235 | 236 | 237 | 238 | 239 | 1 240 | 241 | 242 | 1 243 | 244 | 245 | 1 246 | 247 | 248 | 249 | 250 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 251 | 1 252 | 253 | 254 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 255 | 1 256 | 257 | 258 | 259 | 260 | library\lib\x86 261 | 1 262 | 263 | 264 | 265 | 266 | 1 267 | 268 | 269 | 1 270 | 271 | 272 | 1 273 | 274 | 275 | 276 | 277 | 278 | library\lib\armeabi 279 | 1 280 | 281 | 282 | 283 | 284 | 0 285 | 286 | 287 | 1 288 | 289 | 290 | 1 291 | 292 | 293 | 294 | 295 | 1 296 | 297 | 298 | 1 299 | 300 | 301 | 1 302 | 303 | 304 | 305 | 306 | res\drawable-normal 307 | 1 308 | 309 | 310 | 311 | 312 | res\drawable-xhdpi 313 | 1 314 | 315 | 316 | 317 | 318 | res\drawable-large 319 | 1 320 | 321 | 322 | 323 | 324 | 1 325 | 326 | 327 | 1 328 | 329 | 330 | 1 331 | 332 | 333 | 334 | 335 | 336 | res\drawable-hdpi 337 | 1 338 | 339 | 340 | 341 | 342 | library\lib\armeabi-v7a 343 | 1 344 | 345 | 346 | 347 | 348 | 349 | 350 | 1 351 | 352 | 353 | 1 354 | 355 | 356 | 1 357 | 358 | 359 | 360 | 361 | res\values 362 | 1 363 | 364 | 365 | 366 | 367 | res\drawable-small 368 | 1 369 | 370 | 371 | 372 | 373 | res\drawable 374 | 1 375 | 376 | 377 | 378 | 379 | 1 380 | 381 | 382 | 1 383 | 384 | 385 | 1 386 | 387 | 388 | 389 | 390 | 1 391 | 392 | 393 | 394 | 395 | res\drawable 396 | 1 397 | 398 | 399 | 400 | 401 | 0 402 | 403 | 404 | 0 405 | 406 | 407 | 0 408 | 409 | 410 | 0 411 | 412 | 413 | 0 414 | 415 | 416 | 0 417 | 418 | 419 | 420 | 421 | library\lib\armeabi-v7a 422 | 1 423 | 424 | 425 | 426 | 427 | 0 428 | .bpl 429 | 430 | 431 | 1 432 | .dylib 433 | 434 | 435 | 1 436 | .dylib 437 | 438 | 439 | 1 440 | .dylib 441 | 442 | 443 | 1 444 | .dylib 445 | 446 | 447 | 448 | 449 | res\drawable-mdpi 450 | 1 451 | 452 | 453 | 454 | 455 | res\drawable-xlarge 456 | 1 457 | 458 | 459 | 460 | 461 | res\drawable-ldpi 462 | 1 463 | 464 | 465 | 466 | 467 | 0 468 | .dll;.bpl 469 | 470 | 471 | 1 472 | .dylib 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | True 485 | False 486 | 487 | 488 | 12 489 | 490 | 491 | 492 | 493 | 494 | -------------------------------------------------------------------------------- /ByteSizeLib.Tests/src/ArithmeticMethodsTest.pas: -------------------------------------------------------------------------------- 1 | unit ArithmeticMethodsTest; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, DUnitX.TestFramework, uByteSize; 7 | 8 | type 9 | 10 | [TestFixture] 11 | TArithmeticMethods = class(TObject) 12 | 13 | public 14 | 15 | [Test] 16 | procedure AddMethod(); 17 | [Test] 18 | procedure AddBitsMethod(); 19 | [Test] 20 | procedure AddBytesMethod(); 21 | [Test] 22 | procedure AddKiloBytesMethod(); 23 | [Test] 24 | procedure AddMegaBytesMethod(); 25 | [Test] 26 | procedure AddGigaBytesMethod(); 27 | [Test] 28 | procedure AddTeraBytesMethod(); 29 | [Test] 30 | procedure AddPetaBytesMethod(); 31 | [Test] 32 | procedure SubtractMethod(); 33 | [Test] 34 | procedure IncrementOperator(); 35 | [Test] 36 | procedure DecrementOperator(); 37 | [Test] 38 | procedure MinusOperator(); 39 | end; 40 | 41 | implementation 42 | 43 | procedure TArithmeticMethods.AddMethod(); 44 | var 45 | size1, result: TByteSize; 46 | d2: Double; 47 | i16: Int64; 48 | begin 49 | d2 := 2; 50 | i16 := 16; 51 | size1 := TByteSize.FromBytes(1); 52 | result := size1.Add(size1); 53 | 54 | Assert.AreEqual(d2, result.Bytes); 55 | Assert.AreEqual(i16, result.Bits); 56 | end; 57 | 58 | procedure TArithmeticMethods.AddBitsMethod(); 59 | var 60 | size: TByteSize; 61 | d2: Double; 62 | i16: Int64; 63 | begin 64 | d2 := 2; 65 | i16 := 16; 66 | size := TByteSize.FromBytes(1).AddBits(8); 67 | 68 | Assert.AreEqual(d2, size.Bytes); 69 | Assert.AreEqual(i16, size.Bits); 70 | end; 71 | 72 | procedure TArithmeticMethods.AddBytesMethod(); 73 | var 74 | size: TByteSize; 75 | d2: Double; 76 | i16: Int64; 77 | begin 78 | d2 := 2; 79 | i16 := 16; 80 | size := TByteSize.FromBytes(1).AddBytes(1); 81 | 82 | Assert.AreEqual(d2, size.Bytes); 83 | Assert.AreEqual(i16, size.Bits); 84 | end; 85 | 86 | procedure TArithmeticMethods.AddKiloBytesMethod(); 87 | var 88 | size: TByteSize; 89 | d1, d2: Double; 90 | begin 91 | d1 := 4 * 1024; 92 | d2 := 4; 93 | size := TByteSize.FromKiloBytes(2).AddKiloBytes(2); 94 | 95 | Assert.AreEqual(Int64(4 * 1024 * 8), size.Bits); 96 | Assert.AreEqual(d1, size.Bytes); 97 | Assert.AreEqual(d2, size.KiloBytes); 98 | end; 99 | 100 | procedure TArithmeticMethods.AddMegaBytesMethod(); 101 | var 102 | size: TByteSize; 103 | d1, d2, d3: Double; 104 | begin 105 | d1 := 4 * 1024 * 1024; 106 | d2 := 4 * 1024; 107 | d3 := 4; 108 | size := TByteSize.FromMegaBytes(2).AddMegaBytes(2); 109 | 110 | Assert.AreEqual(Int64(4 * 1024 * 1024 * 8), size.Bits); 111 | Assert.AreEqual(d1, size.Bytes); 112 | Assert.AreEqual(d2, size.KiloBytes); 113 | Assert.AreEqual(d3, size.MegaBytes); 114 | end; 115 | 116 | procedure TArithmeticMethods.AddGigaBytesMethod(); 117 | var 118 | size: TByteSize; 119 | d0, d1, d2, d3, d4: Double; 120 | begin 121 | 122 | d0 := (4.0 * 1024 * 1024 * 1024 * 8); 123 | d1 := (4.0 * 1024 * 1024 * 1024); 124 | d2 := (4.0 * 1024 * 1024); 125 | d3 := 4.0 * 1024; 126 | d4 := 4.0; 127 | size := TByteSize.FromGigaBytes(2).AddGigaBytes(2); 128 | Assert.AreEqual(d0, size.Bits.ToDouble); 129 | Assert.AreEqual(d1, size.Bytes); 130 | Assert.AreEqual(d2, size.KiloBytes); 131 | Assert.AreEqual(d3, size.MegaBytes); 132 | Assert.AreEqual(d4, size.GigaBytes); 133 | end; 134 | 135 | procedure TArithmeticMethods.AddTeraBytesMethod(); 136 | var 137 | size: TByteSize; 138 | d0, d1, d2, d3, d4, d5: Double; 139 | begin 140 | 141 | d0 := (4.0 * 1024 * 1024 * 1024 * 1024 * 8); 142 | d1 := (4.0 * 1024 * 1024 * 1024 * 1024); 143 | d2 := (4.0 * 1024 * 1024 * 1024); 144 | d3 := (4.0 * 1024 * 1024); 145 | d4 := (4.0 * 1024); 146 | d5 := 4.0; 147 | size := TByteSize.FromTeraBytes(2).AddTeraBytes(2); 148 | 149 | Assert.AreEqual(d0, size.Bits.ToDouble); 150 | Assert.AreEqual(d1, size.Bytes); 151 | Assert.AreEqual(d2, size.KiloBytes); 152 | Assert.AreEqual(d3, size.MegaBytes); 153 | Assert.AreEqual(d4, size.GigaBytes); 154 | Assert.AreEqual(d5, size.TeraBytes); 155 | end; 156 | 157 | procedure TArithmeticMethods.AddPetaBytesMethod(); 158 | var 159 | size: TByteSize; 160 | d0, d1, d2, d3, d4, d5, d6: Double; 161 | begin 162 | 163 | d0 := (4.0 * 1024 * 1024 * 1024 * 1024 * 1024 * 8); 164 | d1 := (4.0 * 1024 * 1024 * 1024 * 1024 * 1024); 165 | d2 := (4.0 * 1024 * 1024 * 1024 * 1024); 166 | d3 := (4.0 * 1024 * 1024 * 1024); 167 | d4 := (4.0 * 1024 * 1024); 168 | d5 := 4.0 * 1024; 169 | d6 := 4.0; 170 | 171 | size := TByteSize.FromPetaBytes(2).AddPetaBytes(2); 172 | 173 | Assert.AreEqual(d0, size.Bits.ToDouble); 174 | Assert.AreEqual(d1, size.Bytes); 175 | Assert.AreEqual(d2, size.KiloBytes); 176 | Assert.AreEqual(d3, size.MegaBytes); 177 | Assert.AreEqual(d4, size.GigaBytes); 178 | Assert.AreEqual(d5, size.TeraBytes); 179 | Assert.AreEqual(d6, size.PetaBytes); 180 | end; 181 | 182 | procedure TArithmeticMethods.SubtractMethod(); 183 | var 184 | size: TByteSize; 185 | begin 186 | size := (TByteSize.FromBytes(4)).Subtract(TByteSize.FromBytes(2)); 187 | Assert.AreEqual(Int64(16), size.Bits); 188 | Assert.AreEqual((2).ToDouble, size.Bytes); 189 | end; 190 | 191 | procedure TArithmeticMethods.IncrementOperator(); 192 | var 193 | size: TByteSize; 194 | begin 195 | size := TByteSize.FromBytes(2); 196 | Inc(size); 197 | 198 | Assert.AreEqual(Int64(24), size.Bits); 199 | Assert.AreEqual((3).ToDouble, size.Bytes); 200 | end; 201 | 202 | procedure TArithmeticMethods.DecrementOperator(); 203 | var 204 | size: TByteSize; 205 | begin 206 | size := TByteSize.FromBytes(2); 207 | Dec(size); 208 | 209 | Assert.AreEqual(Int64(8), size.Bits); 210 | Assert.AreEqual((1).ToDouble, size.Bytes); 211 | end; 212 | 213 | procedure TArithmeticMethods.MinusOperator(); 214 | var 215 | size: TByteSize; 216 | begin 217 | size := TByteSize.FromBytes(2); 218 | size := -size; 219 | 220 | Assert.AreEqual(Int64(-16), size.Bits); 221 | Assert.AreEqual((-2).ToDouble, size.Bytes); 222 | end; 223 | 224 | initialization 225 | 226 | TDUnitX.RegisterTestFixture(TArithmeticMethods); 227 | 228 | end. 229 | -------------------------------------------------------------------------------- /ByteSizeLib.Tests/src/CreatingMethodsTest.pas: -------------------------------------------------------------------------------- 1 | unit CreatingMethodsTest; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, DUnitX.TestFramework, uByteSize; 7 | 8 | type 9 | 10 | [TestFixture] 11 | TCreatingMethods = class(TObject) 12 | public 13 | [Test] 14 | procedure cConstructor(); 15 | [Test] 16 | procedure FromBitsMethod(); 17 | [Test] 18 | procedure FromBytesMethod(); 19 | [Test] 20 | procedure FromKiloBytesMethod(); 21 | [Test] 22 | procedure FromMegaBytesMethod(); 23 | [Test] 24 | procedure FromGigaBytesMethod(); 25 | [Test] 26 | procedure FromTeraBytesMethod(); 27 | [Test] 28 | procedure FromPetaBytesMethod(); 29 | end; 30 | 31 | implementation 32 | 33 | procedure TCreatingMethods.cConstructor(); 34 | var 35 | byteSize, d0, d1, d2, d3, d4: Double; 36 | result: TByteSize; 37 | begin 38 | // Arrange 39 | byteSize := 1125899906842624; 40 | 41 | // Act 42 | result := TByteSize.Create(byteSize); 43 | 44 | d0 := (byteSize * 8); 45 | d1 := byteSize / 1024; 46 | d2 := byteSize / 1024 / 1024; 47 | d3 := byteSize / 1024 / 1024 / 1024; 48 | d4 := byteSize / 1024 / 1024 / 1024 / 1024; 49 | 50 | // Assert 51 | Assert.AreEqual(d0, (result.Bits).ToDouble); 52 | Assert.AreEqual(byteSize, result.Bytes); 53 | Assert.AreEqual(d1, result.KiloBytes); 54 | Assert.AreEqual(d2, result.MegaBytes); 55 | Assert.AreEqual(d3, result.GigaBytes); 56 | Assert.AreEqual(d4, result.TeraBytes); 57 | Assert.AreEqual((1).ToDouble, result.PetaBytes); 58 | end; 59 | 60 | procedure TCreatingMethods.FromBitsMethod(); 61 | var 62 | value: Int64; 63 | result: TByteSize; 64 | begin 65 | // Arrange 66 | value := 8; 67 | 68 | // Act 69 | result := TByteSize.FromBits(value); 70 | 71 | // Assert 72 | Assert.AreEqual((8).ToDouble, (result.Bits).ToDouble); 73 | Assert.AreEqual((1).ToDouble, result.Bytes); 74 | end; 75 | 76 | procedure TCreatingMethods.FromBytesMethod(); 77 | var 78 | value, d0: Double; 79 | result: TByteSize; 80 | begin 81 | // Arrange 82 | value := 1.5; 83 | d0 := 1.5; 84 | 85 | // Act 86 | result := TByteSize.FromBytes(value); 87 | 88 | // Assert 89 | Assert.AreEqual((12).ToDouble, (result.Bits).ToDouble); 90 | Assert.AreEqual(d0, result.Bytes); 91 | end; 92 | 93 | procedure TCreatingMethods.FromKiloBytesMethod(); 94 | var 95 | value, d0: Double; 96 | result: TByteSize; 97 | begin 98 | // Arrange 99 | value := 1.5; 100 | d0 := 1.5; 101 | 102 | // Act 103 | result := TByteSize.FromKiloBytes(value); 104 | 105 | // Assert 106 | Assert.AreEqual((1536).ToDouble, result.Bytes); 107 | Assert.AreEqual(d0, result.KiloBytes); 108 | end; 109 | 110 | procedure TCreatingMethods.FromMegaBytesMethod(); 111 | var 112 | value, d0: Double; 113 | result: TByteSize; 114 | begin 115 | // Arrange 116 | value := 1.5; 117 | d0 := 1.5; 118 | 119 | // Act 120 | result := TByteSize.FromMegaBytes(value); 121 | 122 | // Assert 123 | Assert.AreEqual((1572864).ToDouble, result.Bytes); 124 | Assert.AreEqual(d0, result.MegaBytes); 125 | end; 126 | 127 | procedure TCreatingMethods.FromGigaBytesMethod(); 128 | var 129 | value, d0: Double; 130 | result: TByteSize; 131 | begin 132 | // Arrange 133 | value := 1.5; 134 | d0 := 1.5; 135 | 136 | // Act 137 | result := TByteSize.FromGigaBytes(value); 138 | 139 | // Assert 140 | Assert.AreEqual((1610612736).ToDouble, result.Bytes); 141 | Assert.AreEqual(d0, result.GigaBytes); 142 | end; 143 | 144 | procedure TCreatingMethods.FromTeraBytesMethod(); 145 | var 146 | value, d0: Double; 147 | result: TByteSize; 148 | begin 149 | // Arrange 150 | value := 1.5; 151 | d0 := 1.5; 152 | 153 | // Act 154 | result := TByteSize.FromTeraBytes(value); 155 | 156 | // Assert 157 | Assert.AreEqual((1649267441664).ToDouble, result.Bytes); 158 | Assert.AreEqual(d0, result.TeraBytes); 159 | end; 160 | 161 | procedure TCreatingMethods.FromPetaBytesMethod(); 162 | var 163 | value, d0: Double; 164 | result: TByteSize; 165 | begin 166 | // Arrange 167 | value := 1.5; 168 | d0 := 1.5; 169 | 170 | // Act 171 | result := TByteSize.FromPetaBytes(value); 172 | 173 | // Assert 174 | Assert.AreEqual((1688849860263936).ToDouble, result.Bytes); 175 | Assert.AreEqual(d0, result.PetaBytes); 176 | end; 177 | 178 | initialization 179 | 180 | TDUnitX.RegisterTestFixture(TCreatingMethods); 181 | 182 | end. 183 | -------------------------------------------------------------------------------- /ByteSizeLib.Tests/src/ParsingMethodsTest.pas: -------------------------------------------------------------------------------- 1 | unit ParsingMethodsTest; 2 | 3 | interface 4 | 5 | uses 6 | DUnitX.TestFramework, System.SysUtils, Winapi.Windows, uByteSize; 7 | 8 | type 9 | 10 | [TestFixture] 11 | TParsingMethods = class(TObject) 12 | public 13 | // Base parsing functionality 14 | [Test] 15 | procedure Parse(); 16 | [Test] 17 | procedure TryParse(); 18 | [Test] 19 | procedure ParseDecimalMB(); 20 | [Test] 21 | procedure TryParseReturnsFalseOnBadValue(); 22 | [Test] 23 | procedure TryParseReturnsFalseOnMissingMagnitude(); 24 | [Test] 25 | procedure TryParseReturnsFalseOnMissingValue(); 26 | [Test] 27 | procedure TryParseWorksWithLotsOfSpaces(); 28 | [Test] 29 | procedure ParsePartialBits(); 30 | // Parse method throws exceptions 31 | [Test] 32 | procedure ParseThrowsOnInvalid(); 33 | // Various magnitudes 34 | [Test] 35 | procedure ParseBits(); 36 | [Test] 37 | procedure ParseBytes(); 38 | [Test] 39 | procedure ParseKB(); 40 | [Test] 41 | procedure ParseMB(); 42 | [Test] 43 | procedure ParseGB(); 44 | [Test] 45 | procedure ParseTB(); 46 | [Test] 47 | procedure ParsePB(); 48 | [Test] 49 | procedure ParseLocaleNumberSeparator(); 50 | 51 | end; 52 | 53 | implementation 54 | 55 | procedure TParsingMethods.Parse(); 56 | var 57 | val: String; 58 | result, expected: TByteSize; 59 | begin 60 | val := '1020KB'; 61 | expected := TByteSize.FromKiloBytes(1020); 62 | 63 | result := TByteSize.Parse(val); 64 | Assert.AreEqual(expected, result); 65 | end; 66 | 67 | procedure TParsingMethods.TryParse(); 68 | var 69 | val: String; 70 | resultByteSize, expected: TByteSize; 71 | resultBool: Boolean; 72 | begin 73 | val := '1020KB'; 74 | expected := TByteSize.FromKiloBytes(1020); 75 | resultBool := TByteSize.TryParse(val, resultByteSize); 76 | 77 | Assert.IsTrue(resultBool); 78 | Assert.AreEqual(expected, resultByteSize); 79 | end; 80 | 81 | procedure TParsingMethods.ParseDecimalMB(); 82 | var 83 | val: String; 84 | result, expected: TByteSize; 85 | begin 86 | val := '100.5MB'; 87 | expected := TByteSize.FromMegaBytes(100.5); 88 | 89 | result := TByteSize.Parse(val); 90 | Assert.AreEqual(expected, result); 91 | end; 92 | 93 | procedure TParsingMethods.TryParseReturnsFalseOnBadValue(); 94 | var 95 | val: String; 96 | resultByteSize: TByteSize; 97 | resultBool: Boolean; 98 | begin 99 | val := 'Unexpected Value'; 100 | resultBool := TByteSize.TryParse(val, resultByteSize); 101 | 102 | Assert.IsFalse(resultBool); 103 | Assert.AreEqual(Default (TByteSize), resultByteSize); 104 | end; 105 | 106 | procedure TParsingMethods.TryParseReturnsFalseOnMissingMagnitude(); 107 | var 108 | val: String; 109 | resultByteSize: TByteSize; 110 | resultBool: Boolean; 111 | begin 112 | val := '1000'; 113 | resultBool := TByteSize.TryParse(val, resultByteSize); 114 | 115 | Assert.IsFalse(resultBool); 116 | Assert.AreEqual(Default (TByteSize), resultByteSize); 117 | end; 118 | 119 | procedure TParsingMethods.TryParseReturnsFalseOnMissingValue(); 120 | var 121 | val: String; 122 | resultByteSize: TByteSize; 123 | resultBool: Boolean; 124 | begin 125 | val := 'KB'; 126 | resultBool := TByteSize.TryParse(val, resultByteSize); 127 | 128 | Assert.IsFalse(resultBool); 129 | Assert.AreEqual(Default (TByteSize), resultByteSize); 130 | end; 131 | 132 | procedure TParsingMethods.TryParseWorksWithLotsOfSpaces(); 133 | var 134 | val: String; 135 | result, expected: TByteSize; 136 | begin 137 | val := ' 100 KB '; 138 | expected := TByteSize.FromKiloBytes(100); 139 | 140 | result := TByteSize.Parse(val); 141 | Assert.AreEqual(expected, result); 142 | end; 143 | 144 | procedure TParsingMethods.ParsePartialBits(); 145 | var 146 | val: String; 147 | begin 148 | val := '10.5b'; 149 | 150 | Assert.WillRaise( 151 | procedure 152 | begin 153 | TByteSize.Parse(val); 154 | end, EFormatException); 155 | end; 156 | 157 | procedure TParsingMethods.ParseThrowsOnInvalid(); 158 | var 159 | badValue: String; 160 | begin 161 | badValue := 'Unexpected Value'; 162 | 163 | Assert.WillRaise( 164 | procedure 165 | begin 166 | TByteSize.Parse(badValue); 167 | end, EFormatException); 168 | end; 169 | 170 | procedure TParsingMethods.ParseBits(); 171 | var 172 | val: String; 173 | result, expected: TByteSize; 174 | begin 175 | val := '1b'; 176 | expected := TByteSize.FromBits(1); 177 | 178 | result := TByteSize.Parse(val); 179 | Assert.AreEqual(expected, result); 180 | end; 181 | 182 | procedure TParsingMethods.ParseBytes(); 183 | var 184 | val: String; 185 | result, expected: TByteSize; 186 | begin 187 | val := '1B'; 188 | expected := TByteSize.FromBytes(1); 189 | 190 | result := TByteSize.Parse(val); 191 | Assert.AreEqual(expected, result); 192 | end; 193 | 194 | procedure TParsingMethods.ParseKB(); 195 | var 196 | val: String; 197 | result, expected: TByteSize; 198 | begin 199 | val := '1020KB'; 200 | expected := TByteSize.FromKiloBytes(1020); 201 | 202 | result := TByteSize.Parse(val); 203 | Assert.AreEqual(expected, result); 204 | end; 205 | 206 | procedure TParsingMethods.ParseMB(); 207 | var 208 | val: String; 209 | result, expected: TByteSize; 210 | begin 211 | val := '1000MB'; 212 | expected := TByteSize.FromMegaBytes(1000); 213 | 214 | result := TByteSize.Parse(val); 215 | Assert.AreEqual(expected, result); 216 | end; 217 | 218 | procedure TParsingMethods.ParseGB(); 219 | var 220 | val: String; 221 | result, expected: TByteSize; 222 | begin 223 | val := '805GB'; 224 | expected := TByteSize.FromGigaBytes(805); 225 | 226 | result := TByteSize.Parse(val); 227 | Assert.AreEqual(expected, result); 228 | end; 229 | 230 | procedure TParsingMethods.ParseTB(); 231 | var 232 | val: String; 233 | result, expected: TByteSize; 234 | begin 235 | val := '100TB'; 236 | expected := TByteSize.FromTeraBytes(100); 237 | 238 | result := TByteSize.Parse(val); 239 | Assert.AreEqual(expected, result); 240 | end; 241 | 242 | procedure TParsingMethods.ParsePB(); 243 | var 244 | val: String; 245 | result, expected: TByteSize; 246 | begin 247 | val := '100PB'; 248 | expected := TByteSize.FromPetaBytes(100); 249 | 250 | result := TByteSize.Parse(val); 251 | Assert.AreEqual(expected, result); 252 | end; 253 | 254 | procedure TParsingMethods.ParseLocaleNumberSeparator(); 255 | var 256 | OriginalLocale: Cardinal; 257 | val: String; 258 | expected, result: TByteSize; 259 | begin 260 | 261 | OriginalLocale := GetThreadLocale; 262 | if SetThreadLocale(1031) then // Set Locale to German (de-DE) 263 | 264 | begin 265 | val := '1.500,5 MB'; 266 | // Arrange 267 | expected := TByteSize.FromMegaBytes(1500.5); 268 | 269 | // Act 270 | result := TByteSize.Parse(val); 271 | 272 | // Assert 273 | Assert.AreEqual(expected, result); 274 | end 275 | else 276 | begin 277 | raise Exception.Create('Error Setting Locale (First Instance)'); 278 | end; 279 | 280 | if not(SetThreadLocale(OriginalLocale)) then 281 | raise Exception.Create('Error Setting Locale (Second Instance)'); 282 | end; 283 | 284 | initialization 285 | 286 | TDUnitX.RegisterTestFixture(TParsingMethods); 287 | 288 | end. 289 | -------------------------------------------------------------------------------- /ByteSizeLib.Tests/src/ToStringMethodTest.pas: -------------------------------------------------------------------------------- 1 | unit ToStringMethodTest; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, Winapi.Windows, DUnitX.TestFramework, uByteSize; 7 | 8 | type 9 | 10 | [TestFixture] 11 | TToStringMethod = class(TObject) 12 | class var 13 | FFormatSettings: TFormatSettings; 14 | public 15 | [Setup] 16 | procedure Setup(); 17 | [Test] 18 | procedure ReturnsLargestMetricSuffix(); 19 | [Test] 20 | procedure ReturnsDefaultNumberFormat(); 21 | [Test] 22 | procedure ReturnsProvidedNumberFormat(); 23 | [Test] 24 | procedure ReturnsBits(); 25 | [Test] 26 | procedure ReturnsBytes(); 27 | [Test] 28 | procedure ReturnsKiloBytes(); 29 | [Test] 30 | procedure ReturnsMegaBytes(); 31 | [Test] 32 | procedure ReturnsGigaBytes(); 33 | [Test] 34 | procedure ReturnsTeraBytes(); 35 | [Test] 36 | procedure ReturnsPetaBytes(); 37 | [Test] 38 | procedure ReturnsSelectedFormat(); 39 | [Test] 40 | procedure ReturnsLargestMetricPrefixLargerThanZero(); 41 | [Test] 42 | procedure ReturnsLargestMetricPrefixLargerThanZeroForNegativeValues(); 43 | [Test] 44 | procedure ReturnsLargestMetricSuffixUsingCustomFormatSettingsOne(); 45 | [Test] 46 | procedure ReturnsLargestMetricSuffixUsingCustomFormatSettingsTwo(); 47 | [Test] 48 | procedure ReturnsLargestMetricSuffixUsingCustomFormatSettingsThree(); 49 | [Test] 50 | procedure ReturnsLargestMetricSuffixUsingCurrentLocale(); 51 | [Test] 52 | procedure ReturnsZeroBits(); 53 | end; 54 | 55 | implementation 56 | 57 | procedure TToStringMethod.Setup(); 58 | 59 | begin 60 | FFormatSettings := TFormatSettings.Create; 61 | end; 62 | 63 | procedure TToStringMethod.ReturnsLargestMetricSuffix(); 64 | var 65 | b: TByteSize; 66 | result: String; 67 | lDouble: Double; 68 | begin 69 | lDouble := 10.5; 70 | // Arrange 71 | b := TByteSize.FromKiloBytes(10.5); 72 | 73 | // Act 74 | result := b.ToString(); 75 | 76 | // Assert 77 | Assert.AreEqual(FormatFloat('0.0 KB', lDouble, FFormatSettings), result); 78 | end; 79 | 80 | procedure TToStringMethod.ReturnsDefaultNumberFormat(); 81 | var 82 | b: TByteSize; 83 | result: String; 84 | lDouble: Double; 85 | begin 86 | lDouble := 10.5; 87 | // Arrange 88 | b := TByteSize.FromKiloBytes(10.5); 89 | 90 | // Act 91 | result := b.ToString('KB'); 92 | 93 | // Assert 94 | Assert.AreEqual(FormatFloat('0.0 KB', lDouble, FFormatSettings), result); 95 | end; 96 | 97 | procedure TToStringMethod.ReturnsProvidedNumberFormat(); 98 | var 99 | b: TByteSize; 100 | result: String; 101 | lDouble: Double; 102 | begin 103 | lDouble := 10.1234; 104 | // Arrange 105 | b := TByteSize.FromKiloBytes(10.1234); 106 | 107 | // Act 108 | result := b.ToString('#.#### KB'); 109 | 110 | // Assert 111 | Assert.AreEqual(FormatFloat('0.0000 KB', lDouble, FFormatSettings), result); 112 | end; 113 | 114 | procedure TToStringMethod.ReturnsBits(); 115 | var 116 | b: TByteSize; 117 | result: String; 118 | begin 119 | // Arrange 120 | b := TByteSize.FromBits(10); 121 | 122 | // Act 123 | result := b.ToString('##.#### b'); 124 | 125 | // Assert 126 | Assert.AreEqual('10 b', result); 127 | end; 128 | 129 | procedure TToStringMethod.ReturnsBytes(); 130 | var 131 | b: TByteSize; 132 | result: String; 133 | begin 134 | // Arrange 135 | b := TByteSize.FromBytes(10); 136 | 137 | // Act 138 | result := b.ToString('##.#### B'); 139 | 140 | // Assert 141 | Assert.AreEqual('10 B', result); 142 | end; 143 | 144 | procedure TToStringMethod.ReturnsKiloBytes(); 145 | var 146 | b: TByteSize; 147 | result: String; 148 | begin 149 | // Arrange 150 | b := TByteSize.FromKiloBytes(10); 151 | 152 | // Act 153 | result := b.ToString('##.#### KB'); 154 | 155 | // Assert 156 | Assert.AreEqual('10 KB', result); 157 | end; 158 | 159 | procedure TToStringMethod.ReturnsMegaBytes(); 160 | var 161 | b: TByteSize; 162 | result: String; 163 | begin 164 | // Arrange 165 | b := TByteSize.FromMegaBytes(10); 166 | 167 | // Act 168 | result := b.ToString('##.#### MB'); 169 | 170 | // Assert 171 | Assert.AreEqual('10 MB', result); 172 | end; 173 | 174 | procedure TToStringMethod.ReturnsGigaBytes(); 175 | var 176 | b: TByteSize; 177 | result: String; 178 | begin 179 | // Arrange 180 | b := TByteSize.FromGigaBytes(10); 181 | 182 | // Act 183 | result := b.ToString('##.#### GB'); 184 | 185 | // Assert 186 | Assert.AreEqual('10 GB', result); 187 | end; 188 | 189 | procedure TToStringMethod.ReturnsTeraBytes(); 190 | var 191 | b: TByteSize; 192 | result: String; 193 | begin 194 | // Arrange 195 | b := TByteSize.FromTeraBytes(10); 196 | 197 | // Act 198 | result := b.ToString('##.#### TB'); 199 | 200 | // Assert 201 | Assert.AreEqual('10 TB', result); 202 | end; 203 | 204 | procedure TToStringMethod.ReturnsPetaBytes(); 205 | var 206 | b: TByteSize; 207 | result: String; 208 | begin 209 | // Arrange 210 | b := TByteSize.FromPetaBytes(10); 211 | 212 | // Act 213 | result := b.ToString('##.#### PB'); 214 | 215 | // Assert 216 | Assert.AreEqual('10 PB', result); 217 | end; 218 | 219 | procedure TToStringMethod.ReturnsSelectedFormat(); 220 | var 221 | b: TByteSize; 222 | result: String; 223 | lDouble: Double; 224 | begin 225 | lDouble := 10; 226 | // Arrange 227 | b := TByteSize.FromTeraBytes(10); 228 | 229 | // Act 230 | result := b.ToString('0.0 TB'); 231 | 232 | // Assert 233 | Assert.AreEqual(FormatFloat('0.0 TB', lDouble, FFormatSettings), result); 234 | end; 235 | 236 | procedure TToStringMethod.ReturnsLargestMetricPrefixLargerThanZero(); 237 | var 238 | b: TByteSize; 239 | result: String; 240 | begin 241 | // Arrange 242 | b := TByteSize.FromMegaBytes(0.5); 243 | 244 | // Act 245 | result := b.ToString('#.#'); 246 | 247 | // Assert 248 | Assert.AreEqual('512 KB', result); 249 | end; 250 | 251 | procedure TToStringMethod. 252 | ReturnsLargestMetricPrefixLargerThanZeroForNegativeValues(); 253 | var 254 | b: TByteSize; 255 | result: String; 256 | begin 257 | // Arrange 258 | b := TByteSize.FromMegaBytes(-0.5); 259 | 260 | // Act 261 | result := b.ToString('#.#'); 262 | 263 | // Assert 264 | Assert.AreEqual('-512 KB', result); 265 | end; 266 | 267 | procedure TToStringMethod. 268 | ReturnsLargestMetricSuffixUsingCustomFormatSettingsOne(); 269 | var 270 | FrenchFormatSettings: TFormatSettings; 271 | b: TByteSize; 272 | result: String; 273 | begin 274 | FrenchFormatSettings := TFormatSettings.Create('fr-FR'); 275 | 276 | // Arrange 277 | b := TByteSize.FromKiloBytes(10000); 278 | 279 | // Act 280 | result := b.ToString('#.##', FrenchFormatSettings); 281 | 282 | // Assert 283 | Assert.AreEqual('9,77 MB', result); 284 | end; 285 | 286 | procedure TToStringMethod. 287 | ReturnsLargestMetricSuffixUsingCustomFormatSettingsTwo(); 288 | var 289 | GermanFormatSettings: TFormatSettings; 290 | b: TByteSize; 291 | result: String; 292 | begin 293 | GermanFormatSettings := TFormatSettings.Create('de-DE'); 294 | 295 | // Arrange 296 | b := TByteSize.FromKiloBytes(10000); 297 | 298 | // Act 299 | result := b.ToString('#.#', GermanFormatSettings); 300 | 301 | // Assert 302 | Assert.AreEqual('9,8 MB', result); 303 | end; 304 | 305 | procedure TToStringMethod. 306 | ReturnsLargestMetricSuffixUsingCustomFormatSettingsThree(); 307 | var 308 | GermanFormatSettings: TFormatSettings; 309 | b: TByteSize; 310 | result: String; 311 | lDouble: Double; 312 | begin 313 | lDouble := 10.5; 314 | GermanFormatSettings := TFormatSettings.Create('de-DE'); 315 | 316 | // Arrange 317 | b := TByteSize.FromKiloBytes(10.5); 318 | 319 | // Act 320 | result := b.ToString('0.0 KB', GermanFormatSettings); 321 | 322 | // Assert 323 | Assert.AreEqual(FormatFloat('0.0 KB', lDouble, GermanFormatSettings), result); 324 | end; 325 | 326 | procedure TToStringMethod.ReturnsLargestMetricSuffixUsingCurrentLocale(); 327 | var 328 | b: TByteSize; 329 | result: String; 330 | OriginalLocale: Cardinal; 331 | begin 332 | OriginalLocale := GetThreadLocale; 333 | if SetThreadLocale(1036) then // Set Locale to French (fr-FR) 334 | begin 335 | // Arrange 336 | b := TByteSize.FromKiloBytes(10000); 337 | 338 | // Act 339 | result := b.ToString(); 340 | 341 | // Assert 342 | Assert.AreEqual('9,77 MB', result); 343 | end 344 | else 345 | begin 346 | raise Exception.Create('Error Setting Locale (First Instance)'); 347 | end; 348 | 349 | if not(SetThreadLocale(OriginalLocale)) then 350 | raise Exception.Create('Error Setting Locale (Second Instance)'); 351 | end; 352 | 353 | procedure TToStringMethod.ReturnsZeroBits(); 354 | var 355 | b: TByteSize; 356 | result: String; 357 | begin 358 | // Arrange 359 | b := TByteSize.FromBits(0); 360 | 361 | // Act 362 | result := b.ToString(); 363 | 364 | // Assert 365 | Assert.AreEqual('0 b', result); 366 | end; 367 | 368 | initialization 369 | 370 | TDUnitX.RegisterTestFixture(TToStringMethod); 371 | 372 | end. 373 | -------------------------------------------------------------------------------- /ByteSizeLib.groupproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {B6E2020E-C785-4102-8226-CD62C6D52A20} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Default.Personality.12 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /ByteSizeLib/ByteSizeLibPascal.dpr: -------------------------------------------------------------------------------- 1 | program ByteSizeLibPascal; 2 | 3 | uses 4 | Vcl.Forms, 5 | uByteSize in 'src\Main\uByteSize.pas'; 6 | 7 | {$R *.res} 8 | 9 | begin 10 | Application.Initialize; 11 | Application.MainFormOnTaskbar := True; 12 | Application.Run; 13 | end. 14 | -------------------------------------------------------------------------------- /ByteSizeLib/ByteSizeLibPascal.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {3E122233-5030-4556-9ACD-0835AB3A9401} 4 | 18.1 5 | VCL 6 | ByteSizeLibPascal.dpr 7 | True 8 | Release 9 | Win32 10 | 1 11 | Application 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Cfg_1 34 | true 35 | true 36 | 37 | 38 | true 39 | Cfg_1 40 | true 41 | true 42 | 43 | 44 | true 45 | Base 46 | true 47 | 48 | 49 | true 50 | Cfg_2 51 | true 52 | true 53 | 54 | 55 | true 56 | Cfg_2 57 | true 58 | true 59 | 60 | 61 | ByteSizeLibPascal 62 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) 63 | $(BDS)\bin\delphi_PROJECTICON.ico 64 | .\$(Platform)\$(Config) 65 | .\$(Platform)\$(Config) 66 | false 67 | false 68 | false 69 | false 70 | false 71 | 72 | 73 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 74 | $(BDS)\bin\default_app.manifest 75 | DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;emsclientfiredac;DataSnapFireDAC;svnui;tethering;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;skinpackd10Seattle;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FixInsight_10;DBXFirebirdDriver;DataSnapClient;inet;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;madExcept_;bsfd10Seattle;FireDACInfxDriver;vclimg;madBasic_;TeeDB;ibmonitor;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;madDisAsm_;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;DataSnapIndy10ServerTransport;dsnapxml;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage) 76 | true 77 | 1033 78 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 79 | 80 | 81 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 82 | $(BDS)\bin\default_app.manifest 83 | DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;emsclientfiredac;DataSnapFireDAC;tethering;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;DBXFirebirdDriver;DataSnapClient;inet;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACInfxDriver;vclimg;TeeDB;ibmonitor;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;DataSnapIndy10ServerTransport;dsnapxml;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage) 84 | true 85 | 1033 86 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 87 | 88 | 89 | DEBUG;$(DCC_Define) 90 | true 91 | false 92 | true 93 | true 94 | true 95 | 96 | 97 | true 98 | true 99 | false 100 | 101 | 102 | true 103 | true 104 | 105 | 106 | false 107 | RELEASE;$(DCC_Define) 108 | 0 109 | 0 110 | 111 | 112 | true 113 | true 114 | 115 | 116 | true 117 | true 118 | 119 | 120 | 121 | MainSource 122 | 123 | 124 | 125 | Cfg_2 126 | Base 127 | 128 | 129 | Base 130 | 131 | 132 | Cfg_1 133 | Base 134 | 135 | 136 | 137 | Delphi.Personality.12 138 | Application 139 | 140 | 141 | 142 | ByteSizeLibPascal.dpr 143 | 144 | 145 | 146 | 147 | 148 | ByteSizeLibPascal.exe 149 | true 150 | 151 | 152 | 153 | 154 | ByteSizeLibPascal.exe 155 | true 156 | 157 | 158 | 159 | 160 | 0 161 | .dll;.bpl 162 | 163 | 164 | 1 165 | .dylib 166 | 167 | 168 | Contents\MacOS 169 | 1 170 | .dylib 171 | 172 | 173 | 1 174 | .dylib 175 | 176 | 177 | 1 178 | .dylib 179 | 180 | 181 | 182 | 183 | Contents\Resources 184 | 1 185 | 186 | 187 | 188 | 189 | classes 190 | 1 191 | 192 | 193 | 194 | 195 | Contents\MacOS 196 | 0 197 | 198 | 199 | 1 200 | 201 | 202 | Contents\MacOS 203 | 1 204 | 205 | 206 | 207 | 208 | 1 209 | 210 | 211 | 1 212 | 213 | 214 | 1 215 | 216 | 217 | 218 | 219 | res\drawable-xxhdpi 220 | 1 221 | 222 | 223 | 224 | 225 | library\lib\mips 226 | 1 227 | 228 | 229 | 230 | 231 | 0 232 | 233 | 234 | 1 235 | 236 | 237 | Contents\MacOS 238 | 1 239 | 240 | 241 | 1 242 | 243 | 244 | library\lib\armeabi-v7a 245 | 1 246 | 247 | 248 | 1 249 | 250 | 251 | 252 | 253 | 0 254 | 255 | 256 | Contents\MacOS 257 | 1 258 | .framework 259 | 260 | 261 | 262 | 263 | 1 264 | 265 | 266 | 1 267 | 268 | 269 | 1 270 | 271 | 272 | 273 | 274 | 1 275 | 276 | 277 | 1 278 | 279 | 280 | 1 281 | 282 | 283 | 284 | 285 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 286 | 1 287 | 288 | 289 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 290 | 1 291 | 292 | 293 | 294 | 295 | library\lib\x86 296 | 1 297 | 298 | 299 | 300 | 301 | 1 302 | 303 | 304 | 1 305 | 306 | 307 | 1 308 | 309 | 310 | 311 | 312 | 1 313 | 314 | 315 | 1 316 | 317 | 318 | 1 319 | 320 | 321 | 322 | 323 | library\lib\armeabi 324 | 1 325 | 326 | 327 | 328 | 329 | 0 330 | 331 | 332 | 1 333 | 334 | 335 | Contents\MacOS 336 | 1 337 | 338 | 339 | 340 | 341 | 1 342 | 343 | 344 | 1 345 | 346 | 347 | 1 348 | 349 | 350 | 351 | 352 | res\drawable-normal 353 | 1 354 | 355 | 356 | 357 | 358 | res\drawable-xhdpi 359 | 1 360 | 361 | 362 | 363 | 364 | res\drawable-large 365 | 1 366 | 367 | 368 | 369 | 370 | 1 371 | 372 | 373 | 1 374 | 375 | 376 | 1 377 | 378 | 379 | 380 | 381 | ../ 382 | 1 383 | 384 | 385 | ../ 386 | 1 387 | 388 | 389 | 390 | 391 | res\drawable-hdpi 392 | 1 393 | 394 | 395 | 396 | 397 | library\lib\armeabi-v7a 398 | 1 399 | 400 | 401 | 402 | 403 | Contents 404 | 1 405 | 406 | 407 | 408 | 409 | ../ 410 | 1 411 | 412 | 413 | 414 | 415 | 1 416 | 417 | 418 | 1 419 | 420 | 421 | 1 422 | 423 | 424 | 425 | 426 | res\values 427 | 1 428 | 429 | 430 | 431 | 432 | res\drawable-small 433 | 1 434 | 435 | 436 | 437 | 438 | res\drawable 439 | 1 440 | 441 | 442 | 443 | 444 | 1 445 | 446 | 447 | 1 448 | 449 | 450 | 1 451 | 452 | 453 | 454 | 455 | 1 456 | 457 | 458 | 459 | 460 | res\drawable 461 | 1 462 | 463 | 464 | 465 | 466 | 0 467 | 468 | 469 | 0 470 | 471 | 472 | Contents\Resources\StartUp\ 473 | 0 474 | 475 | 476 | 0 477 | 478 | 479 | 0 480 | 481 | 482 | 0 483 | 484 | 485 | 486 | 487 | library\lib\armeabi-v7a 488 | 1 489 | 490 | 491 | 492 | 493 | 0 494 | .bpl 495 | 496 | 497 | 1 498 | .dylib 499 | 500 | 501 | Contents\MacOS 502 | 1 503 | .dylib 504 | 505 | 506 | 1 507 | .dylib 508 | 509 | 510 | 1 511 | .dylib 512 | 513 | 514 | 515 | 516 | res\drawable-mdpi 517 | 1 518 | 519 | 520 | 521 | 522 | res\drawable-xlarge 523 | 1 524 | 525 | 526 | 527 | 528 | res\drawable-ldpi 529 | 1 530 | 531 | 532 | 533 | 534 | 1 535 | 536 | 537 | 1 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | True 550 | False 551 | 552 | 553 | 12 554 | 555 | 556 | 557 | 558 | 559 | -------------------------------------------------------------------------------- /ByteSizeLib/src/Main/uByteSize.pas: -------------------------------------------------------------------------------- 1 | unit uByteSize; 2 | 3 | {$IFNDEF FPC} 4 | {$IF CompilerVersion >= 24} // XE3 and Above 5 | {$ZEROBASEDSTRINGS OFF} 6 | {$LEGACYIFEND ON} 7 | {$IFEND} 8 | {$IF CompilerVersion >= 22} // XE and Above 9 | {$DEFINE SUPPORT_TFORMATSETTINGS_CREATE_INSTANCE} 10 | {$IFEND} 11 | {$IF CompilerVersion >= 23} // XE2 and Above 12 | {$DEFINE SCOPEDUNITNAMES} 13 | {$IFEND} 14 | {$ELSE} 15 | {$MODE delphi} 16 | {$ENDIF FPC} 17 | 18 | interface 19 | 20 | uses 21 | {$IFDEF SCOPEDUNITNAMES} 22 | System.SysUtils, 23 | System.StrUtils, 24 | System.Generics.Defaults; 25 | {$ELSE} 26 | {$IFNDEF FPC} 27 | Generics.Defaults, 28 | {$ENDIF FPC} 29 | SysUtils, 30 | StrUtils; 31 | {$ENDIF} 32 | 33 | resourcestring 34 | SEmptyString = 'Input String is null or whitespace'; 35 | SInvalidInput = 'No byte indicator found in value "%s".'; 36 | SInvalidInput2 = 'No number found in value "%s".'; 37 | SInvalidBit = 'Can''t have partial bits for value "%s".'; 38 | SUnSupportedMagnitude = 'Bytes of magnitude "%s" is not supported.'; 39 | 40 | type 41 | 42 | TByteSize = record 43 | 44 | public 45 | 46 | strict private 47 | 48 | FBits: Int64; 49 | FBytes: Double; 50 | 51 | function GetBits: Int64; inline; 52 | function GetBytes: Double; inline; 53 | function GetKiloBytes: Double; inline; 54 | function GetMegaBytes: Double; inline; 55 | function GetGigaBytes: Double; inline; 56 | function GetTeraBytes: Double; inline; 57 | function GetPetaBytes: Double; inline; 58 | 59 | function GetLargestWholeNumberSymbol: String; 60 | property LargestWholeNumberSymbol: String read GetLargestWholeNumberSymbol; 61 | function GetLargestWholeNumberValue: Double; 62 | property LargestWholeNumberValue: Double read GetLargestWholeNumberValue; 63 | 64 | class function GetMinValue: TByteSize; static; inline; 65 | class function GetMaxValue: TByteSize; static; inline; 66 | 67 | { Utils } 68 | 69 | class function has(const SubStr: String; const Str: String): Boolean; 70 | static; inline; 71 | class function output(n: Double; formatsettings: TFormatSettings; 72 | const formatstr: String): String; static; inline; 73 | 74 | class function Contains(InChar: Char; const InString: String) 75 | : Boolean; static; 76 | class function IndexOf(const SubStr: String; const Str: String; 77 | caseSensitive: Boolean): Integer; static; 78 | class function IsNullOrWhiteSpace(const InValue: string): Boolean; 79 | static; inline; 80 | class function FloatingMod(a: Double; b: Double): Double; static; inline; 81 | 82 | const 83 | 84 | Int64MaxValue = Int64(9223372036854775807); 85 | 86 | BitsInByte = Int64(8); 87 | BytesInKiloByte = Int64(1024); 88 | BytesInMegaByte = Int64(1048576); 89 | BytesInGigaByte = Int64(1073741824); 90 | BytesInTeraByte = Int64(1099511627776); 91 | BytesInPetaByte = Int64(1125899906842624); 92 | 93 | BitSymbol = 'b'; 94 | ByteSymbol = 'B'; 95 | KiloByteSymbol = 'KB'; 96 | MegaByteSymbol = 'MB'; 97 | GigaByteSymbol = 'GB'; 98 | TeraByteSymbol = 'TB'; 99 | PetaByteSymbol = 'PB'; 100 | 101 | public 102 | 103 | property Bits: Int64 read GetBits; 104 | property Bytes: Double read GetBytes; 105 | property KiloBytes: Double read GetKiloBytes; 106 | property MegaBytes: Double read GetMegaBytes; 107 | property GigaBytes: Double read GetGigaBytes; 108 | property TeraBytes: Double read GetTeraBytes; 109 | property PetaBytes: Double read GetPetaBytes; 110 | 111 | class property MinValue: TByteSize read GetMinValue; 112 | class property MaxValue: TByteSize read GetMaxValue; 113 | 114 | constructor Create(byteSize: Double); 115 | 116 | class function FromBits(value: Int64): TByteSize; static; 117 | class function FromBytes(value: Double): TByteSize; static; 118 | class function FromKiloBytes(value: Double): TByteSize; static; 119 | class function FromMegaBytes(value: Double): TByteSize; static; 120 | class function FromGigaBytes(value: Double): TByteSize; static; 121 | class function FromTeraBytes(value: Double): TByteSize; static; 122 | class function FromPetaBytes(value: Double): TByteSize; static; 123 | 124 | class function TryParse(const s: String; out varresult: TByteSize) 125 | : Boolean; static; 126 | class function Parse(const s: String): TByteSize; static; 127 | 128 | /// 129 | /// Converts the value of the current ByteSize object to a string. 130 | /// The metric prefix symbol (bit, byte, kilo, mega, giga, tera) used is 131 | /// the largest metric prefix such that the corresponding value is greater 132 | // than or equal to one. 133 | /// 134 | function ToString: String; overload; 135 | function ToString(lformat: String): String; overload; 136 | function ToString(lformat: String; formatsettings: TFormatSettings) 137 | : String; overload; 138 | 139 | function Equals(value: TByteSize): Boolean; 140 | function CompareTo(other: TByteSize): Integer; 141 | 142 | function Add(bs: TByteSize): TByteSize; 143 | function AddBits(value: Int64): TByteSize; 144 | function AddBytes(value: Double): TByteSize; 145 | function AddKiloBytes(value: Double): TByteSize; 146 | function AddMegaBytes(value: Double): TByteSize; 147 | function AddGigaBytes(value: Double): TByteSize; 148 | function AddTeraBytes(value: Double): TByteSize; 149 | function AddPetaBytes(value: Double): TByteSize; 150 | function Subtract(bs: TByteSize): TByteSize; 151 | 152 | class operator Add(b1: TByteSize; b2: TByteSize): TByteSize; 153 | class operator Subtract(b1: TByteSize; b2: TByteSize): TByteSize; 154 | class operator Inc(b: TByteSize): TByteSize; 155 | class operator Dec(b: TByteSize): TByteSize; 156 | class operator Positive(b: TByteSize): TByteSize; 157 | class operator Negative(b: TByteSize): TByteSize; 158 | class operator Equal(b1: TByteSize; b2: TByteSize): Boolean; 159 | class operator NotEqual(b1: TByteSize; b2: TByteSize): Boolean; 160 | class operator LessThan(b1: TByteSize; b2: TByteSize): Boolean; 161 | class operator LessThanOrEqual(b1: TByteSize; b2: TByteSize): Boolean; 162 | class operator GreaterThan(b1: TByteSize; b2: TByteSize): Boolean; 163 | class operator GreaterThanOrEqual(b1: TByteSize; b2: TByteSize): Boolean; 164 | 165 | end; 166 | 167 | EFormatException = class(Exception); 168 | EArgumentNilException = class(Exception); 169 | 170 | implementation 171 | 172 | constructor TByteSize.Create(byteSize: Double); 173 | var 174 | tempDouble: Double; 175 | begin 176 | tempDouble := byteSize * BitsInByte; 177 | // Get Truncation because bits are whole units 178 | FBits := Trunc(tempDouble); 179 | FBytes := byteSize; 180 | end; 181 | 182 | function TByteSize.GetLargestWholeNumberSymbol: String; 183 | begin 184 | 185 | // Absolute value is used to deal with negative values 186 | if (Abs(Self.PetaBytes) >= 1) then 187 | begin 188 | result := TByteSize.PetaByteSymbol; 189 | Exit; 190 | end; 191 | 192 | if (Abs(Self.TeraBytes) >= 1) then 193 | begin 194 | result := TByteSize.TeraByteSymbol; 195 | Exit; 196 | end; 197 | 198 | if (Abs(Self.GigaBytes) >= 1) then 199 | begin 200 | result := TByteSize.GigaByteSymbol; 201 | Exit; 202 | end; 203 | 204 | if (Abs(Self.MegaBytes) >= 1) then 205 | begin 206 | result := TByteSize.MegaByteSymbol; 207 | Exit; 208 | end; 209 | 210 | if (Abs(Self.KiloBytes) >= 1) then 211 | begin 212 | result := TByteSize.KiloByteSymbol; 213 | Exit; 214 | end; 215 | 216 | if (Abs(Self.Bytes) >= 1) then 217 | begin 218 | result := TByteSize.ByteSymbol; 219 | Exit; 220 | end; 221 | 222 | result := TByteSize.BitSymbol; 223 | 224 | end; 225 | 226 | function TByteSize.GetLargestWholeNumberValue: Double; 227 | begin 228 | 229 | // Absolute value is used to deal with negative values 230 | if (Abs(Self.PetaBytes) >= 1) then 231 | begin 232 | result := Self.PetaBytes; 233 | Exit; 234 | end; 235 | 236 | if (Abs(Self.TeraBytes) >= 1) then 237 | begin 238 | result := Self.TeraBytes; 239 | Exit; 240 | end; 241 | 242 | if (Abs(Self.GigaBytes) >= 1) then 243 | begin 244 | result := Self.GigaBytes; 245 | Exit; 246 | end; 247 | 248 | if (Abs(Self.MegaBytes) >= 1) then 249 | begin 250 | result := Self.MegaBytes; 251 | Exit; 252 | end; 253 | 254 | if (Abs(Self.KiloBytes) >= 1) then 255 | begin 256 | result := Self.KiloBytes; 257 | Exit; 258 | end; 259 | 260 | if (Abs(Self.Bytes) >= 1) then 261 | begin 262 | result := Self.Bytes; 263 | Exit; 264 | end; 265 | 266 | result := Self.Bits; 267 | end; 268 | 269 | class function TByteSize.FromBits(value: Int64): TByteSize; 270 | var 271 | tempDouble, dBitsInByte: Double; 272 | begin 273 | dBitsInByte := BitsInByte * 1.0; 274 | tempDouble := value / dBitsInByte; 275 | result := TByteSize.Create(tempDouble); 276 | end; 277 | 278 | class function TByteSize.FromBytes(value: Double): TByteSize; 279 | begin 280 | result := TByteSize.Create(value); 281 | end; 282 | 283 | class function TByteSize.FromKiloBytes(value: Double): TByteSize; 284 | var 285 | tempDouble: Double; 286 | begin 287 | tempDouble := value * BytesInKiloByte; 288 | result := TByteSize.Create(tempDouble); 289 | end; 290 | 291 | class function TByteSize.FromMegaBytes(value: Double): TByteSize; 292 | var 293 | tempDouble: Double; 294 | begin 295 | tempDouble := value * BytesInMegaByte; 296 | result := TByteSize.Create(tempDouble); 297 | end; 298 | 299 | class function TByteSize.FromGigaBytes(value: Double): TByteSize; 300 | var 301 | tempDouble: Double; 302 | begin 303 | tempDouble := value * BytesInGigaByte; 304 | result := TByteSize.Create(tempDouble); 305 | end; 306 | 307 | class function TByteSize.FromTeraBytes(value: Double): TByteSize; 308 | var 309 | tempDouble: Double; 310 | begin 311 | tempDouble := value * BytesInTeraByte; 312 | result := TByteSize.Create(tempDouble); 313 | end; 314 | 315 | class function TByteSize.FromPetaBytes(value: Double): TByteSize; 316 | var 317 | tempDouble: Double; 318 | begin 319 | tempDouble := value * BytesInPetaByte; 320 | result := TByteSize.Create(tempDouble); 321 | end; 322 | 323 | function TByteSize.ToString: String; 324 | var 325 | lFormatSettings: TFormatSettings; 326 | begin 327 | 328 | {$IFDEF FPC} 329 | lFormatSettings := DefaultFormatSettings; 330 | {$ELSE} 331 | {$IFDEF SUPPORT_TFORMATSETTINGS_CREATE_INSTANCE} 332 | lFormatSettings := TFormatSettings.Create; 333 | {$ELSE} 334 | GetLocaleFormatSettings(0, lFormatSettings); 335 | {$ENDIF} 336 | {$ENDIF} 337 | result := Self.ToString('0.##', lFormatSettings); 338 | 339 | end; 340 | 341 | function TByteSize.ToString(lformat: String): String; 342 | var 343 | lFormatSettings: TFormatSettings; 344 | begin 345 | {$IFDEF FPC} 346 | lFormatSettings := DefaultFormatSettings; 347 | {$ELSE} 348 | {$IFDEF SUPPORT_TFORMATSETTINGS_CREATE_INSTANCE} 349 | lFormatSettings := TFormatSettings.Create; 350 | {$ELSE} 351 | GetLocaleFormatSettings(0, lFormatSettings); 352 | {$ENDIF} 353 | {$ENDIF} 354 | result := Self.ToString(lformat, lFormatSettings); 355 | end; 356 | 357 | function TByteSize.ToString(lformat: String; 358 | formatsettings: TFormatSettings): String; 359 | 360 | {$IFNDEF FPC} 361 | var 362 | comparer: IComparer; 363 | {$ENDIF} 364 | begin 365 | if ((not Contains('#', lformat)) and (not Contains('0', lformat))) then 366 | begin 367 | lformat := '0.## ' + lformat; 368 | end; 369 | 370 | {$IFDEF FPC} 371 | if formatsettings.DecimalSeparator = '' then 372 | begin 373 | formatsettings := DefaultFormatSettings; 374 | end; 375 | {$ELSE} 376 | comparer := TComparer.Default; 377 | 378 | if comparer.Compare(formatsettings, Default (TFormatSettings)) = 0 then 379 | {$IF DEFINED (SUPPORT_TFORMATSETTINGS_CREATE_INSTANCE)} 380 | formatsettings := TFormatSettings.Create; 381 | {$ELSE} 382 | GetLocaleFormatSettings(0, formatsettings); 383 | {$IFEND} 384 | {$ENDIF} 385 | if (has('PB', lformat)) then 386 | begin 387 | result := output(Self.PetaBytes, formatsettings, lformat); 388 | Exit; 389 | end; 390 | if (has('TB', lformat)) then 391 | begin 392 | result := output(Self.TeraBytes, formatsettings, lformat); 393 | Exit; 394 | end; 395 | if (has('GB', lformat)) then 396 | begin 397 | result := output(Self.GigaBytes, formatsettings, lformat); 398 | Exit; 399 | end; 400 | if (has('MB', lformat)) then 401 | begin 402 | result := output(Self.MegaBytes, formatsettings, lformat); 403 | Exit; 404 | end; 405 | if (has('KB', lformat)) then 406 | begin 407 | result := output(Self.KiloBytes, formatsettings, lformat); 408 | Exit; 409 | end; 410 | // Byte and Bit symbol must be case-sensitive 411 | if (IndexOf(TByteSize.ByteSymbol, lformat, True) <> -1) then 412 | begin 413 | result := output(Self.Bytes, formatsettings, lformat); 414 | Exit; 415 | end; 416 | 417 | if (IndexOf(TByteSize.BitSymbol, lformat, True) <> -1) then 418 | begin 419 | result := output(Self.Bits, formatsettings, lformat); 420 | Exit; 421 | end; 422 | 423 | result := Format('%s %s', [FormatFloat(lformat, Self.LargestWholeNumberValue, 424 | formatsettings), Self.LargestWholeNumberSymbol]); 425 | 426 | end; 427 | 428 | function TByteSize.Equals(value: TByteSize): Boolean; 429 | begin 430 | result := Self.Bits = value.Bits; 431 | end; 432 | 433 | function TByteSize.CompareTo(other: TByteSize): Integer; 434 | begin 435 | if Self.Bits = other.Bits then 436 | begin 437 | result := 0; 438 | Exit; 439 | end; 440 | 441 | if Self.Bits < other.Bits then 442 | begin 443 | result := -1; 444 | Exit; 445 | end 446 | else 447 | begin 448 | result := 1; 449 | Exit; 450 | end; 451 | 452 | end; 453 | 454 | function TByteSize.Add(bs: TByteSize): TByteSize; 455 | begin 456 | result := TByteSize.Create(Self.Bytes + bs.Bytes); 457 | end; 458 | 459 | function TByteSize.AddBits(value: Int64): TByteSize; 460 | begin 461 | result := Self + FromBits(value); 462 | end; 463 | 464 | function TByteSize.AddBytes(value: Double): TByteSize; 465 | begin 466 | result := Self + TByteSize.FromBytes(value); 467 | end; 468 | 469 | function TByteSize.AddKiloBytes(value: Double): TByteSize; 470 | begin 471 | result := Self + TByteSize.FromKiloBytes(value); 472 | end; 473 | 474 | function TByteSize.AddMegaBytes(value: Double): TByteSize; 475 | begin 476 | result := Self + TByteSize.FromMegaBytes(value); 477 | end; 478 | 479 | function TByteSize.AddGigaBytes(value: Double): TByteSize; 480 | begin 481 | result := Self + TByteSize.FromGigaBytes(value); 482 | end; 483 | 484 | function TByteSize.AddTeraBytes(value: Double): TByteSize; 485 | begin 486 | result := Self + TByteSize.FromTeraBytes(value); 487 | end; 488 | 489 | function TByteSize.AddPetaBytes(value: Double): TByteSize; 490 | begin 491 | result := Self + TByteSize.FromPetaBytes(value); 492 | end; 493 | 494 | function TByteSize.Subtract(bs: TByteSize): TByteSize; 495 | begin 496 | result := TByteSize.Create(Self.Bytes - bs.Bytes); 497 | end; 498 | 499 | class operator TByteSize.Add(b1: TByteSize; b2: TByteSize): TByteSize; 500 | begin 501 | result := TByteSize.Create(b1.Bytes + b2.Bytes); 502 | end; 503 | 504 | class operator TByteSize.Subtract(b1: TByteSize; b2: TByteSize): TByteSize; 505 | begin 506 | result := TByteSize.Create(b1.Bytes - b2.Bytes); 507 | end; 508 | 509 | class operator TByteSize.Inc(b: TByteSize): TByteSize; 510 | begin 511 | result := TByteSize.Create(b.Bytes + 1); 512 | end; 513 | 514 | class operator TByteSize.Dec(b: TByteSize): TByteSize; 515 | begin 516 | result := TByteSize.Create(b.Bytes - 1); 517 | end; 518 | 519 | class operator TByteSize.Positive(b: TByteSize): TByteSize; 520 | begin 521 | result := TByteSize.Create(+b.Bytes); 522 | end; 523 | 524 | class operator TByteSize.Negative(b: TByteSize): TByteSize; 525 | begin 526 | result := TByteSize.Create(-b.Bytes); 527 | end; 528 | 529 | class operator TByteSize.Equal(b1: TByteSize; b2: TByteSize): Boolean; 530 | begin 531 | result := b1.Bits = b2.Bits; 532 | end; 533 | 534 | class operator TByteSize.NotEqual(b1: TByteSize; b2: TByteSize): Boolean; 535 | begin 536 | result := b1.Bits <> b2.Bits; 537 | end; 538 | 539 | class operator TByteSize.LessThan(b1: TByteSize; b2: TByteSize): Boolean; 540 | begin 541 | result := b1.Bits < b2.Bits; 542 | end; 543 | 544 | class operator TByteSize.LessThanOrEqual(b1: TByteSize; b2: TByteSize): Boolean; 545 | begin 546 | result := b1.Bits <= b2.Bits; 547 | end; 548 | 549 | class operator TByteSize.GreaterThan(b1: TByteSize; b2: TByteSize): Boolean; 550 | begin 551 | result := b1.Bits > b2.Bits; 552 | end; 553 | 554 | class operator TByteSize.GreaterThanOrEqual(b1: TByteSize; 555 | b2: TByteSize): Boolean; 556 | begin 557 | result := b1.Bits >= b2.Bits; 558 | end; 559 | 560 | class function TByteSize.TryParse(const s: String; 561 | out varresult: TByteSize): Boolean; 562 | 563 | begin 564 | try 565 | varresult := Parse(s); 566 | result := True; 567 | except 568 | varresult := Default (TByteSize); 569 | result := False; 570 | end; 571 | end; 572 | 573 | class function TByteSize.Parse(const s: String): TByteSize; 574 | var 575 | num, lastNumber, tempInt: Integer; 576 | found: Boolean; 577 | numberPart, sizePart, tempS: String; 578 | number, d1: Double; 579 | lFormatSettings: TFormatSettings; 580 | decimalSeperator, groupSeperator: Char; 581 | begin 582 | 583 | // Arg checking 584 | if (IsNullOrWhiteSpace(s)) then 585 | raise EArgumentNilException.CreateRes(@SEmptyString); 586 | 587 | // Get the index of the first non-digit character 588 | tempS := TrimLeft(s); // Protect against leading spaces 589 | found := False; 590 | 591 | {$IFDEF FPC} 592 | lFormatSettings := DefaultFormatSettings; 593 | {$ELSE} 594 | {$IF DEFINED (SUPPORT_TFORMATSETTINGS_CREATE_INSTANCE)} 595 | lFormatSettings := TFormatSettings.Create; 596 | {$ELSE} 597 | GetLocaleFormatSettings(0, lFormatSettings); 598 | {$IFEND} 599 | {$ENDIF} 600 | decimalSeperator := lFormatSettings.DecimalSeparator; 601 | groupSeperator := lFormatSettings.ThousandSeparator; 602 | 603 | // Pick first non-digit number 604 | 605 | for num := 1 to Length(tempS) do 606 | begin 607 | if (not(CharInSet(tempS[num], ['0' .. '9']) or 608 | (tempS[num] = decimalSeperator) or (tempS[num] = groupSeperator))) then 609 | 610 | begin 611 | found := True; 612 | break; 613 | end; 614 | 615 | end; 616 | 617 | if (not found) then 618 | begin 619 | 620 | raise EFormatException.CreateResFmt(@SInvalidInput, [s]); 621 | 622 | end; 623 | 624 | lastNumber := num; 625 | 626 | // Cut the input string in half 627 | numberPart := Trim(Copy(tempS, 1, lastNumber - 1)); 628 | sizePart := Trim(Copy(tempS, lastNumber, Length(tempS) - (lastNumber - 1))); 629 | 630 | // Get the numeric part 631 | // since ThousandSeperators and Currency Symbols are not allowed in 632 | // "TryStrToFloat" and "StrToFloat" for ("Delphi"), we simply replace our "ThousandSeperators" 633 | // with an empty Char. 634 | numberPart := StringReplace(numberPart, groupSeperator, '', 635 | [rfReplaceAll, rfIgnoreCase]); 636 | if not(TryStrToFloat(numberPart, number, lFormatSettings)) then 637 | begin 638 | raise EFormatException.CreateResFmt(@SInvalidInput2, [s]); 639 | end; 640 | 641 | // Get the magnitude part 642 | tempInt := AnsiIndexStr(sizePart, ['b', 'B', 'KB', 'kB', 'kb', 'MB', 'mB', 643 | 'mb', 'GB', 'gB', 'gb', 'TB', 'tB', 'tb', 'PB', 'pB', 'pb']); 644 | case tempInt of 645 | 0: 646 | begin 647 | 648 | d1 := 1 * 1.0; 649 | if (FloatingMod(number, d1) <> 0) then // Can't have partial bits 650 | begin 651 | raise EFormatException.CreateResFmt(@SInvalidBit, [s]); 652 | end 653 | else 654 | begin 655 | result := FromBits(Trunc(number)); 656 | Exit; 657 | end; 658 | 659 | end; 660 | 661 | 1: 662 | begin 663 | result := FromBytes(number); 664 | Exit; 665 | end; 666 | 667 | 2 .. 4: 668 | begin 669 | result := FromKiloBytes(number); 670 | Exit; 671 | end; 672 | 673 | 5 .. 7: 674 | begin 675 | result := FromMegaBytes(number); 676 | Exit; 677 | end; 678 | 679 | 8 .. 10: 680 | begin 681 | result := FromGigaBytes(number); 682 | Exit; 683 | end; 684 | 685 | 11 .. 13: 686 | begin 687 | result := FromTeraBytes(number); 688 | Exit; 689 | end; 690 | 691 | 14 .. 16: 692 | begin 693 | result := FromPetaBytes(number); 694 | Exit; 695 | end; 696 | 697 | else 698 | raise EFormatException.CreateResFmt(@SUnSupportedMagnitude, [sizePart]); 699 | 700 | end; 701 | 702 | end; 703 | 704 | class function TByteSize.has(const SubStr: String; const Str: String): Boolean; 705 | begin 706 | result := IndexOf(SubStr, Str, False) <> -1; 707 | end; 708 | 709 | class function TByteSize.output(n: Double; formatsettings: TFormatSettings; 710 | const formatstr: String): String; 711 | begin 712 | result := FormatFloat(formatstr, n, formatsettings); 713 | end; 714 | 715 | class function TByteSize.Contains(InChar: Char; const InString: String) 716 | : Boolean; 717 | var 718 | i: Integer; 719 | 720 | begin 721 | result := False; 722 | for i := 1 to Length(InString) do 723 | 724 | begin 725 | if InString[i] = InChar then 726 | begin 727 | result := True; 728 | Exit; 729 | end; 730 | end; 731 | 732 | end; 733 | 734 | class function TByteSize.IndexOf(const SubStr: String; const Str: String; 735 | caseSensitive: Boolean): Integer; 736 | 737 | begin 738 | if caseSensitive then 739 | result := Pos(SubStr, Str) - 1 740 | else 741 | result := Pos(AnsiUpperCase(SubStr), AnsiUpperCase(Str)) - 1; 742 | end; 743 | 744 | class function TByteSize.IsNullOrWhiteSpace(const InValue: string): Boolean; 745 | begin 746 | result := Length(Trim(InValue)) = 0; 747 | end; 748 | 749 | class function TByteSize.FloatingMod(a: Double; b: Double): Double; 750 | var 751 | tempDouble: Double; 752 | begin 753 | tempDouble := (a / b); 754 | result := a - b * Trunc(tempDouble); 755 | end; 756 | 757 | class function TByteSize.GetMinValue: TByteSize; 758 | begin 759 | result := TByteSize.FromBits(0); 760 | end; 761 | 762 | function TByteSize.GetPetaBytes: Double; 763 | begin 764 | result := Bytes / BytesInPetaByte; 765 | end; 766 | 767 | function TByteSize.GetTeraBytes: Double; 768 | begin 769 | result := Bytes / BytesInTeraByte; 770 | end; 771 | 772 | function TByteSize.GetBits: Int64; 773 | begin 774 | result := FBits; 775 | end; 776 | 777 | function TByteSize.GetBytes: Double; 778 | begin 779 | result := FBytes; 780 | end; 781 | 782 | function TByteSize.GetGigaBytes: Double; 783 | begin 784 | result := Bytes / BytesInGigaByte; 785 | end; 786 | 787 | function TByteSize.GetKiloBytes: Double; 788 | begin 789 | result := Bytes / BytesInKiloByte; 790 | end; 791 | 792 | class function TByteSize.GetMaxValue: TByteSize; 793 | begin 794 | result := TByteSize.FromBits(Int64MaxValue); 795 | end; 796 | 797 | function TByteSize.GetMegaBytes: Double; 798 | begin 799 | result := Bytes / BytesInMegaByte; 800 | end; 801 | 802 | end. 803 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ugochukwu Mmaduekwe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ByteSizeLibPascal 2 | =========== 3 | 4 | **This is a Port of [ByteSize](https://github.com/omar/ByteSize) to Delphi/FreePascal.** 5 | 6 | `TByteSize` is a utility "record" that makes byte size representation in code easier by removing ambiguity of the value being represented. 7 | 8 | `TByteSize` is to bytes what `System.TimeSpan.TTimeSpan` is to time. 9 | 10 | #### Building 11 | 12 | This project was created using Delphi 10 Seattle Update 1 but should compile in 13 | any Delphi version from 2009 and FreePascal 3.0.0 Upwards. 14 | 15 | ## Usage 16 | 17 | Without `TByteSize`: 18 | 19 | ```pascal 20 | const 21 | MaxFileSizeMBs = 1.5; 22 | 23 | // I need it in KBs! 24 | 25 | var 26 | kilobytes: Double; 27 | begin 28 | kilobytes := MaxFileSizeMBs * 1024; 29 | end; 30 | ``` 31 | 32 | With `ByteSize`: 33 | 34 | ```pascal 35 | var 36 | MaxFileSize: TByteSize; 37 | begin 38 | MaxFileSize := TByteSize.FromMegaBytes(1.5); 39 | end; 40 | 41 | // I have it in KBs! 42 | MaxFileSize.KiloBytes; 43 | ``` 44 | 45 | `TByteSize` behaves like any other `record` backed by a numerical value. 46 | 47 | ```pascal 48 | // Add 49 | var 50 | monthlyUsage, currentUsage, total, delta, : TByteSize; 51 | begin 52 | monthlyUsage := TByteSize.FromGigaBytes(10); 53 | currentUsage := TByteSize.FromMegaBytes(512); 54 | total := monthlyUsage + currentUsage; 55 | 56 | total.Add(ByteSize.FromKiloBytes(10)); 57 | total.AddGigaBytes(10); 58 | 59 | // Subtract 60 | delta := total.Subtract(TByteSize.FromKiloBytes(10)); 61 | delta := delta - TByteSize.FromGigaBytes(100); 62 | delta := delta.AddMegaBytes(-100); 63 | 64 | end; 65 | ``` 66 | 67 | ### Constructors 68 | 69 | You can create a `ByteSize` "object" from `bits`, `bytes`, `kilobytes`, `megabytes`, `gigabytes`, and `terabytes`. 70 | 71 | ```pascal 72 | TByteSize.Create(1.5); // Constructor takes in bytes 73 | 74 | // Static Constructors 75 | TByteSize.FromBits(10); // Bits are whole numbers only 76 | TByteSize.FromBytes(1.5); // Same as constructor 77 | TByteSize.FromKiloBytes(1.5); 78 | TByteSize.FromMegaBytes(1.5); 79 | TByteSize.FromGigaBytes(1.5); 80 | TByteSize.FromTeraBytes(1.5); 81 | TByteSize.FromPetaBytes(1.5); 82 | 83 | ``` 84 | 85 | ### Properties 86 | 87 | A `TByteSize` "object" contains representations in `bits`, `bytes`, `kilobytes`, `megabytes`, `gigabytes`, `terabytes` and `petabytes`. 88 | 89 | ```pascal 90 | var 91 | maxFileSize: TByteSize; 92 | begin 93 | maxFileSize := TByteSize.FromKiloBytes(10); 94 | 95 | maxFileSize.Bits; // 81920 96 | maxFileSize.Bytes; // 10240 97 | maxFileSize.KiloBytes; // 10 98 | maxFileSize.MegaBytes; // 0.009765625 99 | maxFileSize.GigaBytes; // 9.53674316e-6 100 | maxFileSize.TeraBytes; // 9.31322575e-9 101 | end; 102 | ``` 103 | 104 | A `TByteSize` "object" also contains two properties that represent the largest metric prefix symbol and value. 105 | 106 | ```pascal 107 | var 108 | maxFileSize: TByteSize; 109 | begin 110 | maxFileSize := TByteSize.FromKiloBytes(10); 111 | 112 | maxFileSize.LargestWholeNumberSymbol; // "KB" 113 | maxFileSize.LargestWholeNumberValue; // 10 114 | 115 | end; 116 | ``` 117 | 118 | ### String Representation 119 | 120 | All String Parsing (`String to TByteSize`) operations are localized to use the number decimal separator of the currently set Locale. 121 | 122 | #### ToString 123 | 124 | `TByteSize` comes with a handy `ToString` method that uses the largest metric prefix whose value is greater than or equal to 1. 125 | 126 | ```pascal 127 | TByteSize.FromBits(7).ToString; // 7 b 128 | TByteSize.FromBits(8).ToString; // 1 B 129 | TByteSize.FromKiloBytes(.5).ToString; // 512 B 130 | TByteSize.FromKiloBytes(1000).ToString; // 1000 KB 131 | TByteSize.FromKiloBytes(1024).ToString; // 1 MB 132 | TByteSize.FromGigabytes(.5).ToString; // 512 MB 133 | TByteSize.FromGigabytes(1024).ToString; // 1 TB 134 | ``` 135 | 136 | #### Formatting 137 | 138 | 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`, `PB`. The formatter uses the built in [`FormatFloat` method](http://docwiki.embarcadero.com/Libraries/Seattle/en/System.SysUtils.FormatFloat). The default number format is `#.##` which rounds the number to two decimal places. 139 | 140 | You can include symbol and number formats. 141 | 142 | ```pascal 143 | var 144 | b: TByteSize; 145 | begin 146 | b := TByteSize.FromKiloBytes(10.505); 147 | 148 | // Default number format is #.## 149 | b.ToString('KB'); // 10.52 KB 150 | b.ToString('MB'); // .01 MB 151 | b.ToString('b'); // 86057 b 152 | 153 | // Default symbol is the largest metric prefix value >= 1 154 | b.ToString('#.#'); // 10.5 KB 155 | 156 | // All valid values of double.ToString(string format) are acceptable 157 | b.ToString('0.0000'); // 10.5050 KB 158 | b.ToString('000.00'); // 010.51 KB 159 | 160 | // You can include number format and symbols 161 | b.ToString('#.#### MB'); // .0103 MB 162 | b.ToString('0.00 GB'); // 0 GB 163 | b.ToString('#.## B'); // 10757.12 B 164 | end; 165 | ``` 166 | 167 | #### Parsing 168 | 169 | `ByteSize` has a `Parse` and `TryParse` method. 170 | 171 | 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. 172 | 173 | ```pascal 174 | var 175 | output: TByteSize; 176 | begin 177 | TByteSize.TryParse('1.5mb', output); 178 | 179 | // Invalid 180 | TByteSize.Parse('1.5 b'); // Can't have partial bits 181 | 182 | // Valid 183 | TByteSize.Parse('5b'); 184 | TByteSize.Parse('1.55B'); 185 | TByteSize.Parse('1.55KB'); 186 | TByteSize.Parse('1.55 kB '); // Spaces are trimmed 187 | TByteSize.Parse('1.55 kb'); 188 | TByteSize.Parse('1.55 MB'); 189 | TByteSize.Parse('1.55 mB'); 190 | TByteSize.Parse('1.55 mb'); 191 | TByteSize.Parse('1.55 GB'); 192 | TByteSize.Parse('1.55 gB'); 193 | TByteSize.Parse('1.55 gb'); 194 | TByteSize.Parse('1.55 TB'); 195 | TByteSize.Parse('1.55 tB'); 196 | TByteSize.Parse('1.55 tb'); 197 | TByteSize.Parse('1,55 kb'); // de-DE culture 198 | end; 199 | ``` 200 | 201 | ###Unit Tests 202 | 203 | Unit Tests can be found in ByteSizeLib.Tests Folder. 204 | The unit tests makes use of DUnitX and TestInsight. 205 | 206 | ###License 207 | 208 | This "Software" is Licensed Under **`MIT License (MIT)`** . 209 | 210 | #### Tip Jar 211 | * :dollar: **Bitcoin**: `1MhFfW7tDuEHQSgie65uJcAfJgCNchGeKf` 212 | * :euro: **Ethereum**: `0x6c1DC21aeC49A822A4f1E3bf07c623C2C1978a98` 213 | * :pound: **Pascalcoin**: `345367-40` 214 | 215 | ###Conclusion 216 | 217 | 218 | Special Thanks to [Omar Khudeira](https://github.com/omar/) for [this](https://github.com/omar/ByteSize) awesome library. 219 | (Thanks to the developers of [DUnitX Testing Framework](https://github.com/VSoftTechnologies/DUnitX/) and [TestInsight](https://bitbucket.org/sglienke/testinsight/wiki/Home/) for making tools that simplifies unit testing. 220 | 221 | --------------------------------------------------------------------------------