From 97f1e4e193c9e379676f16f91b4a0aa6867a9784 Mon Sep 17 00:00:00 2001 From: sharpchen Date: Wed, 5 Feb 2025 06:38:16 +0800 Subject: [PATCH] main --- .../document/Articles/docs/ADB Cheat Sheet.md | 2 +- .../docs/Understanding Bit Operation.md | 180 ++++++++++++++++++ .../docs/Understanding String Formatting.md | 81 +++++++- .../PowerShell/docs/Item Manipulation/Path.md | 3 +- .../docs/Item Manipulation/Scoped Options.md | 8 + 5 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 docs/document/Modern CSharp/docs/Understanding Bit Operation.md create mode 100644 docs/document/PowerShell/docs/Item Manipulation/Scoped Options.md diff --git a/docs/document/Articles/docs/ADB Cheat Sheet.md b/docs/document/Articles/docs/ADB Cheat Sheet.md index 185ab54..e7a9eb4 100644 --- a/docs/document/Articles/docs/ADB Cheat Sheet.md +++ b/docs/document/Articles/docs/ADB Cheat Sheet.md @@ -32,7 +32,7 @@ adb sideload /path/to/rom.zip ## ABI -```ps1 +```sh adb shell getprop ro.vendor.product.cpu.abilist64 adb shell getprop ro.vendor.product.cpu.abilist # all abi ``` diff --git a/docs/document/Modern CSharp/docs/Understanding Bit Operation.md b/docs/document/Modern CSharp/docs/Understanding Bit Operation.md new file mode 100644 index 0000000..c8c532d --- /dev/null +++ b/docs/document/Modern CSharp/docs/Understanding Bit Operation.md @@ -0,0 +1,180 @@ +# Understanding Bit Operation + +## Bit Shifting + +### Left & Right Shifting + +Left shifting moves the whole bit sequence with specific count to left, `0` will fill up the tail and the leading bits are just discarded. + +```cs + +uint before = 0b_1001_0000_0000_0000_0000_0000_0000_1001; +uint after = before << 4; +Console.WriteLine($"{nameof(before),6}: {before,32:B32}"); +Console.WriteLine($"{nameof(after),6}: {after:B32}"); + +// before: 10010000000000000000000000001001 +// ^^^^ ^^^^ +// discarded move left + +// after: 00000000000000000000000010010000 +// ^^^^ +``` + +Right shifting does it reversely. +The only difference is, when shifting on *signed* integers, bits would be filled with the sign bit value(`0` for positive, `1` for negative) + +```cs +sbyte before = sbyte.MinValue; +sbyte after = (sbyte)(before >> 4); +Console.WriteLine($"{nameof(before),6}: {before:B8}"); +Console.WriteLine($"{nameof(after),6}: {after:B8}"); + +``` + +> [!NOTE] +> Left & Right Shifting supports only `int`, `uint`, `long`, `ulong`. If you perform shifting on other integer types, the leftoperand is converted as `int` + +> [!NOTE] +> If shift count exceeds the bit width or is even negative, the count is determined by +> - if leftoperand is `int` or `uint`: `count = count & 0b_1_1111` +> - if leftoperand is `long` or `ulong`: `count = count & 0b_11_1111` + +> [!NOTE] +> Left shifting might discard sign of the number when it's signed +>```cs +>int foo = -0b_0001_0001_0001_0001_0001_0001_0001_0001_01; +>Console.WriteLine(foo.ToString("B32")); +>Console.WriteLine((foo << 1).ToString("B32")); +>Console.WriteLine(int.IsPositive(foo << 1)); + +>// 10111011101110111011101110111011 +>// 01110111011101110111011101110110 +>// True +>``` + +### Unsigned Right Shifting + +> [!NOTE] +> `>>>` was supported since C# 11 + +If you want to make sure that the empty bits are filled with `0` instead of value of the sign when working with the signed integers, use `>>>`! + +```cs +int before = int.MinValue; +int after = before >> 2; +int afterUnsigned = before >>> 2; // [!code highlight] +Console.WriteLine($"{nameof(before),-20}: {before:B32}"); +Console.WriteLine($"{nameof(after),-20}: {after:B32}"); +Console.WriteLine($"{nameof(afterUnsigned),-20}: {afterUnsigned:B32}"); + +// before : 10000000000000000000000000000000 +// after : 11100000000000000000000000000000 +// afterUnsigned : 00100000000000000000000000000000 // [!code highlight] +``` + +> [!NOTE] +> Before `>>>` was added, you had to perform casting to achieve the same +>```cs +>int afterUnsigned = unchecked((int)((uint)before >> 2)); +>``` + +## Bitwise NOT + +Reverse value of each bit + +```cs +uint before = 0b_0100010; +uint after = ~before; +Console.WriteLine($"{nameof(before),6}: {before,32:B32}"); +Console.WriteLine($"{nameof(after),6}: {after:B}"); +// before: 00000000000000000000000000100010 +// after: 11111111111111111111111111011101 +``` + +## Bitwise OR & AND & XOR + +- bitwise OR `|`: returns `1` for each bit as long as one of the two is `1`, else `0` +- bitwise AND `&`: returns `1` for each bit as long as all of the two is `1`, else `0` +- bitwise XOR `^`: returns `1` if the two bits are different, `0` when identical + + +## Bitwise on Enum + +Enum can be flags when the type is marked with `FlagsAttribute` and ordinary enum members are powers of 2(members represent the `All` or `None` are exceptional) + +```cs +[Flags] +enum Foo +{ + None = 0b0000, + Bar = 0b0001, + Baz = 0b0010, + Qux = 0b0100, + Goo = 0b1000, + All = 0b1111 +} +// powers can be easily done by left shifting +[Flags] +enum Foo +{ + None = 0, + Bar = 1, + Baz = 1 << 1, + Qux = 1 << 2, + Goo = 1 << 3, + All = ~(~0 << 4) +} +``` + +## Bit Mask + +Bit mask is a common pattern that works like a filter to include or exclude or test bits. +The mask can refer to a integer represented as binary, a sequence of integers or a matrix of integers. The classical usage is a singular number. + +### Is Bit Set + +A common usage of mask is check whether specific bit **is set** + +- when a bit is `1` meaning that it **is set** +- when a bit is `0` meaning that it **is cleared** + +A mask is a predefined number with special layout designated to solve specific problem. +The following example shows how a mask is generated for the purpose. + +`1` is shifted left to the position we would like to compare, and a bitwise AND is performed. +Only the position matters since other bits are all `0` in the mask. +So only when the bit on the position is set can the operation returns non-zero value. + +```cs +uint number = 0b_0101; +int position = 2; +int mask = 1 << position; // generate a special number 0100 +bool positionIsSet = (number & mask) != 0; +``` + +This is the particular same case as how we tell whether a union of enum contains a enum flag. +Since each enum member has **only one bit set**, the union in the following example has two bits set, only when the set bit from the flag being checked overlaps with any bit of the union can it evaluate to non-zero. +And in fact the operation `(union & flag)` should be equal to the flag itself. + +> [!WARNING] +> You have to make sure the enum member ot integer to be checked is a valid member or it may evaluate to unexpected value. + +```cs +Foo foo = Foo.Bar | Foo.Qux; +_ = (foo & Foo.Qux) != 0; // True +_ = (foo & Foo.Qux) == Foo.Qux; // True +_ = (foo & Foo.Goo) != 0; // False +_ = (foo & Foo.Goo) == Foo.Goo; // False + +[Flags] +enum Foo +{ + None = 0, + Bar = 1, + Baz = 1 << 1, + Qux = 1 << 2, + Goo = 1 << 3, + All = ~(~0 << 4) +} +``` diff --git a/docs/document/Modern CSharp/docs/Understanding String Formatting.md b/docs/document/Modern CSharp/docs/Understanding String Formatting.md index 9d1600c..931eafe 100644 --- a/docs/document/Modern CSharp/docs/Understanding String Formatting.md +++ b/docs/document/Modern CSharp/docs/Understanding String Formatting.md @@ -26,7 +26,7 @@ The second syntax in composite formatting is a optional integer for the interpol ```cs string.Format("{0,20}", 123); // 123 -string.Format("{0,-20}", 123); +string.Format("{0,-20:G}", 123); // 123 ^ ends here ``` @@ -94,7 +94,54 @@ Composite formatting supports a dedicated syntax to represent any numeric format > [!NOTE] > See [standard TimeSpan format](https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-timespan-format-strings#the-general-long-g-format-specifier) and [Arbitrary TimeSpan format](https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-timespan-format-strings) -## How to Support a Custom Format +### Enum Format + +Enum formatting is handled by `Enum.ToString` static methods. They're implicitly called as if they're intrinsic. + +There's two scenarios of enum formatting +- singular value + A valid enum value as integer can be directly evaluated as the enum name. + More specifically, the format is **G**eneral when there's no format specified. + If an integer is not a valid value for the enum, compiler does not yell but the default evaluation for it will be the number itself + ```cs + Console.WriteLine(((DayOfWeek)0).ToString()); // Sunday + Console.WriteLine(((DayOfWeek)0).ToString("G")); // Sunday + Console.WriteLine(((DayOfWeek)7).ToString()); // 7, which is not a member of the enum + ``` + However, `Enum.ToString` supports `F` format for a invalid value of enum that can be formatted as a union + > [!NOTE] + > Respectively you can use `D` and `X` to enforce format a enum or enum union to be decimal numeric and hexadecimal when the enum is a valid flag + ```cs + Console.WriteLine(((DayOfWeek)7).ToString("F")); // Monday, Saturday + Console.WriteLine((Foo.Bar | Foo.Baz).ToString("F")); // Bar, Baz + enum Foo + { + None = 0b0000, + Bar = 0b0001, + Baz = 0b0010, + Qux = 0b0100, + Goo = 0b1000, + All = 0b1111 + } + ``` +- bitwise or + As long as the enum was marked with `FlagAttribute` and all member values are in a powered order, the bitwise or result of any distinct combination can be formatted as the names of enum member separated by comma. + ```cs + var foo = (Foo.Bar | Foo.Baz | Foo.Bar).ToString(); // Bar, Baz + [Flags] + enum Foo + { + None = 0b0000, + Bar = 0b0001, + Baz = 0b0010, + Qux = 0b0100, + Goo = 0b1000, + All = 0b1111 + } + ``` + + +## Custom Formatting Before we implement a custom process for our format, we have to understand the common interfaces for formatting. @@ -320,3 +367,33 @@ if (s == null) // if ICustomFormatter.Format returns null // [!code highlight] > [!NOTE] > `ISpanFormattable` is a more advance topic since .NET 6. + +## Formatting in Interpolated String + +### Use Culture + +Interpolated strings are always formatted using `CultureInfo.CurrentCulture` by default. + +- .NET 5 and earlier: `FormattableString` can be used as a wrapper of a interpolated string and use `FormattableString.ToString(IFormatProvider)` to format it by certain culture. + + ```cs + FormattableString str = $"I am a syntax sugar for {"FormattableString"}"; + _ = str.ToString(CultureInfo.CreateSpecificCulture("en-US")); + ``` + +- since .NET 6: using `string.Create(IFormatProvider? provider, ref DefaultInterpolatedStringHandler handler)` is a more performance solution. + The syntax shorthand is kind of extreme, you don't even have to specify `ref`, compiler will do it for you. + + ```cs + _ = string.Create( + CultureInfo.CreateSpecificCulture("en-US"), + $"I am a syntax sugar for {"DefaultInterpolatedStringHandler"}" + ); + ``` + +### Interpolated String Handler + + +> [!NOTE] +> See [Interpolated String Handler Pattern](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/improved-interpolated-strings#the-handler-pattern) +> and [Custom Interpolated String Handler](https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/performance/interpolated-string-handler) diff --git a/docs/document/PowerShell/docs/Item Manipulation/Path.md b/docs/document/PowerShell/docs/Item Manipulation/Path.md index 94a5a59..b9b6fb4 100644 --- a/docs/document/PowerShell/docs/Item Manipulation/Path.md +++ b/docs/document/PowerShell/docs/Item Manipulation/Path.md @@ -18,7 +18,7 @@ ## Part of Path -- `-Path(0, pv)`: get parent path as `PathInfo` +- `-Path(0, pv)`: get parent path as `string` ```ps1 Split-Path ([System.IO.Path]::GetTempFileName()) # C:\Users\username\AppData\Local\Temp ``` @@ -92,6 +92,7 @@ ```ps1 Join-Path -Path foo -ChildPath foo -AdditionalChildPath foo, foo, foo # this is how it work formally Join-Path foo foo foo foo foo # this is how you could use it in daily life + # foo\foo\foo\foo\foo ``` - `-Resolve(switch)`: resolve( and validate) the path and join them, supports wildcard to join multiple matches at one time ```ps1 diff --git a/docs/document/PowerShell/docs/Item Manipulation/Scoped Options.md b/docs/document/PowerShell/docs/Item Manipulation/Scoped Options.md new file mode 100644 index 0000000..a8f9b72 --- /dev/null +++ b/docs/document/PowerShell/docs/Item Manipulation/Scoped Options.md @@ -0,0 +1,8 @@ +# Scoped Options + +Scoped options are constrains to describe the state of a **item**, only specific to items alive during a session like aliases, functions and variables. + +Item cmdlets may have `-Options` parameter but there won't have completion for it unless you're operating on a session state item. + +> [!NOTE] +> See [ScopedItemOptions](https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.scopeditemoptions?view=powershellsdk-7.4.0&viewFallbackFrom=powershellsdk-7.0.0)