Compare commits

..

64 Commits

Author SHA1 Message Date
Leonard Hecker
d2c41bf82d Remove chromium math & Rarely used til::rect helpers 2024-07-20 19:11:56 +02:00
Leonard Hecker
784f3f8780 Bad merge? 2024-07-20 03:02:13 +02:00
Leonard Hecker
3eb298dd5a Merge remote-tracking branch 'origin/main' into dev/lhecker/goodbye-vtengine 2024-07-19 22:38:02 +02:00
Leonard Hecker
21b13ca461 Avoid emitting VT for no-op SetConsoleActiveScreenBuffer calls 2024-07-18 04:29:46 +02:00
Leonard Hecker
81f3778bad Merge remote-tracking branch 'origin/main' into dev/lhecker/goodbye-vtengine 2024-07-18 04:25:46 +02:00
Leonard Hecker
a7158fb26a Fix bad merge 2024-07-17 18:13:19 +02:00
Leonard Hecker
e37b10fc89 Merge remote-tracking branch 'origin/main' into dev/lhecker/goodbye-vtengine 2024-07-17 18:08:43 +02:00
Leonard Hecker
55f5f34f67 Merge remote-tracking branch 'origin/main' into dev/lhecker/goodbye-vtengine 2024-07-17 03:16:03 +02:00
Leonard Hecker
f6f81e3da8 Merge remote-tracking branch 'origin/main' into dev/lhecker/goodbye-vtengine 2024-07-15 15:57:24 +02:00
Leonard Hecker
04aa614d66 More AuditMode fixes 2024-07-15 01:39:43 +02:00
Leonard Hecker
44a538d7e5 Address AuditMode issues 2024-07-15 01:13:37 +02:00
Leonard Hecker
34857bc3e7 should've 2024-07-15 00:47:07 +02:00
Leonard Hecker
119026afaf Right, we can't remove those 2024-07-15 00:46:17 +02:00
Leonard Hecker
316b91a2ff Proper overlapped IO, ITerminalHandoff3 2024-07-15 00:28:35 +02:00
Leonard Hecker
730d6873a3 VtIo tracing, More robust shutdown 2024-07-15 00:16:57 +02:00
Leonard Hecker
d67b70da8d More flexible CreateOverlappedPipe 2024-07-15 00:15:24 +02:00
Leonard Hecker
245279d74a Eh, NtCreateFile for consistency 2024-07-14 00:00:50 +02:00
Leonard Hecker
c3f48da21d Another one 2024-07-13 23:57:41 +02:00
Leonard Hecker
e1eb9db115 Make AuditMode happy, Improve comments 2024-07-13 23:49:32 +02:00
Leonard Hecker
2c1d7fcd28 Spell fix 2024-07-13 23:30:13 +02:00
Leonard Hecker
93930bb3fa They said anonymous overlapped pipes can't be done 2024-07-13 23:27:23 +02:00
Leonard Hecker
495c3e5295 10% faster for 128KiB of memory. Good deal. 2024-07-12 22:03:24 +02:00
Leonard Hecker
cc31a59669 Use overlapped pipes for WT 2024-07-12 21:32:18 +02:00
Leonard Hecker
d3ee58b9fc Add a missing force-wrap, Minor cleanup 2024-07-12 00:19:42 +02:00
Leonard Hecker
882f3faf0d Merge remote-tracking branch 'origin/main' into dev/lhecker/goodbye-vtengine 2024-07-11 23:50:49 +02:00
Leonard Hecker
512468d47f LNM 2024-07-11 18:38:20 +02:00
Leonard Hecker
8b59551151 Forgot to call Submit() 2024-07-11 18:33:13 +02:00
Leonard Hecker
d65bb806cd Forgot to remove LNM 2024-07-11 18:12:31 +02:00
Leonard Hecker
f0db29ddd1 Fix exception correctness, CRLF translation, C1 pictograms, Line wrap, Wide chars 2024-07-11 18:08:36 +02:00
Leonard Hecker
f35127abbe Improve comments 2024-07-11 18:04:44 +02:00
Leonard Hecker
7b5b3657f2 Merge remote-tracking branch 'origin/main' into dev/lhecker/goodbye-vtengine 2024-07-11 03:19:02 +02:00
Leonard Hecker
669a530204 Don't use RIS for cls 2024-07-08 01:49:19 +02:00
Leonard Hecker
c8d0a934fb Revert incorrect ASB fix 2024-07-08 01:28:44 +02:00
Leonard Hecker
edd4c758d7 Fix GetVtIo for alt buffers 2024-07-08 01:26:12 +02:00
Leonard Hecker
e9e6227a4e Better GetVtIo naming, Less VtEngine code, Fix control char sanitization 2024-07-08 00:00:49 +02:00
Leonard Hecker
9535e49518 Uh... 2024-07-07 22:34:50 +02:00
Leonard Hecker
9c42bfcb8d Fix VtIoTests 2024-07-07 19:34:34 +02:00
Leonard Hecker
29766619f0 Remove DECCOLM from DA1 2024-07-07 19:31:38 +02:00
Leonard Hecker
92087fbd23 AuditMode fix 2024-07-07 18:25:03 +02:00
Leonard Hecker
c92c5cf716 Fixed cls->RIS translation, Way faster pwsh cls 2024-07-07 18:07:34 +02:00
Leonard Hecker
eaf364ec37 Fix the injection of ConPTY modes 2024-07-07 17:42:57 +02:00
Leonard Hecker
976343e1ab Fix the cursor reset when entering the ASB twice 2024-07-07 17:42:09 +02:00
Leonard Hecker
d3b4592b71 Remove IsConsolePty 2024-07-07 17:42:01 +02:00
Leonard Hecker
6b254492be Remove AlwaysAcceptC1 2024-07-07 17:38:57 +02:00
Leonard Hecker
b78e5bc044 Fix x86 build, Fix a missing FMT_COMPILE 2024-07-07 03:44:48 +02:00
Leonard Hecker
1047ed4f1a A way simpler ReadConsoleOutputWImplHelper, because why not 2024-07-06 03:42:15 +02:00
Leonard Hecker
a138b284a4 Fix spelling 2024-07-06 02:52:02 +02:00
Leonard Hecker
a3f5d59ebe x86 wants its __stdcall back 2024-07-05 18:48:11 +02:00
Leonard Hecker
6a13e5aabc A common C++ L 2024-07-05 17:58:41 +02:00
Leonard Hecker
0e51acd5d9 Fix conhost feature tests 2024-07-05 16:01:16 +02:00
Leonard Hecker
c3d5ce14dd Fix AuditMode, Unstage some unnecessary changes 2024-07-05 14:27:50 +02:00
Leonard Hecker
3e346f1174 Fix synchronous reads 2024-07-05 14:24:39 +02:00
Leonard Hecker
7c6c1824eb Spel 2024-07-04 17:33:15 +02:00
Leonard Hecker
7462a20097 Fix midi crash, Fix double DSR response 2024-07-04 17:28:50 +02:00
Leonard Hecker
78ae6dda80 OVERLAPPED for stdin, Timeouts for PSEUDOCONSOLE_INHERIT_CURSOR 2024-07-04 17:28:12 +02:00
Leonard Hecker
8de1a7543f Move OVERLAPPED helpers to Types 2024-07-04 17:27:17 +02:00
Leonard Hecker
9e3d3983d5 Some leftover VtEngine logic 2024-07-04 17:26:28 +02:00
Leonard Hecker
db2b762221 Remove references to deleted tests 2024-07-04 03:49:40 +02:00
Leonard Hecker
eec17eb805 Slightly more elegant formatAttributes 2024-07-04 03:48:13 +02:00
Leonard Hecker
89b4c09e50 Fix support for far 2024-07-04 02:46:10 +02:00
Leonard Hecker
73e3dd31b5 Fix support for vim 2024-07-04 02:33:20 +02:00
Leonard Hecker
656a0492d7 Restore win32im/focus on RIS, Clean up some stuff 2024-07-03 23:21:57 +02:00
Leonard Hecker
17d39eb3eb Fix build, Fix tests 2024-07-03 04:02:36 +02:00
Leonard Hecker
fec64563a0 A minor ConPTY refactoring: Goodbye VtEngine Edition 2024-07-03 03:36:02 +02:00
599 changed files with 9654 additions and 21376 deletions

View File

@@ -1,7 +1,6 @@
name: "Bug report 🐛"
description: Report errors or unexpected behavior
labels: [Issue-Bug, Needs-Triage]
type: Bug
body:
- type: markdown
attributes:
@@ -13,7 +12,7 @@ body:
- type: input
attributes:
label: Windows Terminal version
placeholder: "1.21.2701.0"
placeholder: "1.7.3651.0"
description: |
You can copy the version number from the About dialog. Open the About dialog by opening the menu with the "V" button (to the right of the "+" button that opens a new tab) and choosing About from the end of the list.
validations:
@@ -22,7 +21,7 @@ body:
- type: input
attributes:
label: Windows build number
placeholder: "10.0.22621.0"
placeholder: "10.0.19042.0"
description: |
Please run `ver` or `[Environment]::OSVersion`.
validations:
@@ -33,9 +32,9 @@ body:
label: Other Software
description: If you're reporting a bug about our interaction with other software, what software? What versions?
placeholder: |
vim 9.1 (inside WSL)
OpenSSH_for_Windows_9.5p1
My Cool Application v0.4 (include a code snippet if it would help!)
vim 8.2 (inside WSL)
OpenSSH_for_Windows_8.1p1
My Cool Application v0.3 (include a code snippet if it would help!)
validations:
required: false

View File

@@ -0,0 +1,10 @@
---
name: "Documentation Issue 📚"
about: Report issues in our documentation
title: ''
labels: Issue-Docs
assignees: ''
---
<!-- Briefly describe which document needs to be corrected and why. -->

View File

@@ -0,0 +1,35 @@
---
name: "Feature Request/Idea 🚀"
about: Suggest a new feature or improvement (this does not mean you have to implement
it)
title: ''
labels: Issue-Feature
assignees: ''
---
<!--
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING:
1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement.
2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement.
3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number).
4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement.
5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement.
All good? Then proceed!
-->
# Description of the new feature/enhancement
<!--
A clear and concise description of what the problem is that the new feature would solve.
Describe why and how a user would use this new functionality (if applicable).
-->
# Proposed technical implementation details (optional)
<!--
A clear and concise description of what you want to happen.
-->

View File

@@ -1,20 +0,0 @@
name: "Feature Request/Idea 🚀"
description: Suggest a new feature or improvement (this does not mean you have to implement it)
labels: [Issue-Feature]
type: Feature
body:
- type: textarea
attributes:
label: Description of the new feature
description: A clear and concise description of what the problem is that the new feature would solve.
placeholder: |
... and guess what? I have four Terminals. And I have a hover car, and a hover house. And my computer's a runner, and it shows.
validations:
required: true
- type: textarea
attributes:
label: Proposed technical implementation details
description: This field is optional. If you have any ideas, let us know!
validations:
required: false

View File

@@ -5,7 +5,6 @@ breadcrumbs
ccmp
ccon
clickable
cmark
CMMI
colorbrewer
consvc
@@ -23,13 +22,11 @@ Emacspeak
Fitt
FTCS
gantt
gfm
ghe
gje
godbolt
hyperlinking
hyperlinks
Kbds
kje
libfuzzer
liga
@@ -46,7 +43,6 @@ mkmk
mnt
mru
nje
NTMTo
notwrapped
ogonek
overlined

View File

@@ -43,7 +43,6 @@ DONTADDTORECENT
DWMSBT
DWMWA
DWORDLONG
EMPH
endfor
ENDSESSION
enumset
@@ -63,7 +62,6 @@ GETDESKWALLPAPER
GETHIGHCONTRAST
GETMOUSEHOVERTIME
GETTEXTLENGTH
HARDBREAKS
Hashtable
HIGHCONTRASTON
HIGHCONTRASTW
@@ -98,7 +96,6 @@ IGraphics
IImage
IInheritable
IMap
imm
IMonarch
IObject
iosfwd
@@ -117,7 +114,6 @@ IUri
IVirtual
KEYSELECT
LCID
LINEBREAK
llabs
llu
localtime
@@ -151,7 +147,6 @@ NIF
NIN
NOAGGREGATION
NOASYNC
NOBREAKS
NOCHANGEDIR
NOPROGRESS
NOREDIRECTIONBITMAP
@@ -179,7 +174,6 @@ PALLOC
PATINVERT
PEXPLICIT
PICKFOLDERS
PINPUT
pmr
ptstr
QUERYENDSESSION
@@ -208,7 +202,6 @@ SINGLEUSE
SIZENS
smoothstep
snprintf
SOFTBREAK
spsc
sregex
SRWLOC

View File

@@ -104,7 +104,6 @@
^doc/reference/UTF8-torture-test\.txt$
^doc/reference/windows-terminal-logo\.ans$
^oss/
^NOTICE.md
^samples/PixelShaders/Screenshots/
^src/interactivity/onecore/BgfxEngine\.
^src/renderer/atlas/
@@ -129,4 +128,3 @@
^XamlStyler\.json$
ignore$
Resources/(?!en)
^\.vsconfig$

View File

@@ -0,0 +1,5 @@
EOB
swrapped
wordi
wordiswrapped
wrappe

View File

@@ -9,6 +9,7 @@ ABORTIFHUNG
ACCESSTOKEN
acidev
ACIOSS
ACover
acp
actctx
ACTCTXW
@@ -16,8 +17,6 @@ ADDALIAS
ADDREF
ADDSTRING
ADDTOOL
adml
admx
AFill
AFX
AHelper
@@ -39,7 +38,6 @@ ANSISYS
ANSISYSRC
ANSISYSSC
answerback
ANSWERBACKMESSAGE
antialiasing
ANull
anycpu
@@ -88,7 +86,6 @@ Autowrap
AVerify
awch
azurecr
AZZ
backgrounded
Backgrounder
backgrounding
@@ -145,8 +142,8 @@ BTNFACE
bufferout
buffersize
buflen
buildsystems
buildtransitive
buildsystems
BValue
bytebuffer
cac
@@ -182,6 +179,7 @@ CFuzz
cgscrn
chafa
changelists
charinfo
CHARSETINFO
chh
chshdng
@@ -265,6 +263,7 @@ consolegit
consolehost
CONSOLEIME
consoleinternal
Consoleroot
CONSOLESETFOREGROUND
consoletaeftemplates
consoleuwp
@@ -341,7 +340,6 @@ CXVIRTUALSCREEN
CXVSCROLL
CYFRAME
CYFULLSCREEN
cygdrive
CYHSCROLL
CYMIN
CYPADDEDBORDER
@@ -387,7 +385,7 @@ DECCIR
DECCKM
DECCKSR
DECCOLM
deccra
DECCRA
DECCTR
DECDC
DECDHL
@@ -399,7 +397,7 @@ DECEKBD
DECERA
DECFI
DECFNK
decfra
DECFRA
DECGCI
DECGCR
DECGNL
@@ -567,7 +565,6 @@ entrypoints
ENU
ENUMLOGFONT
ENUMLOGFONTEX
EOB
EOK
EPres
EQU
@@ -729,6 +726,7 @@ GHIJKL
gitcheckin
gitfilters
gitlab
gitmodules
gle
GLOBALFOCUS
GLYPHENTRY
@@ -786,7 +784,6 @@ HIWORD
HKCU
hkey
hkl
HKLM
hlocal
hlsl
HMB
@@ -869,7 +866,6 @@ INLINEPREFIX
inproc
Inputkeyinfo
Inputreadhandledata
INPUTSCOPE
INSERTMODE
INTERACTIVITYBASE
INTERCEPTCOPYPASTE
@@ -919,7 +915,6 @@ Keymapping
keyscan
keystate
keyups
Kickstart
KILLACTIVE
KILLFOCUS
kinda
@@ -1025,6 +1020,7 @@ lstatus
lstrcmp
lstrcmpi
LTEXT
LTLTLTLTL
ltsc
LUID
luma
@@ -1119,6 +1115,7 @@ msrc
MSVCRTD
MTSM
Munged
munges
murmurhash
muxes
myapplet
@@ -1220,6 +1217,7 @@ ntlpcapi
ntm
ntrtl
ntstatus
NTSYSCALLAPI
nttree
nturtl
ntuser
@@ -1235,7 +1233,6 @@ NUMSCROLL
NUnit
nupkg
NVIDIA
NVT
OACR
objbase
ocolor
@@ -1296,7 +1293,6 @@ parms
PATCOPY
pathcch
PATTERNID
pbstr
pcb
pcch
PCCHAR
@@ -1382,11 +1378,9 @@ POSTCHARBREAKS
POSX
POSXSCROLL
POSYSCROLL
ppbstr
PPEB
ppf
ppidl
pprg
PPROC
ppropvar
ppsi
@@ -1413,7 +1407,6 @@ processenv
processhost
PROCESSINFOCLASS
PRODEXT
Productize
PROPERTYID
PROPERTYKEY
propertyval
@@ -1465,7 +1458,6 @@ QWER
Qxxxxxxxxxxxxxxx
qzmp
RAII
Ralph
RALT
rasterbar
rasterfont
@@ -1531,6 +1523,7 @@ rftp
rgbi
RGBQUAD
rgbs
rgci
rgfae
rgfte
rgn
@@ -1608,7 +1601,6 @@ SELECTALL
SELECTEDFONT
SELECTSTRING
Selfhosters
Serbo
SERVERDLL
SETACTIVE
SETBUDDYINT
@@ -1703,7 +1695,6 @@ srcsrv
SRCSRVTRG
srctool
srect
SRGS
srvinit
srvpipe
ssa
@@ -1741,7 +1732,6 @@ swapchain
swapchainpanel
SWMR
SWP
swrapped
SYMED
SYNCPAINT
syscalls
@@ -1823,7 +1813,6 @@ TITLEISLINKNAME
TJson
TLambda
TLDP
tldr
TLEN
TMAE
TMPF
@@ -1839,6 +1828,8 @@ TOPDOWNDIB
TOpt
tosign
touchpad
Tpp
Tpqrst
tracelogging
traceviewpp
trackbar
@@ -1851,6 +1842,7 @@ triaging
TRIMZEROHEADINGS
trx
tsa
tsattrs
tsgr
tsm
TStr
@@ -1962,6 +1954,7 @@ VPACKMANIFESTDIRECTORY
VPR
VREDRAW
vsc
vsconfig
vscprintf
VSCROLL
vsdevshell
@@ -1978,8 +1971,10 @@ vswhere
vtapp
VTE
VTID
vtio
vtmode
vtpipeterm
vtpt
VTRGB
VTRGBTo
vtseq
@@ -2001,6 +1996,7 @@ wcswidth
wddm
wddmcon
WDDMCONSOLECONTEXT
WDK
wdm
webpage
websites
@@ -2015,7 +2011,6 @@ WHelper
wic
WIDTHSCROLL
Widthx
Wiggum
wil
WImpl
WINAPI
@@ -2075,6 +2070,7 @@ winuserp
WINVER
wistd
wmain
wmemory
WMSZ
wnd
WNDALLOC
@@ -2085,8 +2081,6 @@ WNDCLASSW
Wndproc
WNegative
WNull
wordi
wordiswrapped
workarea
WOutside
WOWARM
@@ -2100,7 +2094,6 @@ WPrep
WPresent
wprp
wprpi
wrappe
wregex
writeback
WRITECONSOLE
@@ -2144,7 +2137,6 @@ XBUTTONDOWN
XBUTTONUP
XCast
XCENTER
xchar
xcopy
XCount
xdy
@@ -2176,7 +2168,6 @@ yact
YCast
YCENTER
YCount
yizz
YLimit
YPan
YSubstantial
@@ -2190,4 +2181,3 @@ ZCtrl
ZWJs
ZYXWVU
ZYXWVUTd
zzf

View File

@@ -22,7 +22,6 @@ vcvars\w*
ROY\sG\.\sBIV
!(?:(?i)ESC)!\[
!(?:(?i)CSI)!(?:\d+(?:;\d+|)m|[ABCDF])
(?i)rgb:[a-z0-9]{2,4}/[a-z0-9]{2,4}/[a-z0-9]{2,4}
# SSE intrinsics like "_mm_subs_epu16"
\b_mm(?:|256|512)_\w+\b

View File

@@ -13,7 +13,7 @@ jobs:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v1.0.2
- uses: actions/add-to-project@v1.0.1
with:
project-url: https://github.com/orgs/microsoft/projects/159
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}

33
.github/workflows/similarIssues.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: GitGudSimilarIssues comments
on:
issues:
types: [opened]
jobs:
getSimilarIssues:
runs-on: ubuntu-latest
outputs:
message: ${{ steps.getBody.outputs.message }}
steps:
- id: getBody
uses: craigloewen-msft/GitGudSimilarIssues@main
with:
issueTitle: ${{ github.event.issue.title }}
issueBody: ${{ github.event.issue.body }}
repo: ${{ github.repository }}
similaritytolerance: "0.8"
add-comment:
needs: getSimilarIssues
runs-on: ubuntu-latest
permissions:
issues: write
if: needs.getSimilarIssues.outputs.message != ''
steps:
- name: Add comment
run: gh issue comment "$NUMBER" --repo "$REPO" --body "$BODY"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NUMBER: ${{ github.event.issue.number }}
REPO: ${{ github.repository }}
BODY: ${{ needs.getSimilarIssues.outputs.message }}

View File

@@ -1,51 +1,35 @@
{
"version": "1.0",
"components": [
"Microsoft.VisualStudio.Component.Roslyn.Compiler",
"Microsoft.Component.MSBuild",
"Microsoft.VisualStudio.Component.Roslyn.LanguageServices",
"Microsoft.VisualStudio.Component.SQL.LocalDB.Runtime",
"Microsoft.VisualStudio.Component.SQL.CLR",
"Microsoft.VisualStudio.Component.CoreEditor",
"Microsoft.VisualStudio.Workload.CoreEditor",
"Microsoft.Net.Component.4.8.SDK",
"Microsoft.Net.Component.4.7.2.TargetingPack",
"Microsoft.VisualStudio.Component.TextTemplating",
"Microsoft.VisualStudio.Component.NuGet",
"Microsoft.NetCore.Component.Runtime.8.0",
"Microsoft.NetCore.Component.SDK",
"Microsoft.VisualStudio.Component.AppInsights.Tools",
"Microsoft.Net.Component.4.8.TargetingPack",
"Microsoft.VisualStudio.Component.DiagnosticTools",
"Microsoft.NetCore.Component.Runtime.6.0",
"Microsoft.VisualStudio.Component.ClassDesigner",
"Microsoft.VisualStudio.Component.GraphDocument",
"Microsoft.VisualStudio.Component.CodeMap",
"Microsoft.VisualStudio.Component.VC.CoreIde",
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
"Microsoft.VisualStudio.Component.Windows11SDK.22621",
"Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging",
"Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs",
"Microsoft.ComponentGroup.Blend",
"Microsoft.VisualStudio.ComponentGroup.ArchitectureTools.Native",
"Microsoft.VisualStudio.Component.VC.Redist.14.Latest",
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
"Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake",
"Microsoft.VisualStudio.Component.Vcpkg",
"Microsoft.Component.NetFX.Native",
"Microsoft.VisualStudio.Component.Graphics",
"Microsoft.VisualStudio.ComponentGroup.UWP.Xamarin",
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
"Microsoft.VisualStudio.Component.VC.Tools.ARM64EC",
"Microsoft.VisualStudio.Component.UWP.VC.ARM64EC",
"Microsoft.VisualStudio.Component.VC.Tools.ARM64",
"Microsoft.VisualStudio.Component.UWP.VC.ARM64",
"Microsoft.VisualStudio.Component.VC.Tools.ARM",
"Microsoft.VisualStudio.ComponentGroup.UWP.VC",
"Microsoft.VisualStudio.Workload.Universal",
"Microsoft.VisualStudio.Workload.NativeDesktop",
"Microsoft.VisualStudio.ComponentGroup.WindowsAppDevelopment.Prerequisites",
"Microsoft.VisualStudio.ComponentGroup.UWP.NetCoreAndStandard",
"Microsoft.VisualStudio.Workload.Universal"
],
"extensions": []
"Microsoft.VisualStudio.Workload.ManagedDesktop",
"Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites",
"Microsoft.VisualStudio.Component.NuGet",
"Microsoft.VisualStudio.Component.Roslyn.Compiler",
"Microsoft.VisualStudio.Component.Roslyn.LanguageServices",
"Microsoft.Net.ComponentGroup.DevelopmentPrerequisites",
"Microsoft.Component.MSBuild",
"Microsoft.VisualStudio.Component.ManagedDesktop.Core",
"Microsoft.Net.Component.4.TargetingPack",
"Microsoft.Net.Component.4.5.TargetingPack",
"Microsoft.VisualStudio.Component.DiagnosticTools",
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
"Microsoft.VisualStudio.Component.Windows11SDK.22621",
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
"Microsoft.VisualStudio.Component.VC.CoreIde",
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
"Microsoft.VisualStudio.Component.Graphics",
"Microsoft.VisualStudio.Component.VC.Redist.14.Latest",
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
"Microsoft.VisualStudio.Component.VC.Tools.ARM64",
"Microsoft.VisualStudio.Component.VC.ASAN",
"Microsoft.VisualStudio.Component.VC.v143.x86.x64",
"Microsoft.VisualStudio.Component.VC.v143.ARM64",
"Microsoft.VisualStudio.ComponentGroup.UWP.VC",
"Microsoft.VisualStudio.ComponentGroup.UWP.VC.v143",
"Microsoft.VisualStudio.Component.UWP.VC.ARM64"
]
}

View File

@@ -1,34 +0,0 @@
{
"$version": "1.0.0",
"snippets":
[
{
"input": "bx\r",
"name": "Build project",
"description": "Build the project in the CWD"
},
{
"input": "bz\r",
"name": "Build solution, incremental",
"description": "Just build changes to the solution"
},
{
"input": "bcz\r",
"name": "Clean & build solution",
"icon": "\uE8e6",
"description": "Start over. Go get your coffee. "
},
{
"input": "nuget push -ApiKey az -source TerminalDependencies %userprofile%\\Downloads",
"name": "Upload package to nuget feed",
"icon": "\uE898",
"description": "Go download a .nupkg, put it in ~/Downloads, and use this to push to our private feed."
},
{
"input": "runut /name:**\u001b[D",
"name": "Run a test",
"icon": "",
"description": "Enter the name of a test to run"
}
]
}

View File

@@ -41,11 +41,6 @@
-->
<MSBuildCacheIdenticalDuplicateOutputPatterns>$(MSBuildCacheIdenticalDuplicateOutputPatterns);bin\**</MSBuildCacheIdenticalDuplicateOutputPatterns>
<!--
vcpkg is invoked for each and every vcxproj and each invocation uses the same base dir for logging, so allow these duplicate "outputs".
-->
<MSBuildCacheIdenticalDuplicateOutputPatterns>$(MSBuildCacheIdenticalDuplicateOutputPatterns);obj\*\vcpkg\**</MSBuildCacheIdenticalDuplicateOutputPatterns>
<!-- version of MSBuildCache is not part of the cache key -->
<PackagesConfigFile>$(MSBuildThisFileDirectory)\dep\nuget\packages.config</PackagesConfigFile>
<MSBuildCacheIgnoredInputPatterns>$(MSBuildCacheIgnoredInputPatterns);$(PackagesConfigFile)</MSBuildCacheIgnoredInputPatterns>

211
NOTICE.md
View File

@@ -48,42 +48,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## chromium/base/numerics
**Source**: [https://github.com/chromium/chromium/tree/master/base/numerics](https://github.com/chromium/chromium/tree/master/base/numerics)
### License
```
Copyright 2015 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## \{fmt\}
**Source**: [https://github.com/fmtlib/fmt](https://github.com/fmtlib/fmt)
@@ -281,181 +245,6 @@ CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
```
## cmark
**Source**: [https://github.com/commonmark/cmark](https://github.com/commonmark/cmark)
### License
Copyright (c) 2014, John MacFarlane
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-----
houdini.h, houdini_href_e.c, houdini_html_e.c, houdini_html_u.c
derive from https://github.com/vmg/houdini (with some modifications)
Copyright (C) 2012 Vicent Martí
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-----
buffer.h, buffer.c, chunk.h
are derived from code (C) 2012 Github, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-----
utf8.c and utf8.c
are derived from utf8proc
(<http://www.public-software-group.org/utf8proc>),
(C) 2009 Public Software Group e. V., Berlin, Germany.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-----
The normalization code in normalize.py was derived from the
markdowntest project, Copyright 2013 Karl Dubost:
The MIT License (MIT)
Copyright (c) 2013 Karl Dubost
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----
The CommonMark spec (test/spec.txt) is
Copyright (C) 2014-15 John MacFarlane
Released under the Creative Commons CC-BY-SA 4.0 license:
<http://creativecommons.org/licenses/by-sa/4.0/>.
-----
The test software in test/ is
Copyright (c) 2014, John MacFarlane
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Microsoft Open Source
This product also incorporates source code from other Microsoft open source projects, all licensed under the MIT license.

View File

@@ -405,8 +405,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenderingTests", "src\tools
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.UI", "src\cascadia\UIHelpers\UIHelpers.vcxproj", "{6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.UI.Markdown", "src\cascadia\UIMarkdown\UIMarkdown.vcxproj", "{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchcat", "src\tools\benchcat\benchcat.vcxproj", "{2C836962-9543-4CE5-B834-D28E1F124B66}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConsoleMonitor", "src\tools\ConsoleMonitor\ConsoleMonitor.vcxproj", "{328729E9-6723-416E-9C98-951F1473BBE1}"
@@ -2304,28 +2302,6 @@ Global
{6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Release|x64.Build.0 = Release|x64
{6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Release|x86.ActiveCfg = Release|Win32
{6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Release|x86.Build.0 = Release|Win32
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.AuditMode|Any CPU.ActiveCfg = Debug|Win32
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.AuditMode|ARM64.ActiveCfg = Release|ARM64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.AuditMode|x64.ActiveCfg = Release|x64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.AuditMode|x86.ActiveCfg = Release|Win32
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Debug|Any CPU.ActiveCfg = Debug|x64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Debug|ARM64.ActiveCfg = Debug|ARM64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Debug|ARM64.Build.0 = Debug|ARM64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Debug|x64.ActiveCfg = Debug|x64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Debug|x64.Build.0 = Debug|x64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Debug|x86.ActiveCfg = Debug|Win32
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Debug|x86.Build.0 = Debug|Win32
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|x64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Release|Any CPU.ActiveCfg = Release|x64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Release|ARM64.ActiveCfg = Release|ARM64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Release|ARM64.Build.0 = Release|ARM64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Release|x64.ActiveCfg = Release|x64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Release|x64.Build.0 = Release|x64
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Release|x86.ActiveCfg = Release|Win32
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F}.Release|x86.Build.0 = Release|Win32
{2C836962-9543-4CE5-B834-D28E1F124B66}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{2C836962-9543-4CE5-B834-D28E1F124B66}.AuditMode|ARM64.ActiveCfg = Release|ARM64
{2C836962-9543-4CE5-B834-D28E1F124B66}.AuditMode|x64.ActiveCfg = Release|x64
@@ -2479,7 +2455,6 @@ Global
{613CCB57-5FA9-48EF-80D0-6B1E319E20C4} = {A10C4720-DCA4-4640-9749-67F4314F527C}
{37C995E0-2349-4154-8E77-4A52C0C7F46D} = {A10C4720-DCA4-4640-9749-67F4314F527C}
{6515F03F-E56D-4DB4-B23D-AC4FB80DB36F} = {61901E80-E97D-4D61-A9BB-E8F2FDA8B40C}
{7615F03F-E56D-4DB4-B23D-BD4FB80DB36F} = {61901E80-E97D-4D61-A9BB-E8F2FDA8B40C}
{2C836962-9543-4CE5-B834-D28E1F124B66} = {A10C4720-DCA4-4640-9749-67F4314F527C}
{328729E9-6723-416E-9C98-951F1473BBE1} = {A10C4720-DCA4-4640-9749-67F4314F527C}
{BE92101C-04F8-48DA-99F0-E1F4F1D2DC48} = {A10C4720-DCA4-4640-9749-67F4314F527C}

View File

@@ -1,7 +1,5 @@
![terminal-logos](https://github.com/microsoft/terminal/assets/91625426/333ddc76-8ab2-4eb4-a8c0-4d7b953b1179)
[![Terminal Build Status](https://dev.azure.com/shine-oss/terminal/_apis/build/status%2FTerminal%20CI?branchName=main)](https://dev.azure.com/shine-oss/terminal/_build/latest?definitionId=1&branchName=main)
# Welcome to the Windows Terminal, Console and Command-Line repo
This repository contains the source code for:
@@ -147,6 +145,15 @@ _Learn more about the [types of Windows Terminal distributions](https://learn.mi
The plan for the Windows Terminal [is described here](/doc/roadmap-2023.md) and
will be updated as the project proceeds.
## Project Build Status
Project|Build Status
---|---
Terminal|[![Terminal Build Status](https://dev.azure.com/ms/terminal/_apis/build/status/terminal%20CI?branchName=main)](https://dev.azure.com/ms/terminal/_build?definitionId=136)
ColorTool|![Colortool Build Status](https://microsoft.visualstudio.com/_apis/public/build/definitions/c93e867a-8815-43c1-92c4-e7dd5404f1e1/17023/badge)
---
## Terminal & Console Overview
Please take a few minutes to review the overview below before diving into the

View File

@@ -56,15 +56,7 @@ Dies ist ein Open Source-Projekt, und wir freuen uns über die Teilnahme der Com
<ReleaseNotes>
Version __VERSION_NUMBER__
Wir haben umgeschrieben, wie Konsolenanwendungen im Terminal gehostet werden! Melden Sie alle auftretenden Fehler.
- Terminal unterstützt jetzt Sixels!
- Sie können jetzt ein angedocktes Fenster öffnen, das Ausschnitte von Befehlen enthält, die Sie gespeichert haben, um sie später zu verwenden.
- Für Benutzer der Eingabeaufforderung der neuesten Version von Windows 11 wird möglicherweise ein „Kurzer Tipp“-Symbol angezeigt, das installierbare Software von WinGet
vorschlägt
- Ausgewählter Text wird jetzt viel sichtbarer (und anpassbarer!)
- Eine Reihe von Zuverlässigkeitsfehlern, Komfortproblemen und Ärgernissen wurden behoben.
Weitere Informationen finden Sie auf unserer GitHub-Releaseseite.
Weitere Einzelheiten finden Sie auf der Seite der GitHub-Veröffentlichungen.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,13 +56,6 @@ This is an open source project and we welcome community participation. To partic
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=__VERSION_NUMBER__} App Release Note" -->Version __VERSION_NUMBER__
- We've rewritten how console applications are hosted inside Terminal! Please report any bugs you encounter.
- Terminal now supports Sixels!
- You can now open a docked panel containing snippets of commands you have saved to use later
- Command Prompt users on the latest Windows 11 release may see a "quick tip" icon that suggests installable software from WinGet
- Selected text will now be much more visible (and customizable!)
- A number of reliabilty bugs, convenience issues and annoyances have been fixed.
Please see our GitHub releases page for additional details.
</ReleaseNotes>
<ScreenshotCaptions>

View File

@@ -56,14 +56,7 @@ Este es un proyecto de fuente abierta y animamos a la comunidad a participar. Pa
<ReleaseNotes>
Versión __VERSION_NUMBER__
- Hemos reescrito cómo se hospedan las aplicaciones de consola en Terminal. Informe de los errores que encuentre.
- Terminal ahora admite sixeles.
- Ahora puede abrir un panel acoplado que contenga fragmentos de comandos que haya guardado para usarlos más adelante
- Los usuarios del símbolo del sistema de la versión más reciente de Windows 11 pueden ver un icono de "sugerencia rápida" que sugiere software instalable de WinGet
- El texto seleccionado ahora será mucho más visible (y personalizable)
- Se han corregido varios errores de fiabilidad, problemas de comodidad y molestias.
Consulte la página de versiones de GitHub para más información.
Para más información, consulte nuestra página de versiones de GitHub.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@ Il sagit dun projet open source et nous vous invitons à participer dans l
<ReleaseNotes>
Version __VERSION_NUMBER__
- Nous avons réécrit la manière dont les applications de console sont hébergées dans Terminal ! Veuillez signaler tout bug que vous rencontrez.
- Le terminal prend désormais en charge Sixels !
- Vous pouvez désormais ouvrir un panneau ancré contenant des extraits de commandes que vous avez enregistrées pour les utiliser ultérieurement
- Les utilisateurs de l'invite de commande sur la dernière version de Windows 11 peuvent voir une icône « astuce rapide » qui suggère un logiciel installable à partir de WinGet
- Le texte sélectionné sera désormais beaucoup plus visible (et personnalisable !)
- Un certain nombre de bugs de fiabilité, de problèmes de commodité et de désagréments ont été corrigés.
Veuillez consulter notre page de versions GitHub pour plus de détails.
Consultez la page des versions de GitHub pour plus dinformations.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -54,16 +54,9 @@ Si tratta di un progetto open source e la partecipazione della community è molt
</DevStudio>
<ReleaseNotes>
Versione __VERSION_NUMBER__
Versione __VERSION_NUMBER__
- È stato riscritto il modo in cui le applicazioni della console vengono ospitate all'interno di Terminale. Segnala eventuali bug riscontrati.
- Terminal supporta ora Sixel.
- È ora possibile aprire un pannello ancorato contenente frammenti di comandi salvati per usarli in seguito
- Gli utenti del prompt dei comandi nella versione più recente di Windows 11 potrebbero visualizzare un'icona di "suggerimento rapido" che consiglia il software installabile da WinGet
- Il testo selezionato sarà ora molto più visibile, oltre che personalizzabile.
- Sono stati risolti diversi bug di affidabilità, problemi di praticità e fastidi.
Per altri dettagli, vedi la pagina delle versioni di GitHub.
Per ulteriori dettagli, consulta la nostra pagina delle versioni di GitHub.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
バージョン __VERSION_NUMBER__
- ターミナル内でのコンソール アプリケーションのホスト方法を書き換えました。発生したバグを報告してください。
- ターミナルで Sixels がサポートされるようになりました。
- 後で使用するために保存したコマンドのスニペットを含むドッキング パネルを開けるようになりました
- 最新の Windows 11 リリースのコマンド プロンプト ユーザーには、WinGet からインストール可能なソフトウェアを提案する "クイック ヒント" アイコンが表示される場合があります
- 選択したテキストが大幅に見やすくなりました (カスタマイズも可能です)
- 信頼性に関するバグ、利便性の問題、不快な問題の多くが修正されました。
詳細については、GitHub リリース ページをご覧ください。
詳細については、GitHub リリースのページをご覧ください。
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,13 +56,6 @@
<ReleaseNotes>
버전 __VERSION_NUMBER__
- 콘솔 애플리케이션이 터미널 내에서 호스팅되는 방법을 다시 작성했습니다! 발생한 버그를 보고하세요.
- 터미널에서 이제 Sixels를 지원합니다!
- 이제 나중에 사용하기 위해 저장한 명령 조각이 포함된 도킹된 패널을 열 수 있습니다.
- 최신 Windows 11 릴리스의 명령 프롬프트 사용자는 WinGet에서 설치 가능한 소프트웨어를 제안하는 "빠른 팁" 아이콘을 볼 수 있습니다.
- 이제 선택한 텍스트가 훨씬 더 잘 표시됩니다(사용자 지정도 가능!).
- 여러 신뢰성 버그, 편의 문제 및 성가신 사항이 수정되었습니다.
자세한 내용은 GitHub 릴리스 페이지를 참조하세요.
</ReleaseNotes>
<ScreenshotCaptions>

View File

@@ -56,14 +56,7 @@ Este é um projeto de código aberto e a participação da comunidade é bem-vin
<ReleaseNotes>
Versão __VERSION_NUMBER__
- Reescrevemos a forma como os aplicativos de console são hospedados no Terminal! Certifique-se de reportar os bugs que você encontrar.
- O terminal agora é compatível com o Sixels!
- Agora você pode abrir um painel acoplado contendo snippets de comandos que você salvou para usar mais tarde
- Os usuários do Prompt de Comando na versão mais recente do Windows 11 podem ver um ícone de "dica rápida", que sugere softwares instaláveis a partir do WinGet
- O texto selecionado agora ficará muito mais visível (e personalizável!)
- Vários bugs de confiabilidade, problemas de conveniência e incômodos foram resolvidos.
Confira nossa página de lançamentos no GitHub para obter mais detalhes.
Consulte nossa página de lançamentos do GitHub para obter detalhes adicionais.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
Vėѓѕіöй __VERSION_NUMBER__ !!! !!! !
- Ẁē'νё ŕéẁѓĭτťёñ ћοώ ĉòπşõℓε άррℓіċªťįõпѕ αяе ĥθѕťэđ įŋšιďé Ţєямїńąℓ! Рļéаšė яёροřτ αņу ьϋģš ýõμ éпćŏџήţęя. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!
- Ţëямΐʼnαļ ńóẃ ŝüррöятš Śїхέłś! !!! !!! !!!
- ¥оų ĉåи ńòŵ θρėñ д đбčĸэď ράńέļ ċőлŧăīņϊňģ śⁿіφφëťś оƒ ςōмmàⁿďş ŷŏũ ĥªν℮ şåνěđ τσ üśε łαťэŗ !!! !!! !!! !!! !!! !!! !!! !!! !!!
- Ćοмmäлđ Рřōmφť üş℮ŗѕ öη τће ļāťëšτ Щīйđôώѕ 11 řёℓеаѕĕ måў ŝэε ά "qůïςκ ŧĭр" ιсôñ τĥдт šűğģєѕŧѕ ίńśŧăłłавļз šôƒţẁαгέ ƒґόm ЩĩйĞéţ !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
- Śєļèċťєď ţĕжт ωϊŀļ йǿẃ ьέ mџ¢н мǿѓε νĭŝϊъļė (άŋđ сŭŝтŏмΐżдьļē!) !!! !!! !!! !!! !!! !!! !
- Ä ņϋmъŗ ŏƒ ѓēŀїаъïļŧÿ ьüĝś, ςôⁿνėηĭ℮иć℮ îѕšůëş ăπð âлňбγдňçėŝ ћªνε ъēёп ƒΐ×еð. !!! !!! !!! !!! !!! !!! !!! !!!
Ρĺёàŝ℮ ŝез ǿúг ĢīťНŭъ řěłεαśèŝ φāğ℮ ƒóѓ дďδітĭøиąℓ ð℮тªїľŝ. !!! !!! !!! !!! !!! !!!
Рļєάśé ѕέę όüґ ĢίŧĦŭв řęļзąѕєš рαġè ƒőŗ äđδĭτíθņâℓ đέтαιľś. !!! !!! !!! !!! !!! !!!
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
Vėѓѕіöй __VERSION_NUMBER__ !!! !!! !
- Ẁē'νё ŕéẁѓĭτťёñ ћοώ ĉòπşõℓε άррℓіċªťįõпѕ αяе ĥθѕťэđ įŋšιďé Ţєямїńąℓ! Рļéаšė яёροřτ αņу ьϋģš ýõμ éпćŏџήţęя. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!
- Ţëямΐʼnαļ ńóẃ ŝüррöятš Śїхέłś! !!! !!! !!!
- ¥оų ĉåи ńòŵ θρėñ д đбčĸэď ράńέļ ċőлŧăīņϊňģ śⁿіφφëťś оƒ ςōмmàⁿďş ŷŏũ ĥªν℮ şåνěđ τσ üśε łαťэŗ !!! !!! !!! !!! !!! !!! !!! !!! !!!
- Ćοмmäлđ Рřōmφť üş℮ŗѕ öη τће ļāťëšτ Щīйđôώѕ 11 řёℓеаѕĕ måў ŝэε ά "qůïςκ ŧĭр" ιсôñ τĥдт šűğģєѕŧѕ ίńśŧăłłавļз šôƒţẁαгέ ƒґόm ЩĩйĞéţ !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
- Śєļèċťєď ţĕжт ωϊŀļ йǿẃ ьέ mџ¢н мǿѓε νĭŝϊъļė (άŋđ сŭŝтŏмΐżдьļē!) !!! !!! !!! !!! !!! !!! !
- Ä ņϋmъŗ ŏƒ ѓēŀїаъïļŧÿ ьüĝś, ςôⁿνėηĭ℮иć℮ îѕšůëş ăπð âлňбγдňçėŝ ћªνε ъēёп ƒΐ×еð. !!! !!! !!! !!! !!! !!! !!! !!!
Ρĺёàŝ℮ ŝез ǿúг ĢīťНŭъ řěłεαśèŝ φāğ℮ ƒóѓ дďδітĭøиąℓ ð℮тªїľŝ. !!! !!! !!! !!! !!! !!!
Рļєάśé ѕέę όüґ ĢίŧĦŭв řęļзąѕєš рαġè ƒőŗ äđδĭτíθņâℓ đέтαιľś. !!! !!! !!! !!! !!! !!!
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
Vėѓѕіöй __VERSION_NUMBER__ !!! !!! !
- Ẁē'νё ŕéẁѓĭτťёñ ћοώ ĉòπşõℓε άррℓіċªťįõпѕ αяе ĥθѕťэđ įŋšιďé Ţєямїńąℓ! Рļéаšė яёροřτ αņу ьϋģš ýõμ éпćŏџήţęя. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!
- Ţëямΐʼnαļ ńóẃ ŝüррöятš Śїхέłś! !!! !!! !!!
- ¥оų ĉåи ńòŵ θρėñ д đбčĸэď ράńέļ ċőлŧăīņϊňģ śⁿіφφëťś оƒ ςōмmàⁿďş ŷŏũ ĥªν℮ şåνěđ τσ üśε łαťэŗ !!! !!! !!! !!! !!! !!! !!! !!! !!!
- Ćοмmäлđ Рřōmφť üş℮ŗѕ öη τће ļāťëšτ Щīйđôώѕ 11 řёℓеаѕĕ måў ŝэε ά "qůïςκ ŧĭр" ιсôñ τĥдт šűğģєѕŧѕ ίńśŧăłłавļз šôƒţẁαгέ ƒґόm ЩĩйĞéţ !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
- Śєļèċťєď ţĕжт ωϊŀļ йǿẃ ьέ mџ¢н мǿѓε νĭŝϊъļė (άŋđ сŭŝтŏмΐżдьļē!) !!! !!! !!! !!! !!! !!! !
- Ä ņϋmъŗ ŏƒ ѓēŀїаъïļŧÿ ьüĝś, ςôⁿνėηĭ℮иć℮ îѕšůëş ăπð âлňбγдňçėŝ ћªνε ъēёп ƒΐ×еð. !!! !!! !!! !!! !!! !!! !!! !!!
Ρĺёàŝ℮ ŝез ǿúг ĢīťНŭъ řěłεαśèŝ φāğ℮ ƒóѓ дďδітĭøиąℓ ð℮тªїľŝ. !!! !!! !!! !!! !!! !!!
Рļєάśé ѕέę όüґ ĢίŧĦŭв řęļзąѕєš рαġè ƒőŗ äđδĭτíθņâℓ đέтαιľś. !!! !!! !!! !!! !!! !!!
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
Версия __VERSION_NUMBER__
Мы переписали, как консольные приложения размещаются внутри Терминала! Сообщайте о любых ошибках, с которыми вы столкнулись.
Терминал теперь поддерживает форматы Sixel!
Теперь вы можете открыть закрепленную панель, содержащую фрагменты команд, которые вы сохранили для использования в дальнейшем
Пользователи командной строки в новейшем выпуске Windows 11 могут увидеть значок "краткой подсказки", который предлагает устанавливаемые программы из WinGet
Выделенный текст теперь станет более видимым (и настраиваемым!)
Исправлено несколько ошибок надежности, проблем с удобством, а также устранены раздражающие моменты.
Дополнительные сведения см. на странице выпусков GitHub.
Дополнительные сведения см. на странице «Выпуски GitHub».
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -54,14 +54,7 @@
</DevStudio>
<ReleaseNotes>
Version __VERSION_NUMBER__
- 我们已改变主机应用程序在终端内的托管方式!请报告遇到的任何 bug。
- 终端现在支持 Sixels!
- 现在可以打开一个停靠面板,其中包含已保存供以后使用的命令片段
- 最新 Windows 11 版本上的命令提示用户可能会看到“快速提示”图标,该图标建议从 WinGet 安装软件
- 所选文本现在将具有更高的可见性(和可自定义性!)
- 修复了许多可靠性 bug、便利性问题和令人烦恼的问题。
版本 __VERSION_NUMBER__
有关其他详细信息,请参阅我们的 GitHub 发布页面。
</ReleaseNotes>

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
版本 __VERSION_NUMBER__
- 我們已重寫主機應用程式在終端機內託管的方式!請報告您遇到的錯誤
- 終端機現在支援 Sixels!
- 現在,您可以開啟包含已儲存命令程式碼片段的固定面板,以供稍後使用
- 最新 Windows 11 版本中的 [命令提示] 使用者可能會看到「快速提示」圖示,建議可自 WinGet 安裝的軟體
- 選取的文字現在會更明顯 (且可自訂!)
- 已修正一些可靠性錯誤、便利性問題和令人困擾的問題。
如需更多詳細資訊,請參閱我們的 GitHub 發行頁面。
如需詳細資訊,請參閱我們的 GitHub 版本頁面
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@ Dies ist ein Open Source-Projekt, und wir freuen uns über die Teilnahme an der
<ReleaseNotes>
Version __VERSION_NUMBER__
Terminal speichert jetzt den Inhalt des Fensters, wenn Sie die Sitzungswiederherstellung verwenden.
Sie können jetzt mehrere Schriftarten gleichzeitig verwenden.
Kästchenzeichnende Zeichen werden jetzt pixelgenau gerendert.
Die Verwendung eines IME innerhalb des Terminals wurde erheblich verbessert.
Die Farbschemas in Ihrer JSON-Datei sind jetzt viel einfacher.
Eine Reihe von Fehlern im Zusammenhang mit der URL-Verarbeitung, Zeilen mit doppelter Breite, Zeilenumbruch und mehr wurden behoben.
Weitere Informationen finden Sie auf unserer GitHub-Releaseseite.
Weitere Einzelheiten finden Sie auf der Seite der GitHub-Veröffentlichungen.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,13 +56,6 @@ This is an open source project and we welcome community participation. To partic
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=__VERSION_NUMBER__} App Release Note" -->Version __VERSION_NUMBER__
- Terminal will now remember the contents of the window when you use session restoration.
- You can now use multiple fonts at the same time.
- Box-drawing characters are now rendered with pixel perfection.
- The experience of using an IME inside Terminal has been significantly improved.
- The color schemes inside your JSON file will now be much simpler.
- A number of bugs around URL handling, double-width rows, line wrapping, and more have been fixed.
Please see our GitHub releases page for additional details.
</ReleaseNotes>
<ScreenshotCaptions>

View File

@@ -56,14 +56,7 @@ Este es un proyecto de fuente abierta y animamos a la comunidad a participar. Pa
<ReleaseNotes>
Versión __VERSION_NUMBER__
- Terminal recordará ahora el contenido de la ventana cuando use la restauración de la sesión.
- Ahora puede usar varias fuentes al mismo tiempo.
- Los caracteres que dibujan recuadros ahora se representan con precisión de píxel.
- Se ha mejorado significativamente la experiencia de utilizar un IME dentro de Terminal.
- Las combinaciones de colores dentro del archivo JSON ahora serán mucho más sencillas.
- Se han corregido varios errores relacionados con el control de direcciones URL, las filas de ancho doble, el ajuste de líneas y mucho más.
Consulte la página de versiones de GitHub para más información.
Para más información, consulte nuestra página de versiones de GitHub.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@ Il sagit dun projet open source et nous encourageons la participation à l
<ReleaseNotes>
Version __VERSION_NUMBER__
- Le terminal mémorisera désormais le contenu de la fenêtre lorsque vous utiliserez la restauration de session.
- Vous pouvez désormais utiliser plusieurs polices en même temps.
- Les personnages dessinés en boîte sont désormais rendus avec une perfection de pixel.
- L'expérience d'utilisation d'un IME dans le Terminal a été considérablement améliorée.
- Les schémas de couleurs à l'intérieur de votre fichier JSON seront désormais beaucoup plus simples.
- Un certain nombre de bugs concernant la gestion des URL, les lignes à double largeur, le retour à la ligne, etc. ont été corrigés.
Veuillez consulter notre page de versions GitHub pour plus de détails.
Consultez la page des versions de GitHub pour plus dinformations.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -54,16 +54,9 @@ Si tratta di un progetto open source e la partecipazione della community è molt
</DevStudio>
<ReleaseNotes>
Versione __VERSION_NUMBER__
Versione __VERSION_NUMBER__
- Il terminale ricorda ora il contenuto della finestra quando si usa il ripristino della sessione.
- È ora possibile usare più tipi di carattere contemporaneamente.
- I caratteri tracciati vengono ora sottoposti a rendering con pixel di perfezionamento.
- L'esperienza di utilizzo di un IME all'interno di Terminale è stata notevolmente migliorata.
- Le combinazioni di colori all'interno del file JSON saranno ora molto più semplici.
- Sono stati corretti alcuni bug relativi alla gestione degli URL, alle righe a doppia larghezza, al ritorno a capo delle righe e altro ancora.
Per altri dettagli, vedi la pagina delle versioni di GitHub.
Per ulteriori dettagli, consulta la nostra pagina delle versioni di GitHub.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
バージョン __VERSION_NUMBER__
- セッションの復元を使用すると、ターミナルがウィンドウの内容を記憶するようになりました
- 複数のフォントを同時に使用できるようになりました。
- ボックス描画文字がピクセル単位の精度でレンダリングされるようになりました。
- ターミナル内での IME の使用エクスペリエンスが大幅に改善されました。
- JSON ファイル内の配色がはるかにシンプルになりました。
- URL 処理、二重幅の行、行の折り返しなどに関するいくつかのバグが修正されました。
詳細については、GitHub リリース ページをご覧ください。
詳細については、GitHub リリースのページをご覧ください
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,13 +56,6 @@
<ReleaseNotes>
버전 __VERSION_NUMBER__
- 터미널은 이제 세션 복원을 사용할 때 창의 내용을 기억합니다.
- 이제 여러 글꼴을 동시에 사용할 수 있습니다.
- 상자 그리기 캐릭터가 이제 픽셀 완성도로 렌더링됩니다.
- 터미널 내에서 IME를 사용하는 환경이 크게 개선되었습니다.
- 이제 JSON 파일 내의 색 구성표가 훨씬 더 간단해집니다.
- URL 처리, 이중 너비 행, 줄 바꿈 등과 관련된 여러 버그가 수정되었습니다.
자세한 내용은 GitHub 릴리스 페이지를 참조하세요.
</ReleaseNotes>
<ScreenshotCaptions>

View File

@@ -56,14 +56,7 @@ Este é um projeto de código aberto e a participação da comunidade é bem-vin
<ReleaseNotes>
Versão __VERSION_NUMBER__
- O terminal agora se lembra do conteúdo da janela quando você usa a restauração de sessão.
- Agora você pode usar várias fontes ao mesmo tempo.
- Os caracteres da caixa de desenho agora são renderizados com a perfeição de pixels.
- A experiência de usar uma IME dentro do Terminal foi significativamente aprimorada.
- Os esquemas de cores dentro do seu arquivo JSON agora estão muito mais simples.
- Foram corrigidos vários bugs envolvendo o tratamento de URLs, linhas de largura dupla, quebra de linha automática e muito mais.
Confira nossa página de lançamentos no GitHub para obter mais detalhes.
Consulte nossa página de lançamentos do GitHub para obter detalhes adicionais.
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
Vėѓѕіöй __VERSION_NUMBER__ !!! !!! !
- Ŧēгмíйǻŀ шιļł ñσщ řėmėmвзґ τђз ςоńţëηťŝ σƒ ŧћé ẅιⁿδőщ ẅђеή ýóύ ŭš℮ şεššîóŋ řėşτŏѓдτіόŋ. !!! !!! !!! !!! !!! !!! !!! !!! !!!
- Ύоџ ςàⁿ ŋóώ ũşэ múľŧìφľё ƒоʼnťş àт ťħе ѕâmз тìме. !!! !!! !!! !!! !!!
- Вό×-ðгăшĭиġ ¢ĥаяäςтеřѕ äřę ηоẁ ѓëńđêяεď ẁϊτђ φïжêĺ φėŗƒēςŧΐøй. !!! !!! !!! !!! !!! !!! !
- Ťħέ ĕхφêŕï℮ηĉε ŏƒ ύѕïйġ ǻʼn ÎМË îńšïďê Τєřmíлäļ нαŝ ьēέň ѕιĝήîƒіčäπţŀý ĩмφґθνзđ. !!! !!! !!! !!! !!! !!! !!! !!!
- Ťĥę čöℓοг şçђėmęš ιʼnśΐδê убџѓ ĴŠОИ ƒϊŀε ωĭŀł ʼnθω вз мúçĥ ѕїмρℓёґ. !!! !!! !!! !!! !!! !!! !!
- Á ήũmьéŕ òƒ вµġŝ άřòūñδ ÛҐĿ ħàŋδľįйģ, ðőџъŀε-ŵĭďτђ ŗōẁš, ŀϊπė ẃяąрρΐηğ, âⁿđ мŏř℮ ĥāνě везŋ ƒï×έð. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
Ρļēªšê ŝέė őůг ĜīтĤųъ яëŀεäśēś рдġэ ƒõя ãδðìτϊöňãł δèτâĩĺѕ. !!! !!! !!! !!! !!! !!!
Рļєάśé ѕέę όüґ ĢίŧĦŭв řęļзąѕєš рαġè ƒőŗ äđδĭτíθņâℓ đέтαιľś. !!! !!! !!! !!! !!! !!!
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
Vėѓѕіöй __VERSION_NUMBER__ !!! !!! !
- Ŧēгмíйǻŀ шιļł ñσщ řėmėmвзґ τђз ςоńţëηťŝ σƒ ŧћé ẅιⁿδőщ ẅђеή ýóύ ŭš℮ şεššîóŋ řėşτŏѓдτіόŋ. !!! !!! !!! !!! !!! !!! !!! !!! !!!
- Ύоџ ςàⁿ ŋóώ ũşэ múľŧìφľё ƒоʼnťş àт ťħе ѕâmз тìме. !!! !!! !!! !!! !!!
- Вό×-ðгăшĭиġ ¢ĥаяäςтеřѕ äřę ηоẁ ѓëńđêяεď ẁϊτђ φïжêĺ φėŗƒēςŧΐøй. !!! !!! !!! !!! !!! !!! !
- Ťħέ ĕхφêŕï℮ηĉε ŏƒ ύѕïйġ ǻʼn ÎМË îńšïďê Τєřmíлäļ нαŝ ьēέň ѕιĝήîƒіčäπţŀý ĩмφґθνзđ. !!! !!! !!! !!! !!! !!! !!! !!!
- Ťĥę čöℓοг şçђėmęš ιʼnśΐδê убџѓ ĴŠОИ ƒϊŀε ωĭŀł ʼnθω вз мúçĥ ѕїмρℓёґ. !!! !!! !!! !!! !!! !!! !!
- Á ήũmьéŕ òƒ вµġŝ άřòūñδ ÛҐĿ ħàŋδľįйģ, ðőџъŀε-ŵĭďτђ ŗōẁš, ŀϊπė ẃяąрρΐηğ, âⁿđ мŏř℮ ĥāνě везŋ ƒï×έð. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
Ρļēªšê ŝέė őůг ĜīтĤųъ яëŀεäśēś рдġэ ƒõя ãδðìτϊöňãł δèτâĩĺѕ. !!! !!! !!! !!! !!! !!!
Рļєάśé ѕέę όüґ ĢίŧĦŭв řęļзąѕєš рαġè ƒőŗ äđδĭτíθņâℓ đέтαιľś. !!! !!! !!! !!! !!! !!!
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
Vėѓѕіöй __VERSION_NUMBER__ !!! !!! !
- Ŧēгмíйǻŀ шιļł ñσщ řėmėmвзґ τђз ςоńţëηťŝ σƒ ŧћé ẅιⁿδőщ ẅђеή ýóύ ŭš℮ şεššîóŋ řėşτŏѓдτіόŋ. !!! !!! !!! !!! !!! !!! !!! !!! !!!
- Ύоџ ςàⁿ ŋóώ ũşэ múľŧìφľё ƒоʼnťş àт ťħе ѕâmз тìме. !!! !!! !!! !!! !!!
- Вό×-ðгăшĭиġ ¢ĥаяäςтеřѕ äřę ηоẁ ѓëńđêяεď ẁϊτђ φïжêĺ φėŗƒēςŧΐøй. !!! !!! !!! !!! !!! !!! !
- Ťħέ ĕхφêŕï℮ηĉε ŏƒ ύѕïйġ ǻʼn ÎМË îńšïďê Τєřmíлäļ нαŝ ьēέň ѕιĝήîƒіčäπţŀý ĩмφґθνзđ. !!! !!! !!! !!! !!! !!! !!! !!!
- Ťĥę čöℓοг şçђėmęš ιʼnśΐδê убџѓ ĴŠОИ ƒϊŀε ωĭŀł ʼnθω вз мúçĥ ѕїмρℓёґ. !!! !!! !!! !!! !!! !!! !!
- Á ήũmьéŕ òƒ вµġŝ άřòūñδ ÛҐĿ ħàŋδľįйģ, ðőџъŀε-ŵĭďτђ ŗōẁš, ŀϊπė ẃяąрρΐηğ, âⁿđ мŏř℮ ĥāνě везŋ ƒï×έð. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
Ρļēªšê ŝέė őůг ĜīтĤųъ яëŀεäśēś рдġэ ƒõя ãδðìτϊöňãł δèτâĩĺѕ. !!! !!! !!! !!! !!! !!!
Рļєάśé ѕέę όüґ ĢίŧĦŭв řęļзąѕєš рαġè ƒőŗ äđδĭτíθņâℓ đέтαιľś. !!! !!! !!! !!! !!! !!!
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
Версия __VERSION_NUMBER__
Терминал теперь будет запоминать содержимое окна при восстановлении сеанса.
Теперь вы можете использовать несколько шрифтов одновременно.
Символы псевдографики теперь отрисовываются с пиксельной точностью.
Значительно улучшена возможность использования IME внутри Терминала.
Цветовые схемы в JSON-файле теперь будут намного проще.
Исправлено несколько ошибок в обработке URL-адресов, строках двойной ширины, переносе строк и т. д.
Дополнительные сведения см. на странице выпусков GitHub.
Дополнительные сведения см. на странице «Выпуски GitHub».
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -54,14 +54,7 @@
</DevStudio>
<ReleaseNotes>
Version __VERSION_NUMBER__
- 现在,使用会话还原时,终端将记住窗口的内容。
- 现在可以同时使用多种字体。
- 现在以像素为单位呈现框绘图字符。
- 在终端内使用输入法的体验已得到显著提升。
- JSON 文件中的配色方案现在要简单得多。
- 已修复有关 URL 处理、双倍行宽、换行等大量 bug。
版本 __VERSION_NUMBER__
有关其他详细信息,请参阅我们的 GitHub 发布页面。
</ReleaseNotes>

View File

@@ -56,14 +56,7 @@
<ReleaseNotes>
版本 __VERSION_NUMBER__
- 當您使用工作階段還原時,終端機現在會記住視窗的內容
- 現在您可以同時使用多個字型。
- 製表格圖字元現在會以完美像素模式呈現。
- 在終端機內使用 IME 的體驗已大幅改善。
- JSON 檔案內的色彩配置現在將變得更簡單了。
- 已修正一些 URL 處理、雙寬度列、換行等相關錯誤。
如需更多詳細資訊,請參閱我們的 GitHub 發行頁面。
如需詳細資訊,請參閱我們的 GitHub 版本頁面
</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->

View File

@@ -1,6 +1,6 @@
{
"instanceUrl": "https://microsoft.visualstudio.com",
"projectName": "OS",
"areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\Terminal",
"areaPath": "OS\\Windows Client and Services\\ADEPT\\E4D-Engineered for Developers\\SHINE\\Terminal",
"notificationAliases": ["condev@microsoft.com", "duhowett@microsoft.com"]
}

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
<package id="Microsoft.Taef" version="10.93.240607003" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
<package id="Microsoft.Debugging.Tools.PdbStr" version="20220617.1556.0" targetFramework="native" />
<package id="Microsoft.Debugging.Tools.SrcTool" version="20220617.1556.0" targetFramework="native" />

View File

@@ -28,7 +28,7 @@ extends:
official: true
branding: Canary
buildTerminal: true
pgoBuildMode: None # BODGY - OneBranch is on VS 17.10, which is known to be the worst
pgoBuildMode: Optimize
codeSign: true
signingIdentity:
serviceName: $(SigningServiceName)

View File

@@ -27,7 +27,7 @@ parameters:
- name: pgoBuildMode
displayName: "PGO Build Mode"
type: string
default: None # BODGY - OneBranch is on VS 17.10, which is known to be the worst
default: Optimize
values:
- Optimize
- Instrument

View File

@@ -59,7 +59,10 @@ jobs:
submodules: true
persistCredentials: True
- template: steps-setup-versioning.yml
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: steps-download-bin-dir-artifact.yml
parameters:

View File

@@ -159,10 +159,10 @@ jobs:
.\build\scripts\Generate-ThirdPartyNotices.ps1 -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
displayName: Generate NOTICE.html from NOTICE.md
- template: .\steps-install-vcpkg.yml
- template: .\steps-restore-nuget.yml
- template: .\steps-install-vcpkg.yml
- pwsh: |-
.\build\scripts\Set-LatestVCToolsVersion.ps1
displayName: Work around DD-1541167 (VCToolsVersion)

View File

@@ -10,6 +10,6 @@ jobs:
submodules: false
clean: true
- pwsh: |-
- powershell: |-
.\build\scripts\Invoke-FormattingCheck.ps1
displayName: 'Run formatters'

View File

@@ -69,9 +69,10 @@ jobs:
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
submodules: true
persistCredentials: True
- template: steps-setup-versioning.yml
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: steps-download-bin-dir-artifact.yml
parameters:
buildPlatforms: ${{ parameters.buildPlatforms }}

View File

@@ -57,7 +57,10 @@ jobs:
submodules: true
persistCredentials: True
- template: steps-setup-versioning.yml
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: steps-download-bin-dir-artifact.yml
parameters:

View File

@@ -44,7 +44,10 @@ jobs:
submodules: true
persistCredentials: True
- template: steps-setup-versioning.yml
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: DownloadPipelineArtifact@2
displayName: Download all PDBs from all prior build phases

View File

@@ -43,7 +43,10 @@ jobs:
submodules: true
persistCredentials: True
- template: steps-setup-versioning.yml
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: DownloadPipelineArtifact@2
displayName: Download all PDBs from all prior build phases

View File

@@ -38,7 +38,10 @@ jobs:
submodules: true
persistCredentials: True
- template: steps-setup-versioning.yml
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: DownloadPipelineArtifact@2
displayName: Download MSIX Bundle Artifact

View File

@@ -92,7 +92,10 @@ stages:
generateSbom: ${{ parameters.generateSbom }}
codeSign: ${{ parameters.codeSign }}
beforeBuildSteps: # Right before we build, lay down the universal package and localizations
- template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: UniversalPackages@0
displayName: Download terminal-internal Universal Package
@@ -116,7 +119,10 @@ stages:
generateSbom: ${{ parameters.generateSbom }}
codeSign: ${{ parameters.codeSign }}
beforeBuildSteps:
- template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
# WPF doesn't need the localizations or the universal package, but if it does... put them here.
- stage: Package

View File

@@ -106,6 +106,11 @@ extends:
- stage: Build
displayName: Build
dependsOn: []
variables:
# This was set by the parent build, but we need to override it to select a specific compiler version
- template: ./build/pipelines/templates-v2/variables-onebranch-config.yml@self
parameters:
containerVersion: 1.0.02566.28
jobs:
- template: ./build/pipelines/templates-v2/job-build-project.yml@self
parameters:
@@ -130,7 +135,10 @@ extends:
codeSign: ${{ parameters.codeSign }}
signingIdentity: ${{ parameters.signingIdentity }}
beforeBuildSteps: # Right before we build, lay down the universal package and localizations
- template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: UniversalPackages@0
displayName: Download terminal-internal Universal Package
@@ -164,7 +172,10 @@ extends:
codeSign: ${{ parameters.codeSign }}
signingIdentity: ${{ parameters.signingIdentity }}
beforeBuildSteps:
- template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
# WPF doesn't need the localizations or the universal package, but if it does... put them here.
- stage: Package

View File

@@ -1,6 +0,0 @@
steps:
- pwsh: |-
nuget install Microsoft.Windows.Terminal.Versioning -OutputDirectory _versioning
$VersionRoot = (Get-Item _versioning\Microsoft.Windows.*).FullName
& "$VersionRoot\build\Setup.ps1" -ProjectDirectory "$(Build.SourcesDirectory)" -Verbose
displayName: Set up versioning via M.W.T.V

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE in the project root for license information. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Native-Platform Condition="'$(Platform)' == 'Win32'">x86</Native-Platform>
<Native-Platform Condition="'$(Platform)' != 'Win32'">$(Platform)</Native-Platform>
</PropertyGroup>
<ItemGroup>
<Reference Include="$(WinGetPackageRoot)\lib\Microsoft.Management.Deployment.winmd">
<IsWinMDFile>true</IsWinMDFile>
</Reference>
</ItemGroup>
<Target Name="_FixWinGetWinmdPackaging" BeforeTargets="_ComputeAppxPackagePayload">
<ItemGroup>
<PackagingOutputs Include="$(WinGetPackageRoot)\lib\Microsoft.Management.Deployment.winmd">
<OutputGroup>CustomOutputGroupForPackaging</OutputGroup>
<ProjectName>$(ProjectName)</ProjectName>
<TargetPath>Microsoft.Management.Deployment.winmd</TargetPath>
</PackagingOutputs>
</ItemGroup>
</Target>
</Project>

View File

@@ -5,7 +5,7 @@
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
<XesBaseYearForStoreVersion>2024</XesBaseYearForStoreVersion>
<VersionMajor>1</VersionMajor>
<VersionMinor>23</VersionMinor>
<VersionMinor>22</VersionMinor>
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
</PropertyGroup>
</Project>

View File

@@ -104,7 +104,6 @@ GetConsoleKeyboardLayoutNameW(
#define CONSOLE_REGISTRY_DEFAULTFOREGROUND L"DefaultForeground"
#define CONSOLE_REGISTRY_DEFAULTBACKGROUND L"DefaultBackground"
#define CONSOLE_REGISTRY_TERMINALSCROLLING L"TerminalScrolling"
#define CONSOLE_REGISTRY_ANSWERBACKMESSAGE L"AnswerbackMessage"
// end V2 console settings
/*

View File

@@ -3,14 +3,13 @@
<packages>
<!-- Native packages -->
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
<package id="Microsoft.Taef" version="10.93.240607003" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.7.230706001" targetFramework="native" />
<package id="Microsoft.VisualStudio.Setup.Configuration.Native" version="2.3.2262" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.UI.Xaml" version="2.8.4" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.240122.1" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.WindowsPackageManager.ComInterop" version="1.8.1911" targetFramework="native" developmentDependency="true" />
<!-- Managed packages -->
<package id="Appium.WebDriver" version="3.0.0.2" targetFramework="net45" />
@@ -20,7 +19,7 @@
<package id="Selenium.WebDriver" version="3.5.0" targetFramework="net45" />
<!-- MSBuildCache -->
<package id="Microsoft.MSBuildCache.AzurePipelines" version="0.1.283-preview" />
<package id="Microsoft.MSBuildCache.Local" version="0.1.283-preview" />
<package id="Microsoft.MSBuildCache.SharedCompilation" version="0.1.283-preview" />
<package id="Microsoft.MSBuildCache.AzurePipelines" version="0.1.273-preview" />
<package id="Microsoft.MSBuildCache.Local" version="0.1.273-preview" />
<package id="Microsoft.MSBuildCache.SharedCompilation" version="0.1.273-preview" />
</packages>

View File

@@ -618,11 +618,6 @@
"type": "boolean",
"default": false,
"description": "This will override the profile's `elevate` setting."
},
"reloadEnvironmentVariables": {
"type": "boolean",
"default": true,
"description": "When set to true, a new environment block will be generated when creating a new session. Otherwise, the session will inherit the variables the Terminal was started with."
}
},
"type": "object"
@@ -733,9 +728,6 @@
"type": "string",
"default": "",
"description": "The name or GUID of the profile to show in this entry"
},
"icon": {
"$ref": "#/$defs/Icon"
}
}
}
@@ -807,9 +799,6 @@
"type": "string",
"default": "",
"description": "The ID of the action to show in this entry"
},
"icon": {
"$ref": "#/$defs/Icon"
}
}
}
@@ -885,11 +874,6 @@
"default": false,
"description": "If true, the copied content will be copied as a single line (even if there are hard line breaks present in the text). If false, newlines persist from the selected text."
},
"withControlSequences": {
"type": "boolean",
"default": false,
"description": "If true, copied content will contain ANSI escape code control sequences representing the styling of the content."
},
"dismissSelection": {
"type": "boolean",
"default": true,
@@ -2351,7 +2335,7 @@
"description": "When set to `true`, the terminal window will auto-center itself on the display it opens on. The terminal will use the \"initialPosition\" to determine which display to open on.",
"type": "boolean"
},
"warning.inputService": {
"inputServiceWarning": {
"default": true,
"description": "Warning if 'Touch Keyboard and Handwriting Panel Service' is disabled.",
"type": "boolean"
@@ -2366,21 +2350,11 @@
"description": "When set to true, the terminal will focus the pane on mouse hover.",
"type": "boolean"
},
"compatibility.allowHeadless": {
"default": false,
"description": "When set to true, Windows Terminal will run in the background. This allows globalSummon and quakeMode actions to work even when no windows are open.",
"type": "boolean"
},
"compatibility.isolatedMode": {
"default": false,
"description": "When set to true, Terminal windows will not be able to interact with each other (including global hotkeys, tab drag/drop, running commandlines in existing windows, etc.). This is a compatibility escape hatch for users who are running into certain windowing issues.",
"type": "boolean"
},
"compatibility.allowDECRQCRA": {
"default": false,
"description": "When set to true, the terminal will support the DECRQCRA (Request Checksum of Rectangular Area) escape sequence.",
"type": "boolean"
},
"copyFormatting": {
"default": true,
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.",
@@ -2411,12 +2385,12 @@
"description": "When set to `true`, visual animations will be disabled across the application.",
"type": "boolean"
},
"warning.largePaste": {
"largePasteWarning": {
"default": true,
"description": "When set to true, trying to paste text with more than 5 KiB of characters will display a warning asking you whether to continue or not with the paste.",
"type": "boolean"
},
"warning.multiLinePaste": {
"multiLinePasteWarning": {
"default": true,
"description": "When set to true, trying to paste text with a \"new line\" character will display a warning asking you whether to continue or not with the paste.",
"type": "boolean"
@@ -2614,7 +2588,7 @@
"description": "Determines the delimiters used in a double click selection.",
"type": "string"
},
"warning.confirmCloseAllTabs": {
"confirmCloseAllTabs": {
"default": true,
"description": "When set to \"true\" closing a window with multiple tabs open will require confirmation. When set to \"false\", the confirmation dialog will not appear.",
"type": "boolean"
@@ -2876,7 +2850,7 @@
}
},
"autoMarkPrompts": {
"default": true,
"default": false,
"description": "When set to true, prompts will automatically be marked.",
"type": "boolean"
},
@@ -3058,10 +3032,6 @@
"description": "By default Windows treats Ctrl+Alt as an alias for AltGr. When altGrAliasing is set to false, this behavior will be disabled.",
"type": "boolean"
},
"answerbackMessage": {
"description": "The response that is sent when an ENQ control character is received.",
"type": "string"
},
"source": {
"description": "Stores the name of the profile generator that originated this profile.",
"type": [
@@ -3100,17 +3070,6 @@
"default": false,
"description": "When set to true, the window will have an acrylic material background. When set to false, the window will have a plain, untextured background.",
"type": "boolean"
},
"pathTranslationStyle": {
"default": "none",
"description": "Controls how file paths are transformed when they are dragged and dropped on the terminal. Possible values are \"none\", \"wsl\", \"cygwin\" and \"msys2\".",
"enum": [
"none",
"wsl",
"cygwin",
"msys2"
],
"type": "string"
}
}
},

View File

@@ -1,840 +0,0 @@
---
author: Leonard Hecker @lhecker
created on: 2024-06-07
last updated: 2024-06-07
issue id: 13000
---
# In-process ConPTY
## tl;dr
**Why?**
* Out-of-process leads to out-of-sync issues.
* Not all Console APIs have a VT equivalent.
* Time consuming maintenance work due to poor encapsulation inside conhost.
**How?**
1. Remove `VtEngine` and translate Console API calls directly to VT.
2. Move all Console API related code from the `Host` to the `Server` project.
Narrow the `IApiRoutines` interface down to its essentials.
Replace relevant singletons with instances.
3. Make `Server` a standalone library with `IApiRoutines` as its primary callback interface.
Integrate the library in Windows Terminal.
4. (Long term goal:) Ship the `Server` library as part of Windows. Build conhost itself on top of it.
## Why?
**Before:**
```mermaid
%%{ init: { "flowchart": { "curve": "monotoneX" } } }%%
flowchart TD
subgraph conhost
direction LR
subgraph Server
server_io[Console API calls]
end
subgraph ConPTY
VtIo
VtEngine
ConPTY_output[ConPTY Output]
end
conhost_parser[VT parser]
conhost_buffer[Text Buffer]
conhost_renderer[Render Thread]
conhost_atlas[Text Renderer]
server_io-->conhost_parser
server_io--scroll, clear, etc.-->VtIo
conhost_parser--resize, focus-->VtIo
VtIo--scroll, clear, etc.-->VtEngine
conhost_parser--unknown escape sequences-->VtEngine
conhost_buffer--manual flushing-->VtEngine
conhost_renderer-->VtEngine
VtEngine-->ConPTY_output
conhost_buffer--dirty rects-->conhost_renderer
conhost_parser--dirty rects-->conhost_renderer
conhost_parser--plain text-->conhost_buffer
conhost_renderer-->conhost_atlas
conhost_buffer--ReadBuffer-->server_io
end
subgraph wt[Windows Terminal]
direction LR
input[ConPTY Input]
parser[VT parser]
buffer[Text Buffer]
renderer[Render Thread]
atlas[Text Renderer]
input-->parser
parser-->buffer
buffer-->renderer
renderer-->atlas
parser-->renderer
end
conhost--ConPTY's text pipe across processes-->wt
```
**After:**
```mermaid
%%{ init: { "flowchart": { "curve": "monotoneX" } } }%%
flowchart LR
subgraph ConPTY_lib["ConPTY (static library)"]
server_io[Console API calls]
ConPTY_Translation[VT Translation]
server_io<-->ConPTY_Translation
end
subgraph ConPTY["ConPTY (dynamic library)"]
ConPTY_impl[IApiRoutines impl]
ConPTY_parser[VT parser]
ConPTY_buffer[Text Buffer]
ConPTY_output[ConPTY Output]
ConPTY_Translation<-->ConPTY_impl
ConPTY_impl-->ConPTY_parser
ConPTY_parser-->ConPTY_buffer
ConPTY_buffer--ReadBuffer-->ConPTY_impl
ConPTY_impl------>ConPTY_output
end
subgraph conhost
conhost_impl[IApiRoutines impl]
conhost_parser[VT parser]
conhost_buffer[Text Buffer]
conhost_renderer[Render Thread]
conhost_atlas[Text Renderer]
ConPTY_Translation<-->conhost_impl
conhost_impl-->conhost_parser
conhost_parser-->conhost_buffer
conhost_buffer--->conhost_renderer
conhost_buffer--ReadBuffer-->conhost_impl
conhost_renderer-->conhost_atlas
end
subgraph wt[Windows Terminal]
impl[IApiRoutines impl]
parser[VT parser]
buffer[Text Buffer]
renderer[Render Thread]
atlas[Text Renderer]
ConPTY_Translation<-->impl
impl-->parser
parser-->buffer
buffer--->renderer
buffer--ReadBuffer-->impl
renderer-->atlas
end
```
To extend on the [tl;dr](#tldr):
* ConPTY runs outside the hosting terminal which leads to an unsolvable issue: The buffer contents between ConPTY and the terminal can go out of sync.
* The terminal and ConPTY may implement escape sequences differently.
* ...may implement text processing differently.
* ...may implement text reflow (resize) differently.
* Resizing the terminal and ConPTY is asynchronous and there may be concurrent text output.
* ...and it may uncover text from the scrollback, which ConPTY doesn't know about.
* Some Console API methods cannot be represented via escape sequences and so ConPTY cannot produce them either.
The most basic example of this is the lack of LVB gridlines.
* The above suggested new architecture represents a significant simplification with no loss in features.
* ConPTY has fulfilled our needs a thousand times over, but as it's layered on top of conhost it has resulted in software decay.
The layer boundary has blurred over the years resulting in debugging and maintenance difficulties.
Lastly, its performance is insufficient and has been subject to much debate.
It's on us now to pay our debt and clean up the architecture so that ConPTY, conhost, and Windows Terminal can be built on top of it.
Considerations:
* A named `MUTEX` can theoretically solve parts of the out-of-sync issue, because it could be used to synchronize buffer reflow.
However, this requires the lock to be acquired on every API call, on top of the regular console lock, which raises ABBA deadlock concerns.
Making this setup not just hopefully but also provably robust, is likely to be very difficult.
It also doesn't solve any of the other listed problems.
## Goal 1: Remove VtEngine
### Goal
```mermaid
%%{ init: { "flowchart": { "curve": "monotoneX" } } }%%
flowchart TD
subgraph conhost
direction LR
subgraph Server
server_io[Console API calls]
end
subgraph ConPTY
VtIo
VtEngine
ConPTY_output[ConPTY Output]
end
conhost_parser[VT parser]
conhost_buffer[Text Buffer]
conhost_renderer[Render Thread]
conhost_atlas[Text Renderer]
server_io-->conhost_parser
server_io--VT translation-->VtIo
server_io-->VtIo
conhost_parser-->VtIo
VtIo-->VtEngine
conhost_parser-->VtEngine
conhost_buffer-->VtEngine
conhost_renderer-->VtEngine
VtIo-->ConPTY_output
VtEngine-->ConPTY_output
conhost_buffer--dirty rects-->conhost_renderer
conhost_parser-->conhost_renderer
conhost_parser--plain text-->conhost_buffer
conhost_renderer-->conhost_atlas
conhost_buffer--ReadBuffer-->server_io
end
subgraph wt[Windows Terminal]
direction LR
input[ConPTY Input]
parser[VT parser]
buffer[Text Buffer]
renderer[Render Thread]
atlas[Text Renderer]
input-->parser
parser-->buffer
buffer-->renderer
renderer-->atlas
parser-->renderer
end
conhost--ConPTY's text pipe across processes-->wt
linkStyle 2,3,4,5,6,7,9,11 opacity:0.2
style VtEngine opacity:0.2
```
### Goals
* Remove VtEngine
* Remove `--vtmode`
* Remove `--resizeQuirk`
* Add buffering to `VtIo` and hook it up to the output pipe
* Implement direct VT translations for all relevant Console APIs
### Discussion
The idea is that we can translate Console API calls directly to VT at least as well as the current VtEngine setup can.
For instance, a call to `SetConsoleCursorPosition` clearly translates directly to a `CUP` escape sequence.
Effectively, instead of translating output asynchronously in the renderer thread, we'll do it synchronously right during the Console API call.
Apart from the Console APIs, the "cooked read" implementation, which handles our builtin "readline"-like text editor, will need to receive some larger changes as well.
Its popups use `ReadConsoleOutput` and `WriteConsoleOutput` to backup and restore the affected rectangle.
It also directly interfaces with the backing text buffer and its translation to VT relies on the existence of VtEngine.
This results in all of the same issues that were previously outlined.
In order to solve this, the popups need to be rewritten to use escape sequences so that they can be directly passed to the hosting terminal.
They should also always be below the current prompt line so that we don't need to perform a potentially lossy backup/restore operation.
The `--vtmode xterm-ascii` switch exists for the telnet client as it only supports ASCII as per RFC854 section "THE NVT PRINTER AND KEYBOARD".
However, telnet is the only user of this flag and it's trivial to do there (for instance by stripping high codepoints in `WriteOutputToClient` in `telnet/console.cpp`), so there's no reason for us to keep this logic in the new code.
This change will result in a significant reduction in complexity of our architecture.
VT input from the shell or other clients will be given 1:1 to the hosting terminal, which will resolve our ordering and buffering issues.
## Goal 2: Move Console API implementations to Server
### Goal
```mermaid
%%{ init: { "flowchart": { "curve": "monotoneX" } } }%%
flowchart TD
subgraph conhost
direction LR
subgraph Server[Server w/ ConPTY]
server_io[Console API calls]
ConPTY_Translation[VT Translation]
server_io<-->ConPTY_Translation
end
subgraph ConPTY
VtIo
ConPTY_output[ConPTY Output]
VtIo-->ConPTY_output
end
conhost_impl[IApiRoutines impl]
conhost_parser[VT parser]
conhost_buffer[Text Buffer]
conhost_renderer[Render Thread]
conhost_atlas[Text Renderer]
output_new[ConPTY Output]
ConPTY_Translation<-->conhost_impl
conhost_impl-->conhost_parser
conhost_impl----->output_new
server_io---->VtIo
server_io-->conhost_parser
conhost_parser-->conhost_buffer
conhost_parser-->conhost_renderer
conhost_buffer-->conhost_renderer
conhost_buffer--ReadBuffer-->conhost_impl
conhost_buffer-->server_io
conhost_renderer-->conhost_atlas
end
subgraph wt[Windows Terminal]
direction LR
input[ConPTY Input]
parser[VT parser]
buffer[Text Buffer]
renderer[Render Thread]
atlas[Text Renderer]
input-->parser
parser-->buffer
buffer-->renderer
renderer-->atlas
parser-->renderer
end
conhost--ConPTY's text pipe across processes-->wt
linkStyle 1,5,6,11 opacity:0.2
style ConPTY opacity:0.2
style VtIo opacity:0.2
style ConPTY_output opacity:0.2
```
### Goals
* Move the API implementation from the `Host` to the `Server` project.
* Narrow down the `IApiRoutines` interface to its essentials.
* Replace affected singletons with regular class instances.
### Discussion
The basic idea is that instead of having 3 arrows going in and out of the Server component, we got exactly 1.
This makes the console server and its VT translation a reusable component, which we need so that we can solve the out-of-sync issues by integrating it into Windows Terminal.
To make the Server API convenient to use, the interface needs to be narrowed down to as few methods as possible. This interface is currently called `IApiRoutines`.
### API Design
Design goals:
* Low overhead<br>
The API should never be the reason why the terminal is slow.
Among others, the design includes both UTF8 and UTF16 functions, as both encodings are common on Windows and the server component should not make assumptions which one the terminal prefers.
* Easy to use<br>
The Console API is unfortunately quite powerful.
In order to make implementing the callback interface still reasonably easy, the API should have as few methods as are needed.
If a complex Console API call can be expressed as a series of simpler ones, and if no other performance expectations exist, it should be expressed via the simpler ones.
* Works even if only partially implemented<br>
Example: `CreateConsoleScreenBuffer` is seldomly used, but its existence adds significant complexity to the callback API design and potential implementations.
A terminal should either be able to return `E_NOTIMPL` and we provide a fallback, or we provide guidance for how reasonable fallbacks can be implemented (e.g. by using the xterm alt buffer in this example).
> [!IMPORTANT]
> The following API design is a rough draft just to convey the general idea.
> It does not represent a complete, finished design.
> This document will be updated once work on the API begins and the actual API requirements become clearer.
```cs
// The Console API is built around a freely addressable frame buffer. It allows you to
// address any part of the buffer, even those outside of what's considered the "viewport":
//
// ┌──────────────────┐
// │y=-3 │
// │ │ ╮
// │ │ │
// ╭ ├──────────────────┤ ├── VT scrollback (partially addressed)
// │ │y=0 │ │
// │ │ │ ╮ ╯
// │ │ │ │
// Console Buffer ──┤ ├──────────────────┤ ├──── VT Viewport (top y = 1)
// │ │y=3 │ │
// │ │ │ ╯
// │ │ │
// ╰ └──────────────────┘
//
// The good news is that nothing prevents you from giving the Console Buffer the exact
// same size as the VT Viewport and for modern terminals doing so is recommended.
// That way, coordinates are viewport-relative and content below/above the viewport is never addressed:
//
// ┌──────────────────┐ ╮
// │y=-3 │ │
// │ │ ├── VT scrollback (unused)
// │ │ │
// ╭ ├──────────────────┤ ╮ ╯
// │ │y=0 │ │
// Console Buffer ──┤ │ │ ├──── VT Viewport
// │ │ │ │
// ╰ └──────────────────┘ ╯
//
// Coordinates are 0-indexed. Note that while INT32 coordinates are used by this API, coordinates below
// 0 and above 65535 are generally invalid as the Console ABI currently uses unsigned 16-Bit integers.
struct CONSRV_POINT_I32 {
INT32 x;
INT32 y;
};
struct CONSRV_POINT_F32 {
float x;
float y;
};
// These flags are also defined via Windows.h.
#if 0
// These flags are equivalent to the classic 4-bit indexed colors in VT via SGR.
// However, the position of the blue and red bits are swapped.
#define FOREGROUND_BLUE 0x0001 // Text color contains blue.
#define FOREGROUND_GREEN 0x0002 // Text color contains green.
#define FOREGROUND_RED 0x0004 // Text color contains red.
#define FOREGROUND_INTENSITY 0x0008 // Text color is intensified.
#define BACKGROUND_BLUE 0x0010 // Background color contains blue.
#define BACKGROUND_GREEN 0x0020 // Background color contains green.
#define BACKGROUND_RED 0x0040 // Background color contains red.
#define BACKGROUND_INTENSITY 0x0080 // Background color is intensified.
// These two bits are used to represent wide glyphs.
#define COMMON_LVB_LEADING_BYTE 0x0100 // Leading byte.
#define COMMON_LVB_TRAILING_BYTE 0x0200 // Trailing byte.
// This bit is equivalent to the "CSI 7 m" reverse video escape sequence.
#define COMMON_LVB_REVERSE_VIDEO 0x4000 // Reverse foreground and background attribute.
// NOTE: These flags have no equivalent in VT. COMMON_LVB_UNDERSCORE in particular is not the same as a
// "CSI 4 m" underline in VT, despite the name. They're used to give a cell border (= grid) lines.
#define COMMON_LVB_GRID_HORIZONTAL 0x0400 // Top horizontal.
#define COMMON_LVB_GRID_LVERTICAL 0x0800 // Left vertical.
#define COMMON_LVB_GRID_RVERTICAL 0x1000 // Right vertical.
#define COMMON_LVB_UNDERSCORE 0x8000 // Underscore.
#endif
// This struct is binary compatible to the CHAR_INFO struct from the Windows API and functionally equivalent.
//
// The following rules MUST be followed:
// * Each instance represents 1 column in the terminal.
// * Any cells that aren't representable with a single UCS-2 character, or are wider than 2 columns,
// must be replaced with U+FFFD. Grapheme clusters, surrogate pairs, and similar, are not allowed.
// Keep in mind that U+FFFD is a narrow character. It does not get the wide wide-glyph treatment below.
// * Colors that cannot be represented via the `attributes` flags can be replaced with an approximation.
// Alternatively, `FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED` can be used (no `BACKGROUND` bit set).
// * If a wide glyph (2 columns wide) is encountered, the following applies:
// * Create 2 consecutive CONSRV_CHAR_INFO instances (as per the first rule).
// * Repeat the same `character` in both instances, even if it's U+FFFD.
// * Assign the first instance an `attributes` flag of `COMMON_LVB_LEADING_BYTE`
// and the second one `COMMON_LVB_TRAILING_BYTE`.
// * BUT if the request for a CONSRV_CHAR_INFO only partially intersects a wide glyph, replace the character
// (and only the character) with U+0020 whitespace. This also means that `COMMON_LVB_LEADING/TRAILING_BYTE`
// should not be set, because the returned character isn't wide anymore. An example:
// If you have a red "猫" on top of a blue background in the buffer and a single `CONSRV_CHAR_INFO` is requested
// for the left half of the glyph, then you should set `character` to whitespace and `attributes` to
// `FOREGROUND_RED | BACKGROUND_BLUE`. Debug builds of ConPTY will assert that you do this.
//
// For more documentation about the `attributes` flags, see the constants defined above.
struct CONSRV_CHAR_INFO {
wchar_t character;
UINT16 attributes;
};
struct CONSRV_UTF8_STRING {
[size_is(length)] const char* data;
DWORD length;
};
struct CONSRV_UTF16_STRING {
[size_is(length)] const wchar_t* data;
DWORD length;
};
// NOTE: At the time of writing the required fields are not fully known.
// NOTE: boolean is 8 Bits large.
struct CONSRV_INFO {
// NOTE: msys2 relies on the HWND value to uniquely identify terminal sessions.
// If we were to hand out the multiplexed terminal window HWND to msys2, it will break. Either we need to
// create fake windows inside conhost (very bad & buggy) or break msys2 intentionally (also very bad).
HWND window;
CONSRV_UTF16_STRING originalWindowTitle;
CONSRV_UTF16_STRING windowTitle;
CONSRV_POINT_I32 bufferSizeInCells;
CONSRV_POINT_I32 cursorPositionInCells;
CONSRV_POINT_I32 viewPositionInCells;
CONSRV_POINT_I32 viewSizeInCells;
CONSRV_POINT_F32 cellSizeInDIP;
COLORREF colorTable[16];
CONSRV_POINT_I32 selectionStart;
CONSRV_POINT_I32 selectionEnd;
boolean selectionActive;
boolean selectionRectangular;
boolean selectionMouseDown;
float cursorHeight;
boolean cursorHidden;
};
// Any item that has changed relative to the current CONSRV_INFO will be set to a non-null pointer.
// In other words, members that are null represent those that remain unchanged.
//
// If the request cannot be supported return E_INVALIDARG. For instance, you may choose to
// do so if you receive a `bufferSizeInCells` change while the xterm alt buffer is active.
//
// NOTE: At the time of writing the required fields are not fully known.
struct CONSRV_INFO_CHANGE {
CONSRV_POINT_I32* bufferSizeInCells;
CONSRV_POINT_I32* cursorPositionInCells;
CONSRV_POINT_I32* viewPositionInCells;
CONSRV_POINT_I32* viewSizeInCells;
COLORREF* colorTable; // The referenced array is always 16 items large.
float* cursorHeight;
boolean* cursorHidden;
CONSRV_UTF16_STRING* fontName;
UINT32* fontFamily;
UINT32* fontWeight;
CONSRV_POINT_I32* fontSize;
};
interface IConsoleServer : IUnknown {
// TODO: This interface is incomplete. Among others, a way to launch new application into the server is missing.
// ConPTY manages stdin as a ring buffer for you. When the terminal has focus, you simply need to write your input.
// Keyboard input MUST be written via `WriteInputRecords`. The other 2 functions DO NOT parse any VT sequences.
// They're instead meant either for VT responses (DECRPM, etc.) and for dumping plain text (clipboard, etc.).
void WriteInputRecords([in] DWORD count, [in, length_is(count)] const INPUT_RECORD* records);
void WriteInputUTF8([in] CONSRV_UTF8_STRING text);
void WriteInputUTF16([in] CONSRV_UTF16_STRING text);
};
// First of all: You don't need to implement all functions and all structs perfectly for ConPTY to work decently well.
// For instance, if you don't implement `CONSRV_INFO::cursorHeight` properly, barely anything will happen.
interface IConsoleServerCallback : IUnknown {
// The console server is single-threaded and no two calls will be made simultaneously. These two functions
// simply allow you to synchronize the calls down below if your application is multi-threaded.
//
// Lock() will always be called before any of the functions below are called.
// Lock() and Unlock() do not need to support recursive locking.
// Any other calls between Lock() and Unlock() should be treated as an atomic operation.
//
// It is recommended to use a fair lock instead of OS primitives like SRWLOCK. These callback functions may be
// much more often than your text renderer, etc., runs. An unfair lock will result in thread starvation.
HRESULT Lock();
HRESULT Unlock();
// If called, you're requested to create a new console alt buffer. The Console API supports having
// multiple concurrent such buffers. They're not the same as the xterm alt buffer, however (CSI ? 1049 h):
// They can be resized to be larger than the current viewport and switching between such buffers DOES NOT
// clear them nor does it reset any other per-buffer state.
//
// If you have trouble adding support for multiple console alt buffers, consider using the xterm alt buffer
// (CSI ? 1049 h) for the first buffer that gets created, and return E_OUTOFMEMORY for any further buffers.
HRESULT CreateBuffer([out] void** buffer);
// ReleaseBuffer is called once the buffer isn't needed anymore. It's guaranteed to be called and it's guaranteed
// to be called after ActivateBuffer() was used to switch to another buffer (or the main buffer).
HRESULT ReleaseBuffer([in] void* buffer);
// This switches between different console alt buffers. Switching to a buffer should change the content that's
// being shown, similar to the xterm alt buffer, however unlike it doing so DOES NOT reset any per-buffer state.
// All it does is to basically swap out the underlying, active text buffer of the terminal.
//
// If `buffer` is NULL it's a request to switch back to the main buffer.
//
// `temporary` is a hint. If it's `true` it indicates that the previous buffer will soon be activated again.
// In other words, on Unlock() the buffer was active during Lock() will be active again.
// It's recommended that temporary switches are lightweight as they may occur relatively often.
HRESULT ActivateBuffer([in] void* buffer, [in] boolean temporary);
//
// Any functions past this point operate on the currently active buffer.
//
// This function gets a snapshot of the terminal and buffer state.
//
// You must ensure that the returned pointer stays valid until the next GetInfo() or Unlock() call,
// or until the currently active buffer is released.
// You don't need to return a new instance on each call. ConPTY will only use the last returned pointer.
// You don't need to keep the CONSRV_INFO struct constantly up to date, but you're allowed to do so.
// For instance, it's valid to change the `.cursorPosition` when SetCursorPosition() is called.
//
// It's recommended that this function is lightweight as it may be called relatively often.
const CONSRV_INFO* GetInfo();
// When this method is called you're asked to apply any non-null member of the given CONSRV_INFO_CHANGE struct
// to the active buffer. For instance a non-null `.cursorPosition` is identical to calling `SetCursorPosition`,
// a non-null `.bufferSize` is a request to resize the terminal, and so on.
HRESULT SetInfo([in] const CONSRV_INFO_CHANGE* info);
// As explained in the CONSRV_POINT_I32 documentation, ConPTY coordinates may be outside of the VT viewport.
// This function is necessary in order to support this. If you assign the console buffer the same size
// as the VT viewport, `pos` can be translated to VT using
// printf("\x1b[%d;%dC", pos.y + 1, pos.x + 1);
HRESULT SetCursorPosition([in] CONSRV_POINT_I32 pos);
// The Console API supports 4 gridline attributes which cannot be translated to VT.
// This function is necessary to represent those. If you don't plan to support the gridlines,
// you can translate the attributes to VT with the following code or some equivalent:
// static const uint8_t lut[] = { 30, 34, 32, 36, 31, 35, 33, 37, 90, 94, 92, 96, 91, 95, 93, 97 };
// const auto fg = lut[attributes & 0xf];
// const auto bg = lut[(attributes >> 4) & 0xf] + 10;
// printf("\x1b[%d;%dm", fg, bg);
//
// `attributes` of exactly `FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED` are often used to indicate the
// default colors in Windows Console applications, and so you may choose to translate attributes like that as:
// printf("\x1b[39;49");
//
// You may also choose to support COMMON_LVB_REVERSE_VIDEO, which translates to:
// printf("\x1b[7m");
HRESULT SetCurrentAttributes([in] UINT16 attributes);
// Starting from column `pos.x` in row `pos.y`, this reads `count`-many characters and attributes.
// `pos` and `count` will be clamped such that reads never extend outside of the `CONSRV_INFO::bufferSize`.
//
// However, it may still read cells that have never been written to (for instance below the current viewport!).
// Such reads should not fail. Simply fill the `infos` array with whitespaces and a default attribute of your chosing,
// but `FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED` is recommended (no other bits set).
//
// NOTE that this API should ignore any line renditions (DECDWL, DECDHL), margins (DECSLRM, ...), etc.
// Reading outside of the "valid" range for a given row should behave exactly like reading below the viewport,
// as described in the previous paragraph.
HRESULT ReadBuffer([in] CONSRV_POINT_I32 pos, [in] INT32 count, [out, length_is(count)] CONSRV_CHAR_INFO* infos);
// These two functions are used to layout text for the internal "GNU Readline"-like implementation.
// `text` is the string to operate on. As with any other method, input validation should be performed.
// It's preferred to pretend as if invalid codepoints (in particular invalid surrogate pairs)
// are U+FFFD, because this provides the user with some level of text editing capability.
// The alternative is to have none at all when facing invalid strings which is strictly worse.
// `maxClusters` is the maximum amount of "cursor movements" these functions should apply
// (like when pressing the left/right arrow buttons).
// `maxColumns` is the maximum amount of columns the functions may iterate over. When the text is "a猫" and
// `maxColumns` is 2, then the result should be "a", because "猫" doesn't fit anymore.
// `position` on input contains the current position of the cursor inside `text`, counted in characters from the
// start of the `text`. On output it's supposed to contain the new cursor position.
// `position` may be out of bounds and you should clamp it to a valid range first.
// `columns` on output should contain the number of columns that have been iterated over.
//
// The idea is that a `maxClusters = 1` and `maxColumns = inf` can be used to implement left/right cursor movement,
// while `maxClusters = inf` and `maxColumns = window width` can be used to layout text within the window.
//
// You don't need to handle escape characters. These functions will never be called with any present.
// For robustness against bugs it's however recommended to handle them anyway, in whatever way you wish.
// If you have no preference, it's recommended to treat them as zero-width characters.
HRESULT MeasureTextForward([in] CONSRV_UTF16_STRING text, [in] DWORD maxClusters, [in] DWORD maxColumns, [in, out] DWORD* position, [out] DWORD* columns);
HRESULT MeasureTextBackward([in] CONSRV_UTF16_STRING text, [in] DWORD maxClusters, [in] DWORD maxColumns, [in, out] DWORD* position, [out] DWORD* columns);
// UTF8 and UTF16 are both widely used text encodings on Windows and it's recommended that both
// functions are reasonably fast. ConPTY will translate all non-Unicode text to UTF16 for you.
// You must validate incoming text. It's recommended to replace invalid codepoints with U+FFFD.
// You don't need to check for broken up codepoints at the start/end of the text, as ConPTY will handle that for you.
HRESULT WriteUTF8([in] boolean raw, [in] CONSRV_UTF8_STRING text);
HRESULT WriteUTF16([in] boolean raw, [in] CONSRV_UTF16_STRING text);
};
```
The list shows how each Console API function is implemented in terms of the above interface.
* Aliases
<br>Fully implemented inside the server component without API.
* `AddConsoleAlias`
* `GetConsoleAlias`
* `GetConsoleAliases`
* `GetConsoleAliasesLength`
* `GetConsoleAliasExes`
* `GetConsoleAliasExesLength`
* History
<br>Fully implemented inside the server component without API.
* `ExpungeConsoleCommandHistory`
* `GetConsoleCommandHistory`
* `GetConsoleCommandHistoryLength`
* `GetConsoleHistoryInfo`
* `SetConsoleHistoryInfo`
* `SetConsoleNumberOfCommands`
* stdin
<br>Fully implemented inside the server component without API.
* `FlushConsoleInputBuffer`
* `GetConsoleInput`
* `GetConsoleInputCodePage`
* `GetConsoleInputMode`
* `GetNumberOfConsoleInputEvents`
* `ReadConsole`
* `SetConsoleInputCodePage`
* `SetConsoleInputMode`
* `WriteConsoleInput`
* Unsupported since conhost v1
* `GetConsoleDisplayMode`
* `GetConsoleLangId`
* `SetConsoleDisplayMode`
* Buffer management
* `GetConsoleScreenBufferInfoEx`:
Gets information from server's internal `SCREEN_INFORMATION` class (which represents the `HANDLE`).
* `SetConsoleScreenBufferInfoEx`:
Sets information on server's internal `SCREEN_INFORMATION` class.
* `CreateConsoleScreenBuffer`:
`CreateBuffer`
* `SetConsoleActiveScreenBuffer`:
`ActivateBuffer` + `SetInfo`
* `SetConsoleScreenBufferSize`:
`SetInfo`
* Cursor
* `GetConsoleCursorInfo`:
`GetInfo`
* `SetConsoleCursorInfo`:
`SetInfo`
* `SetConsoleCursorPosition`:
`GetInfo`
* Fonts
* `GetConsoleFontSize`:
`GetInfo`
* `GetCurrentConsoleFontEx`:
`GetInfo`
* `SetCurrentConsoleFontEx`:
`SetInfo`
* Window management
* `GetConsoleOriginalTitle`:
`GetInfo`
* `GetConsoleSelectionInfo`:
`GetInfo`
* `GetConsoleTitle`:
`GetInfo`
* `GetConsoleWindow`:
`GetInfo`
* `GetLargestConsoleWindowSize`:
`GetInfo`; The window frame size can be inferred from the difference between the `GetWindowRect(hwnd)` and the `viewSizeInCells * cellSizeInDIP`.
The max. cell count can then be calculated by getting the `MonitorFromWindow(hwnd)` size, subtracting the frame size and calculating the cell count.
* `GetNumberOfConsoleMouseButtons`:
Implemented inside the server component via `GetSystemMetrics(SM_CMOUSEBUTTONS)`
* `SetConsoleTitle`:
`SetInfo`
* `SetConsoleWindowInfo`:
`SetInfo`
* stdout (writing)
* `FillConsoleOutputAttribute`:
Set the new attributes with `SetCurrentAttributes`.
For each line, get the existing contents with `ReadBuffer`, `SetCursorPosition` to the start, concatenate the cells and write them with `WriteUTF16`.
* `FillConsoleOutputCharacter`:
For each line, get the existing contents with `ReadBuffer`, `SetCursorPosition` to the start, concatenate the cells and write them with `WriteUTF16`.
At the start of each line and every time the attributes change use `SetCurrentAttributes` to set them up.
* `GetConsoleOutputCodePage`:
Implemented inside the server component.
* `GetConsoleOutputMode`:
Implemented inside the server component.
* `ScrollConsoleScreenBuffer`:
**TODO**: It may be necessary to add a `ScrollBuffer` API to make vertical scrolling across the entire buffer width faster. This fast pass currently exists as well.
Otherwise, this will be translated to: Read all lines in the source rectangle with `ReadBuffer`.
Then refer to the `WriteConsoleOutput` implementation for writing it to the target.
* `SetConsoleOutputCodePage`:
Implemented inside the server component.
* `SetConsoleOutputMode`:
Implemented inside the server component.
* `SetConsoleTextAttribute`:
`SetCurrentAttributes`
* `WriteConsole`:
`WriteUTF8` if `CP_UTF8` is active and otherwise `WriteUTF16`.
* `WriteConsoleOutput`:
For each line, `SetCursorPosition` to the start, concatenate the cells and write them with `WriteUTF16`.
At the start of each line and every time the attributes change use `SetCurrentAttributes` to set them up.
* `WriteConsoleOutputAttribute`:
Same as `FillConsoleOutputAttribute`, but with varying attributes.
* `WriteConsoleOutputCharacter`:
Same as `FillConsoleOutputCharacter`, but with varying characters.
* stdout (reading)
<br>Each of these will be translated to a series of `ReadBuffer` calls, one for each line.
* `ReadConsoleOutput`
* `ReadConsoleOutputAttribute`
* `ReadConsoleOutputCharacter`
## Goal 3: Productize Server
### Goal
```mermaid
flowchart LR
subgraph ConPTY_lib["ConPTY (static library)"]
server_io[Console API calls]
ConPTY_Translation[VT Translation]
server_io<-->ConPTY_Translation
end
subgraph ConPTY["ConPTY (dynamic library)"]
ConPTY_impl[IApiRoutines impl]
ConPTY_parser[VT parser]
ConPTY_buffer[Text Buffer]
ConPTY_output[ConPTY Output]
ConPTY_Translation<-->ConPTY_impl
ConPTY_impl-->ConPTY_parser
ConPTY_parser-->ConPTY_buffer
ConPTY_buffer--ReadBuffer-->ConPTY_impl
ConPTY_impl------>ConPTY_output
end
subgraph conhost
subgraph conhost_Server[Server]
conhost_server_io[Console API calls]
conhost_ConPTY_Translation[VT Translation]
conhost_server_io<-->conhost_ConPTY_Translation
end
conhost_impl[IApiRoutines impl]
conhost_parser[VT parser]
conhost_buffer[Text Buffer]
conhost_renderer[Render Thread]
conhost_atlas[Text Renderer]
output_new[ConPTY Output]
conhost_ConPTY_Translation<-->conhost_impl
conhost_impl-.remains for<br>back compat.....->output_new
ConPTY_Translation<-->conhost_impl
conhost_impl-->conhost_parser
conhost_parser-->conhost_buffer
conhost_buffer--->conhost_renderer
conhost_buffer--ReadBuffer-->conhost_impl
conhost_renderer-->conhost_atlas
end
subgraph wt[Windows Terminal]
impl[IApiRoutines impl]
parser[VT parser]
buffer[Text Buffer]
renderer[Render Thread]
atlas[Text Renderer]
ConPTY_Translation<-->impl
impl-->parser
parser-->buffer
buffer--->renderer
buffer--ReadBuffer-->impl
renderer-->atlas
end
linkStyle 6,7 opacity:0.2
style conhost_Server opacity:0.2
style conhost_server_io opacity:0.2
style conhost_ConPTY_Translation opacity:0.2
```
After creating an _internal_ API in conhost, the next logical step is for us to extract the interface as a public one and consume it in Windows Terminal.
At this point we should also see if we can find early adopters of the API in other projects.
## Stretch Goal 4: Ship Server in Windows
The console server on Windows has been an internal ABI for the longest time.
As we have started shipping ConPTY bundled with conhost/OpenConsole to other projects, the internal ABI has become a public one.
While we have no intention of ever breaking forward compatability of the console server with future Windows versions, it would be reassuring if the ABI long-term became internal once more.
This will allow us complete freedom over its design, even in the decades to come, and allow us to fully shim any 3rd party applications on Windows if a ABI change were to ever happen.

View File

@@ -1,27 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,17 +0,0 @@
### Notes for Future Maintainers
This was originally imported by @miniksa in January 2020.
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
Please update the provenance information in that file when ingesting an updated version of the dependent library.
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropriate governance standards.
## What should be done to update this in the future?
1. Go to chromium/chromium repository on GitHub.
2. Take the entire contents of the base/numerics directory wholesale and drop it in the base/numerics directory here.
3. Don't change anything about it.
4. Validate that the license in the root of the repository didn't change and update it if so. It is sitting in the same directory as this readme.
If it changed dramatically, ensure that it is still compatible with our license scheme. Also update the NOTICE file in the root of our repository to declare the third-party usage.
5. Submit the pull.

View File

@@ -1,28 +0,0 @@
# Copyright (c) 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This is a dependency-free, header-only, library, and it needs to stay that
# way to facilitate pulling it into various third-party projects. So, this
# file is here to protect against accidentally introducing external
# dependencies or depending on internal implementation details.
source_set("base_numerics") {
visibility = [ "//base/*" ]
sources = [
"checked_math_impl.h",
"clamped_math_impl.h",
"safe_conversions_arm_impl.h",
"safe_conversions_impl.h",
"safe_math_arm_impl.h",
"safe_math_clang_gcc_impl.h",
"safe_math_shared_impl.h",
]
public = [
"checked_math.h",
"clamped_math.h",
"math_constants.h",
"ranges.h",
"safe_conversions.h",
"safe_math.h",
]
}

View File

@@ -1,7 +0,0 @@
# This is a dependency-free, header-only, library, and it needs to stay that
# way to facilitate pulling it into various third-party projects. So, this
# file is here to protect against accidentally introducing dependencies.
include_rules = [
"-base",
"+base/numerics",
]

View File

@@ -1,5 +0,0 @@
jschuh@chromium.org
tsepez@chromium.org
# COMPONENT: Internals

View File

@@ -1,409 +0,0 @@
# `base/numerics`
This directory contains a dependency-free, header-only library of templates
providing well-defined semantics for safely and performantly handling a variety
of numeric operations, including most common arithmetic operations and
conversions.
The public API is broken out into the following header files:
* `checked_math.h` contains the `CheckedNumeric` template class and helper
functions for performing arithmetic and conversion operations that detect
errors and boundary conditions (e.g. overflow, truncation, etc.).
* `clamped_math.h` contains the `ClampedNumeric` template class and
helper functions for performing fast, clamped (i.e. [non-sticky](#notsticky)
saturating) arithmetic operations and conversions.
* `safe_conversions.h` contains the `StrictNumeric` template class and
a collection of custom casting templates and helper functions for safely
converting between a range of numeric types.
* `safe_math.h` includes all of the previously mentioned headers.
*** aside
**Note:** The `Numeric` template types implicitly convert from C numeric types
and `Numeric` templates that are convertable to an underlying C numeric type.
The conversion priority for `Numeric` type coercions is:
* `StrictNumeric` coerces to `ClampedNumeric` and `CheckedNumeric`
* `ClampedNumeric` coerces to `CheckedNumeric`
***
[TOC]
## Common patterns and use-cases
The following covers the preferred style for the most common uses of this
library. Please don't cargo-cult from anywhere else. 😉
### Performing checked arithmetic type conversions
The `checked_cast` template converts between arbitrary arithmetic types, and is
used for cases where a conversion failure should result in program termination:
```cpp
// Crash if signed_value is out of range for buff_size.
size_t buff_size = checked_cast<size_t>(signed_value);
```
### Performing saturated (clamped) arithmetic type conversions
The `saturated_cast` template converts between arbitrary arithmetic types, and
is used in cases where an out-of-bounds source value should be saturated to the
corresponding maximum or minimum of the destination type:
```cpp
// Convert from float with saturation to INT_MAX, INT_MIN, or 0 for NaN.
int int_value = saturated_cast<int>(floating_point_value);
```
### Enforcing arithmetic type conversions at compile-time
The `strict_cast` emits code that is identical to `static_cast`. However,
provides static checks that will cause a compilation failure if the
destination type cannot represent the full range of the source type:
```cpp
// Throw a compiler error if byte_value is changed to an out-of-range-type.
int int_value = strict_cast<int>(byte_value);
```
You can also enforce these compile-time restrictions on function parameters by
using the `StrictNumeric` template:
```cpp
// Throw a compiler error if the size argument cannot be represented by a
// size_t (e.g. passing an int will fail to compile).
bool AllocateBuffer(void** buffer, StrictCast<size_t> size);
```
### Comparing values between arbitrary arithmetic types
Both the `StrictNumeric` and `ClampedNumeric` types provide well defined
comparisons between arbitrary arithmetic types. This allows you to perform
comparisons that are not legal or would trigger compiler warnings or errors
under the normal arithmetic promotion rules:
```cpp
bool foo(unsigned value, int upper_bound) {
// Converting to StrictNumeric allows this comparison to work correctly.
if (MakeStrictNum(value) >= upper_bound)
return false;
```
*** note
**Warning:** Do not perform manual conversions using the comparison operators.
Instead, use the cast templates described in the previous sections, or the
constexpr template functions `IsValueInRangeForNumericType` and
`IsTypeInRangeForNumericType`, as these templates properly handle the full range
of corner cases and employ various optimizations.
***
### Calculating a buffer size (checked arithmetic)
When making exact calculations—such as for buffer lengths—it's often necessary
to know when those calculations trigger an overflow, undefined behavior, or
other boundary conditions. The `CheckedNumeric` template does this by storing
a bit determining whether or not some arithmetic operation has occured that
would put the variable in an "invalid" state. Attempting to extract the value
from a variable in an invalid state will trigger a check/trap condition, that
by default will result in process termination.
Here's an example of a buffer calculation using a `CheckedNumeric` type (note:
the AssignIfValid method will trigger a compile error if the result is ignored).
```cpp
// Calculate the buffer size and detect if an overflow occurs.
size_t size;
if (!CheckAdd(kHeaderSize, CheckMul(count, kItemSize)).AssignIfValid(&size)) {
// Handle an overflow error...
}
```
### Calculating clamped coordinates (non-sticky saturating arithmetic)
Certain classes of calculations—such as coordinate calculations—require
well-defined semantics that always produce a valid result on boundary
conditions. The `ClampedNumeric` template addresses this by providing
performant, non-sticky saturating arithmetic operations.
Here's an example of using a `ClampedNumeric` to calculate an operation
insetting a rectangle.
```cpp
// Use clamped arithmetic since inset calculations might overflow.
void Rect::Inset(int left, int top, int right, int bottom) {
origin_ += Vector2d(left, top);
set_width(ClampSub(width(), ClampAdd(left, right)));
set_height(ClampSub(height(), ClampAdd(top, bottom)));
}
```
*** note
<a name="notsticky"></a>
The `ClampedNumeric` type is not "sticky", which means the saturation is not
retained across individual operations. As such, one arithmetic operation may
result in a saturated value, while the next operation may then "desaturate"
the value. Here's an example:
```cpp
ClampedNumeric<int> value = INT_MAX;
++value; // value is still INT_MAX, due to saturation.
--value; // value is now (INT_MAX - 1), because saturation is not sticky.
```
***
## Conversion functions and StrictNumeric<> in safe_conversions.h
This header includes a collection of helper `constexpr` templates for safely
performing a range of conversions, assignments, and tests.
### Safe casting templates
* `as_signed()` - Returns the supplied integral value as a signed type of
the same width.
* `as_unsigned()` - Returns the supplied integral value as an unsigned type
of the same width.
* `checked_cast<>()` - Analogous to `static_cast<>` for numeric types, except
that by default it will trigger a crash on an out-of-bounds conversion (e.g.
overflow, underflow, NaN to integral) or a compile error if the conversion
error can be detected at compile time. The crash handler can be overridden
to perform a behavior other than crashing.
* `saturated_cast<>()` - Analogous to `static_cast` for numeric types, except
that it returns a saturated result when the specified numeric conversion
would otherwise overflow or underflow. An NaN source returns 0 by
default, but can be overridden to return a different result.
* `strict_cast<>()` - Analogous to `static_cast` for numeric types, except
this causes a compile failure if the destination type is not large
enough to contain any value in the source type. It performs no runtime
checking and thus introduces no runtime overhead.
### Other helper and conversion functions
* `IsValueInRangeForNumericType<>()` - A convenience function that returns
true if the type supplied as the template parameter can represent the value
passed as an argument to the function.
* `IsTypeInRangeForNumericType<>()` - A convenience function that evaluates
entirely at compile-time and returns true if the destination type (first
template parameter) can represent the full range of the source type
(second template parameter).
* `IsValueNegative()` - A convenience function that will accept any
arithmetic type as an argument and will return whether the value is less
than zero. Unsigned types always return false.
* `SafeUnsignedAbs()` - Returns the absolute value of the supplied integer
parameter as an unsigned result (thus avoiding an overflow if the value
is the signed, two's complement minimum).
### StrictNumeric<>
`StrictNumeric<>` is a wrapper type that performs assignments and copies via
the `strict_cast` template, and can perform valid arithmetic comparisons
across any range of arithmetic types. `StrictNumeric` is the return type for
values extracted from a `CheckedNumeric` class instance. The raw numeric value
is extracted via `static_cast` to the underlying type or any type with
sufficient range to represent the underlying type.
* `MakeStrictNum()` - Creates a new `StrictNumeric` from the underlying type
of the supplied arithmetic or StrictNumeric type.
* `SizeT` - Alias for `StrictNumeric<size_t>`.
## CheckedNumeric<> in checked_math.h
`CheckedNumeric<>` implements all the logic and operators for detecting integer
boundary conditions such as overflow, underflow, and invalid conversions.
The `CheckedNumeric` type implicitly converts from floating point and integer
data types, and contains overloads for basic arithmetic operations (i.e.: `+`,
`-`, `*`, `/` for all types and `%`, `<<`, `>>`, `&`, `|`, `^` for integers).
However, *the [variadic template functions
](#CheckedNumeric_in-checked_math_h-Non_member-helper-functions)
are the prefered API,* as they remove type ambiguities and help prevent a number
of common errors. The variadic functions can also be more performant, as they
eliminate redundant expressions that are unavoidable with the with the operator
overloads. (Ideally the compiler should optimize those away, but better to avoid
them in the first place.)
Type promotions are a slightly modified version of the [standard C/C++ numeric
promotions
](http://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_promotions)
with the two differences being that *there is no default promotion to int*
and *bitwise logical operations always return an unsigned of the wider type.*
### Members
The unary negation, increment, and decrement operators are supported, along
with the following unary arithmetic methods, which return a new
`CheckedNumeric` as a result of the operation:
* `Abs()` - Absolute value.
* `UnsignedAbs()` - Absolute value as an equal-width unsigned underlying type
(valid for only integral types).
* `Max()` - Returns whichever is greater of the current instance or argument.
The underlying return type is whichever has the greatest magnitude.
* `Min()` - Returns whichever is lowest of the current instance or argument.
The underlying return type is whichever has can represent the lowest
number in the smallest width (e.g. int8_t over unsigned, int over
int8_t, and float over int).
The following are for converting `CheckedNumeric` instances:
* `type` - The underlying numeric type.
* `AssignIfValid()` - Assigns the underlying value to the supplied
destination pointer if the value is currently valid and within the
range supported by the destination type. Returns true on success.
* `Cast<>()` - Instance method returning a `CheckedNumeric` derived from
casting the current instance to a `CheckedNumeric` of the supplied
destination type.
*** aside
The following member functions return a `StrictNumeric`, which is valid for
comparison and assignment operations, but will trigger a compile failure on
attempts to assign to a type of insufficient range. The underlying value can
be extracted by an explicit `static_cast` to the underlying type or any type
with sufficient range to represent the underlying type.
***
* `IsValid()` - Returns true if the underlying numeric value is valid (i.e.
has not wrapped or saturated and is not the result of an invalid
conversion).
* `ValueOrDie()` - Returns the underlying value. If the state is not valid
this call will trigger a crash by default (but may be overridden by
supplying an alternate handler to the template).
* `ValueOrDefault()` - Returns the current value, or the supplied default if
the state is not valid (but will not crash).
**Comparison operators are explicitly not provided** for `CheckedNumeric`
types because they could result in a crash if the type is not in a valid state.
Patterns like the following should be used instead:
```cpp
// Either input or padding (or both) may be arbitrary sizes.
size_t buff_size;
if (!CheckAdd(input, padding, kHeaderLength).AssignIfValid(&buff_size) ||
buff_size >= kMaxBuffer) {
// Handle an error...
} else {
// Do stuff on success...
}
```
### Non-member helper functions
The following variadic convenience functions, which accept standard arithmetic
or `CheckedNumeric` types, perform arithmetic operations, and return a
`CheckedNumeric` result. The supported functions are:
* `CheckAdd()` - Addition.
* `CheckSub()` - Subtraction.
* `CheckMul()` - Multiplication.
* `CheckDiv()` - Division.
* `CheckMod()` - Modulus (integer only).
* `CheckLsh()` - Left integer shift (integer only).
* `CheckRsh()` - Right integer shift (integer only).
* `CheckAnd()` - Bitwise AND (integer only with unsigned result).
* `CheckOr()` - Bitwise OR (integer only with unsigned result).
* `CheckXor()` - Bitwise XOR (integer only with unsigned result).
* `CheckMax()` - Maximum of supplied arguments.
* `CheckMin()` - Minimum of supplied arguments.
The following wrapper functions can be used to avoid the template
disambiguator syntax when converting a destination type.
* `IsValidForType<>()` in place of: `a.template IsValid<>()`
* `ValueOrDieForType<>()` in place of: `a.template ValueOrDie<>()`
* `ValueOrDefaultForType<>()` in place of: `a.template ValueOrDefault<>()`
The following general utility methods is are useful for converting from
arithmetic types to `CheckedNumeric` types:
* `MakeCheckedNum()` - Creates a new `CheckedNumeric` from the underlying type
of the supplied arithmetic or directly convertible type.
## ClampedNumeric<> in clamped_math.h
`ClampedNumeric<>` implements all the logic and operators for clamped
(non-sticky saturating) arithmetic operations and conversions. The
`ClampedNumeric` type implicitly converts back and forth between floating point
and integer data types, saturating on assignment as appropriate. It contains
overloads for basic arithmetic operations (i.e.: `+`, `-`, `*`, `/` for
all types and `%`, `<<`, `>>`, `&`, `|`, `^` for integers) along with comparison
operators for arithmetic types of any size. However, *the [variadic template
functions
](#ClampedNumeric_in-clamped_math_h-Non_member-helper-functions)
are the prefered API,* as they remove type ambiguities and help prevent
a number of common errors. The variadic functions can also be more performant,
as they eliminate redundant expressions that are unavoidable with the operator
overloads. (Ideally the compiler should optimize those away, but better to avoid
them in the first place.)
Type promotions are a slightly modified version of the [standard C/C++ numeric
promotions
](http://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_promotions)
with the two differences being that *there is no default promotion to int*
and *bitwise logical operations always return an unsigned of the wider type.*
*** aside
Most arithmetic operations saturate normally, to the numeric limit in the
direction of the sign. The potentially unusual cases are:
* **Division:** Division by zero returns the saturated limit in the direction
of sign of the dividend (first argument). The one exception is 0/0, which
returns zero (although logically is NaN).
* **Modulus:** Division by zero returns the dividend (first argument).
* **Left shift:** Non-zero values saturate in the direction of the signed
limit (max/min), even for shifts larger than the bit width. 0 shifted any
amount results in 0.
* **Right shift:** Negative values saturate to -1. Positive or 0 saturates
to 0. (Effectively just an unbounded arithmetic-right-shift.)
* **Bitwise operations:** No saturation; bit pattern is identical to
non-saturated bitwise operations.
***
### Members
The unary negation, increment, and decrement operators are supported, along
with the following unary arithmetic methods, which return a new
`ClampedNumeric` as a result of the operation:
* `Abs()` - Absolute value.
* `UnsignedAbs()` - Absolute value as an equal-width unsigned underlying type
(valid for only integral types).
* `Max()` - Returns whichever is greater of the current instance or argument.
The underlying return type is whichever has the greatest magnitude.
* `Min()` - Returns whichever is lowest of the current instance or argument.
The underlying return type is whichever has can represent the lowest
number in the smallest width (e.g. int8_t over unsigned, int over
int8_t, and float over int).
The following are for converting `ClampedNumeric` instances:
* `type` - The underlying numeric type.
* `RawValue()` - Returns the raw value as the underlying arithmetic type. This
is useful when e.g. assigning to an auto type or passing as a deduced
template parameter.
* `Cast<>()` - Instance method returning a `ClampedNumeric` derived from
casting the current instance to a `ClampedNumeric` of the supplied
destination type.
### Non-member helper functions
The following variadic convenience functions, which accept standard arithmetic
or `ClampedNumeric` types, perform arithmetic operations, and return a
`ClampedNumeric` result. The supported functions are:
* `ClampAdd()` - Addition.
* `ClampSub()` - Subtraction.
* `ClampMul()` - Multiplication.
* `ClampDiv()` - Division.
* `ClampMod()` - Modulus (integer only).
* `ClampLsh()` - Left integer shift (integer only).
* `ClampRsh()` - Right integer shift (integer only).
* `ClampAnd()` - Bitwise AND (integer only with unsigned result).
* `ClampOr()` - Bitwise OR (integer only with unsigned result).
* `ClampXor()` - Bitwise XOR (integer only with unsigned result).
* `ClampMax()` - Maximum of supplied arguments.
* `ClampMin()` - Minimum of supplied arguments.
The following is a general utility method that is useful for converting
to a `ClampedNumeric` type:
* `MakeClampedNum()` - Creates a new `ClampedNumeric` from the underlying type
of the supplied arithmetic or directly convertible type.

View File

@@ -1,393 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_CHECKED_MATH_H_
#define BASE_NUMERICS_CHECKED_MATH_H_
#include <stddef.h>
#include <limits>
#include <type_traits>
#include "base/numerics/checked_math_impl.h"
namespace base {
namespace internal {
template <typename T>
class CheckedNumeric {
static_assert(std::is_arithmetic<T>::value,
"CheckedNumeric<T>: T must be a numeric type.");
public:
using type = T;
constexpr CheckedNumeric() = default;
// Copy constructor.
template <typename Src>
constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs)
: state_(rhs.state_.value(), rhs.IsValid()) {}
template <typename Src>
friend class CheckedNumeric;
// This is not an explicit constructor because we implicitly upgrade regular
// numerics to CheckedNumerics to make them easier to use.
template <typename Src>
constexpr CheckedNumeric(Src value) // NOLINT(runtime/explicit)
: state_(value) {
static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
}
// This is not an explicit constructor because we want a seamless conversion
// from StrictNumeric types.
template <typename Src>
constexpr CheckedNumeric(
StrictNumeric<Src> value) // NOLINT(runtime/explicit)
: state_(static_cast<Src>(value)) {}
// IsValid() - The public API to test if a CheckedNumeric is currently valid.
// A range checked destination type can be supplied using the Dst template
// parameter.
template <typename Dst = T>
constexpr bool IsValid() const {
return state_.is_valid() &&
IsValueInRangeForNumericType<Dst>(state_.value());
}
// AssignIfValid(Dst) - Assigns the underlying value if it is currently valid
// and is within the range supported by the destination type. Returns true if
// successful and false otherwise.
template <typename Dst>
#if defined(__clang__) || defined(__GNUC__)
__attribute__((warn_unused_result))
#elif defined(_MSC_VER)
_Check_return_
#endif
constexpr bool
AssignIfValid(Dst* result) const {
return BASE_NUMERICS_LIKELY(IsValid<Dst>())
? ((*result = static_cast<Dst>(state_.value())), true)
: false;
}
// ValueOrDie() - The primary accessor for the underlying value. If the
// current state is not valid it will CHECK and crash.
// A range checked destination type can be supplied using the Dst template
// parameter, which will trigger a CHECK if the value is not in bounds for
// the destination.
// The CHECK behavior can be overridden by supplying a handler as a
// template parameter, for test code, etc. However, the handler cannot access
// the underlying value, and it is not available through other means.
template <typename Dst = T, class CheckHandler = CheckOnFailure>
constexpr StrictNumeric<Dst> ValueOrDie() const {
return BASE_NUMERICS_LIKELY(IsValid<Dst>())
? static_cast<Dst>(state_.value())
: CheckHandler::template HandleFailure<Dst>();
}
// ValueOrDefault(T default_value) - A convenience method that returns the
// current value if the state is valid, and the supplied default_value for
// any other state.
// A range checked destination type can be supplied using the Dst template
// parameter. WARNING: This function may fail to compile or CHECK at runtime
// if the supplied default_value is not within range of the destination type.
template <typename Dst = T, typename Src>
constexpr StrictNumeric<Dst> ValueOrDefault(const Src default_value) const {
return BASE_NUMERICS_LIKELY(IsValid<Dst>())
? static_cast<Dst>(state_.value())
: checked_cast<Dst>(default_value);
}
// Returns a checked numeric of the specified type, cast from the current
// CheckedNumeric. If the current state is invalid or the destination cannot
// represent the result then the returned CheckedNumeric will be invalid.
template <typename Dst>
constexpr CheckedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
return *this;
}
// This friend method is available solely for providing more detailed logging
// in the the tests. Do not implement it in production code, because the
// underlying values may change at any time.
template <typename U>
friend U GetNumericValueForTest(const CheckedNumeric<U>& src);
// Prototypes for the supported arithmetic operator overloads.
template <typename Src>
constexpr CheckedNumeric& operator+=(const Src rhs);
template <typename Src>
constexpr CheckedNumeric& operator-=(const Src rhs);
template <typename Src>
constexpr CheckedNumeric& operator*=(const Src rhs);
template <typename Src>
constexpr CheckedNumeric& operator/=(const Src rhs);
template <typename Src>
constexpr CheckedNumeric& operator%=(const Src rhs);
template <typename Src>
constexpr CheckedNumeric& operator<<=(const Src rhs);
template <typename Src>
constexpr CheckedNumeric& operator>>=(const Src rhs);
template <typename Src>
constexpr CheckedNumeric& operator&=(const Src rhs);
template <typename Src>
constexpr CheckedNumeric& operator|=(const Src rhs);
template <typename Src>
constexpr CheckedNumeric& operator^=(const Src rhs);
constexpr CheckedNumeric operator-() const {
// The negation of two's complement int min is int min, so we simply
// check for that in the constexpr case.
// We use an optimized code path for a known run-time variable.
return MustTreatAsConstexpr(state_.value()) || !std::is_signed<T>::value ||
std::is_floating_point<T>::value
? CheckedNumeric<T>(
NegateWrapper(state_.value()),
IsValid() && (!std::is_signed<T>::value ||
std::is_floating_point<T>::value ||
NegateWrapper(state_.value()) !=
std::numeric_limits<T>::lowest()))
: FastRuntimeNegate();
}
constexpr CheckedNumeric operator~() const {
return CheckedNumeric<decltype(InvertWrapper(T()))>(
InvertWrapper(state_.value()), IsValid());
}
constexpr CheckedNumeric Abs() const {
return !IsValueNegative(state_.value()) ? *this : -*this;
}
template <typename U>
constexpr CheckedNumeric<typename MathWrapper<CheckedMaxOp, T, U>::type> Max(
const U rhs) const {
using R = typename UnderlyingType<U>::type;
using result_type = typename MathWrapper<CheckedMaxOp, T, U>::type;
// TODO(jschuh): This can be converted to the MathOp version and remain
// constexpr once we have C++14 support.
return CheckedNumeric<result_type>(
static_cast<result_type>(
IsGreater<T, R>::Test(state_.value(), Wrapper<U>::value(rhs))
? state_.value()
: Wrapper<U>::value(rhs)),
state_.is_valid() && Wrapper<U>::is_valid(rhs));
}
template <typename U>
constexpr CheckedNumeric<typename MathWrapper<CheckedMinOp, T, U>::type> Min(
const U rhs) const {
using R = typename UnderlyingType<U>::type;
using result_type = typename MathWrapper<CheckedMinOp, T, U>::type;
// TODO(jschuh): This can be converted to the MathOp version and remain
// constexpr once we have C++14 support.
return CheckedNumeric<result_type>(
static_cast<result_type>(
IsLess<T, R>::Test(state_.value(), Wrapper<U>::value(rhs))
? state_.value()
: Wrapper<U>::value(rhs)),
state_.is_valid() && Wrapper<U>::is_valid(rhs));
}
// This function is available only for integral types. It returns an unsigned
// integer of the same width as the source type, containing the absolute value
// of the source, and properly handling signed min.
constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>
UnsignedAbs() const {
return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
SafeUnsignedAbs(state_.value()), state_.is_valid());
}
constexpr CheckedNumeric& operator++() {
*this += 1;
return *this;
}
constexpr CheckedNumeric operator++(int) {
CheckedNumeric value = *this;
*this += 1;
return value;
}
constexpr CheckedNumeric& operator--() {
*this -= 1;
return *this;
}
constexpr CheckedNumeric operator--(int) {
CheckedNumeric value = *this;
*this -= 1;
return value;
}
// These perform the actual math operations on the CheckedNumerics.
// Binary arithmetic operations.
template <template <typename, typename, typename> class M,
typename L,
typename R>
static constexpr CheckedNumeric MathOp(const L lhs, const R rhs) {
using Math = typename MathWrapper<M, L, R>::math;
T result = 0;
bool is_valid =
Wrapper<L>::is_valid(lhs) && Wrapper<R>::is_valid(rhs) &&
Math::Do(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs), &result);
return CheckedNumeric<T>(result, is_valid);
}
// Assignment arithmetic operations.
template <template <typename, typename, typename> class M, typename R>
constexpr CheckedNumeric& MathOp(const R rhs) {
using Math = typename MathWrapper<M, T, R>::math;
T result = 0; // Using T as the destination saves a range check.
bool is_valid = state_.is_valid() && Wrapper<R>::is_valid(rhs) &&
Math::Do(state_.value(), Wrapper<R>::value(rhs), &result);
*this = CheckedNumeric<T>(result, is_valid);
return *this;
}
private:
CheckedNumericState<T> state_;
CheckedNumeric FastRuntimeNegate() const {
T result;
bool success = CheckedSubOp<T, T>::Do(T(0), state_.value(), &result);
return CheckedNumeric<T>(result, IsValid() && success);
}
template <typename Src>
constexpr CheckedNumeric(Src value, bool is_valid)
: state_(value, is_valid) {}
// These wrappers allow us to handle state the same way for both
// CheckedNumeric and POD arithmetic types.
template <typename Src>
struct Wrapper {
static constexpr bool is_valid(Src) { return true; }
static constexpr Src value(Src value) { return value; }
};
template <typename Src>
struct Wrapper<CheckedNumeric<Src>> {
static constexpr bool is_valid(const CheckedNumeric<Src> v) {
return v.IsValid();
}
static constexpr Src value(const CheckedNumeric<Src> v) {
return v.state_.value();
}
};
template <typename Src>
struct Wrapper<StrictNumeric<Src>> {
static constexpr bool is_valid(const StrictNumeric<Src>) { return true; }
static constexpr Src value(const StrictNumeric<Src> v) {
return static_cast<Src>(v);
}
};
};
// Convenience functions to avoid the ugly template disambiguator syntax.
template <typename Dst, typename Src>
constexpr bool IsValidForType(const CheckedNumeric<Src> value) {
return value.template IsValid<Dst>();
}
template <typename Dst, typename Src>
constexpr StrictNumeric<Dst> ValueOrDieForType(
const CheckedNumeric<Src> value) {
return value.template ValueOrDie<Dst>();
}
template <typename Dst, typename Src, typename Default>
constexpr StrictNumeric<Dst> ValueOrDefaultForType(
const CheckedNumeric<Src> value,
const Default default_value) {
return value.template ValueOrDefault<Dst>(default_value);
}
// Convience wrapper to return a new CheckedNumeric from the provided arithmetic
// or CheckedNumericType.
template <typename T>
constexpr CheckedNumeric<typename UnderlyingType<T>::type> MakeCheckedNum(
const T value) {
return value;
}
// These implement the variadic wrapper for the math operations.
template <template <typename, typename, typename> class M,
typename L,
typename R>
constexpr CheckedNumeric<typename MathWrapper<M, L, R>::type> CheckMathOp(
const L lhs,
const R rhs) {
using Math = typename MathWrapper<M, L, R>::math;
return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
rhs);
}
// General purpose wrapper template for arithmetic operations.
template <template <typename, typename, typename> class M,
typename L,
typename R,
typename... Args>
constexpr CheckedNumeric<typename ResultType<M, L, R, Args...>::type>
CheckMathOp(const L lhs, const R rhs, const Args... args) {
return CheckMathOp<M>(CheckMathOp<M>(lhs, rhs), args...);
}
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Add, +, +=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Sub, -, -=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mul, *, *=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Div, /, /=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mod, %, %=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Lsh, <<, <<=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Rsh, >>, >>=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, And, &, &=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Or, |, |=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Xor, ^, ^=)
BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Max)
BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Min)
// These are some extra StrictNumeric operators to support simple pointer
// arithmetic with our result types. Since wrapping on a pointer is always
// bad, we trigger the CHECK condition here.
template <typename L, typename R>
L* operator+(L* lhs, const StrictNumeric<R> rhs) {
uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs),
CheckMul(sizeof(L), static_cast<R>(rhs)))
.template ValueOrDie<uintptr_t>();
return reinterpret_cast<L*>(result);
}
template <typename L, typename R>
L* operator-(L* lhs, const StrictNumeric<R> rhs) {
uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs),
CheckMul(sizeof(L), static_cast<R>(rhs)))
.template ValueOrDie<uintptr_t>();
return reinterpret_cast<L*>(result);
}
} // namespace internal
using internal::CheckedNumeric;
using internal::IsValidForType;
using internal::ValueOrDieForType;
using internal::ValueOrDefaultForType;
using internal::MakeCheckedNum;
using internal::CheckMax;
using internal::CheckMin;
using internal::CheckAdd;
using internal::CheckSub;
using internal::CheckMul;
using internal::CheckDiv;
using internal::CheckMod;
using internal::CheckLsh;
using internal::CheckRsh;
using internal::CheckAnd;
using internal::CheckOr;
using internal::CheckXor;
} // namespace base
#endif // BASE_NUMERICS_CHECKED_MATH_H_

View File

@@ -1,567 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_CHECKED_MATH_IMPL_H_
#define BASE_NUMERICS_CHECKED_MATH_IMPL_H_
#include <stddef.h>
#include <stdint.h>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <type_traits>
#include "base/numerics/safe_conversions.h"
#include "base/numerics/safe_math_shared_impl.h"
namespace base {
namespace internal {
template <typename T>
constexpr bool CheckedAddImpl(T x, T y, T* result) {
static_assert(std::is_integral<T>::value, "Type must be integral");
// Since the value of x+y is undefined if we have a signed type, we compute
// it using the unsigned type of the same size.
using UnsignedDst = typename std::make_unsigned<T>::type;
using SignedDst = typename std::make_signed<T>::type;
UnsignedDst ux = static_cast<UnsignedDst>(x);
UnsignedDst uy = static_cast<UnsignedDst>(y);
UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy);
*result = static_cast<T>(uresult);
// Addition is valid if the sign of (x + y) is equal to either that of x or
// that of y.
return (std::is_signed<T>::value)
? static_cast<SignedDst>((uresult ^ ux) & (uresult ^ uy)) >= 0
: uresult >= uy; // Unsigned is either valid or underflow.
}
template <typename T, typename U, class Enable = void>
struct CheckedAddOp {};
template <typename T, typename U>
struct CheckedAddOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
// TODO(jschuh) Make this "constexpr if" once we're C++17.
if (CheckedAddFastOp<T, U>::is_supported)
return CheckedAddFastOp<T, U>::Do(x, y, result);
// Double the underlying type up to a full machine word.
using FastPromotion = typename FastIntegerArithmeticPromotion<T, U>::type;
using Promotion =
typename std::conditional<(IntegerBitsPlusSign<FastPromotion>::value >
IntegerBitsPlusSign<intptr_t>::value),
typename BigEnoughPromotion<T, U>::type,
FastPromotion>::type;
// Fail if either operand is out of range for the promoted type.
// TODO(jschuh): This could be made to work for a broader range of values.
if (BASE_NUMERICS_UNLIKELY(!IsValueInRangeForNumericType<Promotion>(x) ||
!IsValueInRangeForNumericType<Promotion>(y))) {
return false;
}
Promotion presult = {};
bool is_valid = true;
if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
presult = static_cast<Promotion>(x) + static_cast<Promotion>(y);
} else {
is_valid = CheckedAddImpl(static_cast<Promotion>(x),
static_cast<Promotion>(y), &presult);
}
*result = static_cast<V>(presult);
return is_valid && IsValueInRangeForNumericType<V>(presult);
}
};
template <typename T>
constexpr bool CheckedSubImpl(T x, T y, T* result) {
static_assert(std::is_integral<T>::value, "Type must be integral");
// Since the value of x+y is undefined if we have a signed type, we compute
// it using the unsigned type of the same size.
using UnsignedDst = typename std::make_unsigned<T>::type;
using SignedDst = typename std::make_signed<T>::type;
UnsignedDst ux = static_cast<UnsignedDst>(x);
UnsignedDst uy = static_cast<UnsignedDst>(y);
UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy);
*result = static_cast<T>(uresult);
// Subtraction is valid if either x and y have same sign, or (x-y) and x have
// the same sign.
return (std::is_signed<T>::value)
? static_cast<SignedDst>((uresult ^ ux) & (ux ^ uy)) >= 0
: x >= y;
}
template <typename T, typename U, class Enable = void>
struct CheckedSubOp {};
template <typename T, typename U>
struct CheckedSubOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
// TODO(jschuh) Make this "constexpr if" once we're C++17.
if (CheckedSubFastOp<T, U>::is_supported)
return CheckedSubFastOp<T, U>::Do(x, y, result);
// Double the underlying type up to a full machine word.
using FastPromotion = typename FastIntegerArithmeticPromotion<T, U>::type;
using Promotion =
typename std::conditional<(IntegerBitsPlusSign<FastPromotion>::value >
IntegerBitsPlusSign<intptr_t>::value),
typename BigEnoughPromotion<T, U>::type,
FastPromotion>::type;
// Fail if either operand is out of range for the promoted type.
// TODO(jschuh): This could be made to work for a broader range of values.
if (BASE_NUMERICS_UNLIKELY(!IsValueInRangeForNumericType<Promotion>(x) ||
!IsValueInRangeForNumericType<Promotion>(y))) {
return false;
}
Promotion presult = {};
bool is_valid = true;
if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
presult = static_cast<Promotion>(x) - static_cast<Promotion>(y);
} else {
is_valid = CheckedSubImpl(static_cast<Promotion>(x),
static_cast<Promotion>(y), &presult);
}
*result = static_cast<V>(presult);
return is_valid && IsValueInRangeForNumericType<V>(presult);
}
};
template <typename T>
constexpr bool CheckedMulImpl(T x, T y, T* result) {
static_assert(std::is_integral<T>::value, "Type must be integral");
// Since the value of x*y is potentially undefined if we have a signed type,
// we compute it using the unsigned type of the same size.
using UnsignedDst = typename std::make_unsigned<T>::type;
using SignedDst = typename std::make_signed<T>::type;
const UnsignedDst ux = SafeUnsignedAbs(x);
const UnsignedDst uy = SafeUnsignedAbs(y);
UnsignedDst uresult = static_cast<UnsignedDst>(ux * uy);
const bool is_negative =
std::is_signed<T>::value && static_cast<SignedDst>(x ^ y) < 0;
*result = is_negative ? 0 - uresult : uresult;
// We have a fast out for unsigned identity or zero on the second operand.
// After that it's an unsigned overflow check on the absolute value, with
// a +1 bound for a negative result.
return uy <= UnsignedDst(!std::is_signed<T>::value || is_negative) ||
ux <= (std::numeric_limits<T>::max() + UnsignedDst(is_negative)) / uy;
}
template <typename T, typename U, class Enable = void>
struct CheckedMulOp {};
template <typename T, typename U>
struct CheckedMulOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
// TODO(jschuh) Make this "constexpr if" once we're C++17.
if (CheckedMulFastOp<T, U>::is_supported)
return CheckedMulFastOp<T, U>::Do(x, y, result);
using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
// Verify the destination type can hold the result (always true for 0).
if (BASE_NUMERICS_UNLIKELY((!IsValueInRangeForNumericType<Promotion>(x) ||
!IsValueInRangeForNumericType<Promotion>(y)) &&
x && y)) {
return false;
}
Promotion presult = {};
bool is_valid = true;
if (CheckedMulFastOp<Promotion, Promotion>::is_supported) {
// The fast op may be available with the promoted type.
is_valid = CheckedMulFastOp<Promotion, Promotion>::Do(x, y, &presult);
} else if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
} else {
is_valid = CheckedMulImpl(static_cast<Promotion>(x),
static_cast<Promotion>(y), &presult);
}
*result = static_cast<V>(presult);
return is_valid && IsValueInRangeForNumericType<V>(presult);
}
};
// Division just requires a check for a zero denominator or an invalid negation
// on signed min/-1.
template <typename T, typename U, class Enable = void>
struct CheckedDivOp {};
template <typename T, typename U>
struct CheckedDivOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
if (BASE_NUMERICS_UNLIKELY(!y))
return false;
// The overflow check can be compiled away if we don't have the exact
// combination of types needed to trigger this case.
using Promotion = typename BigEnoughPromotion<T, U>::type;
if (BASE_NUMERICS_UNLIKELY(
(std::is_signed<T>::value && std::is_signed<U>::value &&
IsTypeInRangeForNumericType<T, Promotion>::value &&
static_cast<Promotion>(x) ==
std::numeric_limits<Promotion>::lowest() &&
y == static_cast<U>(-1)))) {
return false;
}
// This branch always compiles away if the above branch wasn't removed.
if (BASE_NUMERICS_UNLIKELY((!IsValueInRangeForNumericType<Promotion>(x) ||
!IsValueInRangeForNumericType<Promotion>(y)) &&
x)) {
return false;
}
Promotion presult = Promotion(x) / Promotion(y);
*result = static_cast<V>(presult);
return IsValueInRangeForNumericType<V>(presult);
}
};
template <typename T, typename U, class Enable = void>
struct CheckedModOp {};
template <typename T, typename U>
struct CheckedModOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
using Promotion = typename BigEnoughPromotion<T, U>::type;
if (BASE_NUMERICS_LIKELY(y)) {
Promotion presult = static_cast<Promotion>(x) % static_cast<Promotion>(y);
*result = static_cast<Promotion>(presult);
return IsValueInRangeForNumericType<V>(presult);
}
return false;
}
};
template <typename T, typename U, class Enable = void>
struct CheckedLshOp {};
// Left shift. Shifts less than 0 or greater than or equal to the number
// of bits in the promoted type are undefined. Shifts of negative values
// are undefined. Otherwise it is defined when the result fits.
template <typename T, typename U>
struct CheckedLshOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = T;
template <typename V>
static constexpr bool Do(T x, U shift, V* result) {
// Disallow negative numbers and verify the shift is in bounds.
if (BASE_NUMERICS_LIKELY(!IsValueNegative(x) &&
as_unsigned(shift) <
as_unsigned(std::numeric_limits<T>::digits))) {
// Shift as unsigned to avoid undefined behavior.
*result = static_cast<V>(as_unsigned(x) << shift);
// If the shift can be reversed, we know it was valid.
return *result >> shift == x;
}
// Handle the legal corner-case of a full-width signed shift of zero.
return std::is_signed<T>::value && !x &&
as_unsigned(shift) == as_unsigned(std::numeric_limits<T>::digits);
}
};
template <typename T, typename U, class Enable = void>
struct CheckedRshOp {};
// Right shift. Shifts less than 0 or greater than or equal to the number
// of bits in the promoted type are undefined. Otherwise, it is always defined,
// but a right shift of a negative value is implementation-dependent.
template <typename T, typename U>
struct CheckedRshOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = T;
template <typename V>
static bool Do(T x, U shift, V* result) {
// Use the type conversion push negative values out of range.
if (BASE_NUMERICS_LIKELY(as_unsigned(shift) <
IntegerBitsPlusSign<T>::value)) {
T tmp = x >> shift;
*result = static_cast<V>(tmp);
return IsValueInRangeForNumericType<V>(tmp);
}
return false;
}
};
template <typename T, typename U, class Enable = void>
struct CheckedAndOp {};
// For simplicity we support only unsigned integer results.
template <typename T, typename U>
struct CheckedAndOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename std::make_unsigned<
typename MaxExponentPromotion<T, U>::type>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
result_type tmp = static_cast<result_type>(x) & static_cast<result_type>(y);
*result = static_cast<V>(tmp);
return IsValueInRangeForNumericType<V>(tmp);
}
};
template <typename T, typename U, class Enable = void>
struct CheckedOrOp {};
// For simplicity we support only unsigned integers.
template <typename T, typename U>
struct CheckedOrOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename std::make_unsigned<
typename MaxExponentPromotion<T, U>::type>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
result_type tmp = static_cast<result_type>(x) | static_cast<result_type>(y);
*result = static_cast<V>(tmp);
return IsValueInRangeForNumericType<V>(tmp);
}
};
template <typename T, typename U, class Enable = void>
struct CheckedXorOp {};
// For simplicity we support only unsigned integers.
template <typename T, typename U>
struct CheckedXorOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename std::make_unsigned<
typename MaxExponentPromotion<T, U>::type>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
result_type tmp = static_cast<result_type>(x) ^ static_cast<result_type>(y);
*result = static_cast<V>(tmp);
return IsValueInRangeForNumericType<V>(tmp);
}
};
// Max doesn't really need to be implemented this way because it can't fail,
// but it makes the code much cleaner to use the MathOp wrappers.
template <typename T, typename U, class Enable = void>
struct CheckedMaxOp {};
template <typename T, typename U>
struct CheckedMaxOp<
T,
U,
typename std::enable_if<std::is_arithmetic<T>::value &&
std::is_arithmetic<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
result_type tmp = IsGreater<T, U>::Test(x, y) ? static_cast<result_type>(x)
: static_cast<result_type>(y);
*result = static_cast<V>(tmp);
return IsValueInRangeForNumericType<V>(tmp);
}
};
// Min doesn't really need to be implemented this way because it can't fail,
// but it makes the code much cleaner to use the MathOp wrappers.
template <typename T, typename U, class Enable = void>
struct CheckedMinOp {};
template <typename T, typename U>
struct CheckedMinOp<
T,
U,
typename std::enable_if<std::is_arithmetic<T>::value &&
std::is_arithmetic<U>::value>::type> {
using result_type = typename LowestValuePromotion<T, U>::type;
template <typename V>
static constexpr bool Do(T x, U y, V* result) {
result_type tmp = IsLess<T, U>::Test(x, y) ? static_cast<result_type>(x)
: static_cast<result_type>(y);
*result = static_cast<V>(tmp);
return IsValueInRangeForNumericType<V>(tmp);
}
};
// This is just boilerplate that wraps the standard floating point arithmetic.
// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \
template <typename T, typename U> \
struct Checked##NAME##Op< \
T, U, \
typename std::enable_if<std::is_floating_point<T>::value || \
std::is_floating_point<U>::value>::type> { \
using result_type = typename MaxExponentPromotion<T, U>::type; \
template <typename V> \
static constexpr bool Do(T x, U y, V* result) { \
using Promotion = typename MaxExponentPromotion<T, U>::type; \
Promotion presult = x OP y; \
*result = static_cast<V>(presult); \
return IsValueInRangeForNumericType<V>(presult); \
} \
};
BASE_FLOAT_ARITHMETIC_OPS(Add, +)
BASE_FLOAT_ARITHMETIC_OPS(Sub, -)
BASE_FLOAT_ARITHMETIC_OPS(Mul, *)
BASE_FLOAT_ARITHMETIC_OPS(Div, /)
#undef BASE_FLOAT_ARITHMETIC_OPS
// Floats carry around their validity state with them, but integers do not. So,
// we wrap the underlying value in a specialization in order to hide that detail
// and expose an interface via accessors.
enum NumericRepresentation {
NUMERIC_INTEGER,
NUMERIC_FLOATING,
NUMERIC_UNKNOWN
};
template <typename NumericType>
struct GetNumericRepresentation {
static const NumericRepresentation value =
std::is_integral<NumericType>::value
? NUMERIC_INTEGER
: (std::is_floating_point<NumericType>::value ? NUMERIC_FLOATING
: NUMERIC_UNKNOWN);
};
template <typename T,
NumericRepresentation type = GetNumericRepresentation<T>::value>
class CheckedNumericState {};
// Integrals require quite a bit of additional housekeeping to manage state.
template <typename T>
class CheckedNumericState<T, NUMERIC_INTEGER> {
private:
// is_valid_ precedes value_ because member intializers in the constructors
// are evaluated in field order, and is_valid_ must be read when initializing
// value_.
bool is_valid_;
T value_;
// Ensures that a type conversion does not trigger undefined behavior.
template <typename Src>
static constexpr T WellDefinedConversionOrZero(const Src value,
const bool is_valid) {
using SrcType = typename internal::UnderlyingType<Src>::type;
return (std::is_integral<SrcType>::value || is_valid)
? static_cast<T>(value)
: static_cast<T>(0);
}
public:
template <typename Src, NumericRepresentation type>
friend class CheckedNumericState;
constexpr CheckedNumericState() : is_valid_(true), value_(0) {}
template <typename Src>
constexpr CheckedNumericState(Src value, bool is_valid)
: is_valid_(is_valid && IsValueInRangeForNumericType<T>(value)),
value_(WellDefinedConversionOrZero(value, is_valid_)) {
static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
}
// Copy constructor.
template <typename Src>
constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs)
: is_valid_(rhs.IsValid()),
value_(WellDefinedConversionOrZero(rhs.value(), is_valid_)) {}
template <typename Src>
constexpr explicit CheckedNumericState(Src value)
: is_valid_(IsValueInRangeForNumericType<T>(value)),
value_(WellDefinedConversionOrZero(value, is_valid_)) {}
constexpr bool is_valid() const { return is_valid_; }
constexpr T value() const { return value_; }
};
// Floating points maintain their own validity, but need translation wrappers.
template <typename T>
class CheckedNumericState<T, NUMERIC_FLOATING> {
private:
T value_;
// Ensures that a type conversion does not trigger undefined behavior.
template <typename Src>
static constexpr T WellDefinedConversionOrNaN(const Src value,
const bool is_valid) {
using SrcType = typename internal::UnderlyingType<Src>::type;
return (StaticDstRangeRelationToSrcRange<T, SrcType>::value ==
NUMERIC_RANGE_CONTAINED ||
is_valid)
? static_cast<T>(value)
: std::numeric_limits<T>::quiet_NaN();
}
public:
template <typename Src, NumericRepresentation type>
friend class CheckedNumericState;
constexpr CheckedNumericState() : value_(0.0) {}
template <typename Src>
constexpr CheckedNumericState(Src value, bool is_valid)
: value_(WellDefinedConversionOrNaN(value, is_valid)) {}
template <typename Src>
constexpr explicit CheckedNumericState(Src value)
: value_(WellDefinedConversionOrNaN(
value,
IsValueInRangeForNumericType<T>(value))) {}
// Copy constructor.
template <typename Src>
constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs)
: value_(WellDefinedConversionOrNaN(
rhs.value(),
rhs.is_valid() && IsValueInRangeForNumericType<T>(rhs.value()))) {}
constexpr bool is_valid() const {
// Written this way because std::isfinite is not reliably constexpr.
return MustTreatAsConstexpr(value_)
? value_ <= std::numeric_limits<T>::max() &&
value_ >= std::numeric_limits<T>::lowest()
: std::isfinite(value_);
}
constexpr T value() const { return value_; }
};
} // namespace internal
} // namespace base
#endif // BASE_NUMERICS_CHECKED_MATH_IMPL_H_

View File

@@ -1,264 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_CLAMPED_MATH_H_
#define BASE_NUMERICS_CLAMPED_MATH_H_
#include <stddef.h>
#include <limits>
#include <type_traits>
#include "base/numerics/clamped_math_impl.h"
namespace base {
namespace internal {
template <typename T>
class ClampedNumeric {
static_assert(std::is_arithmetic<T>::value,
"ClampedNumeric<T>: T must be a numeric type.");
public:
using type = T;
constexpr ClampedNumeric() : value_(0) {}
// Copy constructor.
template <typename Src>
constexpr ClampedNumeric(const ClampedNumeric<Src>& rhs)
: value_(saturated_cast<T>(rhs.value_)) {}
template <typename Src>
friend class ClampedNumeric;
// This is not an explicit constructor because we implicitly upgrade regular
// numerics to ClampedNumerics to make them easier to use.
template <typename Src>
constexpr ClampedNumeric(Src value) // NOLINT(runtime/explicit)
: value_(saturated_cast<T>(value)) {
static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
}
// This is not an explicit constructor because we want a seamless conversion
// from StrictNumeric types.
template <typename Src>
constexpr ClampedNumeric(
StrictNumeric<Src> value) // NOLINT(runtime/explicit)
: value_(saturated_cast<T>(static_cast<Src>(value))) {}
// Returns a ClampedNumeric of the specified type, cast from the current
// ClampedNumeric, and saturated to the destination type.
template <typename Dst>
constexpr ClampedNumeric<typename UnderlyingType<Dst>::type> Cast() const {
return *this;
}
// Prototypes for the supported arithmetic operator overloads.
template <typename Src>
constexpr ClampedNumeric& operator+=(const Src rhs);
template <typename Src>
constexpr ClampedNumeric& operator-=(const Src rhs);
template <typename Src>
constexpr ClampedNumeric& operator*=(const Src rhs);
template <typename Src>
constexpr ClampedNumeric& operator/=(const Src rhs);
template <typename Src>
constexpr ClampedNumeric& operator%=(const Src rhs);
template <typename Src>
constexpr ClampedNumeric& operator<<=(const Src rhs);
template <typename Src>
constexpr ClampedNumeric& operator>>=(const Src rhs);
template <typename Src>
constexpr ClampedNumeric& operator&=(const Src rhs);
template <typename Src>
constexpr ClampedNumeric& operator|=(const Src rhs);
template <typename Src>
constexpr ClampedNumeric& operator^=(const Src rhs);
constexpr ClampedNumeric operator-() const {
// The negation of two's complement int min is int min, so that's the
// only overflow case where we will saturate.
return ClampedNumeric<T>(SaturatedNegWrapper(value_));
}
constexpr ClampedNumeric operator~() const {
return ClampedNumeric<decltype(InvertWrapper(T()))>(InvertWrapper(value_));
}
constexpr ClampedNumeric Abs() const {
// The negation of two's complement int min is int min, so that's the
// only overflow case where we will saturate.
return ClampedNumeric<T>(SaturatedAbsWrapper(value_));
}
template <typename U>
constexpr ClampedNumeric<typename MathWrapper<ClampedMaxOp, T, U>::type> Max(
const U rhs) const {
using result_type = typename MathWrapper<ClampedMaxOp, T, U>::type;
return ClampedNumeric<result_type>(
ClampedMaxOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
}
template <typename U>
constexpr ClampedNumeric<typename MathWrapper<ClampedMinOp, T, U>::type> Min(
const U rhs) const {
using result_type = typename MathWrapper<ClampedMinOp, T, U>::type;
return ClampedNumeric<result_type>(
ClampedMinOp<T, U>::Do(value_, Wrapper<U>::value(rhs)));
}
// This function is available only for integral types. It returns an unsigned
// integer of the same width as the source type, containing the absolute value
// of the source, and properly handling signed min.
constexpr ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>
UnsignedAbs() const {
return ClampedNumeric<typename UnsignedOrFloatForSize<T>::type>(
SafeUnsignedAbs(value_));
}
constexpr ClampedNumeric& operator++() {
*this += 1;
return *this;
}
constexpr ClampedNumeric operator++(int) {
ClampedNumeric value = *this;
*this += 1;
return value;
}
constexpr ClampedNumeric& operator--() {
*this -= 1;
return *this;
}
constexpr ClampedNumeric operator--(int) {
ClampedNumeric value = *this;
*this -= 1;
return value;
}
// These perform the actual math operations on the ClampedNumerics.
// Binary arithmetic operations.
template <template <typename, typename, typename> class M,
typename L,
typename R>
static constexpr ClampedNumeric MathOp(const L lhs, const R rhs) {
using Math = typename MathWrapper<M, L, R>::math;
return ClampedNumeric<T>(
Math::template Do<T>(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs)));
}
// Assignment arithmetic operations.
template <template <typename, typename, typename> class M, typename R>
constexpr ClampedNumeric& MathOp(const R rhs) {
using Math = typename MathWrapper<M, T, R>::math;
*this =
ClampedNumeric<T>(Math::template Do<T>(value_, Wrapper<R>::value(rhs)));
return *this;
}
template <typename Dst>
constexpr operator Dst() const {
return saturated_cast<typename ArithmeticOrUnderlyingEnum<Dst>::type>(
value_);
}
// This method extracts the raw integer value without saturating it to the
// destination type as the conversion operator does. This is useful when
// e.g. assigning to an auto type or passing as a deduced template parameter.
constexpr T RawValue() const { return value_; }
private:
T value_;
// These wrappers allow us to handle state the same way for both
// ClampedNumeric and POD arithmetic types.
template <typename Src>
struct Wrapper {
static constexpr Src value(Src value) {
return static_cast<typename UnderlyingType<Src>::type>(value);
}
};
};
// Convience wrapper to return a new ClampedNumeric from the provided arithmetic
// or ClampedNumericType.
template <typename T>
constexpr ClampedNumeric<typename UnderlyingType<T>::type> MakeClampedNum(
const T value) {
return value;
}
#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
// Overload the ostream output operator to make logging work nicely.
template <typename T>
std::ostream& operator<<(std::ostream& os, const ClampedNumeric<T>& value) {
os << static_cast<T>(value);
return os;
}
#endif
// These implement the variadic wrapper for the math operations.
template <template <typename, typename, typename> class M,
typename L,
typename R>
constexpr ClampedNumeric<typename MathWrapper<M, L, R>::type> ClampMathOp(
const L lhs,
const R rhs) {
using Math = typename MathWrapper<M, L, R>::math;
return ClampedNumeric<typename Math::result_type>::template MathOp<M>(lhs,
rhs);
}
// General purpose wrapper template for arithmetic operations.
template <template <typename, typename, typename> class M,
typename L,
typename R,
typename... Args>
constexpr ClampedNumeric<typename ResultType<M, L, R, Args...>::type>
ClampMathOp(const L lhs, const R rhs, const Args... args) {
return ClampMathOp<M>(ClampMathOp<M>(lhs, rhs), args...);
}
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Add, +, +=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Sub, -, -=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mul, *, *=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Div, /, /=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Mod, %, %=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Lsh, <<, <<=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Rsh, >>, >>=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, And, &, &=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Or, |, |=)
BASE_NUMERIC_ARITHMETIC_OPERATORS(Clamped, Clamp, Xor, ^, ^=)
BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Max)
BASE_NUMERIC_ARITHMETIC_VARIADIC(Clamped, Clamp, Min)
BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLess, <)
BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsLessOrEqual, <=)
BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreater, >)
BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsGreaterOrEqual, >=)
BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsEqual, ==)
BASE_NUMERIC_COMPARISON_OPERATORS(Clamped, IsNotEqual, !=)
} // namespace internal
using internal::ClampedNumeric;
using internal::MakeClampedNum;
using internal::ClampMax;
using internal::ClampMin;
using internal::ClampAdd;
using internal::ClampSub;
using internal::ClampMul;
using internal::ClampDiv;
using internal::ClampMod;
using internal::ClampLsh;
using internal::ClampRsh;
using internal::ClampAnd;
using internal::ClampOr;
using internal::ClampXor;
} // namespace base
#endif // BASE_NUMERICS_CLAMPED_MATH_H_

View File

@@ -1,341 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
#define BASE_NUMERICS_CLAMPED_MATH_IMPL_H_
#include <stddef.h>
#include <stdint.h>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <type_traits>
#include "base/numerics/checked_math.h"
#include "base/numerics/safe_conversions.h"
#include "base/numerics/safe_math_shared_impl.h"
namespace base {
namespace internal {
template <typename T,
typename std::enable_if<std::is_integral<T>::value &&
std::is_signed<T>::value>::type* = nullptr>
constexpr T SaturatedNegWrapper(T value) {
return MustTreatAsConstexpr(value) || !ClampedNegFastOp<T>::is_supported
? (NegateWrapper(value) != std::numeric_limits<T>::lowest()
? NegateWrapper(value)
: std::numeric_limits<T>::max())
: ClampedNegFastOp<T>::Do(value);
}
template <typename T,
typename std::enable_if<std::is_integral<T>::value &&
!std::is_signed<T>::value>::type* = nullptr>
constexpr T SaturatedNegWrapper(T value) {
return T(0);
}
template <
typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
constexpr T SaturatedNegWrapper(T value) {
return -value;
}
template <typename T,
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
constexpr T SaturatedAbsWrapper(T value) {
// The calculation below is a static identity for unsigned types, but for
// signed integer types it provides a non-branching, saturated absolute value.
// This works because SafeUnsignedAbs() returns an unsigned type, which can
// represent the absolute value of all negative numbers of an equal-width
// integer type. The call to IsValueNegative() then detects overflow in the
// special case of numeric_limits<T>::min(), by evaluating the bit pattern as
// a signed integer value. If it is the overflow case, we end up subtracting
// one from the unsigned result, thus saturating to numeric_limits<T>::max().
return static_cast<T>(SafeUnsignedAbs(value) -
IsValueNegative<T>(SafeUnsignedAbs(value)));
}
template <
typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
constexpr T SaturatedAbsWrapper(T value) {
return value < 0 ? -value : value;
}
template <typename T, typename U, class Enable = void>
struct ClampedAddOp {};
template <typename T, typename U>
struct ClampedAddOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V = result_type>
static constexpr V Do(T x, U y) {
if (ClampedAddFastOp<T, U>::is_supported)
return ClampedAddFastOp<T, U>::template Do<V>(x, y);
static_assert(std::is_same<V, result_type>::value ||
IsTypeInRangeForNumericType<U, V>::value,
"The saturation result cannot be determined from the "
"provided types.");
const V saturated = CommonMaxOrMin<V>(IsValueNegative(y));
V result = {};
return BASE_NUMERICS_LIKELY((CheckedAddOp<T, U>::Do(x, y, &result)))
? result
: saturated;
}
};
template <typename T, typename U, class Enable = void>
struct ClampedSubOp {};
template <typename T, typename U>
struct ClampedSubOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V = result_type>
static constexpr V Do(T x, U y) {
// TODO(jschuh) Make this "constexpr if" once we're C++17.
if (ClampedSubFastOp<T, U>::is_supported)
return ClampedSubFastOp<T, U>::template Do<V>(x, y);
static_assert(std::is_same<V, result_type>::value ||
IsTypeInRangeForNumericType<U, V>::value,
"The saturation result cannot be determined from the "
"provided types.");
const V saturated = CommonMaxOrMin<V>(!IsValueNegative(y));
V result = {};
return BASE_NUMERICS_LIKELY((CheckedSubOp<T, U>::Do(x, y, &result)))
? result
: saturated;
}
};
template <typename T, typename U, class Enable = void>
struct ClampedMulOp {};
template <typename T, typename U>
struct ClampedMulOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V = result_type>
static constexpr V Do(T x, U y) {
// TODO(jschuh) Make this "constexpr if" once we're C++17.
if (ClampedMulFastOp<T, U>::is_supported)
return ClampedMulFastOp<T, U>::template Do<V>(x, y);
V result = {};
const V saturated =
CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y));
return BASE_NUMERICS_LIKELY((CheckedMulOp<T, U>::Do(x, y, &result)))
? result
: saturated;
}
};
template <typename T, typename U, class Enable = void>
struct ClampedDivOp {};
template <typename T, typename U>
struct ClampedDivOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V = result_type>
static constexpr V Do(T x, U y) {
V result = {};
if (BASE_NUMERICS_LIKELY((CheckedDivOp<T, U>::Do(x, y, &result))))
return result;
// Saturation goes to max, min, or NaN (if x is zero).
return x ? CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y))
: SaturationDefaultLimits<V>::NaN();
}
};
template <typename T, typename U, class Enable = void>
struct ClampedModOp {};
template <typename T, typename U>
struct ClampedModOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V = result_type>
static constexpr V Do(T x, U y) {
V result = {};
return BASE_NUMERICS_LIKELY((CheckedModOp<T, U>::Do(x, y, &result)))
? result
: x;
}
};
template <typename T, typename U, class Enable = void>
struct ClampedLshOp {};
// Left shift. Non-zero values saturate in the direction of the sign. A zero
// shifted by any value always results in zero.
template <typename T, typename U>
struct ClampedLshOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = T;
template <typename V = result_type>
static constexpr V Do(T x, U shift) {
static_assert(!std::is_signed<U>::value, "Shift value must be unsigned.");
if (BASE_NUMERICS_LIKELY(shift < std::numeric_limits<T>::digits)) {
// Shift as unsigned to avoid undefined behavior.
V result = static_cast<V>(as_unsigned(x) << shift);
// If the shift can be reversed, we know it was valid.
if (BASE_NUMERICS_LIKELY(result >> shift == x))
return result;
}
return x ? CommonMaxOrMin<V>(IsValueNegative(x)) : 0;
}
};
template <typename T, typename U, class Enable = void>
struct ClampedRshOp {};
// Right shift. Negative values saturate to -1. Positive or 0 saturates to 0.
template <typename T, typename U>
struct ClampedRshOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = T;
template <typename V = result_type>
static constexpr V Do(T x, U shift) {
static_assert(!std::is_signed<U>::value, "Shift value must be unsigned.");
// Signed right shift is odd, because it saturates to -1 or 0.
const V saturated = as_unsigned(V(0)) - IsValueNegative(x);
return BASE_NUMERICS_LIKELY(shift < IntegerBitsPlusSign<T>::value)
? saturated_cast<V>(x >> shift)
: saturated;
}
};
template <typename T, typename U, class Enable = void>
struct ClampedAndOp {};
template <typename T, typename U>
struct ClampedAndOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename std::make_unsigned<
typename MaxExponentPromotion<T, U>::type>::type;
template <typename V>
static constexpr V Do(T x, U y) {
return static_cast<result_type>(x) & static_cast<result_type>(y);
}
};
template <typename T, typename U, class Enable = void>
struct ClampedOrOp {};
// For simplicity we promote to unsigned integers.
template <typename T, typename U>
struct ClampedOrOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename std::make_unsigned<
typename MaxExponentPromotion<T, U>::type>::type;
template <typename V>
static constexpr V Do(T x, U y) {
return static_cast<result_type>(x) | static_cast<result_type>(y);
}
};
template <typename T, typename U, class Enable = void>
struct ClampedXorOp {};
// For simplicity we support only unsigned integers.
template <typename T, typename U>
struct ClampedXorOp<T,
U,
typename std::enable_if<std::is_integral<T>::value &&
std::is_integral<U>::value>::type> {
using result_type = typename std::make_unsigned<
typename MaxExponentPromotion<T, U>::type>::type;
template <typename V>
static constexpr V Do(T x, U y) {
return static_cast<result_type>(x) ^ static_cast<result_type>(y);
}
};
template <typename T, typename U, class Enable = void>
struct ClampedMaxOp {};
template <typename T, typename U>
struct ClampedMaxOp<
T,
U,
typename std::enable_if<std::is_arithmetic<T>::value &&
std::is_arithmetic<U>::value>::type> {
using result_type = typename MaxExponentPromotion<T, U>::type;
template <typename V = result_type>
static constexpr V Do(T x, U y) {
return IsGreater<T, U>::Test(x, y) ? saturated_cast<V>(x)
: saturated_cast<V>(y);
}
};
template <typename T, typename U, class Enable = void>
struct ClampedMinOp {};
template <typename T, typename U>
struct ClampedMinOp<
T,
U,
typename std::enable_if<std::is_arithmetic<T>::value &&
std::is_arithmetic<U>::value>::type> {
using result_type = typename LowestValuePromotion<T, U>::type;
template <typename V = result_type>
static constexpr V Do(T x, U y) {
return IsLess<T, U>::Test(x, y) ? saturated_cast<V>(x)
: saturated_cast<V>(y);
}
};
// This is just boilerplate that wraps the standard floating point arithmetic.
// A macro isn't the nicest solution, but it beats rewriting these repeatedly.
#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \
template <typename T, typename U> \
struct Clamped##NAME##Op< \
T, U, \
typename std::enable_if<std::is_floating_point<T>::value || \
std::is_floating_point<U>::value>::type> { \
using result_type = typename MaxExponentPromotion<T, U>::type; \
template <typename V = result_type> \
static constexpr V Do(T x, U y) { \
return saturated_cast<V>(x OP y); \
} \
};
BASE_FLOAT_ARITHMETIC_OPS(Add, +)
BASE_FLOAT_ARITHMETIC_OPS(Sub, -)
BASE_FLOAT_ARITHMETIC_OPS(Mul, *)
BASE_FLOAT_ARITHMETIC_OPS(Div, /)
#undef BASE_FLOAT_ARITHMETIC_OPS
} // namespace internal
} // namespace base
#endif // BASE_NUMERICS_CLAMPED_MATH_IMPL_H_

View File

@@ -1,19 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_MATH_CONSTANTS_H_
#define BASE_NUMERICS_MATH_CONSTANTS_H_
namespace base {
constexpr double kPiDouble = 3.14159265358979323846;
constexpr float kPiFloat = 3.14159265358979323846f;
// The mean acceleration due to gravity on Earth in m/s^2.
constexpr double kMeanGravityDouble = 9.80665;
constexpr float kMeanGravityFloat = 9.80665f;
} // namespace base
#endif // BASE_NUMERICS_MATH_CONSTANTS_H_

View File

@@ -1,27 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_RANGES_H_
#define BASE_NUMERICS_RANGES_H_
#include <algorithm>
#include <cmath>
namespace base {
// To be replaced with std::clamp() from C++17, someday.
template <class T>
constexpr const T& ClampToRange(const T& value, const T& min, const T& max) {
return std::min(std::max(value, min), max);
}
template <typename T>
constexpr bool IsApproximatelyEqual(T lhs, T rhs, T tolerance) {
static_assert(std::is_arithmetic<T>::value, "Argument must be arithmetic");
return std::abs(rhs - lhs) <= tolerance;
}
} // namespace base
#endif // BASE_NUMERICS_RANGES_H_

View File

@@ -1,358 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_
#define BASE_NUMERICS_SAFE_CONVERSIONS_H_
#include <stddef.h>
#include <limits>
#include <type_traits>
#include "base/numerics/safe_conversions_impl.h"
#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__))
#include "base/numerics/safe_conversions_arm_impl.h"
#define BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (1)
#else
#define BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (0)
#endif
#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
#include <ostream>
#endif
namespace base {
namespace internal {
#if !BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS
template <typename Dst, typename Src>
struct SaturateFastAsmOp {
static const bool is_supported = false;
static constexpr Dst Do(Src) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<Dst>();
}
};
#endif // BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS
#undef BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS
// The following special case a few specific integer conversions where we can
// eke out better performance than range checking.
template <typename Dst, typename Src, typename Enable = void>
struct IsValueInRangeFastOp {
static const bool is_supported = false;
static constexpr bool Do(Src value) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<bool>();
}
};
// Signed to signed range comparison.
template <typename Dst, typename Src>
struct IsValueInRangeFastOp<
Dst,
Src,
typename std::enable_if<
std::is_integral<Dst>::value && std::is_integral<Src>::value &&
std::is_signed<Dst>::value && std::is_signed<Src>::value &&
!IsTypeInRangeForNumericType<Dst, Src>::value>::type> {
static const bool is_supported = true;
static constexpr bool Do(Src value) {
// Just downcast to the smaller type, sign extend it back to the original
// type, and then see if it matches the original value.
return value == static_cast<Dst>(value);
}
};
// Signed to unsigned range comparison.
template <typename Dst, typename Src>
struct IsValueInRangeFastOp<
Dst,
Src,
typename std::enable_if<
std::is_integral<Dst>::value && std::is_integral<Src>::value &&
!std::is_signed<Dst>::value && std::is_signed<Src>::value &&
!IsTypeInRangeForNumericType<Dst, Src>::value>::type> {
static const bool is_supported = true;
static constexpr bool Do(Src value) {
// We cast a signed as unsigned to overflow negative values to the top,
// then compare against whichever maximum is smaller, as our upper bound.
return as_unsigned(value) <= as_unsigned(CommonMax<Src, Dst>());
}
};
// Convenience function that returns true if the supplied value is in range
// for the destination type.
template <typename Dst, typename Src>
constexpr bool IsValueInRangeForNumericType(Src value) {
using SrcType = typename internal::UnderlyingType<Src>::type;
return internal::IsValueInRangeFastOp<Dst, SrcType>::is_supported
? internal::IsValueInRangeFastOp<Dst, SrcType>::Do(
static_cast<SrcType>(value))
: internal::DstRangeRelationToSrcRange<Dst>(
static_cast<SrcType>(value))
.IsValid();
}
// checked_cast<> is analogous to static_cast<> for numeric types,
// except that it CHECKs that the specified numeric conversion will not
// overflow or underflow. NaN source will always trigger a CHECK.
template <typename Dst,
class CheckHandler = internal::CheckOnFailure,
typename Src>
constexpr Dst checked_cast(Src value) {
// This throws a compile-time error on evaluating the constexpr if it can be
// determined at compile-time as failing, otherwise it will CHECK at runtime.
using SrcType = typename internal::UnderlyingType<Src>::type;
return BASE_NUMERICS_LIKELY((IsValueInRangeForNumericType<Dst>(value)))
? static_cast<Dst>(static_cast<SrcType>(value))
: CheckHandler::template HandleFailure<Dst>();
}
// Default boundaries for integral/float: max/infinity, lowest/-infinity, 0/NaN.
// You may provide your own limits (e.g. to saturated_cast) so long as you
// implement all of the static constexpr member functions in the class below.
template <typename T>
struct SaturationDefaultLimits : public std::numeric_limits<T> {
static constexpr T NaN() {
return std::numeric_limits<T>::has_quiet_NaN
? std::numeric_limits<T>::quiet_NaN()
: T();
}
using std::numeric_limits<T>::max;
static constexpr T Overflow() {
return std::numeric_limits<T>::has_infinity
? std::numeric_limits<T>::infinity()
: std::numeric_limits<T>::max();
}
using std::numeric_limits<T>::lowest;
static constexpr T Underflow() {
return std::numeric_limits<T>::has_infinity
? std::numeric_limits<T>::infinity() * -1
: std::numeric_limits<T>::lowest();
}
};
template <typename Dst, template <typename> class S, typename Src>
constexpr Dst saturated_cast_impl(Src value, RangeCheck constraint) {
// For some reason clang generates much better code when the branch is
// structured exactly this way, rather than a sequence of checks.
return !constraint.IsOverflowFlagSet()
? (!constraint.IsUnderflowFlagSet() ? static_cast<Dst>(value)
: S<Dst>::Underflow())
// Skip this check for integral Src, which cannot be NaN.
: (std::is_integral<Src>::value || !constraint.IsUnderflowFlagSet()
? S<Dst>::Overflow()
: S<Dst>::NaN());
}
// We can reduce the number of conditions and get slightly better performance
// for normal signed and unsigned integer ranges. And in the specific case of
// Arm, we can use the optimized saturation instructions.
template <typename Dst, typename Src, typename Enable = void>
struct SaturateFastOp {
static const bool is_supported = false;
static constexpr Dst Do(Src value) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<Dst>();
}
};
template <typename Dst, typename Src>
struct SaturateFastOp<
Dst,
Src,
typename std::enable_if<std::is_integral<Src>::value &&
std::is_integral<Dst>::value &&
SaturateFastAsmOp<Dst, Src>::is_supported>::type> {
static const bool is_supported = true;
static Dst Do(Src value) { return SaturateFastAsmOp<Dst, Src>::Do(value); }
};
template <typename Dst, typename Src>
struct SaturateFastOp<
Dst,
Src,
typename std::enable_if<std::is_integral<Src>::value &&
std::is_integral<Dst>::value &&
!SaturateFastAsmOp<Dst, Src>::is_supported>::type> {
static const bool is_supported = true;
static Dst Do(Src value) {
// The exact order of the following is structured to hit the correct
// optimization heuristics across compilers. Do not change without
// checking the emitted code.
Dst saturated = CommonMaxOrMin<Dst, Src>(
IsMaxInRangeForNumericType<Dst, Src>() ||
(!IsMinInRangeForNumericType<Dst, Src>() && IsValueNegative(value)));
return BASE_NUMERICS_LIKELY(IsValueInRangeForNumericType<Dst>(value))
? static_cast<Dst>(value)
: saturated;
}
};
// saturated_cast<> is analogous to static_cast<> for numeric types, except
// that the specified numeric conversion will saturate by default rather than
// overflow or underflow, and NaN assignment to an integral will return 0.
// All boundary condition behaviors can be overriden with a custom handler.
template <typename Dst,
template <typename> class SaturationHandler = SaturationDefaultLimits,
typename Src>
constexpr Dst saturated_cast(Src value) {
using SrcType = typename UnderlyingType<Src>::type;
return !IsCompileTimeConstant(value) &&
SaturateFastOp<Dst, SrcType>::is_supported &&
std::is_same<SaturationHandler<Dst>,
SaturationDefaultLimits<Dst>>::value
? SaturateFastOp<Dst, SrcType>::Do(static_cast<SrcType>(value))
: saturated_cast_impl<Dst, SaturationHandler, SrcType>(
static_cast<SrcType>(value),
DstRangeRelationToSrcRange<Dst, SaturationHandler, SrcType>(
static_cast<SrcType>(value)));
}
// strict_cast<> is analogous to static_cast<> for numeric types, except that
// it will cause a compile failure if the destination type is not large enough
// to contain any value in the source type. It performs no runtime checking.
template <typename Dst, typename Src>
constexpr Dst strict_cast(Src value) {
using SrcType = typename UnderlyingType<Src>::type;
static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric.");
static_assert(std::is_arithmetic<Dst>::value, "Result must be numeric.");
// If you got here from a compiler error, it's because you tried to assign
// from a source type to a destination type that has insufficient range.
// The solution may be to change the destination type you're assigning to,
// and use one large enough to represent the source.
// Alternatively, you may be better served with the checked_cast<> or
// saturated_cast<> template functions for your particular use case.
static_assert(StaticDstRangeRelationToSrcRange<Dst, SrcType>::value ==
NUMERIC_RANGE_CONTAINED,
"The source type is out of range for the destination type. "
"Please see strict_cast<> comments for more information.");
return static_cast<Dst>(static_cast<SrcType>(value));
}
// Some wrappers to statically check that a type is in range.
template <typename Dst, typename Src, class Enable = void>
struct IsNumericRangeContained {
static const bool value = false;
};
template <typename Dst, typename Src>
struct IsNumericRangeContained<
Dst,
Src,
typename std::enable_if<ArithmeticOrUnderlyingEnum<Dst>::value &&
ArithmeticOrUnderlyingEnum<Src>::value>::type> {
static const bool value = StaticDstRangeRelationToSrcRange<Dst, Src>::value ==
NUMERIC_RANGE_CONTAINED;
};
// StrictNumeric implements compile time range checking between numeric types by
// wrapping assignment operations in a strict_cast. This class is intended to be
// used for function arguments and return types, to ensure the destination type
// can always contain the source type. This is essentially the same as enforcing
// -Wconversion in gcc and C4302 warnings on MSVC, but it can be applied
// incrementally at API boundaries, making it easier to convert code so that it
// compiles cleanly with truncation warnings enabled.
// This template should introduce no runtime overhead, but it also provides no
// runtime checking of any of the associated mathematical operations. Use
// CheckedNumeric for runtime range checks of the actual value being assigned.
template <typename T>
class StrictNumeric {
public:
using type = T;
constexpr StrictNumeric() : value_(0) {}
// Copy constructor.
template <typename Src>
constexpr StrictNumeric(const StrictNumeric<Src>& rhs)
: value_(strict_cast<T>(rhs.value_)) {}
// This is not an explicit constructor because we implicitly upgrade regular
// numerics to StrictNumerics to make them easier to use.
template <typename Src>
constexpr StrictNumeric(Src value) // NOLINT(runtime/explicit)
: value_(strict_cast<T>(value)) {}
// If you got here from a compiler error, it's because you tried to assign
// from a source type to a destination type that has insufficient range.
// The solution may be to change the destination type you're assigning to,
// and use one large enough to represent the source.
// If you're assigning from a CheckedNumeric<> class, you may be able to use
// the AssignIfValid() member function, specify a narrower destination type to
// the member value functions (e.g. val.template ValueOrDie<Dst>()), use one
// of the value helper functions (e.g. ValueOrDieForType<Dst>(val)).
// If you've encountered an _ambiguous overload_ you can use a static_cast<>
// to explicitly cast the result to the destination type.
// If none of that works, you may be better served with the checked_cast<> or
// saturated_cast<> template functions for your particular use case.
template <typename Dst,
typename std::enable_if<
IsNumericRangeContained<Dst, T>::value>::type* = nullptr>
constexpr operator Dst() const {
return static_cast<typename ArithmeticOrUnderlyingEnum<Dst>::type>(value_);
}
private:
const T value_;
};
// Convience wrapper returns a StrictNumeric from the provided arithmetic type.
template <typename T>
constexpr StrictNumeric<typename UnderlyingType<T>::type> MakeStrictNum(
const T value) {
return value;
}
#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
// Overload the ostream output operator to make logging work nicely.
template <typename T>
std::ostream& operator<<(std::ostream& os, const StrictNumeric<T>& value) {
os << static_cast<T>(value);
return os;
}
#endif
#define BASE_NUMERIC_COMPARISON_OPERATORS(CLASS, NAME, OP) \
template <typename L, typename R, \
typename std::enable_if< \
internal::Is##CLASS##Op<L, R>::value>::type* = nullptr> \
constexpr bool operator OP(const L lhs, const R rhs) { \
return SafeCompare<NAME, typename UnderlyingType<L>::type, \
typename UnderlyingType<R>::type>(lhs, rhs); \
}
BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsLess, <)
BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsLessOrEqual, <=)
BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsGreater, >)
BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsGreaterOrEqual, >=)
BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsEqual, ==)
BASE_NUMERIC_COMPARISON_OPERATORS(Strict, IsNotEqual, !=)
} // namespace internal
using internal::as_signed;
using internal::as_unsigned;
using internal::checked_cast;
using internal::strict_cast;
using internal::saturated_cast;
using internal::SafeUnsignedAbs;
using internal::StrictNumeric;
using internal::MakeStrictNum;
using internal::IsValueInRangeForNumericType;
using internal::IsTypeInRangeForNumericType;
using internal::IsValueNegative;
// Explicitly make a shorter size_t alias for convenience.
using SizeT = StrictNumeric<size_t>;
} // namespace base
#endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_

View File

@@ -1,51 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_
#define BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_
#include <cassert>
#include <limits>
#include <type_traits>
#include "base/numerics/safe_conversions_impl.h"
namespace base {
namespace internal {
// Fast saturation to a destination type.
template <typename Dst, typename Src>
struct SaturateFastAsmOp {
static constexpr bool is_supported =
std::is_signed<Src>::value && std::is_integral<Dst>::value &&
std::is_integral<Src>::value &&
IntegerBitsPlusSign<Src>::value <= IntegerBitsPlusSign<int32_t>::value &&
IntegerBitsPlusSign<Dst>::value <= IntegerBitsPlusSign<int32_t>::value &&
!IsTypeInRangeForNumericType<Dst, Src>::value;
__attribute__((always_inline)) static Dst Do(Src value) {
int32_t src = value;
typename std::conditional<std::is_signed<Dst>::value, int32_t,
uint32_t>::type result;
if (std::is_signed<Dst>::value) {
asm("ssat %[dst], %[shift], %[src]"
: [dst] "=r"(result)
: [src] "r"(src), [shift] "n"(IntegerBitsPlusSign<Dst>::value <= 32
? IntegerBitsPlusSign<Dst>::value
: 32));
} else {
asm("usat %[dst], %[shift], %[src]"
: [dst] "=r"(result)
: [src] "r"(src), [shift] "n"(IntegerBitsPlusSign<Dst>::value < 32
? IntegerBitsPlusSign<Dst>::value
: 31));
}
return static_cast<Dst>(result);
}
};
} // namespace internal
} // namespace base
#endif // BASE_NUMERICS_SAFE_CONVERSIONS_ARM_IMPL_H_

View File

@@ -1,850 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
#define BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
#include <stdint.h>
#include <limits>
#include <type_traits>
#if defined(__GNUC__) || defined(__clang__)
#define BASE_NUMERICS_LIKELY(x) __builtin_expect(!!(x), 1)
#define BASE_NUMERICS_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define BASE_NUMERICS_LIKELY(x) (x)
#define BASE_NUMERICS_UNLIKELY(x) (x)
#endif
namespace base {
namespace internal {
// The std library doesn't provide a binary max_exponent for integers, however
// we can compute an analog using std::numeric_limits<>::digits.
template <typename NumericType>
struct MaxExponent {
static const int value = std::is_floating_point<NumericType>::value
? std::numeric_limits<NumericType>::max_exponent
: std::numeric_limits<NumericType>::digits + 1;
};
// The number of bits (including the sign) in an integer. Eliminates sizeof
// hacks.
template <typename NumericType>
struct IntegerBitsPlusSign {
static const int value = std::numeric_limits<NumericType>::digits +
std::is_signed<NumericType>::value;
};
// Helper templates for integer manipulations.
template <typename Integer>
struct PositionOfSignBit {
static const size_t value = IntegerBitsPlusSign<Integer>::value - 1;
};
// Determines if a numeric value is negative without throwing compiler
// warnings on: unsigned(value) < 0.
template <typename T,
typename std::enable_if<std::is_signed<T>::value>::type* = nullptr>
constexpr bool IsValueNegative(T value) {
static_assert(std::is_arithmetic<T>::value, "Argument must be numeric.");
return value < 0;
}
template <typename T,
typename std::enable_if<!std::is_signed<T>::value>::type* = nullptr>
constexpr bool IsValueNegative(T) {
static_assert(std::is_arithmetic<T>::value, "Argument must be numeric.");
return false;
}
// This performs a fast negation, returning a signed value. It works on unsigned
// arguments, but probably doesn't do what you want for any unsigned value
// larger than max / 2 + 1 (i.e. signed min cast to unsigned).
template <typename T>
constexpr typename std::make_signed<T>::type ConditionalNegate(
T x,
bool is_negative) {
static_assert(std::is_integral<T>::value, "Type must be integral");
using SignedT = typename std::make_signed<T>::type;
using UnsignedT = typename std::make_unsigned<T>::type;
return static_cast<SignedT>(
(static_cast<UnsignedT>(x) ^ -SignedT(is_negative)) + is_negative);
}
// This performs a safe, absolute value via unsigned overflow.
template <typename T>
constexpr typename std::make_unsigned<T>::type SafeUnsignedAbs(T value) {
static_assert(std::is_integral<T>::value, "Type must be integral");
using UnsignedT = typename std::make_unsigned<T>::type;
return IsValueNegative(value) ? 0 - static_cast<UnsignedT>(value)
: static_cast<UnsignedT>(value);
}
// This allows us to switch paths on known compile-time constants.
#if defined(__clang__) || defined(__GNUC__)
constexpr bool CanDetectCompileTimeConstant() {
return true;
}
template <typename T>
constexpr bool IsCompileTimeConstant(const T v) {
return __builtin_constant_p(v);
}
#else
constexpr bool CanDetectCompileTimeConstant() {
return false;
}
template <typename T>
constexpr bool IsCompileTimeConstant(const T) {
return false;
}
#endif
template <typename T>
constexpr bool MustTreatAsConstexpr(const T v) {
// Either we can't detect a compile-time constant, and must always use the
// constexpr path, or we know we have a compile-time constant.
return !CanDetectCompileTimeConstant() || IsCompileTimeConstant(v);
}
// Forces a crash, like a CHECK(false). Used for numeric boundary errors.
// Also used in a constexpr template to trigger a compilation failure on
// an error condition.
struct CheckOnFailure {
template <typename T>
static T HandleFailure() {
#if defined(_MSC_VER)
__debugbreak();
#elif defined(__GNUC__) || defined(__clang__)
__builtin_trap();
#else
((void)(*(volatile char*)0 = 0));
#endif
return T();
}
};
enum IntegerRepresentation {
INTEGER_REPRESENTATION_UNSIGNED,
INTEGER_REPRESENTATION_SIGNED
};
// A range for a given nunmeric Src type is contained for a given numeric Dst
// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and
// numeric_limits<Src>::lowest() >= numeric_limits<Dst>::lowest() are true.
// We implement this as template specializations rather than simple static
// comparisons to ensure type correctness in our comparisons.
enum NumericRangeRepresentation {
NUMERIC_RANGE_NOT_CONTAINED,
NUMERIC_RANGE_CONTAINED
};
// Helper templates to statically determine if our destination type can contain
// maximum and minimum values represented by the source type.
template <typename Dst,
typename Src,
IntegerRepresentation DstSign = std::is_signed<Dst>::value
? INTEGER_REPRESENTATION_SIGNED
: INTEGER_REPRESENTATION_UNSIGNED,
IntegerRepresentation SrcSign = std::is_signed<Src>::value
? INTEGER_REPRESENTATION_SIGNED
: INTEGER_REPRESENTATION_UNSIGNED>
struct StaticDstRangeRelationToSrcRange;
// Same sign: Dst is guaranteed to contain Src only if its range is equal or
// larger.
template <typename Dst, typename Src, IntegerRepresentation Sign>
struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign> {
static const NumericRangeRepresentation value =
MaxExponent<Dst>::value >= MaxExponent<Src>::value
? NUMERIC_RANGE_CONTAINED
: NUMERIC_RANGE_NOT_CONTAINED;
};
// Unsigned to signed: Dst is guaranteed to contain source only if its range is
// larger.
template <typename Dst, typename Src>
struct StaticDstRangeRelationToSrcRange<Dst,
Src,
INTEGER_REPRESENTATION_SIGNED,
INTEGER_REPRESENTATION_UNSIGNED> {
static const NumericRangeRepresentation value =
MaxExponent<Dst>::value > MaxExponent<Src>::value
? NUMERIC_RANGE_CONTAINED
: NUMERIC_RANGE_NOT_CONTAINED;
};
// Signed to unsigned: Dst cannot be statically determined to contain Src.
template <typename Dst, typename Src>
struct StaticDstRangeRelationToSrcRange<Dst,
Src,
INTEGER_REPRESENTATION_UNSIGNED,
INTEGER_REPRESENTATION_SIGNED> {
static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
};
// This class wraps the range constraints as separate booleans so the compiler
// can identify constants and eliminate unused code paths.
class RangeCheck {
public:
constexpr RangeCheck(bool is_in_lower_bound, bool is_in_upper_bound)
: is_underflow_(!is_in_lower_bound), is_overflow_(!is_in_upper_bound) {}
constexpr RangeCheck() : is_underflow_(0), is_overflow_(0) {}
constexpr bool IsValid() const { return !is_overflow_ && !is_underflow_; }
constexpr bool IsInvalid() const { return is_overflow_ && is_underflow_; }
constexpr bool IsOverflow() const { return is_overflow_ && !is_underflow_; }
constexpr bool IsUnderflow() const { return !is_overflow_ && is_underflow_; }
constexpr bool IsOverflowFlagSet() const { return is_overflow_; }
constexpr bool IsUnderflowFlagSet() const { return is_underflow_; }
constexpr bool operator==(const RangeCheck rhs) const {
return is_underflow_ == rhs.is_underflow_ &&
is_overflow_ == rhs.is_overflow_;
}
constexpr bool operator!=(const RangeCheck rhs) const {
return !(*this == rhs);
}
private:
// Do not change the order of these member variables. The integral conversion
// optimization depends on this exact order.
const bool is_underflow_;
const bool is_overflow_;
};
// The following helper template addresses a corner case in range checks for
// conversion from a floating-point type to an integral type of smaller range
// but larger precision (e.g. float -> unsigned). The problem is as follows:
// 1. Integral maximum is always one less than a power of two, so it must be
// truncated to fit the mantissa of the floating point. The direction of
// rounding is implementation defined, but by default it's always IEEE
// floats, which round to nearest and thus result in a value of larger
// magnitude than the integral value.
// Example: float f = UINT_MAX; // f is 4294967296f but UINT_MAX
// // is 4294967295u.
// 2. If the floating point value is equal to the promoted integral maximum
// value, a range check will erroneously pass.
// Example: (4294967296f <= 4294967295u) // This is true due to a precision
// // loss in rounding up to float.
// 3. When the floating point value is then converted to an integral, the
// resulting value is out of range for the target integral type and
// thus is implementation defined.
// Example: unsigned u = (float)INT_MAX; // u will typically overflow to 0.
// To fix this bug we manually truncate the maximum value when the destination
// type is an integral of larger precision than the source floating-point type,
// such that the resulting maximum is represented exactly as a floating point.
template <typename Dst, typename Src, template <typename> class Bounds>
struct NarrowingRange {
using SrcLimits = std::numeric_limits<Src>;
using DstLimits = typename std::numeric_limits<Dst>;
// Computes the mask required to make an accurate comparison between types.
static const int kShift =
(MaxExponent<Src>::value > MaxExponent<Dst>::value &&
SrcLimits::digits < DstLimits::digits)
? (DstLimits::digits - SrcLimits::digits)
: 0;
template <
typename T,
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
// Masks out the integer bits that are beyond the precision of the
// intermediate type used for comparison.
static constexpr T Adjust(T value) {
static_assert(std::is_same<T, Dst>::value, "");
static_assert(kShift < DstLimits::digits, "");
return static_cast<T>(
ConditionalNegate(SafeUnsignedAbs(value) & ~((T(1) << kShift) - T(1)),
IsValueNegative(value)));
}
template <typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type* =
nullptr>
static constexpr T Adjust(T value) {
static_assert(std::is_same<T, Dst>::value, "");
static_assert(kShift == 0, "");
return value;
}
static constexpr Dst max() { return Adjust(Bounds<Dst>::max()); }
static constexpr Dst lowest() { return Adjust(Bounds<Dst>::lowest()); }
};
template <typename Dst,
typename Src,
template <typename> class Bounds,
IntegerRepresentation DstSign = std::is_signed<Dst>::value
? INTEGER_REPRESENTATION_SIGNED
: INTEGER_REPRESENTATION_UNSIGNED,
IntegerRepresentation SrcSign = std::is_signed<Src>::value
? INTEGER_REPRESENTATION_SIGNED
: INTEGER_REPRESENTATION_UNSIGNED,
NumericRangeRepresentation DstRange =
StaticDstRangeRelationToSrcRange<Dst, Src>::value>
struct DstRangeRelationToSrcRangeImpl;
// The following templates are for ranges that must be verified at runtime. We
// split it into checks based on signedness to avoid confusing casts and
// compiler warnings on signed an unsigned comparisons.
// Same sign narrowing: The range is contained for normal limits.
template <typename Dst,
typename Src,
template <typename> class Bounds,
IntegerRepresentation DstSign,
IntegerRepresentation SrcSign>
struct DstRangeRelationToSrcRangeImpl<Dst,
Src,
Bounds,
DstSign,
SrcSign,
NUMERIC_RANGE_CONTAINED> {
static constexpr RangeCheck Check(Src value) {
using SrcLimits = std::numeric_limits<Src>;
using DstLimits = NarrowingRange<Dst, Src, Bounds>;
return RangeCheck(
static_cast<Dst>(SrcLimits::lowest()) >= DstLimits::lowest() ||
static_cast<Dst>(value) >= DstLimits::lowest(),
static_cast<Dst>(SrcLimits::max()) <= DstLimits::max() ||
static_cast<Dst>(value) <= DstLimits::max());
}
};
// Signed to signed narrowing: Both the upper and lower boundaries may be
// exceeded for standard limits.
template <typename Dst, typename Src, template <typename> class Bounds>
struct DstRangeRelationToSrcRangeImpl<Dst,
Src,
Bounds,
INTEGER_REPRESENTATION_SIGNED,
INTEGER_REPRESENTATION_SIGNED,
NUMERIC_RANGE_NOT_CONTAINED> {
static constexpr RangeCheck Check(Src value) {
using DstLimits = NarrowingRange<Dst, Src, Bounds>;
return RangeCheck(value >= DstLimits::lowest(), value <= DstLimits::max());
}
};
// Unsigned to unsigned narrowing: Only the upper bound can be exceeded for
// standard limits.
template <typename Dst, typename Src, template <typename> class Bounds>
struct DstRangeRelationToSrcRangeImpl<Dst,
Src,
Bounds,
INTEGER_REPRESENTATION_UNSIGNED,
INTEGER_REPRESENTATION_UNSIGNED,
NUMERIC_RANGE_NOT_CONTAINED> {
static constexpr RangeCheck Check(Src value) {
using DstLimits = NarrowingRange<Dst, Src, Bounds>;
return RangeCheck(
DstLimits::lowest() == Dst(0) || value >= DstLimits::lowest(),
value <= DstLimits::max());
}
};
// Unsigned to signed: Only the upper bound can be exceeded for standard limits.
template <typename Dst, typename Src, template <typename> class Bounds>
struct DstRangeRelationToSrcRangeImpl<Dst,
Src,
Bounds,
INTEGER_REPRESENTATION_SIGNED,
INTEGER_REPRESENTATION_UNSIGNED,
NUMERIC_RANGE_NOT_CONTAINED> {
static constexpr RangeCheck Check(Src value) {
using DstLimits = NarrowingRange<Dst, Src, Bounds>;
using Promotion = decltype(Src() + Dst());
return RangeCheck(DstLimits::lowest() <= Dst(0) ||
static_cast<Promotion>(value) >=
static_cast<Promotion>(DstLimits::lowest()),
static_cast<Promotion>(value) <=
static_cast<Promotion>(DstLimits::max()));
}
};
// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst,
// and any negative value exceeds the lower boundary for standard limits.
template <typename Dst, typename Src, template <typename> class Bounds>
struct DstRangeRelationToSrcRangeImpl<Dst,
Src,
Bounds,
INTEGER_REPRESENTATION_UNSIGNED,
INTEGER_REPRESENTATION_SIGNED,
NUMERIC_RANGE_NOT_CONTAINED> {
static constexpr RangeCheck Check(Src value) {
using SrcLimits = std::numeric_limits<Src>;
using DstLimits = NarrowingRange<Dst, Src, Bounds>;
using Promotion = decltype(Src() + Dst());
return RangeCheck(
value >= Src(0) && (DstLimits::lowest() == 0 ||
static_cast<Dst>(value) >= DstLimits::lowest()),
static_cast<Promotion>(SrcLimits::max()) <=
static_cast<Promotion>(DstLimits::max()) ||
static_cast<Promotion>(value) <=
static_cast<Promotion>(DstLimits::max()));
}
};
// Simple wrapper for statically checking if a type's range is contained.
template <typename Dst, typename Src>
struct IsTypeInRangeForNumericType {
static const bool value = StaticDstRangeRelationToSrcRange<Dst, Src>::value ==
NUMERIC_RANGE_CONTAINED;
};
template <typename Dst,
template <typename> class Bounds = std::numeric_limits,
typename Src>
constexpr RangeCheck DstRangeRelationToSrcRange(Src value) {
static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
static_assert(std::is_arithmetic<Dst>::value, "Result must be numeric.");
static_assert(Bounds<Dst>::lowest() < Bounds<Dst>::max(), "");
return DstRangeRelationToSrcRangeImpl<Dst, Src, Bounds>::Check(value);
}
// Integer promotion templates used by the portable checked integer arithmetic.
template <size_t Size, bool IsSigned>
struct IntegerForDigitsAndSign;
#define INTEGER_FOR_DIGITS_AND_SIGN(I) \
template <> \
struct IntegerForDigitsAndSign<IntegerBitsPlusSign<I>::value, \
std::is_signed<I>::value> { \
using type = I; \
}
INTEGER_FOR_DIGITS_AND_SIGN(int8_t);
INTEGER_FOR_DIGITS_AND_SIGN(uint8_t);
INTEGER_FOR_DIGITS_AND_SIGN(int16_t);
INTEGER_FOR_DIGITS_AND_SIGN(uint16_t);
INTEGER_FOR_DIGITS_AND_SIGN(int32_t);
INTEGER_FOR_DIGITS_AND_SIGN(uint32_t);
INTEGER_FOR_DIGITS_AND_SIGN(int64_t);
INTEGER_FOR_DIGITS_AND_SIGN(uint64_t);
#undef INTEGER_FOR_DIGITS_AND_SIGN
// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to
// support 128-bit math, then the ArithmeticPromotion template below will need
// to be updated (or more likely replaced with a decltype expression).
static_assert(IntegerBitsPlusSign<intmax_t>::value == 64,
"Max integer size not supported for this toolchain.");
template <typename Integer, bool IsSigned = std::is_signed<Integer>::value>
struct TwiceWiderInteger {
using type =
typename IntegerForDigitsAndSign<IntegerBitsPlusSign<Integer>::value * 2,
IsSigned>::type;
};
enum ArithmeticPromotionCategory {
LEFT_PROMOTION, // Use the type of the left-hand argument.
RIGHT_PROMOTION // Use the type of the right-hand argument.
};
// Determines the type that can represent the largest positive value.
template <typename Lhs,
typename Rhs,
ArithmeticPromotionCategory Promotion =
(MaxExponent<Lhs>::value > MaxExponent<Rhs>::value)
? LEFT_PROMOTION
: RIGHT_PROMOTION>
struct MaxExponentPromotion;
template <typename Lhs, typename Rhs>
struct MaxExponentPromotion<Lhs, Rhs, LEFT_PROMOTION> {
using type = Lhs;
};
template <typename Lhs, typename Rhs>
struct MaxExponentPromotion<Lhs, Rhs, RIGHT_PROMOTION> {
using type = Rhs;
};
// Determines the type that can represent the lowest arithmetic value.
template <typename Lhs,
typename Rhs,
ArithmeticPromotionCategory Promotion =
std::is_signed<Lhs>::value
? (std::is_signed<Rhs>::value
? (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value
? LEFT_PROMOTION
: RIGHT_PROMOTION)
: LEFT_PROMOTION)
: (std::is_signed<Rhs>::value
? RIGHT_PROMOTION
: (MaxExponent<Lhs>::value < MaxExponent<Rhs>::value
? LEFT_PROMOTION
: RIGHT_PROMOTION))>
struct LowestValuePromotion;
template <typename Lhs, typename Rhs>
struct LowestValuePromotion<Lhs, Rhs, LEFT_PROMOTION> {
using type = Lhs;
};
template <typename Lhs, typename Rhs>
struct LowestValuePromotion<Lhs, Rhs, RIGHT_PROMOTION> {
using type = Rhs;
};
// Determines the type that is best able to represent an arithmetic result.
template <
typename Lhs,
typename Rhs = Lhs,
bool is_intmax_type =
std::is_integral<typename MaxExponentPromotion<Lhs, Rhs>::type>::value&&
IntegerBitsPlusSign<typename MaxExponentPromotion<Lhs, Rhs>::type>::
value == IntegerBitsPlusSign<intmax_t>::value,
bool is_max_exponent =
StaticDstRangeRelationToSrcRange<
typename MaxExponentPromotion<Lhs, Rhs>::type,
Lhs>::value ==
NUMERIC_RANGE_CONTAINED&& StaticDstRangeRelationToSrcRange<
typename MaxExponentPromotion<Lhs, Rhs>::type,
Rhs>::value == NUMERIC_RANGE_CONTAINED>
struct BigEnoughPromotion;
// The side with the max exponent is big enough.
template <typename Lhs, typename Rhs, bool is_intmax_type>
struct BigEnoughPromotion<Lhs, Rhs, is_intmax_type, true> {
using type = typename MaxExponentPromotion<Lhs, Rhs>::type;
static const bool is_contained = true;
};
// We can use a twice wider type to fit.
template <typename Lhs, typename Rhs>
struct BigEnoughPromotion<Lhs, Rhs, false, false> {
using type =
typename TwiceWiderInteger<typename MaxExponentPromotion<Lhs, Rhs>::type,
std::is_signed<Lhs>::value ||
std::is_signed<Rhs>::value>::type;
static const bool is_contained = true;
};
// No type is large enough.
template <typename Lhs, typename Rhs>
struct BigEnoughPromotion<Lhs, Rhs, true, false> {
using type = typename MaxExponentPromotion<Lhs, Rhs>::type;
static const bool is_contained = false;
};
// We can statically check if operations on the provided types can wrap, so we
// can skip the checked operations if they're not needed. So, for an integer we
// care if the destination type preserves the sign and is twice the width of
// the source.
template <typename T, typename Lhs, typename Rhs = Lhs>
struct IsIntegerArithmeticSafe {
static const bool value =
!std::is_floating_point<T>::value &&
!std::is_floating_point<Lhs>::value &&
!std::is_floating_point<Rhs>::value &&
std::is_signed<T>::value >= std::is_signed<Lhs>::value &&
IntegerBitsPlusSign<T>::value >= (2 * IntegerBitsPlusSign<Lhs>::value) &&
std::is_signed<T>::value >= std::is_signed<Rhs>::value &&
IntegerBitsPlusSign<T>::value >= (2 * IntegerBitsPlusSign<Rhs>::value);
};
// Promotes to a type that can represent any possible result of a binary
// arithmetic operation with the source types.
template <typename Lhs,
typename Rhs,
bool is_promotion_possible = IsIntegerArithmeticSafe<
typename std::conditional<std::is_signed<Lhs>::value ||
std::is_signed<Rhs>::value,
intmax_t,
uintmax_t>::type,
typename MaxExponentPromotion<Lhs, Rhs>::type>::value>
struct FastIntegerArithmeticPromotion;
template <typename Lhs, typename Rhs>
struct FastIntegerArithmeticPromotion<Lhs, Rhs, true> {
using type =
typename TwiceWiderInteger<typename MaxExponentPromotion<Lhs, Rhs>::type,
std::is_signed<Lhs>::value ||
std::is_signed<Rhs>::value>::type;
static_assert(IsIntegerArithmeticSafe<type, Lhs, Rhs>::value, "");
static const bool is_contained = true;
};
template <typename Lhs, typename Rhs>
struct FastIntegerArithmeticPromotion<Lhs, Rhs, false> {
using type = typename BigEnoughPromotion<Lhs, Rhs>::type;
static const bool is_contained = false;
};
// Extracts the underlying type from an enum.
template <typename T, bool is_enum = std::is_enum<T>::value>
struct ArithmeticOrUnderlyingEnum;
template <typename T>
struct ArithmeticOrUnderlyingEnum<T, true> {
using type = typename std::underlying_type<T>::type;
static const bool value = std::is_arithmetic<type>::value;
};
template <typename T>
struct ArithmeticOrUnderlyingEnum<T, false> {
using type = T;
static const bool value = std::is_arithmetic<type>::value;
};
// The following are helper templates used in the CheckedNumeric class.
template <typename T>
class CheckedNumeric;
template <typename T>
class ClampedNumeric;
template <typename T>
class StrictNumeric;
// Used to treat CheckedNumeric and arithmetic underlying types the same.
template <typename T>
struct UnderlyingType {
using type = typename ArithmeticOrUnderlyingEnum<T>::type;
static const bool is_numeric = std::is_arithmetic<type>::value;
static const bool is_checked = false;
static const bool is_clamped = false;
static const bool is_strict = false;
};
template <typename T>
struct UnderlyingType<CheckedNumeric<T>> {
using type = T;
static const bool is_numeric = true;
static const bool is_checked = true;
static const bool is_clamped = false;
static const bool is_strict = false;
};
template <typename T>
struct UnderlyingType<ClampedNumeric<T>> {
using type = T;
static const bool is_numeric = true;
static const bool is_checked = false;
static const bool is_clamped = true;
static const bool is_strict = false;
};
template <typename T>
struct UnderlyingType<StrictNumeric<T>> {
using type = T;
static const bool is_numeric = true;
static const bool is_checked = false;
static const bool is_clamped = false;
static const bool is_strict = true;
};
template <typename L, typename R>
struct IsCheckedOp {
static const bool value =
UnderlyingType<L>::is_numeric && UnderlyingType<R>::is_numeric &&
(UnderlyingType<L>::is_checked || UnderlyingType<R>::is_checked);
};
template <typename L, typename R>
struct IsClampedOp {
static const bool value =
UnderlyingType<L>::is_numeric && UnderlyingType<R>::is_numeric &&
(UnderlyingType<L>::is_clamped || UnderlyingType<R>::is_clamped) &&
!(UnderlyingType<L>::is_checked || UnderlyingType<R>::is_checked);
};
template <typename L, typename R>
struct IsStrictOp {
static const bool value =
UnderlyingType<L>::is_numeric && UnderlyingType<R>::is_numeric &&
(UnderlyingType<L>::is_strict || UnderlyingType<R>::is_strict) &&
!(UnderlyingType<L>::is_checked || UnderlyingType<R>::is_checked) &&
!(UnderlyingType<L>::is_clamped || UnderlyingType<R>::is_clamped);
};
// as_signed<> returns the supplied integral value (or integral castable
// Numeric template) cast as a signed integral of equivalent precision.
// I.e. it's mostly an alias for: static_cast<std::make_signed<T>::type>(t)
template <typename Src>
constexpr typename std::make_signed<
typename base::internal::UnderlyingType<Src>::type>::type
as_signed(const Src value) {
static_assert(std::is_integral<decltype(as_signed(value))>::value,
"Argument must be a signed or unsigned integer type.");
return static_cast<decltype(as_signed(value))>(value);
}
// as_unsigned<> returns the supplied integral value (or integral castable
// Numeric template) cast as an unsigned integral of equivalent precision.
// I.e. it's mostly an alias for: static_cast<std::make_unsigned<T>::type>(t)
template <typename Src>
constexpr typename std::make_unsigned<
typename base::internal::UnderlyingType<Src>::type>::type
as_unsigned(const Src value) {
static_assert(std::is_integral<decltype(as_unsigned(value))>::value,
"Argument must be a signed or unsigned integer type.");
return static_cast<decltype(as_unsigned(value))>(value);
}
template <typename L, typename R>
constexpr bool IsLessImpl(const L lhs,
const R rhs,
const RangeCheck l_range,
const RangeCheck r_range) {
return l_range.IsUnderflow() || r_range.IsOverflow() ||
(l_range == r_range &&
static_cast<decltype(lhs + rhs)>(lhs) <
static_cast<decltype(lhs + rhs)>(rhs));
}
template <typename L, typename R>
struct IsLess {
static_assert(std::is_arithmetic<L>::value && std::is_arithmetic<R>::value,
"Types must be numeric.");
static constexpr bool Test(const L lhs, const R rhs) {
return IsLessImpl(lhs, rhs, DstRangeRelationToSrcRange<R>(lhs),
DstRangeRelationToSrcRange<L>(rhs));
}
};
template <typename L, typename R>
constexpr bool IsLessOrEqualImpl(const L lhs,
const R rhs,
const RangeCheck l_range,
const RangeCheck r_range) {
return l_range.IsUnderflow() || r_range.IsOverflow() ||
(l_range == r_range &&
static_cast<decltype(lhs + rhs)>(lhs) <=
static_cast<decltype(lhs + rhs)>(rhs));
}
template <typename L, typename R>
struct IsLessOrEqual {
static_assert(std::is_arithmetic<L>::value && std::is_arithmetic<R>::value,
"Types must be numeric.");
static constexpr bool Test(const L lhs, const R rhs) {
return IsLessOrEqualImpl(lhs, rhs, DstRangeRelationToSrcRange<R>(lhs),
DstRangeRelationToSrcRange<L>(rhs));
}
};
template <typename L, typename R>
constexpr bool IsGreaterImpl(const L lhs,
const R rhs,
const RangeCheck l_range,
const RangeCheck r_range) {
return l_range.IsOverflow() || r_range.IsUnderflow() ||
(l_range == r_range &&
static_cast<decltype(lhs + rhs)>(lhs) >
static_cast<decltype(lhs + rhs)>(rhs));
}
template <typename L, typename R>
struct IsGreater {
static_assert(std::is_arithmetic<L>::value && std::is_arithmetic<R>::value,
"Types must be numeric.");
static constexpr bool Test(const L lhs, const R rhs) {
return IsGreaterImpl(lhs, rhs, DstRangeRelationToSrcRange<R>(lhs),
DstRangeRelationToSrcRange<L>(rhs));
}
};
template <typename L, typename R>
constexpr bool IsGreaterOrEqualImpl(const L lhs,
const R rhs,
const RangeCheck l_range,
const RangeCheck r_range) {
return l_range.IsOverflow() || r_range.IsUnderflow() ||
(l_range == r_range &&
static_cast<decltype(lhs + rhs)>(lhs) >=
static_cast<decltype(lhs + rhs)>(rhs));
}
template <typename L, typename R>
struct IsGreaterOrEqual {
static_assert(std::is_arithmetic<L>::value && std::is_arithmetic<R>::value,
"Types must be numeric.");
static constexpr bool Test(const L lhs, const R rhs) {
return IsGreaterOrEqualImpl(lhs, rhs, DstRangeRelationToSrcRange<R>(lhs),
DstRangeRelationToSrcRange<L>(rhs));
}
};
template <typename L, typename R>
struct IsEqual {
static_assert(std::is_arithmetic<L>::value && std::is_arithmetic<R>::value,
"Types must be numeric.");
static constexpr bool Test(const L lhs, const R rhs) {
return DstRangeRelationToSrcRange<R>(lhs) ==
DstRangeRelationToSrcRange<L>(rhs) &&
static_cast<decltype(lhs + rhs)>(lhs) ==
static_cast<decltype(lhs + rhs)>(rhs);
}
};
template <typename L, typename R>
struct IsNotEqual {
static_assert(std::is_arithmetic<L>::value && std::is_arithmetic<R>::value,
"Types must be numeric.");
static constexpr bool Test(const L lhs, const R rhs) {
return DstRangeRelationToSrcRange<R>(lhs) !=
DstRangeRelationToSrcRange<L>(rhs) ||
static_cast<decltype(lhs + rhs)>(lhs) !=
static_cast<decltype(lhs + rhs)>(rhs);
}
};
// These perform the actual math operations on the CheckedNumerics.
// Binary arithmetic operations.
template <template <typename, typename> class C, typename L, typename R>
constexpr bool SafeCompare(const L lhs, const R rhs) {
static_assert(std::is_arithmetic<L>::value && std::is_arithmetic<R>::value,
"Types must be numeric.");
using Promotion = BigEnoughPromotion<L, R>;
using BigType = typename Promotion::type;
return Promotion::is_contained
// Force to a larger type for speed if both are contained.
? C<BigType, BigType>::Test(
static_cast<BigType>(static_cast<L>(lhs)),
static_cast<BigType>(static_cast<R>(rhs)))
// Let the template functions figure it out for mixed types.
: C<L, R>::Test(lhs, rhs);
}
template <typename Dst, typename Src>
constexpr bool IsMaxInRangeForNumericType() {
return IsGreaterOrEqual<Dst, Src>::Test(std::numeric_limits<Dst>::max(),
std::numeric_limits<Src>::max());
}
template <typename Dst, typename Src>
constexpr bool IsMinInRangeForNumericType() {
return IsLessOrEqual<Dst, Src>::Test(std::numeric_limits<Dst>::lowest(),
std::numeric_limits<Src>::lowest());
}
template <typename Dst, typename Src>
constexpr Dst CommonMax() {
return !IsMaxInRangeForNumericType<Dst, Src>()
? Dst(std::numeric_limits<Dst>::max())
: Dst(std::numeric_limits<Src>::max());
}
template <typename Dst, typename Src>
constexpr Dst CommonMin() {
return !IsMinInRangeForNumericType<Dst, Src>()
? Dst(std::numeric_limits<Dst>::lowest())
: Dst(std::numeric_limits<Src>::lowest());
}
// This is a wrapper to generate return the max or min for a supplied type.
// If the argument is false, the returned value is the maximum. If true the
// returned value is the minimum.
template <typename Dst, typename Src = Dst>
constexpr Dst CommonMaxOrMin(bool is_min) {
return is_min ? CommonMin<Dst, Src>() : CommonMax<Dst, Src>();
}
} // namespace internal
} // namespace base
#endif // BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_

View File

@@ -1,12 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_SAFE_MATH_H_
#define BASE_NUMERICS_SAFE_MATH_H_
#include "base/numerics/checked_math.h"
#include "base/numerics/clamped_math.h"
#include "base/numerics/safe_conversions.h"
#endif // BASE_NUMERICS_SAFE_MATH_H_

View File

@@ -1,122 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
#define BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
#include <cassert>
#include <limits>
#include <type_traits>
#include "base/numerics/safe_conversions.h"
namespace base {
namespace internal {
template <typename T, typename U>
struct CheckedMulFastAsmOp {
static const bool is_supported =
FastIntegerArithmeticPromotion<T, U>::is_contained;
// The following is much more efficient than the Clang and GCC builtins for
// performing overflow-checked multiplication when a twice wider type is
// available. The below compiles down to 2-3 instructions, depending on the
// width of the types in use.
// As an example, an int32_t multiply compiles to:
// smull r0, r1, r0, r1
// cmp r1, r1, asr #31
// And an int16_t multiply compiles to:
// smulbb r1, r1, r0
// asr r2, r1, #16
// cmp r2, r1, asr #15
template <typename V>
__attribute__((always_inline)) static bool Do(T x, U y, V* result) {
using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
Promotion presult;
presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
*result = static_cast<V>(presult);
return IsValueInRangeForNumericType<V>(presult);
}
};
template <typename T, typename U>
struct ClampedAddFastAsmOp {
static const bool is_supported =
BigEnoughPromotion<T, U>::is_contained &&
IsTypeInRangeForNumericType<
int32_t,
typename BigEnoughPromotion<T, U>::type>::value;
template <typename V>
__attribute__((always_inline)) static V Do(T x, U y) {
// This will get promoted to an int, so let the compiler do whatever is
// clever and rely on the saturated cast to bounds check.
if (IsIntegerArithmeticSafe<int, T, U>::value)
return saturated_cast<V>(x + y);
int32_t result;
int32_t x_i32 = checked_cast<int32_t>(x);
int32_t y_i32 = checked_cast<int32_t>(y);
asm("qadd %[result], %[first], %[second]"
: [result] "=r"(result)
: [first] "r"(x_i32), [second] "r"(y_i32));
return saturated_cast<V>(result);
}
};
template <typename T, typename U>
struct ClampedSubFastAsmOp {
static const bool is_supported =
BigEnoughPromotion<T, U>::is_contained &&
IsTypeInRangeForNumericType<
int32_t,
typename BigEnoughPromotion<T, U>::type>::value;
template <typename V>
__attribute__((always_inline)) static V Do(T x, U y) {
// This will get promoted to an int, so let the compiler do whatever is
// clever and rely on the saturated cast to bounds check.
if (IsIntegerArithmeticSafe<int, T, U>::value)
return saturated_cast<V>(x - y);
int32_t result;
int32_t x_i32 = checked_cast<int32_t>(x);
int32_t y_i32 = checked_cast<int32_t>(y);
asm("qsub %[result], %[first], %[second]"
: [result] "=r"(result)
: [first] "r"(x_i32), [second] "r"(y_i32));
return saturated_cast<V>(result);
}
};
template <typename T, typename U>
struct ClampedMulFastAsmOp {
static const bool is_supported = CheckedMulFastAsmOp<T, U>::is_supported;
template <typename V>
__attribute__((always_inline)) static V Do(T x, U y) {
// Use the CheckedMulFastAsmOp for full-width 32-bit values, because
// it's fewer instructions than promoting and then saturating.
if (!IsIntegerArithmeticSafe<int32_t, T, U>::value &&
!IsIntegerArithmeticSafe<uint32_t, T, U>::value) {
V result;
if (CheckedMulFastAsmOp<T, U>::Do(x, y, &result))
return result;
return CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y));
}
assert((FastIntegerArithmeticPromotion<T, U>::is_contained));
using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
return saturated_cast<V>(static_cast<Promotion>(x) *
static_cast<Promotion>(y));
}
};
} // namespace internal
} // namespace base
#endif // BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_

View File

@@ -1,157 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
#define BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
#include <cassert>
#include <limits>
#include <type_traits>
#include "base/numerics/safe_conversions.h"
#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__))
#include "base/numerics/safe_math_arm_impl.h"
#define BASE_HAS_ASSEMBLER_SAFE_MATH (1)
#else
#define BASE_HAS_ASSEMBLER_SAFE_MATH (0)
#endif
namespace base {
namespace internal {
// These are the non-functioning boilerplate implementations of the optimized
// safe math routines.
#if !BASE_HAS_ASSEMBLER_SAFE_MATH
template <typename T, typename U>
struct CheckedMulFastAsmOp {
static const bool is_supported = false;
template <typename V>
static constexpr bool Do(T, U, V*) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<bool>();
}
};
template <typename T, typename U>
struct ClampedAddFastAsmOp {
static const bool is_supported = false;
template <typename V>
static constexpr V Do(T, U) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<V>();
}
};
template <typename T, typename U>
struct ClampedSubFastAsmOp {
static const bool is_supported = false;
template <typename V>
static constexpr V Do(T, U) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<V>();
}
};
template <typename T, typename U>
struct ClampedMulFastAsmOp {
static const bool is_supported = false;
template <typename V>
static constexpr V Do(T, U) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<V>();
}
};
#endif // BASE_HAS_ASSEMBLER_SAFE_MATH
#undef BASE_HAS_ASSEMBLER_SAFE_MATH
template <typename T, typename U>
struct CheckedAddFastOp {
static const bool is_supported = true;
template <typename V>
__attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
return !__builtin_add_overflow(x, y, result);
}
};
template <typename T, typename U>
struct CheckedSubFastOp {
static const bool is_supported = true;
template <typename V>
__attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
return !__builtin_sub_overflow(x, y, result);
}
};
template <typename T, typename U>
struct CheckedMulFastOp {
#if defined(__clang__)
// TODO(jschuh): Get the Clang runtime library issues sorted out so we can
// support full-width, mixed-sign multiply builtins.
// https://crbug.com/613003
// We can support intptr_t, uintptr_t, or a smaller common type.
static const bool is_supported =
(IsTypeInRangeForNumericType<intptr_t, T>::value &&
IsTypeInRangeForNumericType<intptr_t, U>::value) ||
(IsTypeInRangeForNumericType<uintptr_t, T>::value &&
IsTypeInRangeForNumericType<uintptr_t, U>::value);
#else
static const bool is_supported = true;
#endif
template <typename V>
__attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
return CheckedMulFastAsmOp<T, U>::is_supported
? CheckedMulFastAsmOp<T, U>::Do(x, y, result)
: !__builtin_mul_overflow(x, y, result);
}
};
template <typename T, typename U>
struct ClampedAddFastOp {
static const bool is_supported = ClampedAddFastAsmOp<T, U>::is_supported;
template <typename V>
__attribute__((always_inline)) static V Do(T x, U y) {
return ClampedAddFastAsmOp<T, U>::template Do<V>(x, y);
}
};
template <typename T, typename U>
struct ClampedSubFastOp {
static const bool is_supported = ClampedSubFastAsmOp<T, U>::is_supported;
template <typename V>
__attribute__((always_inline)) static V Do(T x, U y) {
return ClampedSubFastAsmOp<T, U>::template Do<V>(x, y);
}
};
template <typename T, typename U>
struct ClampedMulFastOp {
static const bool is_supported = ClampedMulFastAsmOp<T, U>::is_supported;
template <typename V>
__attribute__((always_inline)) static V Do(T x, U y) {
return ClampedMulFastAsmOp<T, U>::template Do<V>(x, y);
}
};
template <typename T>
struct ClampedNegFastOp {
static const bool is_supported = std::is_signed<T>::value;
__attribute__((always_inline)) static T Do(T value) {
// Use this when there is no assembler path available.
if (!ClampedSubFastAsmOp<T, T>::is_supported) {
T result;
return !__builtin_sub_overflow(T(0), value, &result)
? result
: std::numeric_limits<T>::max();
}
// Fallback to the normal subtraction path.
return ClampedSubFastOp<T, T>::template Do<T>(T(0), value);
}
};
} // namespace internal
} // namespace base
#endif // BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_

View File

@@ -1,240 +0,0 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
#define BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_
#include <stddef.h>
#include <stdint.h>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <type_traits>
#include "base/numerics/safe_conversions.h"
#ifdef __asmjs__
// Optimized safe math instructions are incompatible with asmjs.
#define BASE_HAS_OPTIMIZED_SAFE_MATH (0)
// Where available use builtin math overflow support on Clang and GCC.
#elif !defined(__native_client__) && \
((defined(__clang__) && \
((__clang_major__ > 3) || \
(__clang_major__ == 3 && __clang_minor__ >= 4))) || \
(defined(__GNUC__) && __GNUC__ >= 5))
#include "base/numerics/safe_math_clang_gcc_impl.h"
#define BASE_HAS_OPTIMIZED_SAFE_MATH (1)
#else
#define BASE_HAS_OPTIMIZED_SAFE_MATH (0)
#endif
namespace base {
namespace internal {
// These are the non-functioning boilerplate implementations of the optimized
// safe math routines.
#if !BASE_HAS_OPTIMIZED_SAFE_MATH
template <typename T, typename U>
struct CheckedAddFastOp {
static const bool is_supported = false;
template <typename V>
static constexpr bool Do(T, U, V*) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<bool>();
}
};
template <typename T, typename U>
struct CheckedSubFastOp {
static const bool is_supported = false;
template <typename V>
static constexpr bool Do(T, U, V*) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<bool>();
}
};
template <typename T, typename U>
struct CheckedMulFastOp {
static const bool is_supported = false;
template <typename V>
static constexpr bool Do(T, U, V*) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<bool>();
}
};
template <typename T, typename U>
struct ClampedAddFastOp {
static const bool is_supported = false;
template <typename V>
static constexpr V Do(T, U) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<V>();
}
};
template <typename T, typename U>
struct ClampedSubFastOp {
static const bool is_supported = false;
template <typename V>
static constexpr V Do(T, U) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<V>();
}
};
template <typename T, typename U>
struct ClampedMulFastOp {
static const bool is_supported = false;
template <typename V>
static constexpr V Do(T, U) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<V>();
}
};
template <typename T>
struct ClampedNegFastOp {
static const bool is_supported = false;
static constexpr T Do(T) {
// Force a compile failure if instantiated.
return CheckOnFailure::template HandleFailure<T>();
}
};
#endif // BASE_HAS_OPTIMIZED_SAFE_MATH
#undef BASE_HAS_OPTIMIZED_SAFE_MATH
// This is used for UnsignedAbs, where we need to support floating-point
// template instantiations even though we don't actually support the operations.
// However, there is no corresponding implementation of e.g. SafeUnsignedAbs,
// so the float versions will not compile.
template <typename Numeric,
bool IsInteger = std::is_integral<Numeric>::value,
bool IsFloat = std::is_floating_point<Numeric>::value>
struct UnsignedOrFloatForSize;
template <typename Numeric>
struct UnsignedOrFloatForSize<Numeric, true, false> {
using type = typename std::make_unsigned<Numeric>::type;
};
template <typename Numeric>
struct UnsignedOrFloatForSize<Numeric, false, true> {
using type = Numeric;
};
// Wrap the unary operations to allow SFINAE when instantiating integrals versus
// floating points. These don't perform any overflow checking. Rather, they
// exhibit well-defined overflow semantics and rely on the caller to detect
// if an overflow occured.
template <typename T,
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
constexpr T NegateWrapper(T value) {
using UnsignedT = typename std::make_unsigned<T>::type;
// This will compile to a NEG on Intel, and is normal negation on ARM.
return static_cast<T>(UnsignedT(0) - static_cast<UnsignedT>(value));
}
template <
typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
constexpr T NegateWrapper(T value) {
return -value;
}
template <typename T,
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
constexpr typename std::make_unsigned<T>::type InvertWrapper(T value) {
return ~value;
}
template <typename T,
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
constexpr T AbsWrapper(T value) {
return static_cast<T>(SafeUnsignedAbs(value));
}
template <
typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
constexpr T AbsWrapper(T value) {
return value < 0 ? -value : value;
}
template <template <typename, typename, typename> class M,
typename L,
typename R>
struct MathWrapper {
using math = M<typename UnderlyingType<L>::type,
typename UnderlyingType<R>::type,
void>;
using type = typename math::result_type;
};
// These variadic templates work out the return types.
// TODO(jschuh): Rip all this out once we have C++14 non-trailing auto support.
template <template <typename, typename, typename> class M,
typename L,
typename R,
typename... Args>
struct ResultType;
template <template <typename, typename, typename> class M,
typename L,
typename R>
struct ResultType<M, L, R> {
using type = typename MathWrapper<M, L, R>::type;
};
template <template <typename, typename, typename> class M,
typename L,
typename R,
typename... Args>
struct ResultType {
using type =
typename ResultType<M, typename ResultType<M, L, R>::type, Args...>::type;
};
// The following macros are just boilerplate for the standard arithmetic
// operator overloads and variadic function templates. A macro isn't the nicest
// solution, but it beats rewriting these over and over again.
#define BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME) \
template <typename L, typename R, typename... Args> \
constexpr CLASS##Numeric< \
typename ResultType<CLASS##OP_NAME##Op, L, R, Args...>::type> \
CL_ABBR##OP_NAME(const L lhs, const R rhs, const Args... args) { \
return CL_ABBR##MathOp<CLASS##OP_NAME##Op, L, R, Args...>(lhs, rhs, \
args...); \
}
#define BASE_NUMERIC_ARITHMETIC_OPERATORS(CLASS, CL_ABBR, OP_NAME, OP, CMP_OP) \
/* Binary arithmetic operator for all CLASS##Numeric operations. */ \
template <typename L, typename R, \
typename std::enable_if<Is##CLASS##Op<L, R>::value>::type* = \
nullptr> \
constexpr CLASS##Numeric< \
typename MathWrapper<CLASS##OP_NAME##Op, L, R>::type> \
operator OP(const L lhs, const R rhs) { \
return decltype(lhs OP rhs)::template MathOp<CLASS##OP_NAME##Op>(lhs, \
rhs); \
} \
/* Assignment arithmetic operator implementation from CLASS##Numeric. */ \
template <typename L> \
template <typename R> \
constexpr CLASS##Numeric<L>& CLASS##Numeric<L>::operator CMP_OP( \
const R rhs) { \
return MathOp<CLASS##OP_NAME##Op>(rhs); \
} \
/* Variadic arithmetic functions that return CLASS##Numeric. */ \
BASE_NUMERIC_ARITHMETIC_VARIADIC(CLASS, CL_ABBR, OP_NAME)
} // namespace internal
} // namespace base
#endif // BASE_NUMERICS_SAFE_MATH_SHARED_IMPL_H_

View File

@@ -1,15 +0,0 @@
{
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
"Registrations": [
{
"component": {
"type": "git",
"git": {
"repositoryUrl": "https://github.com/chromium/chromium",
"commitHash": "d8710dd959da8e3be56f20af8cc94fbf560fbb6b"
}
}
}
],
"Version": 1
}

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) 2024 Microsoft Corporation -->
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
<policyNamespaces>
<target prefix="terminal" namespace="Microsoft.Policies.WindowsTerminal" />
<using prefix="windows" namespace="Microsoft.Policies.Windows" />
</policyNamespaces>
<resources minRequiredRevision="1.0" />
<supportedOn>
<definitions>
<definition name="SUPPORTED_WindowsTerminal_1_21" displayName="$(string.SUPPORTED_WindowsTerminal_1_21)" />
</definitions>
</supportedOn>
<categories>
<category name="WindowsTerminal" displayName="$(string.WindowsTerminal)">
<parentCategory ref="windows:WindowsComponents" />
</category>
</categories>
<policies>
<policy name="DisabledProfileSources" class="Both" displayName="$(string.DisabledProfileSources)" explainText="$(string.DisabledProfileSourcesText)" presentation="$(presentation.DisabledProfileSources)" key="Software\Policies\Microsoft\Windows Terminal">
<parentCategory ref="WindowsTerminal" />
<supportedOn ref="SUPPORTED_WindowsTerminal_1_21" />
<elements>
<multiText id="DisabledProfileSources" valueName="DisabledProfileSources" required="true" />
</elements>
</policy>
</policies>
</policyDefinitions>

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) 2024 Microsoft Corporation -->
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
<displayName>Windows Terminal</displayName>
<description>Windows Terminal</description>
<resources>
<stringTable>
<string id="WindowsTerminal">Windows Terminal</string>
<string id="SUPPORTED_WindowsTerminal_1_21">At least Windows Terminal 1.21</string>
<string id="DisabledProfileSources">Disabled Profile Sources</string>
<string id="DisabledProfileSourcesText">Profiles will not be generated from any sources listed here. Source names can be arbitrary strings. Potential candidates can be found as the "source" property on profile definitions in Windows Terminal's settings.json file.
Common sources are:
- Windows.Terminal.Azure
- Windows.Terminal.PowershellCore
- Windows.Terminal.Wsl
For instance, setting this policy to Windows.Terminal.Wsl will disable the builtin WSL integration of Windows Terminal.
Note: Existing profiles will disappear from Windows Terminal after adding their source to this policy.</string>
</stringTable>
<presentationTable>
<presentation id="DisabledProfileSources">
<multiTextBox refId="DisabledProfileSources">List of disabled sources (one per line)</multiTextBox>
</presentation>
</presentationTable>
</resources>
</policyDefinitionResources>

View File

@@ -135,5 +135,17 @@
</Target>
<!-- **END VC LIBS HACK** -->
<!-- This is required to get the package dependency in the AppXManifest. -->
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>

View File

@@ -20,9 +20,8 @@
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalMUX>true</TerminalMUX>
</PropertyGroup>
<Import Project="$(SolutionDir)\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
@@ -157,6 +156,14 @@
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<!--
By default, the PRI file will contain resource paths beginning with the
project name. Since we enabled XBF embedding, this *also* includes App.xbf.

View File

@@ -13,9 +13,8 @@
</PropertyGroup>
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalMUX>true</TerminalMUX>
</PropertyGroup>
<Import Project="$(SolutionDir)\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<!-- ========================= XAML files ======================== -->
@@ -91,6 +90,14 @@
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.8.4" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" targetFramework="native" />
</packages>

View File

@@ -17,9 +17,10 @@
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalMUX>true</TerminalMUX>
<TerminalThemeHelpers>true</TerminalThemeHelpers>
</PropertyGroup>
<Import Project="$(SolutionDir)\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
@@ -141,6 +142,14 @@
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.3\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<!-- Override GetPackagingOutputs to roll up all our dependencies.
This ensures that when the WAP packaging project asks what files go into
the package, we tell it.
@@ -216,3 +225,4 @@
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
</Project>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.8.4" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" targetFramework="native" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
</packages>

View File

@@ -7,27 +7,11 @@
#include "Row.hpp"
#include "textBuffer.hpp"
static std::atomic<uint64_t> s_revision{ 0 };
ImageSlice::ImageSlice(const til::size cellSize) noexcept :
_cellSize{ cellSize }
{
}
void ImageSlice::BumpRevision() noexcept
{
// Avoid setting the revision to 0. This allows the renderer to use 0 as a sentinel value.
do
{
_revision = s_revision.fetch_add(1, std::memory_order_relaxed);
} while (_revision == 0);
}
uint64_t ImageSlice::Revision() const noexcept
{
return _revision;
}
til::size ImageSlice::CellSize() const noexcept
{
return _cellSize;
@@ -65,6 +49,7 @@ RGBQUAD* ImageSlice::MutablePixels(const til::CoordType columnBegin, const til::
_columnBegin = existingData ? std::min(_columnBegin, columnBegin) : columnBegin;
_columnEnd = existingData ? std::max(_columnEnd, columnEnd) : columnEnd;
_pixelWidth = (_columnEnd - _columnBegin) * _cellSize.width;
_pixelWidth = (_pixelWidth + 3) & ~3; // Renderer needs this as a multiple of 4
const auto bufferSize = _pixelWidth * _cellSize.height;
if (existingData)
{
@@ -123,8 +108,9 @@ void ImageSlice::CopyBlock(const TextBuffer& srcBuffer, const til::rect srcRect,
void ImageSlice::CopyRow(const ROW& srcRow, ROW& dstRow)
{
const auto srcSlice = srcRow.GetImageSlice();
dstRow.SetImageSlice(srcSlice ? std::make_unique<ImageSlice>(*srcSlice) : nullptr);
const auto& srcSlice = srcRow.GetImageSlice();
auto& dstSlice = dstRow.GetMutableImageSlice();
dstSlice = srcSlice ? std::make_unique<ImageSlice>(*srcSlice) : nullptr;
}
void ImageSlice::CopyCells(const ROW& srcRow, const til::CoordType srcColumn, ROW& dstRow, const til::CoordType dstColumnBegin, const til::CoordType dstColumnEnd)
@@ -133,25 +119,24 @@ void ImageSlice::CopyCells(const ROW& srcRow, const til::CoordType srcColumn, RO
// a blank image into the destination, which is the same thing as an erase.
// Also if the line renditions are different, there's no meaningful way to
// copy the image content, so we also just treat that as an erase.
const auto srcSlice = srcRow.GetImageSlice();
const auto& srcSlice = srcRow.GetImageSlice();
if (!srcSlice || srcRow.GetLineRendition() != dstRow.GetLineRendition()) [[likely]]
{
ImageSlice::EraseCells(dstRow, dstColumnBegin, dstColumnEnd);
}
else
{
auto dstSlice = dstRow.GetMutableImageSlice();
auto& dstSlice = dstRow.GetMutableImageSlice();
if (!dstSlice)
{
dstSlice = dstRow.SetImageSlice(std::make_unique<ImageSlice>(srcSlice->CellSize()));
__assume(dstSlice != nullptr);
dstSlice = std::make_unique<ImageSlice>(srcSlice->CellSize());
}
const auto scale = srcRow.GetLineRendition() != LineRendition::SingleWidth ? 1 : 0;
if (dstSlice->_copyCells(*srcSlice, srcColumn << scale, dstColumnBegin << scale, dstColumnEnd << scale))
{
// If _copyCells returns true, that means the destination was
// completely erased, so we can delete this slice.
dstRow.SetImageSlice(nullptr);
dstSlice = nullptr;
}
}
}
@@ -218,7 +203,7 @@ void ImageSlice::EraseCells(TextBuffer& buffer, const til::point at, const size_
void ImageSlice::EraseCells(ROW& row, const til::CoordType columnBegin, const til::CoordType columnEnd)
{
const auto imageSlice = row.GetMutableImageSlice();
auto& imageSlice = row.GetMutableImageSlice();
if (imageSlice) [[unlikely]]
{
const auto scale = row.GetLineRendition() != LineRendition::SingleWidth ? 1 : 0;
@@ -226,7 +211,7 @@ void ImageSlice::EraseCells(ROW& row, const til::CoordType columnBegin, const ti
{
// If _eraseCells returns true, that means the image was
// completely erased, so we can delete this slice.
row.SetImageSlice(nullptr);
imageSlice = nullptr;
}
}
}

View File

@@ -26,9 +26,6 @@ public:
ImageSlice(const ImageSlice& rhs) = default;
ImageSlice(const til::size cellSize) noexcept;
void BumpRevision() noexcept;
uint64_t Revision() const noexcept;
til::size CellSize() const noexcept;
til::CoordType ColumnOffset() const noexcept;
til::CoordType PixelWidth() const noexcept;
@@ -48,7 +45,6 @@ private:
bool _copyCells(const ImageSlice& srcSlice, const til::CoordType srcColumn, const til::CoordType dstColumnBegin, const til::CoordType dstColumnEnd);
bool _eraseCells(const til::CoordType columnBegin, const til::CoordType columnEnd);
uint64_t _revision = 0;
til::size _cellSize;
std::vector<RGBQUAD> _pixelBuffer;
til::CoordType _columnBegin = 0;

View File

@@ -9,10 +9,6 @@
#include "../../types/inc/convert.hpp"
#include "../../inc/conattrs.hpp"
// BODGY: Misdiagnosis in MSVC 17.11: Referencing global constants in the member
// initializer list leads to this warning. Can probably be removed in the future.
#pragma warning(disable : 26493) // Don't use C-style casts (type.4).)
static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLOR };
OutputCell::OutputCell() noexcept :

View File

@@ -11,10 +11,6 @@
#include "../../types/inc/GlyphWidth.hpp"
#include "../../inc/conattrs.hpp"
// BODGY: Misdiagnosis in MSVC 17.11: Referencing global constants in the member
// initializer list leads to this warning. Can probably be removed in the future.
#pragma warning(disable : 26493) // Don't use C-style casts (type.4).)
static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLOR, INVALID_COLOR };
// Routine Description:
@@ -278,7 +274,7 @@ OutputCellIterator& OutputCellIterator::operator++()
}
case Mode::CharInfo:
{
// Walk forward by one because char infos are just the legacy version of cells and prealigned to columns
// Walk forward by one because charinfos are just the legacy version of cells and prealigned to columns
_pos++;
if (operator bool())
{

View File

@@ -5,10 +5,6 @@
#include "OutputCellView.hpp"
// BODGY: Misdiagnosis in MSVC 17.11: Referencing global constants in the member
// initializer list leads to this warning. Can probably be removed in the future.
#pragma warning(disable : 26493) // Don't use C-style casts (type.4).)
// Routine Description:
// - Constructs a read-only view of data formatted as a single output buffer cell
// Arguments:

Some files were not shown because too many files have changed in this diff Show More