├── src ├── ZString.Unity │ ├── ProjectSettings │ │ ├── boot.config │ │ ├── ProjectVersion.txt │ │ ├── ClusterInputManager.asset │ │ ├── PresetManager.asset │ │ ├── NetworkManager.asset │ │ ├── VFXManager.asset │ │ ├── XRSettings.asset │ │ ├── VersionControlSettings.asset │ │ ├── TimeManager.asset │ │ ├── EditorBuildSettings.asset │ │ ├── AudioManager.asset │ │ ├── TagManager.asset │ │ ├── EditorSettings.asset │ │ ├── UnityConnectSettings.asset │ │ ├── PackageManagerSettings.asset │ │ ├── DynamicsManager.asset │ │ ├── MemorySettings.asset │ │ ├── NavMeshAreas.asset │ │ ├── GraphicsSettings.asset │ │ ├── Physics2DSettings.asset │ │ └── QualitySettings.asset │ ├── UserSettings │ │ ├── Search.settings │ │ └── EditorUserSettings.asset │ ├── Assets │ │ ├── Scripts │ │ │ ├── ZString │ │ │ │ ├── csc.rsp │ │ │ │ ├── csc.rsp.meta │ │ │ │ ├── package.json.meta │ │ │ │ ├── Number.meta │ │ │ │ ├── Unity.meta │ │ │ │ ├── Utf16.meta │ │ │ │ ├── Utf8.meta │ │ │ │ ├── ZString.asmdef.meta │ │ │ │ ├── IResettableBufferWriter.cs │ │ │ │ ├── Shims.cs.meta │ │ │ │ ├── EnumUtil.cs.meta │ │ │ │ ├── ZString.cs.meta │ │ │ │ ├── ExceptionUtil.cs.meta │ │ │ │ ├── FormatHelper.cs.meta │ │ │ │ ├── FormatParser.cs.meta │ │ │ │ ├── Number │ │ │ │ │ ├── BufferEx.cs.meta │ │ │ │ │ ├── FloatEx.cs.meta │ │ │ │ │ ├── GuidEx.cs.meta │ │ │ │ │ ├── MathEx.cs.meta │ │ │ │ │ ├── BitOperations.cs.meta │ │ │ │ │ ├── DecimalEx.cs.meta │ │ │ │ │ ├── HexConverter.cs.meta │ │ │ │ │ ├── Number.DiyFp.cs.meta │ │ │ │ │ ├── Number.Grisu3.cs.meta │ │ │ │ │ ├── FormattingHelpers.cs.meta │ │ │ │ │ ├── InternalSpanEx.cs.meta │ │ │ │ │ ├── Number.BigInteger.cs.meta │ │ │ │ │ ├── Number.Dragon4.cs.meta │ │ │ │ │ ├── Number.Formatting.cs.meta │ │ │ │ │ ├── Number.Parsing.cs.meta │ │ │ │ │ ├── NumberFormatInfoEx.cs.meta │ │ │ │ │ ├── ValueStringBuilder.cs.meta │ │ │ │ │ ├── Number.NumberBuffer.cs.meta │ │ │ │ │ ├── Number.NumberToFloatingPointBits.cs.meta │ │ │ │ │ ├── NumberFormatInfoEx.cs │ │ │ │ │ ├── BufferEx.cs │ │ │ │ │ ├── FloatEx.cs │ │ │ │ │ ├── DecimalEx.cs │ │ │ │ │ ├── FormattingHelpers.cs │ │ │ │ │ └── Number.NumberBuffer.cs │ │ │ │ ├── PreparedFormat.cs.meta │ │ │ │ ├── ZString.Concat.cs.meta │ │ │ │ ├── ZString.Format.cs.meta │ │ │ │ ├── ZString.Prepare.cs.meta │ │ │ │ ├── ZStringWriter.cs.meta │ │ │ │ ├── FastNumberWriter.cs.meta │ │ │ │ ├── PreparedFormatHelper.cs.meta │ │ │ │ ├── ReadOnlyListAdaptor.cs.meta │ │ │ │ ├── ZString.Utf8Format.cs.meta │ │ │ │ ├── IResettableBufferWriter.cs.meta │ │ │ │ ├── StringBuilder.AppendJoin.cs.meta │ │ │ │ ├── Utf16ValueStringBuilder.cs.meta │ │ │ │ ├── Utf8ValueStringBuilder.cs.meta │ │ │ │ ├── Unity │ │ │ │ │ ├── TextMeshProExtensions.cs.meta │ │ │ │ │ ├── TextMeshProExtensions.SetStringBuilder.cs.meta │ │ │ │ │ └── TextMeshProExtensions.SetStringBuilder.cs │ │ │ │ ├── NestedStringBuilderCreationException.cs.meta │ │ │ │ ├── Utf8 │ │ │ │ │ ├── Utf8ValueStringBuilder.AppendFormat.cs.meta │ │ │ │ │ ├── Utf8ValueStringBuilder.CreateFormatter.cs.meta │ │ │ │ │ └── Utf8ValueStringBuilder.SpanFormattableAppend.cs.meta │ │ │ │ ├── Utf16 │ │ │ │ │ ├── Utf16ValueStringBuilder.AppendFormat.cs.meta │ │ │ │ │ ├── Utf16ValueStringBuilder.CreateFormatter.cs.meta │ │ │ │ │ └── Utf16ValueStringBuilder.SpanFormattableAppend.cs.meta │ │ │ │ ├── package.json │ │ │ │ ├── NestedStringBuilderCreationException.cs │ │ │ │ ├── ZString.asmdef │ │ │ │ ├── ExceptionUtil.cs │ │ │ │ ├── ReadOnlyListAdaptor.cs │ │ │ │ └── EnumUtil.cs │ │ │ ├── Editor.meta │ │ │ ├── ZString.meta │ │ │ └── Editor │ │ │ │ ├── PackageExporter.cs.meta │ │ │ │ └── PackageExporter.cs │ │ ├── Resources │ │ │ ├── BillingMode.json │ │ │ └── BillingMode.json.meta │ │ ├── Plugins │ │ │ ├── System.Runtime.CompilerServices.Unsafe.dll │ │ │ └── System.Runtime.CompilerServices.Unsafe.dll.meta │ │ ├── Scenes │ │ │ ├── SampleScene.unity.meta │ │ │ ├── Test.cs.meta │ │ │ └── Test.cs │ │ ├── Plugins.meta │ │ ├── Resources.meta │ │ ├── Scenes.meta │ │ └── Scripts.meta │ └── .vsconfig └── ZString │ ├── IResettableBufferWriter.cs │ ├── Number │ ├── NumberFormatInfoEx.cs │ ├── BufferEx.cs │ ├── FloatEx.cs │ ├── DecimalEx.cs │ ├── FormattingHelpers.cs │ └── Number.NumberBuffer.cs │ ├── NestedStringBuilderCreationException.cs │ ├── ExceptionUtil.cs │ ├── ReadOnlyListAdaptor.cs │ ├── ZString.Prepare.tt │ ├── T4Common.t4 │ ├── _InternalVisibleTo.cs │ ├── Utf8 │ ├── Utf8ValueStringBuilder.CreateFormatter.tt │ ├── Utf8ValueStringBuilder.SpanFormattableAppend.tt │ └── Utf8ValueStringBuilder.AppendFormat.tt │ ├── ZString.Concat.tt │ ├── ZString.Format.tt │ ├── Unity │ └── TextMeshProExtensions.tt │ ├── EnumUtil.cs │ ├── Utf16 │ ├── Utf16ValueStringBuilder.SpanFormattableAppend.tt │ └── Utf16ValueStringBuilder.CreateFormatter.tt │ ├── PreparedFormat.tt │ ├── FormatHelper.tt │ └── ZString.Utf8Format.tt ├── Icon.png ├── docs └── graph.xlsx ├── opensource.snk ├── sandbox ├── BenchmarkVsReleasedVersion │ ├── runall.cmd │ ├── BenchmarkVsReleasedVersion.csproj │ ├── Program.cs │ ├── ConcatBenchmark.cs │ └── FormatBenchmark.cs ├── ConsoleAppNet472 │ ├── packages.config │ ├── Program.cs │ ├── App.config │ ├── Properties │ │ └── AssemblyInfo.cs │ └── ConsoleAppNet472.csproj ├── PerfBenchmark │ ├── PerfBenchmark.csproj │ ├── Program.cs │ └── Benchmarks │ │ ├── VSStringFormatter.cs │ │ ├── FormatBenchmark.cs │ │ ├── StringBuilderAppendJoin.cs │ │ ├── SixObjectConcatBenchmark.cs │ │ ├── StringBuilderAppendFormat.cs │ │ ├── StringListJoinBenchmark.cs │ │ └── AppendPerformance.cs └── ConsoleApp │ ├── ConsoleApp.csproj │ └── Program.cs ├── tests ├── ZString.Tests │ ├── CompositeFormatTest.cs │ ├── StringBuilderTest.cs │ ├── ZStringWriterTest.cs │ ├── Utf8StringBuilderTest.cs │ ├── ZString.Tests.csproj │ ├── RemoveTest.cs │ ├── InsertTest.cs │ ├── EnumTest.cs │ ├── ReplaceTest.cs │ └── NestedStringBuilder.cs └── ZString.NetCore2Tests │ └── ZString.NetCore2Tests.csproj ├── .github ├── workflows │ ├── prevent-github-change.yaml │ ├── stale.yaml │ ├── toc.yaml │ ├── build-debug.yaml │ └── build-release.yaml └── dependabot.yaml ├── LICENSE ├── .editorconfig ├── Directory.Build.props ├── .gitignore └── ZString.sln /src/ZString.Unity/ProjectSettings/boot.config: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/ZString.Unity/UserSettings/Search.settings: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cysharp/ZString/HEAD/Icon.png -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/csc.rsp: -------------------------------------------------------------------------------- 1 | -nullable:enable -------------------------------------------------------------------------------- /docs/graph.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cysharp/ZString/HEAD/docs/graph.xlsx -------------------------------------------------------------------------------- /opensource.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cysharp/ZString/HEAD/opensource.snk -------------------------------------------------------------------------------- /sandbox/BenchmarkVsReleasedVersion/runall.cmd: -------------------------------------------------------------------------------- 1 | dotnet run -c Release --filter * 2 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Resources/BillingMode.json: -------------------------------------------------------------------------------- 1 | {"androidStore":"GooglePlay"} -------------------------------------------------------------------------------- /tests/ZString.Tests/CompositeFormatTest.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cysharp/ZString/HEAD/tests/ZString.Tests/CompositeFormatTest.cs -------------------------------------------------------------------------------- /src/ZString.Unity/.vsconfig: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "components": [ 4 | "Microsoft.VisualStudio.Workload.ManagedGame" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2021.3.41f1 2 | m_EditorVersionWithRevision: 2021.3.41f1 (6c5a9e20c022) 3 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | m_DefaultList: [] 7 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Plugins/System.Runtime.CompilerServices.Unsafe.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cysharp/ZString/HEAD/src/ZString.Unity/Assets/Plugins/System.Runtime.CompilerServices.Unsafe.dll -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scenes/SampleScene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2cda990e2423bbf4892e6590ba056729 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/csc.rsp.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b81dbb099c31f4448d950b4576ad6eb 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/VFXManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!937362698 &1 4 | VFXManager: 5 | m_ObjectHideFlags: 0 6 | m_IndirectShader: {fileID: 0} 7 | m_RenderPipeSettingsPath: 8 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7ddd3a1ff295f1440982cd97100549a7 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 16211642873b4344cb240f8630e96980 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Resources/BillingMode.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4b42856c7aa4be24ba4a8f35e99b41d5 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e4672a57ce755a44805bc58b4ddea29 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9add6c3081c1e8a4087afc4921eff3b7 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fa1e5939638a14f4fa4681331ef65430 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ba0803434cb80a14083de2d39cc00351 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1260d4de3d15f5a45a5ef60c7fd826f0 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18a14422421519445bb6bd0685394b3b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5a401e97d5c5c0b4699e384a5baf299c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf16.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 873812c508c6fd34bb7dce99fc1a640a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf8.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 67d7f0242422cd6459b1e59c73ff46e8 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ZString.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 33661e06c33d31b4c9223810bf503247 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/XRSettings.asset: -------------------------------------------------------------------------------- 1 | { 2 | "m_SettingKeys": [ 3 | "VR Device Disabled", 4 | "VR Device User Alert" 5 | ], 6 | "m_SettingValues": [ 7 | "False", 8 | "False" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/VersionControlSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!890905787 &1 4 | VersionControlSettings: 5 | m_ObjectHideFlags: 0 6 | m_Mode: Visible Meta Files 7 | m_CollabEditorSettings: 8 | inProgressEnabled: 1 9 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.1 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /src/ZString/IResettableBufferWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Cysharp.Text 7 | { 8 | public interface IResettableBufferWriter : IBufferWriter 9 | { 10 | void Reset(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scenes/Test.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: af7cb41eb6ddb6944ae4c758581eb5bc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/IResettableBufferWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Cysharp.Text 7 | { 8 | public interface IResettableBufferWriter : IBufferWriter 9 | { 10 | void Reset(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.github/workflows/prevent-github-change.yaml: -------------------------------------------------------------------------------- 1 | name: Prevent github change 2 | on: 3 | pull_request: 4 | paths: 5 | - ".github/**/*.yaml" 6 | - ".github/**/*.yml" 7 | 8 | jobs: 9 | detect: 10 | permissions: 11 | contents: read 12 | uses: Cysharp/Actions/.github/workflows/prevent-github-change.yaml@main 13 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Shims.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f69d4234282aeb44c988b029e96aaee1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /.github/workflows/stale.yaml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues" 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "0 0 * * *" 7 | 8 | jobs: 9 | stale: 10 | permissions: 11 | contents: read 12 | pull-requests: write 13 | issues: write 14 | uses: Cysharp/Actions/.github/workflows/stale-issue.yaml@main 15 | -------------------------------------------------------------------------------- /.github/workflows/toc.yaml: -------------------------------------------------------------------------------- 1 | name: TOC Generator 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'README.md' 7 | 8 | jobs: 9 | toc: 10 | permissions: 11 | contents: write 12 | uses: Cysharp/Actions/.github/workflows/toc-generator.yaml@main 13 | with: 14 | TOC_TITLE: "## Table of Contents" 15 | secrets: inherit 16 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/EnumUtil.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d12377b4cfb6e604592941b9cdfbcc92 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ZString.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a82083d5baadea245b3adc1ffd14da2c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/Editor/PackageExporter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0104ef67be3b9ca498ff698ad4e0bd71 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ExceptionUtil.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c69ccd87e4d4ef74eaf019d0603195e6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/FormatHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4e46453b986ebf4428a5c23fb3cbb175 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/FormatParser.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a3676d0a8288bd1469a9162fec83cf5a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/BufferEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 02503aa3b1ee88741822361d3f10e8b7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/FloatEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e1bfcfb70d615f24fb88dc092457b6c8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/GuidEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1b4d23acb4f60434ea9257c7cc2a1815 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/MathEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7b74132cfedcf0e428e2b0760181072f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/PreparedFormat.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b2d2a7b702a661244a4045fcf67fe6ca 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ZString.Concat.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3cc4c8c9a298173488ac495332e11009 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ZString.Format.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 46c1d83e619838446ba528f658244b56 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ZString.Prepare.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fca154d819b770049860ac2c8c621141 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ZStringWriter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eb2ec9ac9521172449dbeac815854188 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/FastNumberWriter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dd857f99f11ce484c8a3b600614fd1d3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/BitOperations.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 84f68d164ca4db04082e956ba20ee5b4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/DecimalEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: adc39bbd83ade844e9823e44bb8b5445 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/HexConverter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bc55fbf8adb9a284398481db6426b327 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/Number.DiyFp.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18a3c3c91bd4899498562233c482e696 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/Number.Grisu3.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5447d418e8d20414f941dc0316a0af97 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/PreparedFormatHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 97f2a4c405b87a245ac38c1755f74a3b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ReadOnlyListAdaptor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6bac71655584ae549bb144276ee22eed 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ZString.Utf8Format.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bdd4edf33de6a6c4b9911c8f3515cb8d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/IResettableBufferWriter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c853a6364ab3cd3489eaaab75fbb2f5b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/FormattingHelpers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e18ceaad90d7f5438604312d93b703b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/InternalSpanEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 35ddb60e00efb154aa26c3d822b656eb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/Number.BigInteger.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6ee7ab6f12adee945a329388c6efd7cb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/Number.Dragon4.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c85d12eb4f5572c45baa13de29cee602 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/Number.Formatting.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5424f58089802e74383c0f5c73ef3e33 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/Number.Parsing.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b6559ed9c353778499e24e59333cc89f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/NumberFormatInfoEx.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0550e632456d8424e8b871651efa0bf2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/ValueStringBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4c5602223bfb1324ba376e5508ae9134 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/StringBuilder.AppendJoin.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9e8eda83a35921f4ca67df72e7e5f3e9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf16ValueStringBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a63cdeec02e3c54438967c859226bb32 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf8ValueStringBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ea8889d2a42dc824697d997531ea0c14 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 1 9 | path: Assets/Scenes/SampleScene.unity 10 | guid: 2cda990e2423bbf4892e6590ba056729 11 | m_configObjects: {} 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/Number.NumberBuffer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 87bdf9f8d442e2842b3821eea6b35164 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Unity/TextMeshProExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e8ff697dcb687d47a24aeebcfb46817 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/NestedStringBuilderCreationException.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c2e6121a89e941e4d8388e6842ad3551 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/Number.NumberToFloatingPointBits.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 73257159620332b4aa8656f1ba5a86b3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf8/Utf8ValueStringBuilder.AppendFormat.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5d7ee057fcee1904f9ac7f3bf532a09e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Unity/TextMeshProExtensions.SetStringBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26ef652c2e8c2cc488e0b2e063a179ce 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf16/Utf16ValueStringBuilder.AppendFormat.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c686f65ca8d42c4aa85d157c378f10e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf16/Utf16ValueStringBuilder.CreateFormatter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d81568aff3a79df41881112bb037c194 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf8/Utf8ValueStringBuilder.CreateFormatter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 35e4f4117a41a70438f0ff051e65e239 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf8/Utf8ValueStringBuilder.SpanFormattableAppend.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d3c9ebcd92d8b6842821732af2a75fba 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Utf16/Utf16ValueStringBuilder.SpanFormattableAppend.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0143a9022d2d364409298fa82d0bbc01 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /sandbox/ConsoleAppNet472/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/ZString/Number/NumberFormatInfoEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | 6 | namespace System 7 | { 8 | internal static class NumberFormatInfoEx 9 | { 10 | internal static bool HasInvariantNumberSigns(this NumberFormatInfo info) 11 | { 12 | return info.PositiveSign == "+" && info.NegativeSign == "-"; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/NumberFormatInfoEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | 6 | namespace System 7 | { 8 | internal static class NumberFormatInfoEx 9 | { 10 | internal static bool HasInvariantNumberSigns(this NumberFormatInfo info) 11 | { 12 | return info.PositiveSign == "+" && info.NegativeSign == "-"; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 1024 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_AmbisonicDecoderPlugin: 16 | m_DisableAudio: 0 17 | m_VirtualizeEffects: 1 18 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Unity/TextMeshProExtensions.SetStringBuilder.cs: -------------------------------------------------------------------------------- 1 | #if ZSTRING_TEXTMESHPRO_SUPPORT 2 | using System; 3 | using TMPro; 4 | 5 | namespace Cysharp.Text 6 | { 7 | public static partial class TextMeshProExtensions 8 | { 9 | public static void SetText(this TMP_Text text, Utf16ValueStringBuilder stringBuilder) 10 | { 11 | var array = stringBuilder.AsArraySegment(); 12 | text.SetCharArray(array.Array, array.Offset, array.Count); 13 | } 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /src/ZString.Unity/UserSettings/EditorUserSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!162 &1 4 | EditorUserSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 4 7 | m_ConfigSettings: 8 | vcSharedLogLevel: 9 | value: 0d5e400f0650 10 | flags: 0 11 | m_VCAutomaticAdd: 1 12 | m_VCDebugCom: 0 13 | m_VCDebugCmd: 0 14 | m_VCDebugOut: 0 15 | m_SemanticMergeMode: 2 16 | m_VCShowFailedCheckout: 1 17 | m_VCAllowAsyncUpdate: 0 18 | m_AssetPipelineMode2: 1 19 | m_CacheServerMode: 0 20 | m_CacheServers: [] 21 | -------------------------------------------------------------------------------- /sandbox/PerfBenchmark/PerfBenchmark.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 8.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.cysharp.zstring", 3 | "displayName": "ZString", 4 | "version": "2.6.0", 5 | "unity": "2018.4", 6 | "description": "Zero Allocation StringBuilder for .NET Core and Unity.", 7 | "keywords": [ 8 | "String", 9 | "Performance" 10 | ], 11 | "license": "MIT", 12 | "category": "Scripting", 13 | "dependencies": {}, 14 | "samples": [ 15 | { 16 | "displayName": "Required Managed DLLs", 17 | "description": "Import Required Managed DLLs", 18 | "path": "Samples~/RequiredManagedDLLs" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /sandbox/ConsoleApp/ConsoleApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net7.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | TargetFramework=netstandard2.1 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 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 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /tests/ZString.Tests/StringBuilderTest.cs: -------------------------------------------------------------------------------- 1 | using Cysharp.Text; 2 | using FluentAssertions; 3 | using System.Text; 4 | using Xunit; 5 | 6 | namespace ZStringTests 7 | { 8 | public class StringBuilderTest 9 | { 10 | [Fact] 11 | public void Utf16DisposeTest() 12 | { 13 | var sb = ZString.CreateStringBuilder(); 14 | sb.Dispose(); 15 | sb.Dispose(); // call more than once 16 | } 17 | 18 | [Fact] 19 | public void Utf8DisposeTest() 20 | { 21 | var sb = ZString.CreateUtf8StringBuilder(); 22 | sb.Dispose(); 23 | sb.Dispose(); // call more than once 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sandbox/ConsoleAppNet472/Program.cs: -------------------------------------------------------------------------------- 1 | using Cysharp.Text; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace ConsoleAppNet472 9 | { 10 | class Program 11 | { 12 | static void Main(string[] args) 13 | { 14 | var x = ZString.CreateStringBuilder(); 15 | 16 | var sb = new StringBuilder(); 17 | 18 | 19 | 20 | 21 | x.AppendFormat("hoge{0:.##}, tako{1:000}", 123.456, 9); 22 | Console.WriteLine(x.ToString()); 23 | 24 | var utf7 = ZString.CreateUtf8StringBuilder(); 25 | 26 | 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ZString/NestedStringBuilderCreationException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Cysharp.Text 4 | { 5 | // Currently, this class is internals. 6 | internal class NestedStringBuilderCreationException : InvalidOperationException 7 | { 8 | internal protected NestedStringBuilderCreationException(string typeName, string extraMessage = "") 9 | : base($"A nested call with `notNested: true`, or Either You forgot to call {typeName}.Dispose() of in the past.{extraMessage}") 10 | { 11 | } 12 | 13 | internal protected NestedStringBuilderCreationException(string message, Exception innerException) : base(message, innerException) 14 | { 15 | } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | # ref: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot 2 | version: 2 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" # Check for updates to GitHub Actions every week 8 | cooldown: 9 | default-days: 14 # Wait 14 days before creating another PR for the same dependency. This will prevent vulnerability on the package impact. 10 | ignore: 11 | # I just want update action when major/minor version is updated. patch updates are too noisy. 12 | - dependency-name: "*" 13 | update-types: 14 | - version-update:semver-patch 15 | -------------------------------------------------------------------------------- /src/ZString/Number/BufferEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace System 6 | { 7 | internal static class BufferEx 8 | { 9 | internal static unsafe void ZeroMemory(byte* dest, uint len) 10 | { 11 | if (len == 0) return; 12 | 13 | for (int i = 0; i < len; i++) 14 | { 15 | dest[i] = 0; 16 | } 17 | } 18 | 19 | internal static unsafe void Memcpy(byte* dest, byte* src, int len) 20 | { 21 | if (len == 0) return; 22 | for (int i = 0; i < len; i++) 23 | { 24 | dest[i] = src[i]; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/NestedStringBuilderCreationException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Cysharp.Text 4 | { 5 | // Currently, this class is internals. 6 | internal class NestedStringBuilderCreationException : InvalidOperationException 7 | { 8 | internal protected NestedStringBuilderCreationException(string typeName, string extraMessage = "") 9 | : base($"A nested call with `notNested: true`, or Either You forgot to call {typeName}.Dispose() of in the past.{extraMessage}") 10 | { 11 | } 12 | 13 | internal protected NestedStringBuilderCreationException(string message, Exception innerException) : base(message, innerException) 14 | { 15 | } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 2 10 | m_DefaultBehaviorMode: 1 11 | m_SpritePackerMode: 4 12 | m_SpritePackerPaddingPower: 1 13 | m_EtcTextureCompressorBehavior: 1 14 | m_EtcTextureFastCompressor: 1 15 | m_EtcTextureNormalCompressor: 2 16 | m_EtcTextureBestCompressor: 4 17 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd 18 | m_ProjectGenerationRootNamespace: 19 | m_UserGeneratedProjectSuffix: 20 | m_CollabEditorSettings: 21 | inProgressEnabled: 1 22 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ZString.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ZString", 3 | "references": [ 4 | "Unity.TextMeshPro" 5 | ], 6 | "includePlatforms": [], 7 | "excludePlatforms": [], 8 | "allowUnsafeCode": true, 9 | "overrideReferences": false, 10 | "precompiledReferences": [], 11 | "autoReferenced": true, 12 | "defineConstraints": [], 13 | "versionDefines": [ 14 | { 15 | "name": "com.unity.textmeshpro", 16 | "expression": "", 17 | "define": "ZSTRING_TEXTMESHPRO_SUPPORT" 18 | }, 19 | { 20 | "name": "com.unity.ugui", 21 | "expression": "2.0.0", 22 | "define": "ZSTRING_TEXTMESHPRO_SUPPORT" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/BufferEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace System 6 | { 7 | internal static class BufferEx 8 | { 9 | internal static unsafe void ZeroMemory(byte* dest, uint len) 10 | { 11 | if (len == 0) return; 12 | 13 | for (int i = 0; i < len; i++) 14 | { 15 | dest[i] = 0; 16 | } 17 | } 18 | 19 | internal static unsafe void Memcpy(byte* dest, byte* src, int len) 20 | { 21 | if (len == 0) return; 22 | for (int i = 0; i < len; i++) 23 | { 24 | dest[i] = src[i]; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ZString/ExceptionUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Cysharp.Text 6 | { 7 | internal static class ExceptionUtil 8 | { 9 | internal static void ThrowArgumentException(string paramName) 10 | { 11 | throw new ArgumentException("Can't format argument.", paramName); 12 | } 13 | 14 | internal static void ThrowFormatException() 15 | { 16 | throw new FormatException("Index (zero based) must be greater than or equal to zero and less than the size of the argument list."); 17 | } 18 | 19 | internal static void ThrowFormatError() 20 | { 21 | throw new FormatException("Input string was not in a correct format."); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ExceptionUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Cysharp.Text 6 | { 7 | internal static class ExceptionUtil 8 | { 9 | internal static void ThrowArgumentException(string paramName) 10 | { 11 | throw new ArgumentException("Can't format argument.", paramName); 12 | } 13 | 14 | internal static void ThrowFormatException() 15 | { 16 | throw new FormatException("Index (zero based) must be greater than or equal to zero and less than the size of the argument list."); 17 | } 18 | 19 | internal static void ThrowFormatError() 20 | { 21 | throw new FormatException("Input string was not in a correct format."); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Plugins/System.Runtime.CompilerServices.Unsafe.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: faa5df203ffb85e4e81c6230b4bf1025 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 0 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 1 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | - first: 26 | Windows Store Apps: WindowsStoreApps 27 | second: 28 | enabled: 0 29 | settings: 30 | CPU: AnyCPU 31 | userData: 32 | assetBundleName: 33 | assetBundleVariant: 34 | -------------------------------------------------------------------------------- /sandbox/BenchmarkVsReleasedVersion/BenchmarkVsReleasedVersion.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | NewZString 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/ZString/ReadOnlyListAdaptor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Cysharp.Text 5 | { 6 | /// 7 | /// Most IList interface-implementing classes implement the IReadOnlyList interface. 8 | /// This is for the rare class that does not implement the IList interface. 9 | /// 10 | /// 11 | internal readonly struct ReadOnlyListAdaptor : IReadOnlyList 12 | { 13 | readonly IList _list; 14 | 15 | public ReadOnlyListAdaptor(IList list) => _list = list; 16 | 17 | public T this[int index] => _list[index]; 18 | 19 | public int Count => _list.Count; 20 | 21 | public IEnumerator GetEnumerator() => _list.GetEnumerator(); 22 | 23 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/ReadOnlyListAdaptor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Cysharp.Text 5 | { 6 | /// 7 | /// Most IList interface-implementing classes implement the IReadOnlyList interface. 8 | /// This is for the rare class that does not implement the IList interface. 9 | /// 10 | /// 11 | internal readonly struct ReadOnlyListAdaptor : IReadOnlyList 12 | { 13 | readonly IList _list; 14 | 15 | public ReadOnlyListAdaptor(IList list) => _list = list; 16 | 17 | public T this[int index] => _list[index]; 18 | 19 | public int Count => _list.Count; 20 | 21 | public IEnumerator GetEnumerator() => _list.GetEnumerator(); 22 | 23 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sandbox/BenchmarkVsReleasedVersion/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using BenchmarkDotNet.Columns; 3 | using BenchmarkDotNet.Configs; 4 | using BenchmarkDotNet.Diagnosers; 5 | using BenchmarkDotNet.Environments; 6 | using BenchmarkDotNet.Exporters; 7 | using BenchmarkDotNet.Jobs; 8 | using BenchmarkDotNet.Running; 9 | using Cysharp.Text; 10 | using System; 11 | using System.Buffers; 12 | using System.Reflection; 13 | using System.Text; 14 | 15 | namespace BenchmarkVsReleasedVersion 16 | { 17 | internal class BenchmarkConfig : ManualConfig 18 | { 19 | public BenchmarkConfig() 20 | { 21 | AddDiagnoser(MemoryDiagnoser.Default); 22 | AddJob(Job.ShortRun.WithWarmupCount(1).WithIterationCount(1)); 23 | } 24 | } 25 | 26 | public class Program 27 | { 28 | static void Main(string[] args) 29 | { 30 | BenchmarkSwitcher.FromAssembly(Assembly.GetEntryAssembly()).Run(args); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 1 7 | m_Enabled: 0 8 | m_TestMode: 0 9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events 10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events 11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com 12 | m_TestInitMode: 0 13 | CrashReportingSettings: 14 | m_EventUrl: https://perf-events.cloud.unity3d.com 15 | m_Enabled: 0 16 | m_LogBufferSize: 10 17 | m_CaptureEditorExceptions: 1 18 | UnityPurchasingSettings: 19 | m_Enabled: 0 20 | m_TestMode: 0 21 | UnityAnalyticsSettings: 22 | m_Enabled: 0 23 | m_TestMode: 0 24 | m_InitializeOnStartup: 1 25 | UnityAdsSettings: 26 | m_Enabled: 0 27 | m_InitializeOnStartup: 1 28 | m_TestMode: 0 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | m_GameIds: {} 32 | m_GameId: 33 | PerformanceReportingSettings: 34 | m_Enabled: 0 35 | -------------------------------------------------------------------------------- /sandbox/ConsoleAppNet472/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/PackageManagerSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &1 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 61 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} 13 | m_Name: 14 | m_EditorClassIdentifier: 15 | m_EnablePreReleasePackages: 0 16 | m_EnablePackageDependencies: 0 17 | m_AdvancedSettingsExpanded: 1 18 | m_ScopedRegistriesSettingsExpanded: 1 19 | m_SeeAllPackageVersions: 0 20 | oneTimeWarningShown: 0 21 | m_Registries: 22 | - m_Id: main 23 | m_Name: 24 | m_Url: https://packages.unity.com 25 | m_Scopes: [] 26 | m_IsDefault: 1 27 | m_Capabilities: 7 28 | m_UserSelectedRegistryName: 29 | m_UserAddingNewScopedRegistry: 0 30 | m_RegistryInfoDraft: 31 | m_Modified: 0 32 | m_ErrorMessage: 33 | m_UserModificationsInstanceId: -832 34 | m_OriginalInstanceId: -834 35 | m_LoadAssets: 0 36 | -------------------------------------------------------------------------------- /tests/ZString.Tests/ZStringWriterTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cysharp.Text; 3 | using Xunit; 4 | 5 | namespace ZStringTests 6 | { 7 | public class ZStringWriterTest 8 | { 9 | [Fact] 10 | public void DoubleDisposeTest() 11 | { 12 | var sb = new ZStringWriter(); 13 | sb.Dispose(); 14 | sb.Dispose(); // call more than once 15 | } 16 | 17 | [Fact] 18 | public void BasicWrites() 19 | { 20 | using (var writer = new ZStringWriter()) 21 | { 22 | writer.Write("text1".AsSpan()); 23 | writer.Write("text2"); 24 | writer.Write('c'); 25 | writer.Write(true); 26 | writer.Write(123); 27 | writer.Write(456f); 28 | writer.Write(789d); 29 | writer.Write("end".AsMemory()); 30 | writer.WriteLine(); 31 | 32 | var expected = "text1text2cTrue123456789end" + Environment.NewLine; 33 | Assert.Equal(expected, writer.ToString()); 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Cysharp, Inc. 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 | -------------------------------------------------------------------------------- /sandbox/PerfBenchmark/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using BenchmarkDotNet.Configs; 3 | using BenchmarkDotNet.Diagnosers; 4 | using BenchmarkDotNet.Environments; 5 | using BenchmarkDotNet.Exporters; 6 | using BenchmarkDotNet.Jobs; 7 | using BenchmarkDotNet.Running; 8 | using Cysharp.Text; 9 | using System; 10 | using System.Buffers; 11 | using System.Reflection; 12 | using System.Text; 13 | 14 | namespace PerfBenchmark 15 | { 16 | internal class BenchmarkConfig : ManualConfig 17 | { 18 | public BenchmarkConfig() 19 | { 20 | AddDiagnoser(MemoryDiagnoser.Default); 21 | AddJob(Job.ShortRun.WithWarmupCount(1).WithIterationCount(1).WithRuntime(CoreRuntime.Core50)); 22 | 23 | // Add Targetframeworks net47 to csproj(removed for CI) 24 | //AddJob(Job.ShortRun.WithWarmupCount(1).WithIterationCount(1).WithRuntime(ClrRuntime.Net47)); 25 | } 26 | } 27 | 28 | public class Program 29 | { 30 | static void Main(string[] args) 31 | { 32 | BenchmarkSwitcher.FromAssembly(Assembly.GetEntryAssembly()).Run(args); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/ZString.Tests/Utf8StringBuilderTest.cs: -------------------------------------------------------------------------------- 1 | using Cysharp.Text; 2 | using FluentAssertions; 3 | using System; 4 | using System.Buffers; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using Xunit; 8 | 9 | namespace ZStringTests 10 | { 11 | public class Utf8StringBuilderTest 12 | { 13 | 14 | [Fact] 15 | public void AppendCharRepeat() 16 | { 17 | using (var zsb = ZString.CreateUtf8StringBuilder(notNested: true)) 18 | { 19 | var text = "foo"; 20 | zsb.Append(text); 21 | var bcl = new StringBuilder(text); 22 | 23 | // ASCII 24 | zsb.Append('\x7F', 10); 25 | bcl.Append('\x7F', 10); 26 | zsb.ToString().Should().Be(bcl.ToString()); 27 | 28 | // Non-ASCII 29 | zsb.Append('\x80', 10); 30 | bcl.Append('\x80', 10); 31 | zsb.ToString().Should().Be(bcl.ToString()); 32 | 33 | zsb.Append('\u9bd6', 10); 34 | bcl.Append('\u9bd6', 10); 35 | zsb.ToString().Should().Be(bcl.ToString()); 36 | } 37 | 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/ZString.Tests/ZString.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | ZStringTests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | all 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | 20 | 21 | 22 | 23 | 24 | TargetFramework=netstandard2.1 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_ClothInterCollisionDistance: 0 18 | m_ClothInterCollisionStiffness: 0 19 | m_ContactsGeneration: 1 20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21 | m_AutoSimulation: 1 22 | m_AutoSyncTransforms: 0 23 | m_ReuseCollisionCallbacks: 1 24 | m_ClothInterCollisionSettingsToggle: 0 25 | m_ContactPairsMode: 0 26 | m_BroadphaseType: 0 27 | m_WorldBounds: 28 | m_Center: {x: 0, y: 0, z: 0} 29 | m_Extent: {x: 250, y: 250, z: 250} 30 | m_WorldSubdivisions: 8 31 | -------------------------------------------------------------------------------- /src/ZString/ZString.Prepare.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="T4Common.t4" once="true" #> 8 | using System.Runtime.CompilerServices; 9 | 10 | namespace Cysharp.Text 11 | { 12 | public static partial class ZString 13 | { 14 | <# for(var i = 1; i <= TypeParamMax; i++) { #> 15 | /// Prepare string format to avoid parse template in each operation. 16 | public static Utf16PreparedFormat<<#= CreateTypeArgument(i) #>> PrepareUtf16<<#= CreateTypeArgument(i) #>>(string format) 17 | { 18 | return new Utf16PreparedFormat<<#= CreateTypeArgument(i) #>>(format); 19 | } 20 | 21 | /// Prepare string format to avoid parse template in each operation. 22 | public static Utf8PreparedFormat<<#= CreateTypeArgument(i) #>> PrepareUtf8<<#= CreateTypeArgument(i) #>>(string format) 23 | { 24 | return new Utf8PreparedFormat<<#= CreateTypeArgument(i) #>>(format); 25 | } 26 | 27 | <# } #> 28 | } 29 | } -------------------------------------------------------------------------------- /sandbox/ConsoleAppNet472/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 6 | // 制御されます。アセンブリに関連付けられている情報を変更するには、 7 | // これらの属性値を変更します。 8 | [assembly: AssemblyTitle("ConsoleAppNet472")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ConsoleAppNet472")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから 18 | // 参照できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 19 | // その型の ComVisible 属性を true に設定します。 20 | [assembly: ComVisible(false)] 21 | 22 | // このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります 23 | [assembly: Guid("be8a17aa-504a-410d-b86d-92431b0f5594")] 24 | 25 | // アセンブリのバージョン情報は次の 4 つの値で構成されています: 26 | // 27 | // メジャー バージョン 28 | // マイナー バージョン 29 | // ビルド番号 30 | // リビジョン 31 | // 32 | // すべての値を指定するか、次を使用してビルド番号とリビジョン番号を既定に設定できます 33 | // 既定値にすることができます: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_style = space 8 | indent_size = 2 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | # Visual Studio Spell checker configs (https://learn.microsoft.com/en-us/visualstudio/ide/text-spell-checker?view=vs-2022#how-to-customize-the-spell-checker) 13 | spelling_exclusion_path = ./exclusion.dic 14 | 15 | [*.cs] 16 | indent_size = 4 17 | charset = utf-8-bom 18 | end_of_line = unset 19 | 20 | # Solution files 21 | [*.{sln,slnx}] 22 | end_of_line = unset 23 | 24 | # MSBuild project files 25 | [*.{csproj,props,targets}] 26 | end_of_line = unset 27 | 28 | # Xml config files 29 | [*.{ruleset,config,nuspec,resx,runsettings,DotSettings}] 30 | end_of_line = unset 31 | 32 | [*{_AssemblyInfo.cs,.notsupported.cs}] 33 | generated_code = true 34 | 35 | # C# code style settings 36 | [*.{cs}] 37 | dotnet_diagnostic.IDE0044.severity = none # IDE0044: Make field readonly 38 | 39 | # https://stackoverflow.com/questions/79195382/how-to-disable-fading-unused-methods-in-visual-studio-2022-17-12-0 40 | dotnet_diagnostic.IDE0051.severity = none # IDE0051: Remove unused private member 41 | dotnet_diagnostic.IDE0130.severity = none # IDE0130: Namespace does not match folder structure 42 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | $(MSBuildThisFileDirectory)opensource.snk 6 | 7 | 8 | false 9 | $(Version) 10 | Cysharp 11 | Cysharp 12 | © Cysharp, Inc. 13 | string; 14 | https://github.com/Cysharp/ZString 15 | README.md 16 | $(PackageProjectUrl) 17 | git 18 | MIT 19 | Icon.png 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /sandbox/PerfBenchmark/Benchmarks/VSStringFormatter.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Cysharp.Text; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace PerfBenchmark.Benchmarks 8 | { 9 | [Config(typeof(BenchmarkConfig))] 10 | public class VSStringFormatter 11 | { 12 | [Benchmark] 13 | public string ZStringConcatInt() 14 | { 15 | return ZString.Concat((int)1); 16 | } 17 | 18 | [Benchmark] 19 | public string ZStringBuilderInt() 20 | { 21 | using var builder = Cysharp.Text.ZString.CreateStringBuilder(); 22 | builder.Append((int)1); 23 | return builder.ToString(); 24 | } 25 | 26 | [Benchmark] 27 | public string StringFormatterInt() 28 | { 29 | var builder = new System.Text.Formatting.StringBuffer(); 30 | builder.Append((int)1, System.Text.Formatting.StringView.Empty); 31 | return builder.ToString(); 32 | } 33 | 34 | [Benchmark] 35 | public string BclStringBuilderInt() 36 | { 37 | var builder = new StringBuilder(); 38 | builder.Append((int)1); 39 | return builder.ToString(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/ZString.NetCore2Tests/ZString.NetCore2Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | ZStringTests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | all 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | 17 | 18 | all 19 | runtime; build; native; contentfiles; analyzers; buildtransitive 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/MemorySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!387306366 &1 4 | MemorySettings: 5 | m_ObjectHideFlags: 0 6 | m_EditorMemorySettings: 7 | m_MainAllocatorBlockSize: -1 8 | m_ThreadAllocatorBlockSize: -1 9 | m_MainGfxBlockSize: -1 10 | m_ThreadGfxBlockSize: -1 11 | m_CacheBlockSize: -1 12 | m_TypetreeBlockSize: -1 13 | m_ProfilerBlockSize: -1 14 | m_ProfilerEditorBlockSize: -1 15 | m_BucketAllocatorGranularity: -1 16 | m_BucketAllocatorBucketsCount: -1 17 | m_BucketAllocatorBlockSize: -1 18 | m_BucketAllocatorBlockCount: -1 19 | m_ProfilerBucketAllocatorGranularity: -1 20 | m_ProfilerBucketAllocatorBucketsCount: -1 21 | m_ProfilerBucketAllocatorBlockSize: -1 22 | m_ProfilerBucketAllocatorBlockCount: -1 23 | m_TempAllocatorSizeMain: -1 24 | m_JobTempAllocatorBlockSize: -1 25 | m_BackgroundJobTempAllocatorBlockSize: -1 26 | m_JobTempAllocatorReducedBlockSize: -1 27 | m_TempAllocatorSizeGIBakingWorker: -1 28 | m_TempAllocatorSizeNavMeshWorker: -1 29 | m_TempAllocatorSizeAudioWorker: -1 30 | m_TempAllocatorSizeCloudWorker: -1 31 | m_TempAllocatorSizeGfx: -1 32 | m_TempAllocatorSizeJobWorker: -1 33 | m_TempAllocatorSizeBackgroundWorker: -1 34 | m_TempAllocatorSizePreloadManager: -1 35 | m_PlatformMemorySettings: {} 36 | -------------------------------------------------------------------------------- /src/ZString/Number/FloatEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using System.Text; 5 | 6 | namespace System 7 | { 8 | internal static class FloatEx 9 | { 10 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 11 | public static unsafe bool IsFinite(double d) 12 | { 13 | long bits = BitConverter.DoubleToInt64Bits(d); 14 | return (bits & 0x7FFFFFFFFFFFFFFF) < 0x7FF0000000000000; 15 | } 16 | 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | public static unsafe bool IsNegative(double d) 19 | { 20 | return BitConverter.DoubleToInt64Bits(d) < 0; 21 | } 22 | 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public static bool IsFinite(float f) 25 | { 26 | int bits = SingleToInt32Bits(f); 27 | return (bits & 0x7FFFFFFF) < 0x7F800000; 28 | } 29 | 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | public static unsafe bool IsNegative(float f) 32 | { 33 | return SingleToInt32Bits(f) < 0; 34 | } 35 | 36 | 37 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 38 | public static unsafe int SingleToInt32Bits(float value) 39 | { 40 | return *((int*)&value); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/ZString/T4Common.t4: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | <# 6 | const int TypeParamMax = 16; 7 | 8 | string[] utfTypes = new [] { "Utf16", "Utf8" }; 9 | 10 | static string CreateTypeArgument(int i) 11 | { 12 | return string.Join(", ", Enumerable.Range(0, i).Select(x => "T" + (x + 1))); 13 | } 14 | 15 | static string CreateParameters(int i) 16 | { 17 | return string.Join(", ", Enumerable.Range(0, i).Select(x => "T" + (x + 1) + " arg" + (x + 1))); 18 | } 19 | 20 | static string CreateParameterNames(int i) 21 | { 22 | return string.Join(", ", Enumerable.Range(0, i).Select(x => "arg" + (x + 1))); 23 | } 24 | 25 | Type[] spanFormattables = new Type[] 26 | { 27 | typeof(Byte), 28 | typeof(DateTime), 29 | typeof(DateTimeOffset), 30 | typeof(Decimal), 31 | typeof(Double), 32 | typeof(Int16), 33 | typeof(Int32), 34 | typeof(Int64), 35 | typeof(SByte), 36 | typeof(Single), 37 | typeof(TimeSpan), 38 | typeof(UInt16), 39 | typeof(UInt32), 40 | typeof(UInt64), 41 | typeof(Guid), 42 | // typeof(Version), 43 | }; 44 | 45 | var utf8spanFormattables = spanFormattables.Append(typeof(bool)); 46 | #> -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/FloatEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using System.Text; 5 | 6 | namespace System 7 | { 8 | internal static class FloatEx 9 | { 10 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 11 | public static unsafe bool IsFinite(double d) 12 | { 13 | long bits = BitConverter.DoubleToInt64Bits(d); 14 | return (bits & 0x7FFFFFFFFFFFFFFF) < 0x7FF0000000000000; 15 | } 16 | 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | public static unsafe bool IsNegative(double d) 19 | { 20 | return BitConverter.DoubleToInt64Bits(d) < 0; 21 | } 22 | 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public static bool IsFinite(float f) 25 | { 26 | int bits = SingleToInt32Bits(f); 27 | return (bits & 0x7FFFFFFF) < 0x7F800000; 28 | } 29 | 30 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 | public static unsafe bool IsNegative(float f) 32 | { 33 | return SingleToInt32Bits(f) < 0; 34 | } 35 | 36 | 37 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 38 | public static unsafe int SingleToInt32Bits(float value) 39 | { 40 | return *((int*)&value); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /sandbox/PerfBenchmark/Benchmarks/FormatBenchmark.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Cysharp.Text; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Text.Formatting; 7 | 8 | namespace PerfBenchmark.Benchmarks 9 | { 10 | [Config(typeof(BenchmarkConfig))] 11 | public class FormatBenchmark 12 | { 13 | int x; 14 | int y; 15 | string format; 16 | StringBuilder stringBuilder; 17 | Utf16PreparedFormat preparedFormat; 18 | 19 | public FormatBenchmark() 20 | { 21 | x = int.Parse("100"); 22 | y = int.Parse("200"); 23 | format = "x:{0}, y:{1}"; 24 | stringBuilder = new StringBuilder(); 25 | preparedFormat = new Utf16PreparedFormat(format); 26 | } 27 | 28 | [Benchmark(Baseline = true)] 29 | public string StringFormat() 30 | { 31 | return string.Format(format, x, y); 32 | } 33 | 34 | [Benchmark] 35 | public string ZStringFormat() 36 | { 37 | return ZString.Format(format, x, y); 38 | } 39 | 40 | [Benchmark] 41 | public string ZStringPreparedFormat() 42 | { 43 | return preparedFormat.Format(x, y); 44 | } 45 | 46 | [Benchmark] 47 | public string StringFormatterFormat() 48 | { 49 | return StringBuffer.Format(format, x, y); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/ZString/_InternalVisibleTo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("ConsoleApp, PublicKey=00240000048000009400000006020000002400005253413100040000010001000144ec28f1e9ef7b17dacc47425a7a153aea0a7baa590743a2d1a86f4b3e10a8a12712c6e647966bfd8bd6e830048b23bd42bbc56f179585c15b8c19cf86c0eed1b73c993dd7a93a30051dd50fdda0e4d6b65e6874e30f1c37cf8bcbc7fe02c7f2e6a0a3327c0ccc1631bf645f40732521fa0b41a30c178d08f7dd779d42a1ee")] 4 | [assembly: InternalsVisibleTo("ConsoleAppNet472, PublicKey=00240000048000009400000006020000002400005253413100040000010001000144ec28f1e9ef7b17dacc47425a7a153aea0a7baa590743a2d1a86f4b3e10a8a12712c6e647966bfd8bd6e830048b23bd42bbc56f179585c15b8c19cf86c0eed1b73c993dd7a93a30051dd50fdda0e4d6b65e6874e30f1c37cf8bcbc7fe02c7f2e6a0a3327c0ccc1631bf645f40732521fa0b41a30c178d08f7dd779d42a1ee")] 5 | [assembly: InternalsVisibleTo("ZString.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001000144ec28f1e9ef7b17dacc47425a7a153aea0a7baa590743a2d1a86f4b3e10a8a12712c6e647966bfd8bd6e830048b23bd42bbc56f179585c15b8c19cf86c0eed1b73c993dd7a93a30051dd50fdda0e4d6b65e6874e30f1c37cf8bcbc7fe02c7f2e6a0a3327c0ccc1631bf645f40732521fa0b41a30c178d08f7dd779d42a1ee")] 6 | [assembly: InternalsVisibleTo("ZString.NetCore2Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001000144ec28f1e9ef7b17dacc47425a7a153aea0a7baa590743a2d1a86f4b3e10a8a12712c6e647966bfd8bd6e830048b23bd42bbc56f179585c15b8c19cf86c0eed1b73c993dd7a93a30051dd50fdda0e4d6b65e6874e30f1c37cf8bcbc7fe02c7f2e6a0a3327c0ccc1631bf645f40732521fa0b41a30c178d08f7dd779d42a1ee")] -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scenes/Test.cs: -------------------------------------------------------------------------------- 1 | 2 | using Cysharp.Text; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using UnityEngine.Profiling; 6 | using UnityEngine.UI; 7 | 8 | public class Test : MonoBehaviour 9 | { 10 | public Button buttonA; 11 | 12 | private void Start() 13 | { 14 | buttonA.onClick.AddListener(() => 15 | { 16 | int COUNT = 1000; 17 | List strings = new List(); 18 | for (int i = 0; i < 100; i++) 19 | strings.Add("123456789"); 20 | 21 | 22 | Profiler.BeginSample("Append/ZString.StringBuilder()"); 23 | for (int i = 0; i < COUNT; i++) 24 | { 25 | using (var sb = ZString.CreateStringBuilder(true)) 26 | { 27 | for (int j = 0; j < strings.Count; j++) 28 | { 29 | sb.Append(strings[j]); 30 | } 31 | 32 | sb.ToString(); 33 | } 34 | } 35 | Profiler.EndSample(); 36 | 37 | 38 | Profiler.BeginSample("Append/SharedStringBuilderScope()"); 39 | { 40 | for (int i = 0; i < COUNT; i++) 41 | { 42 | System.Text.StringBuilder sb = new System.Text.StringBuilder(); 43 | for (int j = 0; j < strings.Count; j++) 44 | { 45 | sb.Append(strings[j]); 46 | } 47 | 48 | sb.ToString(); 49 | // sb.Clear(); 50 | } 51 | } 52 | Profiler.EndSample(); 53 | }); 54 | } 55 | } -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -887442657 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | debug: 89 | m_Flags: 0 90 | m_SettingNames: 91 | - Humanoid 92 | -------------------------------------------------------------------------------- /tests/ZString.Tests/RemoveTest.cs: -------------------------------------------------------------------------------- 1 | using Cysharp.Text; 2 | using FluentAssertions; 3 | using System.Text; 4 | using Xunit; 5 | 6 | namespace ZStringTests 7 | { 8 | public class RemoveTest 9 | { 10 | [Fact] 11 | public void RemovePart() 12 | { 13 | string str = "The quick brown fox jumps over the lazy dog."; 14 | using (var zsb = ZString.CreateStringBuilder()) 15 | { 16 | zsb.Append(str); 17 | var bcl = new StringBuilder(str); 18 | 19 | // Remove "brown " 20 | zsb.Remove(10, 6); 21 | bcl.Remove(10, 6); 22 | 23 | zsb.ToString().Should().Be(bcl.ToString()); 24 | } 25 | } 26 | 27 | [Fact] 28 | public void RemoveAll() 29 | { 30 | string str = "The quick brown fox jumps over the lazy dog."; 31 | using (var zsb = ZString.CreateStringBuilder()) 32 | { 33 | zsb.Append(str); 34 | var bcl = new StringBuilder(str); 35 | 36 | zsb.Remove(0, str.Length); 37 | bcl.Remove(0, str.Length); 38 | 39 | zsb.ToString().Should().Be(bcl.ToString()); 40 | } 41 | } 42 | 43 | [Fact] 44 | public void RemoveTail() 45 | { 46 | string str = "foo,bar,baz"; 47 | using (var zsb = ZString.CreateStringBuilder()) 48 | { 49 | zsb.Append(str); 50 | var bcl = new StringBuilder(str); 51 | 52 | zsb.Remove(7, 4); 53 | bcl.Remove(7, 4); 54 | 55 | zsb.ToString().Should().Be(bcl.ToString()); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/ZString/Utf8/Utf8ValueStringBuilder.CreateFormatter.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="../T4Common.t4" once="true" #> 8 | using System; 9 | using System.Buffers; 10 | using System.Buffers.Text; 11 | 12 | namespace Cysharp.Text 13 | { 14 | public partial struct Utf8ValueStringBuilder 15 | { 16 | static object CreateFormatter(Type type) 17 | { 18 | <# foreach(var t in utf8spanFormattables) { #> 19 | if (type == typeof(<#= t.FullName #>)) 20 | { 21 | return new TryFormat<<#= t.FullName #>>((<#= t.FullName #> x, Span dest, out int written, StandardFormat format) => Utf8Formatter.TryFormat(x, dest, out written, format)); 22 | } 23 | <# } #> 24 | <# foreach(var t in utf8spanFormattables) { #> 25 | if (type == typeof(<#= t.FullName #>?)) 26 | { 27 | return CreateNullableFormatter<<#= t.FullName #>>(); 28 | } 29 | <# } #> 30 | <# foreach(var t in new [] {typeof(IntPtr), typeof(UIntPtr)} ) { var u = t == typeof(UIntPtr); #> 31 | if (type == typeof(<#= t.FullName #>)) 32 | { 33 | return new TryFormat<<#= t.FullName #>>((<#= t.FullName #> x, Span dest, out int written, StandardFormat format) => <#= t #>.Size == 4 34 | ? Utf8Formatter.TryFormat(x.To<#= u ? "U" : "" #>Int32(), dest, out written, format) 35 | : Utf8Formatter.TryFormat(x.To<#= u ? "U" : "" #>Int64(), dest, out written, format)); 36 | } 37 | <# } #> 38 | 39 | return null; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/ZString/ZString.Concat.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="T4Common.t4" once="true" #> 8 | using System.Runtime.CompilerServices; 9 | 10 | namespace Cysharp.Text 11 | { 12 | public static partial class ZString 13 | { 14 | <# for(var i = 1; i <= TypeParamMax; i++) { #> 15 | /// Concatenates the string representation of some specified objects. 16 | public static string Concat<<#= CreateTypeArgument(i) #>>(<#= CreateParameters(i) #>) 17 | { 18 | <# if(i == 1) { #> 19 | if (typeof(T1) == typeof(string)) 20 | { 21 | return (arg1 != null) ? Unsafe.As(arg1) : string.Empty; 22 | } 23 | 24 | <# } #> 25 | var sb = new Utf16ValueStringBuilder(true); 26 | try 27 | { 28 | <# for(var j = 0; j < i; j++) { #> 29 | if (typeof(T<#= j + 1 #>) == typeof(string)) 30 | { 31 | if(arg<#= j + 1 #> != null) 32 | { 33 | sb.Append(Unsafe.As, string>(ref arg<#= j + 1 #>)); 34 | } 35 | } 36 | else if (typeof(T<#= j + 1 #>) == typeof(int)) 37 | { 38 | sb.Append(Unsafe.As, int>(ref arg<#= j + 1 #>)); 39 | } 40 | else 41 | { 42 | sb.Append(arg<#= j + 1 #>); 43 | } 44 | 45 | <# } #> 46 | return sb.ToString(); 47 | } 48 | finally 49 | { 50 | sb.Dispose(); 51 | } 52 | } 53 | 54 | <# } #> 55 | } 56 | } -------------------------------------------------------------------------------- /src/ZString/ZString.Format.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="T4Common.t4" once="true" #> 8 | using System.Runtime.CompilerServices; 9 | using System; 10 | 11 | namespace Cysharp.Text 12 | { 13 | public static partial class ZString 14 | { 15 | <# for(var i = 1; i <= TypeParamMax; i++) { #> 16 | /// Replaces one or more format items in a string with the string representation of some specified objects. 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | public static string Format<<#= CreateTypeArgument(i) #>>(string format, <#= CreateParameters(i) #>) 19 | { 20 | var sb = new Utf16ValueStringBuilder(true); 21 | try 22 | { 23 | sb.AppendFormat(format, <#= CreateParameterNames(i) #>); 24 | return sb.ToString(); 25 | } 26 | finally 27 | { 28 | sb.Dispose(); 29 | } 30 | } 31 | 32 | /// Replaces one or more format items in a string with the string representation of some specified objects. 33 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 34 | public static string Format<<#= CreateTypeArgument(i) #>>(ReadOnlySpan format, <#= CreateParameters(i) #>) 35 | { 36 | var sb = new Utf16ValueStringBuilder(true); 37 | try 38 | { 39 | sb.AppendFormat(format, <#= CreateParameterNames(i) #>); 40 | return sb.ToString(); 41 | } 42 | finally 43 | { 44 | sb.Dispose(); 45 | } 46 | } 47 | <# } #> 48 | } 49 | } -------------------------------------------------------------------------------- /src/ZString/Unity/TextMeshProExtensions.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <# 8 | static string CreateTypeArgument(int i) 9 | { 10 | return string.Join(", ", Enumerable.Range(0, i).Select(x => "T" + x)); 11 | } 12 | 13 | static string CreateParameters(int i) 14 | { 15 | return string.Join(", ", Enumerable.Range(0, i).Select(x => "T" + x + " arg" + x)); 16 | } 17 | 18 | 19 | static string CreateParameterNames(int i) 20 | { 21 | return string.Join(", ", Enumerable.Range(0, i).Select(x => "arg" + x)); 22 | } 23 | #> 24 | #if ZSTRING_TEXTMESHPRO_SUPPORT 25 | using System; 26 | using TMPro; 27 | 28 | namespace Cysharp.Text 29 | { 30 | public static partial class TextMeshProExtensions 31 | { 32 | public static void SetText(this TMP_Text text, T arg0) 33 | { 34 | using ( var sb = new Cysharp.Text.Utf16ValueStringBuilder( true ) ) 35 | { 36 | sb.Append(arg0); 37 | var array = sb.AsArraySegment(); 38 | text.SetCharArray(array.Array, array.Offset, array.Count); 39 | } 40 | } 41 | 42 | <# for(var i = 1; i <= 16; i++) { #> 43 | public static void SetTextFormat<<#= CreateTypeArgument(i) #>>(this TMP_Text text, string format, <#= CreateParameters(i) #>) 44 | { 45 | using (var sb = new Cysharp.Text.Utf16ValueStringBuilder(true)) 46 | { 47 | sb.AppendFormat(format, <#= CreateParameterNames(i) #>); 48 | var array = sb.AsArraySegment(); 49 | text.SetCharArray(array.Array, array.Offset, array.Count); 50 | } 51 | } 52 | 53 | <# } #> 54 | } 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /sandbox/PerfBenchmark/Benchmarks/StringBuilderAppendJoin.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Cysharp.Text; 3 | using System; 4 | using System.Text; 5 | 6 | namespace PerfBenchmark.Benchmarks 7 | { 8 | [Config(typeof(BenchmarkConfig))] 9 | public class StringBuilderAppendJoin 10 | { 11 | double[] dValues; 12 | float[] fValues; 13 | decimal[] mValues; 14 | public StringBuilderAppendJoin() 15 | { 16 | dValues = new[] { 0d, double.MaxValue, double.MinValue }; 17 | fValues = new[] { 0f, float.MaxValue, float.MinValue }; 18 | mValues = new[] { 0m, decimal.MaxValue, decimal.MinValue }; 19 | 20 | #if NETCOREAPP || NETSTANDARD2_1 21 | if (StringBuilder() != ZStringBuilder()) 22 | throw new Exception(); 23 | #endif 24 | } 25 | 26 | 27 | #if NETCOREAPP || NETSTANDARD2_1 28 | [Benchmark(Baseline = true)] 29 | public int StringBuilder() 30 | { 31 | var sb = new StringBuilder(); 32 | sb.Append("double: "); 33 | sb.AppendJoin(", ", dValues); 34 | sb.AppendLine(); 35 | sb.Append("float: "); 36 | sb.AppendJoin(", ", fValues); 37 | sb.AppendLine(); 38 | sb.Append("decimal: "); 39 | sb.AppendJoin(", ", mValues); 40 | sb.AppendLine(); 41 | return sb.Length; 42 | } 43 | #endif 44 | 45 | [Benchmark] 46 | public int ZStringBuilder() 47 | { 48 | using var sb = ZString.CreateStringBuilder(); 49 | sb.Append("double: "); 50 | sb.AppendJoin(", ", dValues); 51 | sb.AppendLine(); 52 | sb.Append("float: "); 53 | sb.AppendJoin(", ", fValues); 54 | sb.AppendLine(); 55 | sb.Append("decimal: "); 56 | sb.AppendJoin(", ", mValues); 57 | sb.AppendLine(); 58 | return sb.Length; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /sandbox/PerfBenchmark/Benchmarks/SixObjectConcatBenchmark.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Cysharp.Text; 3 | using System; 4 | using System.Text; 5 | 6 | namespace PerfBenchmark.Benchmarks 7 | { 8 | [Config(typeof(BenchmarkConfig))] 9 | public class SixObjectConcatBenchmark 10 | { 11 | int x; 12 | int y; 13 | int z; 14 | 15 | public SixObjectConcatBenchmark() 16 | { 17 | x = int.Parse("333"); 18 | y = int.Parse("444"); 19 | z = int.Parse("555"); 20 | } 21 | 22 | [Benchmark(Baseline = true)] 23 | public string StringPlus() 24 | { 25 | return "x:" + x + " y:" + y + " z:" + z; 26 | } 27 | 28 | [Benchmark] 29 | public string ZStringConcat() 30 | { 31 | return ZString.Concat("x:", x, " y:", y, " z:", z); 32 | } 33 | 34 | [Benchmark] 35 | public string StringFormat() 36 | { 37 | return string.Format("x:{0} y:{1} z:{2}", x, y, z); 38 | } 39 | 40 | [Benchmark] 41 | public string ZStringFormat() 42 | { 43 | return ZString.Format("x:{0} y:{1} z:{2}", x, y, z); 44 | } 45 | 46 | [Benchmark] 47 | public string StringBuilder() 48 | { 49 | var sb = new StringBuilder(); 50 | sb.Append("x:"); 51 | sb.Append(x); 52 | sb.Append(" y:"); 53 | sb.Append(y); 54 | sb.Append(" z:"); 55 | sb.Append(z); 56 | return sb.ToString(); 57 | } 58 | 59 | [Benchmark] 60 | public string ZStringBuilder() 61 | { 62 | using var sb = ZString.CreateStringBuilder(); 63 | sb.Append("x:"); 64 | sb.Append(x); 65 | sb.Append(" y:"); 66 | sb.Append(y); 67 | sb.Append(" z:"); 68 | sb.Append(z); 69 | return sb.ToString(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /sandbox/ConsoleApp/Program.cs: -------------------------------------------------------------------------------- 1 | using Cysharp.Text; 2 | using System; 3 | using System.Text; 4 | using BenchmarkDotNet.Attributes; 5 | using BenchmarkDotNet.Running; 6 | 7 | namespace ConsoleApp 8 | { 9 | public struct MyStruct 10 | { 11 | 12 | } 13 | 14 | class Program 15 | { 16 | static void Main(string[] args) 17 | { 18 | // BenchmarkRunner.Run(); 19 | Run(); 20 | } 21 | 22 | static void Run() 23 | { 24 | ZString.Join(",", "a", "b"); 25 | TimeSpan span = new TimeSpan(12, 34, 56); 26 | Console.WriteLine($"string.Format: {string.Format(@"{0:h\,h\:mm\:ss}", span)}"); 27 | Console.WriteLine($"ZString.Format: {ZString.Format(@"{0:h\,h\:mm\:ss}", span)}"); 28 | } 29 | } 30 | 31 | public class JoinBenchmark 32 | { 33 | public string[] Source = new []{ "111", "222", "333"}; 34 | public const string Sp = ","; 35 | 36 | [Benchmark] 37 | public string StringJoin() 38 | { 39 | return string.Join(Sp, Source); 40 | } 41 | 42 | [Benchmark] 43 | public string ZStringJoin() 44 | { 45 | return ZString.Join(Sp, Source); 46 | } 47 | } 48 | 49 | public class FormatBenchmark 50 | { 51 | int x; 52 | int y; 53 | string format; 54 | StringBuilder stringBuilder; 55 | 56 | public FormatBenchmark() 57 | { 58 | x = int.Parse("100"); 59 | y = int.Parse("200"); 60 | format = "x:{0}, y:{1}"; 61 | stringBuilder = new StringBuilder(); 62 | } 63 | 64 | public string StringFormat() 65 | { 66 | return string.Format(format, x, y); 67 | } 68 | 69 | public string ZStringFormat() 70 | { 71 | return ZString.Format(format, x, y); 72 | } 73 | 74 | //public string StringFormatterFormat() 75 | //{ 76 | // return StringBuffer.Format(format, x, y); 77 | //} 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 12 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 34 | m_PreloadedShaders: [] 35 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 36 | type: 0} 37 | m_CustomRenderPipeline: {fileID: 0} 38 | m_TransparencySortMode: 0 39 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 40 | m_DefaultRenderingPath: 1 41 | m_DefaultMobileRenderingPath: 1 42 | m_TierSettings: [] 43 | m_LightmapStripping: 0 44 | m_FogStripping: 0 45 | m_InstancingStripping: 0 46 | m_LightmapKeepPlain: 1 47 | m_LightmapKeepDirCombined: 1 48 | m_LightmapKeepDynamicPlain: 1 49 | m_LightmapKeepDynamicDirCombined: 1 50 | m_LightmapKeepShadowMask: 1 51 | m_LightmapKeepSubtractive: 1 52 | m_FogKeepLinear: 1 53 | m_FogKeepExp: 1 54 | m_FogKeepExp2: 1 55 | m_AlbedoSwatchInfos: [] 56 | m_LightsUseLinearIntensity: 0 57 | m_LightsUseColorTemperature: 0 58 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 4 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_JobOptions: 23 | serializedVersion: 2 24 | useMultithreading: 0 25 | useConsistencySorting: 0 26 | m_InterpolationPosesPerJob: 100 27 | m_NewContactsPerJob: 30 28 | m_CollideContactsPerJob: 100 29 | m_ClearFlagsPerJob: 200 30 | m_ClearBodyForcesPerJob: 200 31 | m_SyncDiscreteFixturesPerJob: 50 32 | m_SyncContinuousFixturesPerJob: 50 33 | m_FindNearestContactsPerJob: 100 34 | m_UpdateTriggerContactsPerJob: 100 35 | m_IslandSolverCostThreshold: 100 36 | m_IslandSolverBodyCostScale: 1 37 | m_IslandSolverContactCostScale: 10 38 | m_IslandSolverJointCostScale: 10 39 | m_IslandSolverBodiesPerJob: 50 40 | m_IslandSolverContactsPerJob: 50 41 | m_AutoSimulation: 1 42 | m_QueriesHitTriggers: 1 43 | m_QueriesStartInColliders: 1 44 | m_CallbacksOnDisable: 1 45 | m_ReuseCollisionCallbacks: 0 46 | m_AutoSyncTransforms: 0 47 | m_AlwaysShowColliders: 0 48 | m_ShowColliderSleep: 1 49 | m_ShowColliderContacts: 0 50 | m_ShowColliderAABB: 0 51 | m_ContactArrowScale: 0.2 52 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 53 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 54 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 55 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 56 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 57 | -------------------------------------------------------------------------------- /tests/ZString.Tests/InsertTest.cs: -------------------------------------------------------------------------------- 1 | using Cysharp.Text; 2 | using FluentAssertions; 3 | using System.Text; 4 | using Xunit; 5 | 6 | namespace ZStringTests 7 | { 8 | public class InsertTest 9 | { 10 | [Fact] 11 | public void InsertStringTest() 12 | { 13 | string initialValue = "--[]--"; 14 | 15 | using (var zsb = ZString.CreateStringBuilder(notNested: true)) 16 | { 17 | string xyz = "xyz"; 18 | 19 | zsb.Append(initialValue); 20 | var bcl = new StringBuilder(initialValue); 21 | 22 | zsb.Insert(3, xyz, 2); 23 | bcl.Insert(3, xyz, 2); 24 | zsb.ToString().Should().Be(bcl.ToString()); 25 | 26 | zsb.Insert(3, xyz); 27 | bcl.Insert(3, xyz); 28 | zsb.ToString().Should().Be(bcl.ToString()); 29 | 30 | zsb.Insert(0, "<<"); 31 | bcl.Insert(0, "<<"); 32 | zsb.ToString().Should().Be(bcl.ToString()); 33 | 34 | var endIndex = zsb.Length - 1; 35 | zsb.Insert(endIndex, ">>"); 36 | bcl.Insert(endIndex, ">>"); 37 | zsb.ToString().Should().Be(bcl.ToString()); 38 | } 39 | } 40 | 41 | [Fact] 42 | public void InsertLargeStringTest() 43 | { 44 | string initialValue = "--[]--"; 45 | 46 | using (var zsb = ZString.CreateStringBuilder(notNested: true)) 47 | { 48 | string text = new string('X', 32768); 49 | 50 | zsb.Append(initialValue); 51 | var bcl = new StringBuilder(initialValue); 52 | 53 | zsb.Insert(3, text); 54 | bcl.Insert(3, text); 55 | zsb.ToString().Should().Be(bcl.ToString()); 56 | } 57 | } 58 | 59 | [Fact] 60 | public void NotInserted() 61 | { 62 | using (var zsb = ZString.CreateStringBuilder(notNested: true)) 63 | { 64 | var text = "The quick brown dog jumps over the lazy cat."; 65 | zsb.Append(text); 66 | zsb.Insert( 10, ""); 67 | zsb.ToString().Should().Be(text); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/ZString/EnumUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Cysharp.Text 7 | { 8 | internal static class EnumUtil 9 | // where T : Enum 10 | { 11 | const string InvalidName = "$"; 12 | 13 | static readonly Dictionary names; 14 | static readonly Dictionary utf8names; 15 | 16 | static EnumUtil() 17 | { 18 | var enumNames = Enum.GetNames(typeof(T)); 19 | var values = 20 | #if NET7_0_OR_GREATER 21 | Enum.GetValuesAsUnderlyingType(typeof(T)); 22 | #else 23 | Enum.GetValues(typeof(T)); 24 | #endif 25 | names = new Dictionary(enumNames.Length); 26 | utf8names = new Dictionary(enumNames.Length); 27 | for (int i = 0; i < enumNames.Length; i++) 28 | { 29 | var value = (T)values.GetValue(i)!; 30 | if (names.ContainsKey(value)) 31 | { 32 | // already registered = invalid. 33 | names[value] = InvalidName; 34 | utf8names[value] = Array.Empty(); // byte[0] == Invalid. 35 | } 36 | else 37 | { 38 | names.Add(value, enumNames[i]); 39 | utf8names.Add(value, Encoding.UTF8.GetBytes(enumNames[i])); 40 | } 41 | } 42 | } 43 | 44 | public static bool TryFormatUtf16(T value, Span dest, out int written, ReadOnlySpan _) 45 | { 46 | if (!names.TryGetValue(value, out var v) || v == InvalidName) 47 | { 48 | v = value!.ToString(); // T is Enum, not null always 49 | } 50 | 51 | written = v.Length; 52 | return v.AsSpan().TryCopyTo(dest); 53 | } 54 | 55 | public static bool TryFormatUtf8(T value, Span dest, out int written, StandardFormat _) 56 | { 57 | if (!utf8names.TryGetValue(value, out var v) || v.Length == 0) 58 | { 59 | v = Encoding.UTF8.GetBytes(value!.ToString()); 60 | } 61 | 62 | written = v.Length; 63 | return v.AsSpan().TryCopyTo(dest); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/EnumUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Cysharp.Text 7 | { 8 | internal static class EnumUtil 9 | // where T : Enum 10 | { 11 | const string InvalidName = "$"; 12 | 13 | static readonly Dictionary names; 14 | static readonly Dictionary utf8names; 15 | 16 | static EnumUtil() 17 | { 18 | var enumNames = Enum.GetNames(typeof(T)); 19 | var values = 20 | #if NET7_0_OR_GREATER 21 | Enum.GetValuesAsUnderlyingType(typeof(T)); 22 | #else 23 | Enum.GetValues(typeof(T)); 24 | #endif 25 | names = new Dictionary(enumNames.Length); 26 | utf8names = new Dictionary(enumNames.Length); 27 | for (int i = 0; i < enumNames.Length; i++) 28 | { 29 | var value = (T)values.GetValue(i)!; 30 | if (names.ContainsKey(value)) 31 | { 32 | // already registered = invalid. 33 | names[value] = InvalidName; 34 | utf8names[value] = Array.Empty(); // byte[0] == Invalid. 35 | } 36 | else 37 | { 38 | names.Add(value, enumNames[i]); 39 | utf8names.Add(value, Encoding.UTF8.GetBytes(enumNames[i])); 40 | } 41 | } 42 | } 43 | 44 | public static bool TryFormatUtf16(T value, Span dest, out int written, ReadOnlySpan _) 45 | { 46 | if (!names.TryGetValue(value, out var v) || v == InvalidName) 47 | { 48 | v = value!.ToString(); // T is Enum, not null always 49 | } 50 | 51 | written = v.Length; 52 | return v.AsSpan().TryCopyTo(dest); 53 | } 54 | 55 | public static bool TryFormatUtf8(T value, Span dest, out int written, StandardFormat _) 56 | { 57 | if (!utf8names.TryGetValue(value, out var v) || v.Length == 0) 58 | { 59 | v = Encoding.UTF8.GetBytes(value!.ToString()); 60 | } 61 | 62 | written = v.Length; 63 | return v.AsSpan().TryCopyTo(dest); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/ZString.Tests/EnumTest.cs: -------------------------------------------------------------------------------- 1 | using Cysharp.Text; 2 | using FluentAssertions; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using Xunit; 7 | 8 | namespace ZStringTests 9 | { 10 | public enum DuplicateEnum 11 | { 12 | A = 1, 13 | B = 2, 14 | BB = 2, 15 | C = 3 16 | } 17 | 18 | public enum StandardEnum 19 | { 20 | Abc = 1, 21 | Def = 2, 22 | Ghi = 3, 23 | } 24 | 25 | [Flags] 26 | public enum FlagsEnum 27 | { 28 | None = 0, 29 | Abc = 1, 30 | Bcd = 2, 31 | Efg = 4, 32 | } 33 | 34 | public class EnumTest 35 | { 36 | [Fact] 37 | public void Duplicate() 38 | { 39 | ZString.Format("{0}", DuplicateEnum.A).Should().Be("A"); 40 | ZString.Format("{0}", DuplicateEnum.B).Should().Be("B"); 41 | ZString.Format("{0}", DuplicateEnum.BB).Should().Be("B"); 42 | ZString.Format("{0}", DuplicateEnum.C).Should().Be("C"); 43 | Utf8(DuplicateEnum.A); 44 | Utf8(DuplicateEnum.B); 45 | Utf8(DuplicateEnum.BB); 46 | Utf8(DuplicateEnum.C); 47 | } 48 | 49 | [Fact] 50 | public void Standard() 51 | { 52 | ZString.Format("{0}", StandardEnum.Abc).Should().Be("Abc"); 53 | ZString.Format("{0}", StandardEnum.Def).Should().Be("Def"); 54 | ZString.Format("{0}", StandardEnum.Ghi).Should().Be("Ghi"); 55 | Utf8(StandardEnum.Abc); 56 | Utf8(StandardEnum.Def); 57 | Utf8(StandardEnum.Ghi); 58 | } 59 | 60 | [Fact] 61 | public void Flags() 62 | { 63 | ZString.Format("{0}", FlagsEnum.Abc | FlagsEnum.Bcd).Should().Be("Abc, Bcd"); 64 | ZString.Format("{0}", FlagsEnum.None).Should().Be("None"); 65 | ZString.Format("{0}", FlagsEnum.Efg).Should().Be("Efg"); 66 | Utf8(FlagsEnum.Abc | FlagsEnum.Bcd); 67 | Utf8(FlagsEnum.None); 68 | Utf8(FlagsEnum.Efg); 69 | } 70 | 71 | static void Utf8(T e) where T : Enum 72 | { 73 | var s = ZString.CreateUtf8StringBuilder(); 74 | s.AppendFormat("{0}", e); 75 | s.AsSpan().SequenceEqual(Encoding.UTF8.GetBytes(e.ToString())).Should().BeTrue(); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/ZString/Utf16/Utf16ValueStringBuilder.SpanFormattableAppend.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="../T4Common.t4" once="true" #> 8 | using System; 9 | using System.Runtime.CompilerServices; 10 | 11 | namespace Cysharp.Text 12 | { 13 | public partial struct Utf16ValueStringBuilder 14 | { 15 | <# foreach(var t in spanFormattables) { #> 16 | /// Appends the string representation of a specified value to this instance. 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | public void Append(<#= t.FullName #> value) 19 | { 20 | if(!value.TryFormat(buffer.AsSpan(index), out var written)) 21 | { 22 | Grow(written); 23 | if(!value.TryFormat(buffer.AsSpan(index), out written)) 24 | { 25 | ThrowArgumentException(nameof(value)); 26 | } 27 | } 28 | index += written; 29 | } 30 | 31 | /// Appends the string representation of a specified value to this instance with numeric format strings. 32 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 33 | public void Append(<#= t.FullName #> value, string format) 34 | { 35 | if(!value.TryFormat(buffer.AsSpan(index), out var written, format.AsSpan())) 36 | { 37 | Grow(written); 38 | if(!value.TryFormat(buffer.AsSpan(index), out written, format.AsSpan())) 39 | { 40 | ThrowArgumentException(nameof(value)); 41 | } 42 | } 43 | index += written; 44 | } 45 | 46 | /// Appends the string representation of a specified value followed by the default line terminator to the end of this instance. 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | public void AppendLine(<#= t.FullName #> value) 49 | { 50 | Append(value); 51 | AppendLine(); 52 | } 53 | 54 | /// Appends the string representation of a specified value with numeric format strings followed by the default line terminator to the end of this instance. 55 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 56 | public void AppendLine(<#= t.FullName #> value, string format) 57 | { 58 | Append(value, format); 59 | AppendLine(); 60 | } 61 | <# } #> 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sandbox/PerfBenchmark/Benchmarks/StringBuilderAppendFormat.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Cysharp.Text; 3 | using System; 4 | using System.Text; 5 | 6 | namespace PerfBenchmark.Benchmarks 7 | { 8 | [Config(typeof(BenchmarkConfig))] 9 | public class StringBuilderAppendFormat 10 | { 11 | double[] dValues; 12 | float[] fValues; 13 | decimal[] mValues; 14 | public StringBuilderAppendFormat() 15 | { 16 | dValues = new[] { 0d, double.MaxValue, double.MinValue }; 17 | fValues = new[] { 0f, float.MaxValue, float.MinValue }; 18 | mValues = new[] { 0m, decimal.MaxValue, decimal.MinValue }; 19 | 20 | #if NETCOREAPP || NETSTANDARD2_1 21 | if (StringBuilder() != ZStringBuilder()) 22 | throw new Exception(); 23 | #endif 24 | } 25 | 26 | 27 | #if NETCOREAPP || NETSTANDARD2_1 28 | [Benchmark(Baseline = true)] 29 | public int StringBuilder() 30 | { 31 | var sb = new StringBuilder(); 32 | sb.AppendFormat("{{ {0}: {1}, {2}, {3} }} - {4}", "double", dValues[0], dValues[1], dValues[2], 1); 33 | sb.AppendLine(); 34 | sb.AppendFormat("{{ {0}: {1}, {2}, {3} }} - {4}", "float", fValues[0], fValues[1], fValues[2], 2); 35 | sb.AppendLine(); 36 | sb.AppendFormat("{{ {0}: {1}, {2}, {3} }} - {4}", "decimal", mValues[0], mValues[1], mValues[2], 3); 37 | sb.AppendLine(); 38 | return sb.Length; 39 | } 40 | #endif 41 | 42 | [Benchmark] 43 | public int ZStringBuilder() 44 | { 45 | using var sb = ZString.CreateStringBuilder(); 46 | sb.AppendFormat("{{ {0}: {1}, {2}, {3} }} - {4}", "double", dValues[0], dValues[1], dValues[2], 1); 47 | sb.AppendLine(); 48 | sb.AppendFormat("{{ {0}: {1}, {2}, {3} }} - {4}", "float", fValues[0], fValues[1], fValues[2], 2); 49 | sb.AppendLine(); 50 | sb.AppendFormat("{{ {0}: {1}, {2}, {3} }} - {4}", "decimal", mValues[0], mValues[1], mValues[2], 3); 51 | sb.AppendLine(); 52 | return sb.Length; 53 | } 54 | 55 | [Benchmark] 56 | public int ZStringBuilderUtf8() 57 | { 58 | using var sb = ZString.CreateUtf8StringBuilder(); 59 | sb.AppendFormat("{{ {0}: {1}, {2}, {3} }} - {4}", "double", dValues[0], dValues[1], dValues[2], 1); 60 | sb.AppendLine(); 61 | sb.AppendFormat("{{ {0}: {1}, {2}, {3} }} - {4}", "float", fValues[0], fValues[1], fValues[2], 2); 62 | sb.AppendLine(); 63 | sb.AppendFormat("{{ {0}: {1}, {2}, {3} }} - {4}", "decimal", mValues[0], mValues[1], mValues[2], 3); 64 | sb.AppendLine(); 65 | return sb.Length; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/ZString/Utf8/Utf8ValueStringBuilder.SpanFormattableAppend.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="../T4Common.t4" once="true" #> 8 | using System; 9 | using System.Buffers; 10 | using System.Buffers.Text; 11 | using System.Runtime.CompilerServices; 12 | 13 | namespace Cysharp.Text 14 | { 15 | public partial struct Utf8ValueStringBuilder 16 | { 17 | <# foreach(var t in utf8spanFormattables) { #> 18 | /// Appends the string representation of a specified value to this instance. 19 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 20 | public void Append(<#= t.FullName #> value) 21 | { 22 | if(!Utf8Formatter.TryFormat(value, buffer.AsSpan(index), out var written)) 23 | { 24 | Grow(written); 25 | if(!Utf8Formatter.TryFormat(value, buffer.AsSpan(index), out written)) 26 | { 27 | ThrowArgumentException(nameof(value)); 28 | } 29 | } 30 | index += written; 31 | } 32 | 33 | /// Appends the string representation of a specified value to this instance with numeric format strings. 34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 35 | public void Append(<#= t.FullName #> value, StandardFormat format) 36 | { 37 | if(!Utf8Formatter.TryFormat(value, buffer.AsSpan(index), out var written, format)) 38 | { 39 | Grow(written); 40 | if(!Utf8Formatter.TryFormat(value, buffer.AsSpan(index), out written, format)) 41 | { 42 | ThrowArgumentException(nameof(value)); 43 | } 44 | } 45 | index += written; 46 | } 47 | 48 | /// Appends the string representation of a specified value followed by the default line terminator to the end of this instance. 49 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 50 | public void AppendLine(<#= t.FullName #> value) 51 | { 52 | Append(value); 53 | AppendLine(); 54 | } 55 | 56 | /// Appends the string representation of a specified value with numeric format strings followed by the default line terminator to the end of this instance. 57 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 58 | public void AppendLine(<#= t.FullName #> value, StandardFormat format) 59 | { 60 | Append(value, format); 61 | AppendLine(); 62 | } 63 | 64 | <# } #> 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /.github/workflows/build-debug.yaml: -------------------------------------------------------------------------------- 1 | name: Build-Debug 2 | 3 | on: 4 | push: 5 | branches: 6 | - "master" 7 | pull_request: 8 | branches: 9 | - "master" 10 | 11 | jobs: 12 | build-dotnet: 13 | permissions: 14 | contents: read 15 | runs-on: ubuntu-24.04 16 | timeout-minutes: 10 17 | steps: 18 | - uses: Cysharp/Actions/.github/actions/checkout@main 19 | - uses: Cysharp/Actions/.github/actions/setup-dotnet@main 20 | - run: dotnet build -c Release 21 | - run: dotnet test -c Release --no-build 22 | - run: dotnet pack -c Release --no-build -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg -o $GITHUB_WORKSPACE/artifacts 23 | 24 | build-unity: 25 | if: ${{ (github.event_name == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:') }} 26 | strategy: 27 | matrix: 28 | unity: ["2021.3.41f1"] 29 | permissions: 30 | contents: read 31 | runs-on: ubuntu-24.04 32 | timeout-minutes: 15 33 | steps: 34 | - name: Load secrets 35 | id: op-load-secret 36 | uses: 1password/load-secrets-action@581a835fb51b8e7ec56b71cf2ffddd7e68bb25e0 # v2.0.0 37 | with: 38 | export-env: false 39 | env: 40 | OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN_PUBLIC }} 41 | UNITY_EMAIL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/username" 42 | UNITY_PASSWORD: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/credential" 43 | UNITY_SERIAL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/serial" 44 | 45 | - uses: Cysharp/Actions/.github/actions/checkout@main 46 | # Execute scripts: Export Package 47 | # /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export 48 | - name: Build Unity (.unitypacakge) 49 | uses: Cysharp/Actions/.github/actions/unity-builder@main 50 | env: 51 | UNITY_EMAIL: ${{ steps.op-load-secret.outputs.UNITY_EMAIL }} 52 | UNITY_PASSWORD: ${{ steps.op-load-secret.outputs.UNITY_PASSWORD }} 53 | UNITY_SERIAL: ${{ steps.op-load-secret.outputs.UNITY_SERIAL }} 54 | with: 55 | projectPath: src/ZString.Unity 56 | unityVersion: ${{ matrix.unity }} 57 | targetPlatform: StandaloneLinux64 58 | buildMethod: PackageExporter.Export 59 | 60 | - uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files 61 | with: 62 | directory: src/ZString.Unity 63 | 64 | # Store artifacts. 65 | - uses: Cysharp/Actions/.github/actions/upload-artifact@main 66 | with: 67 | name: ZString.Unity.${{ matrix.unity }}.unitypackage.zip 68 | path: ./src/ZString.Unity/*.unitypackage 69 | retention-days: 1 70 | -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/Editor/PackageExporter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using UnityEditor; 5 | using UnityEngine; 6 | 7 | public static class PackageExporter 8 | { 9 | [MenuItem("Tools/Export Unitypackage")] 10 | public static void Export() 11 | { 12 | var root = "Scripts/ZString"; 13 | var version = GetVersion(root); 14 | 15 | var fileName = string.IsNullOrEmpty(version) ? "ZString.Unity.unitypackage" : $"ZString.Unity.{version}.unitypackage"; 16 | var exportPath = "./" + fileName; 17 | 18 | var path = Path.Combine(Application.dataPath, root); 19 | var assets = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) 20 | .Where(x => Path.GetExtension(x) == ".cs" || Path.GetExtension(x) == ".meta" || Path.GetExtension(x) == ".asmdef" || Path.GetExtension(x) == ".rsp") 21 | .Where(x => Path.GetFileNameWithoutExtension(x) != "_InternalVisibleTo") 22 | .Select(x => "Assets" + x.Replace(Application.dataPath, "").Replace(@"\", "/")) 23 | .ToArray(); 24 | 25 | var netStandardsAsset = Directory.EnumerateFiles(Path.Combine(Application.dataPath, "Plugins/"), "*", SearchOption.AllDirectories) 26 | .Select(x => "Assets" + x.Replace(Application.dataPath, "").Replace(@"\", "/")) 27 | .ToArray(); 28 | 29 | assets = assets.Concat(netStandardsAsset).ToArray(); 30 | 31 | UnityEngine.Debug.Log("Export below files" + Environment.NewLine + string.Join(Environment.NewLine, assets)); 32 | 33 | var dir = new FileInfo(exportPath).Directory; 34 | if (!dir.Exists) dir.Create(); 35 | AssetDatabase.ExportPackage( 36 | assets, 37 | exportPath, 38 | ExportPackageOptions.Default); 39 | 40 | UnityEngine.Debug.Log("Export complete: " + Path.GetFullPath(exportPath)); 41 | } 42 | 43 | static string GetVersion(string root) 44 | { 45 | var version = Environment.GetEnvironmentVariable("UNITY_PACKAGE_VERSION"); 46 | var versionJson = Path.Combine(Application.dataPath, root, "package.json"); 47 | 48 | if (File.Exists(versionJson)) 49 | { 50 | var v = JsonUtility.FromJson(File.ReadAllText(versionJson)); 51 | 52 | if (!string.IsNullOrEmpty(version)) 53 | { 54 | if (v.version != version) 55 | { 56 | var msg = $"package.json and env version are mismatched. UNITY_PACKAGE_VERSION:{version}, package.json:{v.version}"; 57 | 58 | if (Application.isBatchMode) 59 | { 60 | Console.WriteLine(msg); 61 | Application.Quit(1); 62 | } 63 | 64 | throw new Exception("package.json and env version are mismatched."); 65 | } 66 | } 67 | 68 | version = v.version; 69 | } 70 | 71 | return version; 72 | } 73 | 74 | public class Version 75 | { 76 | public string version; 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /src/ZString/Number/DecimalEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | 7 | namespace System 8 | { 9 | internal static class DecimalEx 10 | { 11 | [StructLayout(LayoutKind.Explicit)] 12 | private struct DecimalBits 13 | { 14 | [FieldOffset(0)] 15 | public int flags; 16 | [FieldOffset(4)] 17 | public int hi; 18 | [FieldOffset(8)] 19 | public int lo; 20 | [FieldOffset(12)] 21 | public int mid; 22 | } 23 | 24 | [StructLayout(LayoutKind.Explicit)] 25 | private struct DecCalc 26 | { 27 | private const uint TenToPowerNine = 1000000000; 28 | 29 | // NOTE: Do not change the offsets of these fields. This structure must have the same layout as Decimal. 30 | [FieldOffset(0)] 31 | public uint uflags; 32 | [FieldOffset(4)] 33 | public uint uhi; 34 | [FieldOffset(8)] 35 | public uint ulo; 36 | [FieldOffset(12)] 37 | public uint umid; 38 | 39 | /// 40 | /// The low and mid fields combined in little-endian order 41 | /// 42 | [FieldOffset(8)] 43 | private ulong ulomidLE; 44 | 45 | internal static uint DecDivMod1E9(ref DecCalc value) 46 | { 47 | ulong high64 = ((ulong)value.uhi << 32) + value.umid; 48 | ulong div64 = high64 / TenToPowerNine; 49 | value.uhi = (uint)(div64 >> 32); 50 | value.umid = (uint)div64; 51 | 52 | ulong num = ((high64 - (uint)div64 * TenToPowerNine) << 32) + value.ulo; 53 | uint div = (uint)(num / TenToPowerNine); 54 | value.ulo = div; 55 | return (uint)num - div * TenToPowerNine; 56 | } 57 | } 58 | 59 | private const int ScaleShift = 16; 60 | 61 | static ref DecCalc AsMutable(ref decimal d) => ref Unsafe.As(ref d); 62 | 63 | internal static uint High(this decimal value) 64 | { 65 | return Unsafe.As(ref value).uhi; 66 | } 67 | 68 | internal static uint Low(this decimal value) 69 | { 70 | return Unsafe.As(ref value).ulo; 71 | } 72 | 73 | internal static uint Mid(this decimal value) 74 | { 75 | return Unsafe.As(ref value).umid; 76 | } 77 | 78 | internal static bool IsNegative(this decimal value) 79 | { 80 | return Unsafe.As(ref value).flags < 0; 81 | } 82 | 83 | internal static int Scale(this decimal value) 84 | { 85 | return (byte)(Unsafe.As(ref value).flags >> ScaleShift); 86 | } 87 | 88 | internal static uint DecDivMod1E9(ref decimal value) 89 | { 90 | return DecCalc.DecDivMod1E9(ref AsMutable(ref value)); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/ZString/Utf16/Utf16ValueStringBuilder.CreateFormatter.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="../T4Common.t4" once="true" #> 8 | <# 9 | var spanFormattablesA = new Type[] 10 | { 11 | typeof(SByte), 12 | typeof(Int16), 13 | typeof(Int32), 14 | typeof(Int64), 15 | }; 16 | var spanFormattablesB = new Type[] 17 | { 18 | typeof(Byte), 19 | typeof(UInt16), 20 | typeof(UInt32), 21 | typeof(UInt64), 22 | }; 23 | var spanFormattablesC = new Type[] 24 | { 25 | typeof(Single), 26 | typeof(Double), 27 | typeof(TimeSpan), 28 | typeof(DateTime), 29 | typeof(DateTimeOffset), 30 | typeof(Decimal), 31 | typeof(Guid), 32 | }; 33 | #> 34 | using System; 35 | 36 | namespace Cysharp.Text 37 | { 38 | public partial struct Utf16ValueStringBuilder 39 | { 40 | static object CreateFormatter(Type type) 41 | { 42 | <# foreach(var t in spanFormattablesA) { #> 43 | if (type == typeof(<#= t.FullName #>)) 44 | { 45 | return new TryFormat<<#= t.FullName #>>((<#= t.FullName #> x, Span dest, out int written, ReadOnlySpan format) => format.Length == 0 ? FastNumberWriter.TryWriteInt64(dest, out written, x) : x.TryFormat(dest, out written, format)); 46 | } 47 | <# } #> 48 | <# foreach(var t in spanFormattablesB) { #> 49 | if (type == typeof(<#= t.FullName #>)) 50 | { 51 | return new TryFormat<<#= t.FullName #>>((<#= t.FullName #> x, Span dest, out int written, ReadOnlySpan format) => format.Length == 0 ? FastNumberWriter.TryWriteUInt64(dest, out written, x) : x.TryFormat(dest, out written, format)); 52 | } 53 | <# } #> 54 | <# foreach(var t in spanFormattablesC) { #> 55 | if (type == typeof(<#= t.FullName #>)) 56 | { 57 | return new TryFormat<<#= t.FullName #>>((<#= t.FullName #> x, Span dest, out int written, ReadOnlySpan format) => x.TryFormat(dest, out written, format)); 58 | } 59 | <# } #> 60 | <# foreach(var t in spanFormattables.Append(typeof(bool))) { #> 61 | if (type == typeof(<#= t.FullName #>?)) 62 | { 63 | return CreateNullableFormatter<<#= t.FullName #>>(); 64 | } 65 | <# } #> 66 | <# foreach(var t in new [] {typeof(IntPtr), typeof(UIntPtr)}) { var u = t == typeof(UIntPtr); #> 67 | if (type == typeof(<#= t.FullName #>)) 68 | { 69 | return new TryFormat<<#= t.FullName #>>((<#= t.FullName #> x, Span dest, out int written, ReadOnlySpan format) => <#= t #>.Size == 4 70 | ? x.To<#= u ? "U" : "" #>Int32().TryFormat(dest, out written, format) 71 | : x.To<#= u ? "U" : "" #>Int64().TryFormat(dest, out written, format)); 72 | } 73 | <# } #> 74 | return null; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/DecimalEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | 7 | namespace System 8 | { 9 | internal static class DecimalEx 10 | { 11 | [StructLayout(LayoutKind.Explicit)] 12 | private struct DecimalBits 13 | { 14 | [FieldOffset(0)] 15 | public int flags; 16 | [FieldOffset(4)] 17 | public int hi; 18 | [FieldOffset(8)] 19 | public int lo; 20 | [FieldOffset(12)] 21 | public int mid; 22 | } 23 | 24 | [StructLayout(LayoutKind.Explicit)] 25 | private struct DecCalc 26 | { 27 | private const uint TenToPowerNine = 1000000000; 28 | 29 | // NOTE: Do not change the offsets of these fields. This structure must have the same layout as Decimal. 30 | [FieldOffset(0)] 31 | public uint uflags; 32 | [FieldOffset(4)] 33 | public uint uhi; 34 | [FieldOffset(8)] 35 | public uint ulo; 36 | [FieldOffset(12)] 37 | public uint umid; 38 | 39 | /// 40 | /// The low and mid fields combined in little-endian order 41 | /// 42 | [FieldOffset(8)] 43 | private ulong ulomidLE; 44 | 45 | internal static uint DecDivMod1E9(ref DecCalc value) 46 | { 47 | ulong high64 = ((ulong)value.uhi << 32) + value.umid; 48 | ulong div64 = high64 / TenToPowerNine; 49 | value.uhi = (uint)(div64 >> 32); 50 | value.umid = (uint)div64; 51 | 52 | ulong num = ((high64 - (uint)div64 * TenToPowerNine) << 32) + value.ulo; 53 | uint div = (uint)(num / TenToPowerNine); 54 | value.ulo = div; 55 | return (uint)num - div * TenToPowerNine; 56 | } 57 | } 58 | 59 | private const int ScaleShift = 16; 60 | 61 | static ref DecCalc AsMutable(ref decimal d) => ref Unsafe.As(ref d); 62 | 63 | internal static uint High(this decimal value) 64 | { 65 | return Unsafe.As(ref value).uhi; 66 | } 67 | 68 | internal static uint Low(this decimal value) 69 | { 70 | return Unsafe.As(ref value).ulo; 71 | } 72 | 73 | internal static uint Mid(this decimal value) 74 | { 75 | return Unsafe.As(ref value).umid; 76 | } 77 | 78 | internal static bool IsNegative(this decimal value) 79 | { 80 | return Unsafe.As(ref value).flags < 0; 81 | } 82 | 83 | internal static int Scale(this decimal value) 84 | { 85 | return (byte)(Unsafe.As(ref value).flags >> ScaleShift); 86 | } 87 | 88 | internal static uint DecDivMod1E9(ref decimal value) 89 | { 90 | return DecCalc.DecDivMod1E9(ref AsMutable(ref value)); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/ZString/PreparedFormat.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="T4Common.t4" once="true" #> 8 | using System; 9 | using System.Text; 10 | using System.Buffers; 11 | 12 | namespace Cysharp.Text 13 | { 14 | <# foreach(var utf in utfTypes) { var isUtf16 = (utf == "Utf16"); #> 15 | <# for(var i = 1; i <= TypeParamMax; i++) { #> 16 | public sealed partial class <#= utf #>PreparedFormat<<#= CreateTypeArgument(i) #>> 17 | { 18 | public string FormatString { get; } 19 | public int MinSize { get; } 20 | 21 | readonly <#= utf #>FormatSegment[] segments; 22 | <# if(!isUtf16) { #> 23 | readonly byte[] utf8PreEncodedbuffer; 24 | <# } #> 25 | 26 | public <#= utf #>PreparedFormat(string format) 27 | { 28 | this.FormatString = format; 29 | this.segments = PreparedFormatHelper.<#= utf #>Parse(format<#= (!isUtf16 ? ", out utf8PreEncodedbuffer" : "") #>); 30 | 31 | var size = 0; 32 | foreach (var item in segments) 33 | { 34 | if (!item.IsFormatArgument) 35 | { 36 | size += item.Count; 37 | } 38 | } 39 | this.MinSize = size; 40 | } 41 | 42 | public string Format(<#= CreateParameters(i) #>) 43 | { 44 | var sb = new <#= utf #>ValueStringBuilder(true); 45 | try 46 | { 47 | FormatTo(ref sb, <#= CreateParameterNames(i) #>); 48 | return sb.ToString(); 49 | } 50 | finally 51 | { 52 | sb.Dispose(); 53 | } 54 | } 55 | 56 | public void FormatTo(ref TBufferWriter sb, <#= CreateParameters(i) #>) 57 | where TBufferWriter : IBufferWriter<<#= isUtf16 ? "char" : "byte" #>> 58 | { 59 | <# if(isUtf16) { #> 60 | var formatSpan = FormatString.AsSpan(); 61 | <# } else { #> 62 | var formatSpan = utf8PreEncodedbuffer.AsSpan(); 63 | <# } #> 64 | 65 | foreach (var item in segments) 66 | { 67 | switch (item.FormatIndex) 68 | { 69 | case <#= utf #>FormatSegment.NotFormatIndex: 70 | { 71 | var strSpan = formatSpan.Slice(item.Offset, item.Count); 72 | var span = sb.GetSpan(item.Count); 73 | strSpan.TryCopyTo(span); 74 | sb.Advance(item.Count); 75 | break; 76 | } 77 | <# for(var j = 0; j < i; j++) { #> 78 | case <#= j #>: 79 | { 80 | <#= utf #>FormatHelper.FormatTo(ref sb, arg<#= j + 1 #>, item.Alignment, <#= isUtf16 ? "formatSpan.Slice(item.Offset, item.Count)" : "item.StandardFormat" #>, nameof(arg<#= j + 1 #>)); 81 | break; 82 | } 83 | <# } // for(j) #> 84 | default: 85 | break; 86 | } 87 | } 88 | } 89 | } 90 | <# } // for(i) #> 91 | <# } // foreach(utf) #> 92 | } 93 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Bb]in/ 3 | [Oo]bj/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Rr]elease/ 19 | x64/ 20 | *_i.c 21 | *_p.c 22 | *.ilk 23 | *.obj 24 | *.pch 25 | *.pdb 26 | *.pgc 27 | *.pgd 28 | *.rsp 29 | *.sbr 30 | *.tlb 31 | *.tli 32 | *.tlh 33 | *.tmp 34 | *.log 35 | *.vspscc 36 | *.vssscc 37 | .builds 38 | 39 | # Visual C++ cache files 40 | ipch/ 41 | *.aps 42 | *.ncb 43 | *.opensdf 44 | *.sdf 45 | 46 | # Visual Studio profiler 47 | *.psess 48 | *.vsp 49 | *.vspx 50 | 51 | # Guidance Automation Toolkit 52 | *.gpState 53 | 54 | # ReSharper is a .NET coding add-in 55 | _ReSharper* 56 | 57 | # NCrunch 58 | *.ncrunch* 59 | .*crunch*.local.xml 60 | 61 | # Installshield output folder 62 | [Ee]xpress 63 | 64 | # DocProject is a documentation generator add-in 65 | DocProject/buildhelp/ 66 | DocProject/Help/*.HxT 67 | DocProject/Help/*.HxC 68 | DocProject/Help/*.hhc 69 | DocProject/Help/*.hhk 70 | DocProject/Help/*.hhp 71 | DocProject/Help/Html2 72 | DocProject/Help/html 73 | 74 | # Click-Once directory 75 | publish 76 | 77 | # Publish Web Output 78 | *.Publish.xml 79 | 80 | # NuGet Packages Directory 81 | packages 82 | 83 | # Windows Azure Build Output 84 | csx 85 | *.build.csdef 86 | 87 | # Windows Store app package directory 88 | AppPackages/ 89 | 90 | # Others 91 | [Bb]in 92 | [Oo]bj 93 | sql 94 | TestResults 95 | [Tt]est[Rr]esult* 96 | *.Cache 97 | ClientBin 98 | [Ss]tyle[Cc]op.* 99 | ~$* 100 | *.dbmdl 101 | Generated_Code #added for RIA/Silverlight projects 102 | 103 | # Backup & report files from converting an old project file to a newer 104 | # Visual Studio version. Backup files are not needed, because we have git ;-) 105 | _UpgradeReport_Files/ 106 | Backup*/ 107 | UpgradeLog*.XML 108 | .vs/config/applicationhost.config 109 | .vs/restore.dg 110 | 111 | # OTHER 112 | nuget/tools/* 113 | *.nupkg 114 | 115 | .vs 116 | 117 | # Unity 118 | Library/ 119 | Temp/ 120 | src/ZString.Unity/Assembly-CSharp.csproj 121 | src/ZString.Unity/Assembly-CSharp-Editor.csproj 122 | src/ZString.Unity/ZString.csproj 123 | src/ZString.Unity/ZString.Unity.sln 124 | 125 | src/ZString.Unity/ZString.Unity.unitypackage 126 | 127 | # Benchmark Results 128 | **/BenchmarkDotNet.Artifacts/* 129 | 130 | src/ZString.Unity/Unity.Analytics.DataPrivacy.csproj 131 | 132 | src/ZString.Unity/Unity.CollabProxy.Editor.csproj 133 | 134 | src/ZString.Unity/Unity.Rider.Editor.csproj 135 | 136 | src/ZString.Unity/Unity.TextMeshPro.csproj 137 | 138 | src/ZString.Unity/Unity.TextMeshPro.Editor.csproj 139 | 140 | src/ZString.Unity/Unity.Timeline.csproj 141 | 142 | src/ZString.Unity/Unity.Timeline.Editor.csproj 143 | 144 | src/ZString.Unity/Unity.VisualStudio.Editor.csproj 145 | 146 | src/ZString.Unity/Unity.VSCode.Editor.csproj 147 | 148 | src/ZString.Unity/UnityEditor.TestRunner.csproj 149 | 150 | src/ZString.Unity/UnityEditor.UI.csproj 151 | 152 | src/ZString.Unity/UnityEngine.Advertisements.csproj 153 | 154 | src/ZString.Unity/UnityEngine.Monetization.csproj 155 | 156 | src/ZString.Unity/UnityEngine.TestRunner.csproj 157 | 158 | src/ZString.Unity/UnityEngine.UI.csproj 159 | 160 | src/ZString.Unity/*.csproj 161 | -------------------------------------------------------------------------------- /sandbox/BenchmarkVsReleasedVersion/ConcatBenchmark.cs: -------------------------------------------------------------------------------- 1 | extern alias NewZString; 2 | 3 | using BenchmarkDotNet.Attributes; 4 | using BenchmarkDotNet.Configs; 5 | using Cysharp.Text; 6 | using System; 7 | using System.Text; 8 | 9 | namespace BenchmarkVsReleasedVersion 10 | { 11 | [Config(typeof(BenchmarkConfig))] 12 | [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] 13 | [DisassemblyDiagnoser(maxDepth: 3)] 14 | public class ConcatBenchmark 15 | { 16 | int a; 17 | int b; 18 | int c; 19 | int x; 20 | int y; 21 | int z; 22 | 23 | public ConcatBenchmark() 24 | { 25 | a = int.Parse("000"); 26 | b = int.Parse("111"); 27 | c = int.Parse("222"); 28 | x = int.Parse("333"); 29 | y = int.Parse("444"); 30 | z = int.Parse("555"); 31 | } 32 | 33 | [BenchmarkCategory("FourParams"), Benchmark(Baseline = true)] 34 | public string FourParamsConcat_() 35 | { 36 | return ZString 37 | .Concat("x:", x, " y:", y); 38 | } 39 | 40 | [BenchmarkCategory("FourParams"), Benchmark] 41 | public string FourParamsConcatN() 42 | { 43 | return NewZString::Cysharp.Text.ZString 44 | .Concat("x:", x, " y:", y); 45 | } 46 | 47 | [BenchmarkCategory("SixParams"), Benchmark(Baseline = true)] 48 | public string SixParamsConcat_() 49 | { 50 | return ZString 51 | .Concat("a:", a, " b:", b, " c:", c); 52 | } 53 | 54 | [BenchmarkCategory("SixParams"), Benchmark] 55 | public string SixParamsConcatN() 56 | { 57 | return NewZString::Cysharp.Text.ZString 58 | .Concat("a:", a, " b:", b, " c:", c); 59 | } 60 | 61 | [BenchmarkCategory("EightParams"), Benchmark(Baseline = true)] 62 | public string EightParamsConcat_() 63 | { 64 | return ZString 65 | .Concat("a:", a, " b:", b, " c:", c, " x:", x); 66 | } 67 | 68 | [BenchmarkCategory("EightParams"), Benchmark] 69 | public string EightParamsConcatN() 70 | { 71 | return NewZString::Cysharp.Text.ZString 72 | .Concat("a:", a, " b:", b, " c:", c, " x:", x); 73 | } 74 | 75 | [BenchmarkCategory("TenParams"), Benchmark(Baseline = true)] 76 | public string TenParamsConcat_() 77 | { 78 | return ZString 79 | .Concat("a:", a, " b:", b, " c:", c, " x:", x, " y:", y); 80 | } 81 | 82 | [BenchmarkCategory("TenParams"), Benchmark] 83 | public string TenParamsConcatN() 84 | { 85 | return NewZString::Cysharp.Text.ZString 86 | .Concat("a:", a, " b:", b, " c:", c, " x:", x, " y:", y); 87 | } 88 | 89 | [BenchmarkCategory("TwelveParams"), Benchmark(Baseline = true)] 90 | public string TwelveParamsConcat_() 91 | { 92 | return ZString 93 | .Concat("a:", a, " b:", b, " c:", c, " x:", x, " y:", y, " z:", z); 94 | } 95 | 96 | [BenchmarkCategory("TwelveParams"), Benchmark] 97 | public string TwelveParamsConcatN() 98 | { 99 | return NewZString::Cysharp.Text.ZString 100 | .Concat("a:", a, " b:", b, " c:", c, " x:", x, " y:", y, " z:", z); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /sandbox/PerfBenchmark/Benchmarks/StringListJoinBenchmark.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Cysharp.Text; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | namespace PerfBenchmark.Benchmarks 7 | { 8 | [Config(typeof(BenchmarkConfig))] 9 | public class StringListJoinBenchmark 10 | { 11 | //private const char Separator = ','; 12 | private const string Separator = ","; 13 | 14 | List _emptyList; 15 | IEnumerable _enum1; 16 | string[] _array1; 17 | List _list1; 18 | IEnumerable _enum2; 19 | string[] _array2; 20 | List _list2; 21 | IEnumerable _enum10; 22 | List _list10; 23 | string[] _array10; 24 | 25 | public StringListJoinBenchmark() 26 | { 27 | _emptyList = new List(); 28 | _enum1 = Enumerable.Repeat(Guid.NewGuid().ToString(), 1); 29 | _list1 = _enum1.ToList(); 30 | _array1 = _enum1.ToArray(); 31 | _enum2 = Enumerable.Repeat(Guid.NewGuid().ToString(), 2); 32 | _list2 = _enum2.ToList(); 33 | _array2 = _enum2.ToArray(); 34 | _enum10 = Enumerable.Repeat(Guid.NewGuid().ToString(), 10); 35 | _list10 = _enum10.ToList(); 36 | _array10 = _enum10.ToArray(); 37 | } 38 | 39 | [Benchmark] 40 | public string JoinEmptyList() => String.Join(Separator, _emptyList); 41 | 42 | [Benchmark] 43 | public string ZJoinEmptyList() => ZString.Join(Separator, _emptyList); 44 | 45 | [Benchmark] 46 | public string JoinList1() => String.Join(Separator, _list1); 47 | 48 | [Benchmark] 49 | public string ZJoinList1() => ZString.Join(Separator, _list1); 50 | 51 | [Benchmark] 52 | public string JoinArray1() => String.Join(Separator, _array1); 53 | 54 | [Benchmark] 55 | public string ZJoinArray1() => ZString.Join(Separator, _array1); 56 | 57 | [Benchmark] 58 | public string JoinEnumerable1() => String.Join(Separator, _enum1); 59 | 60 | [Benchmark] 61 | public string ZJoinEnumerable1() => ZString.Join(Separator, _enum1); 62 | 63 | [Benchmark] 64 | public string JoinList2() => String.Join(Separator, _list2); 65 | 66 | [Benchmark] 67 | public string ZJoinList2() => ZString.Join(Separator, _list2); 68 | 69 | [Benchmark] 70 | public string JoinArray2() => String.Join(Separator, _array2); 71 | 72 | [Benchmark] 73 | public string ZJoinArray2() => ZString.Join(Separator, _array2); 74 | 75 | [Benchmark] 76 | public string JoinEnumerable2() => String.Join(Separator, _enum2); 77 | 78 | [Benchmark] 79 | public string ZJoinEnumerable2() => ZString.Join(Separator, _enum2); 80 | 81 | [Benchmark] 82 | public string JoinList10() => String.Join(Separator, _list10); 83 | 84 | [Benchmark] 85 | public string ZJoinList10() => ZString.Join(Separator, _list10); 86 | 87 | [Benchmark] 88 | public string JoinArray10() => String.Join(Separator, _array10); 89 | 90 | [Benchmark] 91 | public string ZJoinArray10() => ZString.Join(Separator, _array10); 92 | 93 | [Benchmark] 94 | public string JoinEnumerable10() => String.Join(Separator, _enum10); 95 | 96 | [Benchmark] 97 | public string ZJoinEnumerable10() => ZString.Join(Separator, _enum10); 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /sandbox/PerfBenchmark/Benchmarks/AppendPerformance.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using Cysharp.Text; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace PerfBenchmark.Benchmarks 8 | { 9 | [Config(typeof(BenchmarkConfig))] 10 | public class AppendPerformance 11 | { 12 | List strings; 13 | const int COUNT = 1000; 14 | 15 | public AppendPerformance() 16 | { 17 | strings = new List(); 18 | for (int i = 0; i < 100; i++) 19 | { 20 | strings.Add("123456789"); 21 | } 22 | } 23 | 24 | [Benchmark] 25 | public void ZStringUtf16() 26 | { 27 | for (int i = 0; i < COUNT; i++) 28 | { 29 | using (var sb = ZString.CreateStringBuilder()) 30 | { 31 | for (int j = 0; j < strings.Count; j++) 32 | { 33 | sb.Append(strings[j]); 34 | } 35 | 36 | _ = sb.ToString(); 37 | } 38 | } 39 | } 40 | 41 | //[Benchmark] 42 | //public void ZStringUtf16SpanBased() 43 | //{ 44 | // for (int i = 0; i < COUNT; i++) 45 | // { 46 | // using (var sb = ZString.CreateStringBuilder()) 47 | // { 48 | // for (int j = 0; j < strings.Count; j++) 49 | // { 50 | // sb.AppendSlow(strings[j]); 51 | // } 52 | 53 | // _ = sb.ToString(); 54 | // } 55 | // } 56 | //} 57 | 58 | [Benchmark(Baseline = true)] 59 | public void StringBuilder() 60 | { 61 | for (int i = 0; i < COUNT; i++) 62 | { 63 | System.Text.StringBuilder sb = new System.Text.StringBuilder(); 64 | for (int j = 0; j < strings.Count; j++) 65 | { 66 | sb.Append(strings[j]); 67 | } 68 | 69 | _ = sb.ToString(); 70 | } 71 | } 72 | } 73 | 74 | 75 | [Config(typeof(BenchmarkConfig))] 76 | public class Utf8AppendPerformance 77 | { 78 | List strings; 79 | const int COUNT = 1000; 80 | 81 | public Utf8AppendPerformance() 82 | { 83 | strings = new List(); 84 | for (int i = 0; i < 100; i++) 85 | { 86 | strings.Add("123456789"); 87 | } 88 | } 89 | 90 | [Benchmark] 91 | public void ZStringUtf8() 92 | { 93 | for (int i = 0; i < COUNT; i++) 94 | { 95 | using (var sb = ZString.CreateUtf8StringBuilder()) 96 | { 97 | for (int j = 0; j < strings.Count; j++) 98 | { 99 | sb.Append(strings[j]); 100 | } 101 | 102 | _ = sb.AsSpan().ToArray(); 103 | } 104 | } 105 | } 106 | 107 | [Benchmark(Baseline = true)] 108 | public void StringBuilder() 109 | { 110 | for (int i = 0; i < COUNT; i++) 111 | { 112 | System.Text.StringBuilder sb = new System.Text.StringBuilder(); 113 | for (int j = 0; j < strings.Count; j++) 114 | { 115 | sb.Append(strings[j]); 116 | } 117 | 118 | _ = sb.ToString(); 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/ZString/Utf8/Utf8ValueStringBuilder.AppendFormat.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="../T4Common.t4" once="true" #> 8 | using System; 9 | using System.Buffers; 10 | 11 | namespace Cysharp.Text 12 | { 13 | public partial struct Utf8ValueStringBuilder 14 | { 15 | <# for(var i = 1; i <= TypeParamMax; i++) { #> 16 | /// Appends the string returned by processing a composite format string, each format item is replaced by the string representation of arguments. 17 | public void AppendFormat<<#= CreateTypeArgument(i) #>>(string format, <#= CreateParameters(i) #>) 18 | { 19 | if (format == null) 20 | { 21 | throw new ArgumentNullException(nameof(format)); 22 | } 23 | 24 | var copyFrom = 0; 25 | for (int i = 0; i < format.Length; i++) 26 | { 27 | var c = format[i]; 28 | if (c == '{') 29 | { 30 | // escape. 31 | if (i == format.Length - 1) 32 | { 33 | throw new FormatException("invalid format"); 34 | } 35 | 36 | if (i != format.Length && format[i + 1] == '{') 37 | { 38 | var size = i - copyFrom; 39 | Append(format, copyFrom, size); 40 | i = i + 1; // skip escaped '{' 41 | copyFrom = i; 42 | continue; 43 | } 44 | else 45 | { 46 | var size = i - copyFrom; 47 | Append(format.AsSpan(copyFrom, size)); 48 | } 49 | 50 | // try to find range 51 | var indexParse = FormatParser.Parse(format, i); 52 | copyFrom = indexParse.LastIndex; 53 | i = indexParse.LastIndex - 1; 54 | var writeFormat = StandardFormat.Parse(indexParse.FormatString); 55 | switch (indexParse.Index) 56 | { 57 | <# for(var j = 0; j < i; j++) { #> 58 | case <#= j #>: 59 | AppendFormatInternal(arg<#= j + 1 #>, indexParse.Alignment, writeFormat, nameof(arg<#= j + 1 #>)); 60 | continue; 61 | <# } #> 62 | default: 63 | ThrowFormatException(); 64 | break; 65 | } 66 | } 67 | else if (c == '}') 68 | { 69 | if (i + 1 < format.Length && format[i + 1] == '}') 70 | { 71 | var size = i - copyFrom; 72 | Append(format, copyFrom, size); 73 | i = i + 1; // skip escaped '}' 74 | copyFrom = i; 75 | continue; 76 | } 77 | else 78 | { 79 | ThrowFormatException(); 80 | } 81 | } 82 | 83 | } 84 | 85 | { 86 | // copy final string 87 | var copyLength = format.Length - copyFrom; 88 | if (copyLength > 0) 89 | { 90 | Append(format, copyFrom, copyLength); 91 | } 92 | } 93 | } 94 | 95 | <# } #> 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /ZString.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32901.215 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{175A1317-7622-4CC3-9553-1E9E908FF085}" 7 | ProjectSection(SolutionItems) = preProject 8 | .gitignore = .gitignore 9 | .circleci\config.yml = .circleci\config.yml 10 | LICENSE = LICENSE 11 | README.md = README.md 12 | EndProjectSection 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B385367D-2EB5-49B3-A3EF-922151EC1904}" 15 | EndProject 16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sandbox", "sandbox", "{A7D7AA7D-9A79-48A8-978D-0C98EBD81ED0}" 17 | EndProject 18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0803618F-C4E8-4D37-831E-5D26C5574F49}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZString", "src\ZString\ZString.csproj", "{7B09D422-D19A-457E-ADA0-4CDC2DC581BB}" 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp", "sandbox\ConsoleApp\ConsoleApp.csproj", "{9ADF67E1-1872-43D3-882E-607071726FE7}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZString.Tests", "tests\ZString.Tests\ZString.Tests.csproj", "{62090C00-9727-4375-BE40-ABE2F4D41571}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PerfBenchmark", "sandbox\PerfBenchmark\PerfBenchmark.csproj", "{D766AEB3-3609-4F1D-8D81-5549F748F372}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | Debug|Any CPU = Debug|Any CPU 31 | Release|Any CPU = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {7B09D422-D19A-457E-ADA0-4CDC2DC581BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {7B09D422-D19A-457E-ADA0-4CDC2DC581BB}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {7B09D422-D19A-457E-ADA0-4CDC2DC581BB}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {7B09D422-D19A-457E-ADA0-4CDC2DC581BB}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {9ADF67E1-1872-43D3-882E-607071726FE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {9ADF67E1-1872-43D3-882E-607071726FE7}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {9ADF67E1-1872-43D3-882E-607071726FE7}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {9ADF67E1-1872-43D3-882E-607071726FE7}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {62090C00-9727-4375-BE40-ABE2F4D41571}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {62090C00-9727-4375-BE40-ABE2F4D41571}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {62090C00-9727-4375-BE40-ABE2F4D41571}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {62090C00-9727-4375-BE40-ABE2F4D41571}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {D766AEB3-3609-4F1D-8D81-5549F748F372}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {D766AEB3-3609-4F1D-8D81-5549F748F372}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {D766AEB3-3609-4F1D-8D81-5549F748F372}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {D766AEB3-3609-4F1D-8D81-5549F748F372}.Release|Any CPU.Build.0 = Release|Any CPU 50 | EndGlobalSection 51 | GlobalSection(SolutionProperties) = preSolution 52 | HideSolutionNode = FALSE 53 | EndGlobalSection 54 | GlobalSection(NestedProjects) = preSolution 55 | {7B09D422-D19A-457E-ADA0-4CDC2DC581BB} = {B385367D-2EB5-49B3-A3EF-922151EC1904} 56 | {9ADF67E1-1872-43D3-882E-607071726FE7} = {A7D7AA7D-9A79-48A8-978D-0C98EBD81ED0} 57 | {62090C00-9727-4375-BE40-ABE2F4D41571} = {0803618F-C4E8-4D37-831E-5D26C5574F49} 58 | {D766AEB3-3609-4F1D-8D81-5549F748F372} = {A7D7AA7D-9A79-48A8-978D-0C98EBD81ED0} 59 | EndGlobalSection 60 | GlobalSection(ExtensibilityGlobals) = postSolution 61 | SolutionGuid = {DF39BF43-3E0E-4F7D-9943-7E50D301234D} 62 | EndGlobalSection 63 | EndGlobal 64 | -------------------------------------------------------------------------------- /tests/ZString.Tests/ReplaceTest.cs: -------------------------------------------------------------------------------- 1 | using Cysharp.Text; 2 | using FluentAssertions; 3 | using System.Text; 4 | using Xunit; 5 | 6 | namespace ZStringTests 7 | { 8 | public class ReplaceTest 9 | { 10 | 11 | [Fact] 12 | public void ReplaceAtCharTest() 13 | { 14 | var s = new string(' ', 10); 15 | using (var zsb = ZString.CreateStringBuilder()) 16 | { 17 | zsb.Append(s); 18 | zsb.ReplaceAt('-',2); 19 | zsb.ToString().Should().Be(new StringBuilder(s) { [2] = '-'}.ToString()); 20 | } 21 | } 22 | 23 | [Fact] 24 | public void ReplaceCharTest() 25 | { 26 | var s = new string(' ', 10); 27 | using (var zsb = ZString.CreateStringBuilder()) 28 | { 29 | zsb.Append(s); 30 | zsb.Replace(' ', '-', 2, 5); 31 | zsb.ToString().Should().Be(new StringBuilder(s).Replace(' ', '-', 2, 5).ToString()); 32 | } 33 | 34 | s = "0"; 35 | using (var zsb = ZString.CreateStringBuilder()) 36 | { 37 | zsb.Append(s); 38 | zsb.Replace('0', '1'); 39 | zsb.ToString().Should().Be(new StringBuilder(s).Replace('0', '1').ToString()); 40 | } 41 | } 42 | 43 | [Fact] 44 | public void ReplaceStringTest() 45 | { 46 | using (var zsb = ZString.CreateStringBuilder(notNested: true)) 47 | { 48 | var text = "bra bra BRA bra bra"; 49 | zsb.Append(text); 50 | var bcl = new StringBuilder(text); 51 | 52 | zsb.Replace("bra", null, 1, text.Length - 2); 53 | bcl.Replace("bra", null, 1, text.Length - 2); 54 | 55 | // "bra BRA bra" 56 | zsb.ToString().Should().Be(bcl.ToString()); 57 | } 58 | 59 | using (var zsb = ZString.CreateStringBuilder(notNested: true)) 60 | { 61 | var text = "num num num"; 62 | zsb.Append(text); 63 | var bcl = new StringBuilder(text); 64 | 65 | // over DefaultBufferSize 66 | zsb.Replace("num", new string('1', 32768), 1, text.Length - 2); 67 | bcl.Replace("num", new string('1', 32768), 1, text.Length - 2); 68 | 69 | zsb.ToString().Should().Be(bcl.ToString()); 70 | } 71 | 72 | using (var zsb = ZString.CreateStringBuilder()) 73 | { 74 | var text = "The quick brown dog jumps over the lazy cat."; 75 | zsb.Append(text); 76 | var bcl = new StringBuilder(text); 77 | 78 | // All "cat" -> "dog" 79 | zsb.Replace("cat", "dog"); 80 | bcl.Replace("cat", "dog"); 81 | zsb.ToString().Should().Be(bcl.ToString()); 82 | 83 | // Some "dog" -> "fox" 84 | zsb.Replace("dog", "fox", 15, 20); 85 | bcl.Replace("dog", "fox", 15, 20); 86 | zsb.ToString().Should().Be(bcl.ToString()); 87 | } 88 | } 89 | 90 | [Fact] 91 | public void NotMatchTest() 92 | { 93 | using (var zsb = ZString.CreateStringBuilder(notNested: true)) 94 | { 95 | var text = "The quick brown dog jumps over the lazy cat."; 96 | zsb.Append(text); 97 | zsb.Replace("pig", "dog"); 98 | zsb.ToString().Should().Be(text); 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /tests/ZString.Tests/NestedStringBuilder.cs: -------------------------------------------------------------------------------- 1 | using Cysharp.Text; 2 | using FluentAssertions; 3 | using FluentAssertions.Common; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using Xunit; 9 | 10 | namespace ZStringTests 11 | { 12 | public class NestedStringBuilder 13 | { 14 | [Fact] 15 | public void NotNestedUtf16() 16 | { 17 | using (_ = ZString.CreateStringBuilder(true)) 18 | { 19 | } 20 | using (_ = ZString.CreateStringBuilder(false)) 21 | { 22 | using (_ = ZString.CreateStringBuilder(true)) 23 | { 24 | using (_ = ZString.CreateStringBuilder(false)) 25 | { 26 | } 27 | } 28 | } 29 | } 30 | 31 | [Fact] 32 | public void NestedUtf16() 33 | { 34 | using (_ = ZString.CreateStringBuilder(true)) 35 | { 36 | using (_ = ZString.CreateStringBuilder(false)) 37 | { 38 | Assert.Throws(() => 39 | { 40 | using (_ = ZString.CreateStringBuilder(true)) 41 | { 42 | } 43 | } 44 | ); 45 | } 46 | } 47 | } 48 | 49 | [Fact] 50 | public void NotDisposedUtf16() 51 | { 52 | { 53 | _ = ZString.CreateStringBuilder(true); 54 | } 55 | { 56 | Assert.Throws(() => 57 | { 58 | using (_ = ZString.CreateStringBuilder(true)) 59 | { 60 | } 61 | } 62 | ); 63 | } 64 | Utf16ValueStringBuilder.scratchBufferUsed.IsSameOrEqualTo(true); 65 | Utf16ValueStringBuilder.scratchBufferUsed = false; 66 | } 67 | 68 | [Fact] 69 | public void NotNestedUtf8() 70 | { 71 | using (_ = ZString.CreateUtf8StringBuilder(true)) 72 | { 73 | } 74 | using (_ = ZString.CreateUtf8StringBuilder(false)) 75 | { 76 | using (_ = ZString.CreateUtf8StringBuilder(true)) 77 | { 78 | using (_ = ZString.CreateUtf8StringBuilder(false)) 79 | { 80 | } 81 | } 82 | } 83 | } 84 | 85 | [Fact] 86 | public void NestedUtf8() 87 | { 88 | using (_ = ZString.CreateUtf8StringBuilder(true)) 89 | { 90 | using (_ = ZString.CreateUtf8StringBuilder(false)) 91 | { 92 | Assert.Throws(() => 93 | { 94 | using (_ = ZString.CreateUtf8StringBuilder(true)) 95 | { 96 | } 97 | } 98 | ); 99 | } 100 | } 101 | } 102 | 103 | [Fact] 104 | public void NotDisposedUtf8() 105 | { 106 | { 107 | _ = ZString.CreateUtf8StringBuilder(true); 108 | } 109 | { 110 | Assert.Throws(() => 111 | { 112 | using (_ = ZString.CreateUtf8StringBuilder(true)) 113 | { 114 | } 115 | } 116 | ); 117 | } 118 | Utf8ValueStringBuilder.scratchBufferUsed.IsSameOrEqualTo(true); 119 | Utf8ValueStringBuilder.scratchBufferUsed = false; 120 | } 121 | 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /sandbox/ConsoleAppNet472/ConsoleAppNet472.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {BE8A17AA-504A-410D-B86D-92431B0F5594} 8 | Exe 9 | ConsoleAppNet472 10 | ConsoleAppNet472 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | true 16 | ../../opensource.snk 17 | 18 | 19 | AnyCPU 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | 28 | 29 | AnyCPU 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | ..\..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll 41 | 42 | 43 | 44 | ..\..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll 45 | 46 | 47 | 48 | ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll 49 | 50 | 51 | ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.7.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | {7b09d422-d19a-457e-ada0-4cdc2dc581bb} 71 | ZString 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/ZString/Number/FormattingHelpers.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Numerics; 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace System.Buffers.Text 10 | { 11 | internal static partial class FormattingHelpers 12 | { 13 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 14 | public static int CountDigits(ulong value) 15 | { 16 | int digits = 1; 17 | uint part; 18 | if (value >= 10000000) 19 | { 20 | if (value >= 100000000000000) 21 | { 22 | part = (uint)(value / 100000000000000); 23 | digits += 14; 24 | } 25 | else 26 | { 27 | part = (uint)(value / 10000000); 28 | digits += 7; 29 | } 30 | } 31 | else 32 | { 33 | part = (uint)value; 34 | } 35 | 36 | if (part < 10) 37 | { 38 | // no-op 39 | } 40 | else if (part < 100) 41 | { 42 | digits++; 43 | } 44 | else if (part < 1000) 45 | { 46 | digits += 2; 47 | } 48 | else if (part < 10000) 49 | { 50 | digits += 3; 51 | } 52 | else if (part < 100000) 53 | { 54 | digits += 4; 55 | } 56 | else if (part < 1000000) 57 | { 58 | digits += 5; 59 | } 60 | else 61 | { 62 | Debug.Assert(part < 10000000); 63 | digits += 6; 64 | } 65 | 66 | return digits; 67 | } 68 | 69 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 70 | public static int CountDigits(uint value) 71 | { 72 | int digits = 1; 73 | if (value >= 100000) 74 | { 75 | value /= 100000; 76 | digits += 5; 77 | } 78 | 79 | if (value < 10) 80 | { 81 | // no-op 82 | } 83 | else if (value < 100) 84 | { 85 | digits++; 86 | } 87 | else if (value < 1000) 88 | { 89 | digits += 2; 90 | } 91 | else if (value < 10000) 92 | { 93 | digits += 3; 94 | } 95 | else 96 | { 97 | Debug.Assert(value < 100000); 98 | digits += 4; 99 | } 100 | 101 | return digits; 102 | } 103 | 104 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 105 | public static int CountHexDigits(ulong value) 106 | { 107 | return (64 - BitOperations.LeadingZeroCount(value | 1) + 3) >> 2; 108 | } 109 | 110 | // Counts the number of trailing '0' digits in a decimal number. 111 | // e.g., value = 0 => retVal = 0, valueWithoutTrailingZeros = 0 112 | // value = 1234 => retVal = 0, valueWithoutTrailingZeros = 1234 113 | // value = 320900 => retVal = 2, valueWithoutTrailingZeros = 3209 114 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 115 | public static int CountDecimalTrailingZeros(uint value, out uint valueWithoutTrailingZeros) 116 | { 117 | int zeroCount = 0; 118 | 119 | if (value != 0) 120 | { 121 | while (true) 122 | { 123 | uint temp = value / 10; 124 | if (value != (temp * 10)) 125 | { 126 | break; 127 | } 128 | 129 | value = temp; 130 | zeroCount++; 131 | } 132 | } 133 | 134 | valueWithoutTrailingZeros = value; 135 | return zeroCount; 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/FormattingHelpers.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Numerics; 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace System.Buffers.Text 10 | { 11 | internal static partial class FormattingHelpers 12 | { 13 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 14 | public static int CountDigits(ulong value) 15 | { 16 | int digits = 1; 17 | uint part; 18 | if (value >= 10000000) 19 | { 20 | if (value >= 100000000000000) 21 | { 22 | part = (uint)(value / 100000000000000); 23 | digits += 14; 24 | } 25 | else 26 | { 27 | part = (uint)(value / 10000000); 28 | digits += 7; 29 | } 30 | } 31 | else 32 | { 33 | part = (uint)value; 34 | } 35 | 36 | if (part < 10) 37 | { 38 | // no-op 39 | } 40 | else if (part < 100) 41 | { 42 | digits++; 43 | } 44 | else if (part < 1000) 45 | { 46 | digits += 2; 47 | } 48 | else if (part < 10000) 49 | { 50 | digits += 3; 51 | } 52 | else if (part < 100000) 53 | { 54 | digits += 4; 55 | } 56 | else if (part < 1000000) 57 | { 58 | digits += 5; 59 | } 60 | else 61 | { 62 | Debug.Assert(part < 10000000); 63 | digits += 6; 64 | } 65 | 66 | return digits; 67 | } 68 | 69 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 70 | public static int CountDigits(uint value) 71 | { 72 | int digits = 1; 73 | if (value >= 100000) 74 | { 75 | value /= 100000; 76 | digits += 5; 77 | } 78 | 79 | if (value < 10) 80 | { 81 | // no-op 82 | } 83 | else if (value < 100) 84 | { 85 | digits++; 86 | } 87 | else if (value < 1000) 88 | { 89 | digits += 2; 90 | } 91 | else if (value < 10000) 92 | { 93 | digits += 3; 94 | } 95 | else 96 | { 97 | Debug.Assert(value < 100000); 98 | digits += 4; 99 | } 100 | 101 | return digits; 102 | } 103 | 104 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 105 | public static int CountHexDigits(ulong value) 106 | { 107 | return (64 - BitOperations.LeadingZeroCount(value | 1) + 3) >> 2; 108 | } 109 | 110 | // Counts the number of trailing '0' digits in a decimal number. 111 | // e.g., value = 0 => retVal = 0, valueWithoutTrailingZeros = 0 112 | // value = 1234 => retVal = 0, valueWithoutTrailingZeros = 1234 113 | // value = 320900 => retVal = 2, valueWithoutTrailingZeros = 3209 114 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 115 | public static int CountDecimalTrailingZeros(uint value, out uint valueWithoutTrailingZeros) 116 | { 117 | int zeroCount = 0; 118 | 119 | if (value != 0) 120 | { 121 | while (true) 122 | { 123 | uint temp = value / 10; 124 | if (value != (temp * 10)) 125 | { 126 | break; 127 | } 128 | 129 | value = temp; 130 | zeroCount++; 131 | } 132 | } 133 | 134 | valueWithoutTrailingZeros = value; 135 | return zeroCount; 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /src/ZString/FormatHelper.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="T4Common.t4" once="true" #> 8 | using System; 9 | using System.Text; 10 | using System.Buffers; 11 | using System.Runtime.CompilerServices; 12 | 13 | namespace Cysharp.Text 14 | { 15 | <# foreach(var utf in utfTypes ) { var isUtf16 = (utf == "Utf16"); var elemType = isUtf16 ? "char" : "byte"; #> 16 | internal static partial class <#= utf #>FormatHelper 17 | { 18 | const <#= elemType #> sp = (<#= elemType #>)' '; 19 | 20 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 21 | public static void FormatTo(ref TBufferWriter sb, T arg, int width, <#= isUtf16 ? "ReadOnlySpan" : "StandardFormat" #> format, string argName) 22 | where TBufferWriter : IBufferWriter<<#= elemType #>> 23 | { 24 | if (width <= 0) // leftJustify 25 | { 26 | var span = sb.GetSpan(0); 27 | if (!<#= utf #>ValueStringBuilder.FormatterCache.TryFormatDelegate(arg, span, out var argWritten, format)) 28 | { 29 | sb.Advance(0); 30 | span = sb.GetSpan(Math.Max(span.Length + 1, argWritten)); 31 | if (!<#= utf #>ValueStringBuilder.FormatterCache.TryFormatDelegate(arg, span, out argWritten, format)) 32 | { 33 | ExceptionUtil.ThrowArgumentException(argName); 34 | } 35 | } 36 | sb.Advance(argWritten); 37 | 38 | width *= -1; 39 | int padding = width - argWritten; 40 | if (width > 0 && padding > 0) 41 | { 42 | var paddingSpan = sb.GetSpan(padding); 43 | paddingSpan.Fill(sp); 44 | sb.Advance(padding); 45 | } 46 | } 47 | else 48 | { 49 | FormatToRightJustify(ref sb, arg, width, format, argName); 50 | } 51 | } 52 | 53 | private static void FormatToRightJustify(ref TBufferWriter sb, T arg, int width, <#= isUtf16 ? "ReadOnlySpan" : "StandardFormat" #> format, string argName) 54 | where TBufferWriter : IBufferWriter<<#= elemType #>> 55 | { 56 | if (typeof(T) == typeof(string)) 57 | { 58 | var s = Unsafe.As(arg); 59 | int padding = width - s.Length; 60 | if (padding > 0) 61 | { 62 | var paddingSpan = sb.GetSpan(padding); 63 | paddingSpan.Fill(sp); 64 | sb.Advance(padding); 65 | } 66 | 67 | <# if(isUtf16) { #> 68 | var span = sb.GetSpan(s.Length); 69 | s.AsSpan().CopyTo(span); 70 | sb.Advance(s.Length); 71 | <# }else { #> 72 | ZString.AppendChars(ref sb, s.AsSpan()); 73 | <# } #> 74 | } 75 | else 76 | { 77 | Span<<#= elemType #>> s = stackalloc <#= elemType #>[typeof(T).IsValueType ? Unsafe.SizeOf() * 8 : 1024]; 78 | 79 | if (!<#= utf #>ValueStringBuilder.FormatterCache.TryFormatDelegate(arg, s, out var charsWritten, format)) 80 | { 81 | s = stackalloc <#= elemType #>[s.Length * 2]; 82 | if (!<#= utf #>ValueStringBuilder.FormatterCache.TryFormatDelegate(arg, s, out charsWritten, format)) 83 | { 84 | ExceptionUtil.ThrowArgumentException(argName); 85 | } 86 | } 87 | 88 | int padding = width - charsWritten; 89 | if (padding > 0) 90 | { 91 | var paddingSpan = sb.GetSpan(padding); 92 | paddingSpan.Fill(sp); 93 | sb.Advance(padding); 94 | } 95 | 96 | var span = sb.GetSpan(charsWritten); 97 | s.CopyTo(span); 98 | sb.Advance(charsWritten); 99 | } 100 | } 101 | } 102 | 103 | <# } // foreach(utf) #> 104 | } -------------------------------------------------------------------------------- /src/ZString/ZString.Utf8Format.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".cs" #> 7 | <#@ include file="T4Common.t4" once="true" #> 8 | using System; 9 | using System.Buffers; 10 | using System.Runtime.CompilerServices; 11 | 12 | using static Cysharp.Text.Utf8ValueStringBuilder; 13 | 14 | namespace Cysharp.Text 15 | { 16 | public static partial class ZString 17 | { 18 | <# for(var i = 1; i <= TypeParamMax; i++) { #> 19 | /// Replaces one or more format items in a string with the string representation of some specified values. 20 | public static void Utf8Format<<#= CreateTypeArgument(i) #>>(IBufferWriter bufferWriter, string format, <#= CreateParameters(i) #>) 21 | { 22 | if (format == null) 23 | { 24 | throw new ArgumentNullException(nameof(format)); 25 | } 26 | 27 | var copyFrom = 0; 28 | for (int i = 0; i < format.Length; i++) 29 | { 30 | var c = format[i]; 31 | if (c == '{') 32 | { 33 | // escape. 34 | if (i == format.Length - 1) 35 | { 36 | throw new FormatException("invalid format"); 37 | } 38 | 39 | if (i != format.Length && format[i + 1] == '{') 40 | { 41 | var size = i - copyFrom; 42 | var buffer = bufferWriter.GetSpan(UTF8NoBom.GetMaxByteCount(size)); 43 | var written = UTF8NoBom.GetBytes(format.AsSpan(copyFrom, size), buffer); 44 | bufferWriter.Advance(written); 45 | i = i + 1; // skip escaped '{' 46 | copyFrom = i; 47 | continue; 48 | } 49 | else 50 | { 51 | var size = i - copyFrom; 52 | var buffer = bufferWriter.GetSpan(UTF8NoBom.GetMaxByteCount(size)); 53 | var written = UTF8NoBom.GetBytes(format.AsSpan(copyFrom, size), buffer); 54 | bufferWriter.Advance(written); 55 | } 56 | 57 | // try to find range 58 | var indexParse = FormatParser.Parse(format, i); 59 | copyFrom = indexParse.LastIndex; 60 | i = indexParse.LastIndex - 1; 61 | var writeFormat = StandardFormat.Parse(indexParse.FormatString); 62 | switch (indexParse.Index) 63 | { 64 | <# for(var j = 0; j < i; j++) { #> 65 | case <#= j #>: 66 | Utf8FormatHelper.FormatTo(ref bufferWriter, arg<#= j + 1 #>, indexParse.Alignment, writeFormat, nameof(arg<#= j + 1 #>)); 67 | continue; 68 | <# } #> 69 | default: 70 | ExceptionUtil.ThrowFormatException(); 71 | break; 72 | } 73 | 74 | ExceptionUtil.ThrowFormatException(); 75 | } 76 | else if (c == '}') 77 | { 78 | if (i + 1 < format.Length && format[i + 1] == '}') 79 | { 80 | var size = i - copyFrom; 81 | var buffer = bufferWriter.GetSpan(UTF8NoBom.GetMaxByteCount(size)); 82 | var written = UTF8NoBom.GetBytes(format.AsSpan(copyFrom, size), buffer); 83 | bufferWriter.Advance(written); 84 | i = i + 1; // skip escaped '}' 85 | copyFrom = i; 86 | continue; 87 | } 88 | else 89 | { 90 | ExceptionUtil.ThrowFormatException(); 91 | } 92 | } 93 | } 94 | 95 | { 96 | // copy final string 97 | var copyLength = format.Length - copyFrom; 98 | if (copyLength > 0) 99 | { 100 | var buffer = bufferWriter.GetSpan(UTF8NoBom.GetMaxByteCount(copyLength)); 101 | var written = UTF8NoBom.GetBytes(format.AsSpan(copyFrom, copyLength), buffer); 102 | bufferWriter.Advance(written); 103 | } 104 | } 105 | } 106 | <# } #> 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /.github/workflows/build-release.yaml: -------------------------------------------------------------------------------- 1 | name: Build-Release 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | tag: 7 | description: "tag: git tag you want create. (sample 1.0.0)" 8 | required: true 9 | dry-run: 10 | description: "dry-run: true will never create relase/nuget." 11 | required: true 12 | default: false 13 | type: boolean 14 | 15 | jobs: 16 | update-packagejson: 17 | permissions: 18 | actions: read 19 | contents: write 20 | uses: Cysharp/Actions/.github/workflows/update-packagejson.yaml@main 21 | with: 22 | file-path: ./src/ZString.Unity/Assets/Scripts/ZString/package.json 23 | tag: ${{ inputs.tag }} 24 | dry-run: ${{ inputs.dry-run }} 25 | 26 | build-dotnet: 27 | needs: [update-packagejson] 28 | permissions: 29 | contents: read 30 | runs-on: ubuntu-24.04 31 | timeout-minutes: 10 32 | steps: 33 | - run: echo ${{ needs.update-packagejson.outputs.sha }} 34 | - uses: Cysharp/Actions/.github/actions/checkout@main 35 | with: 36 | ref: ${{ needs.update-packagejson.outputs.sha }} 37 | - uses: Cysharp/Actions/.github/actions/setup-dotnet@main 38 | # pack nuget 39 | - run: dotnet build -c Release -p:Version=${{ inputs.tag }} 40 | - run: dotnet test tests/ZString.Tests -c Release --no-build 41 | - run: dotnet pack -c Release --no-build -p:Version=${{ inputs.tag }} -o ./publish 42 | # Store artifacts. 43 | - uses: Cysharp/Actions/.github/actions/upload-artifact@main 44 | with: 45 | name: nuget 46 | path: ./publish/ 47 | retention-days: 1 48 | 49 | build-unity: 50 | needs: [update-packagejson] 51 | strategy: 52 | matrix: 53 | unity: ["2021.3.41f1"] 54 | permissions: 55 | contents: read 56 | runs-on: ubuntu-24.04 57 | timeout-minutes: 15 58 | steps: 59 | - name: Load secrets 60 | id: op-load-secret 61 | uses: 1password/load-secrets-action@581a835fb51b8e7ec56b71cf2ffddd7e68bb25e0 # v2.0.0 62 | with: 63 | export-env: false 64 | env: 65 | OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN_PUBLIC }} 66 | UNITY_EMAIL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/username" 67 | UNITY_PASSWORD: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/credential" 68 | UNITY_SERIAL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/serial" 69 | 70 | - uses: Cysharp/Actions/.github/actions/checkout@main 71 | with: 72 | ref: ${{ needs.update-packagejson.outputs.sha }} 73 | # Execute scripts: Export Package 74 | # /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export 75 | - name: Build Unity (.unitypacakge) 76 | uses: Cysharp/Actions/.github/actions/unity-builder@main 77 | env: 78 | UNITY_EMAIL: ${{ steps.op-load-secret.outputs.UNITY_EMAIL }} 79 | UNITY_PASSWORD: ${{ steps.op-load-secret.outputs.UNITY_PASSWORD }} 80 | UNITY_SERIAL: ${{ steps.op-load-secret.outputs.UNITY_SERIAL }} 81 | UNITY_PACKAGE_VERSION: ${{ inputs.tag }} 82 | with: 83 | projectPath: src/ZString.Unity 84 | unityVersion: ${{ matrix.unity }} 85 | targetPlatform: StandaloneLinux64 86 | buildMethod: PackageExporter.Export 87 | 88 | - uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files 89 | with: 90 | directory: src/ZString.Unity 91 | 92 | # Store artifacts. 93 | - uses: Cysharp/Actions/.github/actions/upload-artifact@main 94 | with: 95 | name: ZString.Unity.${{ inputs.tag }}.unitypackage 96 | path: ./src/ZString.Unity/ZString.Unity.${{ inputs.tag }}.unitypackage 97 | retention-days: 1 98 | 99 | create-release: 100 | needs: [update-packagejson, build-dotnet, build-unity] 101 | permissions: 102 | contents: write 103 | id-token: write # required for NuGet Trusted Publish 104 | uses: Cysharp/Actions/.github/workflows/create-release.yaml@main 105 | with: 106 | commit-id: ${{ needs.update-packagejson.outputs.sha }} 107 | tag: ${{ inputs.tag }} 108 | dry-run: ${{ inputs.dry-run }} 109 | nuget-push: true 110 | release-upload: true 111 | release-asset-path: ./ZString.Unity.${{ inputs.tag }}.unitypackage/ZString.Unity.${{ inputs.tag }}.unitypackage 112 | secrets: inherit 113 | 114 | cleanup: 115 | if: ${{ needs.update-packagejson.outputs.is-branch-created == 'true' }} 116 | needs: [update-packagejson, build-dotnet, build-unity] 117 | permissions: 118 | contents: write 119 | uses: Cysharp/Actions/.github/workflows/clean-packagejson-branch.yaml@main 120 | with: 121 | branch: ${{ needs.update-packagejson.outputs.branch-name }} 122 | -------------------------------------------------------------------------------- /src/ZString/Number/Number.NumberBuffer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Runtime.CompilerServices; 7 | using System.Text; 8 | 9 | namespace System 10 | { 11 | internal static partial class Number 12 | { 13 | // We need 1 additional byte, per length, for the terminating null 14 | internal const int DecimalNumberBufferLength = 29 + 1 + 1; // 29 for the longest input + 1 for rounding 15 | internal const int DoubleNumberBufferLength = 767 + 1 + 1; // 767 for the longest input + 1 for rounding: 4.9406564584124654E-324 16 | internal const int Int32NumberBufferLength = 10 + 1; // 10 for the longest input: 2,147,483,647 17 | internal const int Int64NumberBufferLength = 19 + 1; // 19 for the longest input: 9,223,372,036,854,775,807 18 | internal const int SingleNumberBufferLength = 112 + 1 + 1; // 112 for the longest input + 1 for rounding: 1.40129846E-45 19 | internal const int UInt32NumberBufferLength = 10 + 1; // 10 for the longest input: 4,294,967,295 20 | internal const int UInt64NumberBufferLength = 20 + 1; // 20 for the longest input: 18,446,744,073,709,551,615 21 | 22 | internal unsafe ref struct NumberBuffer 23 | { 24 | public int DigitsCount; 25 | public int Scale; 26 | public bool IsNegative; 27 | public bool HasNonZeroTail; 28 | public NumberBufferKind Kind; 29 | public Span Digits; 30 | 31 | public NumberBuffer(NumberBufferKind kind, byte* digits, int digitsLength) 32 | { 33 | Debug.Assert(digits != null); 34 | Debug.Assert(digitsLength > 0); 35 | 36 | DigitsCount = 0; 37 | Scale = 0; 38 | IsNegative = false; 39 | HasNonZeroTail = false; 40 | Kind = kind; 41 | Digits = new Span(digits, digitsLength); 42 | 43 | #if DEBUG 44 | Digits.Fill(0xCC); 45 | #endif 46 | 47 | Digits[0] = (byte)('\0'); 48 | CheckConsistency(); 49 | } 50 | 51 | [Conditional("DEBUG")] 52 | public void CheckConsistency() 53 | { 54 | #if DEBUG 55 | Debug.Assert((Kind == NumberBufferKind.Integer) || (Kind == NumberBufferKind.Decimal) || (Kind == NumberBufferKind.FloatingPoint)); 56 | Debug.Assert(Digits[0] != '0', "Leading zeros should never be stored in a Number"); 57 | 58 | int numDigits; 59 | for (numDigits = 0; numDigits < Digits.Length; numDigits++) 60 | { 61 | byte digit = Digits[numDigits]; 62 | 63 | if (digit == 0) 64 | { 65 | break; 66 | } 67 | 68 | Debug.Assert((digit >= '0') && (digit <= '9'), "Unexpected character found in Number"); 69 | } 70 | 71 | Debug.Assert(numDigits == DigitsCount, "Null terminator found in unexpected location in Number"); 72 | Debug.Assert(numDigits < Digits.Length, "Null terminator not found in Number"); 73 | #endif // DEBUG 74 | } 75 | 76 | public byte* GetDigitsPointer() 77 | { 78 | // This is safe to do since we are a ref struct 79 | return (byte*)(Unsafe.AsPointer(ref Digits[0])); 80 | } 81 | 82 | // 83 | // Code coverage note: This only exists so that Number displays nicely in the VS watch window. So yes, I know it works. 84 | // 85 | public override string ToString() 86 | { 87 | StringBuilder sb = new StringBuilder(); 88 | 89 | sb.Append('['); 90 | sb.Append('"'); 91 | 92 | for (int i = 0; i < Digits.Length; i++) 93 | { 94 | byte digit = Digits[i]; 95 | 96 | if (digit == 0) 97 | { 98 | break; 99 | } 100 | 101 | sb.Append((char)(digit)); 102 | } 103 | 104 | sb.Append('"'); 105 | sb.Append(", Length = ").Append(DigitsCount); 106 | sb.Append(", Scale = ").Append(Scale); 107 | sb.Append(", IsNegative = ").Append(IsNegative); 108 | sb.Append(", HasNonZeroTail = ").Append(HasNonZeroTail); 109 | sb.Append(", Kind = ").Append(Kind); 110 | sb.Append(']'); 111 | 112 | return sb.ToString(); 113 | } 114 | } 115 | 116 | internal enum NumberBufferKind : byte 117 | { 118 | Unknown = 0, 119 | Integer = 1, 120 | Decimal = 2, 121 | FloatingPoint = 3, 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /src/ZString.Unity/Assets/Scripts/ZString/Number/Number.NumberBuffer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Runtime.CompilerServices; 7 | using System.Text; 8 | 9 | namespace System 10 | { 11 | internal static partial class Number 12 | { 13 | // We need 1 additional byte, per length, for the terminating null 14 | internal const int DecimalNumberBufferLength = 29 + 1 + 1; // 29 for the longest input + 1 for rounding 15 | internal const int DoubleNumberBufferLength = 767 + 1 + 1; // 767 for the longest input + 1 for rounding: 4.9406564584124654E-324 16 | internal const int Int32NumberBufferLength = 10 + 1; // 10 for the longest input: 2,147,483,647 17 | internal const int Int64NumberBufferLength = 19 + 1; // 19 for the longest input: 9,223,372,036,854,775,807 18 | internal const int SingleNumberBufferLength = 112 + 1 + 1; // 112 for the longest input + 1 for rounding: 1.40129846E-45 19 | internal const int UInt32NumberBufferLength = 10 + 1; // 10 for the longest input: 4,294,967,295 20 | internal const int UInt64NumberBufferLength = 20 + 1; // 20 for the longest input: 18,446,744,073,709,551,615 21 | 22 | internal unsafe ref struct NumberBuffer 23 | { 24 | public int DigitsCount; 25 | public int Scale; 26 | public bool IsNegative; 27 | public bool HasNonZeroTail; 28 | public NumberBufferKind Kind; 29 | public Span Digits; 30 | 31 | public NumberBuffer(NumberBufferKind kind, byte* digits, int digitsLength) 32 | { 33 | Debug.Assert(digits != null); 34 | Debug.Assert(digitsLength > 0); 35 | 36 | DigitsCount = 0; 37 | Scale = 0; 38 | IsNegative = false; 39 | HasNonZeroTail = false; 40 | Kind = kind; 41 | Digits = new Span(digits, digitsLength); 42 | 43 | #if DEBUG 44 | Digits.Fill(0xCC); 45 | #endif 46 | 47 | Digits[0] = (byte)('\0'); 48 | CheckConsistency(); 49 | } 50 | 51 | [Conditional("DEBUG")] 52 | public void CheckConsistency() 53 | { 54 | #if DEBUG 55 | Debug.Assert((Kind == NumberBufferKind.Integer) || (Kind == NumberBufferKind.Decimal) || (Kind == NumberBufferKind.FloatingPoint)); 56 | Debug.Assert(Digits[0] != '0', "Leading zeros should never be stored in a Number"); 57 | 58 | int numDigits; 59 | for (numDigits = 0; numDigits < Digits.Length; numDigits++) 60 | { 61 | byte digit = Digits[numDigits]; 62 | 63 | if (digit == 0) 64 | { 65 | break; 66 | } 67 | 68 | Debug.Assert((digit >= '0') && (digit <= '9'), "Unexpected character found in Number"); 69 | } 70 | 71 | Debug.Assert(numDigits == DigitsCount, "Null terminator found in unexpected location in Number"); 72 | Debug.Assert(numDigits < Digits.Length, "Null terminator not found in Number"); 73 | #endif // DEBUG 74 | } 75 | 76 | public byte* GetDigitsPointer() 77 | { 78 | // This is safe to do since we are a ref struct 79 | return (byte*)(Unsafe.AsPointer(ref Digits[0])); 80 | } 81 | 82 | // 83 | // Code coverage note: This only exists so that Number displays nicely in the VS watch window. So yes, I know it works. 84 | // 85 | public override string ToString() 86 | { 87 | StringBuilder sb = new StringBuilder(); 88 | 89 | sb.Append('['); 90 | sb.Append('"'); 91 | 92 | for (int i = 0; i < Digits.Length; i++) 93 | { 94 | byte digit = Digits[i]; 95 | 96 | if (digit == 0) 97 | { 98 | break; 99 | } 100 | 101 | sb.Append((char)(digit)); 102 | } 103 | 104 | sb.Append('"'); 105 | sb.Append(", Length = ").Append(DigitsCount); 106 | sb.Append(", Scale = ").Append(Scale); 107 | sb.Append(", IsNegative = ").Append(IsNegative); 108 | sb.Append(", HasNonZeroTail = ").Append(HasNonZeroTail); 109 | sb.Append(", Kind = ").Append(Kind); 110 | sb.Append(']'); 111 | 112 | return sb.ToString(); 113 | } 114 | } 115 | 116 | internal enum NumberBufferKind : byte 117 | { 118 | Unknown = 0, 119 | Integer = 1, 120 | Decimal = 2, 121 | FloatingPoint = 3, 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /sandbox/BenchmarkVsReleasedVersion/FormatBenchmark.cs: -------------------------------------------------------------------------------- 1 | // Before use, You must change AssemblyName to "NewZString" of local ZString.csproj 2 | 3 | extern alias NewZString; 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using Cysharp.Text; 9 | using NZString = NewZString::Cysharp.Text.ZString; 10 | using BenchmarkDotNet.Attributes; 11 | using BenchmarkDotNet.Configs; 12 | 13 | namespace BenchmarkVsReleasedVersion 14 | { 15 | [Config(typeof(BenchmarkConfig))] 16 | [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] 17 | [DisassemblyDiagnoser(maxDepth:3)] 18 | public class FormatBenchmark 19 | { 20 | int x; 21 | int y; 22 | 23 | Utf16PreparedFormat _utf16preparedFormat_; 24 | NewZString::Cysharp.Text.Utf16PreparedFormat _utf16preparedFormatN; 25 | 26 | Utf8PreparedFormat _utf8preparedFormat_; 27 | NewZString::Cysharp.Text.Utf8PreparedFormat _utf8preparedFormatN; 28 | 29 | [Params( 30 | "x:{0}, y:{1}", 31 | "This is a test to see how{0} well {1}this does. Hello, world." 32 | )] 33 | public string FormatString { get; set; } 34 | 35 | [GlobalSetup] 36 | public void GlobalSetup() 37 | { 38 | _utf16preparedFormat_ = new Utf16PreparedFormat(FormatString); 39 | _utf16preparedFormatN = new NewZString::Cysharp.Text.Utf16PreparedFormat(FormatString); 40 | 41 | _utf8preparedFormat_ = new Utf8PreparedFormat(FormatString); 42 | _utf8preparedFormatN = new NewZString::Cysharp.Text.Utf8PreparedFormat(FormatString); 43 | } 44 | 45 | 46 | public FormatBenchmark() 47 | { 48 | x = int.Parse("100"); 49 | y = int.Parse("200"); 50 | } 51 | 52 | [BenchmarkCategory("Format"), Benchmark(Baseline = true)] 53 | public string Format_() 54 | { 55 | return ZString.Format(FormatString, x, y); 56 | } 57 | 58 | [BenchmarkCategory("Format"), Benchmark] 59 | public string FormatN() 60 | { 61 | return NZString.Format(FormatString, x, y); 62 | } 63 | 64 | [BenchmarkCategory("CreateUtf16PreparedFormat"), Benchmark(Baseline = true)] 65 | public object CreateUtf16PreparedFormat_() 66 | { 67 | return new Utf16PreparedFormat(FormatString); 68 | } 69 | 70 | [BenchmarkCategory("CreateUtf16PreparedFormat"), Benchmark] 71 | public object CreateUtf16PreparedFormatN() 72 | { 73 | return new NewZString::Cysharp.Text.Utf16PreparedFormat(FormatString); 74 | } 75 | 76 | [BenchmarkCategory("CreateUtf8PreparedFormat"), Benchmark(Baseline = true)] 77 | public object CreateUtf8PreparedFormat_() 78 | { 79 | return new Utf8PreparedFormat(FormatString); 80 | } 81 | 82 | [BenchmarkCategory("CreateUtf8PreparedFormat"), Benchmark] 83 | public object CreateUtf8PreparedFormatN() 84 | { 85 | return new NewZString::Cysharp.Text.Utf8PreparedFormat(FormatString); 86 | } 87 | 88 | [BenchmarkCategory("Utf16PreparedFormat"), Benchmark(Baseline = true)] 89 | public string Utf16PreparedFormat_() 90 | { 91 | return _utf16preparedFormat_.Format(x, y); 92 | } 93 | 94 | [BenchmarkCategory("Utf16PreparedFormat"), Benchmark] 95 | public string Utf16PreparedFormatN() 96 | { 97 | return _utf16preparedFormatN.Format(x, y); 98 | } 99 | 100 | [BenchmarkCategory("Utf8PreparedFormat"), Benchmark(Baseline = true)] 101 | public string Utf8PreparedFormat_() 102 | { 103 | return _utf8preparedFormat_.Format(x, y); 104 | } 105 | 106 | [BenchmarkCategory("Utf8PreparedFormat"), Benchmark] 107 | public string Utf8PreparedFormatN() 108 | { 109 | return _utf8preparedFormatN.Format(x, y); 110 | } 111 | 112 | [BenchmarkCategory("Utf16StringBuilderAppendFormat"), Benchmark(Baseline = true)] 113 | public int Utf16StringBuilderAppendFormat_() 114 | { 115 | using var zsh = ZString.CreateStringBuilder(); 116 | zsh.AppendFormat(FormatString, x, y); 117 | return zsh.Length; 118 | } 119 | 120 | [BenchmarkCategory("Utf16StringBuilderAppendFormat"), Benchmark] 121 | public int Utf16StringBuilderAppendFormatN() 122 | { 123 | using var zsh = NZString.CreateStringBuilder(); 124 | zsh.AppendFormat(FormatString, x, y); 125 | return zsh.Length; 126 | } 127 | 128 | [BenchmarkCategory("Utf8StringBuilderAppendFormat"), Benchmark(Baseline = true)] 129 | public int Utf8StringBuilderAppendFormat_() 130 | { 131 | using var zsh = ZString.CreateUtf8StringBuilder(); 132 | zsh.AppendFormat(FormatString, x, y); 133 | return zsh.Length; 134 | } 135 | 136 | [BenchmarkCategory("Utf8StringBuilderAppendFormat"), Benchmark] 137 | public int Utf8StringBuilderAppendFormatN() 138 | { 139 | using var zsh = NZString.CreateUtf8StringBuilder(); 140 | zsh.AppendFormat(FormatString, x, y); 141 | return zsh.Length; 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/ZString.Unity/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 3 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Very Low 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 0 21 | blendWeights: 1 22 | textureQuality: 1 23 | anisotropicTextures: 0 24 | antiAliasing: 0 25 | softParticles: 0 26 | softVegetation: 0 27 | realtimeReflectionProbes: 0 28 | billboardsFaceCameraPosition: 0 29 | vSyncCount: 0 30 | lodBias: 0.3 31 | maximumLODLevel: 0 32 | particleRaycastBudget: 4 33 | asyncUploadTimeSlice: 2 34 | asyncUploadBufferSize: 16 35 | resolutionScalingFixedDPIFactor: 1 36 | excludedTargetPlatforms: [] 37 | - serializedVersion: 2 38 | name: Low 39 | pixelLightCount: 0 40 | shadows: 0 41 | shadowResolution: 0 42 | shadowProjection: 1 43 | shadowCascades: 1 44 | shadowDistance: 20 45 | shadowNearPlaneOffset: 3 46 | shadowCascade2Split: 0.33333334 47 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 48 | shadowmaskMode: 0 49 | blendWeights: 2 50 | textureQuality: 0 51 | anisotropicTextures: 0 52 | antiAliasing: 0 53 | softParticles: 0 54 | softVegetation: 0 55 | realtimeReflectionProbes: 0 56 | billboardsFaceCameraPosition: 0 57 | vSyncCount: 0 58 | lodBias: 0.4 59 | maximumLODLevel: 0 60 | particleRaycastBudget: 16 61 | asyncUploadTimeSlice: 2 62 | asyncUploadBufferSize: 16 63 | resolutionScalingFixedDPIFactor: 1 64 | excludedTargetPlatforms: [] 65 | - serializedVersion: 2 66 | name: Medium 67 | pixelLightCount: 1 68 | shadows: 0 69 | shadowResolution: 0 70 | shadowProjection: 1 71 | shadowCascades: 1 72 | shadowDistance: 20 73 | shadowNearPlaneOffset: 3 74 | shadowCascade2Split: 0.33333334 75 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 76 | shadowmaskMode: 0 77 | blendWeights: 2 78 | textureQuality: 0 79 | anisotropicTextures: 0 80 | antiAliasing: 0 81 | softParticles: 0 82 | softVegetation: 0 83 | realtimeReflectionProbes: 0 84 | billboardsFaceCameraPosition: 0 85 | vSyncCount: 1 86 | lodBias: 0.7 87 | maximumLODLevel: 0 88 | particleRaycastBudget: 64 89 | asyncUploadTimeSlice: 2 90 | asyncUploadBufferSize: 16 91 | resolutionScalingFixedDPIFactor: 1 92 | excludedTargetPlatforms: [] 93 | - serializedVersion: 2 94 | name: High 95 | pixelLightCount: 2 96 | shadows: 0 97 | shadowResolution: 1 98 | shadowProjection: 1 99 | shadowCascades: 2 100 | shadowDistance: 40 101 | shadowNearPlaneOffset: 3 102 | shadowCascade2Split: 0.33333334 103 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 104 | shadowmaskMode: 1 105 | blendWeights: 2 106 | textureQuality: 0 107 | anisotropicTextures: 0 108 | antiAliasing: 0 109 | softParticles: 0 110 | softVegetation: 1 111 | realtimeReflectionProbes: 0 112 | billboardsFaceCameraPosition: 0 113 | vSyncCount: 1 114 | lodBias: 1 115 | maximumLODLevel: 0 116 | particleRaycastBudget: 256 117 | asyncUploadTimeSlice: 2 118 | asyncUploadBufferSize: 16 119 | resolutionScalingFixedDPIFactor: 1 120 | excludedTargetPlatforms: [] 121 | - serializedVersion: 2 122 | name: Very High 123 | pixelLightCount: 3 124 | shadows: 0 125 | shadowResolution: 2 126 | shadowProjection: 1 127 | shadowCascades: 2 128 | shadowDistance: 70 129 | shadowNearPlaneOffset: 3 130 | shadowCascade2Split: 0.33333334 131 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 132 | shadowmaskMode: 1 133 | blendWeights: 4 134 | textureQuality: 0 135 | anisotropicTextures: 0 136 | antiAliasing: 0 137 | softParticles: 0 138 | softVegetation: 1 139 | realtimeReflectionProbes: 0 140 | billboardsFaceCameraPosition: 0 141 | vSyncCount: 1 142 | lodBias: 1.5 143 | maximumLODLevel: 0 144 | particleRaycastBudget: 1024 145 | asyncUploadTimeSlice: 2 146 | asyncUploadBufferSize: 16 147 | resolutionScalingFixedDPIFactor: 1 148 | excludedTargetPlatforms: [] 149 | - serializedVersion: 2 150 | name: Ultra 151 | pixelLightCount: 4 152 | shadows: 0 153 | shadowResolution: 0 154 | shadowProjection: 1 155 | shadowCascades: 4 156 | shadowDistance: 150 157 | shadowNearPlaneOffset: 3 158 | shadowCascade2Split: 0.33333334 159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 160 | shadowmaskMode: 1 161 | blendWeights: 4 162 | textureQuality: 0 163 | anisotropicTextures: 0 164 | antiAliasing: 0 165 | softParticles: 0 166 | softVegetation: 1 167 | realtimeReflectionProbes: 0 168 | billboardsFaceCameraPosition: 0 169 | vSyncCount: 1 170 | lodBias: 2 171 | maximumLODLevel: 0 172 | particleRaycastBudget: 4096 173 | asyncUploadTimeSlice: 2 174 | asyncUploadBufferSize: 16 175 | resolutionScalingFixedDPIFactor: 1 176 | excludedTargetPlatforms: [] 177 | m_PerPlatformDefaultQuality: 178 | Android: 2 179 | Nintendo 3DS: 5 180 | Nintendo Switch: 5 181 | PS4: 5 182 | PSM: 5 183 | PSP2: 2 184 | Standalone: 5 185 | Tizen: 2 186 | WebGL: 3 187 | WiiU: 5 188 | Windows Store Apps: 5 189 | XboxOne: 5 190 | iPhone: 2 191 | tvOS: 2 192 | --------------------------------------------------------------------------------