Compare commits

...

920 Commits

Author SHA1 Message Date
Kovid Goyal
c9701a9b05 Update changelog 2024-03-25 16:04:23 +05:30
Kovid Goyal
cc76732058 ... 2024-03-25 14:01:45 +05:30
Kovid Goyal
3adf05244d Allow using --debug-rendering with panel kitten 2024-03-25 13:56:35 +05:30
Kovid Goyal
0dd2c3ea27 Edge panels now work
Tested under sway
2024-03-25 13:52:20 +05:30
Kovid Goyal
d56fbb88e5 More work on getting layer to actually render 2024-03-25 12:46:31 +05:30
Kovid Goyal
46db1f7b76 Get the layer sizing function working 2024-03-25 12:15:38 +05:30
Kovid Goyal
85a980ea3e Slightly nicer initial scale guess on wayland 2024-03-25 12:02:33 +05:30
Kovid Goyal
e9689ea50d Fix wayland backend windowfocused() implementation 2024-03-25 10:33:27 +05:30
Kovid Goyal
3fa5125f24 Ensure layer shell hint is set just before actual layer shell window creation 2024-03-25 09:42:56 +05:30
Kovid Goyal
4f049302c8 swapped scales 2024-03-25 09:16:50 +05:30
Kovid Goyal
5f7e53bfde ... 2024-03-25 08:54:10 +05:30
Kovid Goyal
de1dee6c3b Debug setting of exclusive zone 2024-03-24 21:57:52 +05:30
Kovid Goyal
411ae71ca9 ... 2024-03-24 20:48:21 +05:30
Kovid Goyal
0b6943fb5a ... 2024-03-24 20:48:20 +05:30
Kovid Goyal
333ea519ed Infrastructure to go from panel CLI opts all the way to wayland layer shell implementation 2024-03-24 20:48:20 +05:30
Kovid Goyal
56978189e0 Infrastructure for passing layer shell config from python to glfw 2024-03-24 20:48:20 +05:30
Kovid Goyal
fe5ccc144b Finish glfw side support for layer shell 2024-03-24 20:48:20 +05:30
Kovid Goyal
0641ec2d89 GLFW API for configuring a window as a layer shell 2024-03-24 20:48:20 +05:30
Kovid Goyal
707e69a794 Start work on wayland layer shell support 2024-03-24 20:48:20 +05:30
Kovid Goyal
5b4ea0052c ... 2024-03-24 20:44:58 +05:30
Kovid Goyal
a0aba4da4a Fix handling of tab character when cursor is at end of line and wrapping is enabled
Fixes #7250
2024-03-23 08:43:06 +05:30
Kovid Goyal
af82938427 Dont bother applying zero style to fallback
Micro-optimization
2024-03-22 15:37:58 +05:30
Kovid Goyal
42994bac37 DRYer 2024-03-22 15:19:39 +05:30
Kovid Goyal
4878b7cfd3 Proper fix for Zapf Dingbats vs Apple
See #7249
2024-03-22 15:09:44 +05:30
Kovid Goyal
98d32e50e0 macOS: Reject styled fallback from CoreText if its family name is not the same as the original
On some systems, for the good Lord alone knows what reason, CoreText is
giving us Zapf Dingbats as a font for some symbols, which doesnt
actually work.

Fixes #7249 (I hope)
2024-03-22 14:38:08 +05:30
Kovid Goyal
12e9db4ccc DRYer 2024-03-22 14:19:21 +05:30
Kovid Goyal
ebb1063e33 ... 2024-03-22 14:10:30 +05:30
Kovid Goyal
716bcb6d12 ... 2024-03-22 14:08:03 +05:30
Kovid Goyal
2f151e773c ... 2024-03-22 13:52:17 +05:30
Kovid Goyal
1c9f9a74e8 Wayland KDE: Add support for background_blur under kwin using a kwin private Wayland protocol 2024-03-22 13:41:44 +05:30
Kovid Goyal
9df7460fe1 Add a note about how to use edit-in-kitty with sudo to edit root files 2024-03-22 11:56:44 +05:30
Kovid Goyal
55feef8663 Linter fixes 2024-03-22 11:16:02 +05:30
Kovid Goyal
22c59fe19f bump version of imaging 2024-03-22 11:06:52 +05:30
Kovid Goyal
3b74fcb88c switch to a maintained fork of imaging 2024-03-22 10:38:22 +05:30
Kovid Goyal
e818f01ff2 Ensure palette is large enough to avoid panics with invalid images that have pixels refering to colors not in the palette 2024-03-22 10:01:20 +05:30
Kovid Goyal
e11081ac09 Use exiffix rather than imaging to handle EXIF rotation
exiffix works for more formats than just JPEG
2024-03-22 09:35:39 +05:30
Kovid Goyal
0eae7ba21d Remove unused parameter 2024-03-22 09:25:13 +05:30
Kovid Goyal
0be9b888fa string changes 2024-03-22 08:15:10 +05:30
Kovid Goyal
adda3249f5 Lets see if sanitize works 2024-03-21 21:00:58 +05:30
Kovid Goyal
cc11ed5c2c Update changelog 2024-03-21 20:53:36 +05:30
Kovid Goyal
83468535dd Implement support for preferred buffer scale 2024-03-21 20:53:36 +05:30
Kovid Goyal
55115058d2 Scale pointer axis events by effective scale 2024-03-21 20:53:36 +05:30
Kovid Goyal
776bfa3d7e Basic fractional scale protocol works 2024-03-21 20:53:36 +05:30
Kovid Goyal
6979f1c5eb Add listener for fractional scale events 2024-03-21 20:53:36 +05:30
Kovid Goyal
5d0c25f5ea Register the viewporter 2024-03-21 20:53:36 +05:30
Kovid Goyal
eb42ad3a2b Rename scale to integer_scale
We will presumably have a fractional_scale soon
2024-03-21 20:53:36 +05:30
Kovid Goyal
2b6edbccbc Start work on fractional scale support for Wayland
Register the interface on startup
2024-03-21 20:53:36 +05:30
Kovid Goyal
7e12cc57c6 Fix #7245 2024-03-21 20:50:05 +05:30
Kovid Goyal
1f149861f9 Mouse reporting: Fix drag release event outside the window not being reported in legacy mouse reporting modes
Fixes #7244
2024-03-21 20:32:58 +05:30
Kovid Goyal
11882aef2d Fix #7243 2024-03-21 17:16:09 +05:30
Kovid Goyal
3c4db20d2d DRYer 2024-03-21 11:27:41 +05:30
Kovid Goyal
924b87a16a Convenience function to get terminfo data in kittens 2024-03-21 10:58:46 +05:30
Kovid Goyal
198b69e275 An option to set TERMINFO to the database directly instead of a path 2024-03-21 10:48:53 +05:30
Kovid Goyal
ad64472950 Make the terminfo database available in the compiled module 2024-03-21 10:16:50 +05:30
Kovid Goyal
d9f33b19bc ... 2024-03-21 09:46:02 +05:30
Kovid Goyal
a5fea33757 version 0.33.1 2024-03-21 08:34:07 +05:30
Kovid Goyal
8cc360e344 Make preferential usage of NERD font for manual fallback more efficient 2024-03-20 20:33:50 +05:30
Kovid Goyal
a285d09459 ... 2024-03-20 20:07:03 +05:30
Kovid Goyal
e646596c5b macOS: When CoreText fails to find a fallback font for a character in the first Private Use Unicode Area, preferentially use the NERD font, if available, for it
Fixes #6043
2024-03-20 20:01:17 +05:30
Kovid Goyal
f3d9ad3244 ... 2024-03-20 18:59:52 +05:30
Kovid Goyal
752fcb6424 macOS: Fix text rendered with fallback fonts not respecting bold/italic styling 2024-03-20 18:23:09 +05:30
Kovid Goyal
0042288e92 remove unused headers 2024-03-20 17:28:14 +05:30
Kovid Goyal
7ea0af6f6d Fix debug-font-fallback to report re-used faces correctly 2024-03-20 17:26:18 +05:30
Kovid Goyal
69c0eaaf74 Dont request sRGB surfaces on Wayland
Apparently mesa just completely broke it. Besides it being already
broken on NVIDIA. Sigh, more of my life wasted on Wayland.

See https://github.com/kovidgoyal/kitty/issues/7174#issuecomment-2000033873
2024-03-19 08:57:48 +05:30
Kovid Goyal
a0424bf1bd Dont omit frame pointer in debug and profile builds 2024-03-18 10:56:50 +05:30
Kovid Goyal
481eccfe3c Merge branch 'dependabot/go_modules/all-go-deps-75b28919f3' of https://github.com/kovidgoyal/kitty 2024-03-18 09:28:52 +05:30
dependabot[bot]
c5c3f98595 Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma).


Updates `github.com/alecthomas/chroma/v2` from 2.12.0 to 2.13.0
- [Release notes](https://github.com/alecthomas/chroma/releases)
- [Changelog](https://github.com/alecthomas/chroma/blob/master/.goreleaser.yml)
- [Commits](https://github.com/alecthomas/chroma/compare/v2.12.0...v2.13.0)

---
updated-dependencies:
- dependency-name: github.com/alecthomas/chroma/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-18 03:35:28 +00:00
Kovid Goyal
3c19b6f734 Merge branch 'docs/fine-tuning' of https://github.com/Uaitt/kitty 2024-03-17 09:05:18 +05:30
Lorenzo Zabot
2d8deb86bb docs: minor adjustements 2024-03-16 14:43:23 +01:00
Kovid Goyal
5e0185d3eb Ensure KITTY_NO_SIMD is defined for all files on arches without SIMD support 2024-03-15 12:19:47 +05:30
Kovid Goyal
aee84c32e5 Merge branch 'fix-typo' of https://github.com/KaranveerB/kitty 2024-03-15 11:53:19 +05:30
KaranveerB
19a9594143 Fix typo in mapping.rst 2024-03-14 23:01:27 -07:00
Kovid Goyal
32f0da2e77 Ensure no frame is created for assembly functions 2024-03-15 07:58:09 +05:30
Kovid Goyal
d329cb3fff Update FAQ 2024-03-14 21:40:16 +05:30
Kovid Goyal
3bb9e36fc8 ... 2024-03-14 21:00:57 +05:30
Kovid Goyal
76ae5f5b9b DRYer: Use the SIMD detection in setup.py to avoid calling __builtin_cpu_supports 2024-03-14 20:57:09 +05:30
Kovid Goyal
393169f79d Fix #7225 2024-03-14 20:55:05 +05:30
Kovid Goyal
f5570c38dd Turn off sanitizers in CI as they are segfaulting
Trying to debug this in CI is too much work. Hopefully whatever
update in the CI env that is causing these will eventually be fixed.
2024-03-14 18:37:19 +05:30
Kovid Goyal
0153c9bb85 Use -g3 for profiling rather than -g 2024-03-14 17:07:38 +05:30
Kovid Goyal
1712a317d5 ... 2024-03-14 16:38:19 +05:30
Kovid Goyal
10cff577d6 Also get a backtrace when generating go code segfaults on CI 2024-03-14 16:25:52 +05:30
Kovid Goyal
86c59016c6 Try outputting core dump when multiprocessing spawn segfaults 2024-03-14 16:19:33 +05:30
Kovid Goyal
7821ae39ab Also need gdb to get coredumps in CI 2024-03-14 16:09:51 +05:30
Kovid Goyal
039d144c84 Splits layout: Allow resizing until one of the halves in a split is minimally sized
Fixes #7220
2024-03-14 15:59:23 +05:30
Kovid Goyal
af0d570725 Install systemd-coredump on CI so we can see coredumps 2024-03-14 15:18:33 +05:30
Kovid Goyal
288fa0128b Fix test suite running under sanitizers 2024-03-14 15:01:55 +05:30
Kovid Goyal
77125798a4 Redirect to NULL instead of pipe since we dont use the output 2024-03-14 12:15:15 +05:30
Kovid Goyal
c26954c69e ... 2024-03-14 12:05:57 +05:30
Kovid Goyal
9667da307c Print detected compiler type in verbose mode 2024-03-14 12:04:33 +05:30
Kovid Goyal
baa3ec0a62 Explicitly detect compiler types gcc vs clang 2024-03-14 12:02:01 +05:30
Kovid Goyal
478fc766b6 ... 2024-03-14 11:53:44 +05:30
Kovid Goyal
6c49066cde Fix undefined function pointer usage found by clang sanitizer 2024-03-14 11:47:56 +05:30
Kovid Goyal
a839af04dc Fix #7219 2024-03-14 11:13:54 +05:30
Kovid Goyal
3950632517 Switch to detecting clang rather than gcc
gcc makes it impossible to detect that it is gcc via --version
so instead detect clang and assume gcc if not clang.

Fixes #7218
2024-03-14 10:48:27 +05:30
Kovid Goyal
297ac9c3fe ... 2024-03-14 08:54:39 +05:30
Kovid Goyal
60d4ed3a1c ... 2024-03-13 14:12:49 +05:30
Kovid Goyal
a1b40cc8f5 Handle exception raised by Cocoa runtime when trying to get user notification center from a non-bundled executable 2024-03-13 11:43:38 +05:30
Kovid Goyal
5a9cf82564 Fix requesting data from clipboard via OSC 52 getting it from primary selection instead
Fixes #7213
2024-03-13 09:43:28 +05:30
Kovid Goyal
04f8cb6d30 version 0.33.0 2024-03-12 20:49:31 +05:30
Kovid Goyal
5264f3b5aa Merge branch 'dependabot/go_modules/all-go-deps-8f3a99df9e' of https://github.com/kovidgoyal/kitty 2024-03-11 11:11:56 +05:30
dependabot[bot]
5105c2f3ea Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/sys` from 0.17.0 to 0.18.0
- [Commits](https://github.com/golang/sys/compare/v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 04:00:55 +00:00
Kovid Goyal
eb46107575 Merge branch 'master' of https://github.com/pbevin/kitty 2024-03-10 21:41:04 +05:30
Pete Bevin
d75b8c63ef Fix build instructions after ./dev.sh deps 2024-03-10 12:02:51 -04:00
Kovid Goyal
7d787e6c22 Implement box drawing for Fira Code spinner glyphs 2024-03-10 21:08:23 +05:30
Kovid Goyal
36c79f3d50 Implement box drawing for Fira Code progress bar glyphs in PUA 2024-03-10 19:51:07 +05:30
Kovid Goyal
88b7595929 Ignore startup_session when kitty is invoked with command line options specifying a command to run 2024-03-10 09:41:08 +05:30
Kovid Goyal
fccf8db099 GitHub returns errors on delete but actually deletes 2024-03-10 08:41:14 +05:30
Kovid Goyal
d33afd4e96 Move toggle_tab into Boss
actions arent supported on TabManager
2024-03-07 11:57:07 +05:30
Kovid Goyal
76a4840a0f toggle_tab to easily switch to and back from a tab
Fixes #7203
2024-03-07 11:38:28 +05:30
Kovid Goyal
65923b1aba Add some benchamrking 2024-03-07 11:09:24 +05:30
Kovid Goyal
47fea26b62 Add an IndexByte implementation useful for benchmarking against stdlib SIMD implementation 2024-03-07 09:36:40 +05:30
Kovid Goyal
9ea0dde469 Add a note that startup_session prevents processing of cli args 2024-03-07 08:55:44 +05:30
Kovid Goyal
6c31256aa1 Keyboard protocol: Do not deliver a fake key release events on OS window focus out for engaged modifiers
Fixes #7196
2024-03-07 08:29:10 +05:30
Kovid Goyal
210c417d96 ... 2024-03-06 10:41:39 +05:30
Kovid Goyal
c1af14c22a Fix @ send-key not working to send keys to self over TTY 2024-03-05 13:09:07 +05:30
Kovid Goyal
a3d8be5e2f icat: Nicer error when user specifies invalid screen geometry 2024-03-05 10:49:47 +05:30
Kovid Goyal
d08a44ea4c Add a note as to why errors are not reported for send-text 2024-03-05 08:37:56 +05:30
Kovid Goyal
63d974135b Clean up linter warnings 2024-03-05 08:27:13 +05:30
Kovid Goyal
7b34c0603f Fix --match not working for some remote control commands 2024-03-05 08:00:57 +05:30
Kovid Goyal
c3c99113c7 hints kitten: Use default editor rather than hardcoding vim to open file at specific line
Fixes #7186
2024-03-04 21:49:06 +05:30
Kovid Goyal
9352576d1e Merge branch 'nushell-shell-integration' of https://github.com/gutenye/kitty 2024-03-04 19:44:18 +05:30
Guten Ye
dc82a06e9e doc: add detailed step to enable shell integration for Nushell 2024-03-04 21:41:50 +08:00
Kovid Goyal
bb98b81f82 Note that kitty keyboard protocol is supported in yazi
Fixes #7189
2024-03-04 19:03:23 +05:30
Kovid Goyal
1687c74913 Note that nushell supports shell integration 2024-03-04 19:01:31 +05:30
Kovid Goyal
bfe4256bf2 Merge branch 'dependabot/go_modules/all-go-deps-9e5965924d' of https://github.com/kovidgoyal/kitty 2024-03-04 10:43:51 +05:30
dependabot[bot]
66c3e1c1ff Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil).


Updates `github.com/shirou/gopsutil/v3` from 3.24.1 to 3.24.2
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.24.1...v3.24.2)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 03:31:42 +00:00
Kovid Goyal
c6acfa2cd4 Add a note to clarify lock key handling in disambiguate mode 2024-03-03 09:12:54 +05:30
Kovid Goyal
8fa592d849 Parse and ignore SOS codes
Fixes #7184
2024-03-03 08:58:47 +05:30
Kovid Goyal
89108e856f Clarify exactly when modifiers bits are set in the keyboard protocol
Fixes #7183
2024-03-02 13:14:41 +05:30
Kovid Goyal
0a0420bfd0 kitten @ ls: Return the timestamp at which the window was created
Fixes #7178
2024-03-02 09:30:12 +05:30
Kovid Goyal
2cc08cc5fd Cleanup previous PR 2024-03-02 09:24:19 +05:30
Kovid Goyal
f3344e1da0 Merge branch 'escapes' of https://github.com/derekschrock/kitty 2024-03-02 09:24:01 +05:30
Derek Schrock
9eb82c600d Fix invalid escape sequence warning with reset_terminal long_text 2024-03-01 14:33:05 -05:00
Kovid Goyal
17fe6b3373 Simplify sanitize args 2024-03-01 11:08:51 +05:30
Kovid Goyal
c3869dc479 ... 2024-03-01 11:07:51 +05:30
Kovid Goyal
473bff1aae Cheetah speed
😸
2024-02-29 10:16:08 +05:30
Kovid Goyal
99ceb2476e Fix #7169 2024-02-29 09:56:41 +05:30
Kovid Goyal
05881db492 Remove unused code 2024-02-28 12:15:20 +05:30
Kovid Goyal
1086757dc0 More docs 2024-02-28 11:39:16 +05:30
Kovid Goyal
d4c302bea3 Cleanup clear to prompt implementation and allow moving cleared lies into scrollback 2024-02-28 11:27:41 +05:30
Kovid Goyal
b8774327b6 icat kitten: Add a command line argument to override terminal window size detection
Fixes #7165

I had five minutes, so why not.
2024-02-27 23:06:10 +05:30
Kovid Goyal
e9c4e73103 Merge branch 'dependabot/go_modules/all-go-deps-55e9d2be01' of https://github.com/kovidgoyal/kitty 2024-02-26 10:12:12 +05:30
dependabot[bot]
d19a2fb606 Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/dlclark/regexp2](https://github.com/dlclark/regexp2).


Updates `github.com/dlclark/regexp2` from 1.10.0 to 1.11.0
- [Commits](https://github.com/dlclark/regexp2/compare/v1.10.0...v1.11.0)

---
updated-dependencies:
- dependency-name: github.com/dlclark/regexp2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 04:00:28 +00:00
Kovid Goyal
99af9739b2 ... 2024-02-25 19:46:18 +05:30
Kovid Goyal
9ce366fa7b Fix #7154 2024-02-25 15:22:43 +05:30
Kovid Goyal
daeaf65d7e fix compiler warning 2024-02-25 11:17:26 +05:30
Kovid Goyal
c5a10d19a4 Update the changelog 2024-02-25 10:49:22 +05:30
Kovid Goyal
a5f3142514 hints kitten: The option to set the text color for hints now allows arbitrary colors
Fixes #7150
2024-02-25 10:02:38 +05:30
Kovid Goyal
cf49fcc4e9 Make --dump-bytes robust against parser code modifying contents of buffer during parsing 2024-02-25 09:57:45 +05:30
Kovid Goyal
06dd84d6da Ensure event loop ticks ASAP when there is pending input 2024-02-25 09:57:45 +05:30
Kovid Goyal
dd3d4f8451 ... 2024-02-25 09:57:44 +05:30
Kovid Goyal
c08523a1ad Fix --dump-bytes duplicating bytes because of input_delay 2024-02-25 09:57:44 +05:30
Kovid Goyal
559be309ea Document previous PR 2024-02-25 09:57:44 +05:30
Carlos Esparza
299c39a214 add new-tab-left and new-tab-right 2024-02-25 09:57:44 +05:30
Carlos Esparza
4575608a97 add new-tab-neighbor option to detach_window 2024-02-25 09:57:44 +05:30
Kovid Goyal
1a9a7a59ac Make XOR64 test also test alignment issues 2024-02-25 09:57:44 +05:30
Kovid Goyal
e7d6101bd4 DRYer 2024-02-25 09:57:44 +05:30
Kovid Goyal
76381f5cdd Another tdir rmtree failure during tear down ignored 2024-02-25 09:57:44 +05:30
Kovid Goyal
40a4429e58 Ignore failure to remove tempdir during test tear down 2024-02-25 09:57:44 +05:30
Kovid Goyal
bd1aed43ec Check for leftovers when tokenizing 2024-02-25 09:57:44 +05:30
Kovid Goyal
7727cd45cf Delay load replacements as well 2024-02-25 09:57:44 +05:30
Kovid Goyal
4ee5b94584 Improve typing info for lex_scanner 2024-02-25 09:57:44 +05:30
Kovid Goyal
1d5c7d662e log error when failing to parse URL 2024-02-25 09:57:44 +05:30
Kovid Goyal
f4f06222d4 ... 2024-02-25 09:57:44 +05:30
Kovid Goyal
4caf8a6b14 Restore support for alternate character sets
Needed by the execrable ncurses. Adds an extra branch in the hot path,
sigh. Thanks to branch prediction it doesnt have any measurable impact
on the benchmark, thankfully.
2024-02-25 09:57:44 +05:30
Kovid Goyal
c19488f3be Graphics protocol: Add a new delete mode for deleting images whose ids fall within a range
Useful for bulk deletion. See #7080
2024-02-25 09:57:44 +05:30
Kovid Goyal
ad3ab877f8 Use a fast SIMD implementation to XOR data going into the disk cache 2024-02-25 09:57:43 +05:30
Kovid Goyal
88f3c8c5ee Reduce max key size in disk cache
We used only 12 byte keys no need to have a max key size more than 16
2024-02-25 09:57:43 +05:30
Kovid Goyal
91013a4e05 Faster image cache key generation 2024-02-25 09:57:43 +05:30
Kovid Goyal
de92470f0d Improve performance of disk cache when there are thousands of small images
Fixes #7080
2024-02-25 09:57:43 +05:30
Kovid Goyal
1c62b0f1ec ... 2024-02-25 09:57:43 +05:30
Kovid Goyal
b52af64ffe Hide cursor during benchmark run 2024-02-25 09:57:43 +05:30
Kovid Goyal
1db7ac5f6b Use our new shift by n functions to improve function to zero last N bytes
Benchmark neutral but cleaner code using one less vector register and equal
number of operations.
2024-02-25 09:57:43 +05:30
Kovid Goyal
e77a970ca1 Also implement arbitrary byte shift for 128 bit registers 2024-02-25 09:57:43 +05:30
Kovid Goyal
ac984d05f2 Fix gcc detection 2024-02-25 09:57:43 +05:30
Kovid Goyal
f16c2a0d67 Move checking for compiler brand into Env 2024-02-25 09:57:43 +05:30
Kovid Goyal
29a574a4bc Prevent duplicate VZEROUPPER instructions 2024-02-25 09:57:43 +05:30
Kovid Goyal
a7c06b38e6 We dont actually need vzeroupper at start of function
GCC emits vzeroupper automatically when compiling with native
optimizations but we still need it otherwise
2024-02-25 09:57:43 +05:30
Kovid Goyal
16d36c46fe Update to using math/rand/v2 2024-02-25 09:57:43 +05:30
Kovid Goyal
720618bc37 Use go 1.22 for building
It supports PCALIGN on non ARM arches as well
2024-02-25 09:57:43 +05:30
Kovid Goyal
2f727e6561 ... 2024-02-25 09:57:43 +05:30
Kovid Goyal
b65a5f78fd Fix regression causing shells in darwin to not run in login mode 2024-02-25 09:57:43 +05:30
Kovid Goyal
0a1eb038a5 Implement functions for arbitrary byte shifts in vector registers 2024-02-25 09:57:42 +05:30
Kovid Goyal
e541c0534d ... 2024-02-25 09:57:42 +05:30
Kovid Goyal
eb1e3b33b4 Fix test failure on some systems
Broken ass compilers strike again
2024-02-25 09:57:42 +05:30
Kovid Goyal
41ec46d5bb ... 2024-02-25 09:57:42 +05:30
Kovid Goyal
b021e9b648 Do the default func test last so we can see what the failure is on more explicitly 2024-02-25 09:57:42 +05:30
Kovid Goyal
ede4d7fbca ... 2024-02-25 09:57:42 +05:30
Kovid Goyal
d0797a025b Add dedicated tests for find_either_of_two 2024-02-25 09:57:42 +05:30
Kovid Goyal
1acd223f45 ... 2024-02-25 09:57:42 +05:30
Kovid Goyal
8639a2ac40 Update perf figures based on latest code 2024-02-25 09:57:42 +05:30
Kovid Goyal
f48e4ffd5e Port aligned load based find algorithm to C 2024-02-25 09:57:42 +05:30
Kovid Goyal
c01b959723 Fix Go unaligned index implementation 2024-02-25 09:57:42 +05:30
Kovid Goyal
36773c09d3 Functions to get bytes to first match ignoring leading bytes 2024-02-25 09:57:42 +05:30
Kovid Goyal
687340003d ... 2024-02-25 09:57:42 +05:30
Kovid Goyal
7467307200 Add some alignment tests 2024-02-25 09:57:42 +05:30
Kovid Goyal
bbdb0b15f3 DRYer 2024-02-25 09:57:42 +05:30
Kovid Goyal
b5edd9ad57 Dont precalculate mask in loop body
No need since we dont shift. Avoids the extra mask instructions for the
not found case.
2024-02-25 09:57:42 +05:30
Kovid Goyal
a32e1aafa6 ... 2024-02-25 09:57:41 +05:30
Kovid Goyal
f9fd6ffd46 Use only aligned loads for index funcs
Also obviates the necessity for safe slice wrappers
2024-02-25 09:57:41 +05:30
Kovid Goyal
31a5fcf297 DRYer 2024-02-25 09:57:41 +05:30
Kovid Goyal
493fc900e9 Fix build on ARM 2024-02-25 09:57:41 +05:30
Kovid Goyal
3abdc54e4b ... 2024-02-25 09:57:41 +05:30
Kovid Goyal
618aeec709 Finally got gnome-terminal to run on my system
Apparently it needed some kind of GTK desktop portal or the other
🙄

Interesting that its numbers are basically the same as alacritty's. Lot
better than I remember, I guess the recent libvte performance work was
good.
2024-02-25 09:57:41 +05:30
Kovid Goyal
4585361161 Micro optimization 2024-02-25 09:57:41 +05:30
Kovid Goyal
f64739c29b Fix regression that broke handling of single byte control chars when cursor is on second cell of wide character 2024-02-25 09:57:41 +05:30
Kovid Goyal
f3830aa854 Avoid unnecessary if 2024-02-25 09:57:41 +05:30
Kovid Goyal
f1fe0bf40a Code to easily compare SIMD and scalar decode in a live instance
Also remove -mtune=intel as it fails with clang
2024-02-25 09:57:41 +05:30
Kovid Goyal
561712090d Fix cmplt implementation 2024-02-25 09:57:41 +05:30
Kovid Goyal
d5f34c401d Better vector registers to pre-calculate before the loop 2024-02-25 09:57:41 +05:30
Kovid Goyal
d9190ea675 DRYer 2024-02-25 09:57:41 +05:30
Kovid Goyal
57f4ea4d4a Add some tests for broadcast from constant intrinsic 2024-02-25 09:57:41 +05:30
Kovid Goyal
9b0ae8d403 Dont use VEX encoded instructions for 128 bit ISA 2024-02-25 09:57:41 +05:30
Kovid Goyal
aed0611fb8 Avoid double trailing RET 2024-02-25 09:57:40 +05:30
Kovid Goyal
920b8a2496 Use VZEROUPPER in avx functions
See https://www.intel.com/content/dam/develop/external/us/en/documents/11mc12-avoiding-2bavx-sse-2btransition-2bpenalties-2brh-2bfinal-809104.pdf
2024-02-25 09:57:40 +05:30
Kovid Goyal
5a5e31c38b Also zero upper at start of function 2024-02-25 09:57:40 +05:30
Kovid Goyal
db2e0e816d Fix mixing of register types in the same function 2024-02-25 09:57:40 +05:30
Kovid Goyal
a298781b85 DRYer 2024-02-25 09:57:40 +05:30
Kovid Goyal
d5cd9ef2ca ... 2024-02-25 09:57:40 +05:30
Kovid Goyal
55c909c656 Use -mtune=intel for SIMD files when building without native optimizations 2024-02-25 09:57:40 +05:30
Kovid Goyal
da31db3212 ... 2024-02-25 09:57:40 +05:30
Kovid Goyal
601c4ad4df Fix some typos 2024-02-25 09:57:40 +05:30
Kovid Goyal
2549b4328f Update throughput comparison table in light of latest improvements 2024-02-25 09:57:40 +05:30
Kovid Goyal
68d800d4fa make clean should clean generated asm as well 2024-02-25 09:57:40 +05:30
Kovid Goyal
9fc3db1dd1 Work on C0 index func 2024-02-25 09:57:40 +05:30
Kovid Goyal
d4c4805f96 const away to glory 2024-02-25 09:57:40 +05:30
Kovid Goyal
161eae78b6 Make generated asm_* files world readable 2024-02-25 09:57:40 +05:30
Kovid Goyal
6cdc7ac91d A further 5% speedup for UTF-8 decoding
Achieved by decoding in larger chunks thereby amortizing the cost
of creating various constant vectors over larger chunks.
2024-02-25 09:57:40 +05:30
Kovid Goyal
0bccada9d1 No longer need to abort after dealing with trailing bytes 2024-02-25 09:57:40 +05:30
Kovid Goyal
9cb9373274 Allow unbounded output in UTF8Decoder
This will allow us to eventually decode more than a single
vector's worth in a fast inner loop
2024-02-25 09:57:39 +05:30
Kovid Goyal
d987ffe49a Use unaligned stores
Makes no measurable difference in the benchmark. And will eventually
allow us to process larger chunks of data without need to reset a bunch
of vector registers to constant values each time.
2024-02-25 09:57:39 +05:30
Kovid Goyal
77cfd44f24 More efficient clearing of register to all zeros or all ones 2024-02-25 09:57:39 +05:30
Kovid Goyal
59be7213cf Make set1_epi8 more general 2024-02-25 09:57:39 +05:30
Kovid Goyal
d60dacbd09 Implement > and < intrinsics for vector registers 2024-02-25 09:57:39 +05:30
Kovid Goyal
82b7b4fcce Make a re-useable template for generating ASM index functions with different tests 2024-02-25 09:57:39 +05:30
Kovid Goyal
fa9a2b1e2e Switch file input to use new SIMD parser to search for \n and \r in parallel 2024-02-25 09:57:39 +05:30
Kovid Goyal
4e6138d785 Generate SIMD code during build 2024-02-25 09:57:39 +05:30
Kovid Goyal
86a55e2c0a Use an aligned slice for file reads 2024-02-25 09:57:39 +05:30
Kovid Goyal
de8c1e0206 Work on porting SIMD vt arser to Go for the kittens 2024-02-25 09:57:39 +05:30
Kovid Goyal
131716da00 Ignore another warning on some compiler versions in simde 2024-02-25 09:57:39 +05:30
Kovid Goyal
4d35fc2928 Use a custom movmask for ARM rather than the one from simde
Supposedly faster, not that I can measure it, but...
Also gives neater code, so keep it.
2024-02-25 09:57:39 +05:30
Kovid Goyal
3b65c1a58a remove declaration without implementation 2024-02-25 09:57:39 +05:30
Kovid Goyal
9bca415af2 Use aligned loads when finding either of two bytes
No measurable performance improvement, but neater algorithm anyway.
2024-02-25 09:57:39 +05:30
Kovid Goyal
60bc8e6c25 ... 2024-02-25 09:57:39 +05:30
Kovid Goyal
8aa1b112b8 Turns out the simde implementation of movemask is not slow enough to compensate for the speed bump from 256 bit 2024-02-25 09:57:39 +05:30
Kovid Goyal
0bd47d8457 Cleanup KITTY_NO_SIMD compilation 2024-02-25 09:57:39 +05:30
Kovid Goyal
fcbda63023 Move finding byte code into separate functions
movemask() is inefficient on ARM64 this will allow us to use a dedicated
implementation for finding bytes on that platform
2024-02-25 09:57:38 +05:30
Kovid Goyal
1d59bfade3 ... 2024-02-25 09:57:38 +05:30
Kovid Goyal
fd7d0f8787 Fix event loop continuously ticking every input_delay seconds even when no input is available 2024-02-25 09:57:38 +05:30
Kovid Goyal
fa11858a72 Make bash integration tests more robust on macOS 2024-02-25 09:57:38 +05:30
Kovid Goyal
1293ee60e0 ... 2024-02-25 09:57:38 +05:30
Kovid Goyal
66341aa28e Make the env var controlling which SIMD level to use more capable 2024-02-25 09:57:38 +05:30
Kovid Goyal
73342411bc Dont build any SIMD code when the target is neither ARM64 nor x86/amd64 2024-02-25 09:57:38 +05:30
Kovid Goyal
8dd6f9b07c Get universal builds working again
Now we use lipo and build individually so we can pass the correct
compiler flags per arch
2024-02-25 09:57:38 +05:30
Kovid Goyal
7e77a196e6 Build only the SIMD code with SIMD compiler flags 2024-02-25 09:57:38 +05:30
Kovid Goyal
465616223c Drop using the v2 microarch
No significant performance impact and small risk of breakage
2024-02-25 09:57:38 +05:30
Kovid Goyal
9d4193f4ea Fix texture ref not useable on repurposed image object 2024-02-25 09:57:38 +05:30
Kovid Goyal
dafb876d75 Skip simd parser tests on machines without SIMD instructions 2024-02-25 09:57:38 +05:30
Kovid Goyal
4b846e0106 Turns out that using 256 bit code on ARM is slightly faster even though it is emulated with 128 bit registers 2024-02-25 09:57:38 +05:30
Kovid Goyal
76c6630084 Dont use 256 bit code paths on ARM
ARM only has 128 bit registers. simde simulates 256 bit operations using
them, which is fairly pointless for us.
2024-02-25 09:57:38 +05:30
Kovid Goyal
23a4012aeb Add an env var to turn off use of SIMD instructions 2024-02-25 09:57:38 +05:30
Kovid Goyal
eee14ae148 Workaround for machines on GitHub Actions that incorrectly report CPU vector instruction availability 2024-02-25 09:57:37 +05:30
Kovid Goyal
b0ccaa09be Clean up test env reporting 2024-02-25 09:57:37 +05:30
Kovid Goyal
bbaccfdaae DRYer 2024-02-25 09:57:37 +05:30
Kovid Goyal
cb5a2cce53 ... 2024-02-25 09:57:37 +05:30
Kovid Goyal
4fec11af05 Run dsymutil in post link phase 2024-02-25 09:57:37 +05:30
Kovid Goyal
5a9304e1b8 DRYer 2024-02-25 09:57:37 +05:30
Kovid Goyal
2b9c646c5b Build dSYM bundles on CI 2024-02-25 09:57:37 +05:30
Kovid Goyal
6b6f3e0ece ... 2024-02-25 09:57:37 +05:30
Kovid Goyal
b560fe34c9 Give the functions for creating various objects unique names so they are easily recognized in macOS's non-fully-symolicated crash reports 2024-02-25 09:57:37 +05:30
Kovid Goyal
e5b27d066c Output macOS crash reports on CI with nicer formatting 2024-02-25 09:57:37 +05:30
Kovid Goyal
8762a939c0 Dont specify arch/tune when building universal binary 2024-02-25 09:57:37 +05:30
Kovid Goyal
06da31019c Micro-optimize clearing of lines
Use a doubling strategy to memset arrays to a fixed value. Makes the
memset O(log(N)) from O(N) in number of calls to memcpy.
2024-02-25 09:57:37 +05:30
Kovid Goyal
d0621cb82a Better ipd crash report printing 2024-02-25 09:57:37 +05:30
Kovid Goyal
9935b5ddb2 ... 2024-02-25 09:57:37 +05:30
Kovid Goyal
49d664bb0d Fix incorrect line mapping when clearing screen using optimized code 2024-02-25 09:57:37 +05:30
Kovid Goyal
c6c0d0ed60 Sleep for a minute in the hope that macOS crash log will become available 2024-02-25 09:57:37 +05:30
Kovid Goyal
6f74d1b0c1 ... 2024-02-25 09:57:36 +05:30
Kovid Goyal
5eb852532f Use coredumpctl on Linux CI 2024-02-25 09:57:36 +05:30
Kovid Goyal
43e0281ab5 No ulimit on Linux CI 2024-02-25 09:57:36 +05:30
Kovid Goyal
99d1eec021 ... 2024-02-25 09:57:36 +05:30
Kovid Goyal
0a158f3577 More attempts at finding a core dump on macOS 2024-02-25 09:57:36 +05:30
Kovid Goyal
89c431a624 Optimize implementation of clear screen escape code 2024-02-25 09:57:36 +05:30
Kovid Goyal
b48b70aedf Speed up CSI benchmark by another 10% 2024-02-25 09:57:36 +05:30
Kovid Goyal
f105bc5f4e ... 2024-02-25 09:57:36 +05:30
Kovid Goyal
d5fae07ab7 More help text for the benchmark kitten 2024-02-25 09:57:36 +05:30
Kovid Goyal
58dbcf0840 ... 2024-02-25 09:57:36 +05:30
Kovid Goyal
0340c3c8f7 Ensure CSI state reset at end of test 2024-02-25 09:57:36 +05:30
Kovid Goyal
d8a53fbafd Retry on temp errors when reading from terminal 2024-02-25 09:57:36 +05:30
Kovid Goyal
b237e1b99f ... 2024-02-25 09:57:36 +05:30
Kovid Goyal
43f64f71e4 DRYer 2024-02-25 09:57:36 +05:30
Kovid Goyal
ceac074dad Try to print the Apple crash report on test run failure 2024-02-25 09:57:36 +05:30
Kovid Goyal
903dd26a08 Sadly -march=x86-64-v2 is not the culprit for the intermittent SIGILL in macOS CI 2024-02-25 09:57:36 +05:30
Kovid Goyal
f0efb1cb19 Also clear screen at end of each loop when rendering 2024-02-25 09:57:35 +05:30
Kovid Goyal
4eb49b3320 Simplify benchmark kitten
On macOS reading from the same tty device file as we are writing too in
another thread gives continuous EAGAIN errors. We dont actually need
simultaneous read/write, so move the reads to the end.
2024-02-25 09:57:35 +05:30
Kovid Goyal
0fcb055246 tty: retry on temporary read errors 2024-02-25 09:57:35 +05:30
Kovid Goyal
61a89a14b6 Ignore temporary write failures in benchmark kitten 2024-02-25 09:57:35 +05:30
Kovid Goyal
4fbb70d89e Explain the purpose of the CSI column 2024-02-25 09:57:35 +05:30
Kovid Goyal
5c3e54dede Note that konsole and xterm dont support synchronized update 2024-02-25 09:57:35 +05:30
Kovid Goyal
5721b1315e ... 2024-02-25 09:57:35 +05:30
Kovid Goyal
85fcac2a61 Add throughput performance numbers 2024-02-25 09:57:35 +05:30
Kovid Goyal
8d01a42db1 Make the default number of repetitions for benchmark 100 2024-02-25 09:57:35 +05:30
Kovid Goyal
0e4c49a0d6 Fix building on macOS ARM 2024-02-25 09:57:35 +05:30
Kovid Goyal
a9111f9a40 Try disabling x86-64-v2 on macOS 2024-02-25 09:57:35 +05:30
Kovid Goyal
616fcfd201 More tests 2024-02-25 09:57:35 +05:30
Kovid Goyal
b3ca5d51fb Use the new SIMD utf-8 decoder 2024-02-25 09:57:35 +05:30
Kovid Goyal
e783eccc97 fix handling of bits from high byte of 4 byte sequences 2024-02-25 09:57:35 +05:30
Kovid Goyal
c98b9403ac Dynamically allocated parser state should be 64 byte aligned as well 2024-02-25 09:57:35 +05:30
Kovid Goyal
7e6459a5e4 DRYer 2024-02-25 09:57:35 +05:30
Kovid Goyal
67d22b0ec6 Avoid multiple branches for checking for trailing sequence 2024-02-25 09:57:34 +05:30
Kovid Goyal
79f99bb3ad Make print_register useable without full debug 2024-02-25 09:57:34 +05:30
Kovid Goyal
fa3579656b More invalid utf-8 tests 2024-02-25 09:57:34 +05:30
Kovid Goyal
8a10fcaf5a More tests 2024-02-25 09:57:34 +05:30
Kovid Goyal
4c8b8caead Handle trailing incomplete sequences 2024-02-25 09:57:34 +05:30
Kovid Goyal
4238fedee7 More tests 2024-02-25 09:57:34 +05:30
Kovid Goyal
b0dcdf74bd More tests and micro-optimize switch to ASCII fast path 2024-02-25 09:57:34 +05:30
Kovid Goyal
a63d62fb4e ... 2024-02-25 09:57:34 +05:30
Kovid Goyal
8dbb0cff6f Dont call __builtin_ctz with zero 2024-02-25 09:57:34 +05:30
Kovid Goyal
07bba337f5 fix various bugs in AVX2 utility functions 2024-02-25 09:57:34 +05:30
Kovid Goyal
b28fbf6817 fix zero-ing of last n bytes 2024-02-25 09:57:34 +05:30
Kovid Goyal
daa169b8ed More work on utf8 SIMD decode 2024-02-25 09:57:34 +05:30
Kovid Goyal
a5251bedc9 More work on SIMD utf8 decode 2024-02-25 09:57:34 +05:30
Kovid Goyal
e9820eb207 zero out bytes beyond src_sz after loading src into the register 2024-02-25 09:57:34 +05:30
Kovid Goyal
645b2811e2 more work on the SIMD utf8 decode 2024-02-25 09:57:34 +05:30
Kovid Goyal
9804021de4 More work on SIMD utf8 decode 2024-02-25 09:57:34 +05:30
Kovid Goyal
ea5858e10b avoid repeated construction of one, two, tree values vectors 2024-02-25 09:57:33 +05:30
Kovid Goyal
4589a62738 ... 2024-02-25 09:57:33 +05:30
Kovid Goyal
1275c9275b Output the third and final utf8 decoded byte 2024-02-25 09:57:33 +05:30
Kovid Goyal
d95f7ac159 Fix compilation on clang 2024-02-25 09:57:33 +05:30
Kovid Goyal
8e2d448c5c More work on UTF-8 SIMD decode 2024-02-25 09:57:33 +05:30
Kovid Goyal
37c05e3212 ... 2024-02-25 09:57:33 +05:30
Kovid Goyal
99e67f0859 ... 2024-02-25 09:57:33 +05:30
Kovid Goyal
2cb87861c0 Ensure cpu is inited before calling cpu_supports() 2024-02-25 09:57:33 +05:30
Kovid Goyal
c1793d8781 Pause rendering per repetition
Needed when number of repetitions is large enough to cause
paused rendering to be aborted
2024-02-25 09:57:33 +05:30
Kovid Goyal
fce896c480 Do not render when benchmarking parser to better isolate parser performance 2024-02-25 09:57:33 +05:30
Kovid Goyal
f45cd87488 Implement paused rendering for graphics 2024-02-25 09:57:33 +05:30
Kovid Goyal
7b963a2372 Allow texture references to outlive parent images
This is needed for paused rendering of images. Use a simple ref counting
scheme.
2024-02-25 09:57:33 +05:30
Kovid Goyal
d863cbd7c0 Ensure selection data is updated on GPU after paused rendering 2024-02-25 09:57:33 +05:30
Kovid Goyal
e50447c840 Fix cursor rendering during rendering pause 2024-02-25 09:57:33 +05:30
Kovid Goyal
ab919f6fa1 fix copy onto incorrect buffer 2024-02-25 09:57:33 +05:30
Kovid Goyal
f596351bc1 Pause selection rendering 2024-02-25 09:57:33 +05:30
Kovid Goyal
7c5e011fe6 No need to pass Screen to iteration_data() 2024-02-25 09:57:32 +05:30
Kovid Goyal
b444b2ee36 Implement paused rendering for cell data 2024-02-25 09:57:32 +05:30
Kovid Goyal
aeb60edf55 Freeze inverted status during paused rendering 2024-02-25 09:57:32 +05:30
Kovid Goyal
6c2ef90033 Add some const for functions taking ColorProfile 2024-02-25 09:57:32 +05:30
Kovid Goyal
182b0aac98 Freeze the color profile during paused rendering 2024-02-25 09:57:32 +05:30
Kovid Goyal
d9d6bd7ffb ... 2024-02-25 09:57:32 +05:30
Kovid Goyal
21bba05805 Turn off paused rendering on reset, resize and scrollback scroll 2024-02-25 09:57:32 +05:30
Kovid Goyal
b146e9c457 Add basic parser tests for pending mode activation/de-activation 2024-02-25 09:57:32 +05:30
Kovid Goyal
1f835b27c4 start work on implementing pending mode as paused rendering 2024-02-25 09:57:32 +05:30
Kovid Goyal
89debca4af Ensure leftover bytes are a copy 2024-02-25 09:57:32 +05:30
Kovid Goyal
a33b747de5 Fix find_in_memoryview() 2024-02-25 09:57:32 +05:30
Kovid Goyal
532cc44e66 Ensure screen is always set when calling parse_sgr 2024-02-25 09:57:32 +05:30
Kovid Goyal
391a43d967 Store last cursor render pos in the rendered info struct 2024-02-25 09:57:32 +05:30
Kovid Goyal
be37a283d5 Move unfocused ender bool into cursor render info 2024-02-25 09:57:32 +05:30
Kovid Goyal
7e424e1848 Refactor ascii decode into its own function 2024-02-25 09:57:32 +05:30
Kovid Goyal
96bcb1d33b Fix handling on new_input_at 2024-02-25 09:57:32 +05:30
Kovid Goyal
7f60c649f4 ... 2024-02-25 09:57:31 +05:30
Kovid Goyal
e52bcb5b93 more workon simd utf-8 decode 2024-02-25 09:57:31 +05:30
Kovid Goyal
d93283c547 annotate utf-8 encoder 2024-02-25 09:57:31 +05:30
Kovid Goyal
aef0b9f50f ... 2024-02-25 09:57:31 +05:30
Kovid Goyal
74391d7c50 More work on SIMD utf-8 decode 2024-02-25 09:57:31 +05:30
Kovid Goyal
8975d1a9f4 no need to parametrize sentinel 2024-02-25 09:57:31 +05:30
Kovid Goyal
48bf8c6105 Report out of single byte control code embedded in CSI 2024-02-25 09:57:31 +05:30
Kovid Goyal
0ed1c6f840 Simplify utf8 parser func
Also show a replacement char for incomplete utf-8 sequences interrupted by an esc char
2024-02-25 09:57:31 +05:30
Kovid Goyal
72e73f2f81 Fix alignment of output array in UTF8Decoder 2024-02-25 09:57:31 +05:30
Kovid Goyal
95eac2e510 ... 2024-02-25 09:57:31 +05:30
Kovid Goyal
bc499000a5 Infrastructure for developing and testing UTF-8 SIMD decode 2024-02-25 09:57:31 +05:30
Kovid Goyal
e2be8c2d37 Use unaligned loads for SIMD
makes no difference to the benchmarks and simplifies the code
2024-02-25 09:57:31 +05:30
Kovid Goyal
fd4c8e1e2d Get rid of ByteLoader
Doesnt move the benchmarks
2024-02-25 09:57:31 +05:30
Kovid Goyal
ba18c5a669 Move ByteLoader back to simd-string.c in preparation for getting rid of it 2024-02-25 09:57:31 +05:30
Kovid Goyal
293ad34535 Get rid of utoi() 2024-02-25 09:57:31 +05:30
Kovid Goyal
45e10394a0 Get rid of ByteLoader from csi_parse_loop
It benchmark's 4% slower on my machine
2024-02-25 09:57:31 +05:30
Kovid Goyal
0531b4bc79 Move too long CSI check out of parse loop 2024-02-25 09:57:30 +05:30
Kovid Goyal
0f6d11351b Fix benchmark rate calculation 2024-02-25 09:57:30 +05:30
Kovid Goyal
1b11c3e923 Double timeouts on flaky test 2024-02-25 09:57:30 +05:30
Kovid Goyal
c79baa56e4 Remove unused SIMD code 2024-02-25 09:57:30 +05:30
Kovid Goyal
c6f4c93d0a Nicer exit code diagnostic 2024-02-25 09:57:30 +05:30
Kovid Goyal
8742fb8cce Detect availability of intrinsics on intel macs just in case 2024-02-25 09:57:30 +05:30
Kovid Goyal
0bd67620c6 ... 2024-02-25 09:57:30 +05:30
Kovid Goyal
0f60ac2dd7 sprintf -> snprintf 2024-02-25 09:57:30 +05:30
Kovid Goyal
0cd761808a draw_codepoint is never called with from_inputstream=true 2024-02-25 09:57:30 +05:30
Kovid Goyal
43fb09dc39 Speed up Screen.draw 2024-02-25 09:57:30 +05:30
Kovid Goyal
c2d81d67c2 Nicer macros to ignore diagnostics 2024-02-25 09:57:30 +05:30
Kovid Goyal
272e944a13 DRYer 2024-02-25 09:57:30 +05:30
Kovid Goyal
a9f5519d11 Add tests for writing with cursor on trailer of wide char 2024-02-25 09:57:30 +05:30
Kovid Goyal
a055aaf035 ... 2024-02-25 09:57:30 +05:30
Kovid Goyal
718f4b328f Go back to a single code path for drawing text
Slightly reduces pure ASCII performance and improves Unicode
performance. We should be able to get pure ASCII performance back
via SIMD eventually.
2024-02-25 09:57:30 +05:30
Kovid Goyal
b41cf52ce4 ensure no control chars are drawn 2024-02-25 09:57:29 +05:30
Kovid Goyal
e08e15a676 Ensure parser buffer is aligned to 64 bytes 2024-02-25 09:57:29 +05:30
Kovid Goyal
c5f0b03a62 Remove not needed function 2024-02-25 09:57:29 +05:30
Kovid Goyal
794bd85371 Ignore warning from simde on clang 2024-02-25 09:57:29 +05:30
Kovid Goyal
73d657a21a Dont use intel intrinsics switches on ARM 2024-02-25 09:57:29 +05:30
Kovid Goyal
103f5f3956 Move ringbuf into 3rdparty 2024-02-25 09:57:29 +05:30
Kovid Goyal
ef7d92a117 Update uthash from upstream 2024-02-25 09:57:29 +05:30
Kovid Goyal
33102d8c4e Move uthash into 3rdparty 2024-02-25 09:57:29 +05:30
Kovid Goyal
56dcbca238 Move base64simd into a 3rdparty folder 2024-02-25 09:57:29 +05:30
Kovid Goyal
cc6dc96c90 Allow setting benchmark options 2024-02-25 09:57:29 +05:30
Kovid Goyal
2dffad1d8e Use byteloader for printable char ranges 2024-02-25 09:57:29 +05:30
Kovid Goyal
93430cd5f4 Images benchmark should not measure speed of zlib 2024-02-25 09:57:29 +05:30
Kovid Goyal
3d0a90e63d Switch to SIMD based base64 2024-02-25 09:57:29 +05:30
Kovid Goyal
9eb91984dd Cleanup benchmark warmup code 2024-02-25 09:57:29 +05:30
Kovid Goyal
071c8200a6 ... 2024-02-25 09:57:29 +05:30
Kovid Goyal
ad7175a24d ... 2024-02-25 09:57:29 +05:30
Kovid Goyal
24232ba277 Ensure goroutine has started before sending data 2024-02-25 09:57:28 +05:30
Kovid Goyal
0f6e5fe57e Fix benchmark rate calculation 2024-02-25 09:57:28 +05:30
Kovid Goyal
ef8e8313ab For some reason, memcpy is faster than assignment 2024-02-25 09:57:28 +05:30
Kovid Goyal
17cb65e981 Adjust amount of data in the benchmarks for more consistent timing 2024-02-25 09:57:28 +05:30
Kovid Goyal
f2153f060d add unicode benchmark 2024-02-25 09:57:28 +05:30
Kovid Goyal
48c0b30671 Install simde on CI 2024-02-25 09:57:28 +05:30
Kovid Goyal
e8f67281cf Warmup font rendering before running benchmark 2024-02-25 09:57:28 +05:30
Kovid Goyal
49a54b086f Use simde so SIMD speedups work on ARM as well 2024-02-25 09:57:28 +05:30
Kovid Goyal
4790959938 Use -fno-plt
We dont need the PLT and it frees up some registers
2024-02-25 09:57:28 +05:30
Kovid Goyal
33249c872f Use a better default march for binary builds
x86-64-v2 implies SSE4.2 which should be available everywhere by now. We
will see if we get errors with it.

https://developers.redhat.com/blog/2021/01/05/building-red-hat-enterprise-linux-9-for-the-x86-64-v2-microarchitecture-level#architectural_considerations_for_rhel_9
2024-02-25 09:57:28 +05:30
Kovid Goyal
71bf099041 Speed up drawing of printable ascii chars 2024-02-25 09:57:28 +05:30
Kovid Goyal
307acb3f64 Add API to Screen to draw a set of printable ascii chars fast 2024-02-25 09:57:28 +05:30
Kovid Goyal
e5675e9537 Simplify API 2024-02-25 09:57:28 +05:30
Kovid Goyal
9cf425006f ... 2024-02-25 09:57:28 +05:30
Kovid Goyal
c052831291 Dont double parse CSI digits 2024-02-25 09:57:28 +05:30
Kovid Goyal
fe2cd543ba Switch to same algorithm for 128bit SIMD as used for 256 bit SIMD
Avoids needing to write to the haystack and also less chance of a bug in
the never tested simd since all CPUs I have access to have AVX2
2024-02-25 09:57:28 +05:30
Kovid Goyal
1925d5ea65 Prepare for plain sse4 fallback 2024-02-25 09:57:27 +05:30
Kovid Goyal
aacdffd539 DRYer 2024-02-25 09:57:27 +05:30
Kovid Goyal
a0e1eb4985 AVX2 implementation for find either of two 2024-02-25 09:57:27 +05:30
Kovid Goyal
e4c48a5f17 Add AVX2 implementation of find byte not in range
Also fix alignment bug and ensure the simd finders dont return a pointer
beyond the end
2024-02-25 09:57:27 +05:30
Kovid Goyal
021dd168e5 ... 2024-02-25 09:57:27 +05:30
Kovid Goyal
b032313c45 Only use SIMD if CPU supports it at runtime 2024-02-25 09:57:27 +05:30
Kovid Goyal
19a41b4d9a Use sse4.2 instruction for normal mode printable ascii detection 2024-02-25 09:57:27 +05:30
Kovid Goyal
25e7a2882d Work on using SIMD for normal mode dispatch 2024-02-25 09:57:27 +05:30
Kovid Goyal
a75fb6509e ... 2024-02-25 09:57:27 +05:30
Kovid Goyal
23c42cb555 ... 2024-02-25 09:57:27 +05:30
Kovid Goyal
1f8feea454 Parse new data that is writtne while parsing is in progress in the parse loop
Avoids unnecessary memmove()
2024-02-25 09:57:27 +05:30
Kovid Goyal
f0afdc51af ... 2024-02-25 09:57:27 +05:30
Kovid Goyal
ac6afcb0a8 Release the parser IO lock while parsing 2024-02-25 09:57:27 +05:30
Kovid Goyal
ad7f671a7b Add a long escape code benchmark 2024-02-25 09:57:27 +05:30
Kovid Goyal
4f67b8b433 Need -msse4.2 on non-native builds 2024-02-25 09:57:27 +05:30
Kovid Goyal
e3d6aa2c60 Use simd in a few loops 2024-02-25 09:57:27 +05:30
Kovid Goyal
89d416806b ... 2024-02-25 09:57:26 +05:30
Kovid Goyal
859b0cc585 Include -march=native for debug builds 2024-02-25 09:57:26 +05:30
Kovid Goyal
8b4209cb97 Also use fast find for pending mode 2024-02-25 09:57:26 +05:30
Kovid Goyal
8dca5a6b9a ... 2024-02-25 09:57:26 +05:30
Kovid Goyal
200e5bf6e3 Examine 8 bytes at once for terminator char 2024-02-25 09:57:26 +05:30
Kovid Goyal
f4819175b0 Start work on vectorizing searches 2024-02-25 09:57:26 +05:30
Kovid Goyal
5921ca1139 Add images benchmark 2024-02-25 09:57:26 +05:30
Kovid Goyal
dbc4b98742 Ignore input_delay when the input buffer is close to full 2024-02-25 09:57:26 +05:30
Kovid Goyal
822c9cb1d6 ... 2024-02-25 09:57:26 +05:30
Kovid Goyal
529de9c91d Allow specifying benchmarks to run on the command line 2024-02-25 09:57:26 +05:30
Kovid Goyal
7914523a16 Add a CSI + ascii test 2024-02-25 09:57:26 +05:30
Kovid Goyal
d39c71f927 Round the time to two digit precision 2024-02-25 09:57:26 +05:30
Kovid Goyal
934f2ede0b Start work on simple benchmark tool 2024-02-25 09:57:26 +05:30
Kovid Goyal
8dbea2a046 ... 2024-02-25 09:57:26 +05:30
Kovid Goyal
38c8100a76 ... 2024-02-25 09:57:26 +05:30
Kovid Goyal
a560d86d0f Use aligned loads for the byte loader 2024-02-25 09:57:26 +05:30
Kovid Goyal
47a493c090 Increase chunk size for graphics protocol since the VT parser now supports it 2024-02-25 09:57:25 +05:30
Kovid Goyal
35da87994b Fix input_delay not working 2024-02-25 09:57:25 +05:30
Kovid Goyal
f49f2a1b82 Fix buf full -> not full reporting 2024-02-25 09:57:25 +05:30
Kovid Goyal
91c3492455 Allow logging code to log arbitrary length messages 2024-02-25 09:57:25 +05:30
Kovid Goyal
75872a1097 Dont need an extra variable 2024-02-25 09:57:25 +05:30
Kovid Goyal
4c267bdc24 Use a faster base64 implementation
From the Chromium source code BSD licensed
2024-02-25 09:57:25 +05:30
Kovid Goyal
409ca6bfab Allow larger graphics escape code sizes 2024-02-25 09:57:25 +05:30
Kovid Goyal
56abcbf910 Remove unused base64 32bit functions 2024-02-25 09:57:25 +05:30
Kovid Goyal
f140b74f17 ... 2024-02-25 09:57:25 +05:30
Kovid Goyal
8360a4ec53 Only reset urf8 state when transitioning into normal 2024-02-25 09:57:25 +05:30
Kovid Goyal
ccf124218b ... 2024-02-25 09:57:25 +05:30
Kovid Goyal
737d7bf8f2 Fix parse_sgr buf overread 2024-02-25 09:57:25 +05:30
Kovid Goyal
3f41b22011 Use the byte loader for normal mode 2024-02-25 09:57:25 +05:30
Kovid Goyal
43451b1287 ... 2024-02-25 09:57:25 +05:30
Kovid Goyal
2914c2eb95 Use the byte loader for parsing CSI as well 2024-02-25 09:57:25 +05:30
Kovid Goyal
fc1775753a ... 2024-02-25 09:57:25 +05:30
Kovid Goyal
65aca5b140 Speedup utoi by loading numbers in 8 byte chunks 2024-02-25 09:57:24 +05:30
Kovid Goyal
e7c466797c threading test for full buffer 2024-02-25 09:57:24 +05:30
Kovid Goyal
c66c0b8edc threading tests for pending 2024-02-25 09:57:24 +05:30
Kovid Goyal
a6da0ac6ca Log bad remote commands 2024-02-25 09:57:24 +05:30
Kovid Goyal
5c9aa6a21a json.loads() stupidly does not accept memoryview 2024-02-25 09:57:24 +05:30
Kovid Goyal
50935b6c93 Cleanup kitty dcs parsing 2024-02-25 09:57:24 +05:30
Kovid Goyal
0a6d83901d ... 2024-02-25 09:57:24 +05:30
Kovid Goyal
8bff6f1995 More threading tests 2024-02-25 09:57:24 +05:30
Kovid Goyal
8f1b30a25b No need to ask for 7bit controls anymore 2024-02-25 09:57:24 +05:30
Kovid Goyal
9f337e93fc Add some threading tests 2024-02-25 09:57:24 +05:30
Kovid Goyal
08d99967dc Sanitize contents of remote print 2024-02-25 09:57:24 +05:30
Kovid Goyal
72635c55c5 Convenience methods to test parser threading 2024-02-25 09:57:24 +05:30
Kovid Goyal
2b3b8bae23 Fix osc52 null termination 2024-02-25 09:57:24 +05:30
Kovid Goyal
f96182cc11 Fix utf8 decode 2024-02-25 09:57:24 +05:30
Kovid Goyal
93784903b2 Remove FLUSH_DRAW as it is not needed 2024-02-25 09:57:24 +05:30
Kovid Goyal
afcffc03b1 Separate test of write and read so we can test threading 2024-02-25 09:57:24 +05:30
Kovid Goyal
34164dc341 Read errors from child must commit a zero write 2024-02-25 09:57:23 +05:30
Kovid Goyal
6205fb32fd Refactor VT parser for more speed
No longer copy bytes into a separate buffer, instead parse them in place
in the read buffer
2024-02-25 09:57:23 +05:30
Kovid Goyal
23bb2e1b67 Fast function to replace c0 codes 2024-02-25 09:57:23 +05:30
Kovid Goyal
c81ac668da Use a single code path for tests and live VT parsing 2024-02-25 09:57:23 +05:30
Kovid Goyal
f42b49e597 Avoid a double parse for pending mode 2024-02-25 09:57:23 +05:30
Kovid Goyal
a4ca143fc5 Limit amount of pending data we will store 2024-02-25 09:57:23 +05:30
Kovid Goyal
969bd05fc5 Represent malformed UTF-8 with the replacement character 2024-02-25 09:57:23 +05:30
Kovid Goyal
8a83014f51 Dont construct memoryview when not needed in non dump code path 2024-02-25 09:57:23 +05:30
Kovid Goyal
dcde461c02 ... 2024-02-25 09:57:23 +05:30
Kovid Goyal
6c0e938d5a ... 2024-02-25 09:57:23 +05:30
Kovid Goyal
76158f39ba Pass the window id to the dump calback 2024-02-25 09:57:23 +05:30
Kovid Goyal
a4193a1b02 Fix dumping of bytes/commands 2024-02-25 09:57:23 +05:30
Kovid Goyal
5ab1e647bf Use libc alloc instead of python alloc for vt parser 2024-02-25 09:57:23 +05:30
Kovid Goyal
9ecf79fa84 Fix parse worker 2024-02-25 09:57:23 +05:30
Kovid Goyal
44c96a208e All tests now pass 2024-02-25 09:57:23 +05:30
Kovid Goyal
065866895c Get pending mode working and add a few more tests 2024-02-25 09:57:23 +05:30
Kovid Goyal
52025ff030 misc parser and test fixes 2024-02-25 09:57:22 +05:30
Kovid Goyal
5168e0b576 Port parse_bytes() used in the tests 2024-02-25 09:57:22 +05:30
Kovid Goyal
e4bb00d942 Implement UTF-8 decoding for screen_draw() 2024-02-25 09:57:22 +05:30
Kovid Goyal
5f809bf249 Get kitty building with the new VT parser 2024-02-25 09:57:22 +05:30
Kovid Goyal
b083ad9038 Start work on bytes based VT parser 2024-02-25 09:57:22 +05:30
Kovid Goyal
ce2e1b0813 Ensure we dont pass a NULL pointer to wl_pointer_set_cursor()
Possible fix for #7139
2024-02-20 23:31:18 +05:30
Kovid Goyal
be92cc87a4 macOS: The command line args from macos-launch-services-cmdline are now prefixed to any args from open --args rather than overwriting them
The purpose of the file is to provide default command line args when
launching from GUI. Since macOS nowadays also allows command line args
when launch via open, also respect them.

Fixes #7135
2024-02-18 11:22:15 +05:30
Kovid Goyal
b2391553f9 Keyboard protocol: Fix the Enter Tab and Backspace keys generating spurious release events even when report all keys as escape codes is not set
Fixes #7136
2024-02-18 11:12:24 +05:30
Kovid Goyal
d35f391725 Fix #7131 2024-02-15 13:06:33 +05:30
Kovid Goyal
b9ebb23bb9 Fix #7130 2024-02-14 19:11:02 +05:30
Kovid Goyal
c4ef6b87aa ... 2024-02-12 14:58:13 +05:30
Kovid Goyal
031f9d8c26 ... 2024-02-12 14:43:46 +05:30
Kovid Goyal
8c25c55f01 Merge branch 'fix-build-docs' of https://github.com/sytranvn/kitty 2024-02-12 14:36:21 +05:30
Sy Tran
cdce26e519 fix: typo in build docs 2024-02-12 15:59:01 +07:00
Kovid Goyal
925043d645 ... 2024-02-12 11:17:25 +05:30
Kovid Goyal
f63a4cf90c version 0.32.2 2024-02-12 11:15:49 +05:30
Kovid Goyal
e6d881e89b Ensure we have at least a 1px thick line in cross shade 2024-02-12 09:37:35 +05:30
Kovid Goyal
325e6acd7e Parametrize by number of lines not density 2024-02-12 09:35:15 +05:30
Kovid Goyal
10cfc66737 Merge branch 'dependabot/go_modules/all-go-deps-3cea7aaa0b' of https://github.com/kovidgoyal/kitty 2024-02-12 09:33:11 +05:30
Kovid Goyal
5dbfee9e9c DRYer 2024-02-12 09:32:25 +05:30
Kovid Goyal
edd2bc85ae Adjust cross_shade to have appearance more like in Unicode standard
We try to draw approximately seven diagonal lines per cell
2024-02-12 09:30:11 +05:30
dependabot[bot]
e918b3fb1e Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/sys` from 0.16.0 to 0.17.0
- [Commits](https://github.com/golang/sys/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 03:57:03 +00:00
Kovid Goyal
c915d1bf58 Fix #7121 2024-02-12 09:24:51 +05:30
Kovid Goyal
cd2c7b3bbd git rev-list --skip invocation changed 2024-02-12 08:47:50 +05:30
Kovid Goyal
63b8893c50 Fix #7117 2024-02-11 06:30:01 +05:30
Kovid Goyal
946d28ae37 Completion for kitty @ load-config --override xxx 2024-02-10 14:52:29 +05:30
Kovid Goyal
97e2d41233 Completion for kitty @ action 2024-02-10 14:01:45 +05:30
Kovid Goyal
54548931b5 Allow running mappable actions via remote control
Saves me having to define a special remote control wrapper for every
mappable action.
2024-02-10 13:23:06 +05:30
Kovid Goyal
ac7b6870a8 close_other_os_windows: to close non active OS windows
Fixes #7113
2024-02-10 12:20:55 +05:30
Kovid Goyal
576a269648 Special case rendering of some more box drawing characters using shades from the block of symbols for legacy computing
Fixes #7110
2024-02-10 10:13:46 +05:30
Kovid Goyal
4bcf69a47e Add more shade box drawing characters
From the legacy computing symbols block
2024-02-10 09:45:25 +05:30
Kovid Goyal
5a418a8cd6 Merge branch 'prompt_command-empty-check' of https://github.com/akinomyoga/kitty 2024-02-09 19:15:56 +05:30
Kovid Goyal
585ac148a6 ... 2024-02-09 19:14:26 +05:30
Koichi Murase
af84161528 Fix Bash integration removing existing elements of PROMPT_COMMAND 2024-02-09 20:50:30 +09:00
Kovid Goyal
7c14e0d666 macOS: Fix an abort when changing OS window chrome for a full screen window via remote control or the themes kitten
Fixes #7106
2024-02-09 15:32:09 +05:30
Kovid Goyal
62347d7e97 remove unneeded headers 2024-02-09 15:16:56 +05:30
Kovid Goyal
777fd5350b Add a test for Go flock implementation 2024-02-09 11:54:51 +05:30
Kovid Goyal
442ca012fd ... 2024-02-07 11:19:42 +05:30
Kovid Goyal
065b17ddbd kitten @ load-config: Allow (re)loading kitty.conf via remote control 2024-02-07 11:08:55 +05:30
Kovid Goyal
bc3c9ce2fa Fix #7100 2024-02-05 20:48:49 +05:30
Kovid Goyal
9bea8bb5bc remove no longer needed code 2024-02-05 13:54:22 +05:30
Kovid Goyal
fef8c536d8 update .gitignore for vt branch as well 2024-02-05 13:33:30 +05:30
Kovid Goyal
8cc2cad4d9 Use list of legal chars in URL from the WHATWG standard
Notably this excludes some ASCII chars: <>{}[]`|
See https://url.spec.whatwg.org/#url-code-points

Fixes #7095
2024-02-05 13:27:22 +05:30
Kovid Goyal
5f8e5b0a29 Merge branch 'dependabot/go_modules/all-go-deps-b84e69789e' of https://github.com/kovidgoyal/kitty 2024-02-05 09:03:02 +05:30
dependabot[bot]
4ede3a8a82 Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil).


Updates `github.com/shirou/gopsutil/v3` from 3.23.12 to 3.24.1
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.12...v3.24.1)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-05 03:26:59 +00:00
Kovid Goyal
934217baf1 Merge branch 'fix/open-url-with-spl' of https://github.com/chuck-sys/kitty 2024-02-03 08:20:42 +05:30
Kovid Goyal
d0f3b34517 Fix typo in docs 2024-02-03 08:20:11 +05:30
Cheuk Yin Ng
cd8f0c1374 fix: open_url_with docs spelling 2024-02-02 12:02:08 -08:00
Kovid Goyal
9b8ee54034 better example of conditional key mapping 2024-01-29 21:58:10 +05:30
Kovid Goyal
d730c189db Merge branch 'dependabot/go_modules/all-go-deps-676548f652' of https://github.com/kovidgoyal/kitty 2024-01-29 08:40:38 +05:30
dependabot[bot]
3fc1e6911a Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/google/uuid](https://github.com/google/uuid).


Updates `github.com/google/uuid` from 1.5.0 to 1.6.0
- [Release notes](https://github.com/google/uuid/releases)
- [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/uuid/compare/v1.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/google/uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-29 03:06:38 +00:00
Kovid Goyal
e8d9ca4465 Graphics protocol: Improve display of images using unicode placeholders or row/column boxes by resizing them using linear instead of nearest neighbor interpolation on the GPU
Fixes #7070
2024-01-28 08:05:02 +05:30
Kovid Goyal
8c12086beb Dont store query images in disk cache and dont send their data to GPU 2024-01-27 13:41:59 +05:30
Kovid Goyal
5a2ee2f9a3 macOS: Fix kitten @ select-window leaving the keyboard in a partially functional state
Fixes #7074
2024-01-27 12:53:58 +05:30
Kovid Goyal
cafd5a7471 @ send-text --bracketed-paste
Allow automatically wrapping sent text in bracketed paste if the
program running in the destination window has turned on bracketed paste
mode.
2024-01-26 20:51:21 +05:30
Kovid Goyal
4c46d2bc95 ... 2024-01-26 20:07:55 +05:30
Kovid Goyal
c95fc3689b A single multi-key mapping should not prematurely complete as that confuses people trying out the feature
See #7073
2024-01-26 20:04:33 +05:30
Kovid Goyal
8c50632a10 Fix a single key mapping not overriding a previously defined multi-key mapping 2024-01-26 18:02:25 +05:30
Kovid Goyal
ae1bf69a3d Fix date in changelog 2024-01-26 17:24:45 +05:30
Kovid Goyal
08d88af2fb version 0.32.1 2024-01-26 08:33:51 +05:30
Kovid Goyal
4dfbcb539f Add basic tests for modal mappings 2024-01-25 14:42:27 +05:30
Kovid Goyal
cc0d6621a4 Also document how to set user vars from nvim 2024-01-25 14:27:55 +05:30
Kovid Goyal
d6e55f72c0 Forgot to stub out one method for the test 2024-01-25 14:18:09 +05:30
Kovid Goyal
cd30de3727 Fix #7055 2024-01-25 14:06:52 +05:30
Kovid Goyal
cec427777c Add some tests for mappings 2024-01-25 13:56:42 +05:30
Kovid Goyal
30e3ad83bc Move mapping code into its own class
Better encapsulation. Makes boss.py smaller. Allows writing tests
for mapping logic
2024-01-25 11:51:43 +05:30
Kovid Goyal
9ef6801f4c A single key shortcut should override all previous multi-key shortcuts that have that shortcut as a prefix
Fixes #7058
2024-01-25 11:24:40 +05:30
Kovid Goyal
7f1c371b6e DRYer 2024-01-25 09:00:46 +05:30
Kovid Goyal
2f7b0d1d94 Dont show multiple keys bindings in debug output when their focus on conditions are the same 2024-01-25 08:08:52 +05:30
Kovid Goyal
90e1ba7781 Fix #7051 2024-01-24 18:56:04 +05:30
Kovid Goyal
0dfe89a817 ... 2024-01-23 18:42:28 +05:30
Kovid Goyal
c76f75a154 Fix a regression in the previous release that caused overriding of existing multi-key mappings to fail
Fixes #7044
2024-01-23 15:49:30 +05:30
Kovid Goyal
f51520eb79 Clarify behavior of image id==!0 and placement id == 0
See https://github.com/kovidgoyal/kitty/discussions/7043
2024-01-23 08:41:23 +05:30
Kovid Goyal
828f4f312a Wayland+NVIDIA: Do not request an sRGB output buffer as a bug in Wayland causes kitty to not start
Fixes #7021
2024-01-22 13:22:04 +05:30
Kovid Goyal
a9c7a85d9a Clarify the behavior of functional keys with no legacy encoding
See https://github.com/kovidgoyal/kitty/discussions/7037
2024-01-22 08:35:54 +05:30
Kovid Goyal
38393b50c1 Show how to send SIGUSR1 to kitty 2024-01-22 07:36:57 +05:30
Kovid Goyal
7b6c532ac2 ... 2024-01-21 15:34:06 +05:30
Kovid Goyal
b3e74de390 More work on pager kitten 2024-01-21 14:47:56 +05:30
Kovid Goyal
1aa4d7d24b When displaying scrollback fallback to less if the user configures a pager that is not in PATH 2024-01-21 09:22:02 +05:30
Kovid Goyal
a3e324d623 When testing for cf-protection support take env into account 2024-01-21 08:42:55 +05:30
Kovid Goyal
d6116f7426 Fix #7026 2024-01-21 08:33:59 +05:30
Kovid Goyal
ab9631f045 Better fix 2024-01-21 08:27:16 +05:30
Kovid Goyal
ec0a449c63 Fix a regression in the previous release that caused kitten @ send-text with a match parameter to send text twice to the active window
Fixes #7027
2024-01-21 08:24:22 +05:30
Kovid Goyal
01ffbfdb42 Fix a regression in the previous release that caused kitten @ launch --cwd=current to fail over SSH
Fixes #7028
2024-01-21 08:06:44 +05:30
Kovid Goyal
f5621bd56c Merge branch 'dmenu-term' of https://github.com/weakish/kitty 2024-01-20 19:15:50 +05:30
weakish
708750173e Remove dmenu-term in docs
The dmenu-term link returns 404 now.
2024-01-20 08:39:05 +00:00
Kovid Goyal
20e43a3e7d Fix a regression in the previous release that caused multi-key sequences to not abort when pressing an unknown key
Fixes #7022
2024-01-20 08:13:12 +05:30
Kovid Goyal
ff4ee95eba ... 2024-01-20 06:49:49 +05:30
Kovid Goyal
2707c44f0f DRYer 2024-01-19 21:48:40 +05:30
Kovid Goyal
e7e401c8dd More work on pager kitten 2024-01-19 21:16:09 +05:30
Kovid Goyal
b0ab5bd5eb ... 2024-01-19 20:50:11 +05:30
Kovid Goyal
d75395794d ... 2024-01-19 20:46:20 +05:30
Kovid Goyal
c7d894d499 Merge branch 'fix-go-version-check' of https://github.com/Maytha8/kitty 2024-01-19 20:22:42 +05:30
Maytham Alsudany
30905db75f Explicit GO111MODULE=on when getting required Go version 2024-01-19 22:46:48 +08:00
Kovid Goyal
89c3b4f9e2 macOS: Fix a regression in the previous release that broke overriding keyboard shortcuts for actions present in the global menu bar
Fixes #7016
2024-01-19 19:44:04 +05:30
Kovid Goyal
0bd50abd77 Start work on pager kitten 2024-01-19 15:09:20 +05:30
Kovid Goyal
7038292d11 Merge branch 'master' of https://github.com/solopasha/kitty 2024-01-19 14:03:30 +05:30
Kovid Goyal
b33f8416db Fix for spurious github code scanning alert 2024-01-19 14:01:26 +05:30
Pavel Solovev
99b3d0727d Fix build with gcc14 2024-01-19 11:25:53 +03:00
Kovid Goyal
9503725a32 Fix #7013 2024-01-19 13:29:12 +05:30
Kovid Goyal
eb5dd364ae version 0.32.0 2024-01-19 10:50:55 +05:30
Kovid Goyal
4a64f812ad Merge branch 'boss-window-args' of https://github.com/ad-chaos/kitty 2024-01-19 07:46:36 +05:30
ad-chaos
c2acc2460b expose glfw{Get,Set}WindowPos to python 2024-01-18 22:21:39 +05:30
Kovid Goyal
bea8fd25a7 Make argument handling of create_os_window() to be more robust and match its python signature 2024-01-18 21:58:39 +05:30
Kovid Goyal
1593baa9f9 remove unused include 2024-01-18 21:38:18 +05:30
Kovid Goyal
0447b17af2 Merge branch 'nth_os_window-fix' of https://github.com/jackielii/kitty 2024-01-18 19:08:58 +05:30
Jackie Li
0d3c5497ff for #7009
Oops, the num is already negative index, no need to reverse here.

Alternatively this is shorter:

```
    def nth_os_window(self, num: int = 1) -> None:
        if not self.os_window_map:
            return

        if num == 0:
            os_window_id = current_focused_os_window_id() or last_focused_os_window_id()
        elif num > 0:
            ids = tuple(self.os_window_map.keys())
            os_window_id = ids[min(num, len(ids)) - 1]
        else:
            fc_map = os_window_focus_counters()
            ids = sorted(fc_map.keys(), key=fc_map.__getitem__, reverse=True)
            os_window_id = ids[min(-num, len(ids)-1)]
        focus_os_window(os_window_id, True)
```
2024-01-18 09:53:47 +00:00
Kovid Goyal
7826fefe30 Merge branch 'nth_os_window-typo' of https://github.com/jackielii/kitty 2024-01-18 14:43:02 +05:30
Jackie Li
10ca74f502 fix typo and add a couple examples 2024-01-18 09:07:53 +00:00
Kovid Goyal
715548b144 Make test robust against wezterm's system wide shell integration
Not only is it system wide but it runs by default, even outside wezterm,
sigh.
2024-01-18 12:52:54 +05:30
Kovid Goyal
43df7be977 Add a note that themes can override cursor color
See #6987
2024-01-18 07:56:50 +05:30
Kovid Goyal
9b5f665218 Allow focusing previously active OS windows via nth_os_window
Fixes #7009
Fixes #7008
2024-01-18 07:54:15 +05:30
Kovid Goyal
5e934c081e Fix #7004 2024-01-17 08:39:00 +05:30
Kovid Goyal
22dbc94c5f Merge branch 'patch-1' of https://github.com/davidbrochart/kitty 2024-01-16 17:36:25 +05:30
David Brochart
2df1273d53 Remove duplicated line 2024-01-16 13:01:47 +01:00
Kovid Goyal
54900183ec Fix #6997 2024-01-16 13:38:12 +05:30
Kovid Goyal
1c72a94b2f Fix universal build with cf-protection failing 2024-01-15 12:45:55 +05:30
Kovid Goyal
46bb027d14 Fix building on old gcc/clang 2024-01-15 11:23:42 +05:30
Kovid Goyal
37f0c8c0a8 Fix #6994 2024-01-15 10:18:03 +05:30
Kovid Goyal
cad7047a7a Make the text for kitty.scrollback.nvim fit with the rest 2024-01-10 09:39:29 +05:30
Kovid Goyal
e6acc69460 Merge branch 'add_integration_kitty_scrollback_nvim' of https://github.com/mikesmithgh/kitty 2024-01-10 09:39:09 +05:30
Mike Smith
40d8111717 Document integration with tool kitty-scrollback.nvim 2024-01-09 22:43:44 -05:00
Kovid Goyal
970cc9ba7a Merge branch 'dependabot/go_modules/all-go-deps-4690a2b430' of https://github.com/kovidgoyal/kitty 2024-01-08 09:13:43 +05:30
dependabot[bot]
6e685d01b0 Bump the all-go-deps group with 2 updates
Bumps the all-go-deps group with 2 updates: [golang.org/x/image](https://github.com/golang/image) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/image` from 0.14.0 to 0.15.0
- [Commits](https://github.com/golang/image/compare/v0.14.0...v0.15.0)

Updates `golang.org/x/sys` from 0.15.0 to 0.16.0
- [Commits](https://github.com/golang/sys/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-08 03:37:59 +00:00
Kovid Goyal
b8c5c62585 Graphics protocol: Specify some edge case behavior for image display
See https://github.com/kovidgoyal/kitty/discussions/6979
2024-01-08 08:46:17 +05:30
Kovid Goyal
7427e65f60 When copying env for SSH sanitize problematic env vars 2024-01-06 13:53:20 +05:30
Kovid Goyal
e656a75d5e Move implementation of --hold into Child
DRYer. Also fixed use of --hold with launch --cwd=current
2024-01-06 13:14:48 +05:30
Kovid Goyal
1e249035c7 Fix focus_visible_window not switching to other window in stack layout when only two windows are present
Fixes #6970
2024-01-05 21:41:21 +05:30
Kovid Goyal
044f53b35b Merge branch 'fix-wayland-cursor-shape' of https://github.com/jinliu/kitty 2024-01-04 17:37:50 +05:30
Jin Liu
e20eff277b Fix Wayland cursor-shape-v1 cursor not updating
According to https://wayland.app/protocols/cursor-shape-v1#wp_cursor_shape_device_v1:request:set_shape
> The serial parameter must match the latest wl_pointer.enter or
> zwp_tablet_tool_v2.proximity_in serial number sent to the client.

So we can't use wl.serial or wl.pointer_serial, because they are also updated in other places.
2024-01-04 19:54:03 +08:00
Kovid Goyal
5ea1d14617 Merge branch 'dependabot/go_modules/all-go-deps-c69f2790a2' of https://github.com/kovidgoyal/kitty 2024-01-01 08:50:31 +05:30
dependabot[bot]
1bea64768e Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil).


Updates `github.com/shirou/gopsutil/v3` from 3.23.11 to 3.23.12
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.11...v3.23.12)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 03:10:29 +00:00
Kovid Goyal
ab2af0c141 ... 2023-12-26 22:53:57 +05:30
Kovid Goyal
0a2fcf1805 Mouse reporting: Fix incorrect position reported for windows with padding
Fixes #6950
2023-12-26 22:27:20 +05:30
Kovid Goyal
858f0c1073 GNOME Wayland: Fix remembered window size smaller than actual size
Fixes #6946
2023-12-25 19:29:33 +05:30
Kovid Goyal
fb1124b1b9 ... 2023-12-25 17:26:06 +05:30
Kovid Goyal
c76db4bfb4 Wayland: Redraw titlebar title on font size change
Fixes #6945
2023-12-25 17:20:52 +05:30
Kovid Goyal
1e5d14c834 Half the length of the style prefix 2023-12-25 09:43:01 +05:30
Kovid Goyal
5583f60289 Fix #6943 2023-12-25 08:33:54 +05:30
Kovid Goyal
4519b3abee Enable cursor shape on Wayland
Cant replicate the hyprland crash, so am not going to bother about it.

Fixes #6914
2023-12-24 22:56:01 +05:30
Kovid Goyal
cff490f881 Wayland: Add support for the new cursor-shape protocol
It is currently disabled because no compositor seems to support it.
Hyprland reports it as available but using it causes Hyprland to crash.
Plasma 6 is supposed to have it but I am not installing a beta just for
this.

Typical Wayland.
2023-12-24 18:45:17 +05:30
Kovid Goyal
7d8c017215 DRYer 2023-12-24 15:03:56 +05:30
Kovid Goyal
91cdf4af00 kitty keyboard protocol: Specify the behavior of the modifier bits during modifier key events
Fixes #6913
2023-12-24 12:09:13 +05:30
Kovid Goyal
79db8b43e0 Make mypy happy 2023-12-22 06:43:12 +05:30
Kovid Goyal
c03d99e744 Update changelog 2023-12-22 06:20:38 +05:30
Kovid Goyal
7c0cb5481f Merge branch 'master' of https://github.com/FelixKratz/kitty 2023-12-22 06:19:38 +05:30
Felix Kratz
912c5ce4f9 dont reuse cascade point on another display
fix wording

reset cascade point to zero point
2023-12-21 11:30:50 +01:00
Kovid Goyal
39a3c38037 Merge branch 'patch-1' of https://github.com/arthurbacci/kitty 2023-12-21 08:08:59 +05:30
Kovid Goyal
5dfe4427cf Note that the rio terminal also supports the kitty keyboard protocol 2023-12-21 08:07:27 +05:30
Arthur Bacci
b2eac37164 Fix copy-paste typo in graphics-protocol.rst 2023-12-20 15:44:53 -03:00
Kovid Goyal
ec8b7853c5 Improve docs for resize_on_debounce 2023-12-19 17:39:54 +05:30
Kovid Goyal
d9903f5283 Add a note for what to do instead of --detach on macOS 2023-12-18 12:04:23 +05:30
Kovid Goyal
ccfb979218 Merge branch 'dependabot/go_modules/all-go-deps-f5d2d9a206' of https://github.com/kovidgoyal/kitty 2023-12-18 09:52:42 +05:30
dependabot[bot]
ff8387f8e7 Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/google/uuid](https://github.com/google/uuid).

- [Release notes](https://github.com/google/uuid/releases)
- [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/uuid/compare/v1.4.0...v1.5.0)

---
updated-dependencies:
- dependency-name: github.com/google/uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 03:31:14 +00:00
Kovid Goyal
017947de7f panel kitten: Fix rendering with non-zero margin.padding in kitty.conf
Fixes #6923
2023-12-17 11:12:49 +05:30
Kovid Goyal
2a5ba519f5 Fix #6923 2023-12-17 10:50:18 +05:30
Kovid Goyal
b2587c1d54 Fix modifier reporting on macOS
We make use of the fact that the device dependent modifiers flags
actually report left/right modifier. Code taken form SDL, with thanks.
2023-12-14 11:31:48 +05:30
Kovid Goyal
7e5230e6f4 more grammar 2023-12-14 09:06:16 +05:30
Kovid Goyal
64cfe8171f ... 2023-12-14 08:55:43 +05:30
Kovid Goyal
a9b424e307 Keyboard protocol: Clarify the behavior of the modifier bits during modifier key events
I cant find any relevant standards for this, so am just picking the
macOS behavior as it seems more sensible to me.

Fixes #6913
2023-12-14 08:50:19 +05:30
Kovid Goyal
d9ccbcd0ce Font fallback: Fix the font used to render a character sometimes dependent on the order in which characters appear on screen
We ameliorate the performance hit by storing a hash table mapping cell
text to the loaded fallback font index so that lookups for previously
seen text are still fast.

Fixes #6865
2023-12-11 20:27:21 +05:30
Kovid Goyal
7cec82f453 Merge branch 'dependabot/go_modules/all-go-deps-8acd87a792' of https://github.com/kovidgoyal/kitty 2023-12-11 11:04:46 +05:30
dependabot[bot]
18c0a449d2 Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma).

- [Release notes](https://github.com/alecthomas/chroma/releases)
- [Changelog](https://github.com/alecthomas/chroma/blob/master/.goreleaser.yml)
- [Commits](https://github.com/alecthomas/chroma/compare/v2.11.1...v2.12.0)

---
updated-dependencies:
- dependency-name: github.com/alecthomas/chroma/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 03:22:52 +00:00
Kovid Goyal
00f8f340bf macOS: Fix returning from full screen via the button when the titlebar is hidden not hiding the buttons
Fixes #6883
2023-12-10 22:30:15 +05:30
Kovid Goyal
e9e889457d macOS: Fix some combining characters not being rendered
Use Harfbuzz for positioning instead of Core Text as Core Text doesn't
position combining chars correctly anymore. This may mean we need to
redo the cell metrics calculation as well, we will see. Core Text is
still used for rendering but at positions specified by Harfbuzz.

Fixes #6898
2023-12-10 20:30:24 +05:30
Kovid Goyal
d41138c4c6 Make units_per_em available in do_render 2023-12-10 15:29:03 +05:30
Kovid Goyal
69a5c7e3b2 Wayland: Fix a regression in the previous release that broke copying to clipboard under wl-roots based compositors in some circumstances
As is usual in Wayland land, utter chaos. Divergent implementations,
incorrect interpretations of the spec, bla bla.

Fixes #6890
2023-12-08 08:38:08 +05:30
Kovid Goyal
92befa26db Fix #6889 2023-12-07 09:30:04 +05:30
Kovid Goyal
22ac57c374 Another terminal emulator adds support for the kitty keyboard protocol 2023-12-06 16:32:27 +05:30
Kovid Goyal
392a301cd8 Note how to to use hints to open hyperlinks 2023-12-05 07:50:35 +05:30
Kovid Goyal
a1f2a7df4d Port new shlex code to Go 2023-12-04 14:14:11 +05:30
Kovid Goyal
04eafbea9b Implement better syntax highlighting for the new map 2023-12-04 11:54:49 +05:30
Kovid Goyal
cf6c00cebe Merge branch 'dependabot/go_modules/all-go-deps-e63ccaec5d' of https://github.com/kovidgoyal/kitty 2023-12-04 08:59:17 +05:30
dependabot[bot]
08da87a622 Bump the all-go-deps group with 2 updates
Bumps the all-go-deps group with 2 updates: [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) and [howett.net/plist](https://github.com/DHowett/go-plist).


Updates `github.com/shirou/gopsutil/v3` from 3.23.10 to 3.23.11
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.10...v3.23.11)

Updates `howett.net/plist` from 1.0.0 to 1.0.1
- [Commits](https://github.com/DHowett/go-plist/compare/v1.0.0...v1.0.1)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-go-deps
- dependency-name: howett.net/plist
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 03:25:11 +00:00
Kovid Goyal
59e3b202b9 Update changelog 2023-12-03 21:11:52 +05:30
Kovid Goyal
a7bdbb11f2 Document the new modal keymaps 2023-12-03 21:09:26 +05:30
Kovid Goyal
b9fabc62a5 ... 2023-12-03 21:07:01 +05:30
Kovid Goyal
d483c3eb33 Fix literal field parsing 2023-12-03 20:55:47 +05:30
Kovid Goyal
d191896528 Allow more options for what to do in a custom keyboard mode on unknown and action events 2023-12-03 20:07:29 +05:30
Kovid Goyal
ca6c607148 pop_keyboard_mode should return True when nothing is done 2023-12-03 19:12:58 +05:30
Kovid Goyal
cc5424c054 ... 2023-12-03 19:02:46 +05:30
Kovid Goyal
77551cdfc1 Weird macOS docs build failure 2023-12-03 15:06:12 +05:30
Kovid Goyal
c6eab841f9 Send repeat events instead of repeated presses 2023-12-03 13:29:13 +05:30
Kovid Goyal
99995fd9dc Remote control API for send-key 2023-12-03 13:23:01 +05:30
Kovid Goyal
74388b4183 A simple action to remap key presses sent to programs running in kitty 2023-12-03 13:08:53 +05:30
Kovid Goyal
f1fc2126bc Refactor the mapping docs 2023-12-03 12:25:15 +05:30
Kovid Goyal
9a0e84293f ... 2023-12-02 16:35:30 +05:30
Kovid Goyal
847ef008e2 Allow spaces in --when-focus-on 2023-12-02 16:23:43 +05:30
Kovid Goyal
3c4f2aa1b8 shlex.split -> shlex_split 2023-12-02 15:17:08 +05:30
Kovid Goyal
6c8f499303 Merge branch 'cursor_non_gnome' of https://github.com/jinliu/kitty 2023-12-02 15:00:50 +05:30
Kovid Goyal
b0ba4b4a42 Fast and robust implementation of shlex.split
Also returns position of words in src string which we will need for
keymap parsing.
2023-12-02 14:57:02 +05:30
Jin Liu
293cd40509 Get cursor theme from desktop portal in non-GNOME desktops
Even if current DE is not GNOME, it may still use the GNOME
desktop portal as a fallback for Settings (e.g. KDE). So if
the user installed xdg-desktop-portal-gtk, and KDE synced
its cursor theme with GNOME, then we can still get it from
the GNOME namespace in the Settings.ReadAll result from the
portal.
2023-12-02 15:00:03 +08:00
Kovid Goyal
0d10ee1a8c DRYer 2023-12-02 08:07:25 +05:30
Kovid Goyal
d63b852b90 Un-matched modifier keys should not pop keyboard mode 2023-12-01 19:34:20 +05:30
Kovid Goyal
9560968a7d Sequences should not participate in global shortcuts 2023-12-01 19:31:14 +05:30
Kovid Goyal
53980d00f0 a couple more tests 2023-12-01 18:16:22 +05:30
Kovid Goyal
5bc2cde454 Add --debug-input output for sequence prefix matches 2023-12-01 17:19:08 +05:30
Kovid Goyal
d4ff54e0d8 Dont use branch-protection=standard on linux ARM as it reportedly causes crashes
See https://github.com/kovidgoyal/kitty/issues/6845#issuecomment-1835886938
2023-12-01 16:48:30 +05:30
Kovid Goyal
f2075f99fd More comprehensive is_arm check
Apparently on some Linux machines platform.machine() is 'aarch64' not
'arm64'.
2023-12-01 16:36:34 +05:30
Kovid Goyal
f46425c2f9 Fix #6876 2023-12-01 16:28:48 +05:30
Kovid Goyal
ad4e9bb42c Add a check that the output buffer is actually sRGB 2023-12-01 13:58:09 +05:30
Kovid Goyal
97f5cad335 Request an SRGB output buffer from the window system explicitly
Possible fix for #6845
2023-12-01 13:50:11 +05:30
Kovid Goyal
788295e534 Turn on control flow protection build options 2023-12-01 07:36:02 +05:30
Kovid Goyal
336035f507 Merge branch 'feature/fix-build-problems-nix' of https://github.com/gabyx/kitty 2023-12-01 07:06:13 +05:30
Gabriel Nützi
1883208cf6 fix: Correct Nix shell for building correctly 2023-11-30 22:09:15 +01:00
Kovid Goyal
8d1fde18f8 Fix sequence mapping 2023-11-30 21:17:02 +05:30
Kovid Goyal
d7633b95d0 Get debug config printing the changes in all keyboard modes 2023-11-30 20:47:30 +05:30
Kovid Goyal
165f1ccfd1 Port the test 2023-11-30 20:06:20 +05:30
Kovid Goyal
063a663958 Beep when multi-key sequence is aborted by mismatch 2023-11-30 20:02:25 +05:30
Kovid Goyal
66bc86e4f2 Report invalid --when-focus-on expressions to user 2023-11-30 20:00:49 +05:30
Kovid Goyal
15eb03c5e2 Add no-op to paste_actions 2023-11-30 19:54:01 +05:30
Kovid Goyal
c064a2e559 Port visual_window_select to use a keyboard mode 2023-11-30 19:50:57 +05:30
Kovid Goyal
9e815212dc Implement modal keyboard handling 2023-11-30 19:44:41 +05:30
Kovid Goyal
cb418a0040 Infrastructure for more map options 2023-11-30 13:36:29 +05:30
Kovid Goyal
716bf714db Fix a couple of tests 2023-11-30 11:53:09 +05:30
Kovid Goyal
f11f770011 Allow creating key mappings that depend on the state of the focused window, such as what program is running inside it 2023-11-30 11:35:30 +05:30
Kovid Goyal
8a1571f62c Add full docs for matching windows/tabs to the remote control page 2023-11-29 21:44:52 +05:30
Kovid Goyal
3876d518bd Fix setting swap interval for newly created OS window not always working 2023-11-29 21:13:10 +05:30
Kovid Goyal
72e14053f5 Simplify unmapping key/mouse button events
No need to specify the no-op action just specify no action. More
intuitive.
2023-11-28 12:37:27 +05:30
Kovid Goyal
bd7f38eb7d rg changed its help output to conform more closely to GNU conventions
Which is good I suppose, but it breaks hyperlinked_greps --help parsing.
I have updated it to match current rg which of course means it fails on
older rg.
2023-11-27 22:08:03 +05:30
Kovid Goyal
e19335377f Merge branch 'update-ask-kitten-help-msg' of https://github.com/lemontheme/kitty 2023-11-27 14:54:02 +05:30
adriaan
382d2f1ed0 Update help in main.py 2023-11-26 16:53:31 +01:00
Kovid Goyal
9bb85bd294 ask kitten: Better error message when choice letter is not present in choice text. Fixes #6855 2023-11-26 10:10:50 +05:30
Kovid Goyal
c10ea63818 Implement local filename completion for the transfer kitten 2023-11-25 07:46:30 +05:30
Kovid Goyal
4b3d29ecc3 Cant wait to drop python 3.8
Fixes #6848
2023-11-24 16:49:18 +05:30
Kovid Goyal
b297c27e09 ... 2023-11-23 19:43:37 +05:30
Kovid Goyal
6a09804910 Fix loading of window logo images via @launch
Use the path when either the pointer ORE the size is false. Apparently
some code paths pass pointers from a python y# conversion with an empty
bytestring as no value.

Fixes #6844
2023-11-23 19:34:35 +05:30
Kovid Goyal
c2b4df0666 No need to use fmemopen 2023-11-23 19:30:43 +05:30
Kovid Goyal
79f3692f1e Better PNG load error reporting 2023-11-23 19:16:43 +05:30
Kovid Goyal
35b2dcb065 ... 2023-11-23 17:25:52 +05:30
Kovid Goyal
2b751f56bd Port test 2023-11-22 10:50:05 +05:30
Kovid Goyal
882d471c90 Make config line parsing in Go use same algorithm as in python 2023-11-22 10:01:45 +05:30
Kovid Goyal
fc64ef41b3 when parsing conf files in go accept both space and tab as key separators 2023-11-22 09:49:33 +05:30
Kovid Goyal
b1e4c06220 Cleanup matching code for @ls and @send-text
Use the same utility function as other commands uses. Fixes #6835
2023-11-21 07:49:33 +05:30
Kovid Goyal
ef9dada80d Failure to change to cwd should not be fatal in bootstrap.py to match bootstrap.sh 2023-11-20 19:35:41 +05:30
Kovid Goyal
6d49686aee Merge branch 'patch-1' of https://github.com/Notarin/kitty 2023-11-19 09:32:54 +05:30
Notarin
3cbb8d5c8f Update graphics-protocol.rst
Fixed a very small typo
2023-11-18 22:36:39 -05:00
Kovid Goyal
ea28e20915 Show repology badge in 3 columns 2023-11-17 18:43:06 +05:30
Kovid Goyal
4897c4df00 Merge branch 'fish-sudo' of https://github.com/sersorrel/kitty 2023-11-17 08:39:04 +05:30
ash
b3c5b1185c Improve resilience of shell integration for sudo in fish
Running `sudo --version` will now not error out.
2023-11-17 00:24:40 +00:00
Kovid Goyal
b961e65f22 Clean up previous PR 2023-11-14 20:46:04 +05:30
Kovid Goyal
6d9593944a Merge branch 'notify_on_cmd_finish_use_bell' of https://github.com/jinliu/kitty 2023-11-14 20:40:11 +05:30
Jin Liu
a0d5f7a07b Add bell and command option to notify_on_cmd_finish
Instead of sending a desktop notification, it can be set to
ring the terminal bell or run a user-specified command.
2023-11-14 20:31:28 +08:00
Kovid Goyal
69e3e5c727 Use a boolean rather than an int 2023-11-14 16:35:01 +05:30
Kovid Goyal
04506975e5 Cleanup previous PR 2023-11-14 14:55:43 +05:30
Kovid Goyal
b5067c1369 Merge branch 'done-notification' of https://github.com/jinliu/kitty 2023-11-14 14:34:20 +05:30
Jin Liu
0f52b69372 launch watcher: add on_cmd_startstop event 2023-11-14 16:46:46 +08:00
Jin Liu
24bb28b773 Allow sending notification when a command finishes
When the option `notify_on_command_finish` is set, and a command
takes more than `notify_on_command_finish_min_duration` seconds
to execute, then when it finishes, send a desktop notification.

The value of `notify_on_command_finish` can be:
never | unfocused | invisible | always
the latter three are interpreted the same way as in the `o=` option
of the desktop notification protocol.
2023-11-14 16:46:38 +08:00
Kovid Goyal
553d833fd4 Merge branch 'dependabot/go_modules/all-go-deps-81e38e3cc5' of https://github.com/kovidgoyal/kitty 2023-11-13 08:45:40 +05:30
dependabot[bot]
2d5ce6191e Bump the all-go-deps group with 2 updates
Bumps the all-go-deps group with 2 updates: [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma) and [golang.org/x/image](https://github.com/golang/image).


Updates `github.com/alecthomas/chroma/v2` from 2.10.0 to 2.11.1
- [Release notes](https://github.com/alecthomas/chroma/releases)
- [Changelog](https://github.com/alecthomas/chroma/blob/master/.goreleaser.yml)
- [Commits](https://github.com/alecthomas/chroma/compare/v2.10.0...v2.11.1)

Updates `golang.org/x/image` from 0.13.0 to 0.14.0
- [Commits](https://github.com/golang/image/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: github.com/alecthomas/chroma/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 03:09:09 +00:00
Kovid Goyal
5fe77e38b7 ... 2023-11-13 01:10:38 +05:30
Kovid Goyal
9a08489112 Fix config file reloading not working is a system config file is set and no user config file is present at startup
Fixes #6801
2023-11-13 01:02:02 +05:30
Kovid Goyal
2047ea8eec Allow package build to complete without docs if user chose to skip building kitten 2023-11-12 08:16:26 +05:30
Kovid Goyal
4d510e3318 Fix searching for kitten to build man pages on macOS 2023-11-12 07:56:03 +05:30
Kovid Goyal
87f7bd2f9e See what's going on with finding kitten in CI 2023-11-11 20:11:40 +05:30
Kovid Goyal
2ffe03ee48 mypy again 2023-11-11 20:01:28 +05:30
Kovid Goyal
4c56e76840 Fix #6812 2023-11-11 20:00:46 +05:30
Kovid Goyal
a3c8f32c1a Fix Linux CI build 2023-11-11 17:36:10 +05:30
Kovid Goyal
176ffc7f51 ... 2023-11-11 17:14:09 +05:30
Kovid Goyal
70bc4f1033 Generate man pages for kitten and all its sub-commands recursively
Fixes #6808
2023-11-11 17:09:23 +05:30
Kovid Goyal
0f2196357c Make mypy happy 2023-11-11 16:07:18 +05:30
Kovid Goyal
2759ec1fe1 Add an option to setup.py to skip building kitten
Fixes #6809
2023-11-11 15:55:56 +05:30
Kovid Goyal
dee2e83fb4 Remove no longer needed monkeypatch 2023-11-11 13:44:34 +05:30
Kovid Goyal
65754a2032 ... 2023-11-11 08:45:39 +05:30
Kovid Goyal
77292a16d6 Make shebangs consistent
Follow PEP 0394 and use /usr/bin/env python so that the python in the
users venv is respected. Not that the kitty python files are meant to be
executed standalone anyway, but, whatever.

Fixes #6810
2023-11-11 08:32:05 +05:30
Kovid Goyal
2402c6f253 Fix failing tests 2023-11-10 08:56:22 +05:30
Kovid Goyal
77140fc798 Fix #6803 2023-11-10 08:49:33 +05:30
Kovid Goyal
cda97b5451 string changes 2023-11-08 19:35:02 +05:30
Kovid Goyal
b247fda672 version 0.31.0 2023-11-08 13:15:45 +05:30
Kovid Goyal
8dfe1fcca9 Ensure clenup is run even when ssh child is killed by interrupt 2023-11-06 22:02:06 +05:30
Kovid Goyal
a6f13a64dc Allow only printable ascii in echo 2023-11-06 21:28:25 +05:30
Kovid Goyal
bd5fcb00e0 Fix regression that broke quick exit from ssh kitten 2023-11-06 21:22:41 +05:30
Kovid Goyal
ac2ec44a7f python 3.10+ requires PY_SSIZE_T_CLEAN 2023-11-06 14:41:45 +05:30
Kovid Goyal
d2444bae80 Merge branch 'dependabot/go_modules/all-go-deps-32cfe409cb' of https://github.com/kovidgoyal/kitty 2023-11-06 09:20:13 +05:30
dependabot[bot]
a6571ba8db Bump the all-go-deps group with 2 updates
Bumps the all-go-deps group with 2 updates: [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `github.com/shirou/gopsutil/v3` from 3.23.9 to 3.23.10
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.9...v3.23.10)

Updates `golang.org/x/sys` from 0.13.0 to 0.14.0
- [Commits](https://github.com/golang/sys/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-go-deps
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 03:44:18 +00:00
Kovid Goyal
5fab30b36f Bump version of bundled python 2023-11-05 17:59:19 +05:30
Kovid Goyal
9a179a7e90 Add focus reporting capabilities to terminfo
See https://lists.gnu.org/archive/html/bug-ncurses/2023-10/msg00117.html
2023-11-05 15:00:13 +05:30
Kovid Goyal
bc1da5525e ssh kitten: Fix restore state not being called after interrupt 2023-11-05 08:38:04 +05:30
Kovid Goyal
995112d952 Add non-interactive options for paste sanitization 2023-11-04 07:34:46 +05:30
Kovid Goyal
169315d33d Improve paste sanitization
Replace C0 chars with their graphical equivalents and \n with \eE
which has the same visual effect. C1 chars are replaced by reverse
question mark.
2023-11-04 07:23:59 +05:30
Kovid Goyal
114b8dff51 ... 2023-11-03 20:01:33 +05:30
Kovid Goyal
61429c73c7 Wayland: Fix primary selections not working with the river compositor
Fixes #6785
2023-11-03 19:57:54 +05:30
Kovid Goyal
2aa37de6ff Only alias sudo if no systemwide terminfo db for xterm-kitty is found 2023-11-03 12:30:29 +05:30
Kovid Goyal
a54586dfa9 Add a note about dynamic config reload behavior of underline_hyperlinks 2023-11-03 09:12:17 +05:30
Kovid Goyal
b4f88b4f81 A new option to control when hyperlinks are underlined
While kitty is never going to underline detected URLs as the performance
of that is absurd, underlining hyperlinks specifically is acceptable,
since they dont require detection.

See #6766
2023-11-03 08:51:58 +05:30
Kovid Goyal
954b7f87a5 Add some docs on why no-sudo might be needed 2023-11-03 08:26:54 +05:30
Kovid Goyal
d113a6c2cf ssh kitten: Fix a regression that broken ctrl+space mapping in zsh
Fixes #6780
2023-11-03 07:16:07 +05:30
Kovid Goyal
52cebf0150 DRYer 2023-11-02 08:09:51 +05:30
Kovid Goyal
827a7d5094 Add a new interactive action to set the active window title 2023-11-02 08:05:49 +05:30
Kovid Goyal
a04d19df4a ... 2023-10-31 17:59:08 +05:30
Kovid Goyal
7e1580ef09 fish integration: Dont clobber user defined sudo function 2023-10-31 16:49:31 +05:30
Kovid Goyal
f3ece8b7c4 Update changelog 2023-10-31 16:29:04 +05:30
Kovid Goyal
be3b8fcfb7 Also use a function for sudo in fish to avoid the --edit issue 2023-10-31 16:27:21 +05:30
Kovid Goyal
9d5bb3b2f2 bash integration: Also make sudo a function
There is less need in bash since its sudo completion is not as buggy,
but it does fix the sudo --edit issue
2023-10-31 15:53:45 +05:30
Kovid Goyal
492ec3dfbf zsh integration: Use a function for sudo
This fixes sudo --edit and works around the zsh sudo completions bug:
https://www.zsh.org/mla/workers/2023/msg00983.html
2023-10-31 12:24:35 +05:30
Kovid Goyal
309a6e9319 ... 2023-10-31 11:50:34 +05:30
Kovid Goyal
12db4683ac Run local build before building docs 2023-10-31 06:18:23 +05:30
Kovid Goyal
30b736eed7 Merge branch 'override_warning' of https://github.com/joveian/kitty 2023-10-30 22:44:51 +05:30
joveian
4d085a00e1 Warn of possible graphics issues with text_fg_override_threshold
Issue #6767
2023-10-30 09:04:27 -07:00
Kovid Goyal
dfd84d85a2 Merge branch 'dependabot/go_modules/all-go-deps-9450db85af' of https://github.com/kovidgoyal/kitty 2023-10-30 08:46:48 +05:30
dependabot[bot]
cb139692f5 Bump the all-go-deps group with 2 updates
Bumps the all-go-deps group with 2 updates: [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma) and [github.com/google/uuid](https://github.com/google/uuid).


Updates `github.com/alecthomas/chroma/v2` from 2.9.1 to 2.10.0
- [Release notes](https://github.com/alecthomas/chroma/releases)
- [Changelog](https://github.com/alecthomas/chroma/blob/master/.goreleaser.yml)
- [Commits](https://github.com/alecthomas/chroma/compare/v2.9.1...v2.10.0)

Updates `github.com/google/uuid` from 1.3.1 to 1.4.0
- [Release notes](https://github.com/google/uuid/releases)
- [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/uuid/compare/v1.3.1...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/alecthomas/chroma/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
- dependency-name: github.com/google/uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 03:14:51 +00:00
Kovid Goyal
47836f5086 ... 2023-10-29 08:50:27 +05:30
Kovid Goyal
778adfcd3d Report invalid effective listen_on as a bad config error 2023-10-29 08:44:41 +05:30
Kovid Goyal
24d9d502b1 Set window title when showing errors 2023-10-29 08:24:08 +05:30
Kovid Goyal
8dadcf568c A bad listen_on value should not prevent startup
Ideally we should report the error more verbosely,
maybe someday when I have more time.
2023-10-28 19:40:43 +05:30
Kovid Goyal
0f02725f50 ... 2023-10-28 07:59:45 +05:30
Kovid Goyal
3beb1e454a Fix #6761 2023-10-27 21:54:13 +05:30
Kovid Goyal
c174c3cb38 ... 2023-10-27 15:49:37 +05:30
Kovid Goyal
f05a58f363 Note cursor movement behavior for relative placements in the spec 2023-10-27 15:43:15 +05:30
Kovid Goyal
9f42e915c8 Clarify relative placement spec 2023-10-27 15:38:56 +05:30
Kovid Goyal
52d5a4679f Graphics protocol: Support for positioning images relative to other images
Fixes #6617
2023-10-27 15:27:30 +05:30
Kovid Goyal
aee14a49f0 ... 2023-10-27 14:19:35 +05:30
Kovid Goyal
acf586867c Fix empty emoticons panel in unicode input kitten
Fixes #6760
2023-10-27 14:18:46 +05:30
Kovid Goyal
7cb392c7ab Use a hash table for images 2023-10-26 20:40:02 +05:30
Kovid Goyal
f8d5e30300 Use a hash table for image placements 2023-10-26 19:42:32 +05:30
Kovid Goyal
be5a0e8559 Same treatment for image and render data arrays 2023-10-26 16:29:13 +05:30
Kovid Goyal
7cffb2a714 Prepare for fast image/ref lookup via hashmap 2023-10-26 15:45:06 +05:30
Kovid Goyal
6111bc8ed6 Cleanup changelog 2023-10-26 09:00:37 +05:30
Kovid Goyal
1c1519c6e4 micro optimization 2023-10-25 18:41:27 +05:30
Kovid Goyal
b55883591d ... 2023-10-25 18:37:10 +05:30
Kovid Goyal
ae4a13b249 Better fix for macOS deadlock
Fix it in glfw. Dont hold the tick lock when calling the tick callback
as the tick callback might be waiting on a lock.
2023-10-25 18:32:07 +05:30
Kovid Goyal
61c4f80e90 Fix deadlock on macOS caused by recent support for pipe peers
Apparently on macOS we cant post an event to the main loop if the main loop is
waiting on a lock we are holding. Absurd.

Fixes #6751
2023-10-25 18:16:13 +05:30
Kovid Goyal
0ce996120a Allow o key to take effect in any chunk of OSC 99 2023-10-25 15:50:58 +05:30
Kovid Goyal
47b8b442dc Document when o key was added to desktop notifications spec 2023-10-25 15:42:57 +05:30
Kovid Goyal
32d23921df ... 2023-10-25 13:54:22 +05:30
Kovid Goyal
19374208e0 desktop notification protocol: Allow applications sending notifications to specify that the notification should only be displayed if the window is currently unfocused
Fixes #6755
2023-10-25 13:52:32 +05:30
Kovid Goyal
8c83284d5e Fix #6750 2023-10-25 12:14:36 +05:30
Kovid Goyal
9c25a183db On second thoughts dont use foreground process env vars for kitten @ ls
Since the purpose of the env vars is mostly to recognize windows the
original env vars make more sense. Also I dislike changing behavior for
no good reason.
2023-10-25 12:12:16 +05:30
Kovid Goyal
24895f0225 ... 2023-10-25 12:00:44 +05:30
Kovid Goyal
eefb865e6e kitten @ ls: Return environ of foreground process
This is needed on macOS where we now run the shell via login and we
aren't allowed to read the environ of login because its setuid.

Fixes #6749
2023-10-25 09:54:12 +05:30
Kovid Goyal
b1ec1c2678 ... 2023-10-24 18:39:28 +05:30
Kovid Goyal
ce583ea460 Render Private Use Unicode symbols using two cells if the second cell contains a non-breaking space as well as a normal space
There is some software out there that uses nbsp as a separator,
presumably as some kind of hack.

https://github.com/ibhagwan/fzf-lua/issues/916
2023-10-24 17:38:49 +05:30
Kovid Goyal
539a8706dc Update bundled harfbuzz version
The old version shows very poor perfromance shaping some fonts with
ligatures on macOS.

Fixes #6743
2023-10-24 16:39:29 +05:30
Kovid Goyal
467e7e5041 function to convert monotonic_t to microsecs 2023-10-24 16:38:17 +05:30
Kovid Goyal
d94a5bd386 Fix #6746 2023-10-24 07:21:30 +05:30
Kovid Goyal
480737a355 Merge branch 'dependabot/go_modules/all-go-deps-abad278ef8' of https://github.com/kovidgoyal/kitty 2023-10-23 08:50:15 +05:30
dependabot[bot]
d63739a598 Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/bmatcuk/doublestar/v4](https://github.com/bmatcuk/doublestar).

- [Release notes](https://github.com/bmatcuk/doublestar/releases)
- [Commits](https://github.com/bmatcuk/doublestar/compare/v4.6.0...v4.6.1)

---
updated-dependencies:
- dependency-name: github.com/bmatcuk/doublestar/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 03:19:21 +00:00
Kovid Goyal
3526e59d3b Fix stripping of escape codes not stripping \r when bracketed paste is not active 2023-10-21 08:15:15 +05:30
Kovid Goyal
7292d1c9df Clean up mouse-demo kitten
Fixes #6738
2023-10-21 07:55:23 +05:30
Kovid Goyal
c9a95cacd9 ... 2023-10-20 18:24:21 +05:30
Kovid Goyal
8853f6bae2 Consider \r dangerous without bracketed paste 2023-10-20 13:38:35 +05:30
Kovid Goyal
beb18cc250 Add window titles to various ask kitten invocations 2023-10-20 13:36:02 +05:30
Kovid Goyal
321f1a6650 Nicer formatting for paste sanitization confirmation message 2023-10-20 13:22:58 +05:30
Kovid Goyal
8d8d89573c ... 2023-10-20 13:14:25 +05:30
Kovid Goyal
89ee128a92 ... 2023-10-20 13:05:21 +05:30
Kovid Goyal
defa2e29ac Always ask for confirmation when pasting text with control codes in it 2023-10-20 13:02:28 +05:30
Kovid Goyal
56963c693e When pasting in bracketed paste mode and the cursor is at a shell prompt, strip out C0 control codes
Some shells incorrectly interpret these allowing escape from bracketed paste mode. Thanks to David Leadbetter for discovering.
2023-10-20 12:17:13 +05:30
Kovid Goyal
f098240ace ... 2023-10-20 08:43:45 +05:30
Kovid Goyal
4b997a961c A new option single_window_padding_width to use a different padding when only a single window is visible
Fixes #6734
2023-10-20 08:37:45 +05:30
Kovid Goyal
512a672398 ... 2023-10-19 08:12:04 +05:30
Kovid Goyal
6cfb451ec8 Two new event types for watchers
on_title_change and on_set_user_var
2023-10-19 07:54:33 +05:30
Kovid Goyal
4a463f7712 More kitty @ -> kitten @ 2023-10-18 21:16:12 +05:30
Kovid Goyal
5ea9700c82 More kitty @ -> kitten @ 2023-10-18 20:40:39 +05:30
Kovid Goyal
1332cf8ac7 Create an easy to use alias for running remote control scripts 2023-10-18 20:29:50 +05:30
Kovid Goyal
f8ab5f3f67 ... 2023-10-18 20:15:05 +05:30
Kovid Goyal
822311d523 Change kitty @ to kitten @ in the docs 2023-10-18 20:13:49 +05:30
Kovid Goyal
713569fcfa Advertise the ability to run remote control scripts without turning on remote control 2023-10-18 20:10:17 +05:30
Kovid Goyal
7d32a77fe4 ... 2023-10-18 20:00:41 +05:30
Kovid Goyal
314fe4fe4a Allow launched background process to work with --allow-remote-control
Use a dedicated socketpair for such processes. Fixes #6712
2023-10-18 19:56:58 +05:30
Kovid Goyal
a9b412baba Fix a regression that broke kitten update-self
Fixes #6729
2023-10-18 19:19:35 +05:30
Kovid Goyal
0300a355d0 update docs for remote_kitty 2023-10-18 17:31:44 +05:30
Kovid Goyal
fa53ac7896 Fix deprecation warning for compositing operation 2023-10-18 06:12:31 +05:30
Kovid Goyal
cb15b98afd Add presenterm to the list of integrations 2023-10-17 21:52:18 +05:30
Kovid Goyal
6a50af12d3 Make set_pointer_shapes private 2023-10-17 21:47:03 +05:30
Kovid Goyal
45a98b19c5 Mention that pointer shapes can be demo-ed with the mouse_demo kitten 2023-10-17 21:17:45 +05:30
Kovid Goyal
e9e1a7a7c3 Fix the diagonal resize shapes on Linux 2023-10-17 21:15:20 +05:30
Kovid Goyal
6804d16519 Show pointer shapes in mouse_demo kitten 2023-10-17 21:07:57 +05:30
Kovid Goyal
ee8399ba56 Port the mouse_demo kitten to Go 2023-10-17 20:21:22 +05:30
Kovid Goyal
c03dff2322 Fix help text and short desc for the two wrapper kittens 2023-10-17 19:50:47 +05:30
Kovid Goyal
dc6edf9191 Improve the docs for how to match multi-line hints
See #6692
2023-10-17 15:23:58 +05:30
Kovid Goyal
70a588cb36 ... 2023-10-17 15:23:43 +05:30
Kovid Goyal
81b032a161 Dont expand cwd=current in rc launch
This is easily done at the command line. And its semantics are
are to refer to cwd of active window.
2023-10-17 05:01:28 +05:30
Kovid Goyal
ddb121b418 Remote control launch: Fix the --copy-env option not copying current environment variables
Fixes #6724
2023-10-16 22:32:51 +05:30
Kovid Goyal
d2026574b8 Add a sentence emphasizing the pointer shapes are independent of mouse reporting 2023-10-16 20:36:09 +05:30
Kovid Goyal
187fa996f8 Add the cell pointer shape 2023-10-16 20:33:12 +05:30
Kovid Goyal
870522a792 Merge branch 'dependabot/go_modules/all-go-deps-6213d6d4c1' of https://github.com/kovidgoyal/kitty 2023-10-16 08:53:53 +05:30
dependabot[bot]
5478f6665a Bump the all-go-deps group with 1 update
Bumps the all-go-deps group with 1 update: [github.com/google/go-cmp](https://github.com/google/go-cmp).

- [Release notes](https://github.com/google/go-cmp/releases)
- [Commits](https://github.com/google/go-cmp/compare/v0.5.9...v0.6.0)

---
updated-dependencies:
- dependency-name: github.com/google/go-cmp
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 03:20:56 +00:00
Kovid Goyal
5d5bbe9b96 Add a paragraph on legacy xterm compat for pointer shapes 2023-10-15 21:59:04 +05:30
Kovid Goyal
3a6c7e78df Note when support for pointer shapes was added 2023-10-15 21:51:10 +05:30
Kovid Goyal
10a2f246bc ... 2023-10-15 21:48:57 +05:30
Kovid Goyal
17ce474b79 Use hand pointer when hovering over buttons in ask kitten 2023-10-15 21:35:51 +05:30
Kovid Goyal
d66074f19f Add pointer shape enum to kittens 2023-10-15 21:03:41 +05:30
Kovid Goyal
1693107608 A new escape code to change the shape of the mouse pointer
Fixes #6711
2023-10-15 19:57:36 +05:30
Kovid Goyal
e15b16b072 Mention behavior of focus_follows_mouse in docs on macOS 2023-10-15 14:25:16 +05:30
Kovid Goyal
9375e671bc dedup choice literals 2023-10-15 10:10:05 +05:30
Kovid Goyal
0e11174aa5 We require python 3.8 so no need to guard typing.Literal 2023-10-15 09:58:19 +05:30
Kovid Goyal
baddc966dc Ignore long lines in another generated file 2023-10-15 09:57:58 +05:30
Kovid Goyal
119582a9d4 Make relative imports work in gen scripts even when directly executed 2023-10-15 09:51:03 +05:30
Kovid Goyal
792b74503c Implement mouse shape support for macOS
Code for loading hidden system cursors not available via NCursor comes
from the SDL library, with thanks.
2023-10-15 09:42:06 +05:30
Kovid Goyal
4f1971c480 Rationalize mouse cursor shape handling
Now can use the full range of standard mouse cursor shapes similar to
those supported by browsers via the CSS cursor property.

Still needs to be fully implemented for cocoa backend.
2023-10-15 09:17:31 +05:30
Kovid Goyal
a8a1571ed1 Fix #6715 2023-10-14 08:49:46 +05:30
Kovid Goyal
a79dd3996a Also move data files for gen scripts into gen dir 2023-10-14 08:04:37 +05:30
Kovid Goyal
e6ef2fceea py3.8 support 2023-10-14 07:57:03 +05:30
Kovid Goyal
56063b96fd Move gen scripts into their own package 2023-10-14 07:44:18 +05:30
Kovid Goyal
cae19bba60 ... 2023-10-14 06:05:32 +05:30
Kovid Goyal
1f91250a40 Fix trailing bracket not ignored when detecting a multi-line URL with the trailing bracket as the first character on the last line
Fixes #6710
2023-10-13 10:44:58 +05:30
Kovid Goyal
ee1e65e619 Remove pre python 3.8 compat shim as we now require 3.8 2023-10-12 20:40:33 +05:30
Kovid Goyal
00dc5a8dc5 Fix a regression caused by rewrite of kittens to Go that made various kittens reset colors in a terminal when the colors were changed by escape code
Fixes #6708
2023-10-12 20:19:28 +05:30
Kovid Goyal
4d230f5035 Fix #6695 2023-10-10 09:38:52 +05:30
Kovid Goyal
73bc6e4bfc ... 2023-10-10 06:10:19 +05:30
Kovid Goyal
b78264183f Centralize freeing of opts object allocs 2023-10-10 06:08:28 +05:30
Kovid Goyal
455d0a6048 Dont show hidden sub-commands during completion 2023-10-10 05:41:27 +05:30
Kovid Goyal
5d0dabe51c completion: match exe on basename alone 2023-10-10 05:22:40 +05:30
Kovid Goyal
16e7ca3a95 kitten @ set-background-opacity --toggle
Fixes #6691
2023-10-10 05:04:50 +05:30
Kovid Goyal
70f3909cdc Add background_opacity to @ ls output 2023-10-10 04:54:27 +05:30
Kovid Goyal
f73d32e15d A new option menu_map that allows adding entries to the global menubar on macOS 2023-10-09 19:47:25 +05:30
Kovid Goyal
3338e4fb25 ... 2023-10-09 15:28:16 +05:30
Kovid Goyal
726d4ca9bc Typecheck map_type 2023-10-09 11:56:25 +05:30
Kovid Goyal
32b7be2201 Proper fix for braindead macOS login
Always run it in the home dir as it seems to expect that. Change the
working dir after running login
2023-10-09 11:29:32 +05:30
Kovid Goyal
dc26db7759 Merge branch 'dependabot/go_modules/all-go-deps-92d01672c5' of https://github.com/kovidgoyal/kitty 2023-10-09 09:12:37 +05:30
dependabot[bot]
8fd5b62560 Bump the all-go-deps group with 2 updates
Bumps the all-go-deps group with 2 updates: [golang.org/x/image](https://github.com/golang/image) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/image` from 0.12.0 to 0.13.0
- [Commits](https://github.com/golang/image/compare/v0.12.0...v0.13.0)

Updates `golang.org/x/sys` from 0.12.0 to 0.13.0
- [Commits](https://github.com/golang/sys/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-09 03:37:48 +00:00
Kovid Goyal
619d4e3dc4 Run login on macOS with -q
Fixes #6689
2023-10-09 07:05:43 +05:30
Kovid Goyal
f03027c33d Merge branch 'nolto' of https://github.com/bmwiedemann/kitty 2023-10-08 08:33:05 +05:30
Kovid Goyal
a95dc0ceb8 Merge branch 'reproducible' of https://github.com/bmwiedemann/kitty 2023-10-08 08:27:21 +05:30
Bernhard M. Wiedemann
17b7703dab Fix compilation without LTO
When building without link-time-optimization through the
KITTY_NO_LTO env var or the setup.py --disable-link-time-optimization option
compilation failed with a warning about freeing "ans" memory.

Chances are, this is dead code that gets optimized out by LTO.
2023-10-08 04:52:24 +02:00
Bernhard M. Wiedemann
50968c12b1 Make build reproducible
This needs 3 fixes:
* for an ordering issue in docs_ref_map_generated.h
* for a filesystem-order issue in uniforms_generated.h
* to normalize mtimes in the data_generated.bin tar

This patch was done while working on reproducible builds for openSUSE.
2023-10-08 04:48:51 +02:00
Kovid Goyal
edb9c924fe Note that fzf now supports the kitty graphics protocol for image previews 2023-10-08 07:22:54 +05:30
Kovid Goyal
805bc499ee Fix documentation of word_and_line_from_point 2023-10-06 10:01:24 +05:30
Kovid Goyal
baa0270ef3 Merge branch 'mouse-selection-line-from-word-feature' of https://github.com/warpfork/kitty 2023-10-06 09:43:07 +05:30
Eric Myhre
d310acc780 Add word-and-line-from-point feature to possible mouse selection actions. 2023-10-05 17:47:53 +02:00
391 changed files with 24418 additions and 5726 deletions

6
.gitattributes vendored
View File

@@ -16,11 +16,17 @@ kittens/diff/options/types.py linguist-generated=true
kittens/diff/options/parse.py linguist-generated=true
glfw/*.c linguist-vendored=true
glfw/*.h linguist-vendored=true
3rdparty/** linguist-vendored=true
kittens/unicode_input/names.h linguist-generated=true
tools/wcswidth/std.go linguist-generated=true
tools/unicode_names/names.txt linguist-generated=true
terminfo/kitty.term* linguist-generated=true
terminfo/x/* linguist-generated=true
*_generated.h linguist-generated=true
*_generated.go linguist-generated=true
*_generated_test.go linguist-generated=true
*_generated_test.s linguist-generated=true
*_generated.s linguist-generated=true
*.py text diff=python
*.m text diff=objc

View File

@@ -2,6 +2,7 @@
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
import glob
import io
import os
import shlex
@@ -9,6 +10,7 @@ import shutil
import subprocess
import sys
import tarfile
import time
from urllib.request import urlopen
BUNDLE_URL = 'https://download.calibre-ebook.com/ci/kitty/{}-64.tar.xz'
@@ -17,14 +19,44 @@ is_macos = 'darwin' in sys.platform.lower()
SW = None
def run(*a):
def do_print_crash_reports():
print('Printing available crash reports...')
if is_macos:
end_time = time.monotonic() + 90
while time.monotonic() < end_time:
time.sleep(1)
items = glob.glob(os.path.join(os.path.expanduser('~/Library/Logs/DiagnosticReports'), 'kitty-*.ips'))
if items:
break
if items:
time.sleep(1)
print(os.path.basename(items[0]))
sdir = os.path.dirname(os.path.abspath(__file__))
subprocess.check_call([sys.executable, os.path.join(sdir, 'macos_crash_report.py'), items[0]])
else:
run('sh -c "echo bt | coredumpctl debug"')
print(flush=True)
def run(*a, print_crash_reports=False):
if len(a) == 1:
a = shlex.split(a[0])
print(' '.join(map(shlex.quote, a)))
cmd = ' '.join(map(shlex.quote, a))
print(cmd)
sys.stdout.flush()
ret = subprocess.Popen(a).wait()
if ret != 0:
raise SystemExit(ret)
if ret < 0:
import signal
try:
sig = signal.Signals(-ret)
except ValueError:
pass
else:
if print_crash_reports:
do_print_crash_reports()
raise SystemExit(f'The following process was killed by signal: {sig.name}:\n{cmd}')
raise SystemExit(f'The following process failed with exit code: {ret}:\n{cmd}')
def install_deps():
@@ -37,13 +69,13 @@ def install_deps():
import ssl
if ssl.OPENSSL_VERSION_INFO[0] == 1:
openssl += '@1.1'
run('brew', 'install', 'fish', openssl, *items)
run('brew', 'install', 'fish', 'simde', openssl, *items)
else:
run('sudo apt-get update')
run('sudo apt-get install -y libgl1-mesa-dev libxi-dev libxrandr-dev libxinerama-dev ca-certificates'
' libxcursor-dev libxcb-xkb-dev libdbus-1-dev libxkbcommon-dev libharfbuzz-dev libx11-xcb-dev zsh'
' libpng-dev liblcms2-dev libfontconfig-dev libxkbcommon-x11-dev libcanberra-dev libxxhash-dev uuid-dev'
' zsh bash dash')
' libsimde-dev zsh bash dash systemd-coredump gdb')
# for some reason these directories are world writable which causes zsh
# compinit to break
run('sudo chmod -R og-w /usr/share/zsh')
@@ -59,13 +91,18 @@ def install_deps():
def build_kitty():
python = shutil.which('python3') if is_bundle else sys.executable
cmd = f'{python} setup.py build --verbose'
if is_macos:
cmd += ' --debug' # for better crash report to debug SIGILL issue
if os.environ.get('KITTY_SANITIZE') == '1':
cmd += ' --debug --sanitize'
run(cmd)
def test_kitty():
run('./test.py')
if is_macos:
run('ulimit -c unlimited')
run('sudo chmod -R 777 /cores')
run('./test.py', print_crash_reports=True)
def package_kitty():

View File

@@ -2,7 +2,7 @@ name: CI
on: [push, pull_request]
env:
CI: 'true'
ASAN_OPTIONS: leak_check_at_exit=0
ASAN_OPTIONS: detect_leaks=0
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8

450
.github/workflows/macos_crash_report.py vendored Executable file
View File

@@ -0,0 +1,450 @@
#!/usr/bin/env python
# License: GPLv3 Copyright: 2024, Kovid Goyal <kovid at kovidgoyal.net>
import json
import posixpath
import sys
from collections import namedtuple
from datetime import datetime
from enum import Enum
from functools import cached_property
from typing import IO, List, Mapping, Optional
Frame = namedtuple('Frame', 'image_name image_base image_offset symbol symbol_offset')
Register = namedtuple('Register', 'name value')
def surround(x: str, start: int, end: int) -> str:
if sys.stdout.isatty():
x = f'\033[{start}m{x}\033[{end}m'
return x
def cyan(x: str) -> str:
return surround(x, 96, 39)
def bold(x: str) -> str:
return surround(x, 1, 22)
class BugType(Enum):
WatchdogTimeout = '28'
BasebandStats = '195'
GPUEvent = '284'
Sandbox = '187'
TerminatingStackshot = '509'
ServiceWatchdogTimeout = '29'
Session = '179'
LegacyStackshot = '188'
MACorrelation = '197'
iMessages = '189'
log_power = '278'
PowerLog = 'powerlog'
DuetKnowledgeCollector2 = '58'
BridgeRestore = '83'
LegacyJetsam = '198'
ExcResource_385 = '385'
Modem = '199'
Stackshot = '288'
SystemInformation = 'system_profile'
Jetsam_298 = '298'
MemoryResource = '30'
Bridge = '31'
DifferentialPrivacy = 'diff_privacy'
FirmwareIntegrity = '32'
CoreAnalytics_33 = '33'
AutoBugCapture = '34'
EfiFirmwareIntegrity = '35'
SystemStats = '36'
AnonSystemStats = '37'
Crash_9 = '9'
Jetsam_98 = '98'
LDCM = '100'
Panic_10 = '10'
Spin = '11'
CLTM = '101'
Hang = '12'
Panic_110 = '110'
ConnectionFailure = '13'
MessageTracer = '14'
LowBattery = '120'
Siri = '201'
ShutdownStall = '17'
Panic_210 = '210'
SymptomsCPUUsage = '202'
AssumptionViolation = '18'
CoreHandwriting = 'chw'
IOMicroStackShot = '44'
CoreAnalytics_211 = '211'
SiriAppPrediction = '203'
spin_45 = '45'
PowerMicroStackshots = '220'
BTMetadata = '212'
SystemMemoryReset = '301'
ResetCount = '115'
AutoBugCapture_204 = '204'
WifiCrashBinary = '221'
MicroRunloopHang = '310'
Rosetta = '213'
glitchyspin = '302'
System = '116'
IOPowerSources = '141'
PanicStats = '205'
PowerLog_230 = '230'
LongRunloopHang = '222'
HomeProductsAnalytics = '311'
DifferentialPrivacy_150 = '150'
Rhodes = '214'
ProactiveEventTrackerTransparency = '303'
WiFi = '117'
SymptomsCPUWakes = '142'
SymptomsCPUUsageFatal = '206'
Crash_109 = '109'
ShortRunloopHang = '223'
CoreHandwriting_231 = '231'
ForceReset = '151'
SiriAppSelection = '215'
PrivateFederatedLearning = '304'
Bluetooth = '118'
SCPMotion = '143'
HangSpin = '207'
StepCount = '160'
RTCTransparency = '224'
DiagnosticRequest = '312'
MemorySnapshot = '152'
Rosetta_B = '216'
AudioAccessory = '305'
General = '119'
HotSpotIOMicroSS = '144'
GeoServicesTransparency = '233'
MotionState = '161'
AppStoreTransparency = '225'
SiriSearchFeedback = '313'
BearTrapReserved = '153'
Portrait = '217'
AWDMetricLog = 'metriclog'
SymptomsIO = '145'
SubmissionReserved = '170'
WifiCrash = '209'
Natalies = '162'
SecurityTransparency = '226'
BiomeMapReduce = '234'
MemoryGraph = '154'
MultichannelAudio = '218'
honeybee_payload = '146'
MesaReserved = '171'
WifiSensing = '235'
SiriMiss = '163'
ExcResourceThreads_227 = '227'
TestA = 'T01'
NetworkUsage = '155'
WifiReserved = '180'
SiriActionPrediction = '219'
honeybee_heartbeat = '147'
ECCEvent = '172'
KeyTransparency = '236'
SubDiagHeartBeat = '164'
ThirdPartyHang = '228'
OSFault = '308'
CoreTime = '156'
WifiDriverReserved = '181'
Crash_309 = '309'
honeybee_issue = '148'
CellularPerfReserved = '173'
TestB = 'T02'
StorageStatus = '165'
SiriNotificationTransparency = '229'
TestC = 'T03'
CPUMicroSS = '157'
AccessoryUpdate = '182'
xprotect = '20'
MultitouchFirmware = '149'
MicroStackshot = '174'
AppLaunchDiagnostics = '238'
KeyboardAccuracy = '166'
GPURestart = '21'
FaceTime = '191'
DuetKnowledgeCollector = '158'
OTASUpdate = '183'
ExcResourceThreads_327 = '327'
ExcResource_22 = '22'
DuetDB = '175'
ThirdPartyHangDeveloper = '328'
PrivacySettings = '167'
GasGauge = '192'
MicroStackShots = '23'
BasebandCrash = '159'
GPURestart_184 = '184'
SystemWatchdogCrash = '409'
FlashStatus = '176'
SleepWakeFailure = '24'
CarouselEvent = '168'
AggregateD = '193'
WakeupsMonitorViolation = '25'
DifferentialPrivacy_50 = '50'
ExcResource_185 = '185'
UIAutomation = '177'
ping = '26'
SiriTransaction = '169'
SURestore = '194'
KtraceStackshot = '186'
WirelessDiagnostics = '27'
PowerLogLite = '178'
SKAdNetworkAnalytics = '237'
HangWorkflowResponsiveness = '239'
CompositorClientHang = '243'
class CrashReportBase:
def __init__(self, metadata: Mapping, data: str, filename: str = None):
self.filename = filename
self._metadata = metadata
self._data = data
self._parse()
def _parse(self):
self._is_json = False
try:
modified_data = self._data
if '\n \n' in modified_data:
modified_data, rest = modified_data.split('\n \n', 1)
rest = '",' + rest.split('",', 1)[1]
modified_data += rest
self._data = json.loads(modified_data)
self._is_json = True
except json.decoder.JSONDecodeError:
pass
@cached_property
def bug_type(self) -> BugType:
return BugType(self.bug_type_str)
@cached_property
def bug_type_str(self) -> str:
return self._metadata['bug_type']
@cached_property
def incident_id(self):
return self._metadata.get('incident_id')
@cached_property
def timestamp(self) -> datetime:
timestamp = self._metadata.get('timestamp')
timestamp_without_timezone = timestamp.rsplit(' ', 1)[0]
return datetime.strptime(timestamp_without_timezone, '%Y-%m-%d %H:%M:%S.%f')
@cached_property
def name(self) -> str:
return self._metadata.get('name')
def __repr__(self) -> str:
filename = ''
if self.filename:
filename = f'FILENAME:{posixpath.basename(self.filename)} '
return f'<{self.__class__} {filename}TIMESTAMP:{self.timestamp}>'
def __str__(self) -> str:
filename = ''
if self.filename:
filename = self.filename
return cyan(f'{self.incident_id} {self.timestamp}\n{filename}\n\n')
class UserModeCrashReport(CrashReportBase):
def _parse_field(self, name: str) -> str:
name += ':'
for line in self._data.split('\n'):
if line.startswith(name):
field = line.split(name, 1)[1]
field = field.strip()
return field
@cached_property
def faulting_thread(self) -> int:
if self._is_json:
return self._data['faultingThread']
else:
return int(self._parse_field('Triggered by Thread'))
@cached_property
def frames(self) -> List[Frame]:
result = []
if self._is_json:
thread_index = self.faulting_thread
images = self._data['usedImages']
for frame in self._data['threads'][thread_index]['frames']:
image = images[frame['imageIndex']]
result.append(
Frame(image_name=image.get('path'), image_base=image.get('base'), symbol=frame.get('symbol'),
image_offset=frame.get('imageOffset'), symbol_offset=frame.get('symbolLocation')))
else:
in_frames = False
for line in self._data.split('\n'):
if in_frames:
splitted = line.split()
if len(splitted) == 0:
break
assert splitted[-2] == '+'
image_base = splitted[-3]
if image_base.startswith('0x'):
result.append(Frame(image_name=splitted[1], image_base=int(image_base, 16), symbol=None,
image_offset=int(splitted[-1]), symbol_offset=None))
else:
# symbolicated
result.append(Frame(image_name=splitted[1], image_base=None, symbol=image_base,
image_offset=None, symbol_offset=int(splitted[-1])))
if line.startswith(f'Thread {self.faulting_thread} Crashed:'):
in_frames = True
return result
@cached_property
def registers(self) -> List[Register]:
result = []
if self._is_json:
thread_index = self._data['faultingThread']
thread_state = self._data['threads'][thread_index]['threadState']
if 'x' in thread_state:
for i, reg_x in enumerate(thread_state['x']):
result.append(Register(name=f'x{i}', value=reg_x['value']))
for i, (name, value) in enumerate(thread_state.items()):
if name == 'x':
for j, reg_x in enumerate(value):
result.append(Register(name=f'x{j}', value=reg_x['value']))
else:
if isinstance(value, dict):
result.append(Register(name=name, value=value['value']))
else:
in_frames = False
for line in self._data.split('\n'):
if in_frames:
splitted = line.split()
if len(splitted) == 0:
break
for i in range(0, len(splitted), 2):
register_name = splitted[i]
if not register_name.endswith(':'):
break
register_name = register_name[:-1]
register_value = int(splitted[i + 1], 16)
result.append(Register(name=register_name, value=register_value))
if line.startswith(f'Thread {self.faulting_thread} crashed with ARM Thread State'):
in_frames = True
return result
@cached_property
def exception_type(self):
if self._is_json:
return self._data['exception'].get('type')
else:
return self._parse_field('Exception Type')
@cached_property
def exception_subtype(self) -> Optional[str]:
if self._is_json:
return self._data['exception'].get('subtype')
else:
return self._parse_field('Exception Subtype')
@cached_property
def application_specific_information(self) -> Optional[str]:
result = ''
if self._is_json:
asi = self._data.get('asi')
if asi is None:
return None
return asi
else:
in_frames = False
for line in self._data.split('\n'):
if in_frames:
line = line.strip()
if len(line) == 0:
break
result += line + '\n'
if line.startswith('Application Specific Information:'):
in_frames = True
result = result.strip()
if not result:
return None
return result
def __str__(self) -> str:
result = super().__str__()
result += bold(f'Exception: {self.exception_type}\n')
if self.exception_subtype:
result += bold('Exception Subtype: ')
result += f'{self.exception_subtype}\n'
if self.application_specific_information:
result += bold('Application Specific Information: ')
result += str(self.application_specific_information)
result += '\n'
result += bold('Registers:')
for i, register in enumerate(self.registers):
if i % 4 == 0:
result += '\n'
result += f'{register.name} = 0x{register.value:016x} '.rjust(30)
result += '\n\n'
result += bold('Frames:\n')
for frame in self.frames:
image_base = '_HEADER'
if frame.image_base is not None:
image_base = f'0x{frame.image_base:x}'
result += f'\t[{frame.image_name}] {image_base}'
if frame.image_offset:
result += f' + 0x{frame.image_offset:x}'
if frame.symbol is not None:
result += f' ({frame.symbol} + 0x{frame.symbol_offset:x})'
result += '\n'
return result
def get_crash_report_from_file(crash_report_file: IO) -> CrashReportBase:
metadata = json.loads(crash_report_file.readline())
try:
bug_type = BugType(metadata['bug_type'])
except ValueError:
return CrashReportBase(metadata, crash_report_file.read(), crash_report_file.name)
bug_type_parsers = {
BugType.Crash_109: UserModeCrashReport,
BugType.Crash_309: UserModeCrashReport,
BugType.ExcResourceThreads_327: UserModeCrashReport,
BugType.ExcResource_385: UserModeCrashReport,
}
parser = bug_type_parsers.get(bug_type)
if parser is None:
return CrashReportBase(metadata, crash_report_file.read(), crash_report_file.name)
return parser(metadata, crash_report_file.read(), crash_report_file.name)
if __name__ == '__main__':
with open(sys.argv[-1]) as f:
print(get_crash_report_from_file(f))

4
.gitignore vendored
View File

@@ -4,6 +4,9 @@
*.bin
*_stub.pyi
*_generated.go
*_generated.s
*_generated_test.go
*_generated_test.s
*_generated.h
/.dmypy.json
/dependencies
@@ -18,6 +21,7 @@ __pycache__/
/glfw/wayland-*-client-protocol.[ch]
/docs/_build/
/docs/generated/
/tools/simdstring/simdstring.test
/.mypy_cache
/.ruff_cache
.DS_Store

28
3rdparty/base64/LICENSE vendored Normal file
View File

@@ -0,0 +1,28 @@
Copyright (c) 2005-2007, Nick Galbreath
Copyright (c) 2015-2018, Wojciech Muła
Copyright (c) 2016-2017, Matthieu Darbois
Copyright (c) 2013-2022, Alfred Klomp
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
HOLDER 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.

491
3rdparty/base64/README.md vendored Normal file
View File

@@ -0,0 +1,491 @@
# Fast Base64 stream encoder/decoder
[![Build Status](https://github.com/aklomp/base64/actions/workflows/test.yml/badge.svg)](https://github.com/aklomp/base64/actions/workflows/test.yml)
This is an implementation of a base64 stream encoding/decoding library in C99
with SIMD (AVX2, AVX512, NEON, AArch64/NEON, SSSE3, SSE4.1, SSE4.2, AVX) and
[OpenMP](http://www.openmp.org) acceleration. It also contains wrapper functions
to encode/decode simple length-delimited strings. This library aims to be:
- FAST;
- easy to use;
- elegant.
On x86, the library does runtime feature detection. The first time it's called,
the library will determine the appropriate encoding/decoding routines for the
machine. It then remembers them for the lifetime of the program. If your
processor supports AVX2, SSSE3, SSE4.1, SSE4.2 or AVX instructions, the library
will pick an optimized codec that lets it encode/decode 12 or 24 bytes at a
time, which gives a speedup of four or more times compared to the "plain"
bytewise codec.
AVX512 support is only for encoding at present, utilizing the AVX512 VL and VBMI
instructions. Decoding part reused AVX2 implementations. For CPUs later than
Cannonlake (manufactured in 2018) supports these instructions.
NEON support is hardcoded to on or off at compile time, because portable
runtime feature detection is unavailable on ARM.
Even if your processor does not support SIMD instructions, this is a very fast
library. The fallback routine can process 32 or 64 bits of input in one round,
depending on your processor's word width, which still makes it significantly
faster than naive bytewise implementations. On some 64-bit machines, the 64-bit
routines even outperform the SSSE3 ones.
To the author's knowledge, at the time of original release, this was the only
Base64 library to offer SIMD acceleration. The author wrote
[an article](http://www.alfredklomp.com/programming/sse-base64) explaining one
possible SIMD approach to encoding/decoding Base64. The article can help figure
out what the code is doing, and why.
Notable features:
- Really fast on x86 and ARM systems by using SIMD vector processing;
- Can use [OpenMP](http://www.openmp.org) for even more parallel speedups;
- Really fast on other 32 or 64-bit platforms through optimized routines;
- Reads/writes blocks of streaming data;
- Does not dynamically allocate memory;
- Valid C99 that compiles with pedantic options on;
- Re-entrant and threadsafe;
- Unit tested;
- Uses Duff's Device.
## Acknowledgements
The original AVX2, NEON and Aarch64/NEON codecs were generously contributed by
[Inkymail](https://github.com/inkymail/base64), who, in their fork, also
implemented some additional features. Their work is slowly being backported
into this project.
The SSSE3 and AVX2 codecs were substantially improved by using some very clever
optimizations described by Wojciech Muła in a
[series](http://0x80.pl/notesen/2016-01-12-sse-base64-encoding.html) of
[articles](http://0x80.pl/notesen/2016-01-17-sse-base64-decoding.html).
His own code is [here](https://github.com/WojciechMula/toys/tree/master/base64).
The AVX512 encoder is based on code from Wojciech Muła's
[base64simd](https://github.com/WojciechMula/base64simd) library.
The OpenMP implementation was added by Ferry Toth (@htot) from [Exalon Delft](http://www.exalondelft.nl).
## Building
The `lib` directory contains the code for the actual library.
Typing `make` in the toplevel directory will build `lib/libbase64.o` and `bin/base64`.
The first is a single, self-contained object file that you can link into your own project.
The second is a standalone test binary that works similarly to the `base64` system utility.
The matching header file needed to use this library is in `include/libbase64.h`.
To compile just the "plain" library without SIMD codecs, type:
```sh
make lib/libbase64.o
```
Optional SIMD codecs can be included by specifying the `AVX2_CFLAGS`, `AVX512_CFLAGS`,
`NEON32_CFLAGS`, `NEON64_CFLAGS`, `SSSE3_CFLAGS`, `SSE41_CFLAGS`, `SSE42_CFLAGS` and/or `AVX_CFLAGS` environment variables.
A typical build invocation on x86 looks like this:
```sh
AVX2_CFLAGS=-mavx2 SSSE3_CFLAGS=-mssse3 SSE41_CFLAGS=-msse4.1 SSE42_CFLAGS=-msse4.2 AVX_CFLAGS=-mavx make lib/libbase64.o
```
### AVX2
To build and include the AVX2 codec, set the `AVX2_CFLAGS` environment variable to a value that will turn on AVX2 support in your compiler, typically `-mavx2`.
Example:
```sh
AVX2_CFLAGS=-mavx2 make
```
### AVX512
To build and include the AVX512 codec, set the `AVX512_CFLAGS` environment variable to a value that will turn on AVX512 support in your compiler, typically `-mavx512vl -mavx512vbmi`.
Example:
```sh
AVX512_CFLAGS="-mavx512vl -mavx512vbmi" make
```
The codec will only be used if runtime feature detection shows that the target machine supports AVX2.
### SSSE3
To build and include the SSSE3 codec, set the `SSSE3_CFLAGS` environment variable to a value that will turn on SSSE3 support in your compiler, typically `-mssse3`.
Example:
```sh
SSSE3_CFLAGS=-mssse3 make
```
The codec will only be used if runtime feature detection shows that the target machine supports SSSE3.
### NEON
This library includes two NEON codecs: one for regular 32-bit ARM and one for the 64-bit AArch64 with NEON, which has double the amount of SIMD registers and can do full 64-byte table lookups.
These codecs encode in 48-byte chunks and decode in massive 64-byte chunks, so they had to be augmented with an uint32/64 codec to stay fast on smaller inputs!
Use LLVM/Clang for compiling the NEON codecs.
The code generation of at least GCC 4.6 (the version shipped with Raspbian and used for testing) contains a bug when compiling `vstq4_u8()`, and the generated assembly code is of low quality.
NEON intrinsics are a known weak area of GCC.
Clang does a better job.
NEON support can unfortunately not be portably detected at runtime from userland (the `mrc` instruction is privileged), so the default value for using the NEON codec is determined at compile-time.
But you can do your own runtime detection.
You can include the NEON codec and make it the default, then do a runtime check if the CPU has NEON support, and if not, force a downgrade to non-NEON with `BASE64_FORCE_PLAIN`.
These are your options:
1. Don't include NEON support;
2. build NEON support and make it the default, but build all other code without NEON flags so that you can override the default at runtime with `BASE64_FORCE_PLAIN`;
3. build everything with NEON support and make it the default;
4. build everything with NEON support, but don't make it the default (which makes no sense).
For option 1, simply don't specify any NEON-specific compiler flags at all, like so:
```sh
CC=clang CFLAGS="-march=armv6" make
```
For option 2, keep your `CFLAGS` plain, but set the `NEON32_CFLAGS` environment variable to a value that will build NEON support.
The line below, for instance, will build all the code at ARMv6 level, except for the NEON codec, which is built at ARMv7.
It will also make the NEON codec the default.
For ARMv6 platforms, override that default at runtime with the `BASE64_FORCE_PLAIN` flag.
No ARMv7/NEON code will then be touched.
```sh
CC=clang CFLAGS="-march=armv6" NEON32_CFLAGS="-march=armv7 -mfpu=neon" make
```
For option 3, put everything in your `CFLAGS` and use a stub, but non-empty, `NEON32_CFLAGS`.
This example works for the Raspberry Pi 2B V1.1, which has NEON support:
```sh
CC=clang CFLAGS="-march=armv7 -mtune=cortex-a7" NEON32_CFLAGS="-mfpu=neon" make
```
To build and include the NEON64 codec, use `CFLAGS` as usual to define the platform and set `NEON64_CFLAGS` to a nonempty stub.
(The AArch64 target has mandatory NEON64 support.)
Example:
```sh
CC=clang CFLAGS="--target=aarch64-linux-gnu -march=armv8-a" NEON64_CFLAGS=" " make
```
### OpenMP
To enable OpenMP on GCC you need to build with `-fopenmp`. This can be by setting the the `OPENMP` environment variable to `1`.
Example:
```sh
OPENMP=1 make
```
This will let the compiler define `_OPENMP`, which in turn will include the OpenMP optimized `lib_openmp.c` into `lib.c`.
By default the number of parallel threads will be equal to the number of cores of the processor.
On a quad core with hyperthreading eight cores will be detected, but hyperthreading will not increase the performance.
To get verbose information about OpenMP start the program with `OMP_DISPLAY_ENV=VERBOSE`, for instance
```sh
OMP_DISPLAY_ENV=VERBOSE test/benchmark
```
To put a limit on the number of threads, start the program with `OMP_THREAD_LIMIT=n`, for instance
```sh
OMP_THREAD_LIMIT=2 test/benchmark
```
An example of running a benchmark with OpenMP, SSSE3 and AVX2 enabled:
```sh
make clean && OPENMP=1 SSSE3_CFLAGS=-mssse3 AVX2_CFLAGS=-mavx2 make && OPENMP=1 make -C test
```
## API reference
Strings are represented as a pointer and a length; they are not
zero-terminated. This was a conscious design decision. In the decoding step,
relying on zero-termination would make no sense since the output could contain
legitimate zero bytes. In the encoding step, returning the length saves the
overhead of calling `strlen()` on the output. If you insist on the trailing
zero, you can easily add it yourself at the given offset.
### Flags
Some API calls take a `flags` argument.
That argument can be used to force the use of a specific codec, even if that codec is a no-op in the current build.
Mainly there for testing purposes, this is also useful on ARM where the only way to do runtime NEON detection is to ask the OS if it's available.
The following constants can be used:
- `BASE64_FORCE_AVX2`
- `BASE64_FORCE_AVX512`
- `BASE64_FORCE_NEON32`
- `BASE64_FORCE_NEON64`
- `BASE64_FORCE_PLAIN`
- `BASE64_FORCE_SSSE3`
- `BASE64_FORCE_SSE41`
- `BASE64_FORCE_SSE42`
- `BASE64_FORCE_AVX`
Set `flags` to `0` for the default behavior, which is runtime feature detection on x86, a compile-time fixed codec on ARM, and the plain codec on other platforms.
### Encoding
#### base64_encode
```c
void base64_encode
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
) ;
```
Wrapper function to encode a plain string of given length.
Output is written to `out` without trailing zero.
Output length in bytes is written to `outlen`.
The buffer in `out` has been allocated by the caller and is at least 4/3 the size of the input.
#### base64_stream_encode_init
```c
void base64_stream_encode_init
( struct base64_state *state
, int flags
) ;
```
Call this before calling `base64_stream_encode()` to init the state.
#### base64_stream_encode
```c
void base64_stream_encode
( struct base64_state *state
, const char *src
, size_t srclen
, char *out
, size_t *outlen
) ;
```
Encodes the block of data of given length at `src`, into the buffer at `out`.
Caller is responsible for allocating a large enough out-buffer; it must be at least 4/3 the size of the in-buffer, but take some margin.
Places the number of new bytes written into `outlen` (which is set to zero when the function starts).
Does not zero-terminate or finalize the output.
#### base64_stream_encode_final
```c
void base64_stream_encode_final
( struct base64_state *state
, char *out
, size_t *outlen
) ;
```
Finalizes the output begun by previous calls to `base64_stream_encode()`.
Adds the required end-of-stream markers if appropriate.
`outlen` is modified and will contain the number of new bytes written at `out` (which will quite often be zero).
### Decoding
#### base64_decode
```c
int base64_decode
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
) ;
```
Wrapper function to decode a plain string of given length.
Output is written to `out` without trailing zero. Output length in bytes is written to `outlen`.
The buffer in `out` has been allocated by the caller and is at least 3/4 the size of the input.
Returns `1` for success, and `0` when a decode error has occured due to invalid input.
Returns `-1` if the chosen codec is not included in the current build.
#### base64_stream_decode_init
```c
void base64_stream_decode_init
( struct base64_state *state
, int flags
) ;
```
Call this before calling `base64_stream_decode()` to init the state.
#### base64_stream_decode
```c
int base64_stream_decode
( struct base64_state *state
, const char *src
, size_t srclen
, char *out
, size_t *outlen
) ;
```
Decodes the block of data of given length at `src`, into the buffer at `out`.
Caller is responsible for allocating a large enough out-buffer; it must be at least 3/4 the size of the in-buffer, but take some margin.
Places the number of new bytes written into `outlen` (which is set to zero when the function starts).
Does not zero-terminate the output.
Returns 1 if all is well, and 0 if a decoding error was found, such as an invalid character.
Returns -1 if the chosen codec is not included in the current build.
Used by the test harness to check whether a codec is available for testing.
## Examples
A simple example of encoding a static string to base64 and printing the output
to stdout:
```c
#include <stdio.h> /* fwrite */
#include "libbase64.h"
int main ()
{
char src[] = "hello world";
char out[20];
size_t srclen = sizeof(src) - 1;
size_t outlen;
base64_encode(src, srclen, out, &outlen, 0);
fwrite(out, outlen, 1, stdout);
return 0;
}
```
A simple example (no error checking, etc) of stream encoding standard input to
standard output:
```c
#include <stdio.h>
#include "libbase64.h"
int main ()
{
size_t nread, nout;
char buf[12000], out[16000];
struct base64_state state;
// Initialize stream encoder:
base64_stream_encode_init(&state, 0);
// Read contents of stdin into buffer:
while ((nread = fread(buf, 1, sizeof(buf), stdin)) > 0) {
// Encode buffer:
base64_stream_encode(&state, buf, nread, out, &nout);
// If there's output, print it to stdout:
if (nout) {
fwrite(out, nout, 1, stdout);
}
// If an error occurred, exit the loop:
if (feof(stdin)) {
break;
}
}
// Finalize encoding:
base64_stream_encode_final(&state, out, &nout);
// If the finalizing resulted in extra output bytes, print them:
if (nout) {
fwrite(out, nout, 1, stdout);
}
return 0;
}
```
Also see `bin/base64.c` for a simple re-implementation of the `base64` utility.
A file or standard input is fed through the encoder/decoder, and the output is
written to standard output.
## Tests
See `tests/` for a small test suite. Testing is automated with
[GitHub Actions](https://github.com/aklomp/base64/actions), which builds and
tests the code across various architectures.
## Benchmarks
Benchmarks can be run with the built-in benchmark program as follows:
```sh
make -C test benchmark <buildflags> && test/benchmark
```
It will run an encoding and decoding benchmark for all of the compiled-in codecs.
The tables below contain some results on random machines. All numbers measured with a 10MB buffer in MB/sec, rounded to the nearest integer.
\*: Update needed
x86 processors
| Processor | Plain enc | Plain dec | SSSE3 enc | SSSE3 dec | AVX enc | AVX dec | AVX2 enc | AVX2 dec |
|-------------------------------------------|----------:|----------:|----------:|----------:|--------:|--------:|---------:|---------:|
| i7-4771 @ 3.5 GHz | 833\* | 1111\* | 3333\* | 4444\* | TBD | TBD | 4999\* | 6666\* |
| i7-4770 @ 3.4 GHz DDR1600 | 1790\* | 3038\* | 4899\* | 4043\* | 4796\* | 5709\* | 4681\* | 6386\* |
| i7-4770 @ 3.4 GHz DDR1600 OPENMP 1 thread | 1784\* | 3041\* | 4945\* | 4035\* | 4776\* | 5719\* | 4661\* | 6294\* |
| i7-4770 @ 3.4 GHz DDR1600 OPENMP 2 thread | 3401\* | 5729\* | 5489\* | 7444\* | 5003\* | 8624\* | 5105\* | 8558\* |
| i7-4770 @ 3.4 GHz DDR1600 OPENMP 4 thread | 4884\* | 7099\* | 4917\* | 7057\* | 4799\* | 7143\* | 4902\* | 7219\* |
| i7-4770 @ 3.4 GHz DDR1600 OPENMP 8 thread | 5212\* | 8849\* | 5284\* | 9099\* | 5289\* | 9220\* | 4849\* | 9200\* |
| i7-4870HQ @ 2.5 GHz | 1471\* | 3066\* | 6721\* | 6962\* | 7015\* | 8267\* | 8328\* | 11576\* |
| i5-4590S @ 3.0 GHz | 3356 | 3197 | 4363 | 6104 | 4243\* | 6233 | 4160\* | 6344 |
| Xeon X5570 @ 2.93 GHz | 2161 | 1508 | 3160 | 3915 | - | - | - | - |
| Pentium4 @ 3.4 GHz | 896 | 740 | - | - | - | - | - | - |
| Atom N270 | 243 | 266 | 508 | 387 | - | - | - | - |
| AMD E-450 | 645 | 564 | 625 | 634 | - | - | - | - |
| Intel Edison @ 500 MHz | 79\* | 92\* | 152\* | 172\* | - | - | - | - |
| Intel Edison @ 500 MHz OPENMP 2 thread | 158\* | 184\* | 300\* | 343\* | - | - | - | - |
| Intel Edison @ 500 MHz (x86-64) | 162 | 119 | 209 | 164 | - | - | - | - |
| Intel Edison @ 500 MHz (x86-64) 2 thread | 319 | 237 | 412 | 329 | - | - | - | - |
ARM processors
| Processor | Plain enc | Plain dec | NEON32 enc | NEON32 dec | NEON64 enc | NEON64 dec |
|-------------------------------------------|----------:|----------:|-----------:|-----------:|-----------:|-----------:|
| Raspberry PI B+ V1.2 | 46\* | 40\* | - | - | - | - |
| Raspberry PI 2 B V1.1 | 85 | 141 | 300 | 225 | - | - |
| Apple iPhone SE armv7 | 1056\* | 895\* | 2943\* | 2618\* | - | - |
| Apple iPhone SE arm64 | 1061\* | 1239\* | - | - | 4098\* | 3983\* |
PowerPC processors
| Processor | Plain enc | Plain dec |
|-------------------------------------------|----------:|----------:|
| PowerPC E6500 @ 1.8GHz | 270\* | 265\* |
Benchmarks on i7-4770 @ 3.4 GHz DDR1600 with varrying buffer sizes:
![Benchmarks](base64-benchmarks.png)
Note: optimal buffer size to take advantage of the cache is in the range of 100 kB to 1 MB, leading to 12x faster AVX encoding/decoding compared to Plain, or a throughput of 24/27GB/sec.
Also note the performance degradation when the buffer size is less than 10 kB due to thread creation overhead.
To prevent this from happening `lib_openmp.c` defines `OMP_THRESHOLD 20000`, requiring at least a 20000 byte buffer to enable multithreading.
## License
This repository is licensed under the
[BSD 2-clause License](http://opensource.org/licenses/BSD-2-Clause). See the
LICENSE file.

146
3rdparty/base64/include/libbase64.h vendored Normal file
View File

@@ -0,0 +1,146 @@
#ifndef LIBBASE64_H
#define LIBBASE64_H
#include <stddef.h> /* size_t */
#if defined(_WIN32) || defined(__CYGWIN__)
#define BASE64_SYMBOL_IMPORT __declspec(dllimport)
#define BASE64_SYMBOL_EXPORT __declspec(dllexport)
#define BASE64_SYMBOL_PRIVATE
#elif __GNUC__ >= 4
#define BASE64_SYMBOL_IMPORT __attribute__ ((visibility ("default")))
#define BASE64_SYMBOL_EXPORT __attribute__ ((visibility ("default")))
#define BASE64_SYMBOL_PRIVATE __attribute__ ((visibility ("hidden")))
#else
#define BASE64_SYMBOL_IMPORT
#define BASE64_SYMBOL_EXPORT
#define BASE64_SYMBOL_PRIVATE
#endif
#if defined(BASE64_STATIC_DEFINE)
#define BASE64_EXPORT
#define BASE64_NO_EXPORT
#else
#if defined(BASE64_EXPORTS) // defined if we are building the shared library
#define BASE64_EXPORT BASE64_SYMBOL_EXPORT
#else
#define BASE64_EXPORT BASE64_SYMBOL_IMPORT
#endif
#define BASE64_NO_EXPORT BASE64_SYMBOL_PRIVATE
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* These are the flags that can be passed in the `flags` argument. The values
* below force the use of a given codec, even if that codec is a no-op in the
* current build. Used in testing. Set to 0 for the default behavior, which is
* runtime feature detection on x86, a compile-time fixed codec on ARM, and
* the plain codec on other platforms: */
#define BASE64_FORCE_AVX2 (1 << 0)
#define BASE64_FORCE_NEON32 (1 << 1)
#define BASE64_FORCE_NEON64 (1 << 2)
#define BASE64_FORCE_PLAIN (1 << 3)
#define BASE64_FORCE_SSSE3 (1 << 4)
#define BASE64_FORCE_SSE41 (1 << 5)
#define BASE64_FORCE_SSE42 (1 << 6)
#define BASE64_FORCE_AVX (1 << 7)
#define BASE64_FORCE_AVX512 (1 << 8)
struct base64_state {
int eof;
int bytes;
int flags;
unsigned char carry;
};
/* Wrapper function to encode a plain string of given length. Output is written
* to *out without trailing zero. Output length in bytes is written to *outlen.
* The buffer in `out` has been allocated by the caller and is at least 4/3 the
* size of the input. See above for `flags`; set to 0 for default operation: */
void BASE64_EXPORT base64_encode
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
) ;
/* Call this before calling base64_stream_encode() to init the state. See above
* for `flags`; set to 0 for default operation: */
void BASE64_EXPORT base64_stream_encode_init
( struct base64_state *state
, int flags
) ;
/* Encodes the block of data of given length at `src`, into the buffer at
* `out`. Caller is responsible for allocating a large enough out-buffer; it
* must be at least 4/3 the size of the in-buffer, but take some margin. Places
* the number of new bytes written into `outlen` (which is set to zero when the
* function starts). Does not zero-terminate or finalize the output. */
void BASE64_EXPORT base64_stream_encode
( struct base64_state *state
, const char *src
, size_t srclen
, char *out
, size_t *outlen
) ;
/* Finalizes the output begun by previous calls to `base64_stream_encode()`.
* Adds the required end-of-stream markers if appropriate. `outlen` is modified
* and will contain the number of new bytes written at `out` (which will quite
* often be zero). */
void BASE64_EXPORT base64_stream_encode_final
( struct base64_state *state
, char *out
, size_t *outlen
) ;
/* Wrapper function to decode a plain string of given length. Output is written
* to *out without trailing zero. Output length in bytes is written to *outlen.
* The buffer in `out` has been allocated by the caller and is at least 3/4 the
* size of the input. See above for `flags`, set to 0 for default operation: */
int BASE64_EXPORT base64_decode
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
) ;
/* Call this before calling base64_stream_decode() to init the state. See above
* for `flags`; set to 0 for default operation: */
void BASE64_EXPORT base64_stream_decode_init
( struct base64_state *state
, int flags
) ;
/* Decodes the block of data of given length at `src`, into the buffer at
* `out`. Caller is responsible for allocating a large enough out-buffer; it
* must be at least 3/4 the size of the in-buffer, but take some margin. Places
* the number of new bytes written into `outlen` (which is set to zero when the
* function starts). Does not zero-terminate the output. Returns 1 if all is
* well, and 0 if a decoding error was found, such as an invalid character.
* Returns -1 if the chosen codec is not included in the current build. Used by
* the test harness to check whether a codec is available for testing. */
int BASE64_EXPORT base64_stream_decode
( struct base64_state *state
, const char *src
, size_t srclen
, char *out
, size_t *outlen
) ;
#ifdef __cplusplus
}
#endif
#endif /* LIBBASE64_H */

66
3rdparty/base64/lib/arch/avx/codec.c vendored Normal file
View File

@@ -0,0 +1,66 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "../../../include/libbase64.h"
#include "../../tables/tables.h"
#include "../../codecs.h"
#include "config.h"
#include "../../env.h"
#if HAVE_AVX
#include <immintrin.h>
// Only enable inline assembly on supported compilers and on 64-bit CPUs.
#ifndef BASE64_AVX_USE_ASM
# if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64
# define BASE64_AVX_USE_ASM 1
# else
# define BASE64_AVX_USE_ASM 0
# endif
#endif
#include "../ssse3/dec_reshuffle.c"
#include "../ssse3/dec_loop.c"
#if BASE64_AVX_USE_ASM
# include "enc_loop_asm.c"
#else
# include "../ssse3/enc_translate.c"
# include "../ssse3/enc_reshuffle.c"
# include "../ssse3/enc_loop.c"
#endif
#endif // HAVE_AVX
BASE64_ENC_FUNCTION(avx)
{
#if HAVE_AVX
#include "../generic/enc_head.c"
// For supported compilers, use a hand-optimized inline assembly
// encoder. Otherwise fall back on the SSSE3 encoder, but compiled with
// AVX flags to generate better optimized AVX code.
#if BASE64_AVX_USE_ASM
enc_loop_avx(&s, &slen, &o, &olen);
#else
enc_loop_ssse3(&s, &slen, &o, &olen);
#endif
#include "../generic/enc_tail.c"
#else
BASE64_ENC_STUB
#endif
}
BASE64_DEC_FUNCTION(avx)
{
#if HAVE_AVX
#include "../generic/dec_head.c"
dec_loop_ssse3(&s, &slen, &o, &olen);
#include "../generic/dec_tail.c"
#else
BASE64_DEC_STUB
#endif
}

View File

@@ -0,0 +1,264 @@
// Apologies in advance for combining the preprocessor with inline assembly,
// two notoriously gnarly parts of C, but it was necessary to avoid a lot of
// code repetition. The preprocessor is used to template large sections of
// inline assembly that differ only in the registers used. If the code was
// written out by hand, it would become very large and hard to audit.
// Generate a block of inline assembly that loads register R0 from memory. The
// offset at which the register is loaded is set by the given round.
#define LOAD(R0, ROUND) \
"vlddqu ("#ROUND" * 12)(%[src]), %["R0"] \n\t"
// Generate a block of inline assembly that deinterleaves and shuffles register
// R0 using preloaded constants. Outputs in R0 and R1.
#define SHUF(R0, R1, R2) \
"vpshufb %[lut0], %["R0"], %["R1"] \n\t" \
"vpand %["R1"], %[msk0], %["R2"] \n\t" \
"vpand %["R1"], %[msk2], %["R1"] \n\t" \
"vpmulhuw %["R2"], %[msk1], %["R2"] \n\t" \
"vpmullw %["R1"], %[msk3], %["R1"] \n\t" \
"vpor %["R1"], %["R2"], %["R1"] \n\t"
// Generate a block of inline assembly that takes R0 and R1 and translates
// their contents to the base64 alphabet, using preloaded constants.
#define TRAN(R0, R1, R2) \
"vpsubusb %[n51], %["R1"], %["R0"] \n\t" \
"vpcmpgtb %[n25], %["R1"], %["R2"] \n\t" \
"vpsubb %["R2"], %["R0"], %["R0"] \n\t" \
"vpshufb %["R0"], %[lut1], %["R2"] \n\t" \
"vpaddb %["R1"], %["R2"], %["R0"] \n\t"
// Generate a block of inline assembly that stores the given register R0 at an
// offset set by the given round.
#define STOR(R0, ROUND) \
"vmovdqu %["R0"], ("#ROUND" * 16)(%[dst]) \n\t"
// Generate a block of inline assembly that generates a single self-contained
// encoder round: fetch the data, process it, and store the result. Then update
// the source and destination pointers.
#define ROUND() \
LOAD("a", 0) \
SHUF("a", "b", "c") \
TRAN("a", "b", "c") \
STOR("a", 0) \
"add $12, %[src] \n\t" \
"add $16, %[dst] \n\t"
// Define a macro that initiates a three-way interleaved encoding round by
// preloading registers a, b and c from memory.
// The register graph shows which registers are in use during each step, and
// is a visual aid for choosing registers for that step. Symbol index:
//
// + indicates that a register is loaded by that step.
// | indicates that a register is in use and must not be touched.
// - indicates that a register is decommissioned by that step.
// x indicates that a register is used as a temporary by that step.
// V indicates that a register is an input or output to the macro.
//
#define ROUND_3_INIT() /* a b c d e f */ \
LOAD("a", 0) /* + */ \
SHUF("a", "d", "e") /* | + x */ \
LOAD("b", 1) /* | + | */ \
TRAN("a", "d", "e") /* | | - x */ \
LOAD("c", 2) /* V V V */
// Define a macro that translates, shuffles and stores the input registers A, B
// and C, and preloads registers D, E and F for the next round.
// This macro can be arbitrarily daisy-chained by feeding output registers D, E
// and F back into the next round as input registers A, B and C. The macro
// carefully interleaves memory operations with data operations for optimal
// pipelined performance.
#define ROUND_3(ROUND, A,B,C,D,E,F) /* A B C D E F */ \
LOAD(D, (ROUND + 3)) /* V V V + */ \
SHUF(B, E, F) /* | | | | + x */ \
STOR(A, (ROUND + 0)) /* - | | | | */ \
TRAN(B, E, F) /* | | | - x */ \
LOAD(E, (ROUND + 4)) /* | | | + */ \
SHUF(C, A, F) /* + | | | | x */ \
STOR(B, (ROUND + 1)) /* | - | | | */ \
TRAN(C, A, F) /* - | | | x */ \
LOAD(F, (ROUND + 5)) /* | | | + */ \
SHUF(D, A, B) /* + x | | | | */ \
STOR(C, (ROUND + 2)) /* | - | | | */ \
TRAN(D, A, B) /* - x V V V */
// Define a macro that terminates a ROUND_3 macro by taking pre-loaded
// registers D, E and F, and translating, shuffling and storing them.
#define ROUND_3_END(ROUND, A,B,C,D,E,F) /* A B C D E F */ \
SHUF(E, A, B) /* + x V V V */ \
STOR(D, (ROUND + 3)) /* | - | | */ \
TRAN(E, A, B) /* - x | | */ \
SHUF(F, C, D) /* + x | | */ \
STOR(E, (ROUND + 4)) /* | - | */ \
TRAN(F, C, D) /* - x | */ \
STOR(F, (ROUND + 5)) /* - */
// Define a type A round. Inputs are a, b, and c, outputs are d, e, and f.
#define ROUND_3_A(ROUND) \
ROUND_3(ROUND, "a", "b", "c", "d", "e", "f")
// Define a type B round. Inputs and outputs are swapped with regard to type A.
#define ROUND_3_B(ROUND) \
ROUND_3(ROUND, "d", "e", "f", "a", "b", "c")
// Terminating macro for a type A round.
#define ROUND_3_A_LAST(ROUND) \
ROUND_3_A(ROUND) \
ROUND_3_END(ROUND, "a", "b", "c", "d", "e", "f")
// Terminating macro for a type B round.
#define ROUND_3_B_LAST(ROUND) \
ROUND_3_B(ROUND) \
ROUND_3_END(ROUND, "d", "e", "f", "a", "b", "c")
// Suppress clang's warning that the literal string in the asm statement is
// overlong (longer than the ISO-mandated minimum size of 4095 bytes for C99
// compilers). It may be true, but the goal here is not C99 portability.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverlength-strings"
static inline void
enc_loop_avx (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
// For a clearer explanation of the algorithm used by this function,
// please refer to the plain (not inline assembly) implementation. This
// function follows the same basic logic.
if (*slen < 16) {
return;
}
// Process blocks of 12 bytes at a time. Input is read in blocks of 16
// bytes, so "reserve" four bytes from the input buffer to ensure that
// we never read beyond the end of the input buffer.
size_t rounds = (*slen - 4) / 12;
*slen -= rounds * 12; // 12 bytes consumed per round
*olen += rounds * 16; // 16 bytes produced per round
// Number of times to go through the 36x loop.
size_t loops = rounds / 36;
// Number of rounds remaining after the 36x loop.
rounds %= 36;
// Lookup tables.
const __m128i lut0 = _mm_set_epi8(
10, 11, 9, 10, 7, 8, 6, 7, 4, 5, 3, 4, 1, 2, 0, 1);
const __m128i lut1 = _mm_setr_epi8(
65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0);
// Temporary registers.
__m128i a, b, c, d, e, f;
__asm__ volatile (
// If there are 36 rounds or more, enter a 36x unrolled loop of
// interleaved encoding rounds. The rounds interleave memory
// operations (load/store) with data operations (table lookups,
// etc) to maximize pipeline throughput.
" test %[loops], %[loops] \n\t"
" jz 18f \n\t"
" jmp 36f \n\t"
" \n\t"
".balign 64 \n\t"
"36: " ROUND_3_INIT()
" " ROUND_3_A( 0)
" " ROUND_3_B( 3)
" " ROUND_3_A( 6)
" " ROUND_3_B( 9)
" " ROUND_3_A(12)
" " ROUND_3_B(15)
" " ROUND_3_A(18)
" " ROUND_3_B(21)
" " ROUND_3_A(24)
" " ROUND_3_B(27)
" " ROUND_3_A_LAST(30)
" add $(12 * 36), %[src] \n\t"
" add $(16 * 36), %[dst] \n\t"
" dec %[loops] \n\t"
" jnz 36b \n\t"
// Enter an 18x unrolled loop for rounds of 18 or more.
"18: cmp $18, %[rounds] \n\t"
" jl 9f \n\t"
" " ROUND_3_INIT()
" " ROUND_3_A(0)
" " ROUND_3_B(3)
" " ROUND_3_A(6)
" " ROUND_3_B(9)
" " ROUND_3_A_LAST(12)
" sub $18, %[rounds] \n\t"
" add $(12 * 18), %[src] \n\t"
" add $(16 * 18), %[dst] \n\t"
// Enter a 9x unrolled loop for rounds of 9 or more.
"9: cmp $9, %[rounds] \n\t"
" jl 6f \n\t"
" " ROUND_3_INIT()
" " ROUND_3_A(0)
" " ROUND_3_B_LAST(3)
" sub $9, %[rounds] \n\t"
" add $(12 * 9), %[src] \n\t"
" add $(16 * 9), %[dst] \n\t"
// Enter a 6x unrolled loop for rounds of 6 or more.
"6: cmp $6, %[rounds] \n\t"
" jl 55f \n\t"
" " ROUND_3_INIT()
" " ROUND_3_A_LAST(0)
" sub $6, %[rounds] \n\t"
" add $(12 * 6), %[src] \n\t"
" add $(16 * 6), %[dst] \n\t"
// Dispatch the remaining rounds 0..5.
"55: cmp $3, %[rounds] \n\t"
" jg 45f \n\t"
" je 3f \n\t"
" cmp $1, %[rounds] \n\t"
" jg 2f \n\t"
" je 1f \n\t"
" jmp 0f \n\t"
"45: cmp $4, %[rounds] \n\t"
" je 4f \n\t"
// Block of non-interlaced encoding rounds, which can each
// individually be jumped to. Rounds fall through to the next.
"5: " ROUND()
"4: " ROUND()
"3: " ROUND()
"2: " ROUND()
"1: " ROUND()
"0: \n\t"
// Outputs (modified).
: [rounds] "+r" (rounds),
[loops] "+r" (loops),
[src] "+r" (*s),
[dst] "+r" (*o),
[a] "=&x" (a),
[b] "=&x" (b),
[c] "=&x" (c),
[d] "=&x" (d),
[e] "=&x" (e),
[f] "=&x" (f)
// Inputs (not modified).
: [lut0] "x" (lut0),
[lut1] "x" (lut1),
[msk0] "x" (_mm_set1_epi32(0x0FC0FC00)),
[msk1] "x" (_mm_set1_epi32(0x04000040)),
[msk2] "x" (_mm_set1_epi32(0x003F03F0)),
[msk3] "x" (_mm_set1_epi32(0x01000010)),
[n51] "x" (_mm_set1_epi8(51)),
[n25] "x" (_mm_set1_epi8(25))
// Clobbers.
: "cc", "memory"
);
}
#pragma GCC diagnostic pop

56
3rdparty/base64/lib/arch/avx2/codec.c vendored Normal file
View File

@@ -0,0 +1,56 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "../../../include/libbase64.h"
#include "../../tables/tables.h"
#include "../../codecs.h"
#include "config.h"
#include "../../env.h"
#if HAVE_AVX2
#include <immintrin.h>
// Only enable inline assembly on supported compilers and on 64-bit CPUs.
#ifndef BASE64_AVX2_USE_ASM
# if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64
# define BASE64_AVX2_USE_ASM 1
# else
# define BASE64_AVX2_USE_ASM 0
# endif
#endif
#include "dec_reshuffle.c"
#include "dec_loop.c"
#if BASE64_AVX2_USE_ASM
# include "enc_loop_asm.c"
#else
# include "enc_translate.c"
# include "enc_reshuffle.c"
# include "enc_loop.c"
#endif
#endif // HAVE_AVX2
BASE64_ENC_FUNCTION(avx2)
{
#if HAVE_AVX2
#include "../generic/enc_head.c"
enc_loop_avx2(&s, &slen, &o, &olen);
#include "../generic/enc_tail.c"
#else
BASE64_ENC_STUB
#endif
}
BASE64_DEC_FUNCTION(avx2)
{
#if HAVE_AVX2
#include "../generic/dec_head.c"
dec_loop_avx2(&s, &slen, &o, &olen);
#include "../generic/dec_tail.c"
#else
BASE64_DEC_STUB
#endif
}

110
3rdparty/base64/lib/arch/avx2/dec_loop.c vendored Normal file
View File

@@ -0,0 +1,110 @@
static inline int
dec_loop_avx2_inner (const uint8_t **s, uint8_t **o, size_t *rounds)
{
const __m256i lut_lo = _mm256_setr_epi8(
0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x13, 0x1A, 0x1B, 0x1B, 0x1B, 0x1A,
0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x13, 0x1A, 0x1B, 0x1B, 0x1B, 0x1A);
const __m256i lut_hi = _mm256_setr_epi8(
0x10, 0x10, 0x01, 0x02, 0x04, 0x08, 0x04, 0x08,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x01, 0x02, 0x04, 0x08, 0x04, 0x08,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10);
const __m256i lut_roll = _mm256_setr_epi8(
0, 16, 19, 4, -65, -65, -71, -71,
0, 0, 0, 0, 0, 0, 0, 0,
0, 16, 19, 4, -65, -65, -71, -71,
0, 0, 0, 0, 0, 0, 0, 0);
const __m256i mask_2F = _mm256_set1_epi8(0x2F);
// Load input:
__m256i str = _mm256_loadu_si256((__m256i *) *s);
// See the SSSE3 decoder for an explanation of the algorithm.
const __m256i hi_nibbles = _mm256_and_si256(_mm256_srli_epi32(str, 4), mask_2F);
const __m256i lo_nibbles = _mm256_and_si256(str, mask_2F);
const __m256i hi = _mm256_shuffle_epi8(lut_hi, hi_nibbles);
const __m256i lo = _mm256_shuffle_epi8(lut_lo, lo_nibbles);
if (!_mm256_testz_si256(lo, hi)) {
return 0;
}
const __m256i eq_2F = _mm256_cmpeq_epi8(str, mask_2F);
const __m256i roll = _mm256_shuffle_epi8(lut_roll, _mm256_add_epi8(eq_2F, hi_nibbles));
// Now simply add the delta values to the input:
str = _mm256_add_epi8(str, roll);
// Reshuffle the input to packed 12-byte output format:
str = dec_reshuffle(str);
// Store the output:
_mm256_storeu_si256((__m256i *) *o, str);
*s += 32;
*o += 24;
*rounds -= 1;
return 1;
}
static inline void
dec_loop_avx2 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 45) {
return;
}
// Process blocks of 32 bytes per round. Because 8 extra zero bytes are
// written after the output, ensure that there will be at least 13
// bytes of input data left to cover the gap. (11 data bytes and up to
// two end-of-string markers.)
size_t rounds = (*slen - 13) / 32;
*slen -= rounds * 32; // 32 bytes consumed per round
*olen += rounds * 24; // 24 bytes produced per round
do {
if (rounds >= 8) {
if (dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds)) {
continue;
}
break;
}
if (rounds >= 4) {
if (dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds)) {
continue;
}
break;
}
if (rounds >= 2) {
if (dec_loop_avx2_inner(s, o, &rounds) &&
dec_loop_avx2_inner(s, o, &rounds)) {
continue;
}
break;
}
dec_loop_avx2_inner(s, o, &rounds);
break;
} while (rounds > 0);
// Adjust for any rounds that were skipped:
*slen += rounds * 32;
*olen -= rounds * 24;
}

View File

@@ -0,0 +1,34 @@
static inline __m256i
dec_reshuffle (const __m256i in)
{
// in, lower lane, bits, upper case are most significant bits, lower
// case are least significant bits:
// 00llllll 00kkkkLL 00jjKKKK 00JJJJJJ
// 00iiiiii 00hhhhII 00ggHHHH 00GGGGGG
// 00ffffff 00eeeeFF 00ddEEEE 00DDDDDD
// 00cccccc 00bbbbCC 00aaBBBB 00AAAAAA
const __m256i merge_ab_and_bc = _mm256_maddubs_epi16(in, _mm256_set1_epi32(0x01400140));
// 0000kkkk LLllllll 0000JJJJ JJjjKKKK
// 0000hhhh IIiiiiii 0000GGGG GGggHHHH
// 0000eeee FFffffff 0000DDDD DDddEEEE
// 0000bbbb CCcccccc 0000AAAA AAaaBBBB
__m256i out = _mm256_madd_epi16(merge_ab_and_bc, _mm256_set1_epi32(0x00011000));
// 00000000 JJJJJJjj KKKKkkkk LLllllll
// 00000000 GGGGGGgg HHHHhhhh IIiiiiii
// 00000000 DDDDDDdd EEEEeeee FFffffff
// 00000000 AAAAAAaa BBBBbbbb CCcccccc
// Pack bytes together in each lane:
out = _mm256_shuffle_epi8(out, _mm256_setr_epi8(
2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1,
2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, -1, -1, -1, -1));
// 00000000 00000000 00000000 00000000
// LLllllll KKKKkkkk JJJJJJjj IIiiiiii
// HHHHhhhh GGGGGGgg FFffffff EEEEeeee
// DDDDDDdd CCcccccc BBBBbbbb AAAAAAaa
// Pack lanes:
return _mm256_permutevar8x32_epi32(out, _mm256_setr_epi32(0, 1, 2, 4, 5, 6, -1, -1));
}

View File

@@ -0,0 +1,89 @@
static inline void
enc_loop_avx2_inner_first (const uint8_t **s, uint8_t **o)
{
// First load is done at s - 0 to not get a segfault:
__m256i src = _mm256_loadu_si256((__m256i *) *s);
// Shift by 4 bytes, as required by enc_reshuffle:
src = _mm256_permutevar8x32_epi32(src, _mm256_setr_epi32(0, 0, 1, 2, 3, 4, 5, 6));
// Reshuffle, translate, store:
src = enc_reshuffle(src);
src = enc_translate(src);
_mm256_storeu_si256((__m256i *) *o, src);
// Subsequent loads will be done at s - 4, set pointer for next round:
*s += 20;
*o += 32;
}
static inline void
enc_loop_avx2_inner (const uint8_t **s, uint8_t **o)
{
// Load input:
__m256i src = _mm256_loadu_si256((__m256i *) *s);
// Reshuffle, translate, store:
src = enc_reshuffle(src);
src = enc_translate(src);
_mm256_storeu_si256((__m256i *) *o, src);
*s += 24;
*o += 32;
}
static inline void
enc_loop_avx2 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 32) {
return;
}
// Process blocks of 24 bytes at a time. Because blocks are loaded 32
// bytes at a time an offset of -4, ensure that there will be at least
// 4 remaining bytes after the last round, so that the final read will
// not pass beyond the bounds of the input buffer:
size_t rounds = (*slen - 4) / 24;
*slen -= rounds * 24; // 24 bytes consumed per round
*olen += rounds * 32; // 32 bytes produced per round
// The first loop iteration requires special handling to ensure that
// the read, which is done at an offset, does not underflow the buffer:
enc_loop_avx2_inner_first(s, o);
rounds--;
while (rounds > 0) {
if (rounds >= 8) {
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
rounds -= 8;
continue;
}
if (rounds >= 4) {
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
rounds -= 4;
continue;
}
if (rounds >= 2) {
enc_loop_avx2_inner(s, o);
enc_loop_avx2_inner(s, o);
rounds -= 2;
continue;
}
enc_loop_avx2_inner(s, o);
break;
}
// Add the offset back:
*s += 4;
}

View File

@@ -0,0 +1,291 @@
// Apologies in advance for combining the preprocessor with inline assembly,
// two notoriously gnarly parts of C, but it was necessary to avoid a lot of
// code repetition. The preprocessor is used to template large sections of
// inline assembly that differ only in the registers used. If the code was
// written out by hand, it would become very large and hard to audit.
// Generate a block of inline assembly that loads register R0 from memory. The
// offset at which the register is loaded is set by the given round and a
// constant offset.
#define LOAD(R0, ROUND, OFFSET) \
"vlddqu ("#ROUND" * 24 + "#OFFSET")(%[src]), %["R0"] \n\t"
// Generate a block of inline assembly that deinterleaves and shuffles register
// R0 using preloaded constants. Outputs in R0 and R1.
#define SHUF(R0, R1, R2) \
"vpshufb %[lut0], %["R0"], %["R1"] \n\t" \
"vpand %["R1"], %[msk0], %["R2"] \n\t" \
"vpand %["R1"], %[msk2], %["R1"] \n\t" \
"vpmulhuw %["R2"], %[msk1], %["R2"] \n\t" \
"vpmullw %["R1"], %[msk3], %["R1"] \n\t" \
"vpor %["R1"], %["R2"], %["R1"] \n\t"
// Generate a block of inline assembly that takes R0 and R1 and translates
// their contents to the base64 alphabet, using preloaded constants.
#define TRAN(R0, R1, R2) \
"vpsubusb %[n51], %["R1"], %["R0"] \n\t" \
"vpcmpgtb %[n25], %["R1"], %["R2"] \n\t" \
"vpsubb %["R2"], %["R0"], %["R0"] \n\t" \
"vpshufb %["R0"], %[lut1], %["R2"] \n\t" \
"vpaddb %["R1"], %["R2"], %["R0"] \n\t"
// Generate a block of inline assembly that stores the given register R0 at an
// offset set by the given round.
#define STOR(R0, ROUND) \
"vmovdqu %["R0"], ("#ROUND" * 32)(%[dst]) \n\t"
// Generate a block of inline assembly that generates a single self-contained
// encoder round: fetch the data, process it, and store the result. Then update
// the source and destination pointers.
#define ROUND() \
LOAD("a", 0, -4) \
SHUF("a", "b", "c") \
TRAN("a", "b", "c") \
STOR("a", 0) \
"add $24, %[src] \n\t" \
"add $32, %[dst] \n\t"
// Define a macro that initiates a three-way interleaved encoding round by
// preloading registers a, b and c from memory.
// The register graph shows which registers are in use during each step, and
// is a visual aid for choosing registers for that step. Symbol index:
//
// + indicates that a register is loaded by that step.
// | indicates that a register is in use and must not be touched.
// - indicates that a register is decommissioned by that step.
// x indicates that a register is used as a temporary by that step.
// V indicates that a register is an input or output to the macro.
//
#define ROUND_3_INIT() /* a b c d e f */ \
LOAD("a", 0, -4) /* + */ \
SHUF("a", "d", "e") /* | + x */ \
LOAD("b", 1, -4) /* | + | */ \
TRAN("a", "d", "e") /* | | - x */ \
LOAD("c", 2, -4) /* V V V */
// Define a macro that translates, shuffles and stores the input registers A, B
// and C, and preloads registers D, E and F for the next round.
// This macro can be arbitrarily daisy-chained by feeding output registers D, E
// and F back into the next round as input registers A, B and C. The macro
// carefully interleaves memory operations with data operations for optimal
// pipelined performance.
#define ROUND_3(ROUND, A,B,C,D,E,F) /* A B C D E F */ \
LOAD(D, (ROUND + 3), -4) /* V V V + */ \
SHUF(B, E, F) /* | | | | + x */ \
STOR(A, (ROUND + 0)) /* - | | | | */ \
TRAN(B, E, F) /* | | | - x */ \
LOAD(E, (ROUND + 4), -4) /* | | | + */ \
SHUF(C, A, F) /* + | | | | x */ \
STOR(B, (ROUND + 1)) /* | - | | | */ \
TRAN(C, A, F) /* - | | | x */ \
LOAD(F, (ROUND + 5), -4) /* | | | + */ \
SHUF(D, A, B) /* + x | | | | */ \
STOR(C, (ROUND + 2)) /* | - | | | */ \
TRAN(D, A, B) /* - x V V V */
// Define a macro that terminates a ROUND_3 macro by taking pre-loaded
// registers D, E and F, and translating, shuffling and storing them.
#define ROUND_3_END(ROUND, A,B,C,D,E,F) /* A B C D E F */ \
SHUF(E, A, B) /* + x V V V */ \
STOR(D, (ROUND + 3)) /* | - | | */ \
TRAN(E, A, B) /* - x | | */ \
SHUF(F, C, D) /* + x | | */ \
STOR(E, (ROUND + 4)) /* | - | */ \
TRAN(F, C, D) /* - x | */ \
STOR(F, (ROUND + 5)) /* - */
// Define a type A round. Inputs are a, b, and c, outputs are d, e, and f.
#define ROUND_3_A(ROUND) \
ROUND_3(ROUND, "a", "b", "c", "d", "e", "f")
// Define a type B round. Inputs and outputs are swapped with regard to type A.
#define ROUND_3_B(ROUND) \
ROUND_3(ROUND, "d", "e", "f", "a", "b", "c")
// Terminating macro for a type A round.
#define ROUND_3_A_LAST(ROUND) \
ROUND_3_A(ROUND) \
ROUND_3_END(ROUND, "a", "b", "c", "d", "e", "f")
// Terminating macro for a type B round.
#define ROUND_3_B_LAST(ROUND) \
ROUND_3_B(ROUND) \
ROUND_3_END(ROUND, "d", "e", "f", "a", "b", "c")
// Suppress clang's warning that the literal string in the asm statement is
// overlong (longer than the ISO-mandated minimum size of 4095 bytes for C99
// compilers). It may be true, but the goal here is not C99 portability.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverlength-strings"
static inline void
enc_loop_avx2 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
// For a clearer explanation of the algorithm used by this function,
// please refer to the plain (not inline assembly) implementation. This
// function follows the same basic logic.
if (*slen < 32) {
return;
}
// Process blocks of 24 bytes at a time. Because blocks are loaded 32
// bytes at a time an offset of -4, ensure that there will be at least
// 4 remaining bytes after the last round, so that the final read will
// not pass beyond the bounds of the input buffer.
size_t rounds = (*slen - 4) / 24;
*slen -= rounds * 24; // 24 bytes consumed per round
*olen += rounds * 32; // 32 bytes produced per round
// Pre-decrement the number of rounds to get the number of rounds
// *after* the first round, which is handled as a special case.
rounds--;
// Number of times to go through the 36x loop.
size_t loops = rounds / 36;
// Number of rounds remaining after the 36x loop.
rounds %= 36;
// Lookup tables.
const __m256i lut0 = _mm256_set_epi8(
10, 11, 9, 10, 7, 8, 6, 7, 4, 5, 3, 4, 1, 2, 0, 1,
14, 15, 13, 14, 11, 12, 10, 11, 8, 9, 7, 8, 5, 6, 4, 5);
const __m256i lut1 = _mm256_setr_epi8(
65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0,
65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0);
// Temporary registers.
__m256i a, b, c, d, e;
// Temporary register f doubles as the shift mask for the first round.
__m256i f = _mm256_setr_epi32(0, 0, 1, 2, 3, 4, 5, 6);
__asm__ volatile (
// The first loop iteration requires special handling to ensure
// that the read, which is normally done at an offset of -4,
// does not underflow the buffer. Load the buffer at an offset
// of 0 and permute the input to achieve the same effect.
LOAD("a", 0, 0)
"vpermd %[a], %[f], %[a] \n\t"
// Perform the standard shuffling and translation steps.
SHUF("a", "b", "c")
TRAN("a", "b", "c")
// Store the result and increment the source and dest pointers.
"vmovdqu %[a], (%[dst]) \n\t"
"add $24, %[src] \n\t"
"add $32, %[dst] \n\t"
// If there are 36 rounds or more, enter a 36x unrolled loop of
// interleaved encoding rounds. The rounds interleave memory
// operations (load/store) with data operations (table lookups,
// etc) to maximize pipeline throughput.
" test %[loops], %[loops] \n\t"
" jz 18f \n\t"
" jmp 36f \n\t"
" \n\t"
".balign 64 \n\t"
"36: " ROUND_3_INIT()
" " ROUND_3_A( 0)
" " ROUND_3_B( 3)
" " ROUND_3_A( 6)
" " ROUND_3_B( 9)
" " ROUND_3_A(12)
" " ROUND_3_B(15)
" " ROUND_3_A(18)
" " ROUND_3_B(21)
" " ROUND_3_A(24)
" " ROUND_3_B(27)
" " ROUND_3_A_LAST(30)
" add $(24 * 36), %[src] \n\t"
" add $(32 * 36), %[dst] \n\t"
" dec %[loops] \n\t"
" jnz 36b \n\t"
// Enter an 18x unrolled loop for rounds of 18 or more.
"18: cmp $18, %[rounds] \n\t"
" jl 9f \n\t"
" " ROUND_3_INIT()
" " ROUND_3_A(0)
" " ROUND_3_B(3)
" " ROUND_3_A(6)
" " ROUND_3_B(9)
" " ROUND_3_A_LAST(12)
" sub $18, %[rounds] \n\t"
" add $(24 * 18), %[src] \n\t"
" add $(32 * 18), %[dst] \n\t"
// Enter a 9x unrolled loop for rounds of 9 or more.
"9: cmp $9, %[rounds] \n\t"
" jl 6f \n\t"
" " ROUND_3_INIT()
" " ROUND_3_A(0)
" " ROUND_3_B_LAST(3)
" sub $9, %[rounds] \n\t"
" add $(24 * 9), %[src] \n\t"
" add $(32 * 9), %[dst] \n\t"
// Enter a 6x unrolled loop for rounds of 6 or more.
"6: cmp $6, %[rounds] \n\t"
" jl 55f \n\t"
" " ROUND_3_INIT()
" " ROUND_3_A_LAST(0)
" sub $6, %[rounds] \n\t"
" add $(24 * 6), %[src] \n\t"
" add $(32 * 6), %[dst] \n\t"
// Dispatch the remaining rounds 0..5.
"55: cmp $3, %[rounds] \n\t"
" jg 45f \n\t"
" je 3f \n\t"
" cmp $1, %[rounds] \n\t"
" jg 2f \n\t"
" je 1f \n\t"
" jmp 0f \n\t"
"45: cmp $4, %[rounds] \n\t"
" je 4f \n\t"
// Block of non-interlaced encoding rounds, which can each
// individually be jumped to. Rounds fall through to the next.
"5: " ROUND()
"4: " ROUND()
"3: " ROUND()
"2: " ROUND()
"1: " ROUND()
"0: \n\t"
// Outputs (modified).
: [rounds] "+r" (rounds),
[loops] "+r" (loops),
[src] "+r" (*s),
[dst] "+r" (*o),
[a] "=&x" (a),
[b] "=&x" (b),
[c] "=&x" (c),
[d] "=&x" (d),
[e] "=&x" (e),
[f] "+x" (f)
// Inputs (not modified).
: [lut0] "x" (lut0),
[lut1] "x" (lut1),
[msk0] "x" (_mm256_set1_epi32(0x0FC0FC00)),
[msk1] "x" (_mm256_set1_epi32(0x04000040)),
[msk2] "x" (_mm256_set1_epi32(0x003F03F0)),
[msk3] "x" (_mm256_set1_epi32(0x01000010)),
[n51] "x" (_mm256_set1_epi8(51)),
[n25] "x" (_mm256_set1_epi8(25))
// Clobbers.
: "cc", "memory"
);
}
#pragma GCC diagnostic pop

View File

@@ -0,0 +1,83 @@
static inline __m256i
enc_reshuffle (const __m256i input)
{
// Translation of the SSSE3 reshuffling algorithm to AVX2. This one
// works with shifted (4 bytes) input in order to be able to work
// efficiently in the two 128-bit lanes.
// Input, bytes MSB to LSB:
// 0 0 0 0 x w v u t s r q p o n m
// l k j i h g f e d c b a 0 0 0 0
const __m256i in = _mm256_shuffle_epi8(input, _mm256_set_epi8(
10, 11, 9, 10,
7, 8, 6, 7,
4, 5, 3, 4,
1, 2, 0, 1,
14, 15, 13, 14,
11, 12, 10, 11,
8, 9, 7, 8,
5, 6, 4, 5));
// in, bytes MSB to LSB:
// w x v w
// t u s t
// q r p q
// n o m n
// k l j k
// h i g h
// e f d e
// b c a b
const __m256i t0 = _mm256_and_si256(in, _mm256_set1_epi32(0x0FC0FC00));
// bits, upper case are most significant bits, lower case are least
// significant bits.
// 0000wwww XX000000 VVVVVV00 00000000
// 0000tttt UU000000 SSSSSS00 00000000
// 0000qqqq RR000000 PPPPPP00 00000000
// 0000nnnn OO000000 MMMMMM00 00000000
// 0000kkkk LL000000 JJJJJJ00 00000000
// 0000hhhh II000000 GGGGGG00 00000000
// 0000eeee FF000000 DDDDDD00 00000000
// 0000bbbb CC000000 AAAAAA00 00000000
const __m256i t1 = _mm256_mulhi_epu16(t0, _mm256_set1_epi32(0x04000040));
// 00000000 00wwwwXX 00000000 00VVVVVV
// 00000000 00ttttUU 00000000 00SSSSSS
// 00000000 00qqqqRR 00000000 00PPPPPP
// 00000000 00nnnnOO 00000000 00MMMMMM
// 00000000 00kkkkLL 00000000 00JJJJJJ
// 00000000 00hhhhII 00000000 00GGGGGG
// 00000000 00eeeeFF 00000000 00DDDDDD
// 00000000 00bbbbCC 00000000 00AAAAAA
const __m256i t2 = _mm256_and_si256(in, _mm256_set1_epi32(0x003F03F0));
// 00000000 00xxxxxx 000000vv WWWW0000
// 00000000 00uuuuuu 000000ss TTTT0000
// 00000000 00rrrrrr 000000pp QQQQ0000
// 00000000 00oooooo 000000mm NNNN0000
// 00000000 00llllll 000000jj KKKK0000
// 00000000 00iiiiii 000000gg HHHH0000
// 00000000 00ffffff 000000dd EEEE0000
// 00000000 00cccccc 000000aa BBBB0000
const __m256i t3 = _mm256_mullo_epi16(t2, _mm256_set1_epi32(0x01000010));
// 00xxxxxx 00000000 00vvWWWW 00000000
// 00uuuuuu 00000000 00ssTTTT 00000000
// 00rrrrrr 00000000 00ppQQQQ 00000000
// 00oooooo 00000000 00mmNNNN 00000000
// 00llllll 00000000 00jjKKKK 00000000
// 00iiiiii 00000000 00ggHHHH 00000000
// 00ffffff 00000000 00ddEEEE 00000000
// 00cccccc 00000000 00aaBBBB 00000000
return _mm256_or_si256(t1, t3);
// 00xxxxxx 00wwwwXX 00vvWWWW 00VVVVVV
// 00uuuuuu 00ttttUU 00ssTTTT 00SSSSSS
// 00rrrrrr 00qqqqRR 00ppQQQQ 00PPPPPP
// 00oooooo 00nnnnOO 00mmNNNN 00MMMMMM
// 00llllll 00kkkkLL 00jjKKKK 00JJJJJJ
// 00iiiiii 00hhhhII 00ggHHHH 00GGGGGG
// 00ffffff 00eeeeFF 00ddEEEE 00DDDDDD
// 00cccccc 00bbbbCC 00aaBBBB 00AAAAAA
}

View File

@@ -0,0 +1,30 @@
static inline __m256i
enc_translate (const __m256i in)
{
// A lookup table containing the absolute offsets for all ranges:
const __m256i lut = _mm256_setr_epi8(
65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0,
65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0);
// Translate values 0..63 to the Base64 alphabet. There are five sets:
// # From To Abs Index Characters
// 0 [0..25] [65..90] +65 0 ABCDEFGHIJKLMNOPQRSTUVWXYZ
// 1 [26..51] [97..122] +71 1 abcdefghijklmnopqrstuvwxyz
// 2 [52..61] [48..57] -4 [2..11] 0123456789
// 3 [62] [43] -19 12 +
// 4 [63] [47] -16 13 /
// Create LUT indices from the input. The index for range #0 is right,
// others are 1 less than expected:
__m256i indices = _mm256_subs_epu8(in, _mm256_set1_epi8(51));
// mask is 0xFF (-1) for range #[1..4] and 0x00 for range #0:
const __m256i mask = _mm256_cmpgt_epi8(in, _mm256_set1_epi8(25));
// Subtract -1, so add 1 to indices for range #[1..4]. All indices are
// now correct:
indices = _mm256_sub_epi8(indices, mask);
// Add offsets to input values:
return _mm256_add_epi8(in, _mm256_shuffle_epi8(lut, indices));
}

42
3rdparty/base64/lib/arch/avx512/codec.c vendored Normal file
View File

@@ -0,0 +1,42 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "../../../include/libbase64.h"
#include "../../tables/tables.h"
#include "../../codecs.h"
#include "config.h"
#include "../../env.h"
#if HAVE_AVX512
#include <immintrin.h>
#include "../avx2/dec_reshuffle.c"
#include "../avx2/dec_loop.c"
#include "enc_reshuffle_translate.c"
#include "enc_loop.c"
#endif // HAVE_AVX512
BASE64_ENC_FUNCTION(avx512)
{
#if HAVE_AVX512
#include "../generic/enc_head.c"
enc_loop_avx512(&s, &slen, &o, &olen);
#include "../generic/enc_tail.c"
#else
BASE64_ENC_STUB
#endif
}
// Reuse AVX2 decoding. Not supporting AVX512 at present
BASE64_DEC_FUNCTION(avx512)
{
#if HAVE_AVX512
#include "../generic/dec_head.c"
dec_loop_avx2(&s, &slen, &o, &olen);
#include "../generic/dec_tail.c"
#else
BASE64_DEC_STUB
#endif
}

View File

@@ -0,0 +1,61 @@
static inline void
enc_loop_avx512_inner (const uint8_t **s, uint8_t **o)
{
// Load input.
__m512i src = _mm512_loadu_si512((__m512i *) *s);
// Reshuffle, translate, store.
src = enc_reshuffle_translate(src);
_mm512_storeu_si512((__m512i *) *o, src);
*s += 48;
*o += 64;
}
static inline void
enc_loop_avx512 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 64) {
return;
}
// Process blocks of 48 bytes at a time. Because blocks are loaded 64
// bytes at a time, ensure that there will be at least 24 remaining
// bytes after the last round, so that the final read will not pass
// beyond the bounds of the input buffer.
size_t rounds = (*slen - 24) / 48;
*slen -= rounds * 48; // 48 bytes consumed per round
*olen += rounds * 64; // 64 bytes produced per round
while (rounds > 0) {
if (rounds >= 8) {
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
rounds -= 8;
continue;
}
if (rounds >= 4) {
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
rounds -= 4;
continue;
}
if (rounds >= 2) {
enc_loop_avx512_inner(s, o);
enc_loop_avx512_inner(s, o);
rounds -= 2;
continue;
}
enc_loop_avx512_inner(s, o);
break;
}
}

View File

@@ -0,0 +1,50 @@
// AVX512 algorithm is based on permutevar and multishift. The code is based on
// https://github.com/WojciechMula/base64simd which is under BSD-2 license.
static inline __m512i
enc_reshuffle_translate (const __m512i input)
{
// 32-bit input
// [ 0 0 0 0 0 0 0 0|c1 c0 d5 d4 d3 d2 d1 d0|
// b3 b2 b1 b0 c5 c4 c3 c2|a5 a4 a3 a2 a1 a0 b5 b4]
// output order [1, 2, 0, 1]
// [b3 b2 b1 b0 c5 c4 c3 c2|c1 c0 d5 d4 d3 d2 d1 d0|
// a5 a4 a3 a2 a1 a0 b5 b4|b3 b2 b1 b0 c3 c2 c1 c0]
const __m512i shuffle_input = _mm512_setr_epi32(0x01020001,
0x04050304,
0x07080607,
0x0a0b090a,
0x0d0e0c0d,
0x10110f10,
0x13141213,
0x16171516,
0x191a1819,
0x1c1d1b1c,
0x1f201e1f,
0x22232122,
0x25262425,
0x28292728,
0x2b2c2a2b,
0x2e2f2d2e);
// Reorder bytes
// [b3 b2 b1 b0 c5 c4 c3 c2|c1 c0 d5 d4 d3 d2 d1 d0|
// a5 a4 a3 a2 a1 a0 b5 b4|b3 b2 b1 b0 c3 c2 c1 c0]
const __m512i in = _mm512_permutexvar_epi8(shuffle_input, input);
// After multishift a single 32-bit lane has following layout
// [c1 c0 d5 d4 d3 d2 d1 d0|b1 b0 c5 c4 c3 c2 c1 c0|
// a1 a0 b5 b4 b3 b2 b1 b0|d1 d0 a5 a4 a3 a2 a1 a0]
// (a = [10:17], b = [4:11], c = [22:27], d = [16:21])
// 48, 54, 36, 42, 16, 22, 4, 10
const __m512i shifts = _mm512_set1_epi64(0x3036242a1016040alu);
__m512i shuffled_in = _mm512_multishift_epi64_epi8(shifts, in);
// Translate immediatedly after reshuffled.
const __m512i lookup = _mm512_loadu_si512(base64_table_enc_6bit);
// Translation 6-bit values to ASCII.
return _mm512_permutexvar_epi8(shuffled_in, lookup);
}

View File

@@ -0,0 +1,86 @@
static inline int
dec_loop_generic_32_inner (const uint8_t **s, uint8_t **o, size_t *rounds)
{
const uint32_t str
= base64_table_dec_32bit_d0[(*s)[0]]
| base64_table_dec_32bit_d1[(*s)[1]]
| base64_table_dec_32bit_d2[(*s)[2]]
| base64_table_dec_32bit_d3[(*s)[3]];
#if BASE64_LITTLE_ENDIAN
// LUTs for little-endian set MSB in case of invalid character:
if (str & UINT32_C(0x80000000)) {
return 0;
}
#else
// LUTs for big-endian set LSB in case of invalid character:
if (str & UINT32_C(1)) {
return 0;
}
#endif
// Store the output:
memcpy(*o, &str, sizeof (str));
*s += 4;
*o += 3;
*rounds -= 1;
return 1;
}
static inline void
dec_loop_generic_32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 8) {
return;
}
// Process blocks of 4 bytes per round. Because one extra zero byte is
// written after the output, ensure that there will be at least 4 bytes
// of input data left to cover the gap. (Two data bytes and up to two
// end-of-string markers.)
size_t rounds = (*slen - 4) / 4;
*slen -= rounds * 4; // 4 bytes consumed per round
*olen += rounds * 3; // 3 bytes produced per round
do {
if (rounds >= 8) {
if (dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds)) {
continue;
}
break;
}
if (rounds >= 4) {
if (dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds)) {
continue;
}
break;
}
if (rounds >= 2) {
if (dec_loop_generic_32_inner(s, o, &rounds) &&
dec_loop_generic_32_inner(s, o, &rounds)) {
continue;
}
break;
}
dec_loop_generic_32_inner(s, o, &rounds);
break;
} while (rounds > 0);
// Adjust for any rounds that were skipped:
*slen += rounds * 4;
*olen -= rounds * 3;
}

View File

@@ -0,0 +1,73 @@
static inline void
enc_loop_generic_32_inner (const uint8_t **s, uint8_t **o)
{
uint32_t src;
// Load input:
memcpy(&src, *s, sizeof (src));
// Reorder to 32-bit big-endian, if not already in that format. The
// workset must be in big-endian, otherwise the shifted bits do not
// carry over properly among adjacent bytes:
src = BASE64_HTOBE32(src);
// Two indices for the 12-bit lookup table:
const size_t index0 = (src >> 20) & 0xFFFU;
const size_t index1 = (src >> 8) & 0xFFFU;
// Table lookup and store:
memcpy(*o + 0, base64_table_enc_12bit + index0, 2);
memcpy(*o + 2, base64_table_enc_12bit + index1, 2);
*s += 3;
*o += 4;
}
static inline void
enc_loop_generic_32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 4) {
return;
}
// Process blocks of 3 bytes at a time. Because blocks are loaded 4
// bytes at a time, ensure that there will be at least one remaining
// byte after the last round, so that the final read will not pass
// beyond the bounds of the input buffer:
size_t rounds = (*slen - 1) / 3;
*slen -= rounds * 3; // 3 bytes consumed per round
*olen += rounds * 4; // 4 bytes produced per round
do {
if (rounds >= 8) {
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
rounds -= 8;
continue;
}
if (rounds >= 4) {
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
rounds -= 4;
continue;
}
if (rounds >= 2) {
enc_loop_generic_32_inner(s, o);
enc_loop_generic_32_inner(s, o);
rounds -= 2;
continue;
}
enc_loop_generic_32_inner(s, o);
break;
} while (rounds > 0);
}

View File

@@ -0,0 +1,77 @@
static inline void
enc_loop_generic_64_inner (const uint8_t **s, uint8_t **o)
{
uint64_t src;
// Load input:
memcpy(&src, *s, sizeof (src));
// Reorder to 64-bit big-endian, if not already in that format. The
// workset must be in big-endian, otherwise the shifted bits do not
// carry over properly among adjacent bytes:
src = BASE64_HTOBE64(src);
// Four indices for the 12-bit lookup table:
const size_t index0 = (src >> 52) & 0xFFFU;
const size_t index1 = (src >> 40) & 0xFFFU;
const size_t index2 = (src >> 28) & 0xFFFU;
const size_t index3 = (src >> 16) & 0xFFFU;
// Table lookup and store:
memcpy(*o + 0, base64_table_enc_12bit + index0, 2);
memcpy(*o + 2, base64_table_enc_12bit + index1, 2);
memcpy(*o + 4, base64_table_enc_12bit + index2, 2);
memcpy(*o + 6, base64_table_enc_12bit + index3, 2);
*s += 6;
*o += 8;
}
static inline void
enc_loop_generic_64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 8) {
return;
}
// Process blocks of 6 bytes at a time. Because blocks are loaded 8
// bytes at a time, ensure that there will be at least 2 remaining
// bytes after the last round, so that the final read will not pass
// beyond the bounds of the input buffer:
size_t rounds = (*slen - 2) / 6;
*slen -= rounds * 6; // 6 bytes consumed per round
*olen += rounds * 8; // 8 bytes produced per round
do {
if (rounds >= 8) {
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
rounds -= 8;
continue;
}
if (rounds >= 4) {
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
rounds -= 4;
continue;
}
if (rounds >= 2) {
enc_loop_generic_64_inner(s, o);
enc_loop_generic_64_inner(s, o);
rounds -= 2;
continue;
}
enc_loop_generic_64_inner(s, o);
break;
} while (rounds > 0);
}

View File

@@ -0,0 +1,39 @@
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "../../../include/libbase64.h"
#include "../../tables/tables.h"
#include "../../codecs.h"
#include "config.h"
#include "../../env.h"
#if BASE64_WORDSIZE == 32
# include "32/enc_loop.c"
#elif BASE64_WORDSIZE == 64
# include "64/enc_loop.c"
#endif
#if BASE64_WORDSIZE >= 32
# include "32/dec_loop.c"
#endif
BASE64_ENC_FUNCTION(plain)
{
#include "enc_head.c"
#if BASE64_WORDSIZE == 32
enc_loop_generic_32(&s, &slen, &o, &olen);
#elif BASE64_WORDSIZE == 64
enc_loop_generic_64(&s, &slen, &o, &olen);
#endif
#include "enc_tail.c"
}
BASE64_DEC_FUNCTION(plain)
{
#include "dec_head.c"
#if BASE64_WORDSIZE >= 32
dec_loop_generic_32(&s, &slen, &o, &olen);
#endif
#include "dec_tail.c"
}

View File

@@ -0,0 +1,37 @@
int ret = 0;
const uint8_t *s = (const uint8_t *) src;
uint8_t *o = (uint8_t *) out;
uint8_t q;
// Use local temporaries to avoid cache thrashing:
size_t olen = 0;
size_t slen = srclen;
struct base64_state st;
st.eof = state->eof;
st.bytes = state->bytes;
st.carry = state->carry;
// If we previously saw an EOF or an invalid character, bail out:
if (st.eof) {
*outlen = 0;
ret = 0;
// If there was a trailing '=' to check, check it:
if (slen && (st.eof == BASE64_AEOF)) {
state->bytes = 0;
state->eof = BASE64_EOF;
ret = ((base64_table_dec_8bit[*s++] == 254) && (slen == 1)) ? 1 : 0;
}
return ret;
}
// Turn four 6-bit numbers into three bytes:
// out[0] = 11111122
// out[1] = 22223333
// out[2] = 33444444
// Duff's device again:
switch (st.bytes)
{
for (;;)
{
case 0:

View File

@@ -0,0 +1,91 @@
if (slen-- == 0) {
ret = 1;
break;
}
if ((q = base64_table_dec_8bit[*s++]) >= 254) {
st.eof = BASE64_EOF;
// Treat character '=' as invalid for byte 0:
break;
}
st.carry = q << 2;
st.bytes++;
// Deliberate fallthrough:
BASE64_FALLTHROUGH
case 1: if (slen-- == 0) {
ret = 1;
break;
}
if ((q = base64_table_dec_8bit[*s++]) >= 254) {
st.eof = BASE64_EOF;
// Treat character '=' as invalid for byte 1:
break;
}
*o++ = st.carry | (q >> 4);
st.carry = q << 4;
st.bytes++;
olen++;
// Deliberate fallthrough:
BASE64_FALLTHROUGH
case 2: if (slen-- == 0) {
ret = 1;
break;
}
if ((q = base64_table_dec_8bit[*s++]) >= 254) {
st.bytes++;
// When q == 254, the input char is '='.
// Check if next byte is also '=':
if (q == 254) {
if (slen-- != 0) {
st.bytes = 0;
// EOF:
st.eof = BASE64_EOF;
q = base64_table_dec_8bit[*s++];
ret = ((q == 254) && (slen == 0)) ? 1 : 0;
break;
}
else {
// Almost EOF
st.eof = BASE64_AEOF;
ret = 1;
break;
}
}
// If we get here, there was an error:
break;
}
*o++ = st.carry | (q >> 2);
st.carry = q << 6;
st.bytes++;
olen++;
// Deliberate fallthrough:
BASE64_FALLTHROUGH
case 3: if (slen-- == 0) {
ret = 1;
break;
}
if ((q = base64_table_dec_8bit[*s++]) >= 254) {
st.bytes = 0;
st.eof = BASE64_EOF;
// When q == 254, the input char is '='. Return 1 and EOF.
// When q == 255, the input char is invalid. Return 0 and EOF.
ret = ((q == 254) && (slen == 0)) ? 1 : 0;
break;
}
*o++ = st.carry | q;
st.carry = 0;
st.bytes = 0;
olen++;
}
}
state->eof = st.eof;
state->bytes = st.bytes;
state->carry = st.carry;
*outlen = olen;
return ret;

View File

@@ -0,0 +1,24 @@
// Assume that *out is large enough to contain the output.
// Theoretically it should be 4/3 the length of src.
const uint8_t *s = (const uint8_t *) src;
uint8_t *o = (uint8_t *) out;
// Use local temporaries to avoid cache thrashing:
size_t olen = 0;
size_t slen = srclen;
struct base64_state st;
st.bytes = state->bytes;
st.carry = state->carry;
// Turn three bytes into four 6-bit numbers:
// in[0] = 00111111
// in[1] = 00112222
// in[2] = 00222233
// in[3] = 00333333
// Duff's device, a for() loop inside a switch() statement. Legal!
switch (st.bytes)
{
for (;;)
{
case 0:

View File

@@ -0,0 +1,34 @@
if (slen-- == 0) {
break;
}
*o++ = base64_table_enc_6bit[*s >> 2];
st.carry = (*s++ << 4) & 0x30;
st.bytes++;
olen += 1;
// Deliberate fallthrough:
BASE64_FALLTHROUGH
case 1: if (slen-- == 0) {
break;
}
*o++ = base64_table_enc_6bit[st.carry | (*s >> 4)];
st.carry = (*s++ << 2) & 0x3C;
st.bytes++;
olen += 1;
// Deliberate fallthrough:
BASE64_FALLTHROUGH
case 2: if (slen-- == 0) {
break;
}
*o++ = base64_table_enc_6bit[st.carry | (*s >> 6)];
*o++ = base64_table_enc_6bit[*s++ & 0x3F];
st.bytes = 0;
olen += 2;
}
}
state->bytes = st.bytes;
state->carry = st.carry;
*outlen = olen;

77
3rdparty/base64/lib/arch/neon32/codec.c vendored Normal file
View File

@@ -0,0 +1,77 @@
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "../../../include/libbase64.h"
#include "../../tables/tables.h"
#include "../../codecs.h"
#include "config.h"
#include "../../env.h"
#ifdef __arm__
# if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && HAVE_NEON32
# define BASE64_USE_NEON32
# endif
#endif
#ifdef BASE64_USE_NEON32
#include <arm_neon.h>
// Only enable inline assembly on supported compilers.
#if defined(__GNUC__) || defined(__clang__)
#define BASE64_NEON32_USE_ASM
#endif
static inline uint8x16_t
vqtbl1q_u8 (const uint8x16_t lut, const uint8x16_t indices)
{
// NEON32 only supports 64-bit wide lookups in 128-bit tables. Emulate
// the NEON64 `vqtbl1q_u8` intrinsic to do 128-bit wide lookups.
uint8x8x2_t lut2;
uint8x8x2_t result;
lut2.val[0] = vget_low_u8(lut);
lut2.val[1] = vget_high_u8(lut);
result.val[0] = vtbl2_u8(lut2, vget_low_u8(indices));
result.val[1] = vtbl2_u8(lut2, vget_high_u8(indices));
return vcombine_u8(result.val[0], result.val[1]);
}
#include "../generic/32/dec_loop.c"
#include "../generic/32/enc_loop.c"
#include "dec_loop.c"
#include "enc_reshuffle.c"
#include "enc_translate.c"
#include "enc_loop.c"
#endif // BASE64_USE_NEON32
// Stride size is so large on these NEON 32-bit functions
// (48 bytes encode, 32 bytes decode) that we inline the
// uint32 codec to stay performant on smaller inputs.
BASE64_ENC_FUNCTION(neon32)
{
#ifdef BASE64_USE_NEON32
#include "../generic/enc_head.c"
enc_loop_neon32(&s, &slen, &o, &olen);
enc_loop_generic_32(&s, &slen, &o, &olen);
#include "../generic/enc_tail.c"
#else
BASE64_ENC_STUB
#endif
}
BASE64_DEC_FUNCTION(neon32)
{
#ifdef BASE64_USE_NEON32
#include "../generic/dec_head.c"
dec_loop_neon32(&s, &slen, &o, &olen);
dec_loop_generic_32(&s, &slen, &o, &olen);
#include "../generic/dec_tail.c"
#else
BASE64_DEC_STUB
#endif
}

View File

@@ -0,0 +1,106 @@
static inline int
is_nonzero (const uint8x16_t v)
{
uint64_t u64;
const uint64x2_t v64 = vreinterpretq_u64_u8(v);
const uint32x2_t v32 = vqmovn_u64(v64);
vst1_u64(&u64, vreinterpret_u64_u32(v32));
return u64 != 0;
}
static inline uint8x16_t
delta_lookup (const uint8x16_t v)
{
const uint8x8_t lut = {
0, 16, 19, 4, (uint8_t) -65, (uint8_t) -65, (uint8_t) -71, (uint8_t) -71,
};
return vcombine_u8(
vtbl1_u8(lut, vget_low_u8(v)),
vtbl1_u8(lut, vget_high_u8(v)));
}
static inline uint8x16_t
dec_loop_neon32_lane (uint8x16_t *lane)
{
// See the SSSE3 decoder for an explanation of the algorithm.
const uint8x16_t lut_lo = {
0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x13, 0x1A, 0x1B, 0x1B, 0x1B, 0x1A
};
const uint8x16_t lut_hi = {
0x10, 0x10, 0x01, 0x02, 0x04, 0x08, 0x04, 0x08,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
};
const uint8x16_t mask_0F = vdupq_n_u8(0x0F);
const uint8x16_t mask_2F = vdupq_n_u8(0x2F);
const uint8x16_t hi_nibbles = vshrq_n_u8(*lane, 4);
const uint8x16_t lo_nibbles = vandq_u8(*lane, mask_0F);
const uint8x16_t eq_2F = vceqq_u8(*lane, mask_2F);
const uint8x16_t hi = vqtbl1q_u8(lut_hi, hi_nibbles);
const uint8x16_t lo = vqtbl1q_u8(lut_lo, lo_nibbles);
// Now simply add the delta values to the input:
*lane = vaddq_u8(*lane, delta_lookup(vaddq_u8(eq_2F, hi_nibbles)));
// Return the validity mask:
return vandq_u8(lo, hi);
}
static inline void
dec_loop_neon32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 64) {
return;
}
// Process blocks of 64 bytes per round. Unlike the SSE codecs, no
// extra trailing zero bytes are written, so it is not necessary to
// reserve extra input bytes:
size_t rounds = *slen / 64;
*slen -= rounds * 64; // 64 bytes consumed per round
*olen += rounds * 48; // 48 bytes produced per round
do {
uint8x16x3_t dec;
// Load 64 bytes and deinterleave:
uint8x16x4_t str = vld4q_u8(*s);
// Decode each lane, collect a mask of invalid inputs:
const uint8x16_t classified
= dec_loop_neon32_lane(&str.val[0])
| dec_loop_neon32_lane(&str.val[1])
| dec_loop_neon32_lane(&str.val[2])
| dec_loop_neon32_lane(&str.val[3]);
// Check for invalid input: if any of the delta values are
// zero, fall back on bytewise code to do error checking and
// reporting:
if (is_nonzero(classified)) {
break;
}
// Compress four bytes into three:
dec.val[0] = vorrq_u8(vshlq_n_u8(str.val[0], 2), vshrq_n_u8(str.val[1], 4));
dec.val[1] = vorrq_u8(vshlq_n_u8(str.val[1], 4), vshrq_n_u8(str.val[2], 2));
dec.val[2] = vorrq_u8(vshlq_n_u8(str.val[2], 6), str.val[3]);
// Interleave and store decoded result:
vst3q_u8(*o, dec);
*s += 64;
*o += 48;
} while (--rounds > 0);
// Adjust for any rounds that were skipped:
*slen += rounds * 64;
*olen -= rounds * 48;
}

View File

@@ -0,0 +1,170 @@
#ifdef BASE64_NEON32_USE_ASM
static inline void
enc_loop_neon32_inner_asm (const uint8_t **s, uint8_t **o)
{
// This function duplicates the functionality of enc_loop_neon32_inner,
// but entirely with inline assembly. This gives a significant speedup
// over using NEON intrinsics, which do not always generate very good
// code. The logic of the assembly is directly lifted from the
// intrinsics version, so it can be used as a guide to this code.
// Temporary registers, used as scratch space.
uint8x16_t tmp0, tmp1, tmp2, tmp3;
uint8x16_t mask0, mask1, mask2, mask3;
// A lookup table containing the absolute offsets for all ranges.
const uint8x16_t lut = {
65U, 71U, 252U, 252U,
252U, 252U, 252U, 252U,
252U, 252U, 252U, 252U,
237U, 240U, 0U, 0U
};
// Numeric constants.
const uint8x16_t n51 = vdupq_n_u8(51);
const uint8x16_t n25 = vdupq_n_u8(25);
const uint8x16_t n63 = vdupq_n_u8(63);
__asm__ (
// Load 48 bytes and deinterleave. The bytes are loaded to
// hard-coded registers q12, q13 and q14, to ensure that they
// are contiguous. Increment the source pointer.
"vld3.8 {d24, d26, d28}, [%[src]]! \n\t"
"vld3.8 {d25, d27, d29}, [%[src]]! \n\t"
// Reshuffle the bytes using temporaries.
"vshr.u8 %q[t0], q12, #2 \n\t"
"vshr.u8 %q[t1], q13, #4 \n\t"
"vshr.u8 %q[t2], q14, #6 \n\t"
"vsli.8 %q[t1], q12, #4 \n\t"
"vsli.8 %q[t2], q13, #2 \n\t"
"vand.u8 %q[t1], %q[t1], %q[n63] \n\t"
"vand.u8 %q[t2], %q[t2], %q[n63] \n\t"
"vand.u8 %q[t3], q14, %q[n63] \n\t"
// t0..t3 are the reshuffled inputs. Create LUT indices.
"vqsub.u8 q12, %q[t0], %q[n51] \n\t"
"vqsub.u8 q13, %q[t1], %q[n51] \n\t"
"vqsub.u8 q14, %q[t2], %q[n51] \n\t"
"vqsub.u8 q15, %q[t3], %q[n51] \n\t"
// Create the mask for range #0.
"vcgt.u8 %q[m0], %q[t0], %q[n25] \n\t"
"vcgt.u8 %q[m1], %q[t1], %q[n25] \n\t"
"vcgt.u8 %q[m2], %q[t2], %q[n25] \n\t"
"vcgt.u8 %q[m3], %q[t3], %q[n25] \n\t"
// Subtract -1 to correct the LUT indices.
"vsub.u8 q12, %q[m0] \n\t"
"vsub.u8 q13, %q[m1] \n\t"
"vsub.u8 q14, %q[m2] \n\t"
"vsub.u8 q15, %q[m3] \n\t"
// Lookup the delta values.
"vtbl.u8 d24, {%q[lut]}, d24 \n\t"
"vtbl.u8 d25, {%q[lut]}, d25 \n\t"
"vtbl.u8 d26, {%q[lut]}, d26 \n\t"
"vtbl.u8 d27, {%q[lut]}, d27 \n\t"
"vtbl.u8 d28, {%q[lut]}, d28 \n\t"
"vtbl.u8 d29, {%q[lut]}, d29 \n\t"
"vtbl.u8 d30, {%q[lut]}, d30 \n\t"
"vtbl.u8 d31, {%q[lut]}, d31 \n\t"
// Add the delta values.
"vadd.u8 q12, %q[t0] \n\t"
"vadd.u8 q13, %q[t1] \n\t"
"vadd.u8 q14, %q[t2] \n\t"
"vadd.u8 q15, %q[t3] \n\t"
// Store 64 bytes and interleave. Increment the dest pointer.
"vst4.8 {d24, d26, d28, d30}, [%[dst]]! \n\t"
"vst4.8 {d25, d27, d29, d31}, [%[dst]]! \n\t"
// Outputs (modified).
: [src] "+r" (*s),
[dst] "+r" (*o),
[t0] "=&w" (tmp0),
[t1] "=&w" (tmp1),
[t2] "=&w" (tmp2),
[t3] "=&w" (tmp3),
[m0] "=&w" (mask0),
[m1] "=&w" (mask1),
[m2] "=&w" (mask2),
[m3] "=&w" (mask3)
// Inputs (not modified).
: [lut] "w" (lut),
[n25] "w" (n25),
[n51] "w" (n51),
[n63] "w" (n63)
// Clobbers.
: "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
"cc", "memory"
);
}
#endif
static inline void
enc_loop_neon32_inner (const uint8_t **s, uint8_t **o)
{
#ifdef BASE64_NEON32_USE_ASM
enc_loop_neon32_inner_asm(s, o);
#else
// Load 48 bytes and deinterleave:
uint8x16x3_t src = vld3q_u8(*s);
// Reshuffle:
uint8x16x4_t out = enc_reshuffle(src);
// Translate reshuffled bytes to the Base64 alphabet:
out = enc_translate(out);
// Interleave and store output:
vst4q_u8(*o, out);
*s += 48;
*o += 64;
#endif
}
static inline void
enc_loop_neon32 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
size_t rounds = *slen / 48;
*slen -= rounds * 48; // 48 bytes consumed per round
*olen += rounds * 64; // 64 bytes produced per round
while (rounds > 0) {
if (rounds >= 8) {
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
rounds -= 8;
continue;
}
if (rounds >= 4) {
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
rounds -= 4;
continue;
}
if (rounds >= 2) {
enc_loop_neon32_inner(s, o);
enc_loop_neon32_inner(s, o);
rounds -= 2;
continue;
}
enc_loop_neon32_inner(s, o);
break;
}
}

View File

@@ -0,0 +1,31 @@
static inline uint8x16x4_t
enc_reshuffle (uint8x16x3_t in)
{
uint8x16x4_t out;
// Input:
// in[0] = a7 a6 a5 a4 a3 a2 a1 a0
// in[1] = b7 b6 b5 b4 b3 b2 b1 b0
// in[2] = c7 c6 c5 c4 c3 c2 c1 c0
// Output:
// out[0] = 00 00 a7 a6 a5 a4 a3 a2
// out[1] = 00 00 a1 a0 b7 b6 b5 b4
// out[2] = 00 00 b3 b2 b1 b0 c7 c6
// out[3] = 00 00 c5 c4 c3 c2 c1 c0
// Move the input bits to where they need to be in the outputs. Except
// for the first output, the high two bits are not cleared.
out.val[0] = vshrq_n_u8(in.val[0], 2);
out.val[1] = vshrq_n_u8(in.val[1], 4);
out.val[2] = vshrq_n_u8(in.val[2], 6);
out.val[1] = vsliq_n_u8(out.val[1], in.val[0], 4);
out.val[2] = vsliq_n_u8(out.val[2], in.val[1], 2);
// Clear the high two bits in the second, third and fourth output.
out.val[1] = vandq_u8(out.val[1], vdupq_n_u8(0x3F));
out.val[2] = vandq_u8(out.val[2], vdupq_n_u8(0x3F));
out.val[3] = vandq_u8(in.val[2], vdupq_n_u8(0x3F));
return out;
}

View File

@@ -0,0 +1,57 @@
static inline uint8x16x4_t
enc_translate (const uint8x16x4_t in)
{
// A lookup table containing the absolute offsets for all ranges:
const uint8x16_t lut = {
65U, 71U, 252U, 252U,
252U, 252U, 252U, 252U,
252U, 252U, 252U, 252U,
237U, 240U, 0U, 0U
};
const uint8x16_t offset = vdupq_n_u8(51);
uint8x16x4_t indices, mask, delta, out;
// Translate values 0..63 to the Base64 alphabet. There are five sets:
// # From To Abs Index Characters
// 0 [0..25] [65..90] +65 0 ABCDEFGHIJKLMNOPQRSTUVWXYZ
// 1 [26..51] [97..122] +71 1 abcdefghijklmnopqrstuvwxyz
// 2 [52..61] [48..57] -4 [2..11] 0123456789
// 3 [62] [43] -19 12 +
// 4 [63] [47] -16 13 /
// Create LUT indices from input:
// the index for range #0 is right, others are 1 less than expected:
indices.val[0] = vqsubq_u8(in.val[0], offset);
indices.val[1] = vqsubq_u8(in.val[1], offset);
indices.val[2] = vqsubq_u8(in.val[2], offset);
indices.val[3] = vqsubq_u8(in.val[3], offset);
// mask is 0xFF (-1) for range #[1..4] and 0x00 for range #0:
mask.val[0] = vcgtq_u8(in.val[0], vdupq_n_u8(25));
mask.val[1] = vcgtq_u8(in.val[1], vdupq_n_u8(25));
mask.val[2] = vcgtq_u8(in.val[2], vdupq_n_u8(25));
mask.val[3] = vcgtq_u8(in.val[3], vdupq_n_u8(25));
// Subtract -1, so add 1 to indices for range #[1..4], All indices are
// now correct:
indices.val[0] = vsubq_u8(indices.val[0], mask.val[0]);
indices.val[1] = vsubq_u8(indices.val[1], mask.val[1]);
indices.val[2] = vsubq_u8(indices.val[2], mask.val[2]);
indices.val[3] = vsubq_u8(indices.val[3], mask.val[3]);
// Lookup delta values:
delta.val[0] = vqtbl1q_u8(lut, indices.val[0]);
delta.val[1] = vqtbl1q_u8(lut, indices.val[1]);
delta.val[2] = vqtbl1q_u8(lut, indices.val[2]);
delta.val[3] = vqtbl1q_u8(lut, indices.val[3]);
// Add delta values:
out.val[0] = vaddq_u8(in.val[0], delta.val[0]);
out.val[1] = vaddq_u8(in.val[1], delta.val[1]);
out.val[2] = vaddq_u8(in.val[2], delta.val[2]);
out.val[3] = vaddq_u8(in.val[3], delta.val[3]);
return out;
}

97
3rdparty/base64/lib/arch/neon64/codec.c vendored Normal file
View File

@@ -0,0 +1,97 @@
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "../../../include/libbase64.h"
#include "../../tables/tables.h"
#include "../../codecs.h"
#include "config.h"
#include "../../env.h"
#ifdef __aarch64__
# if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && HAVE_NEON64
# define BASE64_USE_NEON64
# endif
#endif
#ifdef BASE64_USE_NEON64
#include <arm_neon.h>
// Only enable inline assembly on supported compilers.
#if defined(__GNUC__) || defined(__clang__)
#define BASE64_NEON64_USE_ASM
#endif
static inline uint8x16x4_t
load_64byte_table (const uint8_t *p)
{
#ifdef BASE64_NEON64_USE_ASM
// Force the table to be loaded into contiguous registers. GCC will not
// normally allocate contiguous registers for a `uint8x16x4_t'. These
// registers are chosen to not conflict with the ones in the enc loop.
register uint8x16_t t0 __asm__ ("v8");
register uint8x16_t t1 __asm__ ("v9");
register uint8x16_t t2 __asm__ ("v10");
register uint8x16_t t3 __asm__ ("v11");
__asm__ (
"ld1 {%[t0].16b, %[t1].16b, %[t2].16b, %[t3].16b}, [%[src]], #64 \n\t"
: [src] "+r" (p),
[t0] "=w" (t0),
[t1] "=w" (t1),
[t2] "=w" (t2),
[t3] "=w" (t3)
);
return (uint8x16x4_t) {
.val[0] = t0,
.val[1] = t1,
.val[2] = t2,
.val[3] = t3,
};
#else
return vld1q_u8_x4(p);
#endif
}
#include "../generic/32/dec_loop.c"
#include "../generic/64/enc_loop.c"
#include "dec_loop.c"
#ifdef BASE64_NEON64_USE_ASM
# include "enc_loop_asm.c"
#else
# include "enc_reshuffle.c"
# include "enc_loop.c"
#endif
#endif // BASE64_USE_NEON64
// Stride size is so large on these NEON 64-bit functions
// (48 bytes encode, 64 bytes decode) that we inline the
// uint64 codec to stay performant on smaller inputs.
BASE64_ENC_FUNCTION(neon64)
{
#ifdef BASE64_USE_NEON64
#include "../generic/enc_head.c"
enc_loop_neon64(&s, &slen, &o, &olen);
enc_loop_generic_64(&s, &slen, &o, &olen);
#include "../generic/enc_tail.c"
#else
BASE64_ENC_STUB
#endif
}
BASE64_DEC_FUNCTION(neon64)
{
#ifdef BASE64_USE_NEON64
#include "../generic/dec_head.c"
dec_loop_neon64(&s, &slen, &o, &olen);
dec_loop_generic_32(&s, &slen, &o, &olen);
#include "../generic/dec_tail.c"
#else
BASE64_DEC_STUB
#endif
}

View File

@@ -0,0 +1,129 @@
// The input consists of five valid character sets in the Base64 alphabet,
// which we need to map back to the 6-bit values they represent.
// There are three ranges, two singles, and then there's the rest.
//
// # From To LUT Characters
// 1 [0..42] [255] #1 invalid input
// 2 [43] [62] #1 +
// 3 [44..46] [255] #1 invalid input
// 4 [47] [63] #1 /
// 5 [48..57] [52..61] #1 0..9
// 6 [58..63] [255] #1 invalid input
// 7 [64] [255] #2 invalid input
// 8 [65..90] [0..25] #2 A..Z
// 9 [91..96] [255] #2 invalid input
// 10 [97..122] [26..51] #2 a..z
// 11 [123..126] [255] #2 invalid input
// (12) Everything else => invalid input
// The first LUT will use the VTBL instruction (out of range indices are set to
// 0 in destination).
static const uint8_t dec_lut1[] = {
255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U,
255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U,
255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 62U, 255U, 255U, 255U, 63U,
52U, 53U, 54U, 55U, 56U, 57U, 58U, 59U, 60U, 61U, 255U, 255U, 255U, 255U, 255U, 255U,
};
// The second LUT will use the VTBX instruction (out of range indices will be
// unchanged in destination). Input [64..126] will be mapped to index [1..63]
// in this LUT. Index 0 means that value comes from LUT #1.
static const uint8_t dec_lut2[] = {
0U, 255U, 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U,
14U, 15U, 16U, 17U, 18U, 19U, 20U, 21U, 22U, 23U, 24U, 25U, 255U, 255U, 255U, 255U,
255U, 255U, 26U, 27U, 28U, 29U, 30U, 31U, 32U, 33U, 34U, 35U, 36U, 37U, 38U, 39U,
40U, 41U, 42U, 43U, 44U, 45U, 46U, 47U, 48U, 49U, 50U, 51U, 255U, 255U, 255U, 255U,
};
// All input values in range for the first look-up will be 0U in the second
// look-up result. All input values out of range for the first look-up will be
// 0U in the first look-up result. Thus, the two results can be ORed without
// conflicts.
//
// Invalid characters that are in the valid range for either look-up will be
// set to 255U in the combined result. Other invalid characters will just be
// passed through with the second look-up result (using the VTBX instruction).
// Since the second LUT is 64 bytes, those passed-through values are guaranteed
// to have a value greater than 63U. Therefore, valid characters will be mapped
// to the valid [0..63] range and all invalid characters will be mapped to
// values greater than 63.
static inline void
dec_loop_neon64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 64) {
return;
}
// Process blocks of 64 bytes per round. Unlike the SSE codecs, no
// extra trailing zero bytes are written, so it is not necessary to
// reserve extra input bytes:
size_t rounds = *slen / 64;
*slen -= rounds * 64; // 64 bytes consumed per round
*olen += rounds * 48; // 48 bytes produced per round
const uint8x16x4_t tbl_dec1 = load_64byte_table(dec_lut1);
const uint8x16x4_t tbl_dec2 = load_64byte_table(dec_lut2);
do {
const uint8x16_t offset = vdupq_n_u8(63U);
uint8x16x4_t dec1, dec2;
uint8x16x3_t dec;
// Load 64 bytes and deinterleave:
uint8x16x4_t str = vld4q_u8((uint8_t *) *s);
// Get indices for second LUT:
dec2.val[0] = vqsubq_u8(str.val[0], offset);
dec2.val[1] = vqsubq_u8(str.val[1], offset);
dec2.val[2] = vqsubq_u8(str.val[2], offset);
dec2.val[3] = vqsubq_u8(str.val[3], offset);
// Get values from first LUT:
dec1.val[0] = vqtbl4q_u8(tbl_dec1, str.val[0]);
dec1.val[1] = vqtbl4q_u8(tbl_dec1, str.val[1]);
dec1.val[2] = vqtbl4q_u8(tbl_dec1, str.val[2]);
dec1.val[3] = vqtbl4q_u8(tbl_dec1, str.val[3]);
// Get values from second LUT:
dec2.val[0] = vqtbx4q_u8(dec2.val[0], tbl_dec2, dec2.val[0]);
dec2.val[1] = vqtbx4q_u8(dec2.val[1], tbl_dec2, dec2.val[1]);
dec2.val[2] = vqtbx4q_u8(dec2.val[2], tbl_dec2, dec2.val[2]);
dec2.val[3] = vqtbx4q_u8(dec2.val[3], tbl_dec2, dec2.val[3]);
// Get final values:
str.val[0] = vorrq_u8(dec1.val[0], dec2.val[0]);
str.val[1] = vorrq_u8(dec1.val[1], dec2.val[1]);
str.val[2] = vorrq_u8(dec1.val[2], dec2.val[2]);
str.val[3] = vorrq_u8(dec1.val[3], dec2.val[3]);
// Check for invalid input, any value larger than 63:
const uint8x16_t classified
= vcgtq_u8(str.val[0], vdupq_n_u8(63))
| vcgtq_u8(str.val[1], vdupq_n_u8(63))
| vcgtq_u8(str.val[2], vdupq_n_u8(63))
| vcgtq_u8(str.val[3], vdupq_n_u8(63));
// Check that all bits are zero:
if (vmaxvq_u8(classified) != 0U) {
break;
}
// Compress four bytes into three:
dec.val[0] = vshlq_n_u8(str.val[0], 2) | vshrq_n_u8(str.val[1], 4);
dec.val[1] = vshlq_n_u8(str.val[1], 4) | vshrq_n_u8(str.val[2], 2);
dec.val[2] = vshlq_n_u8(str.val[2], 6) | str.val[3];
// Interleave and store decoded result:
vst3q_u8((uint8_t *) *o, dec);
*s += 64;
*o += 48;
} while (--rounds > 0);
// Adjust for any rounds that were skipped:
*slen += rounds * 64;
*olen -= rounds * 48;
}

View File

@@ -0,0 +1,66 @@
static inline void
enc_loop_neon64_inner (const uint8_t **s, uint8_t **o, const uint8x16x4_t tbl_enc)
{
// Load 48 bytes and deinterleave:
uint8x16x3_t src = vld3q_u8(*s);
// Divide bits of three input bytes over four output bytes:
uint8x16x4_t out = enc_reshuffle(src);
// The bits have now been shifted to the right locations;
// translate their values 0..63 to the Base64 alphabet.
// Use a 64-byte table lookup:
out.val[0] = vqtbl4q_u8(tbl_enc, out.val[0]);
out.val[1] = vqtbl4q_u8(tbl_enc, out.val[1]);
out.val[2] = vqtbl4q_u8(tbl_enc, out.val[2]);
out.val[3] = vqtbl4q_u8(tbl_enc, out.val[3]);
// Interleave and store output:
vst4q_u8(*o, out);
*s += 48;
*o += 64;
}
static inline void
enc_loop_neon64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
size_t rounds = *slen / 48;
*slen -= rounds * 48; // 48 bytes consumed per round
*olen += rounds * 64; // 64 bytes produced per round
// Load the encoding table:
const uint8x16x4_t tbl_enc = load_64byte_table(base64_table_enc_6bit);
while (rounds > 0) {
if (rounds >= 8) {
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
rounds -= 8;
continue;
}
if (rounds >= 4) {
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
rounds -= 4;
continue;
}
if (rounds >= 2) {
enc_loop_neon64_inner(s, o, tbl_enc);
enc_loop_neon64_inner(s, o, tbl_enc);
rounds -= 2;
continue;
}
enc_loop_neon64_inner(s, o, tbl_enc);
break;
}
}

View File

@@ -0,0 +1,168 @@
// Apologies in advance for combining the preprocessor with inline assembly,
// two notoriously gnarly parts of C, but it was necessary to avoid a lot of
// code repetition. The preprocessor is used to template large sections of
// inline assembly that differ only in the registers used. If the code was
// written out by hand, it would become very large and hard to audit.
// Generate a block of inline assembly that loads three user-defined registers
// A, B, C from memory and deinterleaves them, post-incrementing the src
// pointer. The register set should be sequential.
#define LOAD(A, B, C) \
"ld3 {"A".16b, "B".16b, "C".16b}, [%[src]], #48 \n\t"
// Generate a block of inline assembly that takes three deinterleaved registers
// and shuffles the bytes. The output is in temporary registers t0..t3.
#define SHUF(A, B, C) \
"ushr %[t0].16b, "A".16b, #2 \n\t" \
"ushr %[t1].16b, "B".16b, #4 \n\t" \
"ushr %[t2].16b, "C".16b, #6 \n\t" \
"sli %[t1].16b, "A".16b, #4 \n\t" \
"sli %[t2].16b, "B".16b, #2 \n\t" \
"and %[t1].16b, %[t1].16b, %[n63].16b \n\t" \
"and %[t2].16b, %[t2].16b, %[n63].16b \n\t" \
"and %[t3].16b, "C".16b, %[n63].16b \n\t"
// Generate a block of inline assembly that takes temporary registers t0..t3
// and translates them to the base64 alphabet, using a table loaded into
// v8..v11. The output is in user-defined registers A..D.
#define TRAN(A, B, C, D) \
"tbl "A".16b, {v8.16b-v11.16b}, %[t0].16b \n\t" \
"tbl "B".16b, {v8.16b-v11.16b}, %[t1].16b \n\t" \
"tbl "C".16b, {v8.16b-v11.16b}, %[t2].16b \n\t" \
"tbl "D".16b, {v8.16b-v11.16b}, %[t3].16b \n\t"
// Generate a block of inline assembly that interleaves four registers and
// stores them, post-incrementing the destination pointer.
#define STOR(A, B, C, D) \
"st4 {"A".16b, "B".16b, "C".16b, "D".16b}, [%[dst]], #64 \n\t"
// Generate a block of inline assembly that generates a single self-contained
// encoder round: fetch the data, process it, and store the result.
#define ROUND() \
LOAD("v12", "v13", "v14") \
SHUF("v12", "v13", "v14") \
TRAN("v12", "v13", "v14", "v15") \
STOR("v12", "v13", "v14", "v15")
// Generate a block of assembly that generates a type A interleaved encoder
// round. It uses registers that were loaded by the previous type B round, and
// in turn loads registers for the next type B round.
#define ROUND_A() \
SHUF("v2", "v3", "v4") \
LOAD("v12", "v13", "v14") \
TRAN("v2", "v3", "v4", "v5") \
STOR("v2", "v3", "v4", "v5")
// Type B interleaved encoder round. Same as type A, but register sets swapped.
#define ROUND_B() \
SHUF("v12", "v13", "v14") \
LOAD("v2", "v3", "v4") \
TRAN("v12", "v13", "v14", "v15") \
STOR("v12", "v13", "v14", "v15")
// The first type A round needs to load its own registers.
#define ROUND_A_FIRST() \
LOAD("v2", "v3", "v4") \
ROUND_A()
// The last type B round omits the load for the next step.
#define ROUND_B_LAST() \
SHUF("v12", "v13", "v14") \
TRAN("v12", "v13", "v14", "v15") \
STOR("v12", "v13", "v14", "v15")
// Suppress clang's warning that the literal string in the asm statement is
// overlong (longer than the ISO-mandated minimum size of 4095 bytes for C99
// compilers). It may be true, but the goal here is not C99 portability.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverlength-strings"
static inline void
enc_loop_neon64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
size_t rounds = *slen / 48;
if (rounds == 0) {
return;
}
*slen -= rounds * 48; // 48 bytes consumed per round.
*olen += rounds * 64; // 64 bytes produced per round.
// Number of times to go through the 8x loop.
size_t loops = rounds / 8;
// Number of rounds remaining after the 8x loop.
rounds %= 8;
// Temporary registers, used as scratch space.
uint8x16_t tmp0, tmp1, tmp2, tmp3;
__asm__ volatile (
// Load the encoding table into v8..v11.
" ld1 {v8.16b-v11.16b}, [%[tbl]] \n\t"
// If there are eight rounds or more, enter an 8x unrolled loop
// of interleaved encoding rounds. The rounds interleave memory
// operations (load/store) with data operations to maximize
// pipeline throughput.
" cbz %[loops], 4f \n\t"
// The SIMD instructions do not touch the flags.
"88: subs %[loops], %[loops], #1 \n\t"
" " ROUND_A_FIRST()
" " ROUND_B()
" " ROUND_A()
" " ROUND_B()
" " ROUND_A()
" " ROUND_B()
" " ROUND_A()
" " ROUND_B_LAST()
" b.ne 88b \n\t"
// Enter a 4x unrolled loop for rounds of 4 or more.
"4: cmp %[rounds], #4 \n\t"
" b.lt 30f \n\t"
" " ROUND_A_FIRST()
" " ROUND_B()
" " ROUND_A()
" " ROUND_B_LAST()
" sub %[rounds], %[rounds], #4 \n\t"
// Dispatch the remaining rounds 0..3.
"30: cbz %[rounds], 0f \n\t"
" cmp %[rounds], #2 \n\t"
" b.eq 2f \n\t"
" b.lt 1f \n\t"
// Block of non-interlaced encoding rounds, which can each
// individually be jumped to. Rounds fall through to the next.
"3: " ROUND()
"2: " ROUND()
"1: " ROUND()
"0: \n\t"
// Outputs (modified).
: [loops] "+r" (loops),
[src] "+r" (*s),
[dst] "+r" (*o),
[t0] "=&w" (tmp0),
[t1] "=&w" (tmp1),
[t2] "=&w" (tmp2),
[t3] "=&w" (tmp3)
// Inputs (not modified).
: [rounds] "r" (rounds),
[tbl] "r" (base64_table_enc_6bit),
[n63] "w" (vdupq_n_u8(63))
// Clobbers.
: "v2", "v3", "v4", "v5",
"v8", "v9", "v10", "v11",
"v12", "v13", "v14", "v15",
"cc", "memory"
);
}
#pragma GCC diagnostic pop

View File

@@ -0,0 +1,31 @@
static inline uint8x16x4_t
enc_reshuffle (const uint8x16x3_t in)
{
uint8x16x4_t out;
// Input:
// in[0] = a7 a6 a5 a4 a3 a2 a1 a0
// in[1] = b7 b6 b5 b4 b3 b2 b1 b0
// in[2] = c7 c6 c5 c4 c3 c2 c1 c0
// Output:
// out[0] = 00 00 a7 a6 a5 a4 a3 a2
// out[1] = 00 00 a1 a0 b7 b6 b5 b4
// out[2] = 00 00 b3 b2 b1 b0 c7 c6
// out[3] = 00 00 c5 c4 c3 c2 c1 c0
// Move the input bits to where they need to be in the outputs. Except
// for the first output, the high two bits are not cleared.
out.val[0] = vshrq_n_u8(in.val[0], 2);
out.val[1] = vshrq_n_u8(in.val[1], 4);
out.val[2] = vshrq_n_u8(in.val[2], 6);
out.val[1] = vsliq_n_u8(out.val[1], in.val[0], 4);
out.val[2] = vsliq_n_u8(out.val[2], in.val[1], 2);
// Clear the high two bits in the second, third and fourth output.
out.val[1] = vandq_u8(out.val[1], vdupq_n_u8(0x3F));
out.val[2] = vandq_u8(out.val[2], vdupq_n_u8(0x3F));
out.val[3] = vandq_u8(in.val[2], vdupq_n_u8(0x3F));
return out;
}

56
3rdparty/base64/lib/arch/sse41/codec.c vendored Normal file
View File

@@ -0,0 +1,56 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "../../../include/libbase64.h"
#include "../../tables/tables.h"
#include "../../codecs.h"
#include "config.h"
#include "../../env.h"
#if HAVE_SSE41
#include <smmintrin.h>
// Only enable inline assembly on supported compilers and on 64-bit CPUs.
#ifndef BASE64_SSE41_USE_ASM
# if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64
# define BASE64_SSE41_USE_ASM 1
# else
# define BASE64_SSE41_USE_ASM 0
# endif
#endif
#include "../ssse3/dec_reshuffle.c"
#include "../ssse3/dec_loop.c"
#if BASE64_SSE41_USE_ASM
# include "../ssse3/enc_loop_asm.c"
#else
# include "../ssse3/enc_translate.c"
# include "../ssse3/enc_reshuffle.c"
# include "../ssse3/enc_loop.c"
#endif
#endif // HAVE_SSE41
BASE64_ENC_FUNCTION(sse41)
{
#if HAVE_SSE41
#include "../generic/enc_head.c"
enc_loop_ssse3(&s, &slen, &o, &olen);
#include "../generic/enc_tail.c"
#else
BASE64_ENC_STUB
#endif
}
BASE64_DEC_FUNCTION(sse41)
{
#if HAVE_SSE41
#include "../generic/dec_head.c"
dec_loop_ssse3(&s, &slen, &o, &olen);
#include "../generic/dec_tail.c"
#else
BASE64_DEC_STUB
#endif
}

56
3rdparty/base64/lib/arch/sse42/codec.c vendored Normal file
View File

@@ -0,0 +1,56 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "../../../include/libbase64.h"
#include "../../tables/tables.h"
#include "../../codecs.h"
#include "config.h"
#include "../../env.h"
#if HAVE_SSE42
#include <nmmintrin.h>
// Only enable inline assembly on supported compilers and on 64-bit CPUs.
#ifndef BASE64_SSE42_USE_ASM
# if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64
# define BASE64_SSE42_USE_ASM 1
# else
# define BASE64_SSE42_USE_ASM 0
# endif
#endif
#include "../ssse3/dec_reshuffle.c"
#include "../ssse3/dec_loop.c"
#if BASE64_SSE42_USE_ASM
# include "../ssse3/enc_loop_asm.c"
#else
# include "../ssse3/enc_translate.c"
# include "../ssse3/enc_reshuffle.c"
# include "../ssse3/enc_loop.c"
#endif
#endif // HAVE_SSE42
BASE64_ENC_FUNCTION(sse42)
{
#if HAVE_SSE42
#include "../generic/enc_head.c"
enc_loop_ssse3(&s, &slen, &o, &olen);
#include "../generic/enc_tail.c"
#else
BASE64_ENC_STUB
#endif
}
BASE64_DEC_FUNCTION(sse42)
{
#if HAVE_SSE42
#include "../generic/dec_head.c"
dec_loop_ssse3(&s, &slen, &o, &olen);
#include "../generic/dec_tail.c"
#else
BASE64_DEC_STUB
#endif
}

58
3rdparty/base64/lib/arch/ssse3/codec.c vendored Normal file
View File

@@ -0,0 +1,58 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "../../../include/libbase64.h"
#include "../../tables/tables.h"
#include "../../codecs.h"
#include "config.h"
#include "../../env.h"
#if HAVE_SSSE3
#include <tmmintrin.h>
// Only enable inline assembly on supported compilers and on 64-bit CPUs.
// 32-bit CPUs with SSSE3 support, such as low-end Atoms, only have eight XMM
// registers, which is not enough to run the inline assembly.
#ifndef BASE64_SSSE3_USE_ASM
# if (defined(__GNUC__) || defined(__clang__)) && BASE64_WORDSIZE == 64
# define BASE64_SSSE3_USE_ASM 1
# else
# define BASE64_SSSE3_USE_ASM 0
# endif
#endif
#include "dec_reshuffle.c"
#include "dec_loop.c"
#if BASE64_SSSE3_USE_ASM
# include "enc_loop_asm.c"
#else
# include "enc_reshuffle.c"
# include "enc_translate.c"
# include "enc_loop.c"
#endif
#endif // HAVE_SSSE3
BASE64_ENC_FUNCTION(ssse3)
{
#if HAVE_SSSE3
#include "../generic/enc_head.c"
enc_loop_ssse3(&s, &slen, &o, &olen);
#include "../generic/enc_tail.c"
#else
BASE64_ENC_STUB
#endif
}
BASE64_DEC_FUNCTION(ssse3)
{
#if HAVE_SSSE3
#include "../generic/dec_head.c"
dec_loop_ssse3(&s, &slen, &o, &olen);
#include "../generic/dec_tail.c"
#else
BASE64_DEC_STUB
#endif
}

View File

@@ -0,0 +1,173 @@
// The input consists of six character sets in the Base64 alphabet, which we
// need to map back to the 6-bit values they represent. There are three ranges,
// two singles, and then there's the rest.
//
// # From To Add Characters
// 1 [43] [62] +19 +
// 2 [47] [63] +16 /
// 3 [48..57] [52..61] +4 0..9
// 4 [65..90] [0..25] -65 A..Z
// 5 [97..122] [26..51] -71 a..z
// (6) Everything else => invalid input
//
// We will use lookup tables for character validation and offset computation.
// Remember that 0x2X and 0x0X are the same index for _mm_shuffle_epi8, this
// allows to mask with 0x2F instead of 0x0F and thus save one constant
// declaration (register and/or memory access).
//
// For offsets:
// Perfect hash for lut = ((src >> 4) & 0x2F) + ((src == 0x2F) ? 0xFF : 0x00)
// 0000 = garbage
// 0001 = /
// 0010 = +
// 0011 = 0-9
// 0100 = A-Z
// 0101 = A-Z
// 0110 = a-z
// 0111 = a-z
// 1000 >= garbage
//
// For validation, here's the table.
// A character is valid if and only if the AND of the 2 lookups equals 0:
//
// hi \ lo 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
// LUT 0x15 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x13 0x1A 0x1B 0x1B 0x1B 0x1A
//
// 0000 0x10 char NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
// andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
//
// 0001 0x10 char DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
// andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
//
// 0010 0x01 char ! " # $ % & ' ( ) * + , - . /
// andlut 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x00 0x01 0x01 0x01 0x00
//
// 0011 0x02 char 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
// andlut 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x02 0x02 0x02 0x02 0x02
//
// 0100 0x04 char @ A B C D E F G H I J K L M N O
// andlut 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
//
// 0101 0x08 char P Q R S T U V W X Y Z [ \ ] ^ _
// andlut 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x08 0x08 0x08 0x08 0x08
//
// 0110 0x04 char ` a b c d e f g h i j k l m n o
// andlut 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 0111 0x08 char p q r s t u v w x y z { | } ~
// andlut 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x08 0x08 0x08 0x08 0x08
//
// 1000 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
// 1001 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
// 1010 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
// 1011 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
// 1100 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
// 1101 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
// 1110 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
// 1111 0x10 andlut 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10
static inline int
dec_loop_ssse3_inner (const uint8_t **s, uint8_t **o, size_t *rounds)
{
const __m128i lut_lo = _mm_setr_epi8(
0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x13, 0x1A, 0x1B, 0x1B, 0x1B, 0x1A);
const __m128i lut_hi = _mm_setr_epi8(
0x10, 0x10, 0x01, 0x02, 0x04, 0x08, 0x04, 0x08,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10);
const __m128i lut_roll = _mm_setr_epi8(
0, 16, 19, 4, -65, -65, -71, -71,
0, 0, 0, 0, 0, 0, 0, 0);
const __m128i mask_2F = _mm_set1_epi8(0x2F);
// Load input:
__m128i str = _mm_loadu_si128((__m128i *) *s);
// Table lookups:
const __m128i hi_nibbles = _mm_and_si128(_mm_srli_epi32(str, 4), mask_2F);
const __m128i lo_nibbles = _mm_and_si128(str, mask_2F);
const __m128i hi = _mm_shuffle_epi8(lut_hi, hi_nibbles);
const __m128i lo = _mm_shuffle_epi8(lut_lo, lo_nibbles);
// Check for invalid input: if any "and" values from lo and hi are not
// zero, fall back on bytewise code to do error checking and reporting:
if (_mm_movemask_epi8(_mm_cmpgt_epi8(_mm_and_si128(lo, hi), _mm_setzero_si128())) != 0) {
return 0;
}
const __m128i eq_2F = _mm_cmpeq_epi8(str, mask_2F);
const __m128i roll = _mm_shuffle_epi8(lut_roll, _mm_add_epi8(eq_2F, hi_nibbles));
// Now simply add the delta values to the input:
str = _mm_add_epi8(str, roll);
// Reshuffle the input to packed 12-byte output format:
str = dec_reshuffle(str);
// Store the output:
_mm_storeu_si128((__m128i *) *o, str);
*s += 16;
*o += 12;
*rounds -= 1;
return 1;
}
static inline void
dec_loop_ssse3 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 24) {
return;
}
// Process blocks of 16 bytes per round. Because 4 extra zero bytes are
// written after the output, ensure that there will be at least 8 bytes
// of input data left to cover the gap. (6 data bytes and up to two
// end-of-string markers.)
size_t rounds = (*slen - 8) / 16;
*slen -= rounds * 16; // 16 bytes consumed per round
*olen += rounds * 12; // 12 bytes produced per round
do {
if (rounds >= 8) {
if (dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds)) {
continue;
}
break;
}
if (rounds >= 4) {
if (dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds)) {
continue;
}
break;
}
if (rounds >= 2) {
if (dec_loop_ssse3_inner(s, o, &rounds) &&
dec_loop_ssse3_inner(s, o, &rounds)) {
continue;
}
break;
}
dec_loop_ssse3_inner(s, o, &rounds);
break;
} while (rounds > 0);
// Adjust for any rounds that were skipped:
*slen += rounds * 16;
*olen -= rounds * 12;
}

View File

@@ -0,0 +1,33 @@
static inline __m128i
dec_reshuffle (const __m128i in)
{
// in, bits, upper case are most significant bits, lower case are least significant bits
// 00llllll 00kkkkLL 00jjKKKK 00JJJJJJ
// 00iiiiii 00hhhhII 00ggHHHH 00GGGGGG
// 00ffffff 00eeeeFF 00ddEEEE 00DDDDDD
// 00cccccc 00bbbbCC 00aaBBBB 00AAAAAA
const __m128i merge_ab_and_bc = _mm_maddubs_epi16(in, _mm_set1_epi32(0x01400140));
// 0000kkkk LLllllll 0000JJJJ JJjjKKKK
// 0000hhhh IIiiiiii 0000GGGG GGggHHHH
// 0000eeee FFffffff 0000DDDD DDddEEEE
// 0000bbbb CCcccccc 0000AAAA AAaaBBBB
const __m128i out = _mm_madd_epi16(merge_ab_and_bc, _mm_set1_epi32(0x00011000));
// 00000000 JJJJJJjj KKKKkkkk LLllllll
// 00000000 GGGGGGgg HHHHhhhh IIiiiiii
// 00000000 DDDDDDdd EEEEeeee FFffffff
// 00000000 AAAAAAaa BBBBbbbb CCcccccc
// Pack bytes together:
return _mm_shuffle_epi8(out, _mm_setr_epi8(
2, 1, 0,
6, 5, 4,
10, 9, 8,
14, 13, 12,
-1, -1, -1, -1));
// 00000000 00000000 00000000 00000000
// LLllllll KKKKkkkk JJJJJJjj IIiiiiii
// HHHHhhhh GGGGGGgg FFffffff EEEEeeee
// DDDDDDdd CCcccccc BBBBbbbb AAAAAAaa
}

View File

@@ -0,0 +1,67 @@
static inline void
enc_loop_ssse3_inner (const uint8_t **s, uint8_t **o)
{
// Load input:
__m128i str = _mm_loadu_si128((__m128i *) *s);
// Reshuffle:
str = enc_reshuffle(str);
// Translate reshuffled bytes to the Base64 alphabet:
str = enc_translate(str);
// Store:
_mm_storeu_si128((__m128i *) *o, str);
*s += 12;
*o += 16;
}
static inline void
enc_loop_ssse3 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
if (*slen < 16) {
return;
}
// Process blocks of 12 bytes at a time. Because blocks are loaded 16
// bytes at a time, ensure that there will be at least 4 remaining
// bytes after the last round, so that the final read will not pass
// beyond the bounds of the input buffer:
size_t rounds = (*slen - 4) / 12;
*slen -= rounds * 12; // 12 bytes consumed per round
*olen += rounds * 16; // 16 bytes produced per round
do {
if (rounds >= 8) {
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
rounds -= 8;
continue;
}
if (rounds >= 4) {
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
rounds -= 4;
continue;
}
if (rounds >= 2) {
enc_loop_ssse3_inner(s, o);
enc_loop_ssse3_inner(s, o);
rounds -= 2;
continue;
}
enc_loop_ssse3_inner(s, o);
break;
} while (rounds > 0);
}

View File

@@ -0,0 +1,268 @@
// Apologies in advance for combining the preprocessor with inline assembly,
// two notoriously gnarly parts of C, but it was necessary to avoid a lot of
// code repetition. The preprocessor is used to template large sections of
// inline assembly that differ only in the registers used. If the code was
// written out by hand, it would become very large and hard to audit.
// Generate a block of inline assembly that loads register R0 from memory. The
// offset at which the register is loaded is set by the given round.
#define LOAD(R0, ROUND) \
"lddqu ("#ROUND" * 12)(%[src]), %["R0"] \n\t"
// Generate a block of inline assembly that deinterleaves and shuffles register
// R0 using preloaded constants. Outputs in R0 and R1.
#define SHUF(R0, R1) \
"pshufb %[lut0], %["R0"] \n\t" \
"movdqa %["R0"], %["R1"] \n\t" \
"pand %[msk0], %["R0"] \n\t" \
"pand %[msk2], %["R1"] \n\t" \
"pmulhuw %[msk1], %["R0"] \n\t" \
"pmullw %[msk3], %["R1"] \n\t" \
"por %["R1"], %["R0"] \n\t"
// Generate a block of inline assembly that takes R0 and R1 and translates
// their contents to the base64 alphabet, using preloaded constants.
#define TRAN(R0, R1, R2) \
"movdqa %["R0"], %["R1"] \n\t" \
"movdqa %["R0"], %["R2"] \n\t" \
"psubusb %[n51], %["R1"] \n\t" \
"pcmpgtb %[n25], %["R2"] \n\t" \
"psubb %["R2"], %["R1"] \n\t" \
"movdqa %[lut1], %["R2"] \n\t" \
"pshufb %["R1"], %["R2"] \n\t" \
"paddb %["R2"], %["R0"] \n\t"
// Generate a block of inline assembly that stores the given register R0 at an
// offset set by the given round.
#define STOR(R0, ROUND) \
"movdqu %["R0"], ("#ROUND" * 16)(%[dst]) \n\t"
// Generate a block of inline assembly that generates a single self-contained
// encoder round: fetch the data, process it, and store the result. Then update
// the source and destination pointers.
#define ROUND() \
LOAD("a", 0) \
SHUF("a", "b") \
TRAN("a", "b", "c") \
STOR("a", 0) \
"add $12, %[src] \n\t" \
"add $16, %[dst] \n\t"
// Define a macro that initiates a three-way interleaved encoding round by
// preloading registers a, b and c from memory.
// The register graph shows which registers are in use during each step, and
// is a visual aid for choosing registers for that step. Symbol index:
//
// + indicates that a register is loaded by that step.
// | indicates that a register is in use and must not be touched.
// - indicates that a register is decommissioned by that step.
// x indicates that a register is used as a temporary by that step.
// V indicates that a register is an input or output to the macro.
//
#define ROUND_3_INIT() /* a b c d e f */ \
LOAD("a", 0) /* + */ \
SHUF("a", "d") /* | + */ \
LOAD("b", 1) /* | + | */ \
TRAN("a", "d", "e") /* | | - x */ \
LOAD("c", 2) /* V V V */
// Define a macro that translates, shuffles and stores the input registers A, B
// and C, and preloads registers D, E and F for the next round.
// This macro can be arbitrarily daisy-chained by feeding output registers D, E
// and F back into the next round as input registers A, B and C. The macro
// carefully interleaves memory operations with data operations for optimal
// pipelined performance.
#define ROUND_3(ROUND, A,B,C,D,E,F) /* A B C D E F */ \
LOAD(D, (ROUND + 3)) /* V V V + */ \
SHUF(B, E) /* | | | | + */ \
STOR(A, (ROUND + 0)) /* - | | | | */ \
TRAN(B, E, F) /* | | | - x */ \
LOAD(E, (ROUND + 4)) /* | | | + */ \
SHUF(C, A) /* + | | | | */ \
STOR(B, (ROUND + 1)) /* | - | | | */ \
TRAN(C, A, F) /* - | | | x */ \
LOAD(F, (ROUND + 5)) /* | | | + */ \
SHUF(D, A) /* + | | | | */ \
STOR(C, (ROUND + 2)) /* | - | | | */ \
TRAN(D, A, B) /* - x V V V */
// Define a macro that terminates a ROUND_3 macro by taking pre-loaded
// registers D, E and F, and translating, shuffling and storing them.
#define ROUND_3_END(ROUND, A,B,C,D,E,F) /* A B C D E F */ \
SHUF(E, A) /* + V V V */ \
STOR(D, (ROUND + 3)) /* | - | | */ \
TRAN(E, A, B) /* - x | | */ \
SHUF(F, C) /* + | | */ \
STOR(E, (ROUND + 4)) /* | - | */ \
TRAN(F, C, D) /* - x | */ \
STOR(F, (ROUND + 5)) /* - */
// Define a type A round. Inputs are a, b, and c, outputs are d, e, and f.
#define ROUND_3_A(ROUND) \
ROUND_3(ROUND, "a", "b", "c", "d", "e", "f")
// Define a type B round. Inputs and outputs are swapped with regard to type A.
#define ROUND_3_B(ROUND) \
ROUND_3(ROUND, "d", "e", "f", "a", "b", "c")
// Terminating macro for a type A round.
#define ROUND_3_A_LAST(ROUND) \
ROUND_3_A(ROUND) \
ROUND_3_END(ROUND, "a", "b", "c", "d", "e", "f")
// Terminating macro for a type B round.
#define ROUND_3_B_LAST(ROUND) \
ROUND_3_B(ROUND) \
ROUND_3_END(ROUND, "d", "e", "f", "a", "b", "c")
// Suppress clang's warning that the literal string in the asm statement is
// overlong (longer than the ISO-mandated minimum size of 4095 bytes for C99
// compilers). It may be true, but the goal here is not C99 portability.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverlength-strings"
static inline void
enc_loop_ssse3 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
{
// For a clearer explanation of the algorithm used by this function,
// please refer to the plain (not inline assembly) implementation. This
// function follows the same basic logic.
if (*slen < 16) {
return;
}
// Process blocks of 12 bytes at a time. Input is read in blocks of 16
// bytes, so "reserve" four bytes from the input buffer to ensure that
// we never read beyond the end of the input buffer.
size_t rounds = (*slen - 4) / 12;
*slen -= rounds * 12; // 12 bytes consumed per round
*olen += rounds * 16; // 16 bytes produced per round
// Number of times to go through the 36x loop.
size_t loops = rounds / 36;
// Number of rounds remaining after the 36x loop.
rounds %= 36;
// Lookup tables.
const __m128i lut0 = _mm_set_epi8(
10, 11, 9, 10, 7, 8, 6, 7, 4, 5, 3, 4, 1, 2, 0, 1);
const __m128i lut1 = _mm_setr_epi8(
65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0);
// Temporary registers.
__m128i a, b, c, d, e, f;
__asm__ volatile (
// If there are 36 rounds or more, enter a 36x unrolled loop of
// interleaved encoding rounds. The rounds interleave memory
// operations (load/store) with data operations (table lookups,
// etc) to maximize pipeline throughput.
" test %[loops], %[loops] \n\t"
" jz 18f \n\t"
" jmp 36f \n\t"
" \n\t"
".balign 64 \n\t"
"36: " ROUND_3_INIT()
" " ROUND_3_A( 0)
" " ROUND_3_B( 3)
" " ROUND_3_A( 6)
" " ROUND_3_B( 9)
" " ROUND_3_A(12)
" " ROUND_3_B(15)
" " ROUND_3_A(18)
" " ROUND_3_B(21)
" " ROUND_3_A(24)
" " ROUND_3_B(27)
" " ROUND_3_A_LAST(30)
" add $(12 * 36), %[src] \n\t"
" add $(16 * 36), %[dst] \n\t"
" dec %[loops] \n\t"
" jnz 36b \n\t"
// Enter an 18x unrolled loop for rounds of 18 or more.
"18: cmp $18, %[rounds] \n\t"
" jl 9f \n\t"
" " ROUND_3_INIT()
" " ROUND_3_A(0)
" " ROUND_3_B(3)
" " ROUND_3_A(6)
" " ROUND_3_B(9)
" " ROUND_3_A_LAST(12)
" sub $18, %[rounds] \n\t"
" add $(12 * 18), %[src] \n\t"
" add $(16 * 18), %[dst] \n\t"
// Enter a 9x unrolled loop for rounds of 9 or more.
"9: cmp $9, %[rounds] \n\t"
" jl 6f \n\t"
" " ROUND_3_INIT()
" " ROUND_3_A(0)
" " ROUND_3_B_LAST(3)
" sub $9, %[rounds] \n\t"
" add $(12 * 9), %[src] \n\t"
" add $(16 * 9), %[dst] \n\t"
// Enter a 6x unrolled loop for rounds of 6 or more.
"6: cmp $6, %[rounds] \n\t"
" jl 55f \n\t"
" " ROUND_3_INIT()
" " ROUND_3_A_LAST(0)
" sub $6, %[rounds] \n\t"
" add $(12 * 6), %[src] \n\t"
" add $(16 * 6), %[dst] \n\t"
// Dispatch the remaining rounds 0..5.
"55: cmp $3, %[rounds] \n\t"
" jg 45f \n\t"
" je 3f \n\t"
" cmp $1, %[rounds] \n\t"
" jg 2f \n\t"
" je 1f \n\t"
" jmp 0f \n\t"
"45: cmp $4, %[rounds] \n\t"
" je 4f \n\t"
// Block of non-interlaced encoding rounds, which can each
// individually be jumped to. Rounds fall through to the next.
"5: " ROUND()
"4: " ROUND()
"3: " ROUND()
"2: " ROUND()
"1: " ROUND()
"0: \n\t"
// Outputs (modified).
: [rounds] "+r" (rounds),
[loops] "+r" (loops),
[src] "+r" (*s),
[dst] "+r" (*o),
[a] "=&x" (a),
[b] "=&x" (b),
[c] "=&x" (c),
[d] "=&x" (d),
[e] "=&x" (e),
[f] "=&x" (f)
// Inputs (not modified).
: [lut0] "x" (lut0),
[lut1] "x" (lut1),
[msk0] "x" (_mm_set1_epi32(0x0FC0FC00)),
[msk1] "x" (_mm_set1_epi32(0x04000040)),
[msk2] "x" (_mm_set1_epi32(0x003F03F0)),
[msk3] "x" (_mm_set1_epi32(0x01000010)),
[n51] "x" (_mm_set1_epi8(51)),
[n25] "x" (_mm_set1_epi8(25))
// Clobbers.
: "cc", "memory"
);
}
#pragma GCC diagnostic pop

View File

@@ -0,0 +1,48 @@
static inline __m128i
enc_reshuffle (__m128i in)
{
// Input, bytes MSB to LSB:
// 0 0 0 0 l k j i h g f e d c b a
in = _mm_shuffle_epi8(in, _mm_set_epi8(
10, 11, 9, 10,
7, 8, 6, 7,
4, 5, 3, 4,
1, 2, 0, 1));
// in, bytes MSB to LSB:
// k l j k
// h i g h
// e f d e
// b c a b
const __m128i t0 = _mm_and_si128(in, _mm_set1_epi32(0x0FC0FC00));
// bits, upper case are most significant bits, lower case are least significant bits
// 0000kkkk LL000000 JJJJJJ00 00000000
// 0000hhhh II000000 GGGGGG00 00000000
// 0000eeee FF000000 DDDDDD00 00000000
// 0000bbbb CC000000 AAAAAA00 00000000
const __m128i t1 = _mm_mulhi_epu16(t0, _mm_set1_epi32(0x04000040));
// 00000000 00kkkkLL 00000000 00JJJJJJ
// 00000000 00hhhhII 00000000 00GGGGGG
// 00000000 00eeeeFF 00000000 00DDDDDD
// 00000000 00bbbbCC 00000000 00AAAAAA
const __m128i t2 = _mm_and_si128(in, _mm_set1_epi32(0x003F03F0));
// 00000000 00llllll 000000jj KKKK0000
// 00000000 00iiiiii 000000gg HHHH0000
// 00000000 00ffffff 000000dd EEEE0000
// 00000000 00cccccc 000000aa BBBB0000
const __m128i t3 = _mm_mullo_epi16(t2, _mm_set1_epi32(0x01000010));
// 00llllll 00000000 00jjKKKK 00000000
// 00iiiiii 00000000 00ggHHHH 00000000
// 00ffffff 00000000 00ddEEEE 00000000
// 00cccccc 00000000 00aaBBBB 00000000
return _mm_or_si128(t1, t3);
// 00llllll 00kkkkLL 00jjKKKK 00JJJJJJ
// 00iiiiii 00hhhhII 00ggHHHH 00GGGGGG
// 00ffffff 00eeeeFF 00ddEEEE 00DDDDDD
// 00cccccc 00bbbbCC 00aaBBBB 00AAAAAA
}

View File

@@ -0,0 +1,33 @@
static inline __m128i
enc_translate (const __m128i in)
{
// A lookup table containing the absolute offsets for all ranges:
const __m128i lut = _mm_setr_epi8(
65, 71, -4, -4,
-4, -4, -4, -4,
-4, -4, -4, -4,
-19, -16, 0, 0
);
// Translate values 0..63 to the Base64 alphabet. There are five sets:
// # From To Abs Index Characters
// 0 [0..25] [65..90] +65 0 ABCDEFGHIJKLMNOPQRSTUVWXYZ
// 1 [26..51] [97..122] +71 1 abcdefghijklmnopqrstuvwxyz
// 2 [52..61] [48..57] -4 [2..11] 0123456789
// 3 [62] [43] -19 12 +
// 4 [63] [47] -16 13 /
// Create LUT indices from the input. The index for range #0 is right,
// others are 1 less than expected:
__m128i indices = _mm_subs_epu8(in, _mm_set1_epi8(51));
// mask is 0xFF (-1) for range #[1..4] and 0x00 for range #0:
__m128i mask = _mm_cmpgt_epi8(in, _mm_set1_epi8(25));
// Subtract -1, so add 1 to indices for range #[1..4]. All indices are
// now correct:
indices = _mm_sub_epi8(indices, mask);
// Add offsets to input values:
return _mm_add_epi8(in, _mm_shuffle_epi8(lut, indices));
}

305
3rdparty/base64/lib/codec_choose.c vendored Normal file
View File

@@ -0,0 +1,305 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "../include/libbase64.h"
#include "codecs.h"
#include "config.h"
#include "env.h"
#if (__x86_64__ || __i386__ || _M_X86 || _M_X64)
#define BASE64_X86
#if (HAVE_SSSE3 || HAVE_SSE41 || HAVE_SSE42 || HAVE_AVX || HAVE_AVX2 || HAVE_AVX512)
#define BASE64_X86_SIMD
#endif
#endif
#ifdef BASE64_X86
#ifdef _MSC_VER
#include <intrin.h>
#define __cpuid_count(__level, __count, __eax, __ebx, __ecx, __edx) \
{ \
int info[4]; \
__cpuidex(info, __level, __count); \
__eax = info[0]; \
__ebx = info[1]; \
__ecx = info[2]; \
__edx = info[3]; \
}
#define __cpuid(__level, __eax, __ebx, __ecx, __edx) \
__cpuid_count(__level, 0, __eax, __ebx, __ecx, __edx)
#else
#include <cpuid.h>
#if HAVE_AVX512 || HAVE_AVX2 || HAVE_AVX
#if ((__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 2) || (__clang_major__ >= 3))
static inline uint64_t _xgetbv (uint32_t index)
{
uint32_t eax, edx;
__asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
return ((uint64_t)edx << 32) | eax;
}
#else
#error "Platform not supported"
#endif
#endif
#endif
#ifndef bit_AVX512vl
#define bit_AVX512vl (1 << 31)
#endif
#ifndef bit_AVX512vbmi
#define bit_AVX512vbmi (1 << 1)
#endif
#ifndef bit_AVX2
#define bit_AVX2 (1 << 5)
#endif
#ifndef bit_SSSE3
#define bit_SSSE3 (1 << 9)
#endif
#ifndef bit_SSE41
#define bit_SSE41 (1 << 19)
#endif
#ifndef bit_SSE42
#define bit_SSE42 (1 << 20)
#endif
#ifndef bit_AVX
#define bit_AVX (1 << 28)
#endif
#define bit_XSAVE_XRSTORE (1 << 27)
#ifndef _XCR_XFEATURE_ENABLED_MASK
#define _XCR_XFEATURE_ENABLED_MASK 0
#endif
#define _XCR_XMM_AND_YMM_STATE_ENABLED_BY_OS 0x6
#endif
// Function declarations:
#define BASE64_CODEC_FUNCS(arch) \
BASE64_ENC_FUNCTION(arch); \
BASE64_DEC_FUNCTION(arch); \
BASE64_CODEC_FUNCS(avx512)
BASE64_CODEC_FUNCS(avx2)
BASE64_CODEC_FUNCS(neon32)
BASE64_CODEC_FUNCS(neon64)
BASE64_CODEC_FUNCS(plain)
BASE64_CODEC_FUNCS(ssse3)
BASE64_CODEC_FUNCS(sse41)
BASE64_CODEC_FUNCS(sse42)
BASE64_CODEC_FUNCS(avx)
static bool
codec_choose_forced (struct codec *codec, int flags)
{
// If the user wants to use a certain codec,
// always allow it, even if the codec is a no-op.
// For testing purposes.
if (!(flags & 0xFFFF)) {
return false;
}
if (flags & BASE64_FORCE_AVX2) {
codec->enc = base64_stream_encode_avx2;
codec->dec = base64_stream_decode_avx2;
return true;
}
if (flags & BASE64_FORCE_NEON32) {
codec->enc = base64_stream_encode_neon32;
codec->dec = base64_stream_decode_neon32;
return true;
}
if (flags & BASE64_FORCE_NEON64) {
codec->enc = base64_stream_encode_neon64;
codec->dec = base64_stream_decode_neon64;
return true;
}
if (flags & BASE64_FORCE_PLAIN) {
codec->enc = base64_stream_encode_plain;
codec->dec = base64_stream_decode_plain;
return true;
}
if (flags & BASE64_FORCE_SSSE3) {
codec->enc = base64_stream_encode_ssse3;
codec->dec = base64_stream_decode_ssse3;
return true;
}
if (flags & BASE64_FORCE_SSE41) {
codec->enc = base64_stream_encode_sse41;
codec->dec = base64_stream_decode_sse41;
return true;
}
if (flags & BASE64_FORCE_SSE42) {
codec->enc = base64_stream_encode_sse42;
codec->dec = base64_stream_decode_sse42;
return true;
}
if (flags & BASE64_FORCE_AVX) {
codec->enc = base64_stream_encode_avx;
codec->dec = base64_stream_decode_avx;
return true;
}
if (flags & BASE64_FORCE_AVX512) {
codec->enc = base64_stream_encode_avx512;
codec->dec = base64_stream_decode_avx512;
return true;
}
return false;
}
static bool
codec_choose_arm (struct codec *codec)
{
#if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && ((defined(__aarch64__) && HAVE_NEON64) || HAVE_NEON32)
// Unfortunately there is no portable way to check for NEON
// support at runtime from userland in the same way that x86
// has cpuid, so just stick to the compile-time configuration:
#if defined(__aarch64__) && HAVE_NEON64
codec->enc = base64_stream_encode_neon64;
codec->dec = base64_stream_decode_neon64;
#else
codec->enc = base64_stream_encode_neon32;
codec->dec = base64_stream_decode_neon32;
#endif
return true;
#else
(void)codec;
return false;
#endif
}
static bool
codec_choose_x86 (struct codec *codec)
{
#ifdef BASE64_X86_SIMD
unsigned int eax, ebx = 0, ecx = 0, edx;
unsigned int max_level;
#ifdef _MSC_VER
int info[4];
__cpuidex(info, 0, 0);
max_level = info[0];
#else
max_level = __get_cpuid_max(0, NULL);
#endif
#if HAVE_AVX512 || HAVE_AVX2 || HAVE_AVX
// Check for AVX/AVX2/AVX512 support:
// Checking for AVX requires 3 things:
// 1) CPUID indicates that the OS uses XSAVE and XRSTORE instructions
// (allowing saving YMM registers on context switch)
// 2) CPUID indicates support for AVX
// 3) XGETBV indicates the AVX registers will be saved and restored on
// context switch
//
// Note that XGETBV is only available on 686 or later CPUs, so the
// instruction needs to be conditionally run.
if (max_level >= 1) {
__cpuid_count(1, 0, eax, ebx, ecx, edx);
if (ecx & bit_XSAVE_XRSTORE) {
uint64_t xcr_mask;
xcr_mask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
if ((xcr_mask & _XCR_XMM_AND_YMM_STATE_ENABLED_BY_OS) == _XCR_XMM_AND_YMM_STATE_ENABLED_BY_OS) { // check multiple bits at once
#if HAVE_AVX512
if (max_level >= 7) {
__cpuid_count(7, 0, eax, ebx, ecx, edx);
if ((ebx & bit_AVX512vl) && (ecx & bit_AVX512vbmi)) {
codec->enc = base64_stream_encode_avx512;
codec->dec = base64_stream_decode_avx512;
return true;
}
}
#endif
#if HAVE_AVX2
if (max_level >= 7) {
__cpuid_count(7, 0, eax, ebx, ecx, edx);
if (ebx & bit_AVX2) {
codec->enc = base64_stream_encode_avx2;
codec->dec = base64_stream_decode_avx2;
return true;
}
}
#endif
#if HAVE_AVX
__cpuid_count(1, 0, eax, ebx, ecx, edx);
if (ecx & bit_AVX) {
codec->enc = base64_stream_encode_avx;
codec->dec = base64_stream_decode_avx;
return true;
}
#endif
}
}
}
#endif
#if HAVE_SSE42
// Check for SSE42 support:
if (max_level >= 1) {
__cpuid(1, eax, ebx, ecx, edx);
if (ecx & bit_SSE42) {
codec->enc = base64_stream_encode_sse42;
codec->dec = base64_stream_decode_sse42;
return true;
}
}
#endif
#if HAVE_SSE41
// Check for SSE41 support:
if (max_level >= 1) {
__cpuid(1, eax, ebx, ecx, edx);
if (ecx & bit_SSE41) {
codec->enc = base64_stream_encode_sse41;
codec->dec = base64_stream_decode_sse41;
return true;
}
}
#endif
#if HAVE_SSSE3
// Check for SSSE3 support:
if (max_level >= 1) {
__cpuid(1, eax, ebx, ecx, edx);
if (ecx & bit_SSSE3) {
codec->enc = base64_stream_encode_ssse3;
codec->dec = base64_stream_decode_ssse3;
return true;
}
}
#endif
#else
(void)codec;
#endif
return false;
}
void
codec_choose (struct codec *codec, int flags)
{
// User forced a codec:
if (codec_choose_forced(codec, flags)) {
return;
}
// Runtime feature detection:
if (codec_choose_arm(codec)) {
return;
}
if (codec_choose_x86(codec)) {
return;
}
codec->enc = base64_stream_encode_plain;
codec->dec = base64_stream_decode_plain;
}

65
3rdparty/base64/lib/codecs.h vendored Normal file
View File

@@ -0,0 +1,65 @@
#include <stdint.h>
#include <stddef.h>
#include "../include/libbase64.h"
#include "config.h"
// Function parameters for encoding functions:
#define BASE64_ENC_PARAMS \
( struct base64_state *state \
, const char *src \
, size_t srclen \
, char *out \
, size_t *outlen \
)
// Function parameters for decoding functions:
#define BASE64_DEC_PARAMS \
( struct base64_state *state \
, const char *src \
, size_t srclen \
, char *out \
, size_t *outlen \
)
// Function signature for encoding functions:
#define BASE64_ENC_FUNCTION(arch) \
void \
base64_stream_encode_ ## arch \
BASE64_ENC_PARAMS
// Function signature for decoding functions:
#define BASE64_DEC_FUNCTION(arch) \
int \
base64_stream_decode_ ## arch \
BASE64_DEC_PARAMS
// Cast away unused variable, silence compiler:
#define UNUSED(x) ((void)(x))
// Stub function when encoder arch unsupported:
#define BASE64_ENC_STUB \
UNUSED(state); \
UNUSED(src); \
UNUSED(srclen); \
UNUSED(out); \
\
*outlen = 0;
// Stub function when decoder arch unsupported:
#define BASE64_DEC_STUB \
UNUSED(state); \
UNUSED(src); \
UNUSED(srclen); \
UNUSED(out); \
UNUSED(outlen); \
\
return -1;
struct codec
{
void (* enc) BASE64_ENC_PARAMS;
int (* dec) BASE64_DEC_PARAMS;
};
extern void codec_choose (struct codec *, int flags);

74
3rdparty/base64/lib/env.h vendored Normal file
View File

@@ -0,0 +1,74 @@
#ifndef BASE64_ENV_H
#define BASE64_ENV_H
// This header file contains macro definitions that describe certain aspects of
// the compile-time environment. Compatibility and portability macros go here.
// Define machine endianness. This is for GCC:
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
# define BASE64_LITTLE_ENDIAN 1
#else
# define BASE64_LITTLE_ENDIAN 0
#endif
// This is for Clang:
#ifdef __LITTLE_ENDIAN__
# define BASE64_LITTLE_ENDIAN 1
#endif
#ifdef __BIG_ENDIAN__
# define BASE64_LITTLE_ENDIAN 0
#endif
// MSVC++ needs intrin.h for _byteswap_uint64 (issue #68):
#if BASE64_LITTLE_ENDIAN && defined(_MSC_VER)
# include <intrin.h>
#endif
// Endian conversion functions:
#if BASE64_LITTLE_ENDIAN
# ifdef _MSC_VER
// Microsoft Visual C++:
# define BASE64_HTOBE32(x) _byteswap_ulong(x)
# define BASE64_HTOBE64(x) _byteswap_uint64(x)
# else
// GCC and Clang:
# define BASE64_HTOBE32(x) __builtin_bswap32(x)
# define BASE64_HTOBE64(x) __builtin_bswap64(x)
# endif
#else
// No conversion needed:
# define BASE64_HTOBE32(x) (x)
# define BASE64_HTOBE64(x) (x)
#endif
// Detect word size:
#if defined (__x86_64__)
// This also works for the x32 ABI, which has a 64-bit word size.
# define BASE64_WORDSIZE 64
#elif defined (_INTEGRAL_MAX_BITS)
# define BASE64_WORDSIZE _INTEGRAL_MAX_BITS
#elif defined (__WORDSIZE)
# define BASE64_WORDSIZE __WORDSIZE
#elif defined (__SIZE_WIDTH__)
# define BASE64_WORDSIZE __SIZE_WIDTH__
#else
# error BASE64_WORDSIZE_NOT_DEFINED
#endif
// End-of-file definitions.
// Almost end-of-file when waiting for the last '=' character:
#define BASE64_AEOF 1
// End-of-file when stream end has been reached or invalid input provided:
#define BASE64_EOF 2
// GCC 7 defaults to issuing a warning for fallthrough in switch statements,
// unless the fallthrough cases are marked with an attribute. As we use
// fallthrough deliberately, define an alias for the attribute:
#if __GNUC__ >= 7
# define BASE64_FALLTHROUGH __attribute__((fallthrough));
#else
# define BASE64_FALLTHROUGH
#endif
#endif // BASE64_ENV_H

7
3rdparty/base64/lib/exports.txt vendored Normal file
View File

@@ -0,0 +1,7 @@
base64_encode
base64_stream_encode
base64_stream_encode_init
base64_stream_encode_final
base64_decode
base64_stream_decode
base64_stream_decode_init

164
3rdparty/base64/lib/lib.c vendored Normal file
View File

@@ -0,0 +1,164 @@
#include <stdint.h>
#include <stddef.h>
#ifdef _OPENMP
#include <omp.h>
#endif
#include "../include/libbase64.h"
#include "tables/tables.h"
#include "codecs.h"
#include "env.h"
// These static function pointers are initialized once when the library is
// first used, and remain in use for the remaining lifetime of the program.
// The idea being that CPU features don't change at runtime.
static struct codec codec = { NULL, NULL };
void
base64_stream_encode_init (struct base64_state *state, int flags)
{
// If any of the codec flags are set, redo choice:
if (codec.enc == NULL || flags & 0xFF) {
codec_choose(&codec, flags);
}
state->eof = 0;
state->bytes = 0;
state->carry = 0;
state->flags = flags;
}
void
base64_stream_encode
( struct base64_state *state
, const char *src
, size_t srclen
, char *out
, size_t *outlen
)
{
codec.enc(state, src, srclen, out, outlen);
}
void
base64_stream_encode_final
( struct base64_state *state
, char *out
, size_t *outlen
)
{
uint8_t *o = (uint8_t *)out;
if (state->bytes == 1) {
*o++ = base64_table_enc_6bit[state->carry];
*o++ = '=';
*o++ = '=';
*outlen = 3;
return;
}
if (state->bytes == 2) {
*o++ = base64_table_enc_6bit[state->carry];
*o++ = '=';
*outlen = 2;
return;
}
*outlen = 0;
}
void
base64_stream_decode_init (struct base64_state *state, int flags)
{
// If any of the codec flags are set, redo choice:
if (codec.dec == NULL || flags & 0xFFFF) {
codec_choose(&codec, flags);
}
state->eof = 0;
state->bytes = 0;
state->carry = 0;
state->flags = flags;
}
int
base64_stream_decode
( struct base64_state *state
, const char *src
, size_t srclen
, char *out
, size_t *outlen
)
{
return codec.dec(state, src, srclen, out, outlen);
}
#ifdef _OPENMP
// Due to the overhead of initializing OpenMP and creating a team of
// threads, we require the data length to be larger than a threshold:
#define OMP_THRESHOLD 20000
// Conditionally include OpenMP-accelerated codec implementations:
#include "lib_openmp.c"
#endif
void
base64_encode
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
)
{
size_t s;
size_t t;
struct base64_state state;
#ifdef _OPENMP
if (srclen >= OMP_THRESHOLD) {
base64_encode_openmp(src, srclen, out, outlen, flags);
return;
}
#endif
// Init the stream reader:
base64_stream_encode_init(&state, flags);
// Feed the whole string to the stream reader:
base64_stream_encode(&state, src, srclen, out, &s);
// Finalize the stream by writing trailer if any:
base64_stream_encode_final(&state, out + s, &t);
// Final output length is stream length plus tail:
*outlen = s + t;
}
int
base64_decode
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
)
{
int ret;
struct base64_state state;
#ifdef _OPENMP
if (srclen >= OMP_THRESHOLD) {
return base64_decode_openmp(src, srclen, out, outlen, flags);
}
#endif
// Init the stream reader:
base64_stream_decode_init(&state, flags);
// Feed the whole string to the stream reader:
ret = base64_stream_decode(&state, src, srclen, out, outlen);
// If when decoding a whole block, we're still waiting for input then fail:
if (ret && (state.bytes == 0)) {
return ret;
}
return 0;
}

149
3rdparty/base64/lib/lib_openmp.c vendored Normal file
View File

@@ -0,0 +1,149 @@
// This code makes some assumptions on the implementation of
// base64_stream_encode_init(), base64_stream_encode() and base64_stream_decode().
// Basically these assumptions boil down to that when breaking the src into
// parts, out parts can be written without side effects.
// This is met when:
// 1) base64_stream_encode() and base64_stream_decode() don't use globals;
// 2) the shared variables src and out are not read or written outside of the
// bounds of their parts, i.e. when base64_stream_encode() reads a multiple
// of 3 bytes, it must write no more then a multiple of 4 bytes, not even
// temporarily;
// 3) the state flag can be discarded after base64_stream_encode() and
// base64_stream_decode() on the parts.
static inline void
base64_encode_openmp
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
)
{
size_t s;
size_t t;
size_t sum = 0, len, last_len;
struct base64_state state, initial_state;
int num_threads, i;
// Request a number of threads but not necessarily get them:
#pragma omp parallel
{
// Get the number of threads used from one thread only,
// as num_threads is a shared var:
#pragma omp single
{
num_threads = omp_get_num_threads();
// Split the input string into num_threads parts, each
// part a multiple of 3 bytes. The remaining bytes will
// be done later:
len = srclen / (num_threads * 3);
len *= 3;
last_len = srclen - num_threads * len;
// Init the stream reader:
base64_stream_encode_init(&state, flags);
initial_state = state;
}
// Single has an implicit barrier for all threads to wait here
// for the above to complete:
#pragma omp for firstprivate(state) private(s) reduction(+:sum) schedule(static,1)
for (i = 0; i < num_threads; i++)
{
// Feed each part of the string to the stream reader:
base64_stream_encode(&state, src + i * len, len, out + i * len * 4 / 3, &s);
sum += s;
}
}
// As encoding should never fail and we encode an exact multiple
// of 3 bytes, we can discard state:
state = initial_state;
// Encode the remaining bytes:
base64_stream_encode(&state, src + num_threads * len, last_len, out + num_threads * len * 4 / 3, &s);
// Finalize the stream by writing trailer if any:
base64_stream_encode_final(&state, out + num_threads * len * 4 / 3 + s, &t);
// Final output length is stream length plus tail:
sum += s + t;
*outlen = sum;
}
static inline int
base64_decode_openmp
( const char *src
, size_t srclen
, char *out
, size_t *outlen
, int flags
)
{
int num_threads, result = 0, i;
size_t sum = 0, len, last_len, s;
struct base64_state state, initial_state;
// Request a number of threads but not necessarily get them:
#pragma omp parallel
{
// Get the number of threads used from one thread only,
// as num_threads is a shared var:
#pragma omp single
{
num_threads = omp_get_num_threads();
// Split the input string into num_threads parts, each
// part a multiple of 4 bytes. The remaining bytes will
// be done later:
len = srclen / (num_threads * 4);
len *= 4;
last_len = srclen - num_threads * len;
// Init the stream reader:
base64_stream_decode_init(&state, flags);
initial_state = state;
}
// Single has an implicit barrier to wait here for the above to
// complete:
#pragma omp for firstprivate(state) private(s) reduction(+:sum, result) schedule(static,1)
for (i = 0; i < num_threads; i++)
{
int this_result;
// Feed each part of the string to the stream reader:
this_result = base64_stream_decode(&state, src + i * len, len, out + i * len * 3 / 4, &s);
sum += s;
result += this_result;
}
}
// If `result' equals `-num_threads', then all threads returned -1,
// indicating that the requested codec is not available:
if (result == -num_threads) {
return -1;
}
// If `result' does not equal `num_threads', then at least one of the
// threads hit a decode error:
if (result != num_threads) {
return 0;
}
// So far so good, now decode whatever remains in the buffer. Reuse the
// initial state, since we are at a 4-byte boundary:
state = initial_state;
result = base64_stream_decode(&state, src + num_threads * len, last_len, out + num_threads * len * 3 / 4, &s);
sum += s;
*outlen = sum;
// If when decoding a whole block, we're still waiting for input then fail:
if (result && (state.bytes == 0)) {
return result;
}
return 0;
}

1
3rdparty/base64/lib/tables/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
table_generator

17
3rdparty/base64/lib/tables/Makefile vendored Normal file
View File

@@ -0,0 +1,17 @@
.PHONY: all clean
TARGETS := table_dec_32bit.h table_enc_12bit.h table_generator
all: $(TARGETS)
clean:
$(RM) $(TARGETS)
table_dec_32bit.h: table_generator
./$^ > $@
table_enc_12bit.h: table_enc_12bit.py
./$^ > $@
table_generator: table_generator.c
$(CC) $(CFLAGS) -o $@ $^

View File

@@ -0,0 +1,393 @@
#include <stdint.h>
#define CHAR62 '+'
#define CHAR63 '/'
#define CHARPAD '='
#if BASE64_LITTLE_ENDIAN
/* SPECIAL DECODE TABLES FOR LITTLE ENDIAN (INTEL) CPUS */
const uint32_t base64_table_dec_32bit_d0[256] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x000000f8, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000fc,
0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4,
0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018,
0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030,
0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048,
0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060,
0x00000064, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078,
0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090,
0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8,
0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0,
0x000000c4, 0x000000c8, 0x000000cc, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
const uint32_t base64_table_dec_32bit_d1[256] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x0000e003, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000f003,
0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003,
0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,
0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,
0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001,
0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001,
0x00009001, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001,
0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002,
0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002,
0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003,
0x00001003, 0x00002003, 0x00003003, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
const uint32_t base64_table_dec_32bit_d2[256] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x00800f00, 0xffffffff, 0xffffffff, 0xffffffff, 0x00c00f00,
0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00,
0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100,
0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300,
0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400,
0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600,
0x00400600, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700,
0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900,
0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00,
0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00,
0x00400c00, 0x00800c00, 0x00c00c00, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
const uint32_t base64_table_dec_32bit_d3[256] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x003e0000, 0xffffffff, 0xffffffff, 0xffffffff, 0x003f0000,
0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000,
0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000,
0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000,
0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000,
0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000,
0x00190000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000,
0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000,
0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000,
0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000,
0x00310000, 0x00320000, 0x00330000, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
#else
/* SPECIAL DECODE TABLES FOR BIG ENDIAN (IBM/MOTOROLA/SUN) CPUS */
const uint32_t base64_table_dec_32bit_d0[256] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xf8000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfc000000,
0xd0000000, 0xd4000000, 0xd8000000, 0xdc000000, 0xe0000000, 0xe4000000,
0xe8000000, 0xec000000, 0xf0000000, 0xf4000000, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
0x04000000, 0x08000000, 0x0c000000, 0x10000000, 0x14000000, 0x18000000,
0x1c000000, 0x20000000, 0x24000000, 0x28000000, 0x2c000000, 0x30000000,
0x34000000, 0x38000000, 0x3c000000, 0x40000000, 0x44000000, 0x48000000,
0x4c000000, 0x50000000, 0x54000000, 0x58000000, 0x5c000000, 0x60000000,
0x64000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x68000000, 0x6c000000, 0x70000000, 0x74000000, 0x78000000,
0x7c000000, 0x80000000, 0x84000000, 0x88000000, 0x8c000000, 0x90000000,
0x94000000, 0x98000000, 0x9c000000, 0xa0000000, 0xa4000000, 0xa8000000,
0xac000000, 0xb0000000, 0xb4000000, 0xb8000000, 0xbc000000, 0xc0000000,
0xc4000000, 0xc8000000, 0xcc000000, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
const uint32_t base64_table_dec_32bit_d1[256] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x03e00000, 0xffffffff, 0xffffffff, 0xffffffff, 0x03f00000,
0x03400000, 0x03500000, 0x03600000, 0x03700000, 0x03800000, 0x03900000,
0x03a00000, 0x03b00000, 0x03c00000, 0x03d00000, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
0x00100000, 0x00200000, 0x00300000, 0x00400000, 0x00500000, 0x00600000,
0x00700000, 0x00800000, 0x00900000, 0x00a00000, 0x00b00000, 0x00c00000,
0x00d00000, 0x00e00000, 0x00f00000, 0x01000000, 0x01100000, 0x01200000,
0x01300000, 0x01400000, 0x01500000, 0x01600000, 0x01700000, 0x01800000,
0x01900000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x01a00000, 0x01b00000, 0x01c00000, 0x01d00000, 0x01e00000,
0x01f00000, 0x02000000, 0x02100000, 0x02200000, 0x02300000, 0x02400000,
0x02500000, 0x02600000, 0x02700000, 0x02800000, 0x02900000, 0x02a00000,
0x02b00000, 0x02c00000, 0x02d00000, 0x02e00000, 0x02f00000, 0x03000000,
0x03100000, 0x03200000, 0x03300000, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
const uint32_t base64_table_dec_32bit_d2[256] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x000f8000, 0xffffffff, 0xffffffff, 0xffffffff, 0x000fc000,
0x000d0000, 0x000d4000, 0x000d8000, 0x000dc000, 0x000e0000, 0x000e4000,
0x000e8000, 0x000ec000, 0x000f0000, 0x000f4000, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
0x00004000, 0x00008000, 0x0000c000, 0x00010000, 0x00014000, 0x00018000,
0x0001c000, 0x00020000, 0x00024000, 0x00028000, 0x0002c000, 0x00030000,
0x00034000, 0x00038000, 0x0003c000, 0x00040000, 0x00044000, 0x00048000,
0x0004c000, 0x00050000, 0x00054000, 0x00058000, 0x0005c000, 0x00060000,
0x00064000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x00068000, 0x0006c000, 0x00070000, 0x00074000, 0x00078000,
0x0007c000, 0x00080000, 0x00084000, 0x00088000, 0x0008c000, 0x00090000,
0x00094000, 0x00098000, 0x0009c000, 0x000a0000, 0x000a4000, 0x000a8000,
0x000ac000, 0x000b0000, 0x000b4000, 0x000b8000, 0x000bc000, 0x000c0000,
0x000c4000, 0x000c8000, 0x000cc000, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
const uint32_t base64_table_dec_32bit_d3[256] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x00003e00, 0xffffffff, 0xffffffff, 0xffffffff, 0x00003f00,
0x00003400, 0x00003500, 0x00003600, 0x00003700, 0x00003800, 0x00003900,
0x00003a00, 0x00003b00, 0x00003c00, 0x00003d00, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
0x00000100, 0x00000200, 0x00000300, 0x00000400, 0x00000500, 0x00000600,
0x00000700, 0x00000800, 0x00000900, 0x00000a00, 0x00000b00, 0x00000c00,
0x00000d00, 0x00000e00, 0x00000f00, 0x00001000, 0x00001100, 0x00001200,
0x00001300, 0x00001400, 0x00001500, 0x00001600, 0x00001700, 0x00001800,
0x00001900, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0x00001a00, 0x00001b00, 0x00001c00, 0x00001d00, 0x00001e00,
0x00001f00, 0x00002000, 0x00002100, 0x00002200, 0x00002300, 0x00002400,
0x00002500, 0x00002600, 0x00002700, 0x00002800, 0x00002900, 0x00002a00,
0x00002b00, 0x00002c00, 0x00002d00, 0x00002e00, 0x00002f00, 0x00003000,
0x00003100, 0x00003200, 0x00003300, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
#endif

File diff suppressed because it is too large Load Diff

45
3rdparty/base64/lib/tables/table_enc_12bit.py vendored Executable file
View File

@@ -0,0 +1,45 @@
#!/usr/bin/python3
def tr(x):
"""Translate a 6-bit value to the Base64 alphabet."""
s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' \
+ 'abcdefghijklmnopqrstuvwxyz' \
+ '0123456789' \
+ '+/'
return ord(s[x])
def table(fn):
"""Generate a 12-bit lookup table."""
ret = []
for n in range(0, 2**12):
pre = "\n\t" if n % 8 == 0 else " "
pre = "\t" if n == 0 else pre
ret.append("{}0x{:04X}U,".format(pre, fn(n)))
return "".join(ret)
def table_be():
"""Generate a 12-bit big-endian lookup table."""
return table(lambda n: (tr(n & 0x3F) << 0) | (tr(n >> 6) << 8))
def table_le():
"""Generate a 12-bit little-endian lookup table."""
return table(lambda n: (tr(n >> 6) << 0) | (tr(n & 0x3F) << 8))
def main():
"""Entry point."""
lines = [
"#include <stdint.h>",
"",
"const uint16_t base64_table_enc_12bit[] = {",
"#if BASE64_LITTLE_ENDIAN",
table_le(),
"#else",
table_be(),
"#endif",
"};"
]
for line in lines:
print(line)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,184 @@
/**
*
* Copyright 2005, 2006 Nick Galbreath -- nickg [at] modp [dot] com
* Copyright 2017 Matthieu Darbois
* All rights reserved.
*
* http://modp.com/release/base64
*
* 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
* HOLDER 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.
*
*/
/****************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
static uint8_t b64chars[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
static uint8_t padchar = '=';
static void printStart(void)
{
printf("#include <stdint.h>\n");
printf("#define CHAR62 '%c'\n", b64chars[62]);
printf("#define CHAR63 '%c'\n", b64chars[63]);
printf("#define CHARPAD '%c'\n", padchar);
}
static void clearDecodeTable(uint32_t* ary)
{
int i = 0;
for (i = 0; i < 256; ++i) {
ary[i] = 0xFFFFFFFF;
}
}
/* dump uint32_t as hex digits */
void uint32_array_to_c_hex(const uint32_t* ary, size_t sz, const char* name)
{
size_t i = 0;
printf("const uint32_t %s[%d] = {\n", name, (int)sz);
for (;;) {
printf("0x%08" PRIx32, ary[i]);
++i;
if (i == sz)
break;
if (i % 6 == 0) {
printf(",\n");
} else {
printf(", ");
}
}
printf("\n};\n");
}
int main(int argc, char** argv)
{
uint32_t x;
uint32_t i = 0;
uint32_t ary[256];
/* over-ride standard alphabet */
if (argc == 2) {
uint8_t* replacements = (uint8_t*)argv[1];
if (strlen((char*)replacements) != 3) {
fprintf(stderr, "input must be a string of 3 characters '-', '.' or '_'\n");
exit(1);
}
fprintf(stderr, "fusing '%s' as replacements in base64 encoding\n", replacements);
b64chars[62] = replacements[0];
b64chars[63] = replacements[1];
padchar = replacements[2];
}
printStart();
printf("\n\n#if BASE64_LITTLE_ENDIAN\n");
printf("\n\n/* SPECIAL DECODE TABLES FOR LITTLE ENDIAN (INTEL) CPUS */\n\n");
clearDecodeTable(ary);
for (i = 0; i < 64; ++i) {
x = b64chars[i];
ary[x] = i << 2;
}
uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d0");
printf("\n\n");
clearDecodeTable(ary);
for (i = 0; i < 64; ++i) {
x = b64chars[i];
ary[x] = ((i & 0x30) >> 4) | ((i & 0x0F) << 12);
}
uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d1");
printf("\n\n");
clearDecodeTable(ary);
for (i = 0; i < 64; ++i) {
x = b64chars[i];
ary[x] = ((i & 0x03) << 22) | ((i & 0x3c) << 6);
}
uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d2");
printf("\n\n");
clearDecodeTable(ary);
for (i = 0; i < 64; ++i) {
x = b64chars[i];
ary[x] = i << 16;
}
uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d3");
printf("\n\n");
printf("#else\n");
printf("\n\n/* SPECIAL DECODE TABLES FOR BIG ENDIAN (IBM/MOTOROLA/SUN) CPUS */\n\n");
clearDecodeTable(ary);
for (i = 0; i < 64; ++i) {
x = b64chars[i];
ary[x] = i << 26;
}
uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d0");
printf("\n\n");
clearDecodeTable(ary);
for (i = 0; i < 64; ++i) {
x = b64chars[i];
ary[x] = i << 20;
}
uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d1");
printf("\n\n");
clearDecodeTable(ary);
for (i = 0; i < 64; ++i) {
x = b64chars[i];
ary[x] = i << 14;
}
uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d2");
printf("\n\n");
clearDecodeTable(ary);
for (i = 0; i < 64; ++i) {
x = b64chars[i];
ary[x] = i << 8;
}
uint32_array_to_c_hex(ary, sizeof(ary) / sizeof(uint32_t), "base64_table_dec_32bit_d3");
printf("\n\n");
printf("#endif\n");
return 0;
}

40
3rdparty/base64/lib/tables/tables.c vendored Normal file
View File

@@ -0,0 +1,40 @@
#include "tables.h"
const uint8_t
base64_table_enc_6bit[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
"+/";
// In the lookup table below, note that the value for '=' (character 61) is
// 254, not 255. This character is used for in-band signaling of the end of
// the datastream, and we will use that later. The characters A-Z, a-z, 0-9
// and + / are mapped to their "decoded" values. The other bytes all map to
// the value 255, which flags them as "invalid input".
const uint8_t
base64_table_dec_8bit[] =
{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0..15
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 16..31
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, // 32..47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 254, 255, 255, // 48..63
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64..79
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // 80..95
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96..111
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, // 112..127
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 128..143
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
};
#if BASE64_WORDSIZE >= 32
# include "table_dec_32bit.h"
# include "table_enc_12bit.h"
#endif

23
3rdparty/base64/lib/tables/tables.h vendored Normal file
View File

@@ -0,0 +1,23 @@
#ifndef BASE64_TABLES_H
#define BASE64_TABLES_H
#include <stdint.h>
#include "../env.h"
// These tables are used by all codecs for fallback plain encoding/decoding:
extern const uint8_t base64_table_enc_6bit[];
extern const uint8_t base64_table_dec_8bit[];
// These tables are used for the 32-bit and 64-bit generic decoders:
#if BASE64_WORDSIZE >= 32
extern const uint32_t base64_table_dec_32bit_d0[];
extern const uint32_t base64_table_dec_32bit_d1[];
extern const uint32_t base64_table_dec_32bit_d2[];
extern const uint32_t base64_table_dec_32bit_d3[];
// This table is used by the 32 and 64-bit generic encoders:
extern const uint16_t base64_table_enc_12bit[];
#endif
#endif // BASE64_TABLES_H

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2003-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
Copyright (c) 2003-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -51,6 +51,8 @@ typedef unsigned char uint8_t;
#else /* VS2008 or older (or VS2010 in C mode) */
#define NO_DECLTYPE
#endif
#elif defined(__MCST__) /* Elbrus C Compiler */
#define DECLTYPE(x) (__typeof(x))
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
#define NO_DECLTYPE
#else /* GNU, Sun and other compilers */
@@ -450,7 +452,7 @@ do {
#define HASH_DELETE_HH(hh,head,delptrhh) \
do { \
struct UT_hash_handle *_hd_hh_del = (delptrhh); \
const struct UT_hash_handle *_hd_hh_del = (delptrhh); \
if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl->buckets, \
@@ -593,7 +595,9 @@ do {
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
* (archive link: https://archive.is/Ivcan )
*/
#define HASH_SAX(key,keylen,hashv) \
do { \
unsigned _sx_i; \

View File

@@ -11,4 +11,4 @@ https://www.reddit.com/r/KittyTerminal[Reddit community]
Packaging status in various repositories:
image:https://repology.org/badge/vertical-allrepos/kitty.svg["Packaging status", link="https://repology.org/project/kitty/versions"]
image:https://repology.org/badge/vertical-allrepos/kitty.svg?columns=3&header=kitty["Packaging status", link="https://repology.org/project/kitty/versions"]

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
@@ -27,6 +27,7 @@ def compile_terminfo(base):
os.makedirs(odir, exist_ok=True)
ofile = os.path.join(odir, xterm_kitty)
shutil.move(tfile, ofile)
return ofile
def generate_terminfo():
@@ -46,7 +47,14 @@ def generate_terminfo():
with open('terminfo/kitty.termcap', 'w') as f:
f.write(tcap)
compile_terminfo(os.path.join(base, 'terminfo'))
dbfile = compile_terminfo(os.path.join(base, 'terminfo'))
with open(dbfile, 'rb') as f:
data = f.read()
with open('kitty/terminfo.h', 'w') as f:
print(f'static const uint8_t terminfo_data[{len(data)}] = ''{', file=f)
for b in data:
print(b, end=', ', file=f)
print('};', file=f)
if __name__ == '__main__':

View File

@@ -242,7 +242,9 @@ func dependencies(args []string) {
chdir_to_base()
nf := flag.NewFlagSet("deps", flag.ExitOnError)
docsptr := nf.Bool("for-docs", false, "download the dependencies needed to build the documentation")
nf.Parse(args)
if err := nf.Parse(args); err != nil {
exit(err)
}
if *docsptr {
dependencies_for_docs()
fmt.Println("Dependencies needed to generate documentation have been installed. Build docs with ./dev.sh docs")
@@ -323,7 +325,7 @@ func dependencies(args []string) {
}); err != nil {
exit(err)
}
fmt.Println(`Dependencies downloaded. Now build kitty with: make develop`)
fmt.Println(`Dependencies downloaded. Now build kitty with: ./dev.sh build`)
}
// }}}
@@ -384,7 +386,9 @@ func docs(args []string) {
nf := flag.NewFlagSet("deps", flag.ExitOnError)
livereload := nf.Bool("live-reload", false, "build the docs and make them available via s local server with live reloading for ease of development")
failwarn := nf.Bool("fail-warn", false, "make warnings fatal when building the docs")
nf.Parse(args)
if err := nf.Parse(args); err != nil {
exit(err)
}
exe := filepath.Join(root_dir(), "bin", "sphinx-build")
aexe := filepath.Join(root_dir(), "bin", "sphinx-autobuild")
target := "docs"

View File

@@ -46,7 +46,7 @@ def run(*args, **extra_env):
return subprocess.call(list(args), env=env, cwd=cwd)
SETUP_CMD = [PYTHON, 'setup.py', '--build-universal-binary']
SETUP_CMD = [PYTHON, 'setup.py']
def build_frozen_launcher(extra_include_dirs):

View File

@@ -147,9 +147,9 @@
{
"name": "python",
"unix": {
"filename": "Python-3.9.4.tar.xz",
"hash": "sha256:4b0e6644a76f8df864ae24ac500a51bbf68bd098f6a173e27d3b61cdca9aa134",
"urls": ["https://www.python.org/ftp/python/3.9.4/{filename}"]
"filename": "Python-3.11.6.tar.xz",
"hash": "sha256:0fab78fa7f133f4f38210c6260d90d7c0d5c7198446419ce057ec7ac2e6f5f38",
"urls": ["https://www.python.org/ftp/python/3.11.6/{filename}"]
}
},
@@ -244,9 +244,18 @@
{
"name": "harfbuzz",
"unix": {
"filename": "harfbuzz-2.7.4.tar.xz",
"hash": "sha256:6ad11d653347bd25d8317589df4e431a2de372c0cf9be3543368e07ec23bb8e7",
"urls": ["https://github.com/harfbuzz/harfbuzz/releases/download/2.7.4/{filename}"]
"filename": "harfbuzz-8.2.2.tar.xz",
"hash": "sha256:e433ad85fbdf57f680be29479b3f964577379aaf319f557eb76569f0ecbc90f3",
"urls": ["https://github.com/harfbuzz/harfbuzz/releases/download/8.2.2/{filename}"]
}
},
{
"name": "simde",
"unix": {
"filename": "simde-amalgamated-0.7.6.tar.xz",
"hash": "sha256:703eac1f2af7de1f7e4aea2286130b98e1addcc0559426e78304c92e2b4eb5e1",
"urls": ["https://github.com/simd-everywhere/simde/releases/download/v0.7.6/{filename}"]
}
},

View File

@@ -5,13 +5,14 @@ import subprocess
ls_files = subprocess.check_output([ 'git', 'ls-files']).decode('utf-8')
all_files = set(ls_files.splitlines())
all_files.discard('')
cp = subprocess.run(['git', 'check-attr', 'linguist-generated', '--stdin'],
check=True, stdout=subprocess.PIPE, input='\n'.join(all_files).encode('utf-8'))
for line in cp.stdout.decode().splitlines():
if line.endswith(' true'):
fname = line.split(':', 1)[0]
all_files.discard(fname)
for attr in ('linguist-generated', 'linguist-vendored'):
cp = subprocess.run(['git', 'check-attr', attr, '--stdin'],
check=True, stdout=subprocess.PIPE, input='\n'.join(all_files).encode('utf-8'))
for line in cp.stdout.decode().splitlines():
if line.endswith(' true'):
fname = line.split(':', 1)[0]
all_files.discard(fname)
all_files -= {'nerd-fonts-glyphs.txt', 'rowcolumn-diacritics.txt'}
all_files -= {'gen/nerd-fonts-glyphs.txt', 'gen/rowcolumn-diacritics.txt'}
cp = subprocess.run(['cloc', '--list-file', '-'], input='\n'.join(all_files).encode())
raise SystemExit(cp.returncode)

View File

@@ -6,5 +6,6 @@ Mappable actions
The actions described below can be mapped to any key press or mouse action
using the ``map`` and ``mouse_map`` directives in :file:`kitty.conf`. For
configuration examples, see the default shortcut links for each action.
To read about keyboard mapping in more detail, see :doc:`mapping`.
.. include:: /generated/actions.rst

View File

@@ -104,6 +104,8 @@ or another OS window::
map ctrl+f3 detach_window tab-prev
# moves the window into the tab at the left of the active tab
map ctrl+f3 detach_window tab-left
# moves the window into a new tab created to the left of the active tab
map ctrl+f3 detach_window new-tab-left
# asks which tab to move the window into
map ctrl+f4 detach_window ask
@@ -124,7 +126,9 @@ Other keyboard shortcuts
----------------------------------
The full list of actions that can be mapped to key presses is available
:doc:`here </actions>`.
:doc:`here </actions>`. To learn how to do more sophisticated keyboard
mappings, such as modal mappings, per application mappings, etc. see
:doc:`mapping`.
================================== =======================
Action Shortcut

View File

@@ -30,7 +30,7 @@ to build kitty with your changes.
.. note::
If you plan to run kitty from source long-term, there are a couple of
caveats to be aware of. You should occassionally run ``./dev.sh deps``
caveats to be aware of. You should occasionally run ``./dev.sh deps``
to have the dependencies re-downloaded as they are updated periodically.
Also, the built kitty executable assumes it will find source in whatever
directory you first ran :code:`./dev.sh build` in. If you move/rename the
@@ -96,6 +96,7 @@ Run-time dependencies:
Build-time dependencies:
* ``gcc`` or ``clang``
* ``simde``
* ``go`` >= _build_go_version (see :file:`go.mod` for go packages used during building)
* ``pkg-config``
* For building on Linux in addition to the above dependencies you might also
@@ -115,6 +116,7 @@ Build-time dependencies:
- ``libssl-dev``
- ``libpython3-dev``
- ``libxxhash-dev``
- ``libsmide-dev``
Build and run from source with Nix

View File

@@ -9,6 +9,20 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
Recent major new features
---------------------------
Cheetah speed 🐆
~~~~~~~~~~~~~~~~~~~~~~
kitty has grown up and become a cheetah. It now parses data it receives in
parallel :iss:`using SIMD vector CPU instructions <7005>` for a 2x speedup in
benchmarks and a 10%-50% real world speedup depending on workload. There is a
new benchmarking kitten ``kitten __benchmark__`` that can be used to measure
terminal throughput. There is also :ref:`a table <throughput>` showing kitty is
much faster than other terminal emulators based on the benchmark kitten. While
kitty was already so fast that its performance was never a bottleneck, this
improvement makes it even faster and more importantly reduces the energy
consumption to do the same tasks.
File transfer over the tty device
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -28,21 +42,229 @@ The kitten can transfer files to and from the remote computer. It supports
recursive transfer of directories, symlinks and hardlinks. It can even use the
rsync algorithm to speed up repeated transfers of large files.
Truly convenient SSH
~~~~~~~~~~~~~~~~~~~~~~~~
The :doc:`ssh kitten <kittens/ssh>` is redesigned with powerful new features:
* Automatic :ref:`shell_integration` on remote machines
* Easily :ref:`clone local shell/editor config <real_world_ssh_kitten_config>` on remote machines
* Easily :ref:`edit files in your local editor <edit_file>` on remote machines
* Automatic :opt:`re-use of existing connections <kitten-ssh.share_connections>` to avoid connection setup latency
.. }}}
Detailed list of changes
-------------------------------------
0.33.2 [future]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Wayland: panel kitten: Add support for drawing desktop background and bars
using the panel kitten for all compositors that support the requisite Wayland
protocol which is practically speaking all of them but GNOME (:pull:`2590`)
- Wayland: Support fractional scales so that there is no wasted drawing at larger scale followed by resizing in the compositor
- Wayland: Support preferred integer scales
- Wayland KDE: Support :opt:`background_blur`
- A new option :opt:`terminfo_type` to allow passing the terminfo database embedded into the :envvar:`TERMINFO` env var directly instead of via a file
- Mouse reporting: Fix drag release event outside the window not being reported in legacy mouse reporting modes (:iss:`7244`)
- macOS: Fix a regression in the previous release that broke rendering of some symbols on some systems (:iss:`7249`)
- Fix handling of tab character when cursor is at end of line and wrapping is enabled (:iss:`7250`)
0.33.1 [2024-03-21]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fix a regression in the previous release that caused requesting data from the clipboard via OSC 52 to instead return data from the primary selection (:iss:`7213`)
- Splits layout: Allow resizing until one of the halves in a split is minimally sized (:iss:`7220`)
- macOS: Fix text rendered with fallback fonts not respecting bold/italic styling (:disc:`7241`)
- macOS: When CoreText fails to find a fallback font for a character in the first Private Use Unicode Area, preferentially use the NERD font, if available, for it (:iss:`6043`)
0.33.0 [2024-03-12]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- :ref:`Cheetah speed <throughput>` with a redesigned render loop and a 2x faster escape code
parser that uses SIMD CPU vector instruction to parse data in parallel
(:iss:`7005`)
- A new benchmark kitten (``kitten __benchmark__``) to measure terminal
throughput performance
- Graphics protocol: Add a new delete mode for deleting images whose ids fall within a range. Useful for bulk deletion (:iss:`7080`)
- Keyboard protocol: Fix the :kbd:`Enter`, :kbd:`Tab` and :kbd:`Backspace` keys
generating spurious release events even when report all keys as escape codes
is not set (:iss:`7136`)
- macOS: The command line args from :file:`macos-launch-services-cmdline` are now
prefixed to any args from ``open --args`` rather than overwriting them (:iss:`7135`)
- Allow specifying where the new tab is created for :ac:`detach_window` (:pull:`7134`)
- hints kitten: The option to set the text color for hints now allows arbitrary
colors (:pull:`7150`)
- icat kitten: Add a command line argument to override terminal window size detection (:iss:`7165`)
- A new action :ac:`toggle_tab` to easily switch to and back from a tab with a single shortcut (:iss:`7203`)
- When :ac:`clearing terminal <clear_terminal>` add a new type ``to_cursor_scroll`` which can be
used to clear to prompt while moving cleared lines into the scrollback
- Fix a performance bottleneck when dealing with thousands of small images
(:iss:`7080`)
- kitten @ ls: Return the timestamp at which the window was created (:iss:`7178`)
- hints kitten: Use default editor rather than hardcoding vim to open file at specific line (:iss:`7186`)
- Remote control: Fix ``--match`` argument not working for @ls, @send-key,
@set-background-image (:iss:`7192`)
- Keyboard protocol: Do not deliver a fake key release events on OS window focus out for engaged modifiers (:iss:`7196`)
- Ignore :opt:`startup_session` when kitty is invoked with command line options specifying a command to run (:pull:`7198`)
- Box drawing: Specialize rendering for the Fira Code progress bar/spinner glyphs
0.32.2 [2024-02-12]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- kitten @ load-config: Allow (re)loading kitty.conf via remote control
- Remote control: Allow running mappable actions via remote control (`kitten @ action`)
- kitten @ send-text: Add a new option to automatically wrap the sent text in
bracketed paste escape codes if the program in the destination window has
turned on bracketed paste.
- Fix a single key mapping not overriding a previously defined multi-key mapping
- macOS: Fix :code:`kitten @ select-window` leaving the keyboard in a partially functional state (:iss:`7074`)
- Graphics protocol: Improve display of images using Unicode placeholders or
row/column boxes by resizing them using linear instead of nearest neighbor
interpolation on the GPU (:iss:`7070`)
- When matching URLs use the definition of legal characters in URLs from the
`WHATWG spec <https://url.spec.whatwg.org/#url-code-points>`__ rather than older standards (:iss:`7095`)
- hints kitten: Respect the kitty :opt:`url_excluded_characters` option
(:iss:`7075`)
- macOS: Fix an abort when changing OS window chrome for a full screen window via remote control or the themes kitten (:iss:`7106`)
- Special case rendering of some more box drawing characters using shades from the block of symbols for legacy computing (:iss:`7110`)
- A new action :ac:`close_other_os_windows` to close non active OS windows (:disc:`7113`)
0.32.1 [2024-01-26]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- macOS: Fix a regression in the previous release that broke overriding keyboard shortcuts for actions present in the global menu bar (:iss:`7016`)
- Fix a regression in the previous release that caused multi-key sequences to not abort when pressing an unknown key (:iss:`7022`)
- Fix a regression in the previous release that caused `kitten @ launch --cwd=current` to fail over SSH (:iss:`7028`)
- Fix a regression in the previous release that caused `kitten @ send-text` with a match tab parameter to send text twice to the active window (:iss:`7027`)
- Fix a regression in the previous release that caused overriding of existing multi-key mappings to fail (:iss:`7044`, :iss:`7058`)
- Wayland+NVIDIA: Do not request an sRGB output buffer as a bug in Wayland causes kitty to not start (:iss:`7021`)
0.32.0 [2024-01-19]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- :ref:`conditional_mappings`
- Support for :ref:`modal_mappings` such as in modal editors like vim
- A new option :opt:`notify_on_cmd_finish` to show a desktop notification when a long running command finishes (:pull:`6817`)
- A new action :ac:`send_key` to simplify mapping key presses to other keys without needing :ac:`send_text`
- Allow focusing previously active OS windows via :ac:`nth_os_window` (:pull:`7009`)
- Wayland: Fix a regression in the previous release that broke copying to clipboard under wl-roots based compositors in some circumstances
(:iss:`6890`)
- macOS: Fix some combining characters not being rendered (:iss:`6898`)
- macOS: Fix returning from full screen via the button when the titlebar is hidden not hiding the buttons (:iss:`6883`)
- macOS: Fix newly created OS windows not always appearing on the "active" monitor (:pull:`6932`)
- Font fallback: Fix the font used to render a character sometimes dependent on the order in which characters appear on screen (:iss:`6865`)
- panel kitten: Fix rendering with non-zero margin/padding in kitty.conf (:iss:`6923`)
- kitty keyboard protocol: Specify the behavior of the modifier bits during modifier key events (:iss:`6913`)
- Wayland: Enable support for the new cursor-shape protocol so that the mouse cursor is always rendered at the correct size in compositors that support this protocol (:iss:`6914`)
- GNOME Wayland: Fix remembered window size smaller than actual size (:iss:`6946`)
- Mouse reporting: Fix incorrect position reported for windows with padding (:iss:`6950`)
- Fix :ac:`focus_visible_window` not switching to other window in stack layout
when only two windows are present (:iss:`6970`)
0.31.0 [2023-11-08]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Allow :ac:`easily running arbitrarily complex remote control scripts <remote_control_script>` without needing to turn on remote control (:iss:`6712`)
- A new option :opt:`menu_map` that allows adding entries to the global menubar on macOS (:disc:`6680`)
- A new :doc:`escape code <pointer-shapes>` that can be used by programs running in the terminal to change the shape of the mouse pointer (:iss:`6711`)
- Graphics protocol: Support for positioning :ref:`images relative to other images <relative_image_placement>` (:iss:`6400`)
- A new option :opt:`single_window_padding_width` to use a different padding when only a single window is visible (:iss:`6734`)
- A new mouse action ``mouse_selection word_and_line_from_point`` to select the current word under the mouse cursor and extend to end of line (:pull:`6663`)
- A new option :opt:`underline_hyperlinks` to control when hyperlinks are underlined (:iss:`6766`)
- Allow using the full range of standard mouse cursor shapes when customizing the mouse cursor
- macOS: When running the default shell with the login program fix :file:`~/.hushlogin` not being respected when opening windows not in the home directory (:iss:`6689`)
- macOS: Fix poor performance when using ligatures with some fonts, caused by slow harfbuzz shaping (:iss:`6743`)
- :option:`kitten @ set-background-opacity --toggle` - a new flag to easily switch opacity between the specified value and the default (:iss:`6691`)
- Fix a regression caused by rewrite of kittens to Go that made various kittens reset colors in a terminal when the colors were changed by escape code (:iss:`6708`)
- Fix trailing bracket not ignored when detecting a multi-line URL with the trailing bracket as the first character on the last line (:iss:`6710`)
- Fix the :option:`kitten @ launch --copy-env` option not copying current environment variables (:iss:`6724`)
- Fix a regression that broke :program:`kitten update-self` (:iss:`6729`)
- Two new event types for :ref:`watchers <watchers>`, :code:`on_title_change` and :code:`on_set_user_var`
- When pasting, if the text contains terminal control codes ask the user for permission. See :opt:`paste_actions` for details. Thanks to David Leadbeater for discovering this.
- Render Private Use Unicode symbols using two cells if the second cell contains an en-space as well as a normal space
- macOS: Fix a regression in the previous release that caused kitten @ ls to not report the environment variables for the default shell (:iss:`6749`)
- :doc:`Desktop notification protocol </desktop-notifications>`: Allow applications sending notifications to specify that the notification should only be displayed if the window is currently unfocused (:iss:`6755`)
- :doc:`unicode_input kitten </kittens/unicode_input>`: Fix a regression that broke the "Emoticons" tab (:iss:`6760`)
- Shell integration: Fix ``sudo --edit`` not working and also fix completions for sudo not working in zsh (:iss:`6754`, :iss:`6771`)
- A new action :ac:`set_window_title` to interactively change the title of the active window
- ssh kitten: Fix a regression that broken :kbd:`ctrl+space` mapping in zsh (:iss:`6780`)
- Wayland: Fix primary selections not working with the river compositor (:iss:`6785`)
0.30.1 [2023-10-05]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1304,10 +1526,10 @@ Detailed list of changes
- Fix deleting windows that are not the last window via remote control leaving
no window focused (:iss:`3619`)
- Add an option :option:`kitty @ get-text --add-cursor` to also get the current
- Add an option :option:`kitten @ get-text --add-cursor` to also get the current
cursor position and state as ANSI escape codes (:iss:`3625`)
- Add an option :option:`kitty @ get-text --add-wrap-markers` to add line wrap
- Add an option :option:`kitten @ get-text --add-wrap-markers` to add line wrap
markers to the output (:pull:`3633`)
- Improve rendering of curly underlines on HiDPI screens (:pull:`3637`)
@@ -2911,7 +3133,7 @@ Detailed list of changes
- diff kitten: Fix error when right hand side file is binary and left hand side
file is text (:pull:`752`)
- kitty @ new-window: Add a new option :option:`kitty @ new-window --window-type`
- kitty @ new-window: Add a new option :option:`kitten @ new-window --window-type`
to create top-level OS windows (:iss:`770`)
- macOS: The :opt:`focus_follows_mouse` option now also works across top-level kitty OS windows
@@ -3028,7 +3250,7 @@ Detailed list of changes
- diff kitten: Fix default foreground/background colors not being restored when
kitten quits (:iss:`637`)
- Fix :option:`kitty @ set-colors --all` not working when more than one window
- Fix :option:`kitten @ set-colors --all` not working when more than one window
present (:iss:`632`)
- Fix a regression that broke the legacy increase/decrease_font_size actions

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
# vim:fileencoding=utf-8
#
# Configuration file for the Sphinx documentation builder.
@@ -7,18 +7,19 @@
# full list see the documentation:
# https://www.sphinx-doc.org/en/master/config
import glob
import os
import re
import subprocess
import sys
import time
from functools import lru_cache, partial
from typing import Any, Callable, Dict, Iterable, List, Tuple
from typing import Any, Callable, Dict, Iterable, Iterator, List, Tuple
from docutils import nodes
from docutils.parsers.rst.roles import set_classes
from pygments.lexer import RegexLexer, bygroups # type: ignore
from pygments.token import Comment, Keyword, Literal, Name, Number, String, Whitespace # type: ignore
from pygments.token import Comment, Error, Keyword, Literal, Name, Number, String, Whitespace # type: ignore
from sphinx import addnodes, version_info
from sphinx.util.logging import getLogger
@@ -27,7 +28,8 @@ if kitty_src not in sys.path:
sys.path.insert(0, kitty_src)
from kitty.conf.types import Definition, expand_opt_references # noqa
from kitty.constants import str_version, website_url # noqa
from kitty.constants import str_version, website_url # noqa
from kitty.fast_data_types import Shlex # noqa
# config {{{
# -- Project information -----------------------------------------------------
@@ -176,8 +178,8 @@ manpages_url = 'https://man7.org/linux/man-pages/man{section}/{page}.{section}.h
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('invocation', 'kitty', 'kitty Documentation', [author], 1),
('conf', 'kitty.conf', 'kitty terminal emulator configuration file', [author], 5)
('invocation', 'kitty', 'The fast, feature rich terminal emulator', [author], 1),
('conf', 'kitty.conf', 'Configuration file for kitty', [author], 5)
]
@@ -209,16 +211,16 @@ def commit_role(
' Link to a github commit '
try:
commit_id = subprocess.check_output(
f'git rev-list --max-count=1 --skip=# {text}'.split()).decode('utf-8').strip()
f'git rev-list --max-count=1 {text}'.split()).decode('utf-8').strip()
except Exception:
msg = inliner.reporter.error(
f'GitHub commit id "{text}" not recognized.', line=lineno)
f'git commit id "{text}" not recognized.', line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
url = f'https://github.com/kovidgoyal/kitty/commit/{commit_id}'
set_classes(options)
short_id = subprocess.check_output(
f'git rev-list --max-count=1 --abbrev-commit --skip=# {commit_id}'.split()).decode('utf-8').strip()
f'git rev-list --max-count=1 --abbrev-commit {commit_id}'.split()).decode('utf-8').strip()
node = nodes.reference(rawtext, f'commit: {short_id}', refuri=url, **options)
return [node], []
# }}}
@@ -251,20 +253,20 @@ if you specify a program-to-run you can use the special placeholder
as_rst = partial(option_spec_as_rst, heading_char='_')
from kitty.rc.base import all_command_names, command_for_name
from kitty.remote_control import cli_msg, global_options_spec
with open('generated/cli-kitty-at.rst', 'w') as f:
with open('generated/cli-kitten-at.rst', 'w') as f:
p = partial(print, file=f)
p('kitty @')
p('kitten @')
p('-' * 80)
p('.. program::', 'kitty @')
p('.. program::', 'kitten @')
p('\n\n' + as_rst(
global_options_spec, message=cli_msg, usage='command ...', appname='kitty @'))
global_options_spec, message=cli_msg, usage='command ...', appname='kitten @'))
from kitty.rc.base import cli_params_for
for cmd_name in sorted(all_command_names()):
func = command_for_name(cmd_name)
p(f'.. _at-{func.name}:\n')
p('kitty @', func.name)
p('kitten @', func.name)
p('-' * 120)
p('.. program::', 'kitty @', func.name)
p('.. program::', 'kitten @', func.name)
p('\n\n' + as_rst(*cli_params_for(func)))
from kittens.runner import get_kitten_cli_docs
@@ -344,14 +346,70 @@ class ConfLexer(RegexLexer): # type: ignore
aliases = ['conf']
filenames = ['*.conf']
def map_flags(self: RegexLexer, val: str, start_pos: int) -> Iterator[Tuple[int, Any, str]]:
expecting_arg = ''
s = Shlex(val)
from kitty.options.utils import allowed_key_map_options
last_pos = 0
while (tok := s.next_word())[0] > -1:
x = tok[1]
if tok[0] > last_pos:
yield start_pos + last_pos, Whitespace, ' ' * (tok[0] - last_pos)
last_pos = tok[0] + len(x)
tok_start = start_pos + tok[0]
if expecting_arg:
yield tok_start, String, x
expecting_arg = ''
elif x.startswith('--'):
expecting_arg = x[2:]
k, sep, v = expecting_arg.partition('=')
k = k.replace('-', '_')
expecting_arg = k
if expecting_arg not in allowed_key_map_options:
yield tok_start, Error, x
elif sep == '=':
expecting_arg = ''
yield tok_start, Name, x
else:
yield tok_start, Name, x
else:
break
def mapargs(self: RegexLexer, match: 're.Match[str]') -> Iterator[Tuple[int, Any, str]]:
start_pos = match.start()
val = match.group()
parts = val.split(maxsplit=1)
if parts[0].startswith('--'):
seen = 0
for (pos, token, text) in self.map_flags(val, start_pos):
yield pos, token, text
seen += len(text)
start_pos += seen
val = val[seen:]
parts = val.split(maxsplit=1)
if not val:
return
yield start_pos, Literal, parts[0] # key spec
if len(parts) == 1:
return
start_pos += len(parts[0])
val = val[len(parts[0]):]
m = re.match(r'(\s+)(\S+)', val)
if m is None:
return
yield start_pos, Whitespace, m.group(1)
yield start_pos + m.start(2), Name.Function, m.group(2) # action function
yield start_pos + m.end(2), String, val[m.end(2):]
tokens = {
'root': [
(r'#.*?$', Comment.Single),
(r'\s+$', Whitespace),
(r'\s+', Whitespace),
(r'(include)(\s+)(.+?)$', bygroups(Comment.Preproc, Whitespace, Name.Namespace)),
(r'(map)(\s+)(\S+)(\s+)', bygroups(
Keyword.Declaration, Whitespace, String, Whitespace), 'action'),
(r'(map)(\s+)', bygroups(
Keyword.Declaration, Whitespace), 'mapargs'),
(r'(mouse_map)(\s+)(\S+)(\s+)(\S+)(\s+)(\S+)(\s+)', bygroups(
Keyword.Declaration, Whitespace, String, Whitespace, Name.Variable, Whitespace, String, Whitespace), 'action'),
(r'(symbol_map)(\s+)(\S+)(\s+)(.+?)$', bygroups(
@@ -363,6 +421,9 @@ class ConfLexer(RegexLexer): # type: ignore
(r'[a-z_0-9]+$', Name.Function, 'root'),
(r'[a-z_0-9]+', Name.Function, 'args'),
],
'mapargs': [
(r'.+$', mapargs, 'root'),
],
'args': [
(r'\s+', Whitespace, 'args'),
(r'\b(yes|no)\b$', Number.Bin, 'root'),
@@ -529,6 +590,18 @@ def write_conf_docs(app: Any, all_kitten_names: Iterable[str]) -> None:
from kitty.actions import as_rst
with open('generated/actions.rst', 'w', encoding='utf-8') as f:
f.write(as_rst())
from kitty.rc.base import MATCH_TAB_OPTION, MATCH_WINDOW_OPTION
with open('generated/matching.rst', 'w') as f:
print('Matching windows', file=f)
print('______________________________', file=f)
w = 'm' + MATCH_WINDOW_OPTION[MATCH_WINDOW_OPTION.find('Match') + 1:]
print('When matching windows,', w, file=f)
print('Matching tabs', file=f)
print('______________________________', file=f)
w = 'm' + MATCH_TAB_OPTION[MATCH_TAB_OPTION.find('Match') + 1:]
print('When matching tabs,', w, file=f)
# }}}
@@ -549,10 +622,13 @@ def add_html_context(app: Any, pagename: str, templatename: str, context: Any, d
@lru_cache
def monkeypatch_man_writer() -> None:
'''
Monkeypatch the docutils man translator to output better tables
Monkeypatch the docutils man translator to be nicer
'''
from docutils.nodes import Element
from docutils.writers.manpage import Table, Translator
from sphinx.writers.manpage import ManualPageTranslator
# Generate nicer tables https://sourceforge.net/p/docutils/bugs/475/
class PatchedTable(Table): # type: ignore
_options: list[str]
def __init__(self) -> None:
@@ -572,15 +648,103 @@ def monkeypatch_man_writer() -> None:
del ans[3] # top border
del ans[-2] # bottom border
return ans
def visit_table(self: Translator, node: object) -> None:
def visit_table(self: ManualPageTranslator, node: object) -> None:
setattr(self, '_active_table', PatchedTable())
setattr(Translator, 'visit_table', visit_table)
setattr(ManualPageTranslator, 'visit_table', visit_table)
# Improve header generation
def header(self: ManualPageTranslator) -> str:
di = getattr(self, '_docinfo')
di['ktitle'] = di['title'].replace('_', '-')
th = (".TH \"%(ktitle)s\" %(manual_section)s"
" \"%(date)s\" \"%(version)s\"") % di
if di["manual_group"]:
th += " \"%(manual_group)s\"" % di
th += "\n"
sh_tmpl: str = (".SH Name\n"
"%(ktitle)s \\- %(subtitle)s\n")
return th + sh_tmpl % di # type: ignore
setattr(ManualPageTranslator, 'header', header)
def visit_image(self: ManualPageTranslator, node: Element) -> None:
pass
def depart_image(self: ManualPageTranslator, node: Element) -> None:
pass
def depart_figure(self: ManualPageTranslator, node: Element) -> None:
self.body.append(' (images not supported)\n')
Translator.depart_figure(self, node)
setattr(ManualPageTranslator, 'visit_image', visit_image)
setattr(ManualPageTranslator, 'depart_image', depart_image)
setattr(ManualPageTranslator, 'depart_figure', depart_figure)
orig_astext = Translator.astext
def astext(self: Translator) -> Any:
b = []
for line in self.body:
if line.startswith('.SH'):
x, y = line.split(' ', 1)
parts = y.splitlines(keepends=True)
parts[0] = parts[0].capitalize()
line = x + ' ' + '\n'.join(parts)
b.append(line)
self.body = b
return orig_astext(self)
setattr(Translator, 'astext', astext)
def setup_man_pages() -> None:
from kittens.runner import get_kitten_cli_docs
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
for x in glob.glob(os.path.join(base, 'docs/kittens/*.rst')):
kn = os.path.basename(x).rpartition('.')[0]
if kn == 'custom':
continue
cd = get_kitten_cli_docs(kn) or {}
khn = kn.replace('_', '-')
man_pages.append((f'kittens/{kn}', 'kitten-' + khn, cd.get('short_desc', 'kitten Documentation'), [author], 1))
monkeypatch_man_writer()
def build_extra_man_pages() -> None:
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
kitten = os.environ.get('KITTEN_EXE_FOR_DOCS', os.path.join(base, 'kitty/launcher/kitten'))
if not os.path.exists(kitten):
kitten = os.path.join(base, 'kitty/launcher/kitty.app/Contents/MacOS/kitten')
if not os.path.exists(kitten):
subprocess.call(['find', os.path.join(base, 'kitty/launcher')])
raise Exception(f'The kitten binary {kitten} is not built cannot generate man pages')
raw = subprocess.check_output([kitten, '-h']).decode()
started = 0
names = set()
for line in raw.splitlines():
if line.strip() == '@':
started = len(line.rstrip()[:-1])
q = line.strip()
if started and len(q.split()) == 1 and not q.startswith('-') and ':' not in q:
if len(line) - len(line.lstrip()) == started:
if not os.path.exists(os.path.join(base, f'docs/kittens/{q}.rst')):
names.add(q)
cwd = os.path.join(base, 'docs/_build/man')
subprocess.check_call([kitten, '__generate_man_pages__'], cwd=cwd)
subprocess.check_call([kitten, '__generate_man_pages__'] + list(names), cwd=cwd)
if building_man_pages:
setup_man_pages()
def build_finished(*a: Any, **kw: Any) -> None:
if building_man_pages:
build_extra_man_pages()
def setup(app: Any) -> None:
os.makedirs('generated/conf', exist_ok=True)
from kittens.runner import all_kitten_names
monkeypatch_man_writer()
kn = all_kitten_names()
write_cli_docs(kn)
write_remote_control_protocol_docs()
@@ -589,10 +753,7 @@ def setup(app: Any) -> None:
app.connect('source-read', replace_string)
app.add_config_value('analytics_id', '', 'env')
app.connect('html-page-context', add_html_context)
app.connect('build-finished', build_finished)
app.add_lexer('session', SessionLexer() if version_info[0] < 3 else SessionLexer)
app.add_role('link', link_role)
app.add_role('commit', commit_role)
# monkey patch sphinx_inline_tabs to avoid a warning about parallel reads
# see https://github.com/pradyunsg/sphinx-inline-tabs/issues/26
inline_tabs = app.extensions['sphinx_inline_tabs']
inline_tabs.parallel_read_safe = inline_tabs.parallel_write_safe = True

View File

@@ -16,10 +16,10 @@ frames-per-second. See below for an overview of all customization possibilities.
You can open the config file within kitty by pressing :sc:`edit_config_file`
(:kbd:`⌘+,` on macOS). A :file:`kitty.conf` with commented default
configurations and descriptions will be created if the file does not exist.
You can reload the config file within kitty by pressing :sc:`reload_config_file`
(:kbd:`⌃+⌘+,` on macOS) or sending kitty the ``SIGUSR1`` signal.
You can also display the current configuration by pressing :sc:`debug_config`
(:kbd:`⌥+⌘+,` on macOS).
You can reload the config file within kitty by pressing
:sc:`reload_config_file` (:kbd:`⌃+⌘+,` on macOS) or sending kitty the
``SIGUSR1`` signal with ``kill -SIGUSR1 $KITTY_PID``. You can also display the
current configuration by pressing :sc:`debug_config` (:kbd:`⌥+⌘+,` on macOS).
.. _confloc:

View File

@@ -94,9 +94,9 @@ to display it based on what it does understand.
revisions.
======= ==================== ========= =================
======= ==================== ========== =================
Key Value Default Description
======= ==================== ========= =================
======= ==================== ========== =================
``a`` Comma separated list ``focus`` What action to perform when the
of ``report``, notification is clicked
``focus``, with
@@ -113,7 +113,19 @@ Key Value Default Description
``p`` One of ``title`` or ``title`` Whether the payload is the notification title or body. If a
``body``. notification has no title, the body will be used as title.
======= ==================== ========= =================
``o`` One of ``always``, ``always`` When to honor the notification request. ``unfocused`` means when the window
``unfocused`` or the notification is sent on does not have keyboard focus. ``invisible``
``invisible`` means the window both is unfocused
and not visible to the user, for example, because it is in an inactive tab or
its OS window is not currently active.
``always`` is the default and always honors the request.
======= ==================== ========== =================
.. note::
Support for the ``o`` key to prevent notifications from focused windows
was added in kitty version 0.31.0
.. note::

View File

@@ -19,9 +19,9 @@ use Unicode characters from the private use area to represent symbols. Often
these symbols are wide and should be rendered in two cells. However, since
private use area symbols all have their width set to one in the Unicode
standard, |kitty| renders them either smaller or truncated. The exception is if
these characters are followed by a space or empty cell in which case kitty
makes use of the extra cell to render them in two cells. This behavior can be
turned off for specific symbols using :opt:`narrow_symbols`.
these characters are followed by a space or en-space (U+2002) in which case
kitty makes use of the extra cell to render them in two cells. This behavior
can be turned off for specific symbols using :opt:`narrow_symbols`.
Using a color theme with a background color does not work well in vim?
@@ -263,11 +263,12 @@ fonts to be freely resizable, so it does not support bitmapped fonts.
symbols from it automatically, and you can tell it to do so explicitly in
case it doesn't with the :opt:`symbol_map` directive::
# Nerd Fonts v2.3.3
# Nerd Fonts v3.1.0
symbol_map U+23FB-U+23FE,U+2665,U+26A1,U+2B58,U+E000-U+E00A,U+E0A0-U+E0A3,U+E0B0-U+E0D4,U+E200-U+E2A9,U+E300-U+E3E3,U+E5FA-U+E6AA,U+E700-U+E7C5,U+EA60-U+EBEB,U+F000-U+F2E0,U+F300-U+F32F,U+F400-U+F4A9,U+F500-U+F8FF,U+F0001-U+F1AF0 Symbols Nerd Font Mono
symbol_map U+e000-U+e00a,U+ea60-U+ebeb,U+e0a0-U+e0c8,U+e0ca,U+e0cc-U+e0d4,U+e200-U+e2a9,U+e300-U+e3e3,U+e5fa-U+e6b1,U+e700-U+e7c5,U+f000-U+f2e0,U+f300-f372,U+f400-U+f532,U+f0001-U+f1af0 Symbols Nerd Font Mono
Those Unicode symbols beyond the ``E000-F8FF`` Unicode private use area are
Those Unicode symbols not in the `Unicode private use areas
<https://en.wikipedia.org/wiki/Private_Use_Areas>`__ are
not included.
If your font is not listed in ``kitty +list-fonts`` it means that it is not
@@ -386,23 +387,18 @@ You can also change the icon manually by following the steps:
How do I map key presses in kitty to different keys in the terminal program?
--------------------------------------------------------------------------------------
This is accomplished by using ``map`` with :sc:`send_text <send_text>` in :file:`kitty.conf`.
This is accomplished by using ``map`` with :ac:`send_key` in :file:`kitty.conf`.
For example::
map alt+s send_text normal,application \x13
map alt+s send_key ctrl+s
This maps :kbd:`alt+s` to :kbd:`ctrl+s`. To figure out what bytes to use for
the :sc:`send_text <send_text>` you can use the ``show_key`` kitten. Run::
This causes the program running in kitty to receive the :kbd:`ctrl+s` key when
you press the :kbd:`alt+s` key. To see this in action, run::
kitten show_key
kitten show-key -m kitty
Then press the key you want to emulate. Note that this kitten will only show
keys that actually reach the terminal program, in particular, keys mapped to
actions in kitty will not be shown. To check those first map them to
:ac:`no_op`. You can also start a kitty instance without any shortcuts to
interfere::
kitty -o clear_all_shortcuts=yes kitten show_key
Which will print out what key events it receives. To send arbitrary text rather
than a key press, see :sc:`send_text <send_text>` instead.
How do I open a new window or tab with the same working directory as the current window?
@@ -453,9 +449,6 @@ do not use them, if at all possible. kitty contains features that do all of what
tmux does, but better, with the exception of remote persistence (:iss:`391`).
If you still want to use tmux, read on.
Image display will not work, see `tmux issue
<https://github.com/tmux/tmux/issues/1391>`__.
Using ancient versions of tmux such as 1.8 will cause gibberish on screen when
pressing keys (:iss:`3541`).
@@ -464,6 +457,11 @@ and then switch to another and these terminals have different :envvar:`TERM`
variables, tmux will break. You will need to restart it as tmux does not support
multiple terminfo definitions.
Displaying images while inside programs such as nvim or ranger may not work
depending on whether those programs have adopted support for the :ref:`unicode
placeholders <graphics_unicode_placeholders>` workaround that kitty created
for tmux refusing to support images.
If you use any of the advanced features that kitty has innovated, such as
:doc:`styled underlines </underlines>`, :doc:`desktop notifications
</desktop-notifications>`, :doc:`extended keyboard support

View File

@@ -120,7 +120,7 @@ Variables that influence kitty behavior
.. envvar:: KITTY_RC_PASSWORD
Set this to a pass phrase to use the ``kitty @`` remote control command with
Set this to a pass phrase to use the ``kitten @`` remote control command with
:opt:`remote_control_password`.
@@ -164,7 +164,8 @@ Variables that kitty sets when running child programs
.. envvar:: TERMINFO
Path to a directory containing the kitty terminfo database.
Path to a directory containing the kitty terminfo database. Or the terminfo
database itself encoded in base64. See :opt:`terminfo_type`.
.. envvar:: KITTY_INSTALLATION_DIR
@@ -179,8 +180,10 @@ Variables that kitty sets when running child programs
Set when the :doc:`remote control <remote-control>` facility is enabled and
the a socket is used for control via :option:`kitty --listen-on` or :opt:`listen_on`.
Contains the path to the socket. Avoid the need to use :option:`kitty @ --to` when
issuing remote control commands.
Contains the path to the socket. Avoid the need to use :option:`kitten @ --to` when
issuing remote control commands. Can also be a file descriptor of the form
fd:num instead of a socket address, in which case, remote control
communication should proceed over the specified file descriptor.
.. envvar:: KITTY_PIPE_DATA
@@ -228,3 +231,11 @@ Variables that kitty sets when running child programs
Set to ``1`` when kitty is running a shell because of the ``--hold`` flag. Can
be used to specialize shell behavior in the shell rc files as desired.
.. envvar:: KITTY_SIMD
Set it to ``128`` to use 128 bit vector registers, ``256`` to use 256 bit
vector registers or any other value to prevent kitty from using SIMD CPU
vector instructions. Warning, this overrides CPU capability detection so
will cause kitty to crash with SIGILL if your CPU does not support the
necessary SIMD extensions.

View File

@@ -48,6 +48,7 @@ Some programs and libraries that use the kitty graphics protocol:
* `glkitty <https://github.com/michaeljclark/glkitty>`_ - C library to draw OpenGL shaders in the terminal with a glgears demo
* `twitch-tui <https://github.com/Xithrius/twitch-tui>`_ - Twitch chat in the terminal
* `awrit <https://github.com/chase/awrit>`_ - Chromium-based web browser rendered in Kitty with mouse and keyboard support
* `fzf <https://github.com/junegunn/fzf/commit/d8188fce7b7bea982e7f9050c35e488e49fb8fd0>`_ - A command line fuzzy finder
Other terminals that have implemented the graphics protocol:
@@ -459,7 +460,10 @@ When you specify a placement id, it will be added to the acknowledgement code
above. Every placement is uniquely identified by the pair of the ``image id``
and the ``placement id``. If you specify a placement id for an image that does
not have an id (i.e. has id=0), it will be ignored. In particular this means
there can exist multiple images with ``image id=0, placement id=0``.
there can exist multiple images with ``image id=0, placement id=0``. Not
specifying a placement id or using ``p=0`` for multiple put commands (``a=p``)
with the same non-zero image id results in multiple placements the image.
An example response::
<ESC>_Gi=<image id>,p=<placement id>;OK<ESC>\
@@ -478,18 +482,22 @@ Controlling displayed image layout
The image is rendered at the current cursor position, from the upper left corner of
the current cell. You can also specify extra ``X=3`` and ``Y=4`` pixel offsets to display from
a different origin within the cell. Note that the offsets must be smaller that the size of the cell.
a different origin within the cell. Note that the offsets must be smaller than the size of the cell.
By default, the entire image will be displayed (images wider than the available
width will be truncated on the right edge). You can choose a source rectangle (in pixels)
as the part of the image to display. This is done with the keys: ``x, y, w, h`` which specify
the top-left corner, width and height of the source rectangle.
the top-left corner, width and height of the source rectangle. The displayed
area is the intersection of the specified rectangle with the source image
rectangle.
You can also ask the terminal emulator to display the image in a specified rectangle
(num of columns / num of lines), using the control codes ``c,r``. ``c`` is the number of columns
and `r` the number of rows. The image will be scaled (enlarged/shrunk) as needed to fit
the specified area. Note that if you specify a start cell offset via the ``X,Y`` keys, it is not
added to the number of rows/columns.
added to the number of rows/columns. If only one of either ``r`` or ``c`` is
specified, the other one is computed based on the source image aspect ratio, so
that the image is displayed without distortion.
Finally, you can specify the image *z-index*, i.e. the vertical stacking order. Images
placed in the same location with different z-index values will be blended if
@@ -554,7 +562,7 @@ The image will eventually be fit to the specified rectangle, its aspect ratio
preserved. Finally, the image can be actually displayed by using the
placeholder character, encoding the image ID in its foreground color. The row
and column values are specified with diacritics listed in
:download:`rowcolumn-diacritics.txt <../rowcolumn-diacritics.txt>`. For
:download:`rowcolumn-diacritics.txt <../gen/rowcolumn-diacritics.txt>`. For
example, here is how you can print a ``2x2`` placeholder for image ID ``42``:
.. code-block:: sh
@@ -629,7 +637,7 @@ terminal may apply other heuristics (but it doesn't have to).
It is important to distinguish between virtual image placements and real images
displayed on top of Unicode placeholders. Virtual placements are invisible and only play
the role of prototypes for real images. Virtual placements can be deleted by a
deletion command only when the `d` key is equal to ``i``, ``I``, ``n`` or ``N``.
deletion command only when the `d` key is equal to ``i``, ``I``, ``r``, ``R``, ``n`` or ``N``.
The key values ``a``, ``c``, ``p``, ``q``, ``x``, ``y``, ``z`` and their capital
variants never affect virtual placements because they do not have a physical
location on the screen.
@@ -639,6 +647,70 @@ placements from the protocol perspective. They cannot be manipulated using
graphics commands, instead they should be moved, deleted, or modified by
manipulating the underlying Unicode placeholder as normal text.
.. _relative_image_placement:
Relative placements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 0.31.0
Support for positioning images relative to other images
You can specify that a placement is positioned relative to another placement.
This is particularly useful in combination with
:ref:`graphics_unicode_placeholders` above. It can be used to specify a single
transparent pixel image using a Unicode placeholder, which moves around
naturally with the text, the real image(s) can base their position relative to
the placeholder.
To specify that a placement should be relative to another, use the
``P=<image_id>,Q=<placement_id>`` keys, when creating the relative placement.
For example::
<ESC>_Ga=p,i=<image_id>,p=<placement_id>,P=<parent_img_id>,Q=<parent_placement_id><ESC>\
This will create a *relative placement* that refers to the *parent placement*
specified by the ``P`` and ``Q`` keys. When the parent placement moves, the
relative placement moves along with it. The relative placement can be offset
from the parent's location by a specified number of cells, using the ``H`` and
``V`` keys for horizontal and vertical displacement. Positive values move right
and down. Negative values move left and up. The origin is the top left cell of
the parent placement.
The lifetime of a relative placement is tied to the lifetime of its parent. If
its parent is deleted, it is deleted as well. If the image that the relative
placement is a placement of, has no more placements, the image is deleted as
well. Thus, a parent and its relative placements form a *group* that is managed
together.
A relative placement can refer to another relative placement as its parent.
Thus the relative placements can form a chain. It is implementation dependent
how long a chain of such placements is allowed, but implementation must allow
a chain of length at least 8. If the implementation max depth is exceeded, the
terminal must respond with the ``ETOODEEP`` error code.
Virtual placements created for Unicode placeholder based images cannot also be
relative placements. However, a relative placement can refer to a virtual
placement as its parent. When a virtual placement is the parent, its position
is derived from all the actual Unicode placeholder images that refer to it.
The x position is the minimum of all the placeholder x positions and the y
position is the minimum of all the placeholder y positions. If a client
attempts to make a virtual placement relative the terminal must respond with
the ``EINVAL`` error code.
Terminals are required to reject the creation of a relative placement
that would create a cycle, such as when A is relative to B and B is relative to
C and C is relative to A. In such cases, the terminal must respond with the
``ECYCLE`` error code.
If a client attempts to create a reference to a placement that does not exist
the terminal must respond with the ``ENOPARENT`` error code.
.. note::
Since a relative placement gets its position specified based on another
placement, instead of the cursor, the cursor must not move after a relative
position, regardless of the value of the ``C`` key to control cursor
movement.
Deleting images
---------------------
@@ -657,13 +729,14 @@ scrollback buffer. The values of the ``x`` and ``y`` keys are the same as cursor
Value of ``d`` Meaning
================= ============
``a`` or ``A`` Delete all placements visible on screen
``i`` or ``I`` Delete all images with the specified id, specified using the ``i`` key. If you specify a ``p`` key for the placement id as well, then only the placement with the specified image id and placement id will be deleted.
``i`` or ``I`` Delete all images with the specified id, specified using the ``i`` key. If you specify a ``p`` key for the placement id as well, then only the placement with the specified image id and placement id will be deleted.
``n`` or ``N`` Delete newest image with the specified number, specified using the ``I`` key. If you specify a ``p`` key for the
placement id as well, then only the placement with the specified number and placement id will be deleted.
``c`` or ``C`` Delete all placements that intersect with the current cursor position.
``f`` or ``F`` Delete animation frames.
``p`` or ``P`` Delete all placements that intersect a specific cell, the cell is specified using the ``x`` and ``y`` keys
``q`` or ``Q`` Delete all placements that intersect a specific cell having a specific z-index. The cell and z-index is specified using the ``x``, ``y`` and ``z`` keys.
``r`` or ``R`` Delete all images whose id is greater than or equal to the value of the ``x`` key and less than or equal to the value of the ``y`` (added in kitty version 0.33.0).
``x`` or ``X`` Delete all placements that intersect the specified column, specified using the ``x`` key.
``y`` or ``Y`` Delete all placements that intersect the specified row, specified using the ``y`` key.
``z`` or ``Z`` Delete all placements that have the specified z-index, specified using the ``z`` key.
@@ -959,8 +1032,11 @@ Key Value Default Description
``C`` Positive integer ``0`` Cursor movement policy. ``0`` is the default, to move the cursor to after the image.
``1`` is to not move the cursor at all when placing the image.
``U`` Positive integer ``0`` Set to ``1`` to create a virtual placement for a Unicode placeholder.
``1`` is to not move the cursor at all when placing the image.
``z`` 32-bit integer ``0`` The *z-index* vertical stacking order of the image
``P`` Positive integer ``0`` The id of a parent image for relative placement
``Q`` Positive integer ``0`` The id of a placement in the parent image for relative placement
``H`` 32-bit integer ``0`` The offset in cells in the horizontal direction for relative placement
``V`` 32-bit integer ``0`` The offset in cells in the vertical direction for relative placement
**Keys for animation frame loading**
-----------------------------------------------------------
@@ -1008,9 +1084,11 @@ Key Value Default Description
**Keys for deleting images**
-----------------------------------------------------------
``d`` Single character. ``a`` What to delete.
``(a, A, c, C, n, N,
i, I, p, P, q, Q, x,
X, y, Y, z, Z)``.
``(
a, A, c, C, n, N,
i, I, p, P, q, Q, r,
R, x, X, y, Y, z, Z
)``.
======= ==================== ========= =================

View File

@@ -47,6 +47,13 @@ graphics protocol.
Another terminal file manager, with previews of file contents powered by kitty's
graphics protocol.
.. _tool_presentterm:
`presenterm <https://github.com/mfontanini/presenterm>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Show markdown based slides with images in your terminal, powered by the
kitty graphics protocol.
.. _tool_term_image:
`term-image <https://github.com/AnonymouX47/term-image>`__
@@ -182,13 +189,6 @@ A tool to display weather information in your terminal with curl
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
View and manage the system clipboard under Wayland in your kitty terminal
.. tool_dmenu_term:
`dmenu-term <https://github.com/maximbaz/dmenu-term>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run applications on your system with fuzzy find inside a kitty window
Editor integration
-----------------------
@@ -232,16 +232,23 @@ running around inside nvim <https://github.com/giusgad/pets.nvim>`__.
Scrollback manipulation
-------------------------
.. tool_kitty_scrollback_nvim:
`kitty-scrollback.nvim <https://github.com/mikesmithgh/kitty-scrollback.nvim>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Browse the scrollback buffer with Neovim, with simple key actions for efficient
copy/paste and even execution of commands.
.. tool_kitty_search:
`kitty-search <https://github.com/trygveaa/kitty-kitten-search>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Live incremental search of the scrollback buffer.
.. tool_kitty_grab:
`kitty-grab <https://github.com/yurikhan/kitty_grab>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Keyboard based text selection for the kitty scrollback buffer.

View File

@@ -36,6 +36,8 @@ In addition to kitty, this protocol is also implemented in:
* The `foot terminal <https://codeberg.org/dnkl/foot/issues/319>`__
* The `WezTerm terminal <https://wezfurlong.org/wezterm/config/lua/config/enable_kitty_keyboard.html>`__
* The `alacritty terminal <https://github.com/alacritty/alacritty/pull/7125>`__
* The `rio terminal <https://github.com/raphamorim/rio/commit/cd463ca37677a0fc48daa8795ea46dadc92b1e95>`__
* The `notcurses library
<https://github.com/dankamongmen/notcurses/issues/2131>`__
* The `crossterm library
@@ -47,6 +49,7 @@ In addition to kitty, this protocol is also implemented in:
* The `dte text editor <https://gitlab.com/craigbarnes/dte/-/issues/138>`__
* The `Helix text editor <https://github.com/helix-editor/helix/pull/4939>`__
* The `far2l file manager <https://github.com/elfmz/far2l/commit/e1f2ee0ef2b8332e5fa3ad7f2e4afefe7c96fc3b>`__
* The `yazi file manager <https://github.com/sxyazi/yazi>`__
* The `awrit web browser <https://github.com/chase/awrit>`__
* The `nushell shell <https://github.com/nushell/nushell/pull/10540>`__
@@ -81,7 +84,7 @@ text (``CSI`` is the bytes ``0x1b 0x5b``)::
The ``number`` in the first form above will be either the Unicode codepoint for a
key, such as ``97`` for the :kbd:`a` key, or one of the numbers from the
:ref:`functional` table below. The ``modifiers`` optional parameter encodes any
modifiers pressed for the key event. The encoding is described in the
modifiers active for the key event. The encoding is described in the
:ref:`modifiers` section.
The second form is used for a few functional keys, such as the :kbd:`Home`,
@@ -103,9 +106,7 @@ do not. When a key event produces text, the text is sent directly as UTF-8
encoded bytes. This is safe as UTF-8 contains no C0 control codes.
When the key event does not have text, the key event is encoded as an escape code. In
legacy compatibility mode (the default) this uses legacy escape codes, so old terminal
applications continue to work. Key events that could not be represented in
legacy mode are encoded using a ``CSI u`` escape code, that most terminal
programs should just ignore. For more advanced features, such as release/repeat
applications continue to work. For more advanced features, such as release/repeat
reporting etc., applications can tell the terminal they want this information by
sending an escape code to :ref:`progressively enhance <progressive_enhancement>` the data reported for
key events.
@@ -179,11 +180,19 @@ bit field with::
num_lock 0b10000000 (128)
In the escape code, the modifier value is encoded as a decimal number which is
``1 + actual modifiers``. So to represent :kbd:`shift` only, the value would be ``1 +
1 = 2``, to represent :kbd:`ctrl+shift` the value would be ``1 + 0b101 = 6``
and so on. If the modifier field is not present in the escape code, its default
value is ``1`` which means no modifiers.
``1 + actual modifiers``. So to represent :kbd:`shift` only, the value would be
``1 + 1 = 2``, to represent :kbd:`ctrl+shift` the value would be ``1 + 0b101 =
6`` and so on. If the modifier field is not present in the escape code, its
default value is ``1`` which means no modifiers. If a modifier is *active* when
the key event occurs, i.e. if the key is pressed or the lock (for caps lock/num
lock) is enabled, the key event must have the bit for that modifier set.
When the key event is related to an actual modifier key, the corresponding
modifier's bit must be set to the modifier state including the effect for the
current event. For example, when pressing the :kbd:`LEFT_CONTROL` key, the
``ctrl`` bit must be set and when releasing it, it must be reset. When both
left and right control keys are pressed and one is released, the release event
must have the ``ctrl`` bit set. See :iss:`6913` for discussion of this design.
.. _event_types:
@@ -221,8 +230,10 @@ enhancement <progressive_enhancement>` mechanism described below. Some examples:
shift+a -> CSI 97 ; 2 ; 65 u # The text 'A' is reported as 65
option+a -> CSI 97 ; ; 229 u # The text 'å' is reported as 229
If multiple code points are present, they must be separated by colons.
If no known key is associated with the text the key number ``0`` must be used.
If multiple code points are present, they must be separated by colons. If no
known key is associated with the text the key number ``0`` must be used. The
associated text must not contain control codes (control codes are code points
below U+0020 and codepoints in the C0 and C1 blocks).
Non-Unicode keys
@@ -328,7 +339,9 @@ much easier to integrate into the application event loop. The only exceptions
are the :kbd:`Enter`, :kbd:`Tab` and :kbd:`Backspace` keys which still generate the same
bytes as in legacy mode this is to allow the user to type and execute commands
in the shell such as ``reset`` after a program that sets this mode crashes
without clearing it.
without clearing it. Note that the Lock modifiers are not reported for text
producing keys, to keep them useable in legacy programs. To get lock modifiers
for all keys use the :ref:`report_all_keys` enhancement.
.. _report_events:
@@ -340,6 +353,13 @@ and key release events. Normally only key press events are reported and key
repeat events are treated as key press events. See :ref:`event_types` for
details on how these are reported.
.. note::
The :kbd:`Enter`, :kbd:`Tab` and :kbd:`Backspace` keys will not have release
events unless :ref:`report_all_keys` is also set, so that the user can still
type reset at a shell prompt when a program that sets this mode ends without
resetting it.
.. _report_alternates:
Report alternate keys
@@ -474,6 +494,12 @@ must correspond to the :kbd:`Backspace` key.
All keypad keys are reported as their equivalent non-keypad keys. To
distinguish these, use the :ref:`disambiguate <disambiguate>` flag.
Terminals may choose what they want to do about functional keys that have no
legacy encoding. kitty chooses to encode these using ``CSI u`` encoding even in
legacy mode, so that they become usable even in programs that do not
understand the full kitty keyboard protocol. However, terminals may instead choose to
ignore such keys in legacy mode instead, or have an option to control this behavior.
.. _legacy_text:
Legacy text keys

View File

@@ -1,6 +1,11 @@
broadcast
==================================================
.. only:: man
Overview
--------------
*Type text in all kitty windows simultaneously*
The ``broadcast`` kitten can be used to type text simultaneously in all

View File

@@ -1,6 +1,11 @@
clipboard
==================================================
.. only:: man
Overview
--------------
*Copy/paste to the system clipboard from shell scripts*
.. highlight:: sh

View File

@@ -56,7 +56,7 @@ Kittens have full access to internal kitty APIs. However these are neither
entirely stable nor documented. You can instead use the kitty
:doc:`Remote control API </remote-control>`. Simply call
:code:`boss.call_remote_control()`, with the same arguments you
would pass to ``kitty @``. For example:
would pass to ``kitten @``. For example:
.. code-block:: python
@@ -337,9 +337,10 @@ You can parse and read the options in your kitten using the following code:
return ans
overrides = tuple(overrides) if overrides is not None else ()
opts_dict, paths = _load_config(defaults, parse_config, merge_result_dicts, *paths, overrides=overrides)
opts_dict, found_paths = _load_config(defaults, parse_config, merge_result_dicts, *paths, overrides=overrides)
opts = Options(opts_dict)
opts.config_paths = paths
opts.config_paths = found_paths
opts.all_config_paths = paths
opts.config_overrides = overrides
return opts

View File

@@ -1,6 +1,12 @@
Hints
==========
.. only:: man
Overview
--------------
|kitty| has a *hints mode* to select and act on arbitrary text snippets
currently visible on the screen. For example, you can press :sc:`open_url`
to choose any URL visible on the screen and then open it using your default web
@@ -20,8 +26,10 @@ and adding them to the command line for the next command.
You can also press :sc:`goto_file_line` to select anything that looks like a
path or filename followed by a colon and a line number and open the file in
:program:`vim` at the specified line number. The patterns and editor to be used
can be modified using options passed to the kitten. For example::
your default editor at the specified line number (opening at line number will
work only if your editor supports the +linenum command line syntax or is a
"known" editor). The patterns and editor to be used can be modified using
options passed to the kitten. For example::
map ctrl+g kitten hints --type=linenum --linenum-action=tab nvim +{line} {path}

View File

@@ -1,6 +1,12 @@
Hyperlinked grep
=================
.. only:: man
Overview
--------------
.. note::
As of ripgrep versions newer that 13.0 it supports hyperlinks
@@ -39,7 +45,8 @@ Now, run a search with::
Hold down the :kbd:`Ctrl+Shift` keys and click on any of the result lines, to
open the file in :program:`vim` at the matching line. If you use some editor
other than :program:`vim`, you should adjust the :file:`open-actions.conf` file
accordingly.
accordingly. TO open links with the keyboard instead, use
:sc:`open_selected_hyperlink`.
Finally, add an alias to your shell's rc files to invoke the kitten as
:command:`hg`::

View File

@@ -1,13 +1,18 @@
icat
========================================
.. only:: man
Overview
--------------
*Display images in the terminal*
The ``icat`` kitten can be used to display arbitrary images in the |kitty|
terminal. Using it is as simple as::
kitten icat image.jpeg
kitten icat image.jpeg
It supports all image types supported by `ImageMagick
<https://www.imagemagick.org>`__. It even works over SSH. For details, see the

View File

@@ -3,6 +3,11 @@ Draw a GPU accelerated dock panel on your desktop
.. highlight:: sh
.. only:: man
Overview
--------------
You can use this kitten to draw a GPU accelerated panel on the edge of your
screen, that shows the output from an arbitrary terminal program.
@@ -25,7 +30,10 @@ activity, CPU load, date/time, etc.
.. note::
This kitten currently only works on X11 desktops
This kitten currently only works on X11 desktops and Wayland compositors
that support the `wlr layer shell protocol
<https://wayland.app/protocols/wlr-layer-shell-unstable-v1#compositor-support>`__
(which is almost all of them except the usually crippled GNOME).
Using this kitten is simple, for example::

View File

@@ -1,6 +1,12 @@
Query terminal
=================
.. only:: man
Overview
--------------
This kitten is used to query |kitty| from terminal programs about version, values
of various runtime options controlling its features, etc.

View File

@@ -1,6 +1,12 @@
Remote files
==============
.. only:: man
Overview
--------------
|kitty| has the ability to easily *Edit*, *Open* or *Download* files from a
computer into which you are SSHed. In your SSH session run::

View File

@@ -1,13 +1,18 @@
Truly convenient SSH
=========================================
.. only:: man
Overview
----------------
* Automatic :ref:`shell_integration` on remote hosts
* Easily :ref:`clone local shell/editor config <real_world_ssh_kitten_config>` on remote hosts
* Automatic :opt:`re-use of existing connections <kitten-ssh.share_connections>` to avoid connection setup latency
* Make kitty itself available in the remote host :opt:`on demand <kitten-ssh.remote_kitty>`
* Make the kitten binary available in the remote host :opt:`on demand <kitten-ssh.remote_kitty>`
* Easily :opt:`change terminal colors <kitten-ssh.color_scheme>` when connecting to remote hosts

View File

@@ -1,6 +1,12 @@
Changing kitty colors
========================
.. only:: man
Overview
--------------
The themes kitten allows you to easily change color themes, from a collection of
over three hundred pre-built themes available at `kitty-themes
<https://github.com/kovidgoyal/kitty-themes>`_. To use it, simply run::

View File

@@ -1,6 +1,12 @@
Transfer files
================
.. only:: man
Overview
--------------
.. versionadded:: 0.30.0
.. _rsync: https://en.wikipedia.org/wiki/Rsync

View File

@@ -1,6 +1,12 @@
Unicode input
================
.. only:: man
Overview
--------------
You can input Unicode characters by name, hex code, recently used and even an
editable favorites list. Press :sc:`input_unicode_character` to start the
unicode input kitten, shown below.

View File

@@ -83,7 +83,7 @@ the command line:
data to STDIN.
``@input-line-number``
Replaced the number of lines a pager should scroll to match the current
Replaced by the number of lines a pager should scroll to match the current
scroll position in kitty. See :opt:`scrollback_pager` for details.
``@scrolled-by``
@@ -133,8 +133,21 @@ functions for the events you are interested in, for example:
def on_close(boss: Boss, window: Window, data: Dict[str, Any])-> None:
# called when window is closed, typically when the program running in
# it exits.
# it exits
def on_set_user_var(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# called when a "user variable" is set or deleted on a window. Here
# data will contain key and value
def on_title_change(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# called when the window title is changed on a window. Here
# data will contain title and from_child. from_child will be True
# when a title change was requested via escape code from the program
# running in the terminal
def on_cmd_startstop(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# called when the shell starts/stops executing a command. Here
# data will contain is_start and time.
Every callback is passed a reference to the global ``Boss`` object as well as
the ``Window`` object the action is occurring on. The ``data`` object is a dict

View File

@@ -141,7 +141,7 @@ The Splits Layout
--------------------
This is the most flexible layout. You can create any arrangement of windows
by splitting exiting windows repeatedly. To best use this layout you should
by splitting existing windows repeatedly. To best use this layout you should
define a few extra key bindings in :file:`kitty.conf`::
# Create a new window splitting the space used by the existing one so that

351
docs/mapping.rst Normal file
View File

@@ -0,0 +1,351 @@
:orphan:
Making your keyboard dance
==============================
.. highlight:: conf
kitty has extremely powerful facilities for mapping keyboard actions.
Things like combining actions, multi-key mappings, modal mappings,
mappings that send arbitrary text, and mappings dependent on the program
currently running in kitty.
Let's start with the basics. You can map a key press to an action in kitty using
the following syntax::
map ctrl+a new_window_with_cwd
This will map the key press :kbd:`Ctrl+a` to open a new :term:`window`
with the working directory set to the working directory of the current window.
This is the basic operation of the map directive, the tip of the iceberg, for
more read the sections below.
Combining multiple actions on a single keypress
-----------------------------------------------------
Multiple actions can be combined on a single keypress, like a macro. To do this
map the key press to the :ac:`combine` action::
map key combine <separator> action1 <separator> action2 <separator> action3 ...
For example::
map kitty_mod+e combine : new_window : next_layout
This will create a new window and switch to the next available layout. You can
also run arbitrarily powerful scripts on a key press. There are two major
techniques for doing this, using remote control scripts or using kittens.
Remote control scripts
^^^^^^^^^^^^^^^^^^^^^^^^^
These can be written in any language and use the "kitten" binary to control
kitty via its extensive :doc:`Remote control <remote-control>` API. First,
if you just want to run a single remote control command on a key press,
you can just do::
map f1 remote_control set-spacing margin=30
This will run the ``set-spacing`` command, changing window margins to 30 pixels. For
more complex scripts, write a script file in any language you like and save it
somewhere, preferably in the kitty configuration directory. Do not forget to make it
executable. In the script file you run remote control commands by running the
"kitten" binary, for example:
.. code-block:: sh
#!/bin/sh
kitten @ set-spacing margin=30
kitten @ new_window
...
The script can perform arbitrarily complex logic and actions, limited only by
the remote control API, that you can browse by running ``kitten @ --help``.
To run the script you created on a key press, use::
map f1 remote_control_script /path/to/myscript
Kittens
^^^^^^^^^^^^^
Here, kittens refer to Python scripts. The scripts have two parts, one that
runs as a regular command line program inside a kitty window to, for example,
ask the user for some input and a second part that runs inside the kitty
process itself and can perform any operation on the kitty UI, which is itself
implemented in Python. However, the kitty internal API is not documented and
can (very rarely) change, so kittens are harder to get started with than remote
control scripts. To run a kitten on a key press::
map f1 kitten mykitten.py
Many of kitty's features are themselves implemented as kittens, for example,
:doc:`/kittens/unicode_input`, :doc:`/kittens/hints` and
:doc:`/kittens/themes`. To learn about writing your own kittens, see
:doc:`/kittens/custom`.
Syntax for specifying keys
-----------------------------
A mapping maps a key press to some action. In their most basic form, keypresses
are :code:`modifier+key`. Keys are identified simply by their lowercase Unicode
characters. For example: :code:`a` for the :kbd:`A` key, :code:`[` for the left
square bracket key, etc. For functional keys, such as :kbd:`Enter` or
:kbd:`Escape`, the names are present at :ref:`Functional key definitions
<functional>`. For modifier keys, the names are :kbd:`ctrl` (:kbd:`control`,
:kbd:`⌃`), :kbd:`shift` (:kbd:`⇧`), :kbd:`alt` (:kbd:`opt`, :kbd:`option`,
:kbd:`⌥`), :kbd:`super` (:kbd:`cmd`, :kbd:`command`, :kbd:`⌘`).
Additionally, you can use the name :opt:`kitty_mod` as a modifier, the default
value of which is :kbd:`ctrl+shift`. The default kitty shortcuts are defined
using this value, so by changing it in :file:`kitty.conf` you can change
all the modifiers used by all the default shortcuts.
On Linux, you can also use XKB names for functional keys that don't have kitty
names. See :link:`XKB keys
<https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h>`
for a list of key names. The name to use is the part after the :code:`XKB_KEY_`
prefix. Note that you can only use an XKB key name for keys that are not known
as kitty keys.
Finally, you can use raw system key codes to map keys, again only for keys that
are not known as kitty keys. To see the system key code for a key, start kitty
with the :option:`kitty --debug-input` option, kitty will output some debug text
for every key event. In that text look for :code:`native_code`, the value
of that becomes the key name in the shortcut. For example:
.. code-block:: none
on_key_input: glfw key: 0x61 native_code: 0x61 action: PRESS mods: none text: 'a'
Here, the key name for the :kbd:`A` key is :code:`0x61` and you can use it with::
map ctrl+0x61 something
This maps :kbd:`Ctrl+A` to something.
Multi-key mappings
--------------------
A mapping in kitty can involve pressing multiple keys in sequence, with the
syntax shown below::
map key1>key2>key3 action
For example::
map ctrl+f>2 set_font_size 20
The default mappings to run the :doc:`hints kitten </kittens/hints>` to select text on the screen are
examples of multi-key mappings.
Unmapping default shortcuts
-----------------------------
kitty comes with dozens of default keyboard mappings for common operations. See
:doc:`actions` for the full list of actions and the default shortcuts that map
to them. You can unmap an individual shortcut, so that it is passed on to the
program running inside kitty, by mapping it to nothing, for example::
map kitty_mod+enter
This unmaps the default shortcut :sc:`new_window` to open a new window. Almost
all default shortcuts are of the form ``modifier + key`` where the
modifier defaults to :kbd:`Ctrl+Shift` and can be changed using the :opt:`kitty_mod` setting
in :file:`kitty.conf`.
If you want to clear all default shortcuts, you can use
:opt:`clear_all_shortcuts` in :file:`kitty.conf`.
If you would like kitty to completely ignore a key event, not even sending it to
the program running in the terminal, map it to :ac:`discard_event`::
map kitty_mod+f1 discard_event
.. _conditional_mappings:
Conditional mappings depending on the state of the focused window
----------------------------------------------------------------------
Sometimes, you may want different mappings to be active when running a
particular program in kitty, perhaps because it has some native functionality
that duplicates kitty functions or there is a conflict, etc. kitty has the
ability to create mappings that work only when the currently focused window
matches some criteria, such as when it has a particular title or user variable.
Let's see some examples::
map --when-focus-on title:keyboard.protocol kitty_mod+t
This will cause :kbd:`kitty_mod+t` (the default shortcut for opening a new tab)
to be unmapped only when the focused window
has :code:`keyboard protocol` in its title. Run the show-key kitten as::
kitten show-key -m kitty
Press :kbd:`ctrl+shift+t` and instead of a new tab opening, you will
see the key press being reported by the kitten. :code:`--when-focus-on` can test
the focused window using very powerful criteria, see :ref:`search_syntax` for
details. A more practical example unmaps the key when the focused window is
running an editor::
map --when-focus-on var:in_editor kitty_mod+c
In order to make this work, you need to configure your editor as show below:
.. tab:: vim
In :file:`~/.vimrc` add:
.. code-block:: vim
let &t_ti = &t_ti . "\\033]1337;SetUserVar=in_editor=MQo\\007"
let &t_te = &t_te . "\\033]1337;SetUserVar=in_editor\\007"
.. tab:: neovim
In :file:`~/.config/nvim/init.lua` add:
.. code-block:: lua
vim.api.nvim_create_autocmd({ "VimEnter" }, {
group = vim.api.nvim_create_augroup("KittySetVarVimEnter", { clear = true }),
callback = function()
io.stdout:write("\x1b]1337;SetUserVar=in_editor=MQo\007")
end,
})
vim.api.nvim_create_autocmd({ "VimLeave" }, {
group = vim.api.nvim_create_augroup("KittyUnsetVarVimLeave", { clear = true }),
callback = function()
io.stdout:write("\x1b]1337;SetUserVar=in_editor\007")
end,
})
These cause the editor to set the :code:`in_editor` variable in kitty and unset it when exiting.
As a result, the :kbd:`ctrl+shift+c` key will be passed to the editor instead of
copying to clipboard. In the editor, you can map it to copy to the clipboard,
thereby allowing use of a common shortcut both inside and outside the editor
for copying to clipboard.
Sending arbitrary text or keys to the program running in kitty
--------------------------------------------------------------------------------
This is accomplished by using ``map`` with :sc:`send_text <send_text>` in :file:`kitty.conf`.
For example::
map f1 send_text normal,application Hello, world!
Now, pressing :kbd:`f1` will cause ``Hello, world!`` to show up at your shell
prompt. To have the shell execute a command sent via ``send_text`` you need to
also simulate pressing the enter key which is ``\r``. For example::
map f1 send_text normal,application echo Hello, world!\r
Now, if you press :kbd:`f1` when at shell prompt it will run the ``echo Hello,
world!`` command.
To have one key press send another key press, use :ac:`send_key`::
map alt+s send_key ctrl+s
This causes the program running in kitty to receive the :kbd:`ctrl+s` key when
you press the :kbd:`alt+s` key. To see this in action, run::
kitten show-key -m kitty
Which will print out what key events it receives.
.. _modal_mappings:
Modal mappings
--------------------------
kitty has the ability, like vim, to use *modal* key maps. Except that unlike
vim it allows you to define your own arbitrary number of modes. To create a new
mode, use ``map --new-mode <my mode name> <shortcut to enter mode>``. For
example, lets create a mode to manage windows: switching focus, moving the window, etc.::
# Create a new "manage windows" mode (mw)
map --new-mode mw kitty_mod+f7
# Switch focus to the neighboring window in the indicated direction using arrow keys
map --mode mw left neighboring_window left
map --mode mw right neighboring_window right
map --mode mw up neighboring_window up
map --mode mw down neighboring_window down
# Move the active window in the indicated direction
map --mode mw shift+up move_window up
map --mode mw shift+left move_window left
map --mode mw shift+right move_window right
map --mode mw shift+down move_window down
# Resize the active window
map --mode mw n resize_window narrower
map --mode mw w resize_window wider
map --mode mw t resize_window taller
map --mode mw s resize_window shorter
# Exit the manage window mode
map --mode mw esc pop_keyboard_mode
Now, if you run kitty as:
.. code-block:: sh
kitty -o enabled_layouts=vertical --session <(echo "launch\nlaunch\nlaunch")
Press :kbd:`Ctrl+Shift+F7` to enter the mode and then press the up and
down arrow keys to focus the next/previous window. Press :kbd:`Shift+Up` or
:kbd:`Shift+Down` to move the active window up and down. Press :kbd:`t` to make
the active window taller and :kbd:`s` to make it shorter. To exit the mode
press :kbd:`Esc`.
Pressing an unknown key while in a custom keyboard mode by default
beeps. This can be controlled by the ``map --on-unknown`` option as shown
below::
# Beep on unknown keys
map --new-mode XXX --on-unknown beep ...
# Ingore unknown keys silently
map --new-mode XXX --on-unknown ignore ...
# Beep and exit the keyboard mode on unknown key
map --new-mode XXX --on-unknown end ...
# Pass unknown keys to the program running in the active window
map --new-mode XXX --on-unknown passthrough ...
When a key matches an action in a custom keyboard mode, the action is performed
and the custom keyboard mode remains in effect. If you would rather have the
keyboard mode end after the action you can use ``map --on-action`` as shown
below::
# Have this keyboard mode automatically exit after performing any action
map --new-mode XXX --on-action end ...
All mappable actions
------------------------
There is a list of :doc:`all mappable actions <actions>`.
Debugging mapping issues
------------------------------
To debug mapping issues, kitty has several facilities. First, when you run
kitty with the ``--debug-input`` command line flag it outputs details
about all key events it receives form the system and how they are handled.
To see what key events are sent to applications, run kitty like this::
kitty kitten show-key
Press the keys you want to debug and the kitten will print out the bytes it
receives. Note that this uses the legacy terminal keyboard protocol that does
not support all keys and key events. To debug the :doc:`full kitty keyboard
protocol that <keyboard-protocol>` that is nowadays being adopted by more and
more programs, use::
kitty kitten show-key -m kitty

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